11import type { DElementSelector } from '../../hooks/element-ref' ;
2+ import type { Updater } from '../../hooks/immer' ;
23import type { DPlacement } from '../../utils/position' ;
34import type { DTransitionStateList , DTransitionRef } from '../_transition' ;
45
56import { isUndefined } from 'lodash' ;
67import React , { useCallback , useEffect , useMemo , useImperativeHandle , useRef } from 'react' ;
78import ReactDOM , { flushSync } from 'react-dom' ;
89
9- import { useDPrefixConfig , useAsync , useRefSelector , useManualOrAutoState , useId , useImmer , useRefCallback } from '../../hooks' ;
10+ import { useDPrefixConfig , useAsync , useRefSelector , useId , useImmer , useRefCallback } from '../../hooks' ;
1011import { getClassName , globalMaxIndexManager , getPopupPlacementStyle } from '../../utils' ;
1112import { DTransition } from '../_transition' ;
1213
@@ -25,7 +26,7 @@ export interface DPopupRef {
2526}
2627
2728export interface DPopupProps extends React . HTMLAttributes < HTMLDivElement > {
28- dVisible ?: boolean ;
29+ dVisible ?: [ boolean , Updater < boolean > ? ] ;
2930 dPopupContent : React . ReactNode ;
3031 dTriggerRender ?: ( props : DTriggerRenderProps ) => React . ReactNode ;
3132 dTriggerEl ?: HTMLElement | null ;
@@ -91,7 +92,18 @@ export const DPopup = React.forwardRef<DPopupRef, DPopupProps>((props, ref) => {
9192 const [ zIndex , setZIndex ] = useImmer ( 1000 ) ;
9293 const id = useId ( ) ;
9394
94- const [ visible , dispatchVisible ] = useManualOrAutoState ( false , dVisible , onTrigger ) ;
95+ const setVisible = dVisible ?. [ 1 ] ;
96+ const [ autoVisible , setAutoVisible ] = useImmer ( false ) ;
97+ const visible = dVisible ?. [ 0 ] ?? autoVisible ;
98+ const changeVisible = useCallback (
99+ ( val ?: boolean ) => {
100+ const _val = isUndefined ( val ) ? ! visible : val ;
101+ setVisible ?.( _val ) ;
102+ setAutoVisible ( _val ) ;
103+ onTrigger ?.( _val ) ;
104+ } ,
105+ [ onTrigger , setAutoVisible , setVisible , visible ]
106+ ) ;
95107
96108 const [ autoPlacement , setAutoPlacement ] = useImmer < DPlacement > ( dPlacement ) ;
97109
@@ -249,11 +261,11 @@ export const DPopup = React.forwardRef<DPopupRef, DPopupProps>((props, ref) => {
249261 dataRef . current . clearTid && dataRef . current . clearTid ( ) ;
250262 dataRef . current . clearTid = asyncCapture . setTimeout ( ( ) => {
251263 dataRef . current . clearTid = null ;
252- dispatchVisible ( { value : true } ) ;
264+ changeVisible ( true ) ;
253265 } , dMouseEnterDelay ) ;
254266 }
255267 } ,
256- [ asyncCapture , dMouseEnterDelay , dTrigger , onMouseEnter , dispatchVisible ]
268+ [ onMouseEnter , dTrigger , asyncCapture , dMouseEnterDelay , changeVisible ]
257269 ) ;
258270
259271 const handleMouseLeave = useCallback (
@@ -264,11 +276,11 @@ export const DPopup = React.forwardRef<DPopupRef, DPopupProps>((props, ref) => {
264276 dataRef . current . clearTid && dataRef . current . clearTid ( ) ;
265277 dataRef . current . clearTid = asyncCapture . setTimeout ( ( ) => {
266278 dataRef . current . clearTid = null ;
267- dispatchVisible ( { value : false } ) ;
279+ changeVisible ( false ) ;
268280 } , dMouseLeaveDelay ) ;
269281 }
270282 } ,
271- [ asyncCapture , dMouseLeaveDelay , dTrigger , onMouseLeave , dispatchVisible ]
283+ [ onMouseLeave , dTrigger , asyncCapture , dMouseLeaveDelay , changeVisible ]
272284 ) ;
273285
274286 const handleFocus = useCallback (
@@ -277,21 +289,21 @@ export const DPopup = React.forwardRef<DPopupRef, DPopupProps>((props, ref) => {
277289
278290 if ( dTrigger === 'focus' ) {
279291 dataRef . current . clearTid && dataRef . current . clearTid ( ) ;
280- dispatchVisible ( { value : true } ) ;
292+ changeVisible ( true ) ;
281293 }
282294 } ,
283- [ dTrigger , onFocus , dispatchVisible ]
295+ [ onFocus , dTrigger , changeVisible ]
284296 ) ;
285297
286298 const handleBlur = useCallback (
287299 ( e ) => {
288300 onBlur ?.( e ) ;
289301
290302 if ( dTrigger === 'focus' ) {
291- dataRef . current . clearTid = asyncCapture . setTimeout ( ( ) => dispatchVisible ( { value : false } ) , 20 ) ;
303+ dataRef . current . clearTid = asyncCapture . setTimeout ( ( ) => changeVisible ( false ) , 20 ) ;
292304 }
293305 } ,
294- [ asyncCapture , dTrigger , onBlur , dispatchVisible ]
306+ [ onBlur , dTrigger , asyncCapture , changeVisible ]
295307 ) ;
296308
297309 const handleClick = useCallback (
@@ -300,15 +312,15 @@ export const DPopup = React.forwardRef<DPopupRef, DPopupProps>((props, ref) => {
300312
301313 if ( dTrigger === 'click' ) {
302314 dataRef . current . clearTid && dataRef . current . clearTid ( ) ;
303- dispatchVisible ( { value : true } ) ;
315+ changeVisible ( true ) ;
304316 }
305317 } ,
306- [ dTrigger , onClick , dispatchVisible ]
318+ [ onClick , dTrigger , changeVisible ]
307319 ) ;
308320
309321 //#region DidUpdate
310322 useEffect ( ( ) => {
311- if ( dVisible ) {
323+ if ( visible ) {
312324 if ( isUndefined ( dZIndex ) ) {
313325 if ( isUndefined ( dContainer ) ) {
314326 const [ key , maxZIndex ] = globalMaxIndexManager . getMaxIndex ( ) ;
@@ -323,7 +335,7 @@ export const DPopup = React.forwardRef<DPopupRef, DPopupProps>((props, ref) => {
323335 setZIndex ( dZIndex ) ;
324336 }
325337 }
326- } , [ dVisible , dContainer , dZIndex , setZIndex ] ) ;
338+ } , [ dContainer , dZIndex , setZIndex , visible ] ) ;
327339
328340 useEffect ( ( ) => {
329341 if ( ! isUndefined ( dTriggerEl ) ) {
@@ -335,7 +347,7 @@ export const DPopup = React.forwardRef<DPopupRef, DPopupProps>((props, ref) => {
335347 dataRef . current . clearTid && dataRef . current . clearTid ( ) ;
336348 dataRef . current . clearTid = asyncCapture . setTimeout ( ( ) => {
337349 dataRef . current . clearTid = null ;
338- flushSync ( ( ) => dispatchVisible ( { value : true } ) ) ;
350+ flushSync ( ( ) => changeVisible ( true ) ) ;
339351 } , dMouseEnterDelay ) ;
340352 } ,
341353 } ) ;
@@ -344,7 +356,7 @@ export const DPopup = React.forwardRef<DPopupRef, DPopupProps>((props, ref) => {
344356 dataRef . current . clearTid && dataRef . current . clearTid ( ) ;
345357 dataRef . current . clearTid = asyncCapture . setTimeout ( ( ) => {
346358 dataRef . current . clearTid = null ;
347- flushSync ( ( ) => dispatchVisible ( { value : false } ) ) ;
359+ flushSync ( ( ) => changeVisible ( false ) ) ;
348360 } , dMouseLeaveDelay ) ;
349361 } ,
350362 } ) ;
@@ -354,12 +366,12 @@ export const DPopup = React.forwardRef<DPopupRef, DPopupProps>((props, ref) => {
354366 asyncGroup . fromEvent ( triggerRef . current , 'focus' ) . subscribe ( {
355367 next : ( ) => {
356368 dataRef . current . clearTid && dataRef . current . clearTid ( ) ;
357- flushSync ( ( ) => dispatchVisible ( { value : true } ) ) ;
369+ flushSync ( ( ) => changeVisible ( true ) ) ;
358370 } ,
359371 } ) ;
360372 asyncGroup . fromEvent ( triggerRef . current , 'blur' ) . subscribe ( {
361373 next : ( ) => {
362- dataRef . current . clearTid = asyncCapture . setTimeout ( ( ) => flushSync ( ( ) => dispatchVisible ( { value : false } ) ) , 20 ) ;
374+ dataRef . current . clearTid = asyncCapture . setTimeout ( ( ) => flushSync ( ( ) => changeVisible ( false ) ) , 20 ) ;
363375 } ,
364376 } ) ;
365377 }
@@ -368,7 +380,7 @@ export const DPopup = React.forwardRef<DPopupRef, DPopupProps>((props, ref) => {
368380 asyncGroup . fromEvent ( triggerRef . current , 'click' ) . subscribe ( {
369381 next : ( ) => {
370382 dataRef . current . clearTid && dataRef . current . clearTid ( ) ;
371- flushSync ( ( ) => dispatchVisible ( { reverse : true } ) ) ;
383+ flushSync ( ( ) => changeVisible ( ) ) ;
372384 } ,
373385 } ) ;
374386 }
@@ -378,7 +390,7 @@ export const DPopup = React.forwardRef<DPopupRef, DPopupProps>((props, ref) => {
378390 asyncCapture . deleteGroup ( asyncId ) ;
379391 } ;
380392 }
381- } , [ asyncCapture , dMouseEnterDelay , dMouseLeaveDelay , dTrigger , dTriggerEl , dispatchVisible , triggerRef ] ) ;
393+ } , [ asyncCapture , changeVisible , dMouseEnterDelay , dMouseLeaveDelay , dTrigger , dTriggerEl , triggerRef ] ) ;
382394
383395 useEffect ( ( ) => {
384396 const [ asyncGroup , asyncId ] = asyncCapture . createGroup ( ) ;
@@ -387,7 +399,7 @@ export const DPopup = React.forwardRef<DPopupRef, DPopupProps>((props, ref) => {
387399 asyncGroup . fromEvent ( window , 'click' , { capture : true } ) . subscribe ( {
388400 next : ( ) => {
389401 dataRef . current . clearTid = asyncGroup . setTimeout ( ( ) => {
390- flushSync ( ( ) => dispatchVisible ( { value : false } ) ) ;
402+ flushSync ( ( ) => changeVisible ( false ) ) ;
391403 } , 20 ) ;
392404 } ,
393405 } ) ;
@@ -396,7 +408,7 @@ export const DPopup = React.forwardRef<DPopupRef, DPopupProps>((props, ref) => {
396408 return ( ) => {
397409 asyncCapture . deleteGroup ( asyncId ) ;
398410 } ;
399- } , [ asyncCapture , dTrigger , dispatchVisible ] ) ;
411+ } , [ asyncCapture , changeVisible , dTrigger ] ) ;
400412
401413 useEffect ( ( ) => {
402414 const [ asyncGroup , asyncId ] = asyncCapture . createGroup ( ) ;
@@ -438,35 +450,35 @@ export const DPopup = React.forwardRef<DPopupRef, DPopupProps>((props, ref) => {
438450 dataRef . current . clearTid && dataRef . current . clearTid ( ) ;
439451 dataRef . current . clearTid = asyncCapture . setTimeout ( ( ) => {
440452 dataRef . current . clearTid = null ;
441- dispatchVisible ( { value : true } ) ;
453+ changeVisible ( true ) ;
442454 } , dMouseEnterDelay ) ;
443455 } ;
444456 _triggerRenderProps . onMouseLeave = ( ) => {
445457 dataRef . current . clearTid && dataRef . current . clearTid ( ) ;
446458 dataRef . current . clearTid = asyncCapture . setTimeout ( ( ) => {
447459 dataRef . current . clearTid = null ;
448- dispatchVisible ( { value : false } ) ;
460+ changeVisible ( false ) ;
449461 } , dMouseLeaveDelay ) ;
450462 } ;
451463 }
452464 if ( dTrigger === 'focus' ) {
453465 _triggerRenderProps . onFocus = ( ) => {
454466 dataRef . current . clearTid && dataRef . current . clearTid ( ) ;
455- dispatchVisible ( { value : true } ) ;
467+ changeVisible ( true ) ;
456468 } ;
457469 _triggerRenderProps . onBlur = ( ) => {
458- dataRef . current . clearTid = asyncCapture . setTimeout ( ( ) => dispatchVisible ( { value : false } ) , 20 ) ;
470+ dataRef . current . clearTid = asyncCapture . setTimeout ( ( ) => changeVisible ( false ) , 20 ) ;
459471 } ;
460472 }
461473 if ( dTrigger === 'click' ) {
462474 _triggerRenderProps . onClick = ( ) => {
463475 dataRef . current . clearTid && dataRef . current . clearTid ( ) ;
464- dispatchVisible ( { reverse : true } ) ;
476+ changeVisible ( ) ;
465477 } ;
466478 }
467479
468480 return _triggerRenderProps ;
469- } , [ asyncCapture , dMouseEnterDelay , dMouseLeaveDelay , dPrefix , dTrigger , dispatchVisible , id ] ) ;
481+ } , [ asyncCapture , changeVisible , dMouseEnterDelay , dMouseLeaveDelay , dPrefix , dTrigger , id ] ) ;
470482
471483 return (
472484 < >
0 commit comments