mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-06-05 03:09:23 +00:00
[add] Pressable support for hover callbacks
Add 'onHoverIn' and 'onHoverOut' props to Pressable. Fix #1804
This commit is contained in:
@@ -88,11 +88,15 @@ describe('components/Pressable', () => {
|
|||||||
|
|
||||||
test('hover interaction', () => {
|
test('hover interaction', () => {
|
||||||
let container;
|
let container;
|
||||||
|
const onHoverIn = jest.fn();
|
||||||
|
const onHoverOut = jest.fn();
|
||||||
const ref = React.createRef();
|
const ref = React.createRef();
|
||||||
act(() => {
|
act(() => {
|
||||||
({ container } = render(
|
({ container } = render(
|
||||||
<Pressable
|
<Pressable
|
||||||
children={({ hovered }) => (hovered ? <div data-testid="hover-content" /> : null)}
|
children={({ hovered }) => (hovered ? <div data-testid="hover-content" /> : null)}
|
||||||
|
onHoverIn={onHoverIn}
|
||||||
|
onHoverOut={onHoverOut}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
style={({ hovered }) => [hovered && { outline: 'hover-ring' }]}
|
style={({ hovered }) => [hovered && { outline: 'hover-ring' }]}
|
||||||
/>
|
/>
|
||||||
@@ -103,10 +107,12 @@ describe('components/Pressable', () => {
|
|||||||
act(() => {
|
act(() => {
|
||||||
target.pointerover();
|
target.pointerover();
|
||||||
});
|
});
|
||||||
|
expect(onHoverIn).toBeCalled();
|
||||||
expect(container.firstChild).toMatchSnapshot();
|
expect(container.firstChild).toMatchSnapshot();
|
||||||
act(() => {
|
act(() => {
|
||||||
target.pointerout();
|
target.pointerout();
|
||||||
});
|
});
|
||||||
|
expect(onHoverOut).toBeCalled();
|
||||||
expect(container.firstChild).toMatchSnapshot();
|
expect(container.firstChild).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+17
-2
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
import type { HoverEventsConfig } from '../../modules/useHover';
|
||||||
import type { PressResponderConfig } from '../../modules/usePressEvents/PressResponder';
|
import type { PressResponderConfig } from '../../modules/usePressEvents/PressResponder';
|
||||||
import type { ViewProps } from '../View';
|
import type { ViewProps } from '../View';
|
||||||
|
|
||||||
@@ -51,6 +52,10 @@ type Props = $ReadOnly<{|
|
|||||||
onBlur?: $PropertyType<ViewProps, 'onBlur'>,
|
onBlur?: $PropertyType<ViewProps, 'onBlur'>,
|
||||||
// Called when the view is focused
|
// Called when the view is focused
|
||||||
onFocus?: $PropertyType<ViewProps, 'onFocus'>,
|
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
|
// Called when this view's layout changes
|
||||||
onLayout?: $PropertyType<ViewProps, 'onLayout'>,
|
onLayout?: $PropertyType<ViewProps, 'onLayout'>,
|
||||||
// Called when a long-tap gesture is detected.
|
// 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).
|
* Used only for documentation or testing (e.g. snapshot testing).
|
||||||
*/
|
*/
|
||||||
|
testOnly_hovered?: ?boolean,
|
||||||
testOnly_pressed?: ?boolean
|
testOnly_pressed?: ?boolean
|
||||||
|}>;
|
|}>;
|
||||||
|
|
||||||
@@ -85,17 +91,20 @@ function Pressable(props: Props, forwardedRef): React.Node {
|
|||||||
focusable,
|
focusable,
|
||||||
onBlur,
|
onBlur,
|
||||||
onFocus,
|
onFocus,
|
||||||
|
onHoverIn,
|
||||||
|
onHoverOut,
|
||||||
onLongPress,
|
onLongPress,
|
||||||
onPress,
|
onPress,
|
||||||
onPressMove,
|
onPressMove,
|
||||||
onPressIn,
|
onPressIn,
|
||||||
onPressOut,
|
onPressOut,
|
||||||
style,
|
style,
|
||||||
|
testOnly_hovered,
|
||||||
testOnly_pressed,
|
testOnly_pressed,
|
||||||
...rest
|
...rest
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [hovered, setHovered] = useForceableState(false);
|
const [hovered, setHovered] = useForceableState(testOnly_hovered === true);
|
||||||
const [focused, setFocused] = useForceableState(false);
|
const [focused, setFocused] = useForceableState(false);
|
||||||
const [pressed, setPressed] = useForceableState(testOnly_pressed === true);
|
const [pressed, setPressed] = useForceableState(testOnly_pressed === true);
|
||||||
|
|
||||||
@@ -131,7 +140,13 @@ function Pressable(props: Props, forwardedRef): React.Node {
|
|||||||
|
|
||||||
const pressEventHandlers = usePressEvents(hostRef, pressConfig);
|
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 };
|
const interactionState = { hovered, focused, pressed };
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ import useLayoutEffect from '../useLayoutEffect';
|
|||||||
* Types
|
* Types
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type HoverEventsConfig = {
|
export type HoverEventsConfig = {
|
||||||
contain?: ?boolean,
|
contain?: ?boolean,
|
||||||
disabled?: ?boolean,
|
disabled?: ?boolean,
|
||||||
onHoverStart?: ?(e: any) => void,
|
onHoverStart?: ?(e: any) => void,
|
||||||
|
|||||||
Reference in New Issue
Block a user