11import * as React from 'react' ;
2- import { UniqueContext , type UniqueContextProps } from '../context' ;
2+ import Portal from '@rc-component/portal' ;
3+ import TriggerContext , {
4+ UniqueContext ,
5+ type UniqueContextProps ,
6+ type TriggerContextProps ,
7+ type UniqueShowOptions ,
8+ } from '../context' ;
39import useDelay from '../hooks/useDelay' ;
10+ import Popup from '../Popup' ;
411
512export interface UniqueProviderProps {
613 children : React . ReactNode ;
714}
815
916const UniqueProvider = ( { children } : UniqueProviderProps ) => {
17+ const [ open , setOpen ] = React . useState ( false ) ;
1018 const [ target , setTarget ] = React . useState < HTMLElement | null > ( null ) ;
1119 const [ currentNode , setCurrentNode ] = React . useState < React . ReactNode > ( null ) ;
20+ const [ options , setOptions ] = React . useState < UniqueShowOptions | null > ( null ) ;
1221
1322 // ========================== Register ==========================
1423 const delayInvoke = useDelay ( ) ;
1524
16- const show = ( node : React . ReactNode , targetElement : HTMLElement , delay : number ) => {
25+ const show = ( showOptions : UniqueShowOptions ) => {
1726 delayInvoke ( ( ) => {
18- setCurrentNode ( node ) ;
19- setTarget ( targetElement ) ;
20- } , delay ) ;
27+ setOpen ( true ) ;
28+ setCurrentNode ( showOptions . popup ) ;
29+ setTarget ( showOptions . target ) ;
30+ setOptions ( showOptions ) ;
31+ } , showOptions . delay ) ;
2132 } ;
2233
2334 const hide = ( delay : number ) => {
2435 delayInvoke ( ( ) => {
25- setTarget ( null ) ;
26- setCurrentNode ( null ) ;
36+ setOpen ( false ) ;
2737 } , delay ) ;
2838 } ;
2939
@@ -35,20 +45,60 @@ const UniqueProvider = ({ children }: UniqueProviderProps) => {
3545 [ ] ,
3646 ) ;
3747
38- /**
39- * TODO: 参考 index.tsx 的逻辑,增加 Popup 支持:
40- * <TriggerContext.Provider value={context}>
41- <Popup ...
42-
43- 如果渲染需要的 props 不够,可以给 UniqueContextProps 里修改定义以实现需求。
48+ // ======================== Trigger Context =====================
49+ const subPopupElements = React . useRef < Record < string , HTMLElement > > ( { } ) ;
50+ const parentContext = React . useContext ( TriggerContext ) ;
4451
45- 用法 demo 在 docs/examples/two-buttons.tsx 中。
46- */
52+ const triggerContextValue = React . useMemo < TriggerContextProps > (
53+ ( ) => ( {
54+ registerSubPopup : ( id , subPopupEle ) => {
55+ subPopupElements . current [ id ] = subPopupEle ;
56+ parentContext ?. registerSubPopup ( id , subPopupEle ) ;
57+ } ,
58+ } ) ,
59+ [ parentContext ] ,
60+ ) ;
4761
4862 // =========================== Render ===========================
4963 return (
5064 < UniqueContext . Provider value = { contextValue } >
5165 { children }
66+ { options && (
67+ < TriggerContext . Provider value = { triggerContextValue } >
68+ < Popup
69+ portal = { Portal }
70+ prefixCls = { options . prefixCls || 'rc-trigger-popup' }
71+ popup = { currentNode }
72+ className = { options . popupClassName }
73+ style = { options . popupStyle }
74+ target = { target }
75+ open = { open }
76+ keepDom = { false }
77+ fresh = { true }
78+ onVisibleChanged = { ( ) => { } }
79+ ready = { true }
80+ offsetX = { 0 }
81+ offsetY = { 0 }
82+ offsetR = { 0 }
83+ offsetB = { 0 }
84+ onAlign = { ( ) => { } }
85+ onPrepare = { ( ) => Promise . resolve ( ) }
86+ arrowPos = { { } }
87+ align = {
88+ options . popupAlign || {
89+ points : [ 'tl' , 'bl' ] ,
90+ offset : [ 0 , 4 ] ,
91+ }
92+ }
93+ zIndex = { options . zIndex }
94+ mask = { options . mask }
95+ arrow = { options . arrow }
96+ motion = { options . popupMotion }
97+ maskMotion = { options . maskMotion }
98+ getPopupContainer = { options . getPopupContainer }
99+ />
100+ </ TriggerContext . Provider >
101+ ) }
52102 </ UniqueContext . Provider >
53103 ) ;
54104} ;
0 commit comments