braid-design-system
Version:
Themeable design system for the SEEK Group
171 lines (170 loc) • 3.79 kB
JavaScript
import { jsx } from "react/jsx-runtime";
import { createContext, useReducer } from "react";
import { normalizeKey } from "../private/normalizeKey.mjs";
const StepContext = createContext({
stepNumber: 0,
isLast: false
});
const NAV_RIGHT = 0;
const NAV_DOWN = 1;
const NAV_LEFT = 2;
const NAV_UP = 3;
const NAV_HOME = 4;
const NAV_END = 5;
const NAV_TAB = 6;
const NAV_CLICKED = 7;
const NAV_FOCUSED = 8;
const NAV_BLURRED = 9;
const StepperContext = createContext(null);
const getNextStep = (moveAmount, current, maxStep) => {
if (current === null) {
return moveAmount > 0 ? 1 : maxStep;
}
const nextStep = moveAmount + current;
if (nextStep > maxStep) {
return 1;
}
if (nextStep < 1) {
return maxStep;
}
return nextStep;
};
const StepperContextProvider = ({
children,
activeStep,
stepCount: stepCountProp,
progress,
isLinear,
align,
tone = "formAccent",
onStepClick
}) => {
const stepCount = isLinear ? progress : stepCountProp;
const [stepperState, dispatch] = useReducer(
(state, action) => {
switch (action.type) {
case NAV_UP:
case NAV_LEFT: {
return {
...state,
focusedStep: getNextStep(-1, state.focusedStep, stepCount)
};
}
case NAV_DOWN:
case NAV_RIGHT: {
return {
...state,
focusedStep: getNextStep(1, state.focusedStep, stepCount)
};
}
case NAV_HOME: {
return {
...state,
focusedStep: 1
};
}
case NAV_END: {
return {
...state,
focusedStep: stepCount
};
}
case NAV_BLURRED:
case NAV_TAB: {
return {
...state,
focusedStep: null
};
}
case NAV_CLICKED: {
return {
...state,
focusedStep: action.value
};
}
case NAV_FOCUSED: {
return {
...state,
focusedStep: state.focusedStep === null ? activeStep : state.focusedStep
};
}
default:
return state;
}
},
{
focusedStep: null,
activeStep,
isLinear,
tone,
align,
progress,
onStepClick
}
);
const onKeyUp = (event) => {
const targetKey = normalizeKey(event);
if (targetKey === "Tab") {
return;
}
const action = {
ArrowRight: { type: NAV_RIGHT },
ArrowLeft: { type: NAV_LEFT },
ArrowUp: { type: NAV_UP },
ArrowDown: { type: NAV_DOWN },
Home: { type: NAV_HOME },
End: { type: NAV_END }
};
if (action[targetKey]) {
dispatch(action[targetKey]);
}
};
const onKeyDown = (event) => {
const targetKey = normalizeKey(event);
if (targetKey === "Tab") {
dispatch({ type: NAV_TAB });
return;
}
const isNavigationKeyPress = targetKey.indexOf("Arrow") === 0 || ["Home", "End"].includes(targetKey);
if (isNavigationKeyPress) {
event.preventDefault();
}
};
const onFocus = () => dispatch({
type: NAV_FOCUSED
});
const onBlur = () => dispatch({
type: NAV_BLURRED
});
const onClick = (index) => dispatch({
type: NAV_CLICKED,
value: index
});
return /* @__PURE__ */ jsx(
StepperContext.Provider,
{
value: {
...stepperState,
activeStep,
isLinear,
align,
tone,
progress,
onStepClick,
...typeof onStepClick === "function" ? {
onKeyUp,
onKeyDown,
onClick,
onFocus,
onBlur
} : {}
},
children
}
);
};
export {
StepContext,
StepperContext,
StepperContextProvider
};