[Web] Add hover callbacks to Touchable (#4398)
## Description
Hover on web comes straight from the `onPointerEnter`/`onPointerLeave`
the button already uses for its own animation, rather than through the
press pipeline.
- Reported from the pointer handlers rather than an effect, so a leave
and a re-enter batched into one render still produce both events. The
effect only covers `enabled` flipping while the pointer is inside.
- `hovered` is now tracked regardless of `enabled` and masked at render,
so hover resumes on its own when `enabled` flips back with the pointer
still inside — matching the native platforms.
- The payload uses the same coordinate basis as `PointerEventManager`'s
`mapEvent`. Both reads force a layout flush, so it's only built when a
hover callback is actually present.
## Test plan
The `.web` variant isn't resolved by the React Native Jest preset, so
this needs a browser — with a mouse and with a pen.
<details>
<summary>Example code</summary>
```tsx
import React, { useState } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import {
GestureHandlerRootView,
Touchable,
} from 'react-native-gesture-handler';
export default function Example() {
const [log, setLog] = useState<string[]>([]);
const callbacks = (source: string) => ({
onHoverIn: () => setLog((l) => [`${source} onHoverIn`, ...l]),
onHoverOut: () => setLog((l) => [`${source} onHoverOut`, ...l]),
onPressIn: () => setLog((l) => [`${source} onPressIn`, ...l]),
onPressOut: () => setLog((l) => [`${source} onPressOut`, ...l]),
});
return (
<GestureHandlerRootView style={styles.container}>
<View style={styles.row}>
<Touchable style={styles.box} {...callbacks('Touchable')}>
<Text style={styles.text}>Touchable</Text>
</Touchable>
<Pressable style={styles.box} {...callbacks('Pressable')}>
<Text style={styles.text}>Pressable</Text>
</Pressable>
</View>
{log.slice(0, 12).map((entry, i) => (
<Text key={i}>{entry}</Text>
))}
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 24 },
row: { flexDirection: 'row', gap: 24, marginBottom: 24 },
box: {
width: 120,
height: 120,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#6941C6',
},
text: { color: 'white' },
});
```
</details> J
Jakub Piasecki committed
1994741515a3ea08f9708c244e6520d9829f34ce
Parent: 34f5e48
Committed by GitHub <noreply@github.com>
on 8/10/2026, 7:57:32 AM