Skip to content

Commit

Permalink
feat: Added pointerEvents style equivalent to pointerEvents prop (#34586
Browse files Browse the repository at this point in the history
)

Summary:
This adds `pointerEvents` style which is equivalent to `pointerEvents` prop as requested in #34425

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->

[General] [Added] - Added pointerEvents style equivalent to pointerEvents prop

Pull Request resolved: #34586

Test Plan:
```
<View
   style={{
     pointerEvents: 'none'
   }}
 >
</View>
```

Reviewed By: cipolleschi

Differential Revision: D39252830

Pulled By: jacdebug

fbshipit-source-id: 94f265a6b6940a4371e7985d5de3b8143693e069
  • Loading branch information
cyrus25 authored and facebook-github-bot committed Sep 5, 2022
1 parent 5c211f2 commit 5c109b3
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 1 deletion.
1 change: 1 addition & 0 deletions Libraries/Components/View/ReactNativeStyleAttributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
borderTopRightRadius: true,
borderTopStartRadius: true,
opacity: true,
pointerEvents: true,

/**
* Text
Expand Down
10 changes: 9 additions & 1 deletion Libraries/Components/View/View.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {ViewProps} from './ViewPropTypes';

import ViewNativeComponent from './ViewNativeComponent';
import TextAncestor from '../../Text/TextAncestor';
import flattenStyle from '../../StyleSheet/flattenStyle';
import * as React from 'react';

export type Props = ViewProps;
Expand All @@ -27,12 +28,19 @@ const View: React.AbstractComponent<
ViewProps,
React.ElementRef<typeof ViewNativeComponent>,
> = React.forwardRef(
({tabIndex, focusable, ...otherProps}: ViewProps, forwardedRef) => {
(
{tabIndex, focusable, style, pointerEvents, ...otherProps}: ViewProps,
forwardedRef,
) => {
const flattendStyle = flattenStyle(style);
const newPointerEvents = pointerEvents || flattendStyle?.pointerEvents;
return (
<TextAncestor.Provider value={false}>
<ViewNativeComponent
focusable={tabIndex !== undefined ? !tabIndex : focusable}
{...otherProps}
style={style}
pointerEvents={newPointerEvents}
ref={forwardedRef}
/>
</TextAncestor.Provider>
Expand Down
1 change: 1 addition & 0 deletions Libraries/StyleSheet/StyleSheetTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,7 @@ export type ____ViewStyle_InternalCore = $ReadOnly<{
borderTopWidth?: number | AnimatedNode,
opacity?: number | AnimatedNode,
elevation?: number,
pointerEvents?: 'auto' | 'none' | 'box-none' | 'box-only',
}>;

export type ____ViewStyle_Internal = $ReadOnly<{
Expand Down
132 changes: 132 additions & 0 deletions packages/rn-tester/js/examples/PointerEvents/PointerEventsExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,36 @@ class NoneExample extends React.Component<$FlowFixMeProps> {
}
}

class NoneStyleExample extends React.Component<$FlowFixMeProps> {
render(): React.Node {
return (
<View
onTouchStart={() => this.props.onLog('A unspecified touched')}
style={styles.box}>
<DemoText style={styles.text}>A: unspecified</DemoText>
<View
onTouchStart={() => this.props.onLog('B none touched')}
style={[
styles.box,
styles.boxPassedThrough,
styles.pointerEventNone,
]}>
<DemoText style={[styles.text, styles.textPassedThrough]}>
B: none
</DemoText>
<View
onTouchStart={() => this.props.onLog('C unspecified touched')}
style={[styles.box, styles.boxPassedThrough]}>
<DemoText style={[styles.text, styles.textPassedThrough]}>
C: unspecified
</DemoText>
</View>
</View>
</View>
);
}
}

/**
* Special demo text that makes itself untouchable so that it doesn't destroy
* the experiment and confuse the output.
Expand Down Expand Up @@ -142,6 +172,41 @@ class BoxNoneExample extends React.Component<$FlowFixMeProps> {
}
}

class BoxNoneStyleExample extends React.Component<$FlowFixMeProps> {
render(): React.Node {
return (
<View
onTouchStart={() => this.props.onLog('A unspecified touched')}
style={styles.box}>
<DemoText style={styles.text}>A: unspecified</DemoText>
<View
onTouchStart={() => this.props.onLog('B box-none touched')}
style={[
styles.box,
styles.boxPassedThrough,
styles.pointerEventBoxNone,
]}>
<DemoText style={[styles.text, styles.textPassedThrough]}>
B: box-none
</DemoText>
<View
onTouchStart={() => this.props.onLog('C unspecified touched')}
style={styles.box}>
<DemoText style={styles.text}>C: unspecified</DemoText>
</View>
<View
onTouchStart={() =>
this.props.onLog('C explicitly unspecified touched')
}
style={[styles.box, styles.pointerEventAuto]}>
<DemoText style={[styles.text]}>C: explicitly unspecified</DemoText>
</View>
</View>
</View>
);
}
}

class BoxOnlyExample extends React.Component<$FlowFixMeProps> {
render(): React.Node {
return (
Expand Down Expand Up @@ -177,6 +242,43 @@ class BoxOnlyExample extends React.Component<$FlowFixMeProps> {
}
}

class BoxOnlyStyleExample extends React.Component<$FlowFixMeProps> {
render(): React.Node {
return (
<View
onTouchStart={() => this.props.onLog('A unspecified touched')}
style={styles.box}>
<DemoText style={styles.text}>A: unspecified</DemoText>
<View
onTouchStart={() => this.props.onLog('B box-only touched')}
style={[styles.box, styles.pointerEventBoxOnly]}>
<DemoText style={styles.text}>B: box-only</DemoText>
<View
onTouchStart={() => this.props.onLog('C unspecified touched')}
style={[styles.box, styles.boxPassedThrough]}>
<DemoText style={[styles.text, styles.textPassedThrough]}>
C: unspecified
</DemoText>
</View>
<View
onTouchStart={() =>
this.props.onLog('C explicitly unspecified touched')
}
style={[
styles.box,
styles.boxPassedThrough,
styles.pointerEventAuto,
]}>
<DemoText style={[styles.text, styles.textPassedThrough]}>
C: explicitly unspecified
</DemoText>
</View>
</View>
</View>
);
}
}

type OverflowExampleProps = $ReadOnly<{|
overflow: 'hidden' | 'visible',
onLog: (msg: string) => void,
Expand Down Expand Up @@ -242,18 +344,36 @@ const exampleClasses: Array<ExampleClass> = [
description:
'`none` causes touch events on the container and its child components to pass through to the parent container.',
},
{
Component: NoneStyleExample,
title: '`none` style',
description:
'`none` causes touch events on the container and its child components to pass through to the parent container.',
},
{
Component: BoxNoneExample,
title: '`box-none`',
description:
'`box-none` causes touch events on the container to pass through and will only detect touch events on its child components.',
},
{
Component: BoxNoneStyleExample,
title: '`box-none` style',
description:
'`box-none` causes touch events on the container to pass through and will only detect touch events on its child components.',
},
{
Component: BoxOnlyExample,
title: '`box-only`',
description:
"`box-only` causes touch events on the container's child components to pass through and will only detect touch events on the container itself.",
},
{
Component: BoxOnlyStyleExample,
title: '`box-only` style',
description:
"`box-only` causes touch events on the container's child components to pass through and will only detect touch events on the container itself.",
},
{
Component: OverflowVisibleExample,
title: '`overflow: visible`',
Expand Down Expand Up @@ -326,6 +446,18 @@ const styles = StyleSheet.create({
borderColor: '#f0f0f0',
backgroundColor: '#f9f9f9',
},
pointerEventBoxNone: {
pointerEvents: 'box-none',
},
pointerEventBoxOnly: {
pointerEvents: 'box-only',
},
pointerEventNone: {
pointerEvents: 'none',
},
pointerEventAuto: {
pointerEvents: 'auto',
},
});

exports.framework = 'React';
Expand Down

0 comments on commit 5c109b3

Please sign in to comment.