braid-design-system
Version:
Themeable design system for the SEEK Group
126 lines (125 loc) • 3.94 kB
JavaScript
import { jsx, jsxs } from "react/jsx-runtime";
import assert from "assert";
import { Children } from "react";
import { flattenChildren } from "../../utils/flattenChildren.mjs";
import { Box } from "../Box/Box.mjs";
import { Hidden } from "../Hidden/Hidden.mjs";
import { Text } from "../Text/Text.mjs";
import { buildDataAttributes } from "../private/buildDataAttributes.mjs";
import { StepContext, StepperContextProvider } from "./StepperContext.mjs";
import { stretch, stretchLastAboveTablet, progressTrack } from "./Stepper.css.mjs";
const resolveActiveStep = (mode, progress, activeStep) => {
if (mode === "linear" && (typeof activeStep === "undefined" || activeStep > progress)) {
return progress;
}
return activeStep || 0;
};
const Stepper = ({
activeStep,
label,
mode = "linear",
tone,
children,
data,
align = "center",
id,
onStepClick,
...restProps
}) => {
const steps = flattenChildren(children);
const stepCount = steps.length;
const isLinear = mode === "linear";
const progress = "progress" in restProps ? restProps.progress : 0;
const activeStepNumber = resolveActiveStep(mode, progress, activeStep);
let stepName = "";
const stepItems = Children.map(steps, (child, index) => {
const stepNumber = index + 1;
const isLast = stepNumber === stepCount;
assert(
!child || child.type.__isStep__,
"Only Step elements can be direct children of a Stepper. See the documentation for correct usage: https://seek-oss.github.io/braid-design-system/components/Stepper"
);
if (stepNumber === activeStepNumber && typeof child === "object") {
stepName = child.props.children;
}
return /* @__PURE__ */ jsx(
StepContext.Provider,
{
value: {
stepNumber,
isLast
},
children: /* @__PURE__ */ jsx(
Box,
{
component: "li",
className: [
!isLast ? stretch : void 0,
isLast && align === "center" ? stretchLastAboveTablet : void 0
],
children: child
}
)
}
);
});
return /* @__PURE__ */ jsx(
StepperContextProvider,
{
activeStep: activeStepNumber,
tone,
align,
progress,
stepCount: stepItems.length,
isLinear,
onStepClick,
children: /* @__PURE__ */ jsxs(
Box,
{
component: "nav",
position: "relative",
"aria-label": label,
id,
...buildDataAttributes({ data, validateRestProps: restProps }),
children: [
/* @__PURE__ */ jsx(
Box,
{
component: "ol",
display: "flex",
paddingBottom: { mobile: "medium", tablet: "none" },
justifyContent: {
mobile: "spaceBetween",
tablet: align === "center" ? "center" : void 0
},
children: stepItems
}
),
isLinear ? /* @__PURE__ */ jsx(
Box,
{
component: "span",
position: "absolute",
pointerEvents: "none",
className: progressTrack,
role: "progressbar",
"aria-valuemin": 0,
"aria-valuemax": stepCount - 1,
"aria-valuenow": progress > 0 ? progress - 1 : void 0,
"aria-valuetext": progress > 0 ? label : void 0,
style: {
left: `${(100 - (stepCount - 1) / stepCount * 100) / 2}%`,
width: `${(progress - 1) / stepCount * 100}%`
}
}
) : null,
/* @__PURE__ */ jsx(Hidden, { above: "mobile", children: /* @__PURE__ */ jsx(Text, { weight: "strong", children: stepName }) })
]
}
)
}
);
};
export {
Stepper
};