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
15 changes: 0 additions & 15 deletions packages/@react-aria/combobox/src/useComboBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {getChildNodes, getItemCount} from '@react-stately/collections';
import intlMessages from '../intl/*.json';
import {ListKeyboardDelegate, useSelectableCollection} from '@react-aria/selection';
import {privateValidationStateProp} from '@react-stately/form';
import {useInteractOutside} from '@react-aria/interactions';
import {useLocalizedStringFormatter} from '@react-aria/i18n';
import {useMenuTrigger} from '@react-aria/menu';
import {useTextField} from '@react-aria/textfield';
Expand Down Expand Up @@ -366,20 +365,6 @@ export function useComboBox<T, M extends SelectionMode = 'single'>(props: AriaCo
state.close();
} : undefined);

// usePopover -> useOverlay calls useInteractOutside, but ComboBox is non-modal, so `isDismissable` is false
// Because of this, onInteractOutside is not passed to useInteractOutside, so we need to call it here.
useInteractOutside({
ref: popoverRef,
onInteractOutside: (e) => {
let target = getEventTarget(e) as Element;
if (nodeContains(buttonRef?.current, target) || nodeContains(inputRef.current, target)) {
return;
}
state.close();
},
isDisabled: !state.isOpen
});

return {
labelProps,
buttonProps: {
Expand Down
2 changes: 1 addition & 1 deletion packages/@react-aria/dialog/docs/useDialog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ import {useViewportSize} from '@react-aria/utils';

function Modal({state, children, ...props}) {
let ref = React.useRef(null);
let {modalProps, underlayProps} = useModalOverlay(props, state, ref);
let {modalProps, underlayProps} = useModalOverlay({...props, isDismissable: true}, state, ref);

return (
<Overlay>
Expand Down
13 changes: 1 addition & 12 deletions packages/@react-aria/overlays/src/useOverlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ export function useOverlay(props: AriaOverlayProps, ref: RefObject<Element | nul
if (!shouldCloseOnInteractOutside || shouldCloseOnInteractOutside(getEventTarget(e) as Element)) {
if (topMostOverlay === ref) {
e.stopPropagation();
e.preventDefault();
}
}
};
Expand All @@ -108,7 +107,6 @@ export function useOverlay(props: AriaOverlayProps, ref: RefObject<Element | nul
if (!shouldCloseOnInteractOutside || shouldCloseOnInteractOutside(getEventTarget(e) as Element)) {
if (visibleOverlays[visibleOverlays.length - 1] === ref) {
e.stopPropagation();
e.preventDefault();
}
if (lastVisibleOverlay.current === ref) {
onHide();
Expand Down Expand Up @@ -151,20 +149,11 @@ export function useOverlay(props: AriaOverlayProps, ref: RefObject<Element | nul
}
});

let onPointerDownUnderlay = e => {
// fixes a firefox issue that starts text selection https://bugzilla.mozilla.org/show_bug.cgi?id=1675846
if (getEventTarget(e) === e.currentTarget) {
e.preventDefault();
}
};

return {
overlayProps: {
onKeyDown,
...focusWithinProps
},
underlayProps: {
onPointerDown: onPointerDownUnderlay
}
underlayProps: {}
};
}
11 changes: 0 additions & 11 deletions packages/@react-aria/overlays/test/useOverlay.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,4 @@ describe('useOverlay', function () {
fireEvent.keyDown(el, {key: 'Escape'});
expect(onClose).toHaveBeenCalledTimes(1);
});

describe('firefox bug', () => {
installPointerEvent();
it('should prevent default on pointer down on the underlay', function () {
let underlayRef = React.createRef();
render(<Example isOpen isDismissable underlayProps={{ref: underlayRef}} />);
let isPrevented = fireEvent.pointerDown(underlayRef.current, {button: 0, pointerId: 1});
fireEvent.pointerUp(document.body);
expect(isPrevented).toBeFalsy(); // meaning the event had preventDefault called
});
});
});
17 changes: 9 additions & 8 deletions packages/@react-spectrum/combobox/test/ComboBox.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4362,7 +4362,8 @@ describe('ComboBox', function () {
let dismissButtons = within(tray).getAllByRole('button');
switch (Method) {
case 'clicking outside tray':
await user.click(document.body);
fireEvent.mouseDown(document.body, {button: 0});
fireEvent.mouseUp(document.body, {button: 0});
break;
case 'dismiss button':
// TODO: not entirely sure why using user.click here breaks the test... It seems to cause the selectedKey
Expand Down Expand Up @@ -5268,9 +5269,9 @@ describe('ComboBox', function () {

if (parseInt(React.version, 10) >= 19) {
it('resets to defaultSelectedKey when submitting form action', async () => {
function Test(props) {
function Test(props) {
const [value, formAction] = React.useActionState(() => '2', '1');

return (
<Provider theme={theme}>
<form action={formAction}>
Expand All @@ -5280,11 +5281,11 @@ describe('ComboBox', function () {
</Provider>
);
}

let {getByTestId, getByRole, rerender} = render(<Test />);
let input = getByRole('combobox');
expect(input).toHaveValue('One');

let button = getByTestId('submit');
// For some reason, user.click() causes act warnings related to suspense...
await act(() => button.click());
Expand Down Expand Up @@ -5604,7 +5605,7 @@ describe('ComboBox', function () {
it('resets to defaultSelectedKey when submitting form action', async () => {
function Test(props) {
const [value, formAction] = React.useActionState(() => '2', '1');

return (
<Provider theme={theme}>
<form action={formAction}>
Expand All @@ -5614,11 +5615,11 @@ describe('ComboBox', function () {
</Provider>
);
}

let {getByTestId, rerender} = render(<Test />);
let input = document.querySelector('input[name=combobox]');
expect(input).toHaveValue('One');

let button = getByTestId('submit');
await act(async () => await user.click(button));
expect(input).toHaveValue('Two');
Expand Down
5 changes: 3 additions & 2 deletions packages/@react-spectrum/menu/test/MenuTrigger.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ describe('MenuTrigger', function () {
it.each`
Name | Component | props
${'MenuTrigger'} | ${MenuTrigger} | ${{onOpenChange, isOpen: true}}
`('$Name supports a controlled open state ', async function ({Component, props}) {
`('$Name supports a controlled open state ', function ({Component, props}) {
let tree = renderComponent(Component, props);
act(() => {jest.runAllTimers();});
expect(onOpenChange).toBeCalledTimes(0);
Expand All @@ -163,7 +163,8 @@ describe('MenuTrigger', function () {
expect(menu).toBeInTheDocument();

let triggerButton = tree.getByText('Menu Button');
await user.click(triggerButton);
fireEvent.mouseDown(triggerButton, {button: 0});
fireEvent.mouseUp(triggerButton, {button: 0});
act(() => {jest.runAllTimers();});

expect(menu).toBeInTheDocument();
Expand Down
19 changes: 5 additions & 14 deletions packages/@react-spectrum/s2/test/Combobox.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/

jest.mock('@react-aria/live-announcer');
import {act, fireEvent, pointerMap, render, setupIntersectionObserverMock, within} from '@react-spectrum/test-utils-internal';
import {act, pointerMap, render, setupIntersectionObserverMock, waitFor, within} from '@react-spectrum/test-utils-internal';
import {announce} from '@react-aria/live-announcer';
import {Button, ComboBox, ComboBoxItem, Content, ContextualHelp, Dialog, DialogTrigger, Heading, Text} from '../src';
import React from 'react';
Expand Down Expand Up @@ -214,6 +214,7 @@ describe('Combobox', () => {
});

it('should close the combobox when clicking outside the combobox on a dialog backdrop', async () => {
let user = userEvent.setup({delay: null, pointerMap});
let tree = render(
<DialogTrigger>
<Button>Open</Button>
Expand Down Expand Up @@ -247,20 +248,10 @@ describe('Combobox', () => {
jest.runAllTimers();
});
let backdrop = document.querySelector('[style*="--visual-viewport-height"]');
// can't use userEvent here for some reason
fireEvent.mouseDown(backdrop!, {button: 0});
fireEvent.mouseUp(backdrop!, {button: 0});
act(() => {
jest.runAllTimers();
});
expect(comboboxTester.listbox).toBeNull();
await user.click(backdrop!);


fireEvent.mouseDown(backdrop!, {button: 0});
fireEvent.mouseUp(backdrop!, {button: 0});
act(() => {
jest.runAllTimers();
});
await waitFor(() => expect(comboboxTester.listbox).toBeNull());
await user.click(backdrop!);
expect(dialogTester.dialog).toBeNull();
});
});
14 changes: 9 additions & 5 deletions packages/react-aria-components/test/Popover.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* governing permissions and limitations under the License.
*/

import {act, pointerMap, render} from '@react-spectrum/test-utils-internal';
import {act, fireEvent, pointerMap, render} from '@react-spectrum/test-utils-internal';
import {Button, Dialog, DialogTrigger, OverlayArrow, Popover, Pressable} from '../';
import React, {useRef} from 'react';
import {UNSAFE_PortalProvider} from '@react-aria/overlays';
Expand Down Expand Up @@ -102,7 +102,7 @@ describe('Popover', () => {
expect(dialog).toHaveAttribute('data-custom', 'true');
});

it('should support being used standalone', async () => {
it('should support being used standalone', () => {
let triggerRef = React.createRef();
let onOpenChange = jest.fn();
let {getByRole} = render(<>
Expand All @@ -115,12 +115,14 @@ describe('Popover', () => {
let dialog = getByRole('dialog');
expect(dialog).toHaveTextContent('A popover');

await user.click(document.body);
// userEvent seems to trigger a double close event
fireEvent.mouseDown(document.body, {button: 0});
fireEvent.mouseUp(document.body, {button: 0});
expect(onOpenChange).toHaveBeenCalledTimes(1);
expect(onOpenChange).toHaveBeenCalledWith(false);
});

it('isOpen and defaultOpen should override state from context', async () => {
it('isOpen and defaultOpen should override state from context', () => {
let onOpenChange = jest.fn();
let {getByRole} = render(<>
<DialogTrigger>
Expand All @@ -134,7 +136,9 @@ describe('Popover', () => {
let dialog = getByRole('dialog');
expect(dialog).toHaveTextContent('A popover');

await user.click(document.body);
// userEvent seems to trigger a double close event
fireEvent.mouseDown(document.body, {button: 0});
fireEvent.mouseUp(document.body, {button: 0});
expect(onOpenChange).toHaveBeenCalledTimes(1);
expect(onOpenChange).toHaveBeenCalledWith(false);
});
Expand Down
Loading