Skip to content

Commit f4c2f1d

Browse files
zktzkt
authored andcommitted
fix: prevent modal close when dragging from content to mask
- Use bubbling `onMouseDown` to track if the click originated from the mask. - Only trigger close in `onClick` if both mousedown and click targets are the wrapper. - Reset tracking refs when dialog becomes visible to prevent state pollution. - Remove capture listeners to avoid potential event conflicts.
1 parent fcb258d commit f4c2f1d

File tree

2 files changed

+3
-41
lines changed

2 files changed

+3
-41
lines changed

src/Dialog/index.tsx

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ const Dialog: React.FC<IDialogPropTypes> = (props) => {
111111

112112
// >>> Content
113113
const mouseDownOnMaskRef = useRef(false);
114-
const mouseUpOnMaskRef = useRef(false);
115114

116115
// >>> Wrapper
117116
// Close only when element not on dialog
@@ -121,27 +120,21 @@ const Dialog: React.FC<IDialogPropTypes> = (props) => {
121120
if (
122121
onClose &&
123122
wrapperRef.current === e.target &&
124-
mouseDownOnMaskRef.current &&
125-
mouseUpOnMaskRef.current
123+
mouseDownOnMaskRef.current
126124
) {
127125
onInternalClose(e);
128126
}
129127
};
130128
}
131129

132-
function onWrapperMouseDownCapture(e: React.MouseEvent) {
130+
function onWrapperMouseDown(e: React.MouseEvent) {
133131
mouseDownOnMaskRef.current = e.target === wrapperRef.current;
134132
}
135133

136-
function onWrapperMouseUpCapture(e: React.MouseEvent) {
137-
mouseUpOnMaskRef.current = e.target === wrapperRef.current;
138-
}
139-
140134
// ========================= Effect =========================
141135
useEffect(() => {
142136
if (visible) {
143137
mouseDownOnMaskRef.current = false;
144-
mouseUpOnMaskRef.current = false;
145138
setAnimatedVisible(true);
146139
saveLastOutSideActiveElementRef();
147140

@@ -185,8 +178,7 @@ const Dialog: React.FC<IDialogPropTypes> = (props) => {
185178
className={clsx(`${prefixCls}-wrap`, wrapClassName, modalClassNames?.wrapper)}
186179
ref={wrapperRef}
187180
onClick={onWrapperClick}
188-
onMouseDownCapture={onWrapperMouseDownCapture}
189-
onMouseUpCapture={onWrapperMouseUpCapture}
181+
onMouseDown={onWrapperMouseDown}
190182
style={mergedStyle}
191183
{...wrapProps}
192184
>

tests/mask-closable.spec.tsx

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -57,34 +57,4 @@ describe('Dialog.MaskClosable', () => {
5757

5858
expect(onClose).not.toHaveBeenCalled();
5959
});
60-
61-
it('should not close when dragging from mask to content', () => {
62-
const onClose = jest.fn();
63-
const { getByText } = render(
64-
<Dialog visible maskClosable onClose={onClose}>
65-
Content
66-
</Dialog>
67-
);
68-
69-
act(() => {
70-
jest.runAllTimers();
71-
});
72-
73-
const content = getByText('Content');
74-
const mask = document.querySelector('.rc-dialog-wrap');
75-
if (!mask) throw new Error('Mask not found');
76-
77-
// Simulate mouse down on mask
78-
fireEvent.mouseDown(mask);
79-
// Simulate mouse up on content
80-
fireEvent.mouseUp(content);
81-
// Simulate click on mask (since click follows mouseup)
82-
// Note: In real browser, click event might trigger on the common ancestor or user logic might vary,
83-
// but here we simulate what happens if a click event reaches the wrapper.
84-
// If we drag from mask to content, the click likely happens on content or common parent.
85-
// But if propagation reaches wrapper, we want to ensure it doesn't close.
86-
fireEvent.click(mask);
87-
88-
expect(onClose).not.toHaveBeenCalled();
89-
});
9060
});

0 commit comments

Comments
 (0)