@@ -17,6 +17,8 @@ export function useModalManager(): ModalManager {
1717 const beforeCloseCallbacks = useRef <
1818 Map < string , ( value ?: unknown ) => boolean >
1919 > ( new Map ( ) ) ;
20+ const stackRef = useRef ( stack ) ;
21+ stackRef . current = stack ;
2022
2123 const generateId = useCallback ( ( ) => {
2224 return `modal-${ nextId . current ++ } ` ;
@@ -100,31 +102,47 @@ export function useModalManager(): ModalManager {
100102 return callback ? callback ( value ) : true ;
101103 } , [ ] ) ;
102104
103- const closeById = useCallback (
104- ( id : string , options ?: CloseOptions ) : boolean => {
105- let wasClosed = false ;
106-
107- setStack ( ( prev ) => {
108- const modal = prev . find ( ( m ) => m . id === id ) ;
109- if ( ! modal ) {
110- console . error ( `Modal with ID "${ id } " not found, and cant be closed` ) ;
111- return prev ;
112- }
113-
114- if ( ! options ?. force && ! canClose ( id ) ) {
115- return prev ;
105+ const findModalById = useCallback (
106+ (
107+ modals : InternalModalInstance [ ] ,
108+ id : string
109+ ) : InternalModalInstance | null => {
110+ for ( const m of modals ) {
111+ if ( m . id === id ) return m ;
112+ if ( m . nested ) {
113+ const found = findModalById ( [ m . nested ] , id ) ;
114+ if ( found ) return found ;
116115 }
116+ }
117+ return null ;
118+ } ,
119+ [ ]
120+ ) ;
117121
118- wasClosed = true ;
119- beforeCloseCallbacks . current . delete ( id ) ;
120- const newStack = prev . filter ( ( m ) => m . id !== id ) ;
121- setAction ( "pop" ) ;
122- return updateModalStack ( newStack ) ;
123- } ) ;
122+ // Close deepest nested first so promises resolve bottom-up
123+ const closeChain = useCallback (
124+ ( m : InternalModalInstance , options ?: CloseOptions ) : boolean => {
125+ let didClose = false ;
126+ if ( m . nested ) didClose = closeChain ( m . nested , options ) || didClose ;
127+ if ( options ?. force || canClose ( m . id ) ) {
128+ m . close ( undefined , options ) ;
129+ didClose = true ;
130+ }
131+ return didClose ;
132+ } ,
133+ [ canClose ]
134+ ) ;
124135
125- return wasClosed ;
136+ const closeById = useCallback (
137+ ( id : string , options ?: CloseOptions ) : boolean => {
138+ const modal = findModalById ( stackRef . current , id ) ;
139+ if ( ! modal ) {
140+ console . error ( `Modal with ID "${ id } " not found, and cant be closed` ) ;
141+ return false ;
142+ }
143+ return closeChain ( modal , options ) ;
126144 } ,
127- [ updateModalStack , canClose ]
145+ [ findModalById , closeChain ]
128146 ) ;
129147
130148 const closeCurrent = useCallback (
@@ -226,66 +244,28 @@ export function useModalManager(): ModalManager {
226244 `amount must be a number greater than 0. Received ${ n } `
227245 ) ;
228246 }
247+ const current = stackRef . current ;
229248 let didClose = false ;
230-
231- setStack ( ( prev ) => {
232- let closedCount = 0 ;
233- let newStack = [ ...prev ] ;
234-
235- for ( let i = prev . length - 1 ; i >= 0 && closedCount < n ; i -- ) {
236- const modal = prev [ i ] ;
237- if ( options ?. force || canClose ( modal . id ) ) {
238- beforeCloseCallbacks . current . delete ( modal . id ) ;
239- newStack = newStack . filter ( ( m ) => m . id !== modal . id ) ;
240- closedCount += 1 ;
241- }
242- }
243-
244- if ( closedCount > 0 ) {
245- didClose = true ;
246- setAction ( "pop" ) ;
247- }
248-
249- return updateModalStack ( newStack ) ;
250- } ) ;
251-
249+ for ( let i = current . length - 1 , count = 0 ; i >= 0 && count < n ; i -- , count ++ ) {
250+ if ( closeChain ( current [ i ] , options ) ) didClose = true ;
251+ }
252252 return didClose ;
253253 } ,
254- [ updateModalStack , canClose ]
254+ [ closeChain ]
255255 ) ;
256256
257- const closeAll = useCallback ( ( options ?: CloseOptions ) : boolean => {
258- let wasAnyClosed = false ;
259-
260- setStack ( ( prev ) => {
261- if ( prev . length === 0 ) return prev ;
262-
263- if ( options ?. force ) {
264- wasAnyClosed = true ;
265- setAction ( "pop" ) ;
266- beforeCloseCallbacks . current . clear ( ) ;
267- return [ ] ;
268- }
269-
270- const remainingModals : InternalModalInstance [ ] = [ ] ;
271- for ( const modal of prev ) {
272- if ( canClose ( modal . id ) ) {
273- wasAnyClosed = true ;
274- beforeCloseCallbacks . current . delete ( modal . id ) ;
275- } else {
276- remainingModals . push ( modal ) ;
277- }
278- }
279-
280- if ( wasAnyClosed ) {
281- setAction ( "pop" ) ;
257+ const closeAll = useCallback (
258+ ( options ?: CloseOptions ) : boolean => {
259+ const current = stackRef . current ;
260+ if ( current . length === 0 ) return false ;
261+ let didClose = false ;
262+ for ( const m of current ) {
263+ if ( closeChain ( m , options ) ) didClose = true ;
282264 }
283-
284- return updateModalStack ( remainingModals ) ;
285- } ) ;
286-
287- return wasAnyClosed ;
288- } , [ canClose , updateModalStack ] ) ;
265+ return didClose ;
266+ } ,
267+ [ closeChain ]
268+ ) ;
289269
290270 const openNested = useCallback (
291271 < T = unknown , R = unknown > (
0 commit comments