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" +} 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..ec4c1f6e72 100644 --- a/packages/utils/interactive-hooks/package.json +++ b/packages/utils/interactive-hooks/package.json @@ -34,13 +34,16 @@ }, "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", "@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..37505ad221 --- /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[`Pressable with useKeyProps 1`] = ` + +`; 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..ae4a34849c 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 '../useKeyProps.types'; +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..7b31ea1942 --- /dev/null +++ b/packages/utils/interactive-hooks/src/__tests__/useKeyProps.test.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import * as renderer from 'react-test-renderer'; +import { Pressable } from 'react-native'; +import { useKeyProps } from '../useKeyProps'; +import { checkRenderConsistency, 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('Pressable with useKeyProps', () => { + const keyboardProps = useKeyProps(dummyFunction, ' ', 'Enter'); + const tree = renderer.create().toJSON(); + 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); +}); + +it('Pressable with useKeyProps re-renders correctly', () => { + const keyboardProps = useKeyProps(dummyFunction, ' ', 'Enter'); + checkReRender(() => , 2); +}); 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/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 cc8a38649b..0000000000 --- a/packages/utils/interactive-hooks/src/useKeyProps.macos.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { KeyCallback, KeyPressProps } from './useKeyProps'; -import { KeyPressEvent } from './Pressability/CoreEventTypes'; -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( - (args: KeyPressEvent) => { - if (userCallback !== undefined && (keys === undefined || keys.includes(args.nativeEvent.key))) { - userCallback(args); - args.stopPropagation(); - } - }, - [userCallback, ...keys], - ); - - return onKeyEvent; -} - -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(); - } - }; - 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 f65ae8e8d6..f08743df59 100644 --- a/packages/utils/interactive-hooks/src/useKeyProps.ts +++ b/packages/utils/interactive-hooks/src/useKeyProps.ts @@ -1,20 +1,26 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import { KeyPressEvent } from './Pressability/CoreEventTypes'; -import { IHandledKeyboardEvent } from '@office-iss/react-native-win32'; - -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 -}; +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'; -// eslint-disable-next-line @typescript-eslint/no-empty-function -const noOp = () => {}; +/** + * 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. @@ -23,38 +29,106 @@ const noOp = () => {}; * @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; +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; } -// eslint-disable-next-line @typescript-eslint/no-empty-function -const noOp2 = (_userCallback: KeyCallback, ..._keys: string[]) => { - return {}; -}; +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 { + 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; +} /** - * 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); + +/** 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 + * @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 = preferKeyDownForKeyEvents ? useKeyDownProps : useKeyUpProps; 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..0e08ea17fd --- /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; +} + +export type KeyPressEvent = NativeSyntheticEvent; + +export type KeyCallback = (e?: 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.ts b/packages/utils/interactive-hooks/src/useKeyProps.types.ts new file mode 100644 index 0000000000..8e80ac429c --- /dev/null +++ b/packages/utils/interactive-hooks/src/useKeyProps.types.ts @@ -0,0 +1,12 @@ +import { NativeSyntheticEvent } from 'react-native'; + +export type KeyPressEvent = NativeSyntheticEvent; + +export type KeyCallback = (e?: KeyPressEvent) => void; + +export type KeyPressProps = { + onKeyDown?: KeyCallback; + validKeysDown?: string[]; + onKeyUp?: KeyCallback; + validKeysUp?: string[]; +}; 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..1d22202618 --- /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 KeyPressEvent = IKeyboardEvent; + +export type KeyCallback = (e?: KeyPressEvent) => void; + +export type KeyPressProps = { + onKeyDown?: KeyCallback; + keyDownEvents?: IHandledKeyboardEvent[]; // win32 + onKeyUp?: KeyCallback; + 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..37f204eeb7 --- /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 KeyPressEvent = IKeyboardEvent; + +export type KeyCallback = (e?: KeyPressEvent) => void; + +export type KeyPressProps = { + onKeyDown?: KeyCallback; + keyDownEvents?: IHandledKeyboardEvent[]; // Windows + onKeyUp?: KeyCallback; + 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 7321272c2a..0000000000 --- a/packages/utils/interactive-hooks/src/useKeyProps.win32.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { KeyCallback, KeyPressProps } from './useKeyProps'; -import { KeyPressEvent } from './Pressability/CoreEventTypes'; -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( - (args: KeyPressEvent) => { - if (userCallback !== undefined && (keys === undefined || keys.includes(args.nativeEvent.key))) { - userCallback(args); - args.stopPropagation(); - } - }, - [userCallback, ...keys], - ); - - return onKeyEvent; -} - -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(); - } - }; - 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 90cb64bb56..0000000000 --- a/packages/utils/interactive-hooks/src/useKeyProps.windows.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { KeyCallback, KeyPressProps } from './useKeyProps'; -import { KeyPressEvent } from './Pressability/CoreEventTypes'; -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( - (args: KeyPressEvent) => { - if (userCallback !== undefined && (keys === undefined || keys.includes(args.nativeEvent.key))) { - userCallback(args); - args.stopPropagation(); - } - }, - [userCallback, ...keys], - ); - - return onKeyEvent; -} - -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(); - } - }; - 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;