@patternfly/react-core
Version:
This library provides a set of common React components for use with the PatternFly reference implementation.
82 lines (72 loc) • 2.73 kB
text/typescript
import { Children, isValidElement } from 'react';
import { isWizardParentStep, isWizardSubStep, WizardStepType } from './types';
import { WizardStep, WizardStepProps } from './WizardStep';
/**
* Accumulate list of step & sub-step props pulled from child components
* @param children
* @returns WizardStepType[]
*/
export const buildSteps = (children: React.ReactNode) =>
Children.toArray(children).reduce((acc: WizardStepType[], child: React.ReactNode, index: number) => {
if (isWizardStep(child)) {
const { props: childProps } = child;
const { steps: childStepComponents, id } = childProps;
const stepIndex = acc.length + 1;
const subSteps: WizardStepType[] = [];
acc.push(
{
index: stepIndex,
component: child,
...(index === 0 && !childStepComponents?.length && { isVisited: true }),
...(childStepComponents && {
subStepIds: childStepComponents?.map((childStepComponent, subStepIndex) => {
subSteps.push({
index: stepIndex + subStepIndex + 1,
component: childStepComponent,
parentId: id,
...(index === 0 && subStepIndex === 0 && { isVisited: true }),
...normalizeStepProps(childStepComponent.props)
});
return childStepComponent.props.id;
})
}),
...normalizeStepProps(childProps)
},
...subSteps
);
} else {
throw new Error('Wizard only accepts children of type WizardStep.');
}
return acc;
}, []);
export function isWizardStep(
child: any | React.ReactElement<WizardStepProps>
): child is React.ReactElement<WizardStepProps> {
return isValidElement(child) && (child as React.ReactElement<WizardStepProps>).type === WizardStep;
}
// Omit "children" and "steps" when building steps for the Wizard's context
export const normalizeStepProps = ({
children: _children,
steps: _steps,
...controlStep
}: WizardStepProps): Omit<WizardStepType, 'index'> => controlStep;
/**
* Determines whether a step is navigable based on disabled/hidden properties
* @param steps All steps
* @param step
* @returns boolean
*/
export const isStepEnabled = (steps: WizardStepType[], step: WizardStepType): boolean => {
// Skip over parent steps since they are merely containers of sub-steps
if (!isWizardParentStep(step) && !step.isHidden && !step.isDisabled) {
if (isWizardSubStep(step)) {
const parentStep = steps.find((otherStep) => otherStep.id === step.parentId);
if (!parentStep.isHidden && !parentStep.isDisabled) {
return true;
}
} else {
return true;
}
}
return false;
};