@@ -18,11 +18,6 @@ import type {
1818 ConfigureSSOWizardStepProps ,
1919} from './types' ;
2020
21- /**
22- * Marker component for a single step in `<ConfigureSSOWizard>`. The
23- * parent wizard reads its props directly off the JSX element; the
24- * component itself never renders independently
25- */
2621const Step = ( _ : ConfigureSSOWizardStepProps ) : JSX . Element | null => null ;
2722Step . displayName = 'ConfigureSSOWizard.Step' ;
2823
@@ -32,23 +27,28 @@ interface RootProps {
3227
3328/**
3429 * Walks the wizard's children and returns the descriptors for every
35- * `<ConfigureSSOWizard.Step>` element. Anything else (`false` from
36- * `&&`, plain text, fragments, etc.) is silently ignored, so
37- * conditional rendering in JSX naturally drives "skipping"
30+ * `<ConfigureSSOWizard.Step>` element
3831 */
3932function extractSteps ( children : React . ReactNode ) : ConfigureSSOWizardActiveStep [ ] {
4033 const steps : ConfigureSSOWizardActiveStep [ ] = [ ] ;
4134
4235 React . Children . forEach ( children , child => {
43- if ( ! React . isValidElement ( child ) ) return ;
36+ if ( ! React . isValidElement ( child ) ) {
37+ return ;
38+ }
39+
4440 // Tolerate fragments at the top level (e.g. when users factor a
4541 // group of steps into a helper component that returns one)
4642 if ( child . type === React . Fragment ) {
4743 const fragmentChildren = ( child . props as { children ?: React . ReactNode } ) . children ;
4844 steps . push ( ...extractSteps ( fragmentChildren ) ) ;
4945 return ;
5046 }
51- if ( child . type !== Step ) return ;
47+
48+ if ( child . type !== Step ) {
49+ return ;
50+ }
51+
5252 const props = child . props as ConfigureSSOWizardStepProps ;
5353 steps . push ( {
5454 id : props . id ,
@@ -103,11 +103,14 @@ const RootInner = ({ parentWizard, isNested, children }: RootInnerProps): JSX.El
103103
104104 const activeSteps = React . useMemo ( ( ) => extractSteps ( children ) , [ children ] ) ;
105105
106- // Match the URL against non-first steps (most-specific first); the
106+ // Match the URL against non-first steps (most-specific first), the
107107 // first step is mounted as the index route and is always the
108108 // fallback when nothing else matches
109109 const currentStep = React . useMemo < ConfigureSSOWizardActiveStep | undefined > ( ( ) => {
110- if ( activeSteps . length === 0 ) return undefined ;
110+ if ( activeSteps . length === 0 ) {
111+ return undefined ;
112+ }
113+
111114 return (
112115 activeSteps
113116 . slice ( 1 )
@@ -130,22 +133,30 @@ const RootInner = ({ parentWizard, isNested, children }: RootInnerProps): JSX.El
130133 ) ;
131134
132135 const goNext = React . useCallback ( ( ) => {
133- if ( ! currentStep ) return ;
134- const idx = activeSteps . findIndex ( s => s . id === currentStep . id ) ;
135- const next = activeSteps [ idx + 1 ] ;
136- if ( next ) return navigateTo ( next ) ;
137- // End of *this* wizard's siblings → cascade to the parent so
138- // the outer wizard advances past us to the next outer step
136+ if ( ! currentStep ) {
137+ return ;
138+ }
139+
140+ const index = activeSteps . findIndex ( s => s . id === currentStep . id ) ;
141+ const next = activeSteps [ index + 1 ] ;
142+ if ( next ) {
143+ return navigateTo ( next ) ;
144+ }
145+
139146 return parentWizard ?. goNext ( ) ;
140147 } , [ activeSteps , currentStep , navigateTo , parentWizard ] ) ;
141148
142149 const goPrev = React . useCallback ( ( ) => {
143- if ( ! currentStep ) return ;
144- const idx = activeSteps . findIndex ( s => s . id === currentStep . id ) ;
145- const prev = activeSteps [ idx - 1 ] ;
146- if ( prev ) return navigateTo ( prev ) ;
147- // At the first sibling — defer to the parent so the user can
148- // step back into the previous outer step's last position
150+ if ( ! currentStep ) {
151+ return ;
152+ }
153+
154+ const index = activeSteps . findIndex ( s => s . id === currentStep . id ) ;
155+ const prev = activeSteps [ index - 1 ] ;
156+ if ( prev ) {
157+ return navigateTo ( prev ) ;
158+ }
159+
149160 return parentWizard ?. goPrev ( ) ;
150161 } , [ activeSteps , currentStep , navigateTo , parentWizard ] ) ;
151162
@@ -155,21 +166,19 @@ const RootInner = ({ parentWizard, isNested, children }: RootInnerProps): JSX.El
155166 ) ;
156167
157168 const value = React . useMemo < ConfigureSSOWizardContextValue > ( ( ) => {
158- const idx = currentStep ? activeSteps . findIndex ( s => s . id === currentStep . id ) : - 1 ;
169+ const index = currentStep ? activeSteps . findIndex ( s => s . id === currentStep . id ) : - 1 ;
159170 return {
160171 activeSteps,
161172 currentStep,
162- currentIndex : idx ,
173+ currentIndex : index ,
163174 totalSteps : activeSteps . length ,
164- // First/last only count as edges when there's nothing past us
165- // to fall back on (otherwise the parent wizard absorbs the move)
166- isFirstStep : idx <= 0 && ! parentWizard ,
167- isLastStep : idx === activeSteps . length - 1 && ! parentWizard ,
168175 isLoading,
169176 goNext,
170177 goPrev,
171178 goToStep,
172179 isNested,
180+ isFirstStep : index <= 0 && ! parentWizard ,
181+ isLastStep : index === activeSteps . length - 1 && ! parentWizard ,
173182 } ;
174183 } , [ activeSteps , currentStep , isLoading , goNext , goPrev , goToStep , isNested , parentWizard ] ) ;
175184
@@ -181,13 +190,10 @@ const RootInner = ({ parentWizard, isNested, children }: RootInnerProps): JSX.El
181190 const body = < Body activeSteps = { activeSteps } /> ;
182191
183192 if ( isNested ) {
184- // Nested wizards plug into the parent's chrome; they only own
185- // the inner routing for their step's body
186193 return < ConfigureSSOWizardContext . Provider value = { value } > { body } </ ConfigureSSOWizardContext . Provider > ;
187194 }
188195
189- // Outermost wizard owns the full layout: breadcrumb on top, the
190- // step body in the middle, the shared footer at the bottom
196+ // Outermost wizard owns the full layout
191197 return (
192198 < ConfigureSSOWizardContext . Provider value = { value } >
193199 < Header />
@@ -198,15 +204,15 @@ const RootInner = ({ parentWizard, isNested, children }: RootInnerProps): JSX.El
198204} ;
199205
200206/**
201- * Renders the active step's body (or a spinner while async deps are
202- * loading). Each step is mounted at its `path`; the first step is the
203- * index/catch-all so the wizard's base URL renders something
207+ * Renders the active step's body
204208 */
205209const Body = ( { activeSteps } : { activeSteps : ConfigureSSOWizardActiveStep [ ] } ) : JSX . Element | null => {
206210 const { isLoading, isNested } = useConfigureSSOWizard ( ) ;
207211
208212 if ( isLoading ) {
209- if ( isNested ) return null ;
213+ if ( isNested ) {
214+ return null ;
215+ }
210216 return (
211217 < Flex
212218 align = 'center'
@@ -358,8 +364,7 @@ const SkeletonBreadcrumbStep = (): JSX.Element => (
358364/**
359365 * Compact "Step X / Y" badge that mirrors the *nearest* wizard's
360366 * progress. Renders nothing when the nearest wizard has only one
361- * step (i.e. there's nothing meaningful to count). Drop this inside
362- * an inner wizard's step layout to surface inner-step progress
367+ * step
363368 */
364369const StepIndicator = ( ) : JSX . Element | null => {
365370 const { totalSteps, currentIndex } = useConfigureSSOWizard ( ) ;
@@ -499,10 +504,10 @@ const Footer = (props: FooterProps): JSX.Element => {
499504 *
500505 * Steps are written as JSX children: render a `<ConfigureSSOWizard.Step>`
501506 * for each step and toggle visibility with regular conditional
502- * expressions (`{cond && <Step>...</Step>}`). Inner sub-steps are
503- * declared by nesting another `<ConfigureSSOWizard>` inside a step's
504- * body — the inner wizard's `goNext` cascades to the outer one when
505- * it runs out of inner steps
507+ * expressions (`{cond && <Step>...</Step>}`)
508+ *
509+ * Inner sub-steps are declared by nesting another `<ConfigureSSOWizard>` inside
510+ * a step's body
506511 */
507512export const ConfigureSSOWizard = Object . assign ( Root , {
508513 Step,
0 commit comments