### Run Example Application (Bash) Source: https://github.com/gooonzick/wizard/blob/main/CONTRIBUTING.md Command to start the React example application included in the WizardForm project. ```bash # Run React example pnpm dev ``` -------------------------------- ### Install WizardForm Packages using npm, yarn, or pnpm Source: https://github.com/gooonzick/wizard/blob/main/docs/getting-started.md These commands show how to install the necessary WizardForm packages using different package managers. Ensure you have the chosen package manager installed on your system. ```bash npm install @gooonzick/wizard-core @gooonzick/wizard-react ``` ```bash yarn add @gooonzick/wizard-core @gooonzick/wizard-react ``` ```bash pnpm add @gooonzick/wizard-core @gooonzick/wizard-react ``` -------------------------------- ### Create a Wizard using @gooonzick/wizard-core Directly Source: https://github.com/gooonzick/wizard/blob/main/docs/getting-started.md This TypeScript example shows how to create and manage a wizard using only the `@gooonzick/wizard-core` library, without framework-specific integrations. It covers defining the wizard structure, creating a `WizardMachine` instance, and interacting with its methods for navigation, validation, and submission. ```typescript import { WizardMachine, createLinearWizard } from "@gooonzick/wizard-core"; type FormData = { name: string; email: string; }; const wizard = createLinearWizard({ id: "simple-form", steps: [ { id: "personal", title: "Personal Info", validate: (data) => ({ valid: Boolean(data.name), errors: !data.name ? { name: "Name is required" } : undefined, }), }, { id: "contact", title: "Contact Info", validate: (data) => ({ valid: Boolean(data.email), errors: !data.email ? { email: "Email is required" } : undefined, }), }, ], onComplete: async (data) => { console.log("Wizard completed!", data); }, }); // Create a state machine instance const machine = new WizardMachine( wizard, {}, { name: "", email: "" }, { onStateChange: (state) => { console.log("Current step:", state.currentStepId); console.log("Data:", state.data); }, onComplete: (data) => { console.log("Complete:", data); }, }, ); // Navigate await machine.goNext(); await machine.validate(); await machine.submit(); ``` -------------------------------- ### Install Wizard Core and React Packages Source: https://github.com/gooonzick/wizard/blob/main/docs/react-integration.md Installs the necessary wizard core and React integration packages using npm. These packages provide the foundation and UI components for wizard functionality. ```bash npm install @gooonzick/wizard-core @gooonzick/wizard-react ``` -------------------------------- ### Install @gooonzick/wizard-core Source: https://github.com/gooonzick/wizard/blob/main/packages/core/README.md Installs the core library using npm. This is the first step to using the wizard framework in your project. ```bash npm install @gooonzick/wizard-core ``` -------------------------------- ### Install Project Dependencies with pnpm Source: https://github.com/gooonzick/wizard/blob/main/examples/vue-examples/README.md Installs all necessary project dependencies using the pnpm package manager. This command is crucial for setting up the project environment before development or building. ```shell pnpm install ``` -------------------------------- ### Install Wizard Packages Source: https://github.com/gooonzick/wizard/blob/main/packages/docs/guide/vue-integration.md Installs the necessary core and Vue-specific wizard packages using npm. These packages provide the foundation and Vue integration for building wizard flows. ```bash npm install @gooonzick/wizard-core @gooonzick/wizard-vue ``` -------------------------------- ### Install dependencies and run Vue package tests Source: https://github.com/gooonzick/wizard/blob/main/docs/plans/2026-01-19-refactor-dry-violations.md Installs project dependencies using `pnpm install` and then runs tests specifically for the `@gooonzick/wizard-vue` package using `pnpm test --filter=@gooonzick/wizard-vue`. This verifies that the refactoring did not introduce any regressions. ```bash pnpm install pnpm test --filter=@gooonzick/wizard-vue ``` -------------------------------- ### Install, Build, and Test State Package with pnpm Source: https://github.com/gooonzick/wizard/blob/main/docs/plans/2026-01-19-refactor-dry-violations.md Commands to install dependencies, build the specific wizard-state package using pnpm's filtering, and run its tests. This ensures the new state package is correctly integrated and functional. ```bash pnpm install pnpm build --filter=@gooonzick/wizard-state pnpm test --filter=@gooonzick/wizard-state ``` -------------------------------- ### Clone Repository and Install Dependencies (Bash) Source: https://github.com/gooonzick/wizard/blob/main/CONTRIBUTING.md Steps to clone the WizardForm repository and install its dependencies using pnpm. This involves forking, cloning, and running 'pnpm install'. ```bash git clone https://github.com/YOUR_USERNAME/wizard-vite.git cd wizard-vite pnpm install ``` -------------------------------- ### Install @gooonzick/wizard-state Source: https://github.com/gooonzick/wizard/blob/main/packages/state/README.md Installs the wizard-state package and its core dependency using pnpm. ```bash pnpm add @gooonzick/wizard-state @gooonzick/wizard-core ``` -------------------------------- ### WizardMachine Event Handling Example Source: https://github.com/gooonzick/wizard/blob/main/packages/docs/guide/api/core.md An example demonstrating how to instantiate the WizardMachine with custom event handlers for state changes and error reporting. ```typescript const machine = new WizardMachine(definition, context, initialData, { onStateChange: (state) => { console.log("Current step:", state.currentStepId); }, onError: (error) => { console.error("Error:", error); }, }); ``` -------------------------------- ### Installation Source: https://github.com/gooonzick/wizard/blob/main/packages/vue/README.md Instructions for installing the @gooonzick/wizard-vue package along with its core dependency. ```APIDOC ## Installation ```bash npm install @gooonzick/wizard-vue @gooonzick/wizard-core # or pnpm add @gooonzick/wizard-vue @gooonzick/wizard-core # or yarn add @gooonzick/wizard-vue @gooonzick/wizard-core ``` ``` -------------------------------- ### Install WizardForm Core and Integrations Source: https://github.com/gooonzick/wizard/blob/main/README.md Instructions for installing the core WizardForm package and optional integrations for React and Vue. This ensures you have the necessary dependencies for your chosen environment. ```bash # Install core package npm install @gooonzick/wizard-core # For React integration npm install @gooonzick/wizard-core @gooonzick/wizard-react # For Vue integration npm install @gooonzick/wizard-core @gooonzick/wizard-vue ``` -------------------------------- ### Wizard Provider Setup (Vue/TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/packages/docs/guide/vue-integration.md Sets up the `WizardProvider` component to enable granular subscriptions to wizard state. This is useful for optimizing re-renders by only subscribing to the specific parts of the wizard's state that a component needs. ```typescript import { WizardProvider, useWizardData, useWizardNavigation, useWizardValidation, useWizardLoading, useWizardActions, } from "@gooonzick/wizard-vue"; ``` -------------------------------- ### Static Transition Example (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/docs/core-concepts.md Shows a static transition configuration within a step definition, where the wizard always navigates to a predefined next step. ```typescript next: { type: "static", to: "billing-info" } ``` -------------------------------- ### Install and Test React Package with pnpm Source: https://github.com/gooonzick/wizard/blob/main/docs/plans/2026-01-19-refactor-dry-violations.md Commands to install dependencies and run tests for the React package using pnpm's filtering. This verifies that the integration of the shared state package has not introduced any regressions in the React implementation. ```bash pnpm install pnpm test --filter=@gooonzick/wizard-react ``` -------------------------------- ### Create a Two-Step Wizard in React with WizardForm Source: https://github.com/gooonzick/wizard/blob/main/docs/getting-started.md This React component demonstrates how to create and use a simple two-step wizard using the `@gooonzick/wizard-react` hook and `@gooonzick/wizard-core`. It includes form data definition, wizard creation with validation and submission logic, and React component implementation with state management and navigation controls. ```tsx import { useWizard } from "@gooonzick/wizard-react"; import { createLinearWizard } from "@gooonzick/wizard-core"; // 1. Define your data type type FormData = { name: string; email: string; }; // 2. Create a simple linear wizard const wizard = createLinearWizard({ id: "simple-form", steps: [ { id: "personal", title: "Personal Info", validate: (data) => ({ valid: Boolean(data.name), errors: !data.name ? { name: "Name is required" } : undefined, }), }, { id: "contact", title: "Contact Info", validate: (data) => ({ valid: Boolean(data.email), errors: !data.email ? { email: "Email is required" } : undefined, }), onSubmit: async (data) => { // Handle submission console.log("Form submitted:", data); }, }, ], onComplete: (data) => { console.log("Wizard completed!", data); }, }); // 3. Use in React component export function MyForm() { const { state, navigation, actions, validation, loading } = useWizard({ definition: wizard, initialData: { name: "", email: "" }, }); return (

