11import {
22 forwardRef ,
33 useCallback ,
4+ useEffect ,
45 useImperativeHandle ,
56 useRef ,
67 useState ,
@@ -29,6 +30,7 @@ import type {
2930
3031import {
3132 Controller ,
33+ type ControllerProps ,
3234 type ControllerRef ,
3335} from "./_controller"
3436
@@ -45,50 +47,22 @@ export const DialogProvider = forwardRef<DialogProviderRef, DialogProviderProps>
4547 ) {
4648
4749 const
48- controllerRef =
49- useRef < ControllerRef > ( null ) ,
50-
51- dialogDataQueue =
52- useRef < DialogData > ( null ) ,
53-
54- [ mountController , setMountController ] =
55- useState ( false ) ,
56-
57- setControllerRef : React . RefCallback < ControllerRef > =
58- useCallback ( ref => {
59- controllerRef . current = ref
60-
61- if ( controllerRef . current && dialogDataQueue . current ) {
62- controllerRef . current . show ( { ...dialogDataQueue . current } )
63- dialogDataQueue . current = null
64- }
65- } , [ ] ) ,
50+ controllerWrapperRef =
51+ useRef < ControllerWrapperRef > ( null ) ,
6652
6753 show : DialogContext [ "show" ] =
6854 useCallback ( data => {
69- if ( ! controllerRef . current ) {
70- dialogDataQueue . current = { ...data }
71- setMountController ( true )
72- } else {
73- controllerRef . current ?. show ( data )
74- }
55+ controllerWrapperRef . current ?. show ( data )
7556 } , [ ] ) ,
7657
7758 dismiss : DialogContext [ "dismiss" ] =
7859 useCallback ( async ( ) => {
79- return controllerRef . current ?. dismiss ( )
60+ return controllerWrapperRef . current ?. dismiss ( )
8061 } , [ ] ) ,
8162
8263 dismissAll : DialogContext [ "dismissAll" ] =
8364 useCallback ( async ( ) => {
84- return controllerRef . current ?. dismissAll ( )
85- } , [ ] ) ,
86-
87- onEmpty =
88- useCallback ( ( ) => {
89- if ( ! dialogDataQueue . current ) {
90- setMountController ( false )
91- }
65+ return controllerWrapperRef . current ?. dismissAll ( )
9266 } , [ ] )
9367
9468 useImperativeHandle ( ref , ( ) => {
@@ -113,20 +87,101 @@ export const DialogProvider = forwardRef<DialogProviderRef, DialogProviderProps>
11387 >
11488 { children }
11589
116- { mountController && (
117- < InDialogContext . Provider value = { true } >
118- < Controller
119- ref = { setControllerRef }
120- animationConfig = { animationConfig as typeof DialogAnimationConfigs . CarbonReact }
121- modalProps = { modalProps }
122- overlayProps = { overlayProps }
123- overlayTouchDismiss = { overlayTouchDismiss }
124- onEmpty = { onEmpty }
125- />
126- </ InDialogContext . Provider >
127- ) }
90+ < ControllerWrapper
91+ ref = { controllerWrapperRef }
92+ animationConfig = { animationConfig as typeof DialogAnimationConfigs . CarbonReact }
93+ modalProps = { modalProps }
94+ overlayProps = { overlayProps }
95+ overlayTouchDismiss = { overlayTouchDismiss }
96+ />
12897 </ DialogContext . Provider >
12998 )
13099
131100 } ,
132101)
102+
103+ interface ControllerWrapperProps extends Omit < ControllerProps , "onEmpty" > {
104+ ref ?: React . Ref < ControllerWrapperRef > ,
105+ }
106+
107+ interface ControllerWrapperRef extends ControllerRef {
108+ }
109+
110+ /**
111+ * This is a simple component to save a bit of memory by not mounting the actual `Controller` when it's not needed
112+ */
113+ function ControllerWrapper ( {
114+ ref,
115+ ...props
116+ } : ControllerWrapperProps ) {
117+
118+ const
119+ [ mount , setMount ] =
120+ useState ( false ) ,
121+
122+ controllerRef =
123+ useRef < ControllerRef > ( null ) ,
124+
125+ dialogDataQueue =
126+ useRef < DialogData > ( null ) ,
127+
128+ onEmpty =
129+ useCallback ( ( ) => {
130+ if ( ! dialogDataQueue . current && controllerRef . current ) {
131+ setMount ( false )
132+ }
133+ } , [ ] )
134+
135+ useImperativeHandle ( ref , ( ) => {
136+ const errMsg = "Error to get the Controller's ref"
137+
138+ return {
139+ show ( data ) {
140+ if ( controllerRef . current ) {
141+ controllerRef . current . show ( data )
142+ } else {
143+ dialogDataQueue . current = data
144+ setMount ( true )
145+ }
146+ } ,
147+ dismiss ( ) {
148+ if ( controllerRef . current ) {
149+ return controllerRef . current . dismiss ( )
150+ }
151+ console . error ( errMsg )
152+ return Promise . resolve ( )
153+ } ,
154+ dismissAll ( ) {
155+ if ( controllerRef . current ) {
156+ return controllerRef . current . dismissAll ( )
157+ }
158+ console . error ( errMsg )
159+ return Promise . resolve ( )
160+ } ,
161+ }
162+ } , [ ] )
163+
164+ useEffect ( ( ) => {
165+ if ( mount && dialogDataQueue . current && controllerRef . current ) {
166+ controllerRef . current . show ( { ...dialogDataQueue . current } )
167+ dialogDataQueue . current = null
168+ }
169+ } , [
170+ mount ,
171+ ] )
172+
173+ if ( ! mount ) {
174+ return null
175+ }
176+
177+ return (
178+ < InDialogContext . Provider value >
179+ < Controller
180+ ref = { controllerRef }
181+ { ...props }
182+ onEmpty = { onEmpty }
183+ />
184+ </ InDialogContext . Provider >
185+ )
186+
187+ }
0 commit comments