Skip to content

Commit 6064ded

Browse files
committed
chore: wrapper
1 parent 592d0a3 commit 6064ded

4 files changed

Lines changed: 159 additions & 61 deletions

File tree

docs/examples/two-buttons.tsx

Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Trigger, { UniqueProvider } from '@rc-component/trigger';
2-
import React from 'react';
2+
import React, { useState } from 'react';
33
import '../../assets/index.less';
44

55
const builtinPlacements = {
@@ -26,51 +26,63 @@ function getPopupContainer(trigger) {
2626
}
2727

2828
const MovingPopupDemo = () => {
29-
return (
30-
<UniqueProvider>
31-
<div style={{ margin: 100 }}>
32-
<div style={{ display: 'flex', gap: 20 }}>
33-
<Trigger
34-
action={['hover']}
35-
popupPlacement="top"
36-
builtinPlacements={builtinPlacements}
37-
getPopupContainer={getPopupContainer}
38-
popupMotion={{
39-
motionName: 'rc-trigger-popup-zoom',
40-
}}
41-
popup={<div>这是左侧按钮的提示信息</div>}
42-
popupStyle={{
43-
border: '1px solid #ccc',
44-
padding: 10,
45-
background: 'white',
46-
boxSizing: 'border-box',
47-
}}
48-
>
49-
<button type="button">左侧按钮</button>
50-
</Trigger>
51-
52-
<Trigger
53-
action={['hover']}
54-
popupPlacement="top"
55-
builtinPlacements={builtinPlacements}
56-
getPopupContainer={getPopupContainer}
57-
popupMotion={{
58-
motionName: 'rc-trigger-popup-zoom',
59-
}}
60-
popup={<div>This is the tooltip for the right button</div>}
61-
popupStyle={{
62-
border: '1px solid #ccc',
63-
padding: 10,
64-
background: 'white',
65-
boxSizing: 'border-box',
66-
}}
67-
>
68-
<button type="button">Right Button</button>
69-
</Trigger>
70-
</div>
29+
const [useUniqueProvider, setUseUniqueProvider] = useState(true);
30+
31+
const content = (
32+
<div style={{ margin: 100 }}>
33+
<div style={{ marginBottom: 20 }}>
34+
<label>
35+
<input
36+
type="checkbox"
37+
checked={useUniqueProvider}
38+
onChange={(e) => setUseUniqueProvider(e.target.checked)}
39+
/>
40+
使用 UniqueProvider
41+
</label>
7142
</div>
72-
</UniqueProvider>
43+
<div style={{ display: 'flex', gap: 20 }}>
44+
<Trigger
45+
action={['hover']}
46+
popupPlacement="top"
47+
builtinPlacements={builtinPlacements}
48+
getPopupContainer={getPopupContainer}
49+
popupMotion={{
50+
motionName: 'rc-trigger-popup-zoom',
51+
}}
52+
popup={<div>这是左侧按钮的提示信息</div>}
53+
popupStyle={{
54+
border: '1px solid #ccc',
55+
padding: 10,
56+
background: 'white',
57+
boxSizing: 'border-box',
58+
}}
59+
>
60+
<button type="button">左侧按钮</button>
61+
</Trigger>
62+
63+
<Trigger
64+
action={['hover']}
65+
popupPlacement="top"
66+
builtinPlacements={builtinPlacements}
67+
getPopupContainer={getPopupContainer}
68+
popupMotion={{
69+
motionName: 'rc-trigger-popup-zoom',
70+
}}
71+
popup={<div>This is the tooltip for the right button</div>}
72+
popupStyle={{
73+
border: '1px solid #ccc',
74+
padding: 10,
75+
background: 'white',
76+
boxSizing: 'border-box',
77+
}}
78+
>
79+
<button type="button">Right Button</button>
80+
</Trigger>
81+
</div>
82+
</div>
7383
);
84+
85+
return useUniqueProvider ? <UniqueProvider>{content}</UniqueProvider> : content;
7486
};
7587

7688
export default MovingPopupDemo;

src/UniqueProvider/index.tsx

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,39 @@
11
import * 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';
39
import useDelay from '../hooks/useDelay';
10+
import Popup from '../Popup';
411

512
export interface UniqueProviderProps {
613
children: React.ReactNode;
714
}
815

916
const 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
};

src/context.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,27 @@ const TriggerContext = React.createContext<TriggerContextProps | null>(null);
1111
export default TriggerContext;
1212

1313
// ==================== Unique ====================
14+
export interface UniqueShowOptions {
15+
popup: TriggerProps['popup'];
16+
target: HTMLElement;
17+
delay: number;
18+
prefixCls?: string;
19+
popupClassName?: string;
20+
popupStyle?: React.CSSProperties;
21+
popupPlacement?: string;
22+
builtinPlacements?: any;
23+
popupAlign?: any;
24+
zIndex?: number;
25+
mask?: boolean;
26+
maskClosable?: boolean;
27+
popupMotion?: any;
28+
maskMotion?: any;
29+
arrow?: any;
30+
getPopupContainer?: TriggerProps['getPopupContainer'];
31+
}
32+
1433
export interface UniqueContextProps {
15-
show: (popup: TriggerProps['popup'], target: HTMLElement, delay: number) => void;
34+
show: (options: UniqueShowOptions) => void;
1635
hide: (delay: number) => void;
1736
}
1837

src/index.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,24 @@ export function generateTrigger(
327327
// If UniqueContext exists, pass delay to Provider instead of handling it internally
328328
if (uniqueContext) {
329329
if (nextOpen && targetEle) {
330-
uniqueContext.show(popup, targetEle, delay);
330+
uniqueContext.show({
331+
popup,
332+
target: targetEle,
333+
delay,
334+
prefixCls,
335+
popupClassName,
336+
popupStyle,
337+
popupPlacement,
338+
builtinPlacements,
339+
popupAlign,
340+
zIndex,
341+
mask,
342+
maskClosable,
343+
popupMotion,
344+
maskMotion,
345+
arrow,
346+
getPopupContainer,
347+
});
331348
} else {
332349
uniqueContext.hide(delay);
333350
}

0 commit comments

Comments
 (0)