mirror of
https://github.com/logos-storage/logos-storage-marketplace-ui-components.git
synced 2026-01-02 13:33:09 +00:00
121 lines
2.8 KiB
TypeScript
121 lines
2.8 KiB
TypeScript
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<void>;
|
|
|
|
/**
|
|
* 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 (
|
|
<div className="stepper" style={style}>
|
|
<div className="stepper-steps">
|
|
{titles.map((title, index) => (
|
|
<Step
|
|
title={title}
|
|
step={index}
|
|
isActive={index === step}
|
|
isLast={index === titles.length - 1}
|
|
isDone={index < step}
|
|
key={title}
|
|
onClick={step > index ? () => onMoveStep(index) : undefined}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
<div className="stepper-body">
|
|
{progress ? (
|
|
<div className="stepper-progress">
|
|
<Spinner width={"3rem"} />
|
|
</div>
|
|
) : (
|
|
<Body />
|
|
)}
|
|
</div>
|
|
|
|
<div className="stepper-buttons">
|
|
<Button
|
|
label={step ? "Back" : "Close"}
|
|
variant="outline"
|
|
onClick={() => onMoveStep(step - 1)}
|
|
disabled={progress}
|
|
/>
|
|
<Button
|
|
label={label}
|
|
onClick={() => onMoveStep(step + 1)}
|
|
disabled={isNextDisable}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|