{state.currentStep.meta?.title}

{state.currentStepId === "personal" && ( actions.updateField("name", e.target.value)} /> )} {state.currentStepId === "contact" && ( actions.updateField("email", e.target.value)} /> )} {validation.validationErrors && (
{Object.entries(validation.validationErrors).map(([field, error]) => (

{error}

))}
)}
); } ``` -------------------------------- ### Run Development Server with Hot Reloading (pnpm) Source: https://github.com/gooonzick/wizard/blob/main/examples/vue-examples/README.md Compiles and starts the development server, enabling hot-reloading for rapid development cycles. Changes to Vue components and other assets are reflected instantly without a full page reload. ```shell pnpm dev ``` -------------------------------- ### WizardStateManager Subscription Methods Source: https://github.com/gooonzick/wizard/blob/main/packages/state/README.md Shows how to subscribe to all state changes or specific channels like 'navigation'. Includes examples for unsubscribing. ```typescript // Subscribe to all channels (default) const unsub = manager.subscribe(() => console.log("Any change")); // Subscribe to specific channel const navUnsub = manager.subscribe( () => console.log("Navigation changed"), "navigation" ); ``` -------------------------------- ### Install Wizard React Integration Source: https://github.com/gooonzick/wizard/blob/main/packages/docs/index.md Installs the React integration package for WizardForm. This package enables the use of the wizard framework within React applications. ```bash npm install @gooonzick/wizard-react ``` -------------------------------- ### useWizard Hook Example Usage - TypeScript Source: https://github.com/gooonzick/wizard/blob/main/packages/docs/guide/api/react.md A practical example demonstrating how to use the `useWizard` hook in a React component. It shows importing the hook, destructuring its returned values, and providing necessary options like `definition`, `initialData`, and `onComplete` callback. ```typescript import { useWizard } from "@gooonzick/wizard-react"; const { state, navigation, actions, validation, loading } = useWizard({ definition: myWizard, initialData: { name: "", email: "" }, onComplete: (data) => { console.log("Completed:", data); }, }); // Use state.currentStep, state.data, navigation.goNext(), actions.updateField(), etc. ``` -------------------------------- ### Install @gooonzick/wizard-vue and @gooonzick/wizard-core Source: https://github.com/gooonzick/wizard/blob/main/packages/vue/README.md Installs the necessary wizard packages using npm, pnpm, or yarn. These packages are required for both the Vue integration and the core wizard functionality. ```bash npm install @gooonzick/wizard-vue @gooonzick/wizard-core # or pnpm add @gooonzick/wizard-vue @gooonzick/wizard-core # or yarn add @gooonzick/wizard-vue @gooonzick/wizard-core ``` -------------------------------- ### Use Granular Wizard Composables (Vue) Source: https://github.com/gooonzick/wizard/blob/main/packages/docs/guide/vue-integration.md Illustrates the pattern of using a `WizardProvider` with granular composables like `useWizardData`, `useWizardNavigation`, and `useWizardActions`. This approach is recommended for performance optimization in complex forms. ```html ``` ```vue ``` -------------------------------- ### Build Project for Production (pnpm) Source: https://github.com/gooonzick/wizard/blob/main/examples/vue-examples/README.md Performs type-checking, compilation, and minification of the project for production deployment. This command generates optimized assets ready for serving. ```shell pnpm build ``` -------------------------------- ### Resolver Transition Example (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/docs/core-concepts.md Presents a resolver transition, which uses an asynchronous function to dynamically determine the next step based on external logic or API calls. ```typescript next: { type: "resolver", resolve: async (data, ctx) => { // Ask your API which step to show next const userType = await ctx.api.getUserType(data.email); return userType === "premium" ? "premium-setup" : "basic-setup"; }, } ``` -------------------------------- ### WizardStepDefinition Example (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/docs/core-concepts.md Illustrates the structure of a WizardStepDefinition, including its ID, title, validation logic, navigation (next step), lifecycle hooks (onEnter), and enablement condition. ```typescript interface SignupData { name?: string; email?: string; plan?: string; } const personalInfoStep: WizardStepDefinition = { id: "personal", title: "Personal Information", // Validation: must pass before going to next step validate: (data) => ({ valid: Boolean(data.name && data.email), errors: { name: !data.name ? "Required" : undefined, email: !data.email ? "Required" : undefined, }, }), // Navigation: where to go next next: { type: "static", to: "plan-selection" }, // Lifecycle: called when entering this step onEnter: async (data, ctx) => { await ctx.analytics?.track("entered_personal_step"); }, // Can this step be accessed? enabled: true, }; ``` -------------------------------- ### Navigate Between Wizard Steps Source: https://github.com/gooonzick/wizard/blob/main/packages/docs/guide/api/core.md Provides examples of navigating through wizard steps using a `WizardMachine`. It covers moving forward, backward, jumping multiple steps, and navigating to a specific step by its ID. ```typescript // Go forward await machine.goNext(); // Go backward await machine.goPrevious(); // Jump steps await machine.goBack(3); // Jump to specific step await machine.goToStep("step-id"); ``` -------------------------------- ### WizardStepDefinition Example with Validation and Lifecycle Source: https://github.com/gooonzick/wizard/blob/main/packages/docs/guide/core-concepts.md Illustrates a WizardStepDefinition for personal information, including validation rules, a static next transition, and an onEnter lifecycle hook for tracking analytics. ```typescript const personalInfoStep: WizardStepDefinition = { id: "personal", title: "Personal Information", // Validation: must pass before going to next step validate: (data) => ({ valid: Boolean(data.name && data.email), errors: { name: !data.name ? "Required" : undefined, email: !data.email ? "Required" : undefined, }, }), // Navigation: where to go next next: { type: "static", to: "plan-selection" }, // Lifecycle: called when entering this step onEnter: async (data, ctx) => { await ctx.analytics?.track("entered_personal_step"); }, // Can this step be accessed? enabled: true, }; ``` -------------------------------- ### Conditional Transition Example (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/docs/core-concepts.md Demonstrates a conditional transition, allowing the wizard to branch to different steps based on the current data state using a series of branches with 'when' conditions. ```typescript next: { type: "conditional", branches: [ { when: (data) => data.plan === "premium", to: "premium-setup" }, { when: (data) => data.plan === "basic", to: "basic-setup" }, { when: () => true, to: "default-setup" }, // fallback ], } ``` -------------------------------- ### Project Build and Test Commands Source: https://github.com/gooonzick/wizard/blob/main/docs/plans/2026-01-19-refactor-dry-violations.md Provides a sequence of command-line instructions for managing the Wizard project. These include installing dependencies, running type checks, executing the full test suite, building all packages, performing linting, and checking for unused code. These steps are crucial for ensuring code quality and successful deployment. ```bash pnpm install pnpm typecheck pnpm test pnpm build pnpm lint pnpm knip ``` -------------------------------- ### Quick Start: Create and Navigate a Linear Wizard in TypeScript Source: https://github.com/gooonzick/wizard/blob/main/packages/core/README.md Demonstrates how to define data types, create a linear wizard with validation and onSubmit handlers, instantiate a WizardMachine, and navigate through the steps. It showcases basic wizard flow and state management. ```typescript import { WizardMachine, createLinearWizard } from "@gooonzick/wizard-core"; // 1. Define your data type type SignupData = { name: string; email: string; }; // 2. Create a wizard const wizard = createLinearWizard({ id: "signup", steps: [ { id: "name", title: "What's your name?", validate: (data) => ({ valid: Boolean(data.name), errors: data.name ? undefined : { name: "Required" }, }), }, { id: "email", title: "What's your email?", validate: (data) => ({ valid: data.email?.includes("@") ?? false, errors: data.email?.includes("@") ? undefined : { email: "Invalid email" }, }), onSubmit: async (data) => { console.log("Form submitted:", data); }, }, ], onComplete: (data) => { console.log("Wizard complete:", data); }, }); // 3. Create a state machine const machine = new WizardMachine(wizard, {}, { name: "", email: "" }); // 4. Navigate console.log(machine.snapshot.currentStepId); // "name" await machine.goNext(); console.log(machine.snapshot.currentStepId); // "email" ``` -------------------------------- ### Memoizing Wizard Definition (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/docs/react-integration.md Shows the importance of memoizing the wizard definition by creating it once outside the component. It contrasts a 'Don't' example where the definition is recreated on every render with a 'Do' example where it's defined globally. ```tsx // ❌ Don't: Recreate definition on every render function MyWizard() { const definition = createWizard(...).build(); const wizard = useWizard({ definition, ... }); } // ✅ Do: Create once const definition = createWizard(...).build(); function MyWizard() { const wizard = useWizard({ definition, ... }); } ``` -------------------------------- ### Handling Async Operations: Validate and Navigate (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/docs/react-integration.md Demonstrates the correct way to handle asynchronous operations like validation and navigation within a wizard. It contrasts a 'Don't' example that fires and forgets navigation with a 'Do' example that awaits validation and then navigation. ```tsx // ❌ Don't: Fire and forget const handleNext = () => { navigation.goNext(); // Don't await }; // ✅ Do: Await navigation const handleNext = async () => { await actions.validate(); if (validation.isValid) { await navigation.goNext(); } }; ``` -------------------------------- ### Basic React Wizard Usage with useWizard Hook Source: https://github.com/gooonzick/wizard/blob/main/packages/docs/guide/react-integration.md Demonstrates the basic integration of a wizard into a React component using the `useWizard` hook. It shows how to define a wizard, initialize the hook with options, and render the UI based on the hook's returned state and actions. ```tsx import { useWizard } from "@gooonzick/wizard-react"; import { createLinearWizard } from "@gooonzick/wizard-core"; type SignupData = { name: string; email: string; }; const wizard = createLinearWizard({ id: "signup", steps: [ { id: "personal", title: "Personal Info", validate: (data) => ({ valid: Boolean(data.name), errors: data.name ? undefined : { name: "Required" }, }), }, { id: "contact", title: "Contact Info", validate: (data) => ({ valid: Boolean(data.email), errors: data.email ? undefined : { email: "Required" }, }), }, ], onComplete: (data) => { console.log("Completed!", data); }, }); export function SignupForm() { const { state, navigation, actions, validation, loading } = useWizard({ definition: wizardDef, initialData: { name: "", email: "" }, onComplete: (data) => { console.log("Form completed:", data); }, }); return (

