Files
react-native/Libraries/Components/Touchable/TouchableWithoutFeedback.js
T
Tim Yung 7bcae81299 RN: Stop Exporting TouchableWithoutFeedback Props
Summary:
Changes `TouchableWithoutFeedback` so that `Props` is no longer exported as a Flow type.

Instead, other modules should use `React.ElementConfig<typeof TouchableWithoutFeedback>`.

Changelog:
[General] [Removed] - TouchableWithoutFeedback no longer exports Props. Use React.ElementConfig, instead.

Reviewed By: zackargyle, TheSavior

Differential Revision: D18718131

fbshipit-source-id: 0bd63123c49564fdab160d5fc8e7f1bf86da1fbe
2019-11-27 07:48:40 -08:00

216 lines
6.1 KiB
JavaScript
Executable File

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
'use strict';
import Pressability from '../../Pressability/Pressability.js';
import {PressabilityDebugView} from '../../Pressability/PressabilityDebug.js';
import TVTouchable from './TVTouchable.js';
import type {
AccessibilityActionEvent,
AccessibilityActionInfo,
AccessibilityRole,
AccessibilityState,
AccessibilityValue,
} from '../../Components/View/ViewAccessibility';
import type {EdgeInsetsProp} from '../../StyleSheet/EdgeInsetsPropType';
import type {
BlurEvent,
FocusEvent,
LayoutEvent,
PressEvent,
} from '../../Types/CoreEventTypes';
import {Platform, View} from 'react-native';
import * as React from 'react';
type Props = $ReadOnly<{|
accessibilityActions?: ?$ReadOnlyArray<AccessibilityActionInfo>,
accessibilityElementsHidden?: ?boolean,
accessibilityHint?: ?Stringish,
accessibilityIgnoresInvertColors?: ?boolean,
accessibilityLabel?: ?Stringish,
accessibilityLiveRegion?: ?('none' | 'polite' | 'assertive'),
accessibilityRole?: ?AccessibilityRole,
accessibilityState?: ?AccessibilityState,
accessibilityValue?: ?AccessibilityValue,
accessibilityViewIsModal?: ?boolean,
accessible?: ?boolean,
children?: ?React.Node,
delayLongPress?: ?number,
delayPressIn?: ?number,
delayPressOut?: ?number,
disabled?: ?boolean,
focusable?: ?boolean,
hitSlop?: ?EdgeInsetsProp,
importantForAccessibility?: ?('auto' | 'yes' | 'no' | 'no-hide-descendants'),
nativeID?: ?string,
onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed,
onBlur?: ?(event: BlurEvent) => mixed,
onFocus?: ?(event: FocusEvent) => mixed,
onLayout?: ?(event: LayoutEvent) => mixed,
onLongPress?: ?(event: PressEvent) => mixed,
onPress?: ?(event: PressEvent) => mixed,
onPressIn?: ?(event: PressEvent) => mixed,
onPressOut?: ?(event: PressEvent) => mixed,
pressRetentionOffset?: ?EdgeInsetsProp,
rejectResponderTermination?: ?boolean,
testID?: ?string,
touchSoundDisabled?: ?boolean,
|}>;
type State = $ReadOnly<{|
pressability: Pressability,
|}>;
const PASSTHROUGH_PROPS = [
'accessibilityActions',
'accessibilityElementsHidden',
'accessibilityHint',
'accessibilityIgnoresInvertColors',
'accessibilityLabel',
'accessibilityLiveRegion',
'accessibilityRole',
'accessibilityState',
'accessibilityValue',
'accessibilityViewIsModal',
'hitSlop',
'importantForAccessibility',
'nativeID',
'onAccessibilityAction',
'onBlur',
'onFocus',
'onLayout',
'testID',
];
class TouchableWithoutFeedback extends React.Component<Props, State> {
_tvTouchable: ?TVTouchable;
state: State = {
pressability: new Pressability({
getHitSlop: () => this.props.hitSlop,
getLongPressDelayMS: () => {
if (this.props.delayLongPress != null) {
const maybeNumber = this.props.delayLongPress;
if (typeof maybeNumber === 'number') {
return maybeNumber;
}
}
return 500;
},
getPressDelayMS: () => this.props.delayPressIn,
getPressOutDelayMS: () => this.props.delayPressOut,
getPressRectOffset: () => this.props.pressRetentionOffset,
getTouchSoundDisabled: () => this.props.touchSoundDisabled,
onBlur: event => {
if (this.props.onBlur != null) {
this.props.onBlur(event);
}
},
onFocus: event => {
if (this.props.onFocus != null) {
this.props.onFocus(event);
}
},
onLongPress: event => {
if (this.props.onLongPress != null) {
this.props.onLongPress(event);
}
},
onPress: event => {
if (this.props.onPress != null) {
this.props.onPress(event);
}
},
onPressIn: event => {
if (this.props.onPressIn != null) {
this.props.onPressIn(event);
}
},
onPressOut: event => {
if (this.props.onPressOut != null) {
this.props.onPressOut(event);
}
},
onResponderTerminationRequest: () =>
!this.props.rejectResponderTermination,
onStartShouldSetResponder: () => !this.props.disabled,
}),
};
render(): React.Node {
const element = React.Children.only(this.props.children);
const children = [element.props.children];
if (__DEV__) {
if (element.type === View) {
children.push(
<PressabilityDebugView color="red" hitSlop={this.props.hitSlop} />,
);
}
}
// BACKWARD-COMPATIBILITY: Focus and blur events were never supported before
// adopting `Pressability`, so preserve that behavior.
const {
onBlur,
onFocus,
...eventHandlersWithoutBlurAndFocus
} = this.state.pressability.getEventHandlers();
const elementProps: {[string]: mixed, ...} = {
...eventHandlersWithoutBlurAndFocus,
accessible: this.props.accessible !== false,
focusable:
this.props.focusable !== false && this.props.onPress !== undefined,
};
for (const prop of PASSTHROUGH_PROPS) {
if (this.props[prop] !== undefined) {
elementProps[prop] = this.props[prop];
}
}
return React.cloneElement(element, elementProps, ...children);
}
componentDidMount(): void {
if (Platform.isTV) {
this._tvTouchable = new TVTouchable(this, {
getDisabled: () => this.props.disabled === true,
onBlur: event => {
if (this.props.onBlur != null) {
this.props.onBlur(event);
}
},
onFocus: event => {
if (this.props.onFocus != null) {
this.props.onFocus(event);
}
},
onPress: event => {
if (this.props.onPress != null) {
this.props.onPress(event);
}
},
});
}
}
componentWillUnmount(): void {
if (Platform.isTV) {
if (this._tvTouchable != null) {
this._tvTouchable.destroy();
}
}
this.state.pressability.reset();
}
}
module.exports = TouchableWithoutFeedback;