@hitachivantara/uikit-react-lab
Version:
Contributed React components for the NEXT UI Kit.
188 lines (187 loc) • 6.24 kB
JavaScript
import { jsx } from "react/jsx-runtime";
import styled from "@emotion/styled";
import { useTheme, useWidth, HvTypography, HvTooltip } from "@hitachivantara/uikit-react-core";
import { theme } from "@hitachivantara/uikit-styles";
import { useClasses } from "./StepNavigation.styles.js";
import { staticClasses } from "./StepNavigation.styles.js";
import { TITLE_WIDTH, TITLE_MARGIN, SEPARATOR_WIDTH } from "./utils.js";
import { HvSimpleNavigation } from "./SimpleNavigation/SimpleNavigation.js";
import { HvDefaultNavigation } from "./DefaultNavigation/DefaultNavigation.js";
const HvStepNavigation = ({
className,
classes: classesProp,
width,
steps,
stepSize,
showTitles,
type = "Default",
"aria-label": ariaLabel,
...others
}) => {
const { classes, css, cx } = useClasses(classesProp);
const { activeTheme } = useTheme();
const breakpoint = useWidth();
const stepSizeKey = stepSize ?? (["xs", "sm"].includes(breakpoint) ? "sm" : "md");
const hasTitles = showTitles ?? !["xs", "sm"].includes(breakpoint);
const styledLi = (containerSize) => styled("li")({
width: containerSize,
height: containerSize
});
const styledDiv = (containerSize) => styled("div")({
width: containerSize,
height: containerSize
});
const styledSeparatorElement = (title, separatorClassName, separatorHeight, separatorWidth, backgroundColor) => {
const widthValue = separatorWidth - 2 * Number(
(activeTheme?.stepNavigation.separatorMargin || "0px").replace(
"px",
""
)
);
return /* @__PURE__ */ jsx(
"li",
{
"aria-hidden": true,
className: cx(
css({
height: separatorHeight,
width: widthValue,
backgroundColor,
margin: `0 ${theme.stepNavigation.separatorMargin}`
}),
classes.separator
),
children: /* @__PURE__ */ jsx("div", { className: separatorClassName })
},
`separator-${title}`
);
};
const drawItems = ({
separatorValues: { minWidth, maxWidth, getColor, height },
stepValues: { minSize, maxSize, StepComponent }
}) => {
const items = steps.reduce(
(acc, { state, title, separatorClassName, ...props }, index) => {
const containerSize = state === "Current" ? maxSize : minSize;
const StepContainer = styledLi(containerSize);
const Step = styledDiv(Math.max(containerSize, 30));
const stepProps = {
size: stepSizeKey,
state,
title,
number: index + 1,
...props
};
const stepElement = /* @__PURE__ */ jsx(StepContainer, { className: classes.li, children: hasTitles ? /* @__PURE__ */ jsx(
StepComponent,
{
"aria-label": `${title}`,
...stepProps
},
`step-${title}`
) : /* @__PURE__ */ jsx(
HvTooltip,
{
placement: "bottom",
title: /* @__PURE__ */ jsx(HvTypography, { children: `${index + 1}. ${title}` }),
children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Step, { className: classes.li, children: /* @__PURE__ */ jsx(StepComponent, { "aria-label": `${title}`, ...stepProps }) }) })
}
) }, `step-${title}`);
if (index < steps.length - 1) {
const separatorElement = styledSeparatorElement(
title,
separatorClassName,
height,
[steps[index + 1].state, state].includes("Current") ? minWidth : maxWidth,
getColor(
steps[index + 1].state === "Disabled" ? "Disabled" : state,
theme
)
);
acc.push(stepElement, separatorElement);
return acc;
}
acc.push(stepElement);
return acc;
},
[]
);
return /* @__PURE__ */ jsx("ol", { className: classes.ol, children: items });
};
const getDynamicValues = (stepsWidth) => {
const themeBreakpoints = activeTheme?.breakpoints.values || {};
const maxWidth = width?.[breakpoint] ?? Math.max(
Number(hasTitles) * (TITLE_WIDTH + TITLE_MARGIN) * steps.length - TITLE_MARGIN,
SEPARATOR_WIDTH * (steps.length - 1) + stepsWidth
);
const next = Object.keys(themeBreakpoints).find(
(_, index, self) => index - 1 >= 0 ? self[index - 1] === breakpoint : false
);
const navWidth = Math.min(
maxWidth,
next ? themeBreakpoints[next] : maxWidth
);
const titleWidth = Number(hasTitles) * Math.ceil((navWidth + TITLE_MARGIN) / steps.length);
const separatorWidth = Number(!hasTitles) * Math.ceil((navWidth - stepsWidth) / (steps.length - 1));
return { width: navWidth, titleWidth, separatorWidth };
};
const getTitles = (getTitleProps) => hasTitles ? /* @__PURE__ */ jsx("div", { className: classes.titles, children: steps.map(({ title: rawTitle, state, titleClassName }, index) => {
const {
variant = "label",
title = rawTitle,
titleWidth = 0,
titleDisabled = false
} = getTitleProps?.({
state,
rawTitle,
number: index + 1
}) ?? {};
return /* @__PURE__ */ jsx(
HvTypography,
{
variant,
className: cx(
css({
textAlign: "center",
width: titleWidth - TITLE_MARGIN,
marginRight: TITLE_MARGIN
}),
titleClassName
),
disabled: titleDisabled,
children: title
},
title
);
}) }) : null;
const StepNavigation = {
Default: HvDefaultNavigation,
Simple: HvSimpleNavigation
}[type];
return /* @__PURE__ */ jsx(
StepNavigation,
{
numSteps: steps.length,
stepSize: stepSizeKey,
getTitles,
getDynamicValues,
className: cx(classes.root, className),
...others,
children: ({ stepsWidth, navWidth, ...itemsProps }) => /* @__PURE__ */ jsx(
"nav",
{
style: {
width: `${navWidth}px`,
margin: 0
},
"aria-label": ariaLabel,
children: drawItems(itemsProps)
}
)
}
);
};
export {
HvStepNavigation,
staticClasses as stepNavigationClasses
};