@@ -4,16 +4,18 @@ import { css } from '@patternfly/react-styles';
44import styles from '@patternfly/react-styles/css/components/Wizard/wizard' ;
55
66import {
7- DefaultWizardFooterProps ,
8- DefaultWizardNavProps ,
97 isWizardParentStep ,
108 WizardNavStepFunction ,
11- CustomWizardNavFunction
9+ CustomWizardNavFunction ,
10+ WizardControlStep ,
11+ isCustomWizardNav ,
12+ DefaultWizardNavProps
1213} from './types' ;
1314import { buildSteps , normalizeNavStep } from './utils' ;
1415import { useWizardContext , WizardContextProvider } from './WizardContext' ;
1516import { WizardStepProps } from './WizardStep' ;
1617import { WizardToggle } from './WizardToggle' ;
18+ import { WizardFooterProps } from './WizardFooter' ;
1719
1820/**
1921 * Wrapper for all steps and hosts state, including navigation helpers, within context.
@@ -26,7 +28,7 @@ export interface WizardProps extends React.HTMLProps<HTMLDivElement> {
2628 /** Wizard header */
2729 header ?: React . ReactNode ;
2830 /** Wizard footer */
29- footer ?: DefaultWizardFooterProps | React . ReactElement ;
31+ footer ?: Partial < Omit < WizardFooterProps , 'hideBackButton' | 'hideCancelButton' > > | React . ReactElement ;
3032 /** Default wizard nav props or a custom WizardNav (with callback) */
3133 nav ?: DefaultWizardNavProps | CustomWizardNavFunction ;
3234 /** The initial index the wizard is to start on (1 or higher). Defaults to 1. */
@@ -54,83 +56,93 @@ export interface WizardProps extends React.HTMLProps<HTMLDivElement> {
5456export const Wizard = ( props : WizardProps ) => {
5557 const { startIndex = 1 , children, footer, onNavByIndex, onNext, onBack, onSave, onClose, ...internalProps } = props ;
5658 const [ currentStepIndex , setCurrentStepIndex ] = React . useState ( startIndex ) ;
57- const steps = buildSteps ( children ) ;
59+ const initialSteps = buildSteps ( children ) ;
60+ const forceStepVisit = ! isCustomWizardNav ( internalProps . nav ) && internalProps . nav ?. forceStepVisit ;
5861
59- const goToStepByIndex = ( index : number ) => {
60- const lastStepIndex = steps . length ;
62+ const goToNextStep = ( steps : WizardControlStep [ ] = initialSteps ) => {
63+ const newStepIndex =
64+ steps . findIndex ( ( step , index ) => index + 1 > currentStepIndex && ! step . isHidden && ! isWizardParentStep ( step ) ) + 1 ;
6165
62- if ( index < 1 ) {
63- index = 1 ;
64- } else if ( index > lastStepIndex ) {
65- index = lastStepIndex ;
66+ if ( currentStepIndex >= steps . length || ! newStepIndex ) {
67+ return onSave ? onSave ( ) : onClose ?.( ) ;
6668 }
6769
68- const currStep = steps [ index - 1 ] ;
70+ const currStep = isWizardParentStep ( steps [ currentStepIndex ] )
71+ ? steps [ currentStepIndex + 1 ]
72+ : steps [ currentStepIndex ] ;
6973 const prevStep = steps [ currentStepIndex - 1 ] ;
70- setCurrentStepIndex ( index ) ;
7174
72- return onNavByIndex ?.( normalizeNavStep ( currStep ) , normalizeNavStep ( prevStep ) ) ;
75+ setCurrentStepIndex ( newStepIndex ) ;
76+
77+ return onNext ?.( normalizeNavStep ( currStep , steps ) , normalizeNavStep ( prevStep , steps ) ) ;
7378 } ;
7479
75- const goToNextStep = ( ) => {
76- // Save when on the last step, otherwise close
77- if ( currentStepIndex >= steps . length ) {
78- if ( onSave ) {
79- return onSave ( ) ;
80- }
80+ const goToPrevStep = ( steps : WizardControlStep [ ] = initialSteps ) => {
81+ const newStepIndex =
82+ [ ...steps ]
83+ . reverse ( )
84+ . findIndex (
85+ ( step : WizardControlStep , index : number ) =>
86+ index + 1 < currentStepIndex && ! step . isHidden && ! isWizardParentStep ( step )
87+ ) + 1 ;
88+ const currStep = isWizardParentStep ( steps [ currentStepIndex - 2 ] )
89+ ? steps [ currentStepIndex - 3 ]
90+ : steps [ currentStepIndex - 2 ] ;
91+ const prevStep = steps [ currentStepIndex - 1 ] ;
8192
82- return onClose ?.( ) ;
83- }
93+ setCurrentStepIndex ( newStepIndex ) ;
8494
85- let currStep = steps [ currentStepIndex ] ;
86- let newStepIndex = currentStepIndex + 1 ;
87- const prevStep = steps [ currentStepIndex - 1 ] ;
95+ return onBack ?.( normalizeNavStep ( currStep , steps ) , normalizeNavStep ( prevStep , steps ) ) ;
96+ } ;
97+
98+ const goToStepByIndex = ( steps : WizardControlStep [ ] = initialSteps , index : number ) => {
99+ const lastStepIndex = steps . length + 1 ;
88100
89- // Skip parent step and focus on the first sub-step if they exist
90- if ( isWizardParentStep ( currStep ) ) {
91- newStepIndex += 1 ;
92- currStep = steps [ currentStepIndex + 1 ] ;
101+ // Handle index when out of bounds or hidden
102+ if ( index < 1 ) {
103+ index = 1 ;
104+ } else if ( index > lastStepIndex ) {
105+ index = lastStepIndex ;
106+ } else if ( steps [ index - 1 ] . isHidden ) {
107+ // eslint-disable-next-line no-console
108+ console . error ( 'Wizard: Unable to navigate to hidden step.' ) ;
93109 }
94110
95- setCurrentStepIndex ( newStepIndex ) ;
96- return onNext ?.( normalizeNavStep ( currStep ) , normalizeNavStep ( prevStep ) ) ;
111+ const currStep = steps [ index - 1 ] ;
112+ const prevStep = steps [ currentStepIndex - 1 ] ;
113+ setCurrentStepIndex ( index ) ;
114+
115+ return onNavByIndex ?.( normalizeNavStep ( currStep , steps ) , normalizeNavStep ( prevStep , steps ) ) ;
97116 } ;
98117
99- const goToPrevStep = ( ) => {
100- if ( steps . length < currentStepIndex ) {
101- // Previous step was removed, just update the currentStep state
102- setCurrentStepIndex ( steps . length ) ;
118+ const goToStepById = ( steps : WizardControlStep [ ] = initialSteps , id : number | string ) => {
119+ const stepIndex = steps . findIndex ( step => step . id === id ) + 1 ;
120+
121+ if ( stepIndex > 0 && stepIndex < steps . length + 1 && ! steps [ stepIndex ] . isHidden ) {
122+ setCurrentStepIndex ( stepIndex ) ;
103123 } else {
104- let currStep = steps [ currentStepIndex - 2 ] ;
105- let newStepIndex = currentStepIndex - 1 ;
106- const prevStep = steps [ currentStepIndex - 1 ] ;
107-
108- // // Skip parent step and focus on the step prior
109- if ( isWizardParentStep ( currStep ) ) {
110- newStepIndex -= 1 ;
111- currStep = steps [ currentStepIndex - 3 ] ;
112- }
113-
114- setCurrentStepIndex ( newStepIndex ) ;
115- return onBack ?.( normalizeNavStep ( currStep ) , normalizeNavStep ( prevStep ) ) ;
124+ // eslint-disable-next-line no-console
125+ console . error ( `Wizard: Unable to navigate to step with id: ${ id } .` ) ;
116126 }
117127 } ;
118128
119- const goToStepById = ( id : number | string ) => {
120- const stepIndex = steps . findIndex ( step => step . id === id ) + 1 ;
121- stepIndex > 0 && setCurrentStepIndex ( stepIndex ) ;
122- } ;
129+ const goToStepByName = ( steps : WizardControlStep [ ] = initialSteps , name : string ) => {
130+ const stepIndex = initialSteps . findIndex ( step => step . name === name ) + 1 ;
123131
124- const goToStepByName = ( name : string ) => {
125- const stepIndex = steps . findIndex ( step => step . name === name ) + 1 ;
126- stepIndex > 0 && setCurrentStepIndex ( stepIndex ) ;
132+ if ( stepIndex > 0 && stepIndex < steps . length + 1 && ! steps [ stepIndex ] . isHidden ) {
133+ setCurrentStepIndex ( stepIndex ) ;
134+ } else {
135+ // eslint-disable-next-line no-console
136+ console . error ( `Wizard: Unable to navigate to step with name: ${ name } .` ) ;
137+ }
127138 } ;
128139
129140 return (
130141 < WizardContextProvider
131- steps = { steps }
142+ steps = { initialSteps }
132143 currentStepIndex = { currentStepIndex }
133144 footer = { footer }
145+ forceStepVisit = { forceStepVisit }
134146 onNext = { goToNextStep }
135147 onBack = { goToPrevStep }
136148 onClose = { onClose }
@@ -143,9 +155,8 @@ export const Wizard = (props: WizardProps) => {
143155 ) ;
144156} ;
145157
146- // eslint-disable-next-line patternfly-react/no-anonymous-functions
147158const WizardInternal = ( { height, width, className, header, nav, unmountInactiveSteps, ...divProps } : WizardProps ) => {
148- const { activeStep , steps, footer, goToStepByIndex } = useWizardContext ( ) ;
159+ const { currentStep , steps, footer, goToStepByIndex } = useWizardContext ( ) ;
149160
150161 return (
151162 < div
@@ -159,7 +170,7 @@ const WizardInternal = ({ height, width, className, header, nav, unmountInactive
159170 { header }
160171 < WizardToggle
161172 steps = { steps }
162- activeStep = { activeStep }
173+ currentStep = { currentStep }
163174 footer = { footer }
164175 nav = { nav }
165176 goToStepByIndex = { goToStepByIndex }
0 commit comments