@@ -16,7 +16,9 @@ import {useSyncExternalStore} from 'use-sync-external-store/shim/index.js';
16
16
17
17
export interface ToastStateProps {
18
18
/** The maximum number of toasts to display at a time. */
19
- maxVisibleToasts ?: number
19
+ maxVisibleToasts ?: number ,
20
+ /** Function to wrap updates in (i.e. document.startViewTransition()). */
21
+ wrapUpdate ?: < R > ( fn : ( ) => R ) => R
20
22
}
21
23
22
24
export interface ToastOptions {
@@ -86,11 +88,21 @@ export class ToastQueue<T> {
86
88
private queue : QueuedToast < T > [ ] = [ ] ;
87
89
private subscriptions : Set < ( ) => void > = new Set ( ) ;
88
90
private maxVisibleToasts : number ;
91
+ private wrapUpdate ?: < R > ( fn : ( ) => R ) => R ;
89
92
/** The currently visible toasts. */
90
93
visibleToasts : QueuedToast < T > [ ] = [ ] ;
91
94
92
95
constructor ( options ?: ToastStateProps ) {
93
96
this . maxVisibleToasts = options ?. maxVisibleToasts ?? 1 ;
97
+ this . wrapUpdate = options ?. wrapUpdate ;
98
+ }
99
+
100
+ private runWithWrapUpdate < R > ( fn : ( ) => R ) : R {
101
+ if ( this . wrapUpdate ) {
102
+ return this . wrapUpdate ( fn ) ;
103
+ } else {
104
+ return fn ( ) ;
105
+ }
94
106
}
95
107
96
108
/** Subscribes to updates to the visible toasts. */
@@ -101,42 +113,46 @@ export class ToastQueue<T> {
101
113
102
114
/** Adds a new toast to the queue. */
103
115
add ( content : T , options : ToastOptions = { } ) {
104
- let toastKey = Math . random ( ) . toString ( 36 ) ;
105
- let toast : QueuedToast < T > = {
106
- ...options ,
107
- content,
108
- key : toastKey ,
109
- timer : options . timeout ? new Timer ( ( ) => this . close ( toastKey ) , options . timeout ) : undefined
110
- } ;
111
-
112
- let low = 0 ;
113
- let high = this . queue . length ;
114
- while ( low < high ) {
115
- let mid = Math . floor ( ( low + high ) / 2 ) ;
116
- if ( ( toast . priority || 0 ) > ( this . queue [ mid ] . priority || 0 ) ) {
117
- high = mid ;
118
- } else {
119
- low = mid + 1 ;
116
+ return this . runWithWrapUpdate ( ( ) => {
117
+ let toastKey = Math . random ( ) . toString ( 36 ) ;
118
+ let toast : QueuedToast < T > = {
119
+ ...options ,
120
+ content,
121
+ key : toastKey ,
122
+ timer : options . timeout ? new Timer ( ( ) => this . close ( toastKey ) , options . timeout ) : undefined
123
+ } ;
124
+
125
+ let low = 0 ;
126
+ let high = this . queue . length ;
127
+ while ( low < high ) {
128
+ let mid = Math . floor ( ( low + high ) / 2 ) ;
129
+ if ( ( toast . priority || 0 ) > ( this . queue [ mid ] . priority || 0 ) ) {
130
+ high = mid ;
131
+ } else {
132
+ low = mid + 1 ;
133
+ }
120
134
}
121
- }
122
135
123
- this . queue . splice ( low , 0 , toast ) ;
136
+ this . queue . splice ( low , 0 , toast ) ;
124
137
125
- this . updateVisibleToasts ( ) ;
126
- return toastKey ;
138
+ this . updateVisibleToasts ( ) ;
139
+ return toastKey ;
140
+ } ) ;
127
141
}
128
142
129
143
/**
130
144
* Closes a toast.
131
145
*/
132
146
close ( key : string ) {
133
- let index = this . queue . findIndex ( t => t . key === key ) ;
134
- if ( index >= 0 ) {
135
- this . queue [ index ] . onClose ?.( ) ;
136
- this . queue . splice ( index , 1 ) ;
137
- }
147
+ return this . runWithWrapUpdate ( ( ) => {
148
+ let index = this . queue . findIndex ( t => t . key === key ) ;
149
+ if ( index >= 0 ) {
150
+ this . queue [ index ] . onClose ?.( ) ;
151
+ this . queue . splice ( index , 1 ) ;
152
+ }
138
153
139
- this . updateVisibleToasts ( ) ;
154
+ this . updateVisibleToasts ( ) ;
155
+ } ) ;
140
156
}
141
157
142
158
private updateVisibleToasts ( ) {
0 commit comments