@react-native-oh/react-native-harmony 0.72.23-3 → 0.72.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/Alert/Alert.harmony.js +71 -71
- package/Libraries/Alert/AlertManager.ts +35 -35
- package/Libraries/Animated/NativeAnimatedHelper.harmony.js +601 -601
- package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.harmony.js +445 -426
- package/Libraries/Components/AccessibilityInfo/NativeAccessibilityManager.harmony.js +30 -0
- package/Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.harmony.js +26 -0
- package/Libraries/Components/Button/Button.harmony.js +450 -450
- package/Libraries/Components/Image/Image.flow.harmony.js +53 -0
- package/Libraries/Components/Image/Image.harmony.js +299 -0
- package/Libraries/Components/Image/NativeImageLoaderHarmony.js +38 -0
- package/Libraries/Components/RefreshControl/RefreshControl.harmony.js +210 -210
- package/Libraries/Components/SafeAreaView/SafeAreaView.harmony.tsx +76 -75
- package/Libraries/Components/ScrollView/ScrollView.harmony.js +1951 -1951
- package/Libraries/Components/ScrollView/processDecelerationRate.harmony.js +24 -24
- package/Libraries/Components/StatusBar/NativeStatusBarManagerHarmony.js +71 -68
- package/Libraries/Components/StatusBar/StatusBar.harmony.js +447 -447
- package/Libraries/Components/TextInput/TextInput.harmony.js +1707 -1707
- package/Libraries/Components/TextInput/TextInputState.harmony.js +220 -220
- package/Libraries/Components/Touchable/TouchableHighlight.harmony.js +396 -396
- package/Libraries/Components/Touchable/TouchableNativeFeedback.harmony.js +364 -364
- package/Libraries/Components/Touchable/TouchableWithoutFeedback.harmony.js +227 -227
- package/Libraries/Components/View/View.harmony.js +149 -149
- package/Libraries/Core/setUpReactDevTools.harmony.js +93 -93
- package/Libraries/Image/AssetSourceResolver.harmony.ts +78 -78
- package/Libraries/NativeComponent/BaseViewConfig.harmony.js +337 -337
- package/Libraries/ReactNative/UIManager.harmony.js +210 -210
- package/Libraries/Settings/Settings.harmony.js +15 -15
- package/Libraries/Share/Share.harmony.js +174 -174
- package/Libraries/StyleSheet/NativePlatformColor.ts +8 -8
- package/Libraries/StyleSheet/PlatformColorValueTypes.harmony.ts +14 -14
- package/Libraries/Utilities/BackHandler.harmony.js +109 -109
- package/Libraries/Utilities/{NativePlatformConstantsHarmony.ts → NativePlatformConstants.harmony.ts} +8 -8
- package/Libraries/Utilities/Platform.d.ts +117 -117
- package/Libraries/Utilities/Platform.harmony.ts +33 -33
- package/Libraries/Utilities/createPerformanceLogger.harmony.js +328 -328
- package/Libraries/Vibration/Vibration.harmony.js +88 -88
- package/index.js +212 -212
- package/jest.config.js +5 -5
- package/metro.config.js +348 -348
- package/package.json +57 -57
- package/react-native.config.js +10 -10
- package/react_native_openharmony.har +0 -0
- package/tsconfig.json +13 -13
- package/types/index.d.ts +101 -101
|
@@ -1,396 +1,396 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
* @flow strict-local
|
|
8
|
-
* @format
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
// RNOH patch: disable view flattening
|
|
12
|
-
|
|
13
|
-
import type { ColorValue } from "react-native/Libraries/StyleSheet/StyleSheet";
|
|
14
|
-
import typeof TouchableWithoutFeedback from "./TouchableWithoutFeedback";
|
|
15
|
-
|
|
16
|
-
import View from "react-native/Libraries/Components/View/View";
|
|
17
|
-
import Pressability, {
|
|
18
|
-
type PressabilityConfig,
|
|
19
|
-
} from "react-native/Libraries/Pressability/Pressability";
|
|
20
|
-
import { PressabilityDebugView } from "react-native/Libraries/Pressability/PressabilityDebug";
|
|
21
|
-
import StyleSheet, {
|
|
22
|
-
type ViewStyleProp,
|
|
23
|
-
} from "react-native/Libraries/StyleSheet/StyleSheet";
|
|
24
|
-
import Platform from "react-native/Libraries/Utilities/Platform";
|
|
25
|
-
import * as React from "react";
|
|
26
|
-
|
|
27
|
-
type AndroidProps = $ReadOnly<{|
|
|
28
|
-
nextFocusDown?: ?number,
|
|
29
|
-
nextFocusForward?: ?number,
|
|
30
|
-
nextFocusLeft?: ?number,
|
|
31
|
-
nextFocusRight?: ?number,
|
|
32
|
-
nextFocusUp?: ?number,
|
|
33
|
-
|}>;
|
|
34
|
-
|
|
35
|
-
type IOSProps = $ReadOnly<{|
|
|
36
|
-
hasTVPreferredFocus?: ?boolean,
|
|
37
|
-
|}>;
|
|
38
|
-
|
|
39
|
-
type Props = $ReadOnly<{|
|
|
40
|
-
...React.ElementConfig<TouchableWithoutFeedback>,
|
|
41
|
-
...AndroidProps,
|
|
42
|
-
...IOSProps,
|
|
43
|
-
|
|
44
|
-
activeOpacity?: ?number,
|
|
45
|
-
underlayColor?: ?ColorValue,
|
|
46
|
-
style?: ?ViewStyleProp,
|
|
47
|
-
onShowUnderlay?: ?() => void,
|
|
48
|
-
onHideUnderlay?: ?() => void,
|
|
49
|
-
testOnly_pressed?: ?boolean,
|
|
50
|
-
|
|
51
|
-
hostRef: React.Ref<typeof View>,
|
|
52
|
-
|}>;
|
|
53
|
-
|
|
54
|
-
type ExtraStyles = $ReadOnly<{|
|
|
55
|
-
child: ViewStyleProp,
|
|
56
|
-
underlay: ViewStyleProp,
|
|
57
|
-
|}>;
|
|
58
|
-
|
|
59
|
-
type State = $ReadOnly<{|
|
|
60
|
-
pressability: Pressability,
|
|
61
|
-
extraStyles: ?ExtraStyles,
|
|
62
|
-
|}>;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* A wrapper for making views respond properly to touches.
|
|
66
|
-
* On press down, the opacity of the wrapped view is decreased, which allows
|
|
67
|
-
* the underlay color to show through, darkening or tinting the view.
|
|
68
|
-
*
|
|
69
|
-
* The underlay comes from wrapping the child in a new View, which can affect
|
|
70
|
-
* layout, and sometimes cause unwanted visual artifacts if not used correctly,
|
|
71
|
-
* for example if the backgroundColor of the wrapped view isn't explicitly set
|
|
72
|
-
* to an opaque color.
|
|
73
|
-
*
|
|
74
|
-
* TouchableHighlight must have one child (not zero or more than one).
|
|
75
|
-
* If you wish to have several child components, wrap them in a View.
|
|
76
|
-
*
|
|
77
|
-
* Example:
|
|
78
|
-
*
|
|
79
|
-
* ```
|
|
80
|
-
* renderButton: function() {
|
|
81
|
-
* return (
|
|
82
|
-
* <TouchableHighlight onPress={this._onPressButton}>
|
|
83
|
-
* <Image
|
|
84
|
-
* style={styles.button}
|
|
85
|
-
* source={require('./myButton.png')}
|
|
86
|
-
* />
|
|
87
|
-
* </TouchableHighlight>
|
|
88
|
-
* );
|
|
89
|
-
* },
|
|
90
|
-
* ```
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
* ### Example
|
|
94
|
-
*
|
|
95
|
-
* ```ReactNativeWebPlayer
|
|
96
|
-
* import React, { Component } from 'react'
|
|
97
|
-
* import {
|
|
98
|
-
* AppRegistry,
|
|
99
|
-
* StyleSheet,
|
|
100
|
-
* TouchableHighlight,
|
|
101
|
-
* Text,
|
|
102
|
-
* View,
|
|
103
|
-
* } from 'react-native'
|
|
104
|
-
*
|
|
105
|
-
* class App extends Component {
|
|
106
|
-
* constructor(props) {
|
|
107
|
-
* super(props)
|
|
108
|
-
* this.state = { count: 0 }
|
|
109
|
-
* }
|
|
110
|
-
*
|
|
111
|
-
* onPress = () => {
|
|
112
|
-
* this.setState({
|
|
113
|
-
* count: this.state.count+1
|
|
114
|
-
* })
|
|
115
|
-
* }
|
|
116
|
-
*
|
|
117
|
-
* render() {
|
|
118
|
-
* return (
|
|
119
|
-
* <View style={styles.container}>
|
|
120
|
-
* <TouchableHighlight
|
|
121
|
-
* style={styles.button}
|
|
122
|
-
* onPress={this.onPress}
|
|
123
|
-
* >
|
|
124
|
-
* <Text> Touch Here </Text>
|
|
125
|
-
* </TouchableHighlight>
|
|
126
|
-
* <View style={[styles.countContainer]}>
|
|
127
|
-
* <Text style={[styles.countText]}>
|
|
128
|
-
* { this.state.count !== 0 ? this.state.count: null}
|
|
129
|
-
* </Text>
|
|
130
|
-
* </View>
|
|
131
|
-
* </View>
|
|
132
|
-
* )
|
|
133
|
-
* }
|
|
134
|
-
* }
|
|
135
|
-
*
|
|
136
|
-
* const styles = StyleSheet.create({
|
|
137
|
-
* container: {
|
|
138
|
-
* flex: 1,
|
|
139
|
-
* justifyContent: 'center',
|
|
140
|
-
* paddingHorizontal: 10
|
|
141
|
-
* },
|
|
142
|
-
* button: {
|
|
143
|
-
* alignItems: 'center',
|
|
144
|
-
* backgroundColor: '#DDDDDD',
|
|
145
|
-
* padding: 10
|
|
146
|
-
* },
|
|
147
|
-
* countContainer: {
|
|
148
|
-
* alignItems: 'center',
|
|
149
|
-
* padding: 10
|
|
150
|
-
* },
|
|
151
|
-
* countText: {
|
|
152
|
-
* color: '#FF00FF'
|
|
153
|
-
* }
|
|
154
|
-
* })
|
|
155
|
-
*
|
|
156
|
-
* AppRegistry.registerComponent('App', () => App)
|
|
157
|
-
* ```
|
|
158
|
-
*
|
|
159
|
-
*/
|
|
160
|
-
class TouchableHighlight extends React.Component<Props, State> {
|
|
161
|
-
_hideTimeout: ?TimeoutID;
|
|
162
|
-
_isMounted: boolean = false;
|
|
163
|
-
|
|
164
|
-
state: State = {
|
|
165
|
-
pressability: new Pressability(this._createPressabilityConfig()),
|
|
166
|
-
extraStyles:
|
|
167
|
-
this.props.testOnly_pressed === true ? this._createExtraStyles() : null,
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
_createPressabilityConfig(): PressabilityConfig {
|
|
171
|
-
return {
|
|
172
|
-
cancelable: !this.props.rejectResponderTermination,
|
|
173
|
-
disabled:
|
|
174
|
-
this.props.disabled != null
|
|
175
|
-
? this.props.disabled
|
|
176
|
-
: this.props.accessibilityState?.disabled,
|
|
177
|
-
hitSlop: this.props.hitSlop,
|
|
178
|
-
delayLongPress: this.props.delayLongPress,
|
|
179
|
-
delayPressIn: this.props.delayPressIn,
|
|
180
|
-
delayPressOut: this.props.delayPressOut,
|
|
181
|
-
minPressDuration: 0,
|
|
182
|
-
pressRectOffset: this.props.pressRetentionOffset,
|
|
183
|
-
android_disableSound: this.props.touchSoundDisabled,
|
|
184
|
-
onBlur: (event) => {
|
|
185
|
-
if (Platform.isTV) {
|
|
186
|
-
this._hideUnderlay();
|
|
187
|
-
}
|
|
188
|
-
if (this.props.onBlur != null) {
|
|
189
|
-
this.props.onBlur(event);
|
|
190
|
-
}
|
|
191
|
-
},
|
|
192
|
-
onFocus: (event) => {
|
|
193
|
-
if (Platform.isTV) {
|
|
194
|
-
this._showUnderlay();
|
|
195
|
-
}
|
|
196
|
-
if (this.props.onFocus != null) {
|
|
197
|
-
this.props.onFocus(event);
|
|
198
|
-
}
|
|
199
|
-
},
|
|
200
|
-
onLongPress: this.props.onLongPress,
|
|
201
|
-
onPress: (event) => {
|
|
202
|
-
if (this._hideTimeout != null) {
|
|
203
|
-
clearTimeout(this._hideTimeout);
|
|
204
|
-
}
|
|
205
|
-
if (!Platform.isTV) {
|
|
206
|
-
this._showUnderlay();
|
|
207
|
-
this._hideTimeout = setTimeout(() => {
|
|
208
|
-
this._hideUnderlay();
|
|
209
|
-
}, this.props.delayPressOut ?? 0);
|
|
210
|
-
}
|
|
211
|
-
if (this.props.onPress != null) {
|
|
212
|
-
this.props.onPress(event);
|
|
213
|
-
}
|
|
214
|
-
},
|
|
215
|
-
onPressIn: (event) => {
|
|
216
|
-
if (this._hideTimeout != null) {
|
|
217
|
-
clearTimeout(this._hideTimeout);
|
|
218
|
-
this._hideTimeout = null;
|
|
219
|
-
}
|
|
220
|
-
this._showUnderlay();
|
|
221
|
-
if (this.props.onPressIn != null) {
|
|
222
|
-
this.props.onPressIn(event);
|
|
223
|
-
}
|
|
224
|
-
},
|
|
225
|
-
onPressOut: (event) => {
|
|
226
|
-
if (this._hideTimeout == null) {
|
|
227
|
-
this._hideUnderlay();
|
|
228
|
-
}
|
|
229
|
-
if (this.props.onPressOut != null) {
|
|
230
|
-
this.props.onPressOut(event);
|
|
231
|
-
}
|
|
232
|
-
},
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
_createExtraStyles(): ExtraStyles {
|
|
237
|
-
return {
|
|
238
|
-
child: { opacity: this.props.activeOpacity ?? 0.85 },
|
|
239
|
-
underlay: {
|
|
240
|
-
backgroundColor:
|
|
241
|
-
this.props.underlayColor === undefined
|
|
242
|
-
? "black"
|
|
243
|
-
: this.props.underlayColor,
|
|
244
|
-
},
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
_showUnderlay(): void {
|
|
249
|
-
if (!this._isMounted || !this._hasPressHandler()) {
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
this.setState({ extraStyles: this._createExtraStyles() });
|
|
253
|
-
if (this.props.onShowUnderlay != null) {
|
|
254
|
-
this.props.onShowUnderlay();
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
_hideUnderlay(): void {
|
|
259
|
-
if (this._hideTimeout != null) {
|
|
260
|
-
clearTimeout(this._hideTimeout);
|
|
261
|
-
this._hideTimeout = null;
|
|
262
|
-
}
|
|
263
|
-
if (this.props.testOnly_pressed === true) {
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
if (this._hasPressHandler()) {
|
|
267
|
-
this.setState({ extraStyles: null });
|
|
268
|
-
if (this.props.onHideUnderlay != null) {
|
|
269
|
-
this.props.onHideUnderlay();
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
_hasPressHandler(): boolean {
|
|
275
|
-
return (
|
|
276
|
-
this.props.onPress != null ||
|
|
277
|
-
this.props.onPressIn != null ||
|
|
278
|
-
this.props.onPressOut != null ||
|
|
279
|
-
this.props.onLongPress != null
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
render(): React.Node {
|
|
284
|
-
const child = React.Children.only<$FlowFixMe>(this.props.children);
|
|
285
|
-
|
|
286
|
-
// BACKWARD-COMPATIBILITY: Focus and blur events were never supported before
|
|
287
|
-
// adopting `Pressability`, so preserve that behavior.
|
|
288
|
-
const { onBlur, onFocus, ...eventHandlersWithoutBlurAndFocus } =
|
|
289
|
-
this.state.pressability.getEventHandlers();
|
|
290
|
-
|
|
291
|
-
const accessibilityState =
|
|
292
|
-
this.props.disabled != null
|
|
293
|
-
? {
|
|
294
|
-
...this.props.accessibilityState,
|
|
295
|
-
disabled: this.props.disabled,
|
|
296
|
-
}
|
|
297
|
-
: this.props.accessibilityState;
|
|
298
|
-
|
|
299
|
-
const accessibilityValue = {
|
|
300
|
-
max: this.props["aria-valuemax"] ?? this.props.accessibilityValue?.max,
|
|
301
|
-
min: this.props["aria-valuemin"] ?? this.props.accessibilityValue?.min,
|
|
302
|
-
now: this.props["aria-valuenow"] ?? this.props.accessibilityValue?.now,
|
|
303
|
-
text: this.props["aria-valuetext"] ?? this.props.accessibilityValue?.text,
|
|
304
|
-
};
|
|
305
|
-
|
|
306
|
-
const accessibilityLiveRegion =
|
|
307
|
-
this.props["aria-live"] === "off"
|
|
308
|
-
? "none"
|
|
309
|
-
: this.props["aria-live"] ?? this.props.accessibilityLiveRegion;
|
|
310
|
-
|
|
311
|
-
const accessibilityLabel =
|
|
312
|
-
this.props["aria-label"] ?? this.props.accessibilityLabel;
|
|
313
|
-
return (
|
|
314
|
-
<View
|
|
315
|
-
accessible={this.props.accessible !== false}
|
|
316
|
-
accessibilityLabel={accessibilityLabel}
|
|
317
|
-
accessibilityHint={this.props.accessibilityHint}
|
|
318
|
-
accessibilityLanguage={this.props.accessibilityLanguage}
|
|
319
|
-
accessibilityRole={this.props.accessibilityRole}
|
|
320
|
-
accessibilityState={accessibilityState}
|
|
321
|
-
accessibilityValue={accessibilityValue}
|
|
322
|
-
accessibilityActions={this.props.accessibilityActions}
|
|
323
|
-
onAccessibilityAction={this.props.onAccessibilityAction}
|
|
324
|
-
importantForAccessibility={
|
|
325
|
-
this.props["aria-hidden"] === true
|
|
326
|
-
? "no-hide-descendants"
|
|
327
|
-
: this.props.importantForAccessibility
|
|
328
|
-
}
|
|
329
|
-
accessibilityViewIsModal={
|
|
330
|
-
this.props["aria-modal"] ?? this.props.accessibilityViewIsModal
|
|
331
|
-
}
|
|
332
|
-
accessibilityLiveRegion={accessibilityLiveRegion}
|
|
333
|
-
accessibilityElementsHidden={
|
|
334
|
-
this.props["aria-hidden"] ?? this.props.accessibilityElementsHidden
|
|
335
|
-
}
|
|
336
|
-
style={StyleSheet.compose(
|
|
337
|
-
this.props.style,
|
|
338
|
-
this.state.extraStyles?.underlay
|
|
339
|
-
)}
|
|
340
|
-
onLayout={this.props.onLayout}
|
|
341
|
-
hitSlop={this.props.hitSlop}
|
|
342
|
-
hasTVPreferredFocus={this.props.hasTVPreferredFocus}
|
|
343
|
-
nextFocusDown={this.props.nextFocusDown}
|
|
344
|
-
nextFocusForward={this.props.nextFocusForward}
|
|
345
|
-
nextFocusLeft={this.props.nextFocusLeft}
|
|
346
|
-
nextFocusRight={this.props.nextFocusRight}
|
|
347
|
-
nextFocusUp={this.props.nextFocusUp}
|
|
348
|
-
focusable={
|
|
349
|
-
this.props.focusable !== false && this.props.onPress !== undefined
|
|
350
|
-
}
|
|
351
|
-
nativeID={this.props.nativeID}
|
|
352
|
-
testID={this.props.testID}
|
|
353
|
-
ref={this.props.hostRef}
|
|
354
|
-
{...eventHandlersWithoutBlurAndFocus}
|
|
355
|
-
collapsable={false} // RNOH: patch
|
|
356
|
-
>
|
|
357
|
-
{React.cloneElement(child, {
|
|
358
|
-
style: StyleSheet.compose(
|
|
359
|
-
child.props.style,
|
|
360
|
-
this.state.extraStyles?.child
|
|
361
|
-
),
|
|
362
|
-
})}
|
|
363
|
-
{__DEV__ ? (
|
|
364
|
-
<PressabilityDebugView color="green" hitSlop={this.props.hitSlop} />
|
|
365
|
-
) : null}
|
|
366
|
-
</View>
|
|
367
|
-
);
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
componentDidMount(): void {
|
|
371
|
-
this._isMounted = true;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
componentDidUpdate(prevProps: Props, prevState: State) {
|
|
375
|
-
this.state.pressability.configure(this._createPressabilityConfig());
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
componentWillUnmount(): void {
|
|
379
|
-
this._isMounted = false;
|
|
380
|
-
if (this._hideTimeout != null) {
|
|
381
|
-
clearTimeout(this._hideTimeout);
|
|
382
|
-
}
|
|
383
|
-
this.state.pressability.reset();
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
const Touchable = (React.forwardRef((props, hostRef) => (
|
|
388
|
-
<TouchableHighlight {...props} hostRef={hostRef} />
|
|
389
|
-
)): React.AbstractComponent<
|
|
390
|
-
$ReadOnly<$Diff<Props, {| hostRef: React.Ref<typeof View> |}>>,
|
|
391
|
-
React.ElementRef<typeof View>
|
|
392
|
-
>);
|
|
393
|
-
|
|
394
|
-
Touchable.displayName = "TouchableHighlight";
|
|
395
|
-
|
|
396
|
-
module.exports = Touchable;
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
* @flow strict-local
|
|
8
|
+
* @format
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// RNOH patch: disable view flattening
|
|
12
|
+
|
|
13
|
+
import type { ColorValue } from "react-native/Libraries/StyleSheet/StyleSheet";
|
|
14
|
+
import typeof TouchableWithoutFeedback from "./TouchableWithoutFeedback";
|
|
15
|
+
|
|
16
|
+
import View from "react-native/Libraries/Components/View/View";
|
|
17
|
+
import Pressability, {
|
|
18
|
+
type PressabilityConfig,
|
|
19
|
+
} from "react-native/Libraries/Pressability/Pressability";
|
|
20
|
+
import { PressabilityDebugView } from "react-native/Libraries/Pressability/PressabilityDebug";
|
|
21
|
+
import StyleSheet, {
|
|
22
|
+
type ViewStyleProp,
|
|
23
|
+
} from "react-native/Libraries/StyleSheet/StyleSheet";
|
|
24
|
+
import Platform from "react-native/Libraries/Utilities/Platform";
|
|
25
|
+
import * as React from "react";
|
|
26
|
+
|
|
27
|
+
type AndroidProps = $ReadOnly<{|
|
|
28
|
+
nextFocusDown?: ?number,
|
|
29
|
+
nextFocusForward?: ?number,
|
|
30
|
+
nextFocusLeft?: ?number,
|
|
31
|
+
nextFocusRight?: ?number,
|
|
32
|
+
nextFocusUp?: ?number,
|
|
33
|
+
|}>;
|
|
34
|
+
|
|
35
|
+
type IOSProps = $ReadOnly<{|
|
|
36
|
+
hasTVPreferredFocus?: ?boolean,
|
|
37
|
+
|}>;
|
|
38
|
+
|
|
39
|
+
type Props = $ReadOnly<{|
|
|
40
|
+
...React.ElementConfig<TouchableWithoutFeedback>,
|
|
41
|
+
...AndroidProps,
|
|
42
|
+
...IOSProps,
|
|
43
|
+
|
|
44
|
+
activeOpacity?: ?number,
|
|
45
|
+
underlayColor?: ?ColorValue,
|
|
46
|
+
style?: ?ViewStyleProp,
|
|
47
|
+
onShowUnderlay?: ?() => void,
|
|
48
|
+
onHideUnderlay?: ?() => void,
|
|
49
|
+
testOnly_pressed?: ?boolean,
|
|
50
|
+
|
|
51
|
+
hostRef: React.Ref<typeof View>,
|
|
52
|
+
|}>;
|
|
53
|
+
|
|
54
|
+
type ExtraStyles = $ReadOnly<{|
|
|
55
|
+
child: ViewStyleProp,
|
|
56
|
+
underlay: ViewStyleProp,
|
|
57
|
+
|}>;
|
|
58
|
+
|
|
59
|
+
type State = $ReadOnly<{|
|
|
60
|
+
pressability: Pressability,
|
|
61
|
+
extraStyles: ?ExtraStyles,
|
|
62
|
+
|}>;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* A wrapper for making views respond properly to touches.
|
|
66
|
+
* On press down, the opacity of the wrapped view is decreased, which allows
|
|
67
|
+
* the underlay color to show through, darkening or tinting the view.
|
|
68
|
+
*
|
|
69
|
+
* The underlay comes from wrapping the child in a new View, which can affect
|
|
70
|
+
* layout, and sometimes cause unwanted visual artifacts if not used correctly,
|
|
71
|
+
* for example if the backgroundColor of the wrapped view isn't explicitly set
|
|
72
|
+
* to an opaque color.
|
|
73
|
+
*
|
|
74
|
+
* TouchableHighlight must have one child (not zero or more than one).
|
|
75
|
+
* If you wish to have several child components, wrap them in a View.
|
|
76
|
+
*
|
|
77
|
+
* Example:
|
|
78
|
+
*
|
|
79
|
+
* ```
|
|
80
|
+
* renderButton: function() {
|
|
81
|
+
* return (
|
|
82
|
+
* <TouchableHighlight onPress={this._onPressButton}>
|
|
83
|
+
* <Image
|
|
84
|
+
* style={styles.button}
|
|
85
|
+
* source={require('./myButton.png')}
|
|
86
|
+
* />
|
|
87
|
+
* </TouchableHighlight>
|
|
88
|
+
* );
|
|
89
|
+
* },
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
*
|
|
93
|
+
* ### Example
|
|
94
|
+
*
|
|
95
|
+
* ```ReactNativeWebPlayer
|
|
96
|
+
* import React, { Component } from 'react'
|
|
97
|
+
* import {
|
|
98
|
+
* AppRegistry,
|
|
99
|
+
* StyleSheet,
|
|
100
|
+
* TouchableHighlight,
|
|
101
|
+
* Text,
|
|
102
|
+
* View,
|
|
103
|
+
* } from 'react-native'
|
|
104
|
+
*
|
|
105
|
+
* class App extends Component {
|
|
106
|
+
* constructor(props) {
|
|
107
|
+
* super(props)
|
|
108
|
+
* this.state = { count: 0 }
|
|
109
|
+
* }
|
|
110
|
+
*
|
|
111
|
+
* onPress = () => {
|
|
112
|
+
* this.setState({
|
|
113
|
+
* count: this.state.count+1
|
|
114
|
+
* })
|
|
115
|
+
* }
|
|
116
|
+
*
|
|
117
|
+
* render() {
|
|
118
|
+
* return (
|
|
119
|
+
* <View style={styles.container}>
|
|
120
|
+
* <TouchableHighlight
|
|
121
|
+
* style={styles.button}
|
|
122
|
+
* onPress={this.onPress}
|
|
123
|
+
* >
|
|
124
|
+
* <Text> Touch Here </Text>
|
|
125
|
+
* </TouchableHighlight>
|
|
126
|
+
* <View style={[styles.countContainer]}>
|
|
127
|
+
* <Text style={[styles.countText]}>
|
|
128
|
+
* { this.state.count !== 0 ? this.state.count: null}
|
|
129
|
+
* </Text>
|
|
130
|
+
* </View>
|
|
131
|
+
* </View>
|
|
132
|
+
* )
|
|
133
|
+
* }
|
|
134
|
+
* }
|
|
135
|
+
*
|
|
136
|
+
* const styles = StyleSheet.create({
|
|
137
|
+
* container: {
|
|
138
|
+
* flex: 1,
|
|
139
|
+
* justifyContent: 'center',
|
|
140
|
+
* paddingHorizontal: 10
|
|
141
|
+
* },
|
|
142
|
+
* button: {
|
|
143
|
+
* alignItems: 'center',
|
|
144
|
+
* backgroundColor: '#DDDDDD',
|
|
145
|
+
* padding: 10
|
|
146
|
+
* },
|
|
147
|
+
* countContainer: {
|
|
148
|
+
* alignItems: 'center',
|
|
149
|
+
* padding: 10
|
|
150
|
+
* },
|
|
151
|
+
* countText: {
|
|
152
|
+
* color: '#FF00FF'
|
|
153
|
+
* }
|
|
154
|
+
* })
|
|
155
|
+
*
|
|
156
|
+
* AppRegistry.registerComponent('App', () => App)
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
*/
|
|
160
|
+
class TouchableHighlight extends React.Component<Props, State> {
|
|
161
|
+
_hideTimeout: ?TimeoutID;
|
|
162
|
+
_isMounted: boolean = false;
|
|
163
|
+
|
|
164
|
+
state: State = {
|
|
165
|
+
pressability: new Pressability(this._createPressabilityConfig()),
|
|
166
|
+
extraStyles:
|
|
167
|
+
this.props.testOnly_pressed === true ? this._createExtraStyles() : null,
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
_createPressabilityConfig(): PressabilityConfig {
|
|
171
|
+
return {
|
|
172
|
+
cancelable: !this.props.rejectResponderTermination,
|
|
173
|
+
disabled:
|
|
174
|
+
this.props.disabled != null
|
|
175
|
+
? this.props.disabled
|
|
176
|
+
: this.props.accessibilityState?.disabled,
|
|
177
|
+
hitSlop: this.props.hitSlop,
|
|
178
|
+
delayLongPress: this.props.delayLongPress,
|
|
179
|
+
delayPressIn: this.props.delayPressIn,
|
|
180
|
+
delayPressOut: this.props.delayPressOut,
|
|
181
|
+
minPressDuration: 0,
|
|
182
|
+
pressRectOffset: this.props.pressRetentionOffset,
|
|
183
|
+
android_disableSound: this.props.touchSoundDisabled,
|
|
184
|
+
onBlur: (event) => {
|
|
185
|
+
if (Platform.isTV) {
|
|
186
|
+
this._hideUnderlay();
|
|
187
|
+
}
|
|
188
|
+
if (this.props.onBlur != null) {
|
|
189
|
+
this.props.onBlur(event);
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
onFocus: (event) => {
|
|
193
|
+
if (Platform.isTV) {
|
|
194
|
+
this._showUnderlay();
|
|
195
|
+
}
|
|
196
|
+
if (this.props.onFocus != null) {
|
|
197
|
+
this.props.onFocus(event);
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
onLongPress: this.props.onLongPress,
|
|
201
|
+
onPress: (event) => {
|
|
202
|
+
if (this._hideTimeout != null) {
|
|
203
|
+
clearTimeout(this._hideTimeout);
|
|
204
|
+
}
|
|
205
|
+
if (!Platform.isTV) {
|
|
206
|
+
this._showUnderlay();
|
|
207
|
+
this._hideTimeout = setTimeout(() => {
|
|
208
|
+
this._hideUnderlay();
|
|
209
|
+
}, this.props.delayPressOut ?? 0);
|
|
210
|
+
}
|
|
211
|
+
if (this.props.onPress != null) {
|
|
212
|
+
this.props.onPress(event);
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
onPressIn: (event) => {
|
|
216
|
+
if (this._hideTimeout != null) {
|
|
217
|
+
clearTimeout(this._hideTimeout);
|
|
218
|
+
this._hideTimeout = null;
|
|
219
|
+
}
|
|
220
|
+
this._showUnderlay();
|
|
221
|
+
if (this.props.onPressIn != null) {
|
|
222
|
+
this.props.onPressIn(event);
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
onPressOut: (event) => {
|
|
226
|
+
if (this._hideTimeout == null) {
|
|
227
|
+
this._hideUnderlay();
|
|
228
|
+
}
|
|
229
|
+
if (this.props.onPressOut != null) {
|
|
230
|
+
this.props.onPressOut(event);
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
_createExtraStyles(): ExtraStyles {
|
|
237
|
+
return {
|
|
238
|
+
child: { opacity: this.props.activeOpacity ?? 0.85 },
|
|
239
|
+
underlay: {
|
|
240
|
+
backgroundColor:
|
|
241
|
+
this.props.underlayColor === undefined
|
|
242
|
+
? "black"
|
|
243
|
+
: this.props.underlayColor,
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
_showUnderlay(): void {
|
|
249
|
+
if (!this._isMounted || !this._hasPressHandler()) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
this.setState({ extraStyles: this._createExtraStyles() });
|
|
253
|
+
if (this.props.onShowUnderlay != null) {
|
|
254
|
+
this.props.onShowUnderlay();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
_hideUnderlay(): void {
|
|
259
|
+
if (this._hideTimeout != null) {
|
|
260
|
+
clearTimeout(this._hideTimeout);
|
|
261
|
+
this._hideTimeout = null;
|
|
262
|
+
}
|
|
263
|
+
if (this.props.testOnly_pressed === true) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (this._hasPressHandler()) {
|
|
267
|
+
this.setState({ extraStyles: null });
|
|
268
|
+
if (this.props.onHideUnderlay != null) {
|
|
269
|
+
this.props.onHideUnderlay();
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
_hasPressHandler(): boolean {
|
|
275
|
+
return (
|
|
276
|
+
this.props.onPress != null ||
|
|
277
|
+
this.props.onPressIn != null ||
|
|
278
|
+
this.props.onPressOut != null ||
|
|
279
|
+
this.props.onLongPress != null
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
render(): React.Node {
|
|
284
|
+
const child = React.Children.only<$FlowFixMe>(this.props.children);
|
|
285
|
+
|
|
286
|
+
// BACKWARD-COMPATIBILITY: Focus and blur events were never supported before
|
|
287
|
+
// adopting `Pressability`, so preserve that behavior.
|
|
288
|
+
const { onBlur, onFocus, ...eventHandlersWithoutBlurAndFocus } =
|
|
289
|
+
this.state.pressability.getEventHandlers();
|
|
290
|
+
|
|
291
|
+
const accessibilityState =
|
|
292
|
+
this.props.disabled != null
|
|
293
|
+
? {
|
|
294
|
+
...this.props.accessibilityState,
|
|
295
|
+
disabled: this.props.disabled,
|
|
296
|
+
}
|
|
297
|
+
: this.props.accessibilityState;
|
|
298
|
+
|
|
299
|
+
const accessibilityValue = {
|
|
300
|
+
max: this.props["aria-valuemax"] ?? this.props.accessibilityValue?.max,
|
|
301
|
+
min: this.props["aria-valuemin"] ?? this.props.accessibilityValue?.min,
|
|
302
|
+
now: this.props["aria-valuenow"] ?? this.props.accessibilityValue?.now,
|
|
303
|
+
text: this.props["aria-valuetext"] ?? this.props.accessibilityValue?.text,
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const accessibilityLiveRegion =
|
|
307
|
+
this.props["aria-live"] === "off"
|
|
308
|
+
? "none"
|
|
309
|
+
: this.props["aria-live"] ?? this.props.accessibilityLiveRegion;
|
|
310
|
+
|
|
311
|
+
const accessibilityLabel =
|
|
312
|
+
this.props["aria-label"] ?? this.props.accessibilityLabel;
|
|
313
|
+
return (
|
|
314
|
+
<View
|
|
315
|
+
accessible={this.props.accessible !== false}
|
|
316
|
+
accessibilityLabel={accessibilityLabel}
|
|
317
|
+
accessibilityHint={this.props.accessibilityHint}
|
|
318
|
+
accessibilityLanguage={this.props.accessibilityLanguage}
|
|
319
|
+
accessibilityRole={this.props.accessibilityRole}
|
|
320
|
+
accessibilityState={accessibilityState}
|
|
321
|
+
accessibilityValue={accessibilityValue}
|
|
322
|
+
accessibilityActions={this.props.accessibilityActions}
|
|
323
|
+
onAccessibilityAction={this.props.onAccessibilityAction}
|
|
324
|
+
importantForAccessibility={
|
|
325
|
+
this.props["aria-hidden"] === true
|
|
326
|
+
? "no-hide-descendants"
|
|
327
|
+
: this.props.importantForAccessibility
|
|
328
|
+
}
|
|
329
|
+
accessibilityViewIsModal={
|
|
330
|
+
this.props["aria-modal"] ?? this.props.accessibilityViewIsModal
|
|
331
|
+
}
|
|
332
|
+
accessibilityLiveRegion={accessibilityLiveRegion}
|
|
333
|
+
accessibilityElementsHidden={
|
|
334
|
+
this.props["aria-hidden"] ?? this.props.accessibilityElementsHidden
|
|
335
|
+
}
|
|
336
|
+
style={StyleSheet.compose(
|
|
337
|
+
this.props.style,
|
|
338
|
+
this.state.extraStyles?.underlay
|
|
339
|
+
)}
|
|
340
|
+
onLayout={this.props.onLayout}
|
|
341
|
+
hitSlop={this.props.hitSlop}
|
|
342
|
+
hasTVPreferredFocus={this.props.hasTVPreferredFocus}
|
|
343
|
+
nextFocusDown={this.props.nextFocusDown}
|
|
344
|
+
nextFocusForward={this.props.nextFocusForward}
|
|
345
|
+
nextFocusLeft={this.props.nextFocusLeft}
|
|
346
|
+
nextFocusRight={this.props.nextFocusRight}
|
|
347
|
+
nextFocusUp={this.props.nextFocusUp}
|
|
348
|
+
focusable={
|
|
349
|
+
this.props.focusable !== false && this.props.onPress !== undefined
|
|
350
|
+
}
|
|
351
|
+
nativeID={this.props.nativeID}
|
|
352
|
+
testID={this.props.testID}
|
|
353
|
+
ref={this.props.hostRef}
|
|
354
|
+
{...eventHandlersWithoutBlurAndFocus}
|
|
355
|
+
collapsable={false} // RNOH: patch
|
|
356
|
+
>
|
|
357
|
+
{React.cloneElement(child, {
|
|
358
|
+
style: StyleSheet.compose(
|
|
359
|
+
child.props.style,
|
|
360
|
+
this.state.extraStyles?.child
|
|
361
|
+
),
|
|
362
|
+
})}
|
|
363
|
+
{__DEV__ ? (
|
|
364
|
+
<PressabilityDebugView color="green" hitSlop={this.props.hitSlop} />
|
|
365
|
+
) : null}
|
|
366
|
+
</View>
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
componentDidMount(): void {
|
|
371
|
+
this._isMounted = true;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
componentDidUpdate(prevProps: Props, prevState: State) {
|
|
375
|
+
this.state.pressability.configure(this._createPressabilityConfig());
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
componentWillUnmount(): void {
|
|
379
|
+
this._isMounted = false;
|
|
380
|
+
if (this._hideTimeout != null) {
|
|
381
|
+
clearTimeout(this._hideTimeout);
|
|
382
|
+
}
|
|
383
|
+
this.state.pressability.reset();
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const Touchable = (React.forwardRef((props, hostRef) => (
|
|
388
|
+
<TouchableHighlight {...props} hostRef={hostRef} />
|
|
389
|
+
)): React.AbstractComponent<
|
|
390
|
+
$ReadOnly<$Diff<Props, {| hostRef: React.Ref<typeof View> |}>>,
|
|
391
|
+
React.ElementRef<typeof View>
|
|
392
|
+
>);
|
|
393
|
+
|
|
394
|
+
Touchable.displayName = "TouchableHighlight";
|
|
395
|
+
|
|
396
|
+
module.exports = Touchable;
|