mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
7bcae81299
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
216 lines
6.1 KiB
JavaScript
Executable File
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;
|