Skip to content

Commit f9dc1fa

Browse files
committed
chore: init
1 parent 867a20c commit f9dc1fa

5 files changed

Lines changed: 139 additions & 2 deletions

File tree

docs/demos/two-buttons.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: Moving Popup
3+
nav:
4+
title: Demo
5+
path: /demo
6+
---
7+
8+
<code src="../examples/two-buttons.tsx"></code>

docs/examples/two-buttons.tsx

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import Trigger from '@rc-component/trigger';
2+
import React from 'react';
3+
import '../../assets/index.less';
4+
5+
const builtinPlacements = {
6+
left: {
7+
points: ['cr', 'cl'],
8+
offset: [-10, 0],
9+
},
10+
right: {
11+
points: ['cl', 'cr'],
12+
offset: [10, 0],
13+
},
14+
top: {
15+
points: ['bc', 'tc'],
16+
offset: [0, -10],
17+
},
18+
bottom: {
19+
points: ['tc', 'bc'],
20+
offset: [0, 10],
21+
},
22+
};
23+
24+
function getPopupContainer(trigger) {
25+
return trigger.parentNode;
26+
}
27+
28+
const MovingPopupDemo = () => {
29+
return (
30+
<div style={{ margin: 100 }}>
31+
<div style={{ display: 'flex', gap: 20 }}>
32+
<Trigger
33+
action={['hover']}
34+
popupPlacement="top"
35+
builtinPlacements={builtinPlacements}
36+
getPopupContainer={getPopupContainer}
37+
popupMotion={{
38+
motionName: 'rc-trigger-popup-zoom',
39+
}}
40+
popup={<div>这是左侧按钮的提示信息</div>}
41+
popupStyle={{
42+
border: '1px solid #ccc',
43+
padding: 10,
44+
background: 'white',
45+
boxSizing: 'border-box',
46+
}}
47+
>
48+
<button type="button">左侧按钮</button>
49+
</Trigger>
50+
51+
<Trigger
52+
action={['hover']}
53+
popupPlacement="top"
54+
builtinPlacements={builtinPlacements}
55+
getPopupContainer={getPopupContainer}
56+
popupMotion={{
57+
motionName: 'rc-trigger-popup-zoom',
58+
}}
59+
popup={<div>This is the tooltip for the right button</div>}
60+
popupStyle={{
61+
border: '1px solid #ccc',
62+
padding: 10,
63+
background: 'white',
64+
boxSizing: 'border-box',
65+
}}
66+
>
67+
<button type="button">Right Button</button>
68+
</Trigger>
69+
</div>
70+
</div>
71+
);
72+
};
73+
74+
export default MovingPopupDemo;

src/UniqueProvider.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import * as React from 'react';
2+
import { UniqueContext, type UniqueContextProps } from './context';
3+
4+
export interface UniqueProviderProps {
5+
children: React.ReactNode;
6+
}
7+
8+
const UniqueProvider = ({ children }: UniqueProviderProps) => {
9+
const [target, setTarget] = React.useState<HTMLElement | null>(null);
10+
11+
const show = (targetElement: HTMLElement) => {
12+
setTarget(targetElement);
13+
};
14+
15+
const hide = () => {
16+
setTarget(null);
17+
};
18+
19+
const contextValue = React.useMemo<UniqueContextProps>(() => ({
20+
show,
21+
hide,
22+
}), []);
23+
24+
return (
25+
<UniqueContext.Provider value={contextValue}>
26+
{children}
27+
</UniqueContext.Provider>
28+
);
29+
};
30+
31+
export default UniqueProvider;

src/context.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
import * as React from 'react';
22

3+
// ===================== Nest =====================
34
export interface TriggerContextProps {
45
registerSubPopup: (id: string, node: HTMLElement) => void;
56
}
67

78
const TriggerContext = React.createContext<TriggerContextProps | null>(null);
89

910
export default TriggerContext;
11+
12+
// ==================== Unique ====================
13+
export interface UniqueContextProps {
14+
show: (target: HTMLElement) => void;
15+
hide: (target: HTMLElement) => void;
16+
}
17+
18+
export const UniqueContext = React.createContext<UniqueContextProps | null>(
19+
null,
20+
);

src/index.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import useId from '@rc-component/util/lib/hooks/useId';
99
import useLayoutEffect from '@rc-component/util/lib/hooks/useLayoutEffect';
1010
import * as React from 'react';
1111
import Popup, { type MobileConfig } from './Popup';
12-
import type { TriggerContextProps } from './context';
13-
import TriggerContext from './context';
12+
import type { TriggerContextProps, UniqueContextProps } from './context';
13+
import TriggerContext, { UniqueContext } from './context';
1414
import useAction from './hooks/useAction';
1515
import useAlign from './hooks/useAlign';
1616
import useWatch from './hooks/useWatch';
@@ -208,6 +208,9 @@ export function generateTrigger(
208208
};
209209
}, [parentContext]);
210210

211+
// ======================== UniqueContext =========================
212+
const uniqueContext = React.useContext(UniqueContext);
213+
211214
// =========================== Popup ============================
212215
const id = useId();
213216
const [popupEle, setPopupEle] = React.useState<HTMLDivElement>(null);
@@ -299,6 +302,16 @@ export function generateTrigger(
299302
lastTriggerRef.current = [];
300303

301304
const internalTriggerOpen = useEvent((nextOpen: boolean) => {
305+
// If UniqueContext exists, delegate show/hide to Provider
306+
if (uniqueContext) {
307+
if (nextOpen && targetEle) {
308+
uniqueContext.show(targetEle);
309+
} else {
310+
uniqueContext.hide(targetEle);
311+
}
312+
return;
313+
}
314+
302315
setMergedOpen(nextOpen);
303316

304317
// Enter or Pointer will both trigger open state change

0 commit comments

Comments
 (0)