@@ -163,23 +163,22 @@ class OverlayStack {
163163 * @param event {PointerEvent}
164164 */
165165 handlePointerdown = ( event : Event ) : void => {
166+ if ( ! this . stack . length ) return ;
167+
166168 const pointerPath = event . composedPath ( ) ;
167169
168170 // For page overlays only: block clicks outside (no light dismiss)
169171 // Modal overlays have light dismiss handled by handlePointerup
170- if ( this . stack . length ) {
171- const pageOverlays = this . stack . filter (
172- ( o ) => o . open && o . type === 'page'
173- ) ;
174- if (
175- pageOverlays . length > 0 &&
176- ! this . isEventInsideModal ( pointerPath , pageOverlays )
177- ) {
178- event . preventDefault ( ) ;
179- event . stopPropagation ( ) ;
180- event . stopImmediatePropagation ( ) ;
181- return ;
182- }
172+ const pageOverlays = this . stack . filter (
173+ ( o ) => o . open && o . type === 'page'
174+ ) ;
175+ if (
176+ pageOverlays . length > 0 &&
177+ ! this . isEventInsideModal ( pointerPath , pageOverlays )
178+ ) {
179+ event . preventDefault ( ) ;
180+ event . stopImmediatePropagation ( ) ;
181+ return ;
183182 }
184183
185184 this . pointerdownPath = pointerPath ;
@@ -210,7 +209,6 @@ class OverlayStack {
210209 // If click is outside all page overlays, prevent it from reaching the target
211210 // This replicates the behavior that showModal() provided automatically
212211 event . stopImmediatePropagation ( ) ;
213- event . stopPropagation ( ) ;
214212 event . preventDefault ( ) ;
215213 }
216214 } ;
@@ -232,19 +230,30 @@ class OverlayStack {
232230 this . lastOverlay = undefined ;
233231
234232 const lastIndex = this . stack . length - 1 ;
235- const clickedBackdrop = composedPath . some (
236- ( el ) =>
237- el instanceof HTMLElement &&
238- el . classList . contains ( 'modal-backdrop' )
233+
234+ // Avoid the cost of event.composedPath() unless we actually have a modal/page
235+ // overlay open. composedPath() walks and allocates the full event path and can
236+ // be surprisingly expensive in hot paths.
237+ const hasModalOrPageOverlay = this . stack . some (
238+ ( overlay ) =>
239+ overlay . open &&
240+ ( overlay . type === 'modal' || overlay . type === 'page' )
239241 ) ;
240- if ( clickedBackdrop ) {
241- const topOverlay = this . stack [ this . stack . length - 1 ] ;
242- // Only modal overlays close on backdrop click.
243- // Page overlays are blocking and should not be light-dismissable.
244- if ( topOverlay ?. type === 'modal' ) {
245- this . closeOverlay ( topOverlay ) ;
242+ if ( hasModalOrPageOverlay ) {
243+ const clickedBackdrop = composedPath . some (
244+ ( el ) =>
245+ el instanceof HTMLDivElement &&
246+ el . classList . contains ( 'modal-backdrop' )
247+ ) ;
248+ if ( clickedBackdrop ) {
249+ const topOverlay = this . stack [ this . stack . length - 1 ] ;
250+ // Only modal overlays close on backdrop click.
251+ // Page overlays are blocking and should not be light-dismissable.
252+ if ( topOverlay ?. type === 'modal' ) {
253+ this . closeOverlay ( topOverlay ) ;
254+ }
255+ return ;
246256 }
247- return ;
248257 }
249258 const nonAncestorOverlays = this . stack . filter ( ( overlay , i ) => {
250259 const inStack = composedPath . find (
0 commit comments