Skip to content

Commit d2269f6

Browse files
authored
Trigger non-touch events on box-none targets (#906)
* Trigger non-touch events on box-none targets Currently, this library disables _all_ events for a target with `pointerEvents="box-none"`. This behavior is counter to how React Native itself functions. This change continues to disable touch events, e.g. `press`, for targets set to "box-none", but allows triggering non-touch events, e.g. `layout`, `touchStart`. * Event triggers target box-none View instead of child This approach more closely aligns with the original failing test case. * Rename events in test description Attempt to better communicate the test is focused on ensuring that touch events continue to trigger (e.g. `touchStart`), but the final event from a touch tap does not trigger.
1 parent 8ce39f5 commit d2269f6

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

src/__tests__/fireEvent.test.tsx

+34
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,40 @@ test('should not fire on box-only pointerEvents View with nested elements', () =
333333
expect(handlePress).not.toHaveBeenCalled();
334334
});
335335

336+
test('should fire non-pointer events on box-none pointerEvents View', () => {
337+
const handleTouchStart = jest.fn();
338+
339+
const screen = render(
340+
<View
341+
pointerEvents="box-none"
342+
onTouchStart={handleTouchStart}
343+
testID="touch-start-view"
344+
>
345+
<Pressable onPress={() => {}}>
346+
<Text>Trigger</Text>
347+
</Pressable>
348+
</View>
349+
);
350+
351+
fireEvent(screen.getByTestId('touch-start-view'), 'touchStart');
352+
expect(handleTouchStart).toHaveBeenCalled();
353+
});
354+
355+
test('should fire non-touch events on box-none pointerEvents View', () => {
356+
const handleLayout = jest.fn();
357+
358+
const screen = render(
359+
<View pointerEvents="box-none" onLayout={handleLayout} testID="layout-view">
360+
<Pressable onPress={() => {}}>
361+
<Text>Trigger</Text>
362+
</Pressable>
363+
</View>
364+
);
365+
366+
fireEvent(screen.getByTestId('layout-view'), 'layout');
367+
expect(handleLayout).toHaveBeenCalled();
368+
});
369+
336370
test('should pass event up on disabled TouchableOpacity', () => {
337371
const handleInnerPress = jest.fn();
338372
const handleOuterPress = jest.fn();

src/fireEvent.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,17 @@ const isPointerEventEnabled = (
3535
return isPointerEventEnabled(element.parent, true);
3636
};
3737

38+
const isTouchEvent = (eventName?: string) => {
39+
return eventName === 'press';
40+
};
41+
3842
const isEventEnabled = (
3943
element?: ReactTestInstance,
40-
touchResponder?: ReactTestInstance
44+
touchResponder?: ReactTestInstance,
45+
eventName?: string
4146
) => {
4247
if (isTextInput(element)) return element?.props.editable !== false;
43-
if (!isPointerEventEnabled(element)) return false;
48+
if (!isPointerEventEnabled(element) && isTouchEvent(eventName)) return false;
4449

4550
const touchStart = touchResponder?.props.onStartShouldSetResponder?.();
4651
const touchMove = touchResponder?.props.onMoveShouldSetResponder?.();
@@ -61,7 +66,8 @@ const findEventHandler = (
6166
: nearestTouchResponder;
6267

6368
const handler = getEventHandler(element, eventName);
64-
if (handler && isEventEnabled(element, touchResponder)) return handler;
69+
if (handler && isEventEnabled(element, touchResponder, eventName))
70+
return handler;
6571

6672
if (element.parent === null || element.parent.parent === null) {
6773
return null;

0 commit comments

Comments
 (0)