@@ -78,93 +78,122 @@ export const VisualTour = ({
7878 const hasPreviousStep = currentStepIndex > 0 ;
7979 // Configure optional highlighting
8080 let elementToHighlight : HTMLElement | null = null ;
81- if ( step . highlightElementQuery ) {
82- const queries : string [ ] =
83- typeof step . highlightElementQuery === "string"
84- ? [ step . highlightElementQuery ]
85- : step . highlightElementQuery ;
86- queries . forEach ( ( query ) => {
87- if ( elementToHighlight == null ) {
88- elementToHighlight = document . querySelector ( query ) ;
89- }
90- } ) ;
91- }
92- if ( elementToHighlight ) {
93- // Typescript for some reason incorrectly infers the type of elementToHighlight as never
94- ( elementToHighlight as HTMLElement ) . classList . add ( highlightElementClass ) ;
95- ( elementToHighlight as HTMLElement ) . scrollIntoView ( {
96- behavior : "smooth" ,
97- block : "center" ,
98- } ) ;
99- }
100- const stepDisplay = (
101- < Badge tagProps = { { emphasis : "weaker" } } size = "large" >
102- { ` ${ currentStepIndex + 1 } /${ steps . length } ` }
103- </ Badge >
104- ) ;
105- const closeButton = < IconButton name = "navigation-close" text = { closeLabel } onClick = { onClose } /> ;
106- const titleOptions = (
107- < >
108- { stepDisplay }
109- { closeButton }
110- </ >
111- ) ;
112- const actionButtons = [
113- hasNextStep ? (
114- < Button
115- key = { "next" }
116- variant = "outlined"
117- intent = { "primary" }
118- onClick = { ( ) => {
119- setCurrentStepIndex ( currentStepIndex + 1 ) ;
120- } }
121- rightIcon = { "navigation-next" }
122- >
123- { nextLabel } : { steps [ currentStepIndex + 1 ] . title }
124- </ Button >
125- ) : (
126- < Button
127- key = { "close" }
128- text = { closeLabel }
129- onClick = { onClose }
130- variant = "outlined"
131- intent = { "primary" }
132- rightIcon = { "navigation-close" }
133- />
134- ) ,
135- hasPreviousStep ? (
136- < CardActionsAux >
81+ let lastObserver : MutationObserver | null = null ;
82+ const setStepComponent = ( ) => {
83+ const stepDisplay = (
84+ < Badge tagProps = { { emphasis : "weaker" } } size = "large" >
85+ { ` ${ currentStepIndex + 1 } /${ steps . length } ` }
86+ </ Badge >
87+ ) ;
88+ const closeButton = < IconButton name = "navigation-close" text = { closeLabel } onClick = { onClose } /> ;
89+ const titleOptions = (
90+ < >
91+ { stepDisplay }
92+ { closeButton }
93+ </ >
94+ ) ;
95+ const actionButtons = [
96+ hasNextStep ? (
13797 < Button
138- key = { "prev " }
98+ key = { "next " }
13999 variant = "outlined"
100+ intent = { "primary" }
140101 onClick = { ( ) => {
141- setCurrentStepIndex ( currentStepIndex - 1 ) ;
102+ setCurrentStepIndex ( currentStepIndex + 1 ) ;
142103 } }
143- icon = { "navigation-previous " }
104+ rightIcon = { "navigation-next " }
144105 >
145- { prevLabel }
106+ { nextLabel } : { steps [ currentStepIndex + 1 ] . title }
146107 </ Button >
147- </ CardActionsAux >
148- ) : null ,
149- ] ;
150- // TODO: What to do if an element should have been highlighted, but none was found?
151- if ( elementToHighlight ) {
152- setCurrentStepComponent (
153- < StepPopover
154- highlightedElement = { elementToHighlight }
155- titleOption = { titleOptions }
156- actionButtons = { actionButtons }
157- step = { step }
158- />
159- ) ;
160- } else {
161- setCurrentStepComponent (
162- < StepModal titleOption = { titleOptions } actionButtons = { actionButtons } step = { step } onClose = { onClose } />
163- ) ;
108+ ) : (
109+ < Button
110+ key = { "close" }
111+ text = { closeLabel }
112+ onClick = { onClose }
113+ variant = "outlined"
114+ intent = { "primary" }
115+ rightIcon = { "navigation-close" }
116+ />
117+ ) ,
118+ hasPreviousStep ? (
119+ < CardActionsAux >
120+ < Button
121+ key = { "prev" }
122+ variant = "outlined"
123+ onClick = { ( ) => {
124+ setCurrentStepIndex ( currentStepIndex - 1 ) ;
125+ } }
126+ icon = { "navigation-previous" }
127+ >
128+ { prevLabel }
129+ </ Button >
130+ </ CardActionsAux >
131+ ) : null ,
132+ ] ;
133+ // TODO: What to do if an element should have been highlighted, but none was found?
134+ if ( elementToHighlight ) {
135+ setCurrentStepComponent (
136+ < StepPopover
137+ highlightedElement = { elementToHighlight }
138+ titleOption = { titleOptions }
139+ actionButtons = { actionButtons }
140+ step = { step }
141+ />
142+ ) ;
143+ } else {
144+ setCurrentStepComponent (
145+ < StepModal titleOption = { titleOptions } actionButtons = { actionButtons } step = { step } onClose = { onClose } />
146+ ) ;
147+ }
148+ }
149+ const addElementHighlighting = ( ) => {
150+ if ( step . highlightElementQuery ) {
151+ const queries : string [ ] =
152+ typeof step . highlightElementQuery === "string"
153+ ? [ step . highlightElementQuery ]
154+ : step . highlightElementQuery ;
155+ queries . forEach ( ( query ) => {
156+ if ( elementToHighlight == null ) {
157+ elementToHighlight = document . querySelector ( query ) ;
158+ }
159+ } ) ;
160+ } else {
161+ elementToHighlight = null
162+ }
163+ if ( elementToHighlight ) {
164+ // Typescript for some reason incorrectly infers the type of elementToHighlight as never
165+ ( elementToHighlight as HTMLElement ) . classList . add ( highlightElementClass ) ;
166+ ( elementToHighlight as HTMLElement ) . scrollIntoView ( {
167+ behavior : "smooth" ,
168+ block : "center" ,
169+ } ) ;
170+ if ( lastObserver ) {
171+ lastObserver . disconnect ( )
172+ }
173+ lastObserver = new MutationObserver ( function ( ) {
174+ // Re-new element highlighting
175+ if ( step . highlightElementQuery ) {
176+ if ( ! document . body . contains ( elementToHighlight ) ) {
177+ // Element has been removed or replaced
178+ elementToHighlight = null ;
179+ addElementHighlighting ( ) ;
180+ } else if ( ! elementToHighlight ?. classList . contains ( highlightElementClass ) ) {
181+ // Only the classes have been removed
182+ elementToHighlight ?. classList . add ( highlightElementClass ) ;
183+ }
184+ }
185+ } ) ;
186+ lastObserver . observe ( document . body , { childList : true , subtree : true } ) ;
187+ }
188+ setStepComponent ( )
164189 }
190+ addElementHighlighting ( )
165191 return ( ) => {
166192 // Remove previous element highlight
167193 document . querySelector ( `.${ highlightElementClass } ` ) ?. classList . remove ( highlightElementClass ) ;
194+ if ( lastObserver ) {
195+ lastObserver . disconnect ( )
196+ }
168197 } ;
169198 } , [ currentStepIndex ] ) ;
170199
0 commit comments