/**
* @fileoverview Stepper — a controlled/uncontrolled multi-step wizard. Pairs the
* existing visual `Steps`/`Step` indicator with content `StepperPanel`s and a
* built-in `StepperNav` (Back / Next / Finish). State is driven by the headless
* `useStepper` hook — bring your own instance via `stepper={...}` (controlled)
* or let `Stepper` own one (uncontrolled). Panel transitions use JS motion
* (Pattern A) gated by `useSaasflareMotion`.
* @author Saasflare™
* @module packages/ui/components/ui/stepper
* @package ui
*
* @component
* @example
* import { Stepper, StepperPanel } from "@saasflare/ui";
*
*
* Account fields…
* Profile fields…
* All set!
*
*/
import { type ReactNode } from "react";
import { type SaasflareComponentProps } from "../../providers";
import { type UseStepperReturn } from "../../hooks/use-stepper";
/**
* One step descriptor for the Stepper indicator (mirrors the visual `Step`).
*
* @example
* const items: StepperItem[] = [{ title: "Plan" }, { title: "Add-ons", optional: true }];
*/
export interface StepperItem {
/** Title shown in the indicator. */
title: string;
/** Optional sub-description. */
description?: string;
/** Optional icon replacing the number. */
icon?: ReactNode;
/** Marks the step skippable. */
optional?: boolean;
}
/**
* Props for {@link Stepper}.
*
* @example
* …
*/
export interface StepperProps extends SaasflareComponentProps {
/** Step metadata for the indicator. Length defines the step count. */
items: ReadonlyArray;
/** Indicator layout (forwarded to `Steps`). Default: `"horizontal"` */
direction?: "horizontal" | "vertical";
/** Linear mode forwarded to the internal hook. Default: `true` */
linear?: boolean;
/** Bring-your-own hook instance (controlled). When omitted, Stepper owns one. */
stepper?: UseStepperReturn;
/** Initial step when Stepper owns the hook (uncontrolled). Default: `0` */
defaultStep?: number;
/** Global validation gate (uncontrolled mode only). */
validate?: (step: number) => boolean | string | void | Promise;
/** Fired on finish (uncontrolled mode only). */
onComplete?: () => void;
/** `"unmount"` = only active panel in DOM; `"keepMounted"` = all panels mounted, inactive hidden. Default: `"unmount"` */
mountMode?: "unmount" | "keepMounted";
/** Hide the built-in ``. Default: `false` */
hideNav?: boolean;
/** Panel children — one `` per step, in order. */
children: ReactNode;
/** Class for the root. */
className?: string;
}
/**
* Content panel for a single step. Renders only when active (or stays mounted
* and hidden in `keepMounted` mode).
*
* @example
*
*/
export interface StepperPanelProps {
/** 0-based index this panel maps to. */
value: number;
/** Panel content. */
children: ReactNode;
/** Class for the panel. */
className?: string;
}
/**
* Built-in navigation row (Back / Next / Finish). Auto-rendered unless `hideNav`.
*
* @example
*
*/
export interface StepperNavProps {
/** Override Back label. Default: `"Back"` */
backLabel?: ReactNode;
/** Override Next label. Default: `"Next"` */
nextLabel?: ReactNode;
/** Override Finish (last-step Next) label. Default: `"Finish"` */
finishLabel?: ReactNode;
/** Show a "Skip" button on optional steps. Default: `true` */
allowSkip?: boolean;
/** Class for the nav row. */
className?: string;
}
/**
* Render-prop access to the active Stepper's hook (for custom footers/headers).
*
* @example
* {(s) =>
Step {s.activeStep + 1} of {s.count}
}
*/
export interface StepperContentProps {
/** Render-prop receiving the active stepper instance. */
children: (stepper: UseStepperReturn) => ReactNode;
}
/**
* Primary multi-step wizard. Resolves theme axes via {@link useSaasflareProps}
* and emits `data-surface`/`data-radius`/`data-animated` on its root. Owns a
* {@link useStepper} instance unless one is supplied via `stepper`.
*
* Indicator step circles become focusable triggers only in non-linear mode
* (roving tabindex, Arrow/Home/End/Enter/Space); in linear mode they are
* non-interactive and `aria-disabled` to enforce order. On step change, focus
* moves to the newly active panel (skipped on initial mount).
*
* @component
* @layer ui
*
* @param {ReadonlyArray} items - Indicator metadata; length = step count.
* @param {string} direction - Indicator layout: "horizontal" | "vertical".
* @param {boolean} linear - Forbid forward jumps past incomplete required steps.
* @param {UseStepperReturn} stepper - External hook instance (controlled).
* @param {string} mountMode - "unmount" | "keepMounted".
*
* @example
*
* A
* B
*
*
* @example
* // Controlled: drive an external hook instance
* const s = useStepper({ count: 3 });
* …
*/
export declare function Stepper({ items, direction, linear, stepper: externalStepper, defaultStep, validate, onComplete, mountMode, hideNav, children, className, surface, radius, animated, iconWeight, }: StepperProps): import("react/jsx-runtime").JSX.Element;
/**
* Content panel for a single step. As a child of {@link Stepper} it is a data
* carrier: `Stepper` reads its `value`, `children`, and `className` and renders
* the matching region itself (so it can apply motion + ARIA). Rendering one
* standalone simply outputs its children in a labelled region.
*
* @component
* @example
* Step one content
*/
export declare function StepperPanel(props: StepperPanelProps): ReactNode;
/**
* Built-in navigation row: Back, an optional Skip (on optional steps), and a
* Next button that becomes Finish on the last step. Reads the active stepper
* from context and inherits the wizard's theme axes. Next is disabled while an
* async gate is validating.
*
* @component
* @example
*
* …panels…
*
*
*/
export declare function StepperNav({ backLabel, nextLabel, finishLabel, allowSkip, className, }: StepperNavProps): ReactNode;
/**
* Render-prop escape hatch exposing the active Stepper's hook instance, for
* custom headers/footers/summaries outside the built-in nav.
*
* @component
* @example
*
* …panels…
*
* {(s) =>
{s.activeStep + 1}/{s.count}
}
*
*
*/
export declare function StepperContent({ children }: StepperContentProps): ReactNode;