From cf7b32f6ccf15c9f5cba5808509f8670fa51c2f5 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Thu, 6 Aug 2020 18:10:14 -0700 Subject: [PATCH 01/21] Fix keyboard form submission --- packages/@react-aria/interactions/src/usePress.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index 45d498aa722..8e65cdc6038 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -198,7 +198,9 @@ export function usePress(props: PressHookProps): PressResult { let pressProps: HTMLAttributes = { onKeyDown(e) { if (isValidKeyboardEvent(e.nativeEvent)) { - e.preventDefault(); + if (!isSubmitEvent(e.nativeEvent)) { // enter triggers form submit on key down + e.preventDefault(); + } e.stopPropagation(); @@ -249,7 +251,9 @@ export function usePress(props: PressHookProps): PressResult { let onKeyUp = (e: KeyboardEvent) => { if (state.isPressed && isValidKeyboardEvent(e)) { - e.preventDefault(); + if(isSubmitEvent(e)) { // spacebar trigger form submit on key up + e.preventDefault(); + } e.stopPropagation(); state.isPressed = false; @@ -597,6 +601,13 @@ function isValidKeyboardEvent(event: KeyboardEvent): boolean { ); } +function isSubmitEvent(event: KeyboardEvent): boolean { + const {key, target} = event; + const element = target as HTMLElement; + const type = element.getAttribute('type'); + return (key === 'Enter' || key === ' ' || key === 'Spacebar') && type === 'submit'; +} + // Original licensing for the following method can be found in the // NOTICE file in the root directory of this source tree. // See https://github.com/facebook/react/blob/3c713d513195a53788b3f8bb4b70279d68b15bcc/packages/react-interactions/events/src/dom/shared/index.js#L74-L87 From b62208fbfe2dc8e1198ea9a2fef841cbcec55c85 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Thu, 6 Aug 2020 18:19:29 -0700 Subject: [PATCH 02/21] fix lint --- packages/@react-aria/interactions/src/usePress.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index 8e65cdc6038..629645611ce 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -251,7 +251,7 @@ export function usePress(props: PressHookProps): PressResult { let onKeyUp = (e: KeyboardEvent) => { if (state.isPressed && isValidKeyboardEvent(e)) { - if(isSubmitEvent(e)) { // spacebar trigger form submit on key up + if (isSubmitEvent(e)) { // spacebar trigger form submit on key up e.preventDefault(); } e.stopPropagation(); From 0085d46ebb9509042736558b806e990957435066 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Fri, 7 Aug 2020 10:57:58 -0700 Subject: [PATCH 03/21] Update packages/@react-aria/interactions/src/usePress.ts Co-authored-by: Daniel Lu --- packages/@react-aria/interactions/src/usePress.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index 629645611ce..64e63bd8c9e 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -251,7 +251,7 @@ export function usePress(props: PressHookProps): PressResult { let onKeyUp = (e: KeyboardEvent) => { if (state.isPressed && isValidKeyboardEvent(e)) { - if (isSubmitEvent(e)) { // spacebar trigger form submit on key up + if (!isSubmitEvent(e)) { // spacebar trigger form submit on key up e.preventDefault(); } e.stopPropagation(); From 8ee1766cf310e9406fcc933039fb0241b9f339e4 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Tue, 11 Aug 2020 13:44:13 -0700 Subject: [PATCH 04/21] Don't perform a second valid key check --- packages/@react-aria/interactions/src/usePress.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index 64e63bd8c9e..53999d31795 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -600,12 +600,12 @@ function isValidKeyboardEvent(event: KeyboardEvent): boolean { !(role === 'link' && key !== 'Enter') ); } - +// should be run after isValidKeyboardEvent, as that checks the key function isSubmitEvent(event: KeyboardEvent): boolean { - const {key, target} = event; + const {target} = event; const element = target as HTMLElement; const type = element.getAttribute('type'); - return (key === 'Enter' || key === ' ' || key === 'Spacebar') && type === 'submit'; + return type === 'submit'; } // Original licensing for the following method can be found in the From 39abf9eb1bcb90d88bf446649656611c59c52409 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Thu, 13 Aug 2020 13:26:31 -0700 Subject: [PATCH 05/21] These are the only spots I know of so far where we should allow default if requested. I haven't found any others yet. --- packages/@react-aria/button/src/useButton.ts | 5 +++-- packages/@react-aria/interactions/src/usePress.ts | 11 ++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/@react-aria/button/src/useButton.ts b/packages/@react-aria/button/src/useButton.ts index 630905a268c..547a4904964 100644 --- a/packages/@react-aria/button/src/useButton.ts +++ b/packages/@react-aria/button/src/useButton.ts @@ -68,7 +68,8 @@ export function useButton(props: AriaButtonProps, ref: RefObject): onPressChange, onPress, isDisabled, - ref + ref, + allowDefault: type === 'submit' }); let {focusableProps} = useFocusable(props, ref); @@ -101,7 +102,7 @@ export function useToggleButton(props: AriaToggleButtonProps, state: ToggleState ...props, onPress: chain(state.toggle, props.onPress) }, ref); - + return { isPressed, buttonProps: mergeProps(buttonProps, { diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index efd86e78dd3..4d214cadeda 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -25,7 +25,8 @@ export interface PressProps extends PressEvents { /** Whether the target is in a controlled press state (e.g. an overlay it triggers is open). */ isPressed?: boolean, /** Whether the press events should be disabled. */ - isDisabled?: boolean + isDisabled?: boolean, + allowDefault?: boolean } export interface PressHookProps extends PressProps { @@ -92,6 +93,7 @@ export function usePress(props: PressHookProps): PressResult { onPressEnd, onPressUp, isDisabled, + allowDefault = false, isPressed: isPressedProp, // eslint-disable-next-line @typescript-eslint/no-unused-vars ref: _, // Removing `ref` from `domProps` because TypeScript is dumb @@ -199,7 +201,9 @@ export function usePress(props: PressHookProps): PressResult { let pressProps: HTMLAttributes = { onKeyDown(e) { if (isValidKeyboardEvent(e.nativeEvent)) { - if (!isSubmitEvent(e.nativeEvent)) { // enter triggers form submit on key down + // enter triggers form submit on key down + // since enter is a special key for submitting forms and it occurs on key down + if (allowDefault) { e.preventDefault(); } e.stopPropagation(); @@ -252,7 +256,8 @@ export function usePress(props: PressHookProps): PressResult { let onKeyUp = (e: KeyboardEvent) => { if (state.isPressed && isValidKeyboardEvent(e)) { - if (!isSubmitEvent(e)) { // spacebar trigger form submit on key up + // spacebar trigger form submit on key up, this is because it's actually a 'click' + if (allowDefault) { e.preventDefault(); } e.stopPropagation(); From 41daff9d96198babce2982d3912077e6a5169477 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Thu, 13 Aug 2020 13:29:13 -0700 Subject: [PATCH 06/21] Remove unused function --- packages/@react-aria/interactions/src/usePress.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index 4d214cadeda..affa817c0e7 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -610,13 +610,6 @@ function isValidKeyboardEvent(event: KeyboardEvent): boolean { !(role === 'link' && key !== 'Enter') ); } -// should be run after isValidKeyboardEvent, as that checks the key -function isSubmitEvent(event: KeyboardEvent): boolean { - const {target} = event; - const element = target as HTMLElement; - const type = element.getAttribute('type'); - return type === 'submit'; -} function getTouchFromEvent(event: TouchEvent): Touch | null { const {targetTouches} = event; From 1a0547444313aa69d64c35ac2f1a5fb373878917 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Thu, 13 Aug 2020 13:32:23 -0700 Subject: [PATCH 07/21] add a code comment/docs description --- packages/@react-aria/interactions/src/usePress.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index affa817c0e7..9bd8cce3435 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -26,6 +26,7 @@ export interface PressProps extends PressEvents { isPressed?: boolean, /** Whether the press events should be disabled. */ isDisabled?: boolean, + /** If usePress should not preventDefault, which is called by default. Useful for form submission. */ allowDefault?: boolean } From 36255adf30cd2d0202894991f981306d2299e84b Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Thu, 13 Aug 2020 15:15:59 -0700 Subject: [PATCH 08/21] Fix reversed logic --- packages/@react-aria/interactions/src/usePress.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index 9bd8cce3435..5a47e7ecaf2 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -204,7 +204,7 @@ export function usePress(props: PressHookProps): PressResult { if (isValidKeyboardEvent(e.nativeEvent)) { // enter triggers form submit on key down // since enter is a special key for submitting forms and it occurs on key down - if (allowDefault) { + if (!allowDefault) { e.preventDefault(); } e.stopPropagation(); @@ -258,7 +258,7 @@ export function usePress(props: PressHookProps): PressResult { let onKeyUp = (e: KeyboardEvent) => { if (state.isPressed && isValidKeyboardEvent(e)) { // spacebar trigger form submit on key up, this is because it's actually a 'click' - if (allowDefault) { + if (!allowDefault) { e.preventDefault(); } e.stopPropagation(); From 948a7216f7eb55ff791f96b9f2da77f2a842e480 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Fri, 14 Aug 2020 00:00:29 -0700 Subject: [PATCH 09/21] Add tests and handle clicking ourselves --- packages/@react-aria/button/src/useButton.ts | 25 +++++++++-- .../@react-aria/interactions/src/usePress.ts | 11 +---- .../button/test/Button.test.js | 45 ++++++++++++++++++- 3 files changed, 67 insertions(+), 14 deletions(-) diff --git a/packages/@react-aria/button/src/useButton.ts b/packages/@react-aria/button/src/useButton.ts index 547a4904964..69c0ae21c7d 100644 --- a/packages/@react-aria/button/src/useButton.ts +++ b/packages/@react-aria/button/src/useButton.ts @@ -68,13 +68,30 @@ export function useButton(props: AriaButtonProps, ref: RefObject): onPressChange, onPress, isDisabled, - ref, - allowDefault: type === 'submit' + ref }); let {focusableProps} = useFocusable(props, ref); - let buttonProps = mergeProps(focusableProps, pressProps); - buttonProps = mergeProps(buttonProps, filterDOMProps(props, {labelable: true})); + + // enter triggers form submit on key down + // since enter is a special key for submitting forms and it occurs on key down + // spacebar trigger form submit on key up, this is because it's actually a 'click' + let submitProps = {onKeyDown: undefined, onKeyUp: undefined}; + if (type === 'submit') { + // we must use `click` because if we try to use `form.submit` it will bypass the onSubmit handler + // as a result, no one can preventDefault on the form, so instead we use click on the button + submitProps.onKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Enter') { + ref.current?.click(); + } + } + submitProps.onKeyUp = (e: KeyboardEvent) => { + if (e.key === ' ') { + ref.current?.click(); + } + } + } + let buttonProps = mergeProps(submitProps, focusableProps, pressProps, filterDOMProps(props, {labelable: true})); return { isPressed, // Used to indicate press state for visual diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index 5a47e7ecaf2..1f29ab1ceaa 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -202,11 +202,7 @@ export function usePress(props: PressHookProps): PressResult { let pressProps: HTMLAttributes = { onKeyDown(e) { if (isValidKeyboardEvent(e.nativeEvent)) { - // enter triggers form submit on key down - // since enter is a special key for submitting forms and it occurs on key down - if (!allowDefault) { - e.preventDefault(); - } + e.preventDefault(); e.stopPropagation(); @@ -257,10 +253,7 @@ export function usePress(props: PressHookProps): PressResult { let onKeyUp = (e: KeyboardEvent) => { if (state.isPressed && isValidKeyboardEvent(e)) { - // spacebar trigger form submit on key up, this is because it's actually a 'click' - if (!allowDefault) { - e.preventDefault(); - } + e.preventDefault(); e.stopPropagation(); state.isPressed = false; diff --git a/packages/@react-spectrum/button/test/Button.test.js b/packages/@react-spectrum/button/test/Button.test.js index 75dc0d99c4d..fa01407b8ba 100644 --- a/packages/@react-spectrum/button/test/Button.test.js +++ b/packages/@react-spectrum/button/test/Button.test.js @@ -10,11 +10,15 @@ * governing permissions and limitations under the License. */ +import {act, fireEvent, render} from '@testing-library/react'; import {ActionButton, Button, ClearButton, LogicButton} from '../'; -import {fireEvent, render} from '@testing-library/react'; +import {Checkbox, defaultTheme} from '@adobe/react-spectrum'; +import {Form} from '@react-spectrum/form'; +import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {triggerPress} from '@react-spectrum/test-utils'; import V2Button from '@react/react-spectrum/Button'; +import userEvent from "@testing-library/user-event"; /** * Logic Button has no tests outside of this file because functionally it is identical @@ -217,4 +221,43 @@ describe('Button', function () { let button = getByRole('button'); expect(document.activeElement).toBe(button); }); + + + it('submit in form using space', function () { + let onSubmit = jest.fn(e => e.preventDefault()); + let {getByRole} = render( + +
+ An Input + +
+
+ ); + + let button = getByRole('button'); + fireEvent.keyDown(button, {key: ' '}); + fireEvent.keyUp(button, {key: ' '}); + expect(onSubmit).toHaveBeenCalledTimes(1); + }); + + + it('submit in form using enter', function () { + let onSubmit = jest.fn(e => e.preventDefault()); + let {getByRole} = render( + +
+ An Input + +
+
+ ); + + let button = getByRole('button'); + fireEvent.keyDown(button, {key: 'Enter'}); + fireEvent.keyUp(button, {key: 'Enter'}); + expect(onSubmit).toHaveBeenCalledTimes(1); + }); + + + // 'implicit submission' can't be tested https://github.com/testing-library/react-testing-library/issues/487 }); From 54e46087920758de143538ba55ee139cc026a42b Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Fri, 14 Aug 2020 00:11:56 -0700 Subject: [PATCH 10/21] fix lint --- packages/@react-aria/button/src/useButton.ts | 4 ++-- packages/@react-aria/interactions/src/usePress.ts | 5 +---- packages/@react-spectrum/button/test/Button.test.js | 3 +-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/@react-aria/button/src/useButton.ts b/packages/@react-aria/button/src/useButton.ts index 69c0ae21c7d..3e4c5966aea 100644 --- a/packages/@react-aria/button/src/useButton.ts +++ b/packages/@react-aria/button/src/useButton.ts @@ -84,12 +84,12 @@ export function useButton(props: AriaButtonProps, ref: RefObject): if (e.key === 'Enter') { ref.current?.click(); } - } + }; submitProps.onKeyUp = (e: KeyboardEvent) => { if (e.key === ' ') { ref.current?.click(); } - } + }; } let buttonProps = mergeProps(submitProps, focusableProps, pressProps, filterDOMProps(props, {labelable: true})); diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index 1f29ab1ceaa..ac07e4d896c 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -25,9 +25,7 @@ export interface PressProps extends PressEvents { /** Whether the target is in a controlled press state (e.g. an overlay it triggers is open). */ isPressed?: boolean, /** Whether the press events should be disabled. */ - isDisabled?: boolean, - /** If usePress should not preventDefault, which is called by default. Useful for form submission. */ - allowDefault?: boolean + isDisabled?: boolean } export interface PressHookProps extends PressProps { @@ -94,7 +92,6 @@ export function usePress(props: PressHookProps): PressResult { onPressEnd, onPressUp, isDisabled, - allowDefault = false, isPressed: isPressedProp, // eslint-disable-next-line @typescript-eslint/no-unused-vars ref: _, // Removing `ref` from `domProps` because TypeScript is dumb diff --git a/packages/@react-spectrum/button/test/Button.test.js b/packages/@react-spectrum/button/test/Button.test.js index fa01407b8ba..ea27b2c7880 100644 --- a/packages/@react-spectrum/button/test/Button.test.js +++ b/packages/@react-spectrum/button/test/Button.test.js @@ -10,15 +10,14 @@ * governing permissions and limitations under the License. */ -import {act, fireEvent, render} from '@testing-library/react'; import {ActionButton, Button, ClearButton, LogicButton} from '../'; import {Checkbox, defaultTheme} from '@adobe/react-spectrum'; +import {fireEvent, render} from '@testing-library/react'; import {Form} from '@react-spectrum/form'; import {Provider} from '@react-spectrum/provider'; import React from 'react'; import {triggerPress} from '@react-spectrum/test-utils'; import V2Button from '@react/react-spectrum/Button'; -import userEvent from "@testing-library/user-event"; /** * Logic Button has no tests outside of this file because functionally it is identical From 735753892e8c6f6cbddf0d74139dee9471f28531 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Fri, 14 Aug 2020 12:03:25 -0700 Subject: [PATCH 11/21] default preventDefault onclick, but allow a prop that can allow it so that we can submit a form --- packages/@react-aria/button/src/useButton.ts | 5 +++-- packages/@react-aria/interactions/src/usePress.ts | 12 +++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/@react-aria/button/src/useButton.ts b/packages/@react-aria/button/src/useButton.ts index 3e4c5966aea..eb69579d913 100644 --- a/packages/@react-aria/button/src/useButton.ts +++ b/packages/@react-aria/button/src/useButton.ts @@ -68,11 +68,11 @@ export function useButton(props: AriaButtonProps, ref: RefObject): onPressChange, onPress, isDisabled, - ref + ref, + allowClickDefault: type === 'submit' }); let {focusableProps} = useFocusable(props, ref); - // enter triggers form submit on key down // since enter is a special key for submitting forms and it occurs on key down // spacebar trigger form submit on key up, this is because it's actually a 'click' @@ -80,6 +80,7 @@ export function useButton(props: AriaButtonProps, ref: RefObject): if (type === 'submit') { // we must use `click` because if we try to use `form.submit` it will bypass the onSubmit handler // as a result, no one can preventDefault on the form, so instead we use click on the button + // see step 6 https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#firing-submission-events submitProps.onKeyDown = (e: KeyboardEvent) => { if (e.key === 'Enter') { ref.current?.click(); diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index ac07e4d896c..4748c65564d 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -25,7 +25,12 @@ export interface PressProps extends PressEvents { /** Whether the target is in a controlled press state (e.g. an overlay it triggers is open). */ isPressed?: boolean, /** Whether the press events should be disabled. */ - isDisabled?: boolean + isDisabled?: boolean, + /** + * Whether to allow onclick default behavior. + * @default false + **/ + allowClickDefault?: boolean } export interface PressHookProps extends PressProps { @@ -95,6 +100,7 @@ export function usePress(props: PressHookProps): PressResult { isPressed: isPressedProp, // eslint-disable-next-line @typescript-eslint/no-unused-vars ref: _, // Removing `ref` from `domProps` because TypeScript is dumb + allowClickDefault = false, ...domProps } = usePressResponderContext(props); @@ -224,10 +230,10 @@ export function usePress(props: PressHookProps): PressResult { }, onClick(e) { if (e && e.button === 0) { - e.stopPropagation(); - if (isDisabled) { + if (!allowClickDefault) { e.preventDefault(); } + e.stopPropagation(); // If triggered from a screen reader or by using element.click(), // trigger as if it were a keyboard click. From 7719fc1848a4212fd9d2d08207a571f73547fcdb Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Fri, 11 Sep 2020 10:45:25 -0700 Subject: [PATCH 12/21] fix useCheckboxGroup test --- .../checkbox/test/useCheckboxGroup.test.tsx | 63 ++++++++++++------- .../@react-aria/interactions/src/usePress.ts | 2 +- packages/@react-aria/toggle/src/useToggle.ts | 4 +- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx b/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx index 8fd73c4ae72..56e457132a0 100644 --- a/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx +++ b/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx @@ -16,12 +16,13 @@ import {CheckboxGroupState, useCheckboxGroupState} from '@react-stately/checkbox import React, {useRef} from 'react'; import {useCheckboxGroup, useCheckboxGroupItem} from '../'; import userEvent from '@testing-library/user-event'; +import {group} from "@actions/core"; function Checkbox({checkboxGroupState, ...props}: AriaCheckboxProps & { checkboxGroupState: CheckboxGroupState }) { const ref = useRef(); const {children} = props; const {inputProps} = useCheckboxGroupItem(props, checkboxGroupState, ref); - return ; + return ; } function CheckboxGroup({groupProps, checkboxProps}: {groupProps: AriaCheckboxGroupProps, checkboxProps: AriaCheckboxProps[]}) { @@ -63,18 +64,18 @@ describe('useCheckboxGroup', () => { expect(checkboxes[1].value).toBe('cats'); expect(checkboxes[2].value).toBe('dragons'); - expect(checkboxes[0].checked).toBe(false); - expect(checkboxes[1].checked).toBe(false); - expect(checkboxes[2].checked).toBe(false); + expect(checkboxes[0].checked).toBeFalsy(); + expect(checkboxes[1].checked).toBeFalsy(); + expect(checkboxes[2].checked).toBeFalsy(); let dragons = getByLabelText('Dragons'); act(() => {userEvent.click(dragons);}); expect(onChangeSpy).toHaveBeenCalledTimes(1); expect(onChangeSpy).toHaveBeenCalledWith(['dragons']); - expect(checkboxes[0].checked).toBe(false); - expect(checkboxes[1].checked).toBe(false); - expect(checkboxes[2].checked).toBe(true); + expect(checkboxes[0].checked).toBeFalsy(); + expect(checkboxes[1].checked).toBeFalsy(); + expect(checkboxes[2].checked).toBeTruthy(); }); it('can have a default value', () => { @@ -159,13 +160,15 @@ describe('useCheckboxGroup', () => { }); it('sets aria-disabled and makes checkboxes disabled when isDisabled is true', () => { - let {getAllByRole, getByRole} = render( + let groupOnChangeSpy = jest.fn(); + let checkboxOnChangeSpy = jest.fn(); + let {getAllByRole, getByRole, getByLabelText} = render( ); @@ -174,8 +177,15 @@ describe('useCheckboxGroup', () => { let checkboxes = getAllByRole('checkbox') as HTMLInputElement[]; expect(checkboxes[0]).toHaveAttribute('disabled'); - expect(checkboxes[0]).toHaveAttribute('disabled'); - expect(checkboxes[0]).toHaveAttribute('disabled'); + expect(checkboxes[1]).toHaveAttribute('disabled'); + expect(checkboxes[2]).toHaveAttribute('disabled'); + let dragons = getByLabelText('Dragons'); + + act(() => {userEvent.click(dragons);}); + + expect(groupOnChangeSpy).toHaveBeenCalledTimes(0); + expect(checkboxOnChangeSpy).toHaveBeenCalledTimes(0); + expect(checkboxes[2].checked).toBeFalsy(); }); it('doesn\'t set aria-disabled or make checkboxes disabled by default', () => { @@ -194,8 +204,8 @@ describe('useCheckboxGroup', () => { let checkboxes = getAllByRole('checkbox') as HTMLInputElement[]; expect(checkboxes[0]).not.toHaveAttribute('disabled'); - expect(checkboxes[0]).not.toHaveAttribute('disabled'); - expect(checkboxes[0]).not.toHaveAttribute('disabled'); + expect(checkboxes[1]).not.toHaveAttribute('disabled'); + expect(checkboxes[2]).not.toHaveAttribute('disabled'); }); it('doesn\'t set aria-disabled or make checkboxes disabled when isDisabled is false', () => { @@ -214,25 +224,34 @@ describe('useCheckboxGroup', () => { let checkboxes = getAllByRole('checkbox') as HTMLInputElement[]; expect(checkboxes[0]).not.toHaveAttribute('disabled'); - expect(checkboxes[0]).not.toHaveAttribute('disabled'); - expect(checkboxes[0]).not.toHaveAttribute('disabled'); + expect(checkboxes[1]).not.toHaveAttribute('disabled'); + expect(checkboxes[2]).not.toHaveAttribute('disabled'); }); it('sets readOnly on each checkbox', () => { - let {getAllByRole} = render( + let groupOnChangeSpy = jest.fn(); + let checkboxOnChangeSpy = jest.fn(); + let {getAllByRole, getByLabelText} = render( ); let checkboxes = getAllByRole('checkbox') as HTMLInputElement[]; expect(checkboxes[0]).toHaveAttribute('readonly'); - expect(checkboxes[0]).toHaveAttribute('readonly'); - expect(checkboxes[0]).toHaveAttribute('readonly'); + expect(checkboxes[1]).toHaveAttribute('readonly'); + expect(checkboxes[2]).toHaveAttribute('readonly'); + let dragons = getByLabelText('Dragons'); + + act(() => {userEvent.click(dragons);}); + + expect(groupOnChangeSpy).toHaveBeenCalledTimes(0); + expect(checkboxOnChangeSpy).toHaveBeenCalledTimes(0); + expect(checkboxes[2].checked).toBeFalsy(); }); it('should not update state for readonly checkbox', () => { @@ -255,6 +274,6 @@ describe('useCheckboxGroup', () => { expect(groupOnChangeSpy).toHaveBeenCalledTimes(0); expect(checkboxOnChangeSpy).toHaveBeenCalledTimes(0); - expect(checkboxes[2].checked).toBe(false); + expect(checkboxes[2].checked).toBeFalsy(); }); }); diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index 4748c65564d..7779e1a0804 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -230,7 +230,7 @@ export function usePress(props: PressHookProps): PressResult { }, onClick(e) { if (e && e.button === 0) { - if (!allowClickDefault) { + if (!allowClickDefault || isDisabled) { e.preventDefault(); } e.stopPropagation(); diff --git a/packages/@react-aria/toggle/src/useToggle.ts b/packages/@react-aria/toggle/src/useToggle.ts index 743dfee410c..112d83a6c1c 100644 --- a/packages/@react-aria/toggle/src/useToggle.ts +++ b/packages/@react-aria/toggle/src/useToggle.ts @@ -55,7 +55,9 @@ export function useToggle(props: AriaToggleProps, state: ToggleState, ref: RefOb // This handles focusing the input on pointer down, which Safari does not do by default. let {pressProps} = usePress({ - isDisabled + isDisabled, + // something seems off in the useCheckboxGroup test, this worked everywhere else without needing allowClickDefault + allowClickDefault: true }); let {focusableProps} = useFocusable(props, ref); From 513a508095c749bac6a5332a8e6b2ce572735a54 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Fri, 11 Sep 2020 14:38:31 -0700 Subject: [PATCH 13/21] Add another test and explain why the allowClickDefault is needed --- .../checkbox/test/useCheckboxGroup.test.tsx | 1 + packages/@react-aria/toggle/src/useToggle.ts | 4 +++- .../@react-spectrum/checkbox/test/Checkbox.test.js | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx b/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx index 56e457132a0..7342b4f0228 100644 --- a/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx +++ b/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx @@ -245,6 +245,7 @@ describe('useCheckboxGroup', () => { expect(checkboxes[0]).toHaveAttribute('readonly'); expect(checkboxes[1]).toHaveAttribute('readonly'); expect(checkboxes[2]).toHaveAttribute('readonly'); + expect(checkboxes[2].checked).toBeFalsy(); let dragons = getByLabelText('Dragons'); act(() => {userEvent.click(dragons);}); diff --git a/packages/@react-aria/toggle/src/useToggle.ts b/packages/@react-aria/toggle/src/useToggle.ts index 112d83a6c1c..ce76e86dd38 100644 --- a/packages/@react-aria/toggle/src/useToggle.ts +++ b/packages/@react-aria/toggle/src/useToggle.ts @@ -56,7 +56,9 @@ export function useToggle(props: AriaToggleProps, state: ToggleState, ref: RefOb // This handles focusing the input on pointer down, which Safari does not do by default. let {pressProps} = usePress({ isDisabled, - // something seems off in the useCheckboxGroup test, this worked everywhere else without needing allowClickDefault + // This is needed for checkboxes otherwise the input property 'checked' will get out of sync with + // the react prop (attribute) 'checked'. It worked in the integration test without it because FocusRing caused an + // extra render that put the values back in sync. allowClickDefault: true }); diff --git a/packages/@react-spectrum/checkbox/test/Checkbox.test.js b/packages/@react-spectrum/checkbox/test/Checkbox.test.js index 24071372138..3d7d754bab1 100644 --- a/packages/@react-spectrum/checkbox/test/Checkbox.test.js +++ b/packages/@react-spectrum/checkbox/test/Checkbox.test.js @@ -250,4 +250,18 @@ describe('Checkbox', function () { expect(checkbox.checked).toBeTruthy(); expect(onChangeSpy).not.toHaveBeenCalled(); }); + + it.each` + Name | Component | props + ${'Checkbox'} | ${Checkbox} | ${{onChange: onChangeSpy, isReadOnly: true}} + `('$Name supports uncontrolled readOnly', function ({Component, props}) { + let {getByLabelText} = render(Click Me); + + let checkbox = getByLabelText('Click Me'); + expect(checkbox.checked).toBeFalsy(); + + act(() => {userEvent.click(checkbox);}); + expect(checkbox.checked).toBeFalsy(); + expect(onChangeSpy).not.toHaveBeenCalled(); + }); }); From af106c1c2ae15d3cd8abff3c30d789e655db221c Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Fri, 11 Sep 2020 14:53:41 -0700 Subject: [PATCH 14/21] fix lint --- packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx b/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx index 7342b4f0228..72e20b23361 100644 --- a/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx +++ b/packages/@react-aria/checkbox/test/useCheckboxGroup.test.tsx @@ -16,7 +16,6 @@ import {CheckboxGroupState, useCheckboxGroupState} from '@react-stately/checkbox import React, {useRef} from 'react'; import {useCheckboxGroup, useCheckboxGroupItem} from '../'; import userEvent from '@testing-library/user-event'; -import {group} from "@actions/core"; function Checkbox({checkboxGroupState, ...props}: AriaCheckboxProps & { checkboxGroupState: CheckboxGroupState }) { const ref = useRef(); From c88543c9232c835b7661bc62371c5fd37b84570a Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Wed, 7 Apr 2021 16:40:07 -0700 Subject: [PATCH 15/21] Remove potentially extraneous code fix merge --- packages/@react-aria/button/src/useButton.ts | 3 +-- .../@react-aria/checkbox/test/useCheckboxGroup.test.tsx | 2 +- packages/@react-aria/interactions/src/usePress.ts | 8 +------- packages/@react-aria/toggle/src/useToggle.ts | 8 +------- packages/@react-spectrum/checkbox/test/Checkbox.test.js | 2 +- packages/@react-spectrum/form/stories/Form.stories.tsx | 2 +- 6 files changed, 6 insertions(+), 19 deletions(-) diff --git a/packages/@react-aria/button/src/useButton.ts b/packages/@react-aria/button/src/useButton.ts index 6d968603e2e..4d07cbf65b9 100644 --- a/packages/@react-aria/button/src/useButton.ts +++ b/packages/@react-aria/button/src/useButton.ts @@ -84,8 +84,7 @@ export function useButton(props: AriaButtonProps, ref: RefObject(null); @@ -252,7 +246,7 @@ export function usePress(props: PressHookProps): PressResult { }, onClick(e) { if (e && e.button === 0) { - if (!allowClickDefault || isDisabled) { + if (isDisabled) { e.preventDefault(); } e.stopPropagation(); diff --git a/packages/@react-aria/toggle/src/useToggle.ts b/packages/@react-aria/toggle/src/useToggle.ts index ddbf9df7d1e..11849e92a6e 100644 --- a/packages/@react-aria/toggle/src/useToggle.ts +++ b/packages/@react-aria/toggle/src/useToggle.ts @@ -54,13 +54,7 @@ export function useToggle(props: AriaToggleProps, state: ToggleState, ref: RefOb } // This handles focusing the input on pointer down, which Safari does not do by default. - let {pressProps} = usePress({ - isDisabled, - // This is needed for checkboxes otherwise the input property 'checked' will get out of sync with - // the react prop (attribute) 'checked'. It worked in the integration test without it because FocusRing caused an - // extra render that put the values back in sync. - allowClickDefault: true - }); + let {pressProps} = usePress({isDisabled}); let {focusableProps} = useFocusable(props, ref); let interactions = mergeProps(pressProps, focusableProps); diff --git a/packages/@react-spectrum/checkbox/test/Checkbox.test.js b/packages/@react-spectrum/checkbox/test/Checkbox.test.js index 3d11b84da89..9688260d901 100644 --- a/packages/@react-spectrum/checkbox/test/Checkbox.test.js +++ b/packages/@react-spectrum/checkbox/test/Checkbox.test.js @@ -10,9 +10,9 @@ * governing permissions and limitations under the License. */ +import {act, render} from '@testing-library/react'; import {Checkbox} from '../'; import React from 'react'; -import {render} from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import V2Checkbox from '@react/react-spectrum/Checkbox'; diff --git a/packages/@react-spectrum/form/stories/Form.stories.tsx b/packages/@react-spectrum/form/stories/Form.stories.tsx index 1356d682144..d626c24466d 100644 --- a/packages/@react-spectrum/form/stories/Form.stories.tsx +++ b/packages/@react-spectrum/form/stories/Form.stories.tsx @@ -156,7 +156,7 @@ function FormWithControls(props: any = {}) { return ( - Prevent Default onSubmit + Prevent Default onSubmit
{ action('onSubmit')(e); From 64f7a63393710a83633164949209182d1e898427 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Mon, 26 Apr 2021 10:39:49 -0700 Subject: [PATCH 16/21] reduce number of changed lines --- packages/@react-aria/interactions/src/usePress.ts | 2 +- packages/@react-aria/toggle/src/useToggle.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index 62f2695ea24..aab077a3445 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -236,10 +236,10 @@ export function usePress(props: PressHookProps): PressResult { }, onClick(e) { if (e && e.button === 0) { + e.stopPropagation(); if (isDisabled) { e.preventDefault(); } - e.stopPropagation(); // If triggered from a screen reader or by using element.click(), // trigger as if it were a keyboard click. diff --git a/packages/@react-aria/toggle/src/useToggle.ts b/packages/@react-aria/toggle/src/useToggle.ts index 11849e92a6e..4b43e34721f 100644 --- a/packages/@react-aria/toggle/src/useToggle.ts +++ b/packages/@react-aria/toggle/src/useToggle.ts @@ -54,7 +54,9 @@ export function useToggle(props: AriaToggleProps, state: ToggleState, ref: RefOb } // This handles focusing the input on pointer down, which Safari does not do by default. - let {pressProps} = usePress({isDisabled}); + let {pressProps} = usePress({ + isDisabled + }); let {focusableProps} = useFocusable(props, ref); let interactions = mergeProps(pressProps, focusableProps); From 87b372221dfacfd135837f638d56ca26513cd1c4 Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Fri, 25 Jun 2021 17:41:37 -0700 Subject: [PATCH 17/21] [WIP] - Make form submission fix in usePress instead of in useButton (#1997) Make fix in usePress instead of in useButton --- packages/@react-aria/button/src/useButton.ts | 21 +------ .../@react-aria/interactions/src/usePress.ts | 12 +++- .../button/test/Button.test.js | 60 ++++++++++++++----- 3 files changed, 55 insertions(+), 38 deletions(-) diff --git a/packages/@react-aria/button/src/useButton.ts b/packages/@react-aria/button/src/useButton.ts index d748dc94886..ae43cc0a53b 100644 --- a/packages/@react-aria/button/src/useButton.ts +++ b/packages/@react-aria/button/src/useButton.ts @@ -93,26 +93,7 @@ export function useButton(props: AriaButtonProps, ref: RefObject { - if (e.key === 'Enter') { - ref.current?.click(); - } - }; - submitProps.onKeyUp = (e: KeyboardEvent) => { - if (e.key === ' ') { - ref.current?.click(); - } - }; - } - let buttonProps = mergeProps(submitProps, focusableProps, pressProps, filterDOMProps(props, {labelable: true})); + let buttonProps = mergeProps(focusableProps, pressProps, filterDOMProps(props, {labelable: true})); return { isPressed, // Used to indicate press state for visual diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index 1cb493fc51e..baf80f10d5a 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -211,7 +211,9 @@ export function usePress(props: PressHookProps): PressResult { let pressProps: HTMLAttributes = { onKeyDown(e) { if (isValidKeyboardEvent(e.nativeEvent)) { - e.preventDefault(); + if (shouldPreventDefaultKeyboard(e.target as Element)) { + e.preventDefault(); + } e.stopPropagation(); @@ -262,7 +264,9 @@ export function usePress(props: PressHookProps): PressResult { let onKeyUp = (e: KeyboardEvent) => { if (state.isPressed && isValidKeyboardEvent(e)) { - e.preventDefault(); + if (shouldPreventDefaultKeyboard(e.target as Element)) { + e.preventDefault(); + } e.stopPropagation(); state.isPressed = false; @@ -666,6 +670,10 @@ function shouldPreventDefault(target: Element) { return !target.closest('[draggable="true"]'); } +function shouldPreventDefaultKeyboard(target: Element) { + return target.getAttribute('type') !== 'submit'; +} + function isVirtualPointerEvent(event: PointerEvent) { // If the pointer size is zero, then we assume it's from a screen reader. return event.width === 0 && event.height === 0; diff --git a/packages/@react-spectrum/button/test/Button.test.js b/packages/@react-spectrum/button/test/Button.test.js index d1dec40e97d..66f67cbe8e1 100644 --- a/packages/@react-spectrum/button/test/Button.test.js +++ b/packages/@react-spectrum/button/test/Button.test.js @@ -204,13 +204,6 @@ describe('Button', function () { expect(onPressSpy).not.toHaveBeenCalled(); }); - // when a user uses the keyboard and keyDowns 'enter' or 'space' on a button, it fires an onclick. - // when code dispatches a keyDown for 'enter' or 'space', it does not fire onclick - // this means that it's impossible for us to write a test for the 'button' elementType for keyDown 'enter' or 'space' - // see https://jsfiddle.net/snowystinger/z6vmrw4d/1/ - // it's also extraneous to test with 'enter' or 'space' on a button because it'd just be testing - // the spec https://www.w3.org/TR/WCAG20-TECHS/SCR35.html - it.each` Name | Component ${'ActionButton'} | ${ActionButton} @@ -224,39 +217,74 @@ describe('Button', function () { }); - it('submit in form using space', function () { - let onSubmit = jest.fn(e => e.preventDefault()); + it('prevents default for non-submit types', function () { + let eventDown; + let eventUp; + let btn = React.createRef(); let {getByRole} = render( - + An Input - + ); + // need to attach event listeners after instead of directly on Button because the ones directly on Button + // will fire before the usePress ones + btn.current.UNSAFE_getDOMNode().addEventListener('keydown', e => eventDown = e); + btn.current.UNSAFE_getDOMNode().addEventListener('keyup', e => eventUp = e); let button = getByRole('button'); + fireEvent.keyDown(button, {key: 'Enter'}); + fireEvent.keyUp(button, {key: 'Enter'}); + expect(eventDown.defaultPrevented).toBeTruthy(); + expect(eventUp.defaultPrevented).toBeTruthy(); + fireEvent.keyDown(button, {key: ' '}); fireEvent.keyUp(button, {key: ' '}); - expect(onSubmit).toHaveBeenCalledTimes(1); + expect(eventDown.defaultPrevented).toBeTruthy(); + expect(eventUp.defaultPrevented).toBeTruthy(); }); + // we only need to test that we allow the browser to do the default thing when space or enter is pressed on a submit button + // space submits on key up and is actually a click + it('submit in form using space', function () { + let eventUp; + let btn = React.createRef(); + let {getByRole} = render( + +
+ An Input + +
+
+ ); + btn.current.UNSAFE_getDOMNode().addEventListener('keyup', e => eventUp = e); + + let button = getByRole('button'); + fireEvent.keyDown(button, {key: ' '}); + fireEvent.keyUp(button, {key: ' '}); + expect(eventUp.defaultPrevented).toBeFalsy(); + }); + // enter submits on keydown it('submit in form using enter', function () { - let onSubmit = jest.fn(e => e.preventDefault()); + let eventDown; + let btn = React.createRef(); let {getByRole} = render( -
+ An Input - +
); + btn.current.UNSAFE_getDOMNode().addEventListener('keydown', e => eventDown = e); let button = getByRole('button'); fireEvent.keyDown(button, {key: 'Enter'}); fireEvent.keyUp(button, {key: 'Enter'}); - expect(onSubmit).toHaveBeenCalledTimes(1); + expect(eventDown.defaultPrevented).toBeFalsy(); }); From 3fef03a4ef78e5f5bbaf13a53ed6eee31f8dfce2 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Sat, 26 Jun 2021 13:46:55 -0700 Subject: [PATCH 18/21] Add check for element type --- packages/@react-aria/interactions/src/usePress.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index baf80f10d5a..9bbef32ba7a 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -671,7 +671,7 @@ function shouldPreventDefault(target: Element) { } function shouldPreventDefaultKeyboard(target: Element) { - return target.getAttribute('type') !== 'submit'; + return !((target.tagName === 'INPUT' || target.tagName === 'BUTTON') && target.getAttribute('type') === 'submit'); } function isVirtualPointerEvent(event: PointerEvent) { From 1e1d03dd139a2337fd03e7deb7450e98cc66f82a Mon Sep 17 00:00:00 2001 From: Robert Snow Date: Tue, 29 Jun 2021 18:27:25 -0700 Subject: [PATCH 19/21] fix default buttons Get the calculated property, not the attribute, buttons default to type submit --- packages/@react-aria/interactions/src/usePress.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index 1b0769eee2e..07708b6950c 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -718,7 +718,7 @@ function shouldPreventDefault(target: Element) { } function shouldPreventDefaultKeyboard(target: Element) { - return !((target.tagName === 'INPUT' || target.tagName === 'BUTTON') && target.getAttribute('type') === 'submit'); + return !((target.tagName === 'INPUT' || target.tagName === 'BUTTON') && target.type === 'submit'); } function isVirtualPointerEvent(event: PointerEvent) { From c2432612ad794c2792f24cbfb10572e827abbba1 Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Tue, 29 Jun 2021 18:51:30 -0700 Subject: [PATCH 20/21] add node version to cache since icons depends on it --- .circleci/config.yml | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4bc3bc333e0..407093f04be 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,9 +34,9 @@ jobs: - checkout - restore_cache: keys: - - rsp-yarn-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}-{{ checksum "yarn.lock" }} - - rsp-yarn-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}- - - rsp-yarn-{{ .Environment.CACHE_VERSION }}- + - rsp-yarn-1222-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}-{{ checksum "yarn.lock" }} + - rsp-yarn-1222-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}- + - rsp-yarn-1222-{{ .Environment.CACHE_VERSION }}- - run: name: Write npmrc @@ -53,12 +53,12 @@ jobs: - save_cache: paths: - ~/.cache/yarn - key: rsp-yarn-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}-{{ checksum "yarn.lock" }} + key: rsp-yarn-1222-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}-{{ checksum "yarn.lock" }} - save_cache: paths: - ~/react-spectrum - key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} install-17: executor: rsp-large @@ -66,9 +66,9 @@ jobs: - checkout - restore_cache: keys: - - rsp-yarn-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}-{{ checksum "yarn.lock" }} - - rsp-yarn-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}- - - rsp-yarn-{{ .Environment.CACHE_VERSION }}- + - rsp-yarn-1222-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}-{{ checksum "yarn.lock" }} + - rsp-yarn-1222-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}- + - rsp-yarn-1222-{{ .Environment.CACHE_VERSION }}- - run: name: build @@ -78,13 +78,13 @@ jobs: - save_cache: paths: - ~/react-spectrum - key: react-spectrum17-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum17-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} test-ssr: executor: rsp-xlarge steps: - restore_cache: - key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: test ssr @@ -95,7 +95,7 @@ jobs: executor: rsp-xlarge steps: - restore_cache: - key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: mkdir ~/junit @@ -120,7 +120,7 @@ jobs: executor: rsp-xlarge steps: - restore_cache: - key: react-spectrum17-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum17-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: test ssr @@ -132,7 +132,7 @@ jobs: executor: rsp-xlarge steps: - restore_cache: - key: react-spectrum17-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum17-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: mkdir ~/junit @@ -155,7 +155,7 @@ jobs: executor: rsp steps: - restore_cache: - key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: lint @@ -165,7 +165,7 @@ jobs: executor: rsp-large steps: - restore_cache: - key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: build storybook @@ -180,7 +180,7 @@ jobs: executor: rsp-large steps: - restore_cache: - key: react-spectrum17-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum17-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: build storybook-17 @@ -195,7 +195,7 @@ jobs: executor: rsp-xlarge steps: - restore_cache: - key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: build docs @@ -210,7 +210,7 @@ jobs: executor: rsp-xlarge steps: - restore_cache: - key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: build docs @@ -247,7 +247,7 @@ jobs: steps: - checkout - restore_cache: - key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: comment on pr @@ -260,7 +260,7 @@ jobs: executor: rsp-xlarge steps: - restore_cache: - key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: Authenticate with npm command: | From a0ee5f14ebf7d01afc2246845843a933ad547e6e Mon Sep 17 00:00:00 2001 From: Rob Snow Date: Tue, 29 Jun 2021 19:02:18 -0700 Subject: [PATCH 21/21] fix typescript and remove cache busting --- .circleci/config.yml | 40 +++++++++---------- .../@react-aria/interactions/src/usePress.ts | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 407093f04be..4bc3bc333e0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,9 +34,9 @@ jobs: - checkout - restore_cache: keys: - - rsp-yarn-1222-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}-{{ checksum "yarn.lock" }} - - rsp-yarn-1222-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}- - - rsp-yarn-1222-{{ .Environment.CACHE_VERSION }}- + - rsp-yarn-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}-{{ checksum "yarn.lock" }} + - rsp-yarn-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}- + - rsp-yarn-{{ .Environment.CACHE_VERSION }}- - run: name: Write npmrc @@ -53,12 +53,12 @@ jobs: - save_cache: paths: - ~/.cache/yarn - key: rsp-yarn-1222-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}-{{ checksum "yarn.lock" }} + key: rsp-yarn-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}-{{ checksum "yarn.lock" }} - save_cache: paths: - ~/react-spectrum - key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} install-17: executor: rsp-large @@ -66,9 +66,9 @@ jobs: - checkout - restore_cache: keys: - - rsp-yarn-1222-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}-{{ checksum "yarn.lock" }} - - rsp-yarn-1222-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}- - - rsp-yarn-1222-{{ .Environment.CACHE_VERSION }}- + - rsp-yarn-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}-{{ checksum "yarn.lock" }} + - rsp-yarn-{{ .Environment.CACHE_VERSION }}-{{ .Branch }}- + - rsp-yarn-{{ .Environment.CACHE_VERSION }}- - run: name: build @@ -78,13 +78,13 @@ jobs: - save_cache: paths: - ~/react-spectrum - key: react-spectrum17-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum17-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} test-ssr: executor: rsp-xlarge steps: - restore_cache: - key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: test ssr @@ -95,7 +95,7 @@ jobs: executor: rsp-xlarge steps: - restore_cache: - key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: mkdir ~/junit @@ -120,7 +120,7 @@ jobs: executor: rsp-xlarge steps: - restore_cache: - key: react-spectrum17-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum17-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: test ssr @@ -132,7 +132,7 @@ jobs: executor: rsp-xlarge steps: - restore_cache: - key: react-spectrum17-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum17-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: mkdir ~/junit @@ -155,7 +155,7 @@ jobs: executor: rsp steps: - restore_cache: - key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: lint @@ -165,7 +165,7 @@ jobs: executor: rsp-large steps: - restore_cache: - key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: build storybook @@ -180,7 +180,7 @@ jobs: executor: rsp-large steps: - restore_cache: - key: react-spectrum17-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum17-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: build storybook-17 @@ -195,7 +195,7 @@ jobs: executor: rsp-xlarge steps: - restore_cache: - key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: build docs @@ -210,7 +210,7 @@ jobs: executor: rsp-xlarge steps: - restore_cache: - key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: build docs @@ -247,7 +247,7 @@ jobs: steps: - checkout - restore_cache: - key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: comment on pr @@ -260,7 +260,7 @@ jobs: executor: rsp-xlarge steps: - restore_cache: - key: react-spectrum-1222-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} + key: react-spectrum-{{ .Environment.CACHE_VERSION }}-{{ .Environment.CIRCLE_SHA1 }} - run: name: Authenticate with npm command: | diff --git a/packages/@react-aria/interactions/src/usePress.ts b/packages/@react-aria/interactions/src/usePress.ts index 07708b6950c..4de26bcd9e7 100644 --- a/packages/@react-aria/interactions/src/usePress.ts +++ b/packages/@react-aria/interactions/src/usePress.ts @@ -718,7 +718,7 @@ function shouldPreventDefault(target: Element) { } function shouldPreventDefaultKeyboard(target: Element) { - return !((target.tagName === 'INPUT' || target.tagName === 'BUTTON') && target.type === 'submit'); + return !((target.tagName === 'INPUT' || target.tagName === 'BUTTON') && (target as HTMLButtonElement | HTMLInputElement).type === 'submit'); } function isVirtualPointerEvent(event: PointerEvent) {