Skip to content

Commit 4986298

Browse files
authored
refactor: Add checker to ensure next open (#571)
* chore: init hooks * adjust logic
1 parent 22d4f01 commit 4986298

File tree

4 files changed

+32
-17
lines changed

4 files changed

+32
-17
lines changed

src/UniqueProvider/index.tsx

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,33 @@ const UniqueProvider = ({ children }: UniqueProviderProps) => {
4545
// ========================== Register ==========================
4646
const [popupId, setPopupId] = React.useState(0);
4747

48+
// Store the isOpen function from the latest show call
49+
const isOpenRef = React.useRef<(() => boolean) | null>(null);
50+
4851
const delayInvoke = useDelay();
4952

50-
const show = useEvent((showOptions: UniqueShowOptions) => {
51-
delayInvoke(() => {
52-
if (showOptions.id !== options?.id) {
53-
setPopupId((i) => i + 1);
54-
}
55-
trigger(showOptions);
56-
}, showOptions.delay);
57-
});
53+
const show = useEvent(
54+
(showOptions: UniqueShowOptions, isOpen: () => boolean) => {
55+
// Store the isOpen function for later use in hide
56+
isOpenRef.current = isOpen;
57+
58+
delayInvoke(() => {
59+
if (showOptions.id !== options?.id) {
60+
setPopupId((i) => i + 1);
61+
}
62+
trigger(showOptions);
63+
}, showOptions.delay);
64+
},
65+
);
5866

5967
const hide = (delay: number) => {
6068
delayInvoke(() => {
69+
// Check if we should still hide by calling the isOpen function
70+
// If isOpen returns true, it means another trigger wants to keep it open
71+
if (isOpenRef.current?.()) {
72+
return; // Don't hide if something else wants it open
73+
}
74+
6175
trigger(false);
6276
// Don't clear target, currentNode, options immediately, wait until animation completes
6377
}, delay);
@@ -106,7 +120,10 @@ const UniqueProvider = ({ children }: UniqueProviderProps) => {
106120
false, // alignPoint is false for UniqueProvider
107121
);
108122

109-
return classNames(baseClassName, options.getPopupClassNameFromAlign?.(alignInfo));
123+
return classNames(
124+
baseClassName,
125+
options.getPopupClassNameFromAlign?.(alignInfo),
126+
);
110127
}, [
111128
alignInfo,
112129
options?.getPopupClassNameFromAlign,

src/context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export interface UniqueShowOptions {
3535
}
3636

3737
export interface UniqueContextProps {
38-
show: (options: UniqueShowOptions) => void;
38+
show: (options: UniqueShowOptions, isOpen: () => boolean) => void;
3939
hide: (delay: number) => void;
4040
}
4141

src/index.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ export function generateTrigger(
309309
}
310310
});
311311

312+
// Support ref
313+
const isOpen = useEvent(() => mergedOpen);
314+
312315
useLayoutEffect(() => {
313316
setInternalOpen(popupVisible || false);
314317
}, [popupVisible]);
@@ -347,9 +350,7 @@ export function generateTrigger(
347350
!parentContext
348351
) {
349352
if (mergedOpen) {
350-
Promise.resolve().then(() => {
351-
uniqueContext.show(getUniqueOptions(0));
352-
});
353+
uniqueContext.show(getUniqueOptions(0), isOpen);
353354
} else {
354355
uniqueContext.hide(0);
355356
}
@@ -395,7 +396,7 @@ export function generateTrigger(
395396
// If there is a parentContext, don't call uniqueContext methods
396397
if (uniqueContext && unique && openUncontrolled && !parentContext) {
397398
if (nextOpen) {
398-
uniqueContext.show(getUniqueOptions(delay));
399+
uniqueContext.show(getUniqueOptions(delay), isOpen);
399400
} else {
400401
uniqueContext.hide(delay);
401402
}

tests/unique.test.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,5 @@ describe('Trigger.Unique', () => {
151151
// Check that custom className from getPopupClassNameFromAlign is applied
152152
expect(popup.className).toContain('custom-align');
153153
expect(popup.className).toContain('rc-trigger-popup-unique-controlled');
154-
155-
// The base placement className might not be available immediately due to async alignment
156-
// but the custom className should always be applied
157154
});
158155
});

0 commit comments

Comments
 (0)