{state.currentStep.meta?.title}

{state.currentStepId === "personal" && ( actions.updateField("name", e.target.value)} placeholder="Name" /> )} {state.currentStepId === "contact" && ( actions.updateField("email", e.target.value)} placeholder="Email" /> )} {validation.validationErrors && (
{Object.entries(validation.validationErrors).map(([field, error]) => (

{error}

))}
)}
); } ``` -------------------------------- ### Memoize Sub-Components with Vue (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/packages/docs/guide/vue-integration.md Demonstrates how to memoize sub-components in Vue using `defineComponent` and the `setup` function. This is a performance optimization technique to prevent unnecessary re-renders of child components when their props haven't changed. ```typescript import { defineComponent, computed } from "vue"; export default defineComponent({ name: "PersonalStep", props: ["data", "onUpdate"], setup(props) { // Computed properties for optimization // ... return {}; }, }); ``` -------------------------------- ### Basic Usage of WizardStateManager Source: https://github.com/gooonzick/wizard/blob/main/packages/state/README.md Demonstrates how to initialize WizardStateManager, subscribe to state changes (all and specific channels), handle machine state updates, and clean up subscriptions. ```typescript import { WizardMachine } from "@gooonzick/wizard-core"; import { WizardStateManager } from "@gooonzick/wizard-state"; // Create a wizard machine const machine = new WizardMachine(wizardDefinition, context, initialData); // Wrap it with the state manager const manager = new WizardStateManager(machine, "step-1"); // Subscribe to state changes const unsubscribe = manager.subscribe(() => { console.log("State changed"); }); // Subscribe to specific channel const navUnsubscribe = manager.subscribe( () => { console.log("Navigation state changed"); }, "navigation" ); // Handle machine state changes manager.handleStateChange(newState, oldState); // Clean up unsubscribe(); navUnsubscribe(); ``` -------------------------------- ### Validating Before Navigation (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/docs/react-integration.md Provides a code example demonstrating the best practice of validating wizard steps before proceeding to the next. It shows an asynchronous function that first calls `actions.validate()` and then conditionally calls `navigation.goNext()` if `validation.isValid` is true. ```tsx // ✅ Do: Validate first const handleNext = async () => { await actions.validate(); if (validation.isValid) { await navigation.goNext(); } }; ``` -------------------------------- ### Separating Concerns: Logic vs. UI (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/docs/react-integration.md Compares an anti-pattern of mixing wizard logic with UI components against a recommended approach using sub-components. The 'Do' example shows how to pass state and actions down to a dedicated UI component. ```tsx // ❌ Don't: Logic mixed with UI function MyWizard() { const { actions } = useWizard({ definition, initialData }); return ( actions.updateField("name", e.target.value)} /> ); } // ✅ Do: Use sub-components function MyWizard() { const wizard = useWizard({ definition, initialData }); return ; } function PersonalStep({ state, actions, }: { state: UseWizardState; actions: UseWizardActions; }) { return ( actions.updateField("name", e.target.value)} /> ); } ``` -------------------------------- ### useWizard Hook Initialization Example Source: https://github.com/gooonzick/wizard/blob/main/packages/react/README.md Shows how to initialize the `useWizard` hook with a wizard definition, initial data, and optional callbacks like `onComplete`. This hook connects the wizard state machine to your React component. ```tsx const { state, validation, navigation, loading, actions } = useWizard({ definition: wizardDefinition, initialData: myInitialData, context: myContext, onComplete: (data) => { // Handle completion }, }); ``` -------------------------------- ### Common Usage Patterns - Query Step Information Source: https://github.com/gooonzick/wizard/blob/main/docs/api-reference.md Demonstrates how to query information about the current and available steps using the `WizardMachine`. ```APIDOC ## Common Usage Patterns: Query Step Information ### Description This section illustrates how to interact with the `WizardMachine` instance to retrieve information about the wizard's current state, steps, and navigation possibilities. ### Usage ```typescript // Assuming 'machine' is an instance of WizardMachine const machine = new WizardMachine(definition, context, initialData); // Get the current step definition const step = machine.currentStep; // Get a snapshot of the current wizard state const state = machine.snapshot; // Get the ID of the next possible step const nextId = await machine.getNextStepId(); // Check if navigation to a specific step is allowed const canGo = await machine.canNavigateToStep("step-id"); // Get all steps that are currently available for navigation const available = await machine.getAvailableSteps(); ``` ``` -------------------------------- ### Integrating React Hook Form with Wizard (React) Source: https://github.com/gooonzick/wizard/blob/main/docs/react-integration.md Shows how to integrate the wizard library with React Hook Form for managing form state and validation. This example uses `useForm` from `react-hook-form` and `useWizard` from the wizard library to synchronize form data and control wizard navigation. The `handleSubmit` and `watch` functions are used for form submission and data tracking. ```tsx import { useForm } from "react-hook-form"; import { useWizard } from "@gooonzick/wizard-react"; export function FormWizard() { const { register, handleSubmit, watch } = useForm(); const { state, navigation, actions, validation } = useWizard({ definition, initialData, }); const formData = watch(); const handleStepSubmit = async () => { // Validate current step await actions.validate(); if (validation.isValid) { await navigation.goNext(); } }; return (
{state.currentStepId === "personal" && }
); } ``` -------------------------------- ### Create @gooonzick/wizard-state Package Structure Source: https://github.com/gooonzick/wizard/blob/main/docs/plans/2026-01-19-refactor-dry-violations.md Initializes the directory structure for the @gooonzick/wizard-state package, creating necessary subdirectories for source code and tests. ```bash mkdir -p packages/state/src packages/state/tests ``` -------------------------------- ### Initialize and Use WizardMachine in TypeScript Source: https://context7.com/gooonzick/wizard/llms.txt Demonstrates how to initialize and use the WizardMachine in TypeScript. It covers defining wizard steps, creating the machine instance with context and event handlers, reading machine state, updating data, performing validation, navigating through steps, and submitting the wizard. Dependencies include '@gooonzick/wizard-core'. ```typescript import { WizardMachine, createLinearWizard } from "@gooonzick/wizard-core"; type FormData = { firstName: string; lastName: string; age: number }; const wizard = createLinearWizard({ id: "demo", steps: [ { id: "name", title: "Name" }, { id: "age", title: "Age" }, ], }); const machine = new WizardMachine( wizard, { debug: true }, // Context with debug logging { firstName: "", lastName: "", age: 0 }, { onStateChange: (state) => console.log("State changed:", state.currentStepId), onStepEnter: (stepId) => console.log("Entered step:", stepId), onStepLeave: (stepId) => console.log("Left step:", stepId), onValidation: (result) => console.log("Validation:", result.valid), onComplete: (data) => console.log("Wizard complete:", data), onError: (error) => console.error("Error:", error.message), } ); // Read state console.log(machine.snapshot); // { currentStepId, data, isValid, isCompleted, validationErrors } console.log(machine.currentStep); // Current step definition console.log(machine.visited); // ["name"] console.log(machine.history); // ["name"] console.log(machine.isBusy); // false // Update data machine.updateData((data) => ({ ...data, firstName: "John" })); machine.setData({ firstName: "Jane", lastName: "Doe", age: 25 }); // Validation const result = await machine.validate(); console.log(result); // { valid: true } or { valid: false, errors: {...} } // Navigation await machine.goNext(); // Validates, submits, then navigates forward await machine.goPrevious(); // Navigates backward await machine.goToStep("age"); // Jump to specific step await machine.goBack(2); // Go back 2 steps in history // Query navigation const nextStep = await machine.getNextStepId(); // "age" or null const prevStep = await machine.getPreviousStepId(); // null or previous step id const available = await machine.getAvailableSteps(); // ["name", "age"] const canGo = await machine.canNavigateToStep("age"); // true // Submit and complete const canSubmit = await machine.canSubmit(); // true if valid and on last step await machine.submit(); // Validates and runs onSubmit handler ``` -------------------------------- ### Control Wizard Navigation (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/packages/core/README.md Demonstrates how to navigate through wizard steps using the `WizardMachine` instance. Includes methods for moving forward, backward, jumping to specific steps, and querying navigation state. ```typescript const machine = new WizardMachine(definition, context, initialData); // Move forward await machine.goNext(); // Move backward await machine.goPrevious(); // Jump to specific step await machine.goToStep("step-id"); // Query navigation const canGo = await machine.canNavigateToStep("step-id"); const nextId = await machine.getNextStepId(); const available = await machine.getAvailableSteps(); ``` -------------------------------- ### Adopting Granular Hooks with WizardProvider (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/docs/react-integration.md Illustrates how to adopt granular hooks for performance optimization by wrapping the wizard with a WizardProvider and then using specific hooks like useWizardData, useWizardNavigation, and useWizardActions in nested components. ```tsx // Step 1: Wrap with provider // Step 2: Use granular hooks in nested components const { data, currentStepId } = useWizardData(); const { canGoNext, goNext } = useWizardNavigation(); const { updateField } = useWizardActions(); ``` -------------------------------- ### Pull Request Title Example (Text) Source: https://github.com/gooonzick/wizard/blob/main/CONTRIBUTING.md Example of a pull request title following the Conventional Commits format, indicating the type and scope of the changes. ```text feat(react): add granular hooks for performance optimization ``` -------------------------------- ### Conventional Commit Message Examples (Text) Source: https://github.com/gooonzick/wizard/blob/main/CONTRIBUTING.md Examples illustrating the Conventional Commits format for commit messages, including different types and scopes relevant to the WizardForm project. ```text feat(core): add support for async guards fix(react): resolve memory leak in useWizard hook docs(vue): update README with new examples test(core): add tests for transition resolvers chore: update dependencies ``` -------------------------------- ### WizardMachine Initialization and State Access (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/docs/core-concepts.md Demonstrates how to initialize the WizardMachine with a definition, context, and initial data. It also shows how to access the current state, step definition, visited steps, and navigation history using getters. ```typescript import { WizardMachine } from "@gooonzick/wizard-core"; // Assuming 'definition', 'context', and 'initialData' are defined elsewhere const machine = new WizardMachine(definition, context, initialData, { onStateChange: (state) => { // Fired whenever the machine changes state console.log("Current step:", state.currentStepId); }, }); // Access state via getters (not methods) console.log(machine.snapshot); // Get current state console.log(machine.currentStep); // Get current step definition console.log(machine.visited); // Get visited steps console.log(machine.history); // Get navigation history ``` -------------------------------- ### Simple Field Validation Example (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/docs/core-concepts.md A basic example of a step validator that checks if an email field contains the '@' symbol, returning a boolean result and an error message if invalid. ```typescript validate: (data) => ({ valid: data.email?.includes("@"), errors: !data.email?.includes("@") ? { email: "Invalid email" } : undefined, }); ``` -------------------------------- ### Basic React Wizard Integration with useWizard Hook Source: https://github.com/gooonzick/wizard/blob/main/docs/react-integration.md Demonstrates how to use the `useWizard` hook to manage wizard state, navigation, actions, and validation within a React component. It includes defining wizard steps, handling user input, displaying errors, and controlling navigation. ```tsx import { useWizard } from "@gooonz/wizard-react"; import { createLinearWizard } from "@gooonz/wizard-core"; type SignupData = { name: string; email: string; }; const wizardDef = createLinearWizard({ id: "signup", steps: [ { id: "personal", title: "Personal Info", validate: (data) => ({ valid: Boolean(data.name), errors: data.name ? undefined : { name: "Required" }, }), }, { id: "contact", title: "Contact Info", validate: (data) => ({ valid: Boolean(data.email), errors: data.email ? undefined : { email: "Required" }, }), }, ], onComplete: (data) => { console.log("Completed!", data); }, }); export function SignupForm() { const { state, navigation, actions, validation, loading } = useWizard({ definition: wizardDef, initialData: { name: "", email: "" }, onComplete: (data) => { console.log("Form completed:", data); }, }); return (

{state.currentStep.meta?.title}

{state.currentStepId === "personal" && ( actions.updateField("name", e.target.value)} placeholder="Name" /> )} {state.currentStepId === "contact" && ( actions.updateField("email", e.target.value)} placeholder="Email" /> )} {validation.validationErrors && (
{Object.entries(validation.validationErrors).map(([field, error]) => (

{error}

))}
)}
); } ``` -------------------------------- ### JSDoc for createWizard Function (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/CONTRIBUTING.md Provides an example of JSDoc comments for documenting the `createWizard` function, explaining its purpose, parameters, return value, and including a usage example. This adheres to documentation standards for public APIs. ```typescript /** * Creates a new wizard with the given configuration. * * @param id - Unique identifier for the wizard * @returns A wizard builder instance * @example * ```typescript * const wizard = createWizard("signup") * .step("email", (s) => s.next("password")) * .build(); * ``` */ export function createWizard(id: string): WizardBuilder { return new WizardBuilder(id); } ``` -------------------------------- ### Create and Configure Wizard - TypeScript Source: https://github.com/gooonzick/wizard/blob/main/docs/core-concepts.md Defines a multi-step onboarding wizard using the createWizard function. It includes steps for collecting user name, company size, training preference, and a summary, with conditional logic for transitions and step visibility. The wizard supports asynchronous submission and completion actions. ```typescript import { createWizard } from "@gooonzick/wizard-core"; type OnboardingData = { name: string; companySize: "small" | "medium" | "large"; wantsTraining: boolean; }; const wizard = createWizard("onboarding") .initialStep("name") // Step 1: Get user name (static next) .step("name", (s) => s.title("What's your name?").required("name").next("company"), ) // Step 2: Get company size (conditional next) .step("company", (s) => s .title("Company Size") .required("companySize") .nextWhen([ { when: (d) => d.wantsTraining, to: "training" }, { when: () => true, to: "summary" }, ]), ) // Step 3: Training (conditionally shown, resolver previous) .step("training", (s) => s .title("Choose Training") .enabled((d) => d.wantsTraining) .previous({ type: "resolver", resolve: (d) => (d.wantsTraining ? "company" : null), }) .next("summary"), ) // Step 4: Summary (async submit) .step("summary", (s) => s.title("Review").onSubmit(async (data, ctx) => { await ctx.api.submitOnboarding(data); }), ) .onComplete(async (data, ctx) => { await ctx.router.navigate("/dashboard"); }) .build(); ``` -------------------------------- ### Conditional Transition Definition and Example (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/docs/api-reference.md Defines how to branch within a wizard based on specified conditions. The `ConditionalTransition` interface uses an array of `ConditionalBranch` objects, each with a `when` guard and a `to` step ID. The example demonstrates setting up branches for premium and standard user flows. ```typescript interface ConditionalTransition { type: "conditional"; branches: ConditionalBranch[]; } interface ConditionalBranch { when: StepGuard; to: StepId; } // Example: next: { type: "conditional", branches: [ { when: (d) => d.isPremium, to: "premium-setup" }, { when: () => true, to: "standard-setup" }, ], } ``` -------------------------------- ### Common Usage Patterns - Navigate Between Steps Source: https://github.com/gooonzick/wizard/blob/main/docs/api-reference.md Details the methods available for navigating through the wizard's steps. ```APIDOC ## Common Usage Patterns: Navigate Between Steps ### Description This section outlines the various methods provided by the `WizardMachine` for controlling the user's progression through the wizard's steps, including forward, backward, and direct navigation. ### Usage ```typescript // Assuming 'machine' is an instance of WizardMachine // Move to the next step await machine.goNext(); // Move to the previous step await machine.goPrevious(); // Go back a specified number of steps await machine.goBack(3); // Navigate directly to a specific step by its ID await machine.goToStep("step-id"); ``` ``` -------------------------------- ### Tracking Wizard Progress and Visited Steps (React) Source: https://github.com/gooonzick/wizard/blob/main/docs/react-integration.md Demonstrates how to track and display the user's progress through the wizard. It calculates a progress percentage based on visited steps and total available steps. Additionally, it shows how to iterate over visited steps, potentially to display a summary or review of completed sections. ```tsx export function ProgressWizard() { const { state, navigation } = useWizard({ definition, initialData }); const progress = (navigation.visitedSteps.length / navigation.availableSteps.length) * 100; return (

