Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions src/UniqueProvider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,33 @@ const UniqueProvider = ({ children }: UniqueProviderProps) => {
// ========================== Register ==========================
const [popupId, setPopupId] = React.useState(0);

// Store the isOpen function from the latest show call
const isOpenRef = React.useRef<(() => boolean) | null>(null);

const delayInvoke = useDelay();

const show = useEvent((showOptions: UniqueShowOptions) => {
delayInvoke(() => {
if (showOptions.id !== options?.id) {
setPopupId((i) => i + 1);
}
trigger(showOptions);
}, showOptions.delay);
});
const show = useEvent(
(showOptions: UniqueShowOptions, isOpen: () => boolean) => {
// Store the isOpen function for later use in hide
isOpenRef.current = isOpen;

delayInvoke(() => {
if (showOptions.id !== options?.id) {
setPopupId((i) => i + 1);
}
trigger(showOptions);
}, showOptions.delay);
},
);

const hide = (delay: number) => {
delayInvoke(() => {
// Check if we should still hide by calling the isOpen function
// If isOpen returns true, it means another trigger wants to keep it open
if (isOpenRef.current?.()) {
return; // Don't hide if something else wants it open
}

trigger(false);
// Don't clear target, currentNode, options immediately, wait until animation completes
}, delay);
Expand Down Expand Up @@ -106,7 +120,10 @@ const UniqueProvider = ({ children }: UniqueProviderProps) => {
false, // alignPoint is false for UniqueProvider
);

return classNames(baseClassName, options.getPopupClassNameFromAlign?.(alignInfo));
return classNames(
baseClassName,
options.getPopupClassNameFromAlign?.(alignInfo),
);
}, [
alignInfo,
options?.getPopupClassNameFromAlign,
Expand Down
2 changes: 1 addition & 1 deletion src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export interface UniqueShowOptions {
}

export interface UniqueContextProps {
show: (options: UniqueShowOptions) => void;
show: (options: UniqueShowOptions, isOpen: () => boolean) => void;
hide: (delay: number) => void;
}

Expand Down
9 changes: 5 additions & 4 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ export function generateTrigger(
}
});

// Support ref
const isOpen = useEvent(() => mergedOpen);

useLayoutEffect(() => {
setInternalOpen(popupVisible || false);
}, [popupVisible]);
Expand Down Expand Up @@ -347,9 +350,7 @@ export function generateTrigger(
!parentContext
) {
if (mergedOpen) {
Promise.resolve().then(() => {
uniqueContext.show(getUniqueOptions(0));
});
uniqueContext.show(getUniqueOptions(0), isOpen);
} else {
uniqueContext.hide(0);
}
Expand Down Expand Up @@ -395,7 +396,7 @@ export function generateTrigger(
// If there is a parentContext, don't call uniqueContext methods
if (uniqueContext && unique && openUncontrolled && !parentContext) {
if (nextOpen) {
uniqueContext.show(getUniqueOptions(delay));
uniqueContext.show(getUniqueOptions(delay), isOpen);
} else {
uniqueContext.hide(delay);
}
Expand Down
3 changes: 0 additions & 3 deletions tests/unique.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,5 @@ describe('Trigger.Unique', () => {
// Check that custom className from getPopupClassNameFromAlign is applied
expect(popup.className).toContain('custom-align');
expect(popup.className).toContain('rc-trigger-popup-unique-controlled');

// The base placement className might not be available immediately due to async alignment
// but the custom className should always be applied
});
});
Loading