@hitachivantara/uikit-react-lab
Version:
Contributed React components to UI Kit by the community.
140 lines (139 loc) • 5.56 kB
JavaScript
import { HvDefaultNavigation } from "./DefaultNavigation/DefaultNavigation.js";
import { HvSimpleNavigation } from "./SimpleNavigation/SimpleNavigation.js";
import { useClasses } from "./StepNavigation.styles.js";
import { HvTooltip, HvTypography, useTheme, useWidth } from "@hitachivantara/uikit-react-core";
import { theme as theme$1 } from "@hitachivantara/uikit-styles";
import { jsx } from "react/jsx-runtime";
import styled from "@emotion/styled";
//#region src/StepNavigation/StepNavigation.tsx
/**
* Navigation page with steps.
*
* You need to define the `steps` displayed on the component so that itself can be drawn on the UI.
* On each step, you need to define a `state` - 'Pending', 'Failed', 'Completed', 'Current', 'Disabled' -
* and a `title` to be shown as a tooltip or a text above of the step. You can also defined `className`, `separatorClassName`, and `titleClassName` to override the default styles.
*
* If the step component has titles, each one will have 215px of width by default.
*/
var 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) => {
return /* @__PURE__ */ jsx("li", {
"aria-hidden": true,
className: cx(css({
height: separatorHeight,
width: separatorWidth - 8,
backgroundColor,
margin: `0 4px`
}), 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$1));
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) * 235 * steps.length - 20, 100 * (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);
return {
width: navWidth,
titleWidth: Number(hasTitles) * Math.ceil((navWidth + 20) / steps.length),
separatorWidth: Number(!hasTitles) * Math.ceil((navWidth - stepsWidth) / (steps.length - 1))
};
};
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 - 20,
marginRight: 20
}), 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)
})
});
};
//#endregion
export { HvStepNavigation };