Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added pointerEvents style equivalent to pointerEvents prop #34586

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flattendStyle => flattenedStyle

const newPointerEvents = pointerEvents || flattendStyle?.pointerEvents;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should have made the style take priority

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