From 637f1f89057fe7197f8cb06dfb2f1fddbc64773e Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Wed, 28 Dec 2022 14:59:58 -0600 Subject: [PATCH 01/10] Better types + tests for useKeyProps --- .../src/{ => __tests__}/events.types.test.ts | 4 +- .../src/__tests__/useKeyProps.test.tsx | 10 ++++ .../src/useKeyProps.macos.ts | 4 +- .../interactive-hooks/src/useKeyProps.ts | 54 ++++++------------- .../src/useKeyProps.types.macos.ts | 33 ++++++++++++ .../src/useKeyProps.types.ts | 12 +++++ .../src/useKeyProps.types.win32.ts | 12 +++++ .../src/useKeyProps.types.windows.ts | 12 +++++ .../src/useKeyProps.win32.ts | 4 +- .../src/useKeyProps.windows.ts | 4 +- 10 files changed, 102 insertions(+), 47 deletions(-) rename packages/utils/interactive-hooks/src/{ => __tests__}/events.types.test.ts (95%) create mode 100644 packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx create mode 100644 packages/utils/interactive-hooks/src/useKeyProps.types.macos.ts create mode 100644 packages/utils/interactive-hooks/src/useKeyProps.types.ts create mode 100644 packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts create mode 100644 packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts diff --git a/packages/utils/interactive-hooks/src/events.types.test.ts b/packages/utils/interactive-hooks/src/__tests__/events.types.test.ts similarity index 95% rename from packages/utils/interactive-hooks/src/events.types.test.ts rename to packages/utils/interactive-hooks/src/__tests__/events.types.test.ts index f26fac85ee..1ff886ff1f 100644 --- a/packages/utils/interactive-hooks/src/events.types.test.ts +++ b/packages/utils/interactive-hooks/src/__tests__/events.types.test.ts @@ -1,6 +1,6 @@ import { AccessibilityActionEvent, GestureResponderEvent } from 'react-native'; -import { KeyPressEvent } from './Pressability/CoreEventTypes'; -import { isAccessibilityActionEvent, isGestureResponderEvent, isKeyPressEvent } from './events.types'; +import { KeyPressEvent } from '../Pressability/CoreEventTypes'; +import { isAccessibilityActionEvent, isGestureResponderEvent, isKeyPressEvent } from '../events.types'; const createMockEvent = (nativeEvent) => { return { diff --git a/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx b/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx new file mode 100644 index 0000000000..b05e7a8f00 --- /dev/null +++ b/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx @@ -0,0 +1,10 @@ +import { useKeyProps } from '../useKeyProps'; + +it('useKeyProps is memoized', () => { + const dummyFunction = () => { + console.log('dummy'); + }; + const onKeyUpProps1 = useKeyProps(dummyFunction, ' ', 'Enter'); + const onKeyUpProps2 = useKeyProps(dummyFunction, ' ', 'Enter'); + expect(onKeyUpProps1 === onKeyUpProps2).toBeTruthy(); +}); diff --git a/packages/utils/interactive-hooks/src/useKeyProps.macos.ts b/packages/utils/interactive-hooks/src/useKeyProps.macos.ts index cc8a38649b..2a2a8e0833 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.macos.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.macos.ts @@ -1,4 +1,4 @@ -import { KeyCallback, KeyPressProps } from './useKeyProps'; +import { KeyCallback, KeyPressProps } from './useKeyProps.types'; import { KeyPressEvent } from './Pressability/CoreEventTypes'; import { memoize } from '@fluentui-react-native/memo-cache'; import { isModifierKey } from './isModifierKey'; @@ -19,7 +19,7 @@ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { args.stopPropagation(); } }, - [userCallback, ...keys], + [keys, userCallback], ); return onKeyEvent; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.ts b/packages/utils/interactive-hooks/src/useKeyProps.ts index f65ae8e8d6..25d4fe3412 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.ts @@ -1,60 +1,36 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import { KeyPressEvent } from './Pressability/CoreEventTypes'; -import { IHandledKeyboardEvent } from '@office-iss/react-native-win32'; +import { KeyCallback, KeyPressProps } from './useKeyProps.types'; +import { memoize } from '@fluentui-react-native/memo-cache'; -export type KeyCallback = (args?: KeyPressEvent) => void; - -export type KeyPressProps = { - onKeyDown?: KeyCallback; - validKeysDown?: string[]; // macOS - keyDownEvents?: IHandledKeyboardEvent[]; // win32 - onKeyUp?: KeyCallback; - validKeysUp?: string[]; // macOS - keyUpEvents?: IHandledKeyboardEvent[]; // win32 -}; - -// eslint-disable-next-line @typescript-eslint/no-empty-function -const noOp = () => {}; - -/** - * Re-usable hook for an onKeyDown event. - * @param userCallback The function you want to be called once the key has been activated on key up - * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns onKeyEvent() - Callback to determine if key was pressed, if so, call userCallback - * @deprecated use the hook `useKeyProps` instead - */ -export function useKeyCallback(_userCallback?: KeyCallback, ..._keys: string[]) { - return noOp; +function getKeyUpPropsWorker(_userCallback: KeyCallback, ..._keys: string[]): KeyPressProps { + // No keyboard event handling support in React Native on iOS or Android + return {}; } -// eslint-disable-next-line @typescript-eslint/no-empty-function -const noOp2 = (_userCallback: KeyCallback, ..._keys: string[]) => { +function getKeyDownPropsWorker(_userCallback: KeyCallback, ..._keys: string[]): KeyPressProps { + // No keyboard event handling support in React Native on iOS or Android return {}; -}; +} /** - * Re-usable hook for an onKeyUp event. noOp on unsupported platforms. + * Re-usable hook for an onKeyUp event. * @param userCallback The function you want to be called once the key has been activated on key up * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns KeyPressProps: An object containing the correct platform specific props to handle key press + * @returns KeyPressProps: An object containing the correct platform specific props to handle key press */ -export const useKeyUpProps = noOp2; +export const useKeyUpProps = memoize(getKeyUpPropsWorker); /** - * Re-usable hook for an onKeyDown event. noOp on unsupported platforms. + * Re-usable hook for an onKeyDown event. * @param userCallback The function you want to be called once the key has been activated on key down * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback * @returns KeyPressProps: An object containing the correct platform specific props to handle key press */ -export const useKeyDownProps = noOp2; +export const useKeyDownProps = memoize(getKeyDownPropsWorker); /** * Re-usable hook for keyboard events. on macOS, this is onKeyDown, while on windows this is onKeyUp. * @param userCallback The function you want to be called once the key has been activated on key down * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns KeyPressProps: An object containing the correct platform specific props to handle key press + * @returns KeyPressProps: An object containing the correct platform specific props to handle key press */ -export const useKeyProps = noOp2; - -/** Exposes the behavior of useKeyProps for the current platform as a boolean */ -export const preferKeyDownForKeyEvents = false; +export const useKeyProps = memoize(getKeyUpPropsWorker); diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.macos.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.macos.ts new file mode 100644 index 0000000000..5b733c4081 --- /dev/null +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.macos.ts @@ -0,0 +1,33 @@ +import { NativeSyntheticEvent } from 'react-native'; + +// React Native macOS doesn't have typescript types yet, so define the type here. +interface NativeKeyEvent { + // Modifier keys + capsLockKey: boolean; + shiftKey: boolean; + ctrlKey: boolean; + altKey: boolean; + metaKey: boolean; + numericPadKey: boolean; + helpKey: boolean; + functionKey: boolean; + // Key options + ArrowLeft: boolean; + ArrowRight: boolean; + ArrowUp: boolean; + ArrowDown: boolean; + key: string; +} + +interface KeyEvent extends NativeSyntheticEvent {} + +export type KeyCallback = (args?: KeyEvent) => void; + +export type KeyPressProps = { + onKeyDown?: KeyCallback; + validKeysDown?: string[]; // macOS + keyDownEvents?: any[]; // windows + onKeyUp?: KeyCallback; + validKeysUp?: string[]; // macOS + keyUpEvents?: any[]; // windows +}; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.ts new file mode 100644 index 0000000000..54a63f6a38 --- /dev/null +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.ts @@ -0,0 +1,12 @@ +import { KeyPressEvent } from './Pressability/CoreEventTypes'; + +export type KeyCallback = (args?: KeyPressEvent) => void; + +export type KeyPressProps = { + onKeyDown?: KeyCallback; + validKeysDown?: string[]; // macOS + keyDownEvents?: any[]; // windows + onKeyUp?: KeyCallback; + validKeysUp?: string[]; // macOS + keyUpEvents?: any[]; // windows +}; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts new file mode 100644 index 0000000000..090865b78c --- /dev/null +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts @@ -0,0 +1,12 @@ +import { IKeyboardEvent, IHandledKeyboardEvent } from '@office-iss/react-native-win32'; + +export type KeyCallback = (args?: IKeyboardEvent) => void; + +export type KeyPressProps = { + onKeyDown?: KeyCallback; + validKeysDown?: string[]; // macOS + keyDownEvents?: IHandledKeyboardEvent[]; // win32 + onKeyUp?: KeyCallback; + validKeysUp?: string[]; // macOS + keyUpEvents?: IHandledKeyboardEvent[]; // win32 +}; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts new file mode 100644 index 0000000000..54f7706f70 --- /dev/null +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts @@ -0,0 +1,12 @@ +import { IKeyboardEvent, IHandledKeyboardEvent } from 'react-native-windows'; + +export type KeyCallback = (args?: IKeyboardEvent) => void; + +export type KeyPressProps = { + onKeyDown?: KeyCallback; + validKeysDown?: string[]; // macOS + keyDownEvents?: IHandledKeyboardEvent[]; // Windows + onKeyUp?: KeyCallback; + validKeysUp?: string[]; // macOS + keyUpEvents?: IHandledKeyboardEvent[]; // Windows +}; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.win32.ts b/packages/utils/interactive-hooks/src/useKeyProps.win32.ts index 7321272c2a..19824f51e6 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.win32.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.win32.ts @@ -1,4 +1,4 @@ -import { KeyCallback, KeyPressProps } from './useKeyProps'; +import { KeyCallback, KeyPressProps } from './useKeyProps.types'; import { KeyPressEvent } from './Pressability/CoreEventTypes'; import { memoize } from '@fluentui-react-native/memo-cache'; import { isModifierKey } from './isModifierKey'; @@ -19,7 +19,7 @@ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { args.stopPropagation(); } }, - [userCallback, ...keys], + [keys, userCallback], ); return onKeyEvent; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.windows.ts b/packages/utils/interactive-hooks/src/useKeyProps.windows.ts index 90cb64bb56..de8d71278a 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.windows.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.windows.ts @@ -1,4 +1,4 @@ -import { KeyCallback, KeyPressProps } from './useKeyProps'; +import { KeyCallback, KeyPressProps } from './useKeyProps.types'; import { KeyPressEvent } from './Pressability/CoreEventTypes'; import { memoize } from '@fluentui-react-native/memo-cache'; import * as React from 'react'; @@ -19,7 +19,7 @@ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { args.stopPropagation(); } }, - [userCallback, ...keys], + [keys, userCallback], ); return onKeyEvent; From da7f3838c05c5956fe02f98a3549cf669a753f2d Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Wed, 28 Dec 2022 15:00:54 -0600 Subject: [PATCH 02/10] Change files --- ...ractive-hooks-856e3a2e-9eda-44e0-a5c4-f3a83ad215f8.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@fluentui-react-native-interactive-hooks-856e3a2e-9eda-44e0-a5c4-f3a83ad215f8.json diff --git a/change/@fluentui-react-native-interactive-hooks-856e3a2e-9eda-44e0-a5c4-f3a83ad215f8.json b/change/@fluentui-react-native-interactive-hooks-856e3a2e-9eda-44e0-a5c4-f3a83ad215f8.json new file mode 100644 index 0000000000..71eccfafa3 --- /dev/null +++ b/change/@fluentui-react-native-interactive-hooks-856e3a2e-9eda-44e0-a5c4-f3a83ad215f8.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Better types + tests for useKeyProps", + "packageName": "@fluentui-react-native/interactive-hooks", + "email": "sanajmi@microsoft.com", + "dependentChangeType": "patch" +} From aed8f1874c24ee898211f63f3d46422c3cf058e2 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Wed, 28 Dec 2022 15:04:14 -0600 Subject: [PATCH 03/10] Update base type --- packages/utils/interactive-hooks/src/useKeyProps.types.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.ts index 54a63f6a38..ac0e392f02 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.ts @@ -1,6 +1,8 @@ -import { KeyPressEvent } from './Pressability/CoreEventTypes'; +import { NativeSyntheticEvent } from 'react-native'; -export type KeyCallback = (args?: KeyPressEvent) => void; +type KeyboardEvent = NativeSyntheticEvent; + +export type KeyCallback = (args?: KeyboardEvent) => void; export type KeyPressProps = { onKeyDown?: KeyCallback; From a51c309f540f8adf2d1c8347d8d147f0c6d53793 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Wed, 28 Dec 2022 15:12:26 -0600 Subject: [PATCH 04/10] type KeyboardEvent --- .../src/__tests__/events.types.test.ts | 4 ++-- .../src/useKeyProps.macos.ts | 19 +++++++++---------- .../src/useKeyProps.types.macos.ts | 4 ++-- .../src/useKeyProps.types.ts | 4 ++-- .../src/useKeyProps.types.win32.ts | 4 +++- .../src/useKeyProps.types.windows.ts | 4 +++- .../src/useKeyProps.win32.ts | 19 +++++++++---------- .../src/useKeyProps.windows.ts | 19 +++++++++---------- 8 files changed, 39 insertions(+), 38 deletions(-) diff --git a/packages/utils/interactive-hooks/src/__tests__/events.types.test.ts b/packages/utils/interactive-hooks/src/__tests__/events.types.test.ts index 1ff886ff1f..9eeefe10fd 100644 --- a/packages/utils/interactive-hooks/src/__tests__/events.types.test.ts +++ b/packages/utils/interactive-hooks/src/__tests__/events.types.test.ts @@ -1,5 +1,5 @@ import { AccessibilityActionEvent, GestureResponderEvent } from 'react-native'; -import { KeyPressEvent } from '../Pressability/CoreEventTypes'; +import { KeyboardEvent } from '../useKeyProps.types'; import { isAccessibilityActionEvent, isGestureResponderEvent, isKeyPressEvent } from '../events.types'; const createMockEvent = (nativeEvent) => { @@ -44,7 +44,7 @@ const mockGestureEvent: GestureResponderEvent = createMockEvent({ touches: [], }); -const mockKeyPressEvent: KeyPressEvent = createMockEvent({ +const mockKeyPressEvent: KeyboardEvent = createMockEvent({ key: 'enter', }); diff --git a/packages/utils/interactive-hooks/src/useKeyProps.macos.ts b/packages/utils/interactive-hooks/src/useKeyProps.macos.ts index 2a2a8e0833..6ccc01a73c 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.macos.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.macos.ts @@ -1,5 +1,4 @@ -import { KeyCallback, KeyPressProps } from './useKeyProps.types'; -import { KeyPressEvent } from './Pressability/CoreEventTypes'; +import { KeyboardEvent, KeyCallback, KeyPressProps } from './useKeyProps.types'; import { memoize } from '@fluentui-react-native/memo-cache'; import { isModifierKey } from './isModifierKey'; import * as React from 'react'; @@ -13,10 +12,10 @@ import * as React from 'react'; */ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { const onKeyEvent = React.useCallback( - (args: KeyPressEvent) => { - if (userCallback !== undefined && (keys === undefined || keys.includes(args.nativeEvent.key))) { - userCallback(args); - args.stopPropagation(); + (e: KeyboardEvent) => { + if (userCallback !== undefined && (keys === undefined || keys.includes(e.nativeEvent.key))) { + userCallback(e); + e.stopPropagation(); } }, [keys, userCallback], @@ -26,10 +25,10 @@ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { } function getKeyCallbackWorker(userCallback?: KeyCallback, ...keys: string[]) { - const onKeyEvent = (args: KeyPressEvent) => { - if (userCallback !== undefined && !isModifierKey(args.nativeEvent) && (keys === undefined || keys.includes(args.nativeEvent.key))) { - userCallback(args); - args.stopPropagation(); + const onKeyEvent = (e: KeyboardEvent) => { + if (userCallback !== undefined && !isModifierKey(e.nativeEvent) && (keys === undefined || keys.includes(e.nativeEvent.key))) { + userCallback(e); + e.stopPropagation(); } }; return onKeyEvent; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.macos.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.macos.ts index 5b733c4081..efc39eae13 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.macos.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.macos.ts @@ -19,9 +19,9 @@ interface NativeKeyEvent { key: string; } -interface KeyEvent extends NativeSyntheticEvent {} +export type KeyboardEvent = NativeSyntheticEvent; -export type KeyCallback = (args?: KeyEvent) => void; +export type KeyCallback = (e?: KeyboardEvent) => void; export type KeyPressProps = { onKeyDown?: KeyCallback; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.ts index ac0e392f02..57082907a5 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.ts @@ -1,8 +1,8 @@ import { NativeSyntheticEvent } from 'react-native'; -type KeyboardEvent = NativeSyntheticEvent; +export type KeyboardEvent = NativeSyntheticEvent; -export type KeyCallback = (args?: KeyboardEvent) => void; +export type KeyCallback = (e?: KeyboardEvent) => void; export type KeyPressProps = { onKeyDown?: KeyCallback; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts index 090865b78c..a1df4eb858 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts @@ -1,6 +1,8 @@ import { IKeyboardEvent, IHandledKeyboardEvent } from '@office-iss/react-native-win32'; -export type KeyCallback = (args?: IKeyboardEvent) => void; +export type KeyboardEvent = IKeyboardEvent; + +export type KeyCallback = (e?: KeyboardEvent) => void; export type KeyPressProps = { onKeyDown?: KeyCallback; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts index 54f7706f70..8817d4de5f 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts @@ -1,6 +1,8 @@ import { IKeyboardEvent, IHandledKeyboardEvent } from 'react-native-windows'; -export type KeyCallback = (args?: IKeyboardEvent) => void; +export type KeyboardEvent = IKeyboardEvent; + +export type KeyCallback = (e?: KeyboardEvent) => void; export type KeyPressProps = { onKeyDown?: KeyCallback; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.win32.ts b/packages/utils/interactive-hooks/src/useKeyProps.win32.ts index 19824f51e6..e392de705f 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.win32.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.win32.ts @@ -1,5 +1,4 @@ -import { KeyCallback, KeyPressProps } from './useKeyProps.types'; -import { KeyPressEvent } from './Pressability/CoreEventTypes'; +import { KeyboardEvent, KeyCallback, KeyPressProps } from './useKeyProps.types'; import { memoize } from '@fluentui-react-native/memo-cache'; import { isModifierKey } from './isModifierKey'; import * as React from 'react'; @@ -13,10 +12,10 @@ import * as React from 'react'; */ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { const onKeyEvent = React.useCallback( - (args: KeyPressEvent) => { - if (userCallback !== undefined && (keys === undefined || keys.includes(args.nativeEvent.key))) { - userCallback(args); - args.stopPropagation(); + (e: KeyboardEvent) => { + if (userCallback !== undefined && (keys === undefined || keys.includes(e.nativeEvent.key))) { + userCallback(e); + e.stopPropagation(); } }, [keys, userCallback], @@ -26,10 +25,10 @@ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { } export function getKeyCallbackWorker(userCallback?: KeyCallback, ...keys: string[]) { - const onKeyEvent = (args: KeyPressEvent) => { - if (userCallback !== undefined && !isModifierKey(args.nativeEvent) && (keys === undefined || keys.includes(args.nativeEvent.key))) { - userCallback(args); - args.stopPropagation(); + const onKeyEvent = (e: KeyboardEvent) => { + if (userCallback !== undefined && !isModifierKey(e.nativeEvent) && (keys === undefined || keys.includes(args.nativeEvent.key))) { + userCallback(e); + e.stopPropagation(); } }; return onKeyEvent; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.windows.ts b/packages/utils/interactive-hooks/src/useKeyProps.windows.ts index de8d71278a..d23bd7d43d 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.windows.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.windows.ts @@ -1,5 +1,4 @@ -import { KeyCallback, KeyPressProps } from './useKeyProps.types'; -import { KeyPressEvent } from './Pressability/CoreEventTypes'; +import { KeyboardEvent, KeyCallback, KeyPressProps } from './useKeyProps.types'; import { memoize } from '@fluentui-react-native/memo-cache'; import * as React from 'react'; import { isModifierKey } from './isModifierKey'; @@ -13,10 +12,10 @@ import { isModifierKey } from './isModifierKey'; */ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { const onKeyEvent = React.useCallback( - (args: KeyPressEvent) => { - if (userCallback !== undefined && (keys === undefined || keys.includes(args.nativeEvent.key))) { - userCallback(args); - args.stopPropagation(); + (e: KeyboardEvent) => { + if (userCallback !== undefined && (keys === undefined || keys.includes(e.nativeEvent.key))) { + userCallback(e); + e.stopPropagation(); } }, [keys, userCallback], @@ -26,10 +25,10 @@ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { } export function getKeyCallbackWorker(userCallback?: KeyCallback, ...keys: string[]) { - const onKeyEvent = (args: KeyPressEvent) => { - if (userCallback !== undefined && !isModifierKey(args.nativeEvent) && (keys === undefined || keys.includes(args.nativeEvent.key))) { - userCallback(args); - args.stopPropagation(); + const onKeyEvent = (e: KeyboardEvent) => { + if (userCallback !== undefined && !isModifierKey(e.nativeEvent) && (keys === undefined || keys.includes(e.nativeEvent.key))) { + userCallback(e); + e.stopPropagation(); } }; return onKeyEvent; From bf0b9c1b4d6a28a941b74e76a35555cd477176c5 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Wed, 28 Dec 2022 16:00:38 -0600 Subject: [PATCH 05/10] KeyboardEvent -> KeyPressEvent --- .../src/__tests__/events.types.test.ts | 4 ++-- packages/utils/interactive-hooks/src/events.types.ts | 4 ++-- packages/utils/interactive-hooks/src/index.ts | 3 +-- .../utils/interactive-hooks/src/useKeyProps.macos.ts | 6 +++--- .../interactive-hooks/src/useKeyProps.types.macos.ts | 4 ++-- .../utils/interactive-hooks/src/useKeyProps.types.ts | 4 ++-- .../interactive-hooks/src/useKeyProps.types.win32.ts | 10 +++++----- .../interactive-hooks/src/useKeyProps.types.windows.ts | 10 +++++----- .../utils/interactive-hooks/src/useKeyProps.win32.ts | 6 +++--- .../utils/interactive-hooks/src/useKeyProps.windows.ts | 6 +++--- 10 files changed, 28 insertions(+), 29 deletions(-) diff --git a/packages/utils/interactive-hooks/src/__tests__/events.types.test.ts b/packages/utils/interactive-hooks/src/__tests__/events.types.test.ts index 9eeefe10fd..ae4a34849c 100644 --- a/packages/utils/interactive-hooks/src/__tests__/events.types.test.ts +++ b/packages/utils/interactive-hooks/src/__tests__/events.types.test.ts @@ -1,5 +1,5 @@ import { AccessibilityActionEvent, GestureResponderEvent } from 'react-native'; -import { KeyboardEvent } from '../useKeyProps.types'; +import { KeyPressEvent } from '../useKeyProps.types'; import { isAccessibilityActionEvent, isGestureResponderEvent, isKeyPressEvent } from '../events.types'; const createMockEvent = (nativeEvent) => { @@ -44,7 +44,7 @@ const mockGestureEvent: GestureResponderEvent = createMockEvent({ touches: [], }); -const mockKeyPressEvent: KeyboardEvent = createMockEvent({ +const mockKeyPressEvent: KeyPressEvent = createMockEvent({ key: 'enter', }); diff --git a/packages/utils/interactive-hooks/src/events.types.ts b/packages/utils/interactive-hooks/src/events.types.ts index 8ede2bf62d..bdf8da042f 100644 --- a/packages/utils/interactive-hooks/src/events.types.ts +++ b/packages/utils/interactive-hooks/src/events.types.ts @@ -1,5 +1,5 @@ -import { AccessibilityActionEvent, GestureResponderEvent } from 'react-native'; -import { KeyPressEvent, MouseEvent } from './Pressability/CoreEventTypes'; +import { AccessibilityActionEvent, GestureResponderEvent, MouseEvent } from 'react-native'; +import { KeyPressEvent } from './useKeyProps.types'; export type InteractionEvent = GestureResponderEvent | MouseEvent | KeyPressEvent | AccessibilityActionEvent; diff --git a/packages/utils/interactive-hooks/src/index.ts b/packages/utils/interactive-hooks/src/index.ts index 32a01d5552..6f057537e1 100644 --- a/packages/utils/interactive-hooks/src/index.ts +++ b/packages/utils/interactive-hooks/src/index.ts @@ -45,7 +45,6 @@ export type { export type { BlurEvent, FocusEvent, - KeyPressEvent, Layout, LayoutEvent, MouseEvent, @@ -56,8 +55,8 @@ export type { TextLayout, TextLayoutEvent, } from './Pressability/CoreEventTypes'; +export type { KeyPressEvent, KeyCallback, KeyPressProps } from './useKeyProps.types'; export { preferKeyDownForKeyEvents, useKeyCallback, useKeyDownProps, useKeyProps, useKeyUpProps } from './useKeyProps'; -export type { KeyCallback, KeyPressProps } from './useKeyProps'; export { useOnPressWithFocus } from './useOnPressWithFocus'; export type { OnPressCallback, OnPressWithFocusCallback } from './useOnPressWithFocus'; export { getAccessibilityState } from './getAccessibilityState'; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.macos.ts b/packages/utils/interactive-hooks/src/useKeyProps.macos.ts index 6ccc01a73c..159c553e98 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.macos.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.macos.ts @@ -1,4 +1,4 @@ -import { KeyboardEvent, KeyCallback, KeyPressProps } from './useKeyProps.types'; +import { KeyPressEvent, KeyCallback, KeyPressProps } from './useKeyProps.types'; import { memoize } from '@fluentui-react-native/memo-cache'; import { isModifierKey } from './isModifierKey'; import * as React from 'react'; @@ -12,7 +12,7 @@ import * as React from 'react'; */ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { const onKeyEvent = React.useCallback( - (e: KeyboardEvent) => { + (e: KeyPressEvent) => { if (userCallback !== undefined && (keys === undefined || keys.includes(e.nativeEvent.key))) { userCallback(e); e.stopPropagation(); @@ -25,7 +25,7 @@ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { } function getKeyCallbackWorker(userCallback?: KeyCallback, ...keys: string[]) { - const onKeyEvent = (e: KeyboardEvent) => { + const onKeyEvent = (e: KeyPressEvent) => { if (userCallback !== undefined && !isModifierKey(e.nativeEvent) && (keys === undefined || keys.includes(e.nativeEvent.key))) { userCallback(e); e.stopPropagation(); diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.macos.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.macos.ts index efc39eae13..0e08ea17fd 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.macos.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.macos.ts @@ -19,9 +19,9 @@ interface NativeKeyEvent { key: string; } -export type KeyboardEvent = NativeSyntheticEvent; +export type KeyPressEvent = NativeSyntheticEvent; -export type KeyCallback = (e?: KeyboardEvent) => void; +export type KeyCallback = (e?: KeyPressEvent) => void; export type KeyPressProps = { onKeyDown?: KeyCallback; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.ts index 57082907a5..92911c1715 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.ts @@ -1,8 +1,8 @@ import { NativeSyntheticEvent } from 'react-native'; -export type KeyboardEvent = NativeSyntheticEvent; +export type KeyPressEvent = NativeSyntheticEvent; -export type KeyCallback = (e?: KeyboardEvent) => void; +export type KeyCallback = (e?: KeyPressEvent) => void; export type KeyPressProps = { onKeyDown?: KeyCallback; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts index a1df4eb858..dd8e87b1f5 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts @@ -1,14 +1,14 @@ -import { IKeyboardEvent, IHandledKeyboardEvent } from '@office-iss/react-native-win32'; +import { IKeyPressEvent, IHandledKeyPressEvent } from '@office-iss/react-native-win32'; -export type KeyboardEvent = IKeyboardEvent; +export type KeyPressEvent = IKeyPressEvent; -export type KeyCallback = (e?: KeyboardEvent) => void; +export type KeyCallback = (e?: KeyPressEvent) => void; export type KeyPressProps = { onKeyDown?: KeyCallback; validKeysDown?: string[]; // macOS - keyDownEvents?: IHandledKeyboardEvent[]; // win32 + keyDownEvents?: IHandledKeyPressEvent[]; // win32 onKeyUp?: KeyCallback; validKeysUp?: string[]; // macOS - keyUpEvents?: IHandledKeyboardEvent[]; // win32 + keyUpEvents?: IHandledKeyPressEvent[]; // win32 }; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts index 8817d4de5f..9b1ec3a2ef 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts @@ -1,14 +1,14 @@ -import { IKeyboardEvent, IHandledKeyboardEvent } from 'react-native-windows'; +import { IKeyPressEvent, IHandledKeyPressEvent } from 'react-native-windows'; -export type KeyboardEvent = IKeyboardEvent; +export type KeyPressEvent = IKeyPressEvent; -export type KeyCallback = (e?: KeyboardEvent) => void; +export type KeyCallback = (e?: KeyPressEvent) => void; export type KeyPressProps = { onKeyDown?: KeyCallback; validKeysDown?: string[]; // macOS - keyDownEvents?: IHandledKeyboardEvent[]; // Windows + keyDownEvents?: IHandledKeyPressEvent[]; // Windows onKeyUp?: KeyCallback; validKeysUp?: string[]; // macOS - keyUpEvents?: IHandledKeyboardEvent[]; // Windows + keyUpEvents?: IHandledKeyPressEvent[]; // Windows }; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.win32.ts b/packages/utils/interactive-hooks/src/useKeyProps.win32.ts index e392de705f..173b46bb4d 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.win32.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.win32.ts @@ -1,4 +1,4 @@ -import { KeyboardEvent, KeyCallback, KeyPressProps } from './useKeyProps.types'; +import { KeyPressEvent, KeyCallback, KeyPressProps } from './useKeyProps.types'; import { memoize } from '@fluentui-react-native/memo-cache'; import { isModifierKey } from './isModifierKey'; import * as React from 'react'; @@ -12,7 +12,7 @@ import * as React from 'react'; */ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { const onKeyEvent = React.useCallback( - (e: KeyboardEvent) => { + (e: KeyPressEvent) => { if (userCallback !== undefined && (keys === undefined || keys.includes(e.nativeEvent.key))) { userCallback(e); e.stopPropagation(); @@ -25,7 +25,7 @@ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { } export function getKeyCallbackWorker(userCallback?: KeyCallback, ...keys: string[]) { - const onKeyEvent = (e: KeyboardEvent) => { + const onKeyEvent = (e: KeyPressEvent) => { if (userCallback !== undefined && !isModifierKey(e.nativeEvent) && (keys === undefined || keys.includes(args.nativeEvent.key))) { userCallback(e); e.stopPropagation(); diff --git a/packages/utils/interactive-hooks/src/useKeyProps.windows.ts b/packages/utils/interactive-hooks/src/useKeyProps.windows.ts index d23bd7d43d..d7cc11f27f 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.windows.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.windows.ts @@ -1,4 +1,4 @@ -import { KeyboardEvent, KeyCallback, KeyPressProps } from './useKeyProps.types'; +import { KeyPressEvent, KeyCallback, KeyPressProps } from './useKeyProps.types'; import { memoize } from '@fluentui-react-native/memo-cache'; import * as React from 'react'; import { isModifierKey } from './isModifierKey'; @@ -12,7 +12,7 @@ import { isModifierKey } from './isModifierKey'; */ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { const onKeyEvent = React.useCallback( - (e: KeyboardEvent) => { + (e: KeyPressEvent) => { if (userCallback !== undefined && (keys === undefined || keys.includes(e.nativeEvent.key))) { userCallback(e); e.stopPropagation(); @@ -25,7 +25,7 @@ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { } export function getKeyCallbackWorker(userCallback?: KeyCallback, ...keys: string[]) { - const onKeyEvent = (e: KeyboardEvent) => { + const onKeyEvent = (e: KeyPressEvent) => { if (userCallback !== undefined && !isModifierKey(e.nativeEvent) && (keys === undefined || keys.includes(e.nativeEvent.key))) { userCallback(e); e.stopPropagation(); From 240113d28f0c005925a9a7a0122c26d3b0a53b24 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Wed, 28 Dec 2022 16:22:50 -0600 Subject: [PATCH 06/10] More tests + type fix --- .../utils/interactive-hooks/jest.config.js | 4 +-- packages/utils/interactive-hooks/package.json | 4 ++- .../__snapshots__/useKeyProps.test.tsx.snap | 31 +++++++++++++++++++ .../src/__tests__/useKeyProps.test.tsx | 29 +++++++++++++++-- .../src/useKeyProps.types.win32.ts | 6 ++-- .../src/useKeyProps.types.windows.ts | 6 ++-- .../src/useKeyProps.win32.ts | 2 +- 7 files changed, 69 insertions(+), 13 deletions(-) create mode 100644 packages/utils/interactive-hooks/src/__tests__/__snapshots__/useKeyProps.test.tsx.snap diff --git a/packages/utils/interactive-hooks/jest.config.js b/packages/utils/interactive-hooks/jest.config.js index 9163d4be7c..f6813bad78 100644 --- a/packages/utils/interactive-hooks/jest.config.js +++ b/packages/utils/interactive-hooks/jest.config.js @@ -1,2 +1,2 @@ -const { configureJest } = require('@fluentui-react-native/scripts'); -module.exports = configureJest(); +const { configureReactNativeJest } = require('@fluentui-react-native/scripts'); +module.exports = configureReactNativeJest('win32'); diff --git a/packages/utils/interactive-hooks/package.json b/packages/utils/interactive-hooks/package.json index 6596c91c60..d8abfd0a7a 100644 --- a/packages/utils/interactive-hooks/package.json +++ b/packages/utils/interactive-hooks/package.json @@ -40,7 +40,9 @@ "@types/react": "^17.0.2", "@types/react-native": "^0.68.0", "react": "17.0.2", - "react-native": "^0.68.0" + "react-native": "^0.68.0", + "react-native-macos": "^0.68.0", + "react-native-windows": "^0.68.0" }, "peerDependencies": { "react": "17.0.2", diff --git a/packages/utils/interactive-hooks/src/__tests__/__snapshots__/useKeyProps.test.tsx.snap b/packages/utils/interactive-hooks/src/__tests__/__snapshots__/useKeyProps.test.tsx.snap new file mode 100644 index 0000000000..c2581bdba2 --- /dev/null +++ b/packages/utils/interactive-hooks/src/__tests__/__snapshots__/useKeyProps.test.tsx.snap @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`useKeyProps with Pressable 1`] = ` + +`; diff --git a/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx b/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx index b05e7a8f00..e99ec484b8 100644 --- a/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx +++ b/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx @@ -1,10 +1,33 @@ +import * as React from 'react'; +import * as renderer from 'react-test-renderer'; +import { Pressable } from 'react-native'; import { useKeyProps } from '../useKeyProps'; +import { checkReRender } from '@fluentui-react-native/test-tools'; +import { PressablePropsExtended } from '../usePressableState.types'; + +const dummyFunction = () => { + console.log('dummy'); +}; + +// Simple wrapper function to let us use `PressablePropsExtended` to fix type errors +const PressableWithDesktopProps = (props: PressablePropsExtended) => { + return ; +}; it('useKeyProps is memoized', () => { - const dummyFunction = () => { - console.log('dummy'); - }; const onKeyUpProps1 = useKeyProps(dummyFunction, ' ', 'Enter'); const onKeyUpProps2 = useKeyProps(dummyFunction, ' ', 'Enter'); expect(onKeyUpProps1 === onKeyUpProps2).toBeTruthy(); }); + +it('useKeyProps with Pressable', () => { + const keyboardProps = useKeyProps(dummyFunction, ' ', 'Enter'); + + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); +}); + +it('Pressable with useKeyProps re-renders correctly', () => { + const keyboardProps = useKeyProps(dummyFunction, ' ', 'Enter'); + checkReRender(() => , 2); +}); diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts index dd8e87b1f5..221ec99025 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts @@ -1,4 +1,4 @@ -import { IKeyPressEvent, IHandledKeyPressEvent } from '@office-iss/react-native-win32'; +import { IKeyPressEvent, IHandledKeyboardEvent } from '@office-iss/react-native-win32'; export type KeyPressEvent = IKeyPressEvent; @@ -7,8 +7,8 @@ export type KeyCallback = (e?: KeyPressEvent) => void; export type KeyPressProps = { onKeyDown?: KeyCallback; validKeysDown?: string[]; // macOS - keyDownEvents?: IHandledKeyPressEvent[]; // win32 + keyDownEvents?: IHandledKeyboardEvent[]; // win32 onKeyUp?: KeyCallback; validKeysUp?: string[]; // macOS - keyUpEvents?: IHandledKeyPressEvent[]; // win32 + keyUpEvents?: IHandledKeyboardEvent[]; // win32 }; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts index 9b1ec3a2ef..1ca62efc14 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts @@ -1,4 +1,4 @@ -import { IKeyPressEvent, IHandledKeyPressEvent } from 'react-native-windows'; +import { IKeyPressEvent, IHandledKeyboardEvent } from 'react-native-windows'; export type KeyPressEvent = IKeyPressEvent; @@ -7,8 +7,8 @@ export type KeyCallback = (e?: KeyPressEvent) => void; export type KeyPressProps = { onKeyDown?: KeyCallback; validKeysDown?: string[]; // macOS - keyDownEvents?: IHandledKeyPressEvent[]; // Windows + keyDownEvents?: IHandledKeyboardEvent[]; // Windows onKeyUp?: KeyCallback; validKeysUp?: string[]; // macOS - keyUpEvents?: IHandledKeyPressEvent[]; // Windows + keyUpEvents?: IHandledKeyboardEvent[]; // Windows }; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.win32.ts b/packages/utils/interactive-hooks/src/useKeyProps.win32.ts index 173b46bb4d..30c56bdd1f 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.win32.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.win32.ts @@ -26,7 +26,7 @@ export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { export function getKeyCallbackWorker(userCallback?: KeyCallback, ...keys: string[]) { const onKeyEvent = (e: KeyPressEvent) => { - if (userCallback !== undefined && !isModifierKey(e.nativeEvent) && (keys === undefined || keys.includes(args.nativeEvent.key))) { + if (userCallback !== undefined && !isModifierKey(e.nativeEvent) && (keys === undefined || keys.includes(e.nativeEvent.key))) { userCallback(e); e.stopPropagation(); } From b4975cbdeca92e2e556a8ac55cb847c399a9501a Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Wed, 28 Dec 2022 16:25:08 -0600 Subject: [PATCH 07/10] More tests --- .../__tests__/__snapshots__/useKeyProps.test.tsx.snap | 2 +- .../interactive-hooks/src/__tests__/useKeyProps.test.tsx | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/utils/interactive-hooks/src/__tests__/__snapshots__/useKeyProps.test.tsx.snap b/packages/utils/interactive-hooks/src/__tests__/__snapshots__/useKeyProps.test.tsx.snap index c2581bdba2..37505ad221 100644 --- a/packages/utils/interactive-hooks/src/__tests__/__snapshots__/useKeyProps.test.tsx.snap +++ b/packages/utils/interactive-hooks/src/__tests__/__snapshots__/useKeyProps.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`useKeyProps with Pressable 1`] = ` +exports[`Pressable with useKeyProps 1`] = ` { @@ -20,13 +20,18 @@ it('useKeyProps is memoized', () => { expect(onKeyUpProps1 === onKeyUpProps2).toBeTruthy(); }); -it('useKeyProps with Pressable', () => { +it('Pressable with useKeyProps', () => { const keyboardProps = useKeyProps(dummyFunction, ' ', 'Enter'); const tree = renderer.create().toJSON(); expect(tree).toMatchSnapshot(); }); +it('Simple Pressable with useKeyProps rendering does not invalidate styling', () => { + const keyboardProps = useKeyProps(dummyFunction, ' ', 'Enter'); + checkRenderConsistency(() => , 2); +}); + it('Pressable with useKeyProps re-renders correctly', () => { const keyboardProps = useKeyProps(dummyFunction, ' ', 'Enter'); checkReRender(() => , 2); From 0544ba11b473647f11648656fe7a02fc338d4546 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Wed, 28 Dec 2022 17:01:10 -0600 Subject: [PATCH 08/10] Combine useKeyProps to one file --- .../src/__tests__/useKeyProps.test.tsx | 7 -- .../interactive-hooks/src/isModifierKey.ts | 18 --- .../src/useKeyProps.macos.ts | 78 ------------ .../interactive-hooks/src/useKeyProps.ts | 112 ++++++++++++++++-- .../src/useKeyProps.types.ts | 6 +- .../src/useKeyProps.types.win32.ts | 2 - .../src/useKeyProps.types.windows.ts | 2 - .../src/useKeyProps.win32.ts | 82 ------------- .../src/useKeyProps.windows.ts | 74 ------------ 9 files changed, 107 insertions(+), 274 deletions(-) delete mode 100644 packages/utils/interactive-hooks/src/isModifierKey.ts delete mode 100644 packages/utils/interactive-hooks/src/useKeyProps.macos.ts delete mode 100644 packages/utils/interactive-hooks/src/useKeyProps.win32.ts delete mode 100644 packages/utils/interactive-hooks/src/useKeyProps.windows.ts diff --git a/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx b/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx index 4456d4fb8e..2ed0eafb87 100644 --- a/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx +++ b/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx @@ -14,15 +14,8 @@ const PressableWithDesktopProps = (props: PressablePropsExtended) => { return ; }; -it('useKeyProps is memoized', () => { - const onKeyUpProps1 = useKeyProps(dummyFunction, ' ', 'Enter'); - const onKeyUpProps2 = useKeyProps(dummyFunction, ' ', 'Enter'); - expect(onKeyUpProps1 === onKeyUpProps2).toBeTruthy(); -}); - it('Pressable with useKeyProps', () => { const keyboardProps = useKeyProps(dummyFunction, ' ', 'Enter'); - const tree = renderer.create().toJSON(); expect(tree).toMatchSnapshot(); }); diff --git a/packages/utils/interactive-hooks/src/isModifierKey.ts b/packages/utils/interactive-hooks/src/isModifierKey.ts deleted file mode 100644 index 3711b6d713..0000000000 --- a/packages/utils/interactive-hooks/src/isModifierKey.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Verifies if nativeEvent contains modifier key. - * @param nativeEvent - * @returns `true` if one or more of modifier keys are `true` - */ -export const isModifierKey = (nativeEvent: any): boolean => { - return ( - nativeEvent && - (nativeEvent.alt || - nativeEvent.altKey || - nativeEvent.ctrl || - nativeEvent.ctrlKey || - nativeEvent.meta || - nativeEvent.metaKey || - nativeEvent.shift || - nativeEvent.shiftKey) - ); -}; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.macos.ts b/packages/utils/interactive-hooks/src/useKeyProps.macos.ts deleted file mode 100644 index 159c553e98..0000000000 --- a/packages/utils/interactive-hooks/src/useKeyProps.macos.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { KeyPressEvent, KeyCallback, KeyPressProps } from './useKeyProps.types'; -import { memoize } from '@fluentui-react-native/memo-cache'; -import { isModifierKey } from './isModifierKey'; -import * as React from 'react'; - -/** - * Re-usable hook for an onKeyDown event. - * @param userCallback The function you want to be called once the key has been activated on key up - * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns onKeyEvent() - Callback to determine if key was pressed, if so, call userCallback - * @deprecated use useKeyUpProps or useKeyDownProps instead - */ -export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { - const onKeyEvent = React.useCallback( - (e: KeyPressEvent) => { - if (userCallback !== undefined && (keys === undefined || keys.includes(e.nativeEvent.key))) { - userCallback(e); - e.stopPropagation(); - } - }, - [keys, userCallback], - ); - - return onKeyEvent; -} - -function getKeyCallbackWorker(userCallback?: KeyCallback, ...keys: string[]) { - const onKeyEvent = (e: KeyPressEvent) => { - if (userCallback !== undefined && !isModifierKey(e.nativeEvent) && (keys === undefined || keys.includes(e.nativeEvent.key))) { - userCallback(e); - e.stopPropagation(); - } - }; - return onKeyEvent; -} - -function getKeyUpPropsWorker(userCallback: KeyCallback, ...keys: string[]): KeyPressProps { - return { - onKeyUp: getKeyCallbackWorker(userCallback, ...keys), - // Required on macOS to know which key events to suppress natively - validKeysUp: keys, - }; -} - -function getKeyDownPropsWorker(userCallback: KeyCallback, ...keys: string[]): KeyPressProps { - return { - onKeyDown: getKeyCallbackWorker(userCallback, ...keys), - // Required on macOS to know which key events to suppress natively - validKeysDown: keys, - }; -} - -/** - * Re-usable hook for an onKeyUp event. - * @param userCallback The function you want to be called once the key has been activated on key up - * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns KeyPressProps: An object containing the correct platform specific props to handle key press - */ -export const useKeyUpProps = memoize(getKeyUpPropsWorker); - -/** - * Re-usable hook for an onKeyDown event. - * @param userCallback The function you want to be called once the key has been activated on key down - * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns KeyPressProps: An object containing the correct platform specific props to handle key press - */ -export const useKeyDownProps = memoize(getKeyDownPropsWorker); - -/** - * Re-usable hook for keyboard events. on macOS, this is onKeyDown, while on windows this is onKeyUp. - * @param userCallback The function you want to be called once the key has been activated on key down - * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns KeyPressProps: An object containing the correct platform specific props to handle key press - */ -export const useKeyProps = memoize(getKeyDownPropsWorker); - -/** Exposes the behavior of useKeyProps for the current platform as a boolean */ -export const preferKeyDownForKeyEvents = true; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.ts b/packages/utils/interactive-hooks/src/useKeyProps.ts index 25d4fe3412..1b4e96e54a 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.ts @@ -1,14 +1,106 @@ -import { KeyCallback, KeyPressProps } from './useKeyProps.types'; +import * as React from 'react'; +import { Platform } from 'react-native'; import { memoize } from '@fluentui-react-native/memo-cache'; +import { KeyCallback, KeyPressEvent, KeyPressProps } from './useKeyProps.types'; -function getKeyUpPropsWorker(_userCallback: KeyCallback, ..._keys: string[]): KeyPressProps { - // No keyboard event handling support in React Native on iOS or Android - return {}; +/** + * Verifies if nativeEvent contains modifier key. + * @param nativeEvent + * @returns `true` if one or more of modifier keys are `true` + */ +export const isModifierKey = (nativeEvent: any): boolean => { + return ( + nativeEvent && + (nativeEvent.alt || + nativeEvent.altKey || + nativeEvent.ctrl || + nativeEvent.ctrlKey || + nativeEvent.meta || + nativeEvent.metaKey || + nativeEvent.shift || + nativeEvent.shiftKey) + ); +}; + +/** + * Re-usable hook for an onKeyDown event. + * @param userCallback The function you want to be called once the key has been activated on key up + * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback + * @returns onKeyEvent() - Callback to determine if key was pressed, if so, call userCallback + * @deprecated use the hook `useKeyProps` instead + */ +export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { + const onKeyEvent = React.useCallback( + (e: KeyPressEvent) => { + if (userCallback !== undefined && (keys === undefined || keys.includes(e.nativeEvent.key))) { + userCallback(e); + e.stopPropagation(); + } + }, + [keys, userCallback], + ); + + return onKeyEvent; +} + +function getKeyCallbackWorker(userCallback?: KeyCallback, ...keys: string[]) { + const onKeyEvent = (e: KeyPressEvent) => { + if (userCallback !== undefined && !isModifierKey(e.nativeEvent) && (keys === undefined || keys.includes(e.nativeEvent.key))) { + userCallback(e); + e.stopPropagation(); + } + }; + return onKeyEvent; } -function getKeyDownPropsWorker(_userCallback: KeyCallback, ..._keys: string[]): KeyPressProps { - // No keyboard event handling support in React Native on iOS or Android - return {}; +function getKeyUpPropsWorker(userCallback: KeyCallback, ...keys: string[]): KeyPressProps { + const keyboardProps = Platform.select({ + ios: undefined, + android: undefined, + macos: { + onKeyUp: getKeyCallbackWorker(userCallback, ...keys), + validKeysUp: keys, + }, + windows: { + onKeyUp: getKeyCallbackWorker(userCallback, ...keys), + keyUpEvents: keys.map((keyCode) => { + return { key: keyCode }; + }), + }, + // win32 + default: { + onKeyUp: getKeyCallbackWorker(userCallback, ...keys), + keyUpEvents: keys.map((keyCode) => { + return { key: keyCode }; + }), + }, + }); + return keyboardProps; +} + +function getKeyDownPropsWorker(userCallback: KeyCallback, ...keys: string[]): KeyPressProps { + const keyboardProps = Platform.select({ + ios: undefined, + android: undefined, + macos: { + onKeyDown: getKeyCallbackWorker(userCallback, ...keys), + validKeysDown: keys, + }, + windows: { + onKeyDown: getKeyCallbackWorker(userCallback, ...keys), + keyDownEvents: keys.map((keyCode) => { + return { key: keyCode }; + }), + }, + // win32 + default: { + onKeyDown: getKeyCallbackWorker(userCallback, ...keys), + keyDownEvents: keys.map((keyCode) => { + return { key: keyCode }; + }), + }, + }); + return keyboardProps; } /** @@ -34,3 +126,9 @@ export const useKeyDownProps = memoize(getKeyDownPropsWorker); * @returns KeyPressProps: An object containing the correct platform specific props to handle key press */ export const useKeyProps = memoize(getKeyUpPropsWorker); + +/** Exposes the behavior of useKeyProps for the current platform as a boolean */ +export const preferKeyDownForKeyEvents = Platform.select({ + macos: true, + default: false, +}); diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.ts index 92911c1715..8e80ac429c 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.ts @@ -6,9 +6,7 @@ export type KeyCallback = (e?: KeyPressEvent) => void; export type KeyPressProps = { onKeyDown?: KeyCallback; - validKeysDown?: string[]; // macOS - keyDownEvents?: any[]; // windows + validKeysDown?: string[]; onKeyUp?: KeyCallback; - validKeysUp?: string[]; // macOS - keyUpEvents?: any[]; // windows + validKeysUp?: string[]; }; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts index 221ec99025..7cce3f7f74 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts @@ -6,9 +6,7 @@ export type KeyCallback = (e?: KeyPressEvent) => void; export type KeyPressProps = { onKeyDown?: KeyCallback; - validKeysDown?: string[]; // macOS keyDownEvents?: IHandledKeyboardEvent[]; // win32 onKeyUp?: KeyCallback; - validKeysUp?: string[]; // macOS keyUpEvents?: IHandledKeyboardEvent[]; // win32 }; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts index 1ca62efc14..3516fc8c0d 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts @@ -6,9 +6,7 @@ export type KeyCallback = (e?: KeyPressEvent) => void; export type KeyPressProps = { onKeyDown?: KeyCallback; - validKeysDown?: string[]; // macOS keyDownEvents?: IHandledKeyboardEvent[]; // Windows onKeyUp?: KeyCallback; - validKeysUp?: string[]; // macOS keyUpEvents?: IHandledKeyboardEvent[]; // Windows }; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.win32.ts b/packages/utils/interactive-hooks/src/useKeyProps.win32.ts deleted file mode 100644 index 30c56bdd1f..0000000000 --- a/packages/utils/interactive-hooks/src/useKeyProps.win32.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { KeyPressEvent, KeyCallback, KeyPressProps } from './useKeyProps.types'; -import { memoize } from '@fluentui-react-native/memo-cache'; -import { isModifierKey } from './isModifierKey'; -import * as React from 'react'; - -/** - * Re-usable hook for an onKeyDown event. - * @param userCallback The function you want to be called once the key has been activated on key up - * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns onKeyEvent() - Callback to determine if key was pressed, if so, call userCallback - * @deprecated use the hook `useKeyProps` instead - */ -export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { - const onKeyEvent = React.useCallback( - (e: KeyPressEvent) => { - if (userCallback !== undefined && (keys === undefined || keys.includes(e.nativeEvent.key))) { - userCallback(e); - e.stopPropagation(); - } - }, - [keys, userCallback], - ); - - return onKeyEvent; -} - -export function getKeyCallbackWorker(userCallback?: KeyCallback, ...keys: string[]) { - const onKeyEvent = (e: KeyPressEvent) => { - if (userCallback !== undefined && !isModifierKey(e.nativeEvent) && (keys === undefined || keys.includes(e.nativeEvent.key))) { - userCallback(e); - e.stopPropagation(); - } - }; - return onKeyEvent; -} - -function getKeyUpPropsWorker(userCallback: KeyCallback, ...keys: string[]): KeyPressProps { - return { - onKeyUp: getKeyCallbackWorker(userCallback, ...keys), - // Optional on Win32 to know which key events to suppress natively - keyUpEvents: keys.map((keyCode) => { - return { key: keyCode }; - }), - }; -} - -function getKeyDownPropsWorker(userCallback: KeyCallback, ...keys: string[]): KeyPressProps { - return { - onKeyDown: getKeyCallbackWorker(userCallback, ...keys), - // Optional on Win32 to know which key events to suppress natively - keyDownEvents: keys.map((keyCode) => { - return { key: keyCode }; - }), - }; -} - -/** - * Re-usable hook for an onKeyUp event. - * @param userCallback The function you want to be called once the key has been activated on key up - * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns KeyPressProps: An object containing the correct platform specific props to handle key press - */ -export const useKeyUpProps = memoize(getKeyUpPropsWorker); - -/** - * Re-usable hook for an onKeyDown event. - * @param userCallback The function you want to be called once the key has been activated on key down - * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns KeyPressProps: An object containing the correct platform specific props to handle key press - */ -export const useKeyDownProps = memoize(getKeyDownPropsWorker); - -/** - * Re-usable hook for keyboard events. on macOS, this is onKeyDown, while on windows this is onKeyUp. - * @param userCallback The function you want to be called once the key has been activated on key down - * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns KeyPressProps: An object containing the correct platform specific props to handle key press - */ -export const useKeyProps = memoize(getKeyUpPropsWorker); - -/** Exposes the behavior of useKeyProps for the current platform as a boolean */ -export const preferKeyDownForKeyEvents = false; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.windows.ts b/packages/utils/interactive-hooks/src/useKeyProps.windows.ts deleted file mode 100644 index d7cc11f27f..0000000000 --- a/packages/utils/interactive-hooks/src/useKeyProps.windows.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { KeyPressEvent, KeyCallback, KeyPressProps } from './useKeyProps.types'; -import { memoize } from '@fluentui-react-native/memo-cache'; -import * as React from 'react'; -import { isModifierKey } from './isModifierKey'; - -/** - * Re-usable hook for an onKeyDown event. - * @param userCallback The function you want to be called once the key has been activated on key up - * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns onKeyEvent() - Callback to determine if key was pressed, if so, call userCallback - * @deprecated use useKeyUpProps or useKeyDownProps instead - */ -export function useKeyCallback(userCallback?: KeyCallback, ...keys: string[]) { - const onKeyEvent = React.useCallback( - (e: KeyPressEvent) => { - if (userCallback !== undefined && (keys === undefined || keys.includes(e.nativeEvent.key))) { - userCallback(e); - e.stopPropagation(); - } - }, - [keys, userCallback], - ); - - return onKeyEvent; -} - -export function getKeyCallbackWorker(userCallback?: KeyCallback, ...keys: string[]) { - const onKeyEvent = (e: KeyPressEvent) => { - if (userCallback !== undefined && !isModifierKey(e.nativeEvent) && (keys === undefined || keys.includes(e.nativeEvent.key))) { - userCallback(e); - e.stopPropagation(); - } - }; - return onKeyEvent; -} - -function getKeyUpPropsWorker(userCallback: KeyCallback, ...keys: string[]): KeyPressProps { - return { - onKeyUp: getKeyCallbackWorker(userCallback, ...keys), - }; -} - -function getKeyDownPropsWorker(userCallback: KeyCallback, ...keys: string[]): KeyPressProps { - return { - onKeyDown: getKeyCallbackWorker(userCallback, ...keys), - }; -} - -/** - * Re-usable hook for an onKeyUp event. - * @param userCallback The function you want to be called once the key has been activated on key up - * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns KeyPressProps: An object containing the correct platform specific props to handle key press - */ -export const useKeyUpProps = memoize(getKeyUpPropsWorker); - -/** - * Re-usable hook for an onKeyDown event. - * @param userCallback The function you want to be called once the key has been activated on key down - * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns KeyPressProps: An object containing the correct platform specific props to handle key press - */ -export const useKeyDownProps = memoize(getKeyDownPropsWorker); - -/** - * Re-usable hook for keyboard events. on macOS, this is onKeyDown, while on windows this is onKeyUp. - * @param userCallback The function you want to be called once the key has been activated on key down - * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback - * @returns KeyPressProps: An object containing the correct platform specific props to handle key press - */ -export const useKeyProps = memoize(getKeyUpPropsWorker); - -/** Exposes the behavior of useKeyProps for the current platform as a boolean */ -export const preferKeyDownForKeyEvents = false; From fadfed705f3414562420be25c2276c3e50cdae05 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Wed, 28 Dec 2022 17:12:53 -0600 Subject: [PATCH 09/10] more --- packages/utils/interactive-hooks/package.json | 1 + .../utils/interactive-hooks/src/useKeyProps.types.win32.ts | 4 ++-- .../utils/interactive-hooks/src/useKeyProps.types.windows.ts | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/utils/interactive-hooks/package.json b/packages/utils/interactive-hooks/package.json index d8abfd0a7a..ec4c1f6e72 100644 --- a/packages/utils/interactive-hooks/package.json +++ b/packages/utils/interactive-hooks/package.json @@ -34,6 +34,7 @@ }, "devDependencies": { "@fluentui-react-native/eslint-config-rules": "^0.1.1", + "@fluentui-react-native/test-tools": ">=0.1.1 <1.0.0", "@office-iss/react-native-win32": "^0.68.0", "@types/invariant": "^2.2.0", "@types/jest": "^26.0.0", diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts index 7cce3f7f74..1d22202618 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.win32.ts @@ -1,6 +1,6 @@ -import { IKeyPressEvent, IHandledKeyboardEvent } from '@office-iss/react-native-win32'; +import { IKeyboardEvent, IHandledKeyboardEvent } from '@office-iss/react-native-win32'; -export type KeyPressEvent = IKeyPressEvent; +export type KeyPressEvent = IKeyboardEvent; export type KeyCallback = (e?: KeyPressEvent) => void; diff --git a/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts index 3516fc8c0d..37f204eeb7 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.windows.ts @@ -1,6 +1,6 @@ -import { IKeyPressEvent, IHandledKeyboardEvent } from 'react-native-windows'; +import { IKeyboardEvent, IHandledKeyboardEvent } from 'react-native-windows'; -export type KeyPressEvent = IKeyPressEvent; +export type KeyPressEvent = IKeyboardEvent; export type KeyCallback = (e?: KeyPressEvent) => void; From d26a452f54877d54986ba7c05ff2f2e9b00a0878 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Thu, 29 Dec 2022 13:48:25 -0600 Subject: [PATCH 10/10] PR comments --- .../src/__tests__/useKeyProps.test.tsx | 6 ++++++ .../utils/interactive-hooks/src/useKeyProps.ts | 14 +++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx b/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx index 2ed0eafb87..7b31ea1942 100644 --- a/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx +++ b/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx @@ -20,6 +20,12 @@ it('Pressable with useKeyProps', () => { expect(tree).toMatchSnapshot(); }); +it('useKeyProps called twice', () => { + const keyboardProps1 = useKeyProps(dummyFunction, ' ', 'Enter'); + const keyboardProps2 = useKeyProps(dummyFunction, ' ', 'Enter'); + expect(keyboardProps1).toBe(keyboardProps2); +}); + it('Simple Pressable with useKeyProps rendering does not invalidate styling', () => { const keyboardProps = useKeyProps(dummyFunction, ' ', 'Enter'); checkRenderConsistency(() => , 2); diff --git a/packages/utils/interactive-hooks/src/useKeyProps.ts b/packages/utils/interactive-hooks/src/useKeyProps.ts index 1b4e96e54a..f08743df59 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.ts @@ -119,16 +119,16 @@ export const useKeyUpProps = memoize(getKeyUpPropsWorker); */ export const useKeyDownProps = memoize(getKeyDownPropsWorker); +/** Exposes the behavior of useKeyProps for the current platform as a boolean */ +export const preferKeyDownForKeyEvents = Platform.select({ + macos: true, + default: false, +}); + /** * Re-usable hook for keyboard events. on macOS, this is onKeyDown, while on windows this is onKeyUp. * @param userCallback The function you want to be called once the key has been activated on key down * @param keys A string of the key you want to perform some action on. If undefined, always invokes userCallback * @returns KeyPressProps: An object containing the correct platform specific props to handle key press */ -export const useKeyProps = memoize(getKeyUpPropsWorker); - -/** Exposes the behavior of useKeyProps for the current platform as a boolean */ -export const preferKeyDownForKeyEvents = Platform.select({ - macos: true, - default: false, -}); +export const useKeyProps = preferKeyDownForKeyEvents ? useKeyDownProps : useKeyUpProps;