[add] Pressable support for hover callbacks

Add 'onHoverIn' and 'onHoverOut' props to Pressable.

Fix #1804
This commit is contained in:
Nicolas Gallagher
2021-02-05 15:55:08 -08:00
parent d6d28a4886
commit 683962b961
3 changed files with 24 additions and 3 deletions
@@ -88,11 +88,15 @@ describe('components/Pressable', () => {
test('hover interaction', () => {
let container;
const onHoverIn = jest.fn();
const onHoverOut = jest.fn();
const ref = React.createRef();
act(() => {
({ container } = render(
<Pressable
children={({ hovered }) => (hovered ? <div data-testid="hover-content" /> : null)}
onHoverIn={onHoverIn}
onHoverOut={onHoverOut}
ref={ref}
style={({ hovered }) => [hovered && { outline: 'hover-ring' }]}
/>
@@ -103,10 +107,12 @@ describe('components/Pressable', () => {
act(() => {
target.pointerover();
});
expect(onHoverIn).toBeCalled();
expect(container.firstChild).toMatchSnapshot();
act(() => {
target.pointerout();
});
expect(onHoverOut).toBeCalled();
expect(container.firstChild).toMatchSnapshot();
});
+17 -2
View File
@@ -10,6 +10,7 @@
'use strict';
import type { HoverEventsConfig } from '../../modules/useHover';
import type { PressResponderConfig } from '../../modules/usePressEvents/PressResponder';
import type { ViewProps } from '../View';
@@ -51,6 +52,10 @@ type Props = $ReadOnly<{|
onBlur?: $PropertyType<ViewProps, 'onBlur'>,
// Called when the view is focused
onFocus?: $PropertyType<ViewProps, 'onFocus'>,
// Called when the view is hovered
onHoverIn?: $PropertyType<HoverEventsConfig, 'onHoverStart'>,
// Called when the view is no longer hovered
onHoverOut?: $PropertyType<HoverEventsConfig, 'onHoverEnd'>,
// Called when this view's layout changes
onLayout?: $PropertyType<ViewProps, 'onLayout'>,
// Called when a long-tap gesture is detected.
@@ -68,6 +73,7 @@ type Props = $ReadOnly<{|
/**
* Used only for documentation or testing (e.g. snapshot testing).
*/
testOnly_hovered?: ?boolean,
testOnly_pressed?: ?boolean
|}>;
@@ -85,17 +91,20 @@ function Pressable(props: Props, forwardedRef): React.Node {
focusable,
onBlur,
onFocus,
onHoverIn,
onHoverOut,
onLongPress,
onPress,
onPressMove,
onPressIn,
onPressOut,
style,
testOnly_hovered,
testOnly_pressed,
...rest
} = props;
const [hovered, setHovered] = useForceableState(false);
const [hovered, setHovered] = useForceableState(testOnly_hovered === true);
const [focused, setFocused] = useForceableState(false);
const [pressed, setPressed] = useForceableState(testOnly_pressed === true);
@@ -131,7 +140,13 @@ function Pressable(props: Props, forwardedRef): React.Node {
const pressEventHandlers = usePressEvents(hostRef, pressConfig);
useHover(hostRef, { contain: true, disabled, onHoverChange: setHovered });
useHover(hostRef, {
contain: true,
disabled,
onHoverChange: setHovered,
onHoverStart: onHoverIn,
onHoverEnd: onHoverOut
});
const interactionState = { hovered, focused, pressed };
+1 -1
View File
@@ -15,7 +15,7 @@ import useLayoutEffect from '../useLayoutEffect';
* Types
*/
type HoverEventsConfig = {
export type HoverEventsConfig = {
contain?: ?boolean,
disabled?: ?boolean,
onHoverStart?: ?(e: any) => void,