Step {navigation.visitedSteps.length} of {" "} {navigation.availableSteps.length}

{state.currentStepId === "review" && (
{navigation.visitedSteps.map((stepId) => (

{state.currentStep.meta?.title}

))}
)}
); } ``` -------------------------------- ### Resolver Transition Definition and Example (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/docs/api-reference.md Enables dynamic step resolution using an asynchronous function. The `ResolverTransition` interface specifies a `resolve` function that takes wizard data and context to return the next step ID. The example shows an async resolver determining the next step based on an API call. ```typescript interface ResolverTransition { type: "resolver"; resolve: StepTransitionResolver; } type StepTransitionResolver = ( data: T, ctx: WizardContext, ) => SyncOrAsync; // Example: next: { type: "resolver", resolve: async (data, ctx) => { const plan = await ctx.api.getPlan(data.userId); return plan.type === "enterprise" ? "enterprise-setup" : "basic-setup"; }, } ``` -------------------------------- ### Converting Linear Wizard to Builder Pattern in TypeScript Source: https://github.com/gooonzick/wizard/blob/main/docs/defining-wizards.md Provides a code example for converting a wizard built using the linear approach to the builder pattern. It shows how to initialize a new wizard with the builder and manually add steps from the linear wizard. ```typescript // From linear... const linear = createLinearWizard({ ... }); // To builder... const builder = createWizard("same-id") .initialStep(linear.steps[0].id) .step(linear.steps[0].id, (s) => { /* ... */ }) // ... add each step .build(); ``` -------------------------------- ### WizardStateManager: Get Initial Step ID (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/docs/plans/2026-01-19-refactor-dry-violations.md Returns the ID of the very first step in the wizard's defined sequence. ```typescript /** * Get initial step ID */ getInitialStepId(): StepId { return this.initialStepId; } } ``` -------------------------------- ### Use Standalone useWizard Composable (TypeScript) Source: https://github.com/gooonzick/wizard/blob/main/packages/docs/guide/vue-integration.md Demonstrates the new API structure for the standalone `useWizard()` composable, showing how to access state, validation, navigation, loading, and actions. This is suitable for simpler wizards. ```typescript import { useWizard } from "@/composables/useWizard"; // Assuming 'definition' and 'initialData' are defined elsewhere const { state, validation, navigation, loading, actions } = useWizard({ definition, initialData, }); // Access state (note the .value for ComputedRef) const data = state.data.value; const currentStepId = state.currentStepId.value; // Access navigation const canGoNext = navigation.canGoNext.value; await navigation.goNext(); // Access actions actions.updateField("name", "John"); ``` -------------------------------- ### Get Loading Snapshot Source: https://github.com/gooonzick/wizard/blob/main/docs/plans/2026-01-19-refactor-dry-violations.md Returns the current loading state snapshot, which can be used to track asynchronous operations within the wizard. ```typescript /** * Get loading snapshot */ getLoadingSnapshot(): LoadingState { return this.loadingCache; } ``` -------------------------------- ### WizardStateManager Constructor Source: https://github.com/gooonzick/wizard/blob/main/packages/state/README.md Illustrates the initialization of WizardStateManager, which requires a WizardMachine instance and an initial step ID. ```typescript new WizardStateManager( machine: WizardMachine, initialStepId: StepId ) ``` -------------------------------- ### Get Current Machine Snapshot Source: https://github.com/gooonzick/wizard/blob/main/docs/plans/2026-01-19-refactor-dry-violations.md Returns the current snapshot of the wizard machine, providing a complete view of the machine's current state. ```typescript /** * Get current machine snapshot */ getSnapshot(): WizardState { return this.machine.snapshot; } ```