import { Button } from "../Button/Button"; import "./stepper.css"; import { CSSProperties } from "react"; import { Spinner } from "../Spinner/Spinner"; import { Step } from "./Step"; interface CustomStyleCSS extends CSSProperties { "--codex-background"?: string; "--codex-border-radius"?: string; "--codex-stepper-background": string; "--codex-color-primary": string; "--codex-border-color": string; } type Props = { /** * The steps titles */ titles: string[]; /** * The current component to show. */ Body: () => JSX.Element; // The current step to display in stepper state. step: number; // If it's true, the stepper will display a spinner. // The progress is controlled by the parent component, // to give flexibility when changing step. progress: boolean; /** * The duration between two steps in milliseconds. * The default is 500. */ duration?: number; /** * Callback called whenever the step is changing. * It's working in two phase: * "before" - allow to do before actions like updating progress state * "end" - executed after duration time */ onChangeStep: (s: number, state: "before" | "end") => void | Promise; /** * Disable the next button. * Default: progress == true */ isNextDisable?: boolean; style?: CustomStyleCSS; }; type Step = { index: number; title: string; }; export function Stepper({ titles, Body, step, progress, onChangeStep, duration = 500, isNextDisable = progress, style, }: Props) { const onMoveStep = async (newStep: number) => { await onChangeStep(newStep, "before"); setTimeout(() => onChangeStep(newStep, "end"), duration); }; const label = step === titles.length - 1 ? "Finish" : "Next"; return (
{titles.map((title, index) => ( index ? () => onMoveStep(index) : undefined} /> ))}
{progress ? (
) : ( )}
); }