react-native-tvos 0.68.1-1 → 0.68.2-2

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.
Files changed (137) hide show
  1. package/Libraries/Components/DrawerAndroid/AndroidDrawerLayoutNativeComponent.js +6 -6
  2. package/Libraries/Components/Pressable/Pressable.js +13 -2
  3. package/Libraries/Components/Pressable/useAndroidRippleForView.js +3 -1
  4. package/Libraries/Components/{AppleTV → TV}/NativeTVNavigationEventEmitter.js +0 -0
  5. package/Libraries/Components/{AppleTV → TV}/TVEventControl.js +0 -0
  6. package/Libraries/Components/{AppleTV → TV}/TVEventHandler.js +0 -0
  7. package/Libraries/Components/{AppleTV → TV}/TVFocusEventHandler.js +0 -0
  8. package/Libraries/Components/TV/TVFocusGuideView.js +135 -0
  9. package/Libraries/Components/{AppleTV → TV}/TVTextScrollView.js +0 -0
  10. package/Libraries/Components/{AppleTV → TV}/TVViewPropTypes.js +0 -0
  11. package/Libraries/Components/{AppleTV → TV}/tagForComponentOrHandle.js +0 -0
  12. package/Libraries/Components/{AppleTV → TV}/useTVEventHandler.js +0 -0
  13. package/Libraries/Components/Touchable/TVTouchable.js +1 -1
  14. package/Libraries/Components/Touchable/Touchable.js +1 -1
  15. package/Libraries/Components/Touchable/TouchableHighlight.js +19 -5
  16. package/Libraries/Components/Touchable/TouchableNativeFeedback.js +7 -6
  17. package/Libraries/Components/Touchable/TouchableOpacity.js +2 -2
  18. package/Libraries/Components/View/ReactNativeViewViewConfig.js +1 -1
  19. package/Libraries/Components/View/ViewPropTypes.js +1 -1
  20. package/Libraries/Lists/VirtualizedSectionList.js +2 -1
  21. package/Libraries/LogBox/UI/AnsiHighlight.js +4 -2
  22. package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +2 -2
  23. package/Libraries/Renderer/shims/createReactNativeComponentClass.js +1 -1
  24. package/Libraries/Utilities/BackHandler.ios.js +1 -1
  25. package/Libraries/Utilities/ReactNativeTestTools.js +5 -7
  26. package/README.md +6 -1
  27. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +4 -0
  28. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +83 -30
  29. package/React/Views/RCTTVView.h +9 -5
  30. package/React/Views/RCTTVView.m +98 -52
  31. package/ReactAndroid/build.gradle +2 -11
  32. package/ReactAndroid/gradle.properties +1 -1
  33. package/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/Android.mk +1 -0
  34. package/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/Android.mk +2 -0
  35. package/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/jni/Android.mk +1 -0
  36. package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk +1 -0
  37. package/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/Android.mk +1 -0
  38. package/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/Android.mk +1 -0
  39. package/ReactAndroid/src/main/java/com/facebook/react/reactperflogger/jni/Android.mk +1 -0
  40. package/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/Android.mk +2 -0
  41. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/jni/Android.mk +1 -0
  42. package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +173 -103
  43. package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +20 -0
  44. package/ReactAndroid/src/main/jni/first-party/yogajni/Android.mk +1 -0
  45. package/ReactAndroid/src/main/jni/react/jni/Android.mk +2 -0
  46. package/ReactAndroid/src/main/jni/third-party/boost/Android.mk +1 -0
  47. package/ReactCommon/butter/Android.mk +1 -0
  48. package/ReactCommon/cxxreact/Android.mk +1 -0
  49. package/ReactCommon/hermes/executor/Android.mk +2 -0
  50. package/ReactCommon/hermes/inspector/Android.mk +1 -0
  51. package/ReactCommon/jsi/Android.mk +2 -0
  52. package/ReactCommon/jsiexecutor/Android.mk +1 -0
  53. package/ReactCommon/jsinspector/Android.mk +1 -0
  54. package/ReactCommon/logger/Android.mk +1 -0
  55. package/ReactCommon/react/config/Android.mk +1 -0
  56. package/ReactCommon/react/debug/Android.mk +1 -0
  57. package/ReactCommon/react/nativemodule/core/Android.mk +1 -0
  58. package/ReactCommon/react/nativemodule/samples/platform/android/Android.mk +1 -0
  59. package/ReactCommon/react/renderer/animations/Android.mk +1 -0
  60. package/ReactCommon/react/renderer/attributedstring/Android.mk +1 -0
  61. package/ReactCommon/react/renderer/componentregistry/Android.mk +1 -0
  62. package/ReactCommon/react/renderer/componentregistry/native/Android.mk +1 -0
  63. package/ReactCommon/react/renderer/components/image/Android.mk +1 -0
  64. package/ReactCommon/react/renderer/components/modal/Android.mk +1 -0
  65. package/ReactCommon/react/renderer/components/progressbar/Android.mk +1 -0
  66. package/ReactCommon/react/renderer/components/root/Android.mk +1 -0
  67. package/ReactCommon/react/renderer/components/scrollview/Android.mk +1 -0
  68. package/ReactCommon/react/renderer/components/slider/Android.mk +1 -0
  69. package/ReactCommon/react/renderer/components/switch/Android.mk +1 -0
  70. package/ReactCommon/react/renderer/components/text/Android.mk +1 -0
  71. package/ReactCommon/react/renderer/components/textinput/Android.mk +1 -0
  72. package/ReactCommon/react/renderer/components/unimplementedview/Android.mk +1 -0
  73. package/ReactCommon/react/renderer/components/view/Android.mk +1 -0
  74. package/ReactCommon/react/renderer/core/Android.mk +1 -0
  75. package/ReactCommon/react/renderer/debug/Android.mk +1 -0
  76. package/ReactCommon/react/renderer/graphics/Android.mk +1 -0
  77. package/ReactCommon/react/renderer/imagemanager/Android.mk +1 -0
  78. package/ReactCommon/react/renderer/leakchecker/Android.mk +1 -0
  79. package/ReactCommon/react/renderer/mapbuffer/Android.mk +1 -0
  80. package/ReactCommon/react/renderer/mounting/Android.mk +1 -0
  81. package/ReactCommon/react/renderer/runtimescheduler/Android.mk +1 -0
  82. package/ReactCommon/react/renderer/scheduler/Android.mk +1 -0
  83. package/ReactCommon/react/renderer/telemetry/Android.mk +1 -0
  84. package/ReactCommon/react/renderer/templateprocessor/Android.mk +1 -0
  85. package/ReactCommon/react/renderer/textlayoutmanager/Android.mk +1 -0
  86. package/ReactCommon/react/renderer/uimanager/Android.mk +1 -0
  87. package/ReactCommon/react/utils/Android.mk +1 -0
  88. package/ReactCommon/reactperflogger/Android.mk +1 -0
  89. package/ReactCommon/yoga/Android.mk +1 -0
  90. package/android/com/facebook/react/react-native/{0.68.1-1/react-native-0.68.1-1-sources.jar → 0.68.2-2/react-native-0.68.2-2-sources.jar} +0 -0
  91. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2-sources.jar.md5 +1 -0
  92. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2-sources.jar.sha1 +1 -0
  93. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2-sources.jar.sha256 +1 -0
  94. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2-sources.jar.sha512 +1 -0
  95. package/android/com/facebook/react/react-native/{0.68.1-1/react-native-0.68.1-1.aar → 0.68.2-2/react-native-0.68.2-2.aar} +0 -0
  96. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2.aar.md5 +1 -0
  97. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2.aar.sha1 +1 -0
  98. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2.aar.sha256 +1 -0
  99. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2.aar.sha512 +1 -0
  100. package/android/com/facebook/react/react-native/{0.68.1-1/react-native-0.68.1-1.module → 0.68.2-2/react-native-0.68.2-2.module} +15 -15
  101. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2.module.md5 +1 -0
  102. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2.module.sha1 +1 -0
  103. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2.module.sha256 +1 -0
  104. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2.module.sha512 +1 -0
  105. package/android/com/facebook/react/react-native/{0.68.1-1/react-native-0.68.1-1.pom → 0.68.2-2/react-native-0.68.2-2.pom} +1 -1
  106. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2.pom.md5 +1 -0
  107. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2.pom.sha1 +1 -0
  108. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2.pom.sha256 +1 -0
  109. package/android/com/facebook/react/react-native/0.68.2-2/react-native-0.68.2-2.pom.sha512 +1 -0
  110. package/android/com/facebook/react/react-native/maven-metadata.xml +4 -4
  111. package/android/com/facebook/react/react-native/maven-metadata.xml.md5 +1 -1
  112. package/android/com/facebook/react/react-native/maven-metadata.xml.sha1 +1 -1
  113. package/android/com/facebook/react/react-native/maven-metadata.xml.sha256 +1 -1
  114. package/android/com/facebook/react/react-native/maven-metadata.xml.sha512 +1 -1
  115. package/index.js +11 -11
  116. package/package.json +2 -2
  117. package/template/android/app/build.gradle +1 -3
  118. package/template/android/build.gradle +0 -4
  119. package/template/package.json +1 -1
  120. package/tvos-types.d.ts +4 -0
  121. package/Libraries/Components/AppleTV/TVFocusGuideView.js +0 -79
  122. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1-sources.jar.md5 +0 -1
  123. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1-sources.jar.sha1 +0 -1
  124. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1-sources.jar.sha256 +0 -1
  125. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1-sources.jar.sha512 +0 -1
  126. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1.aar.md5 +0 -1
  127. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1.aar.sha1 +0 -1
  128. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1.aar.sha256 +0 -1
  129. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1.aar.sha512 +0 -1
  130. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1.module.md5 +0 -1
  131. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1.module.sha1 +0 -1
  132. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1.module.sha256 +0 -1
  133. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1.module.sha512 +0 -1
  134. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1.pom.md5 +0 -1
  135. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1.pom.sha1 +0 -1
  136. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1.pom.sha256 +0 -1
  137. package/android/com/facebook/react/react-native/0.68.1-1/react-native-0.68.1-1.pom.sha512 +0 -1
@@ -8,17 +8,17 @@
8
8
  * @flow strict-local
9
9
  */
10
10
 
11
- import type {ViewProps} from 'react-native/Libraries/Components/View/ViewPropTypes';
12
- import type {ColorValue} from 'react-native/Libraries/StyleSheet/StyleSheet';
11
+ import type {ViewProps} from '../../Components/View/ViewPropTypes';
12
+ import type {ColorValue} from '../../StyleSheet/StyleSheet';
13
13
  import type {
14
14
  WithDefault,
15
15
  DirectEventHandler,
16
16
  Int32,
17
17
  Float,
18
- } from 'react-native/Libraries/Types/CodegenTypes';
19
- import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';
20
- import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
21
- import type {HostComponent} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes';
18
+ } from '../../Types/CodegenTypes';
19
+ import codegenNativeCommands from '../../Utilities/codegenNativeCommands';
20
+ import codegenNativeComponent from '../../Utilities/codegenNativeComponent';
21
+ import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
22
22
  import * as React from 'react';
23
23
 
24
24
  type DrawerStateEvent = $ReadOnly<{|
@@ -36,9 +36,10 @@ import type {
36
36
  PressEvent,
37
37
  } from '../../Types/CoreEventTypes';
38
38
  import View from '../View/View';
39
- import typeof TVParallaxPropertiesType from '../AppleTV/TVViewPropTypes';
39
+ import typeof TVParallaxPropertiesType from '../TV/TVViewPropTypes';
40
40
  import Platform from '../../Utilities/Platform';
41
- import {tvFocusEventHandler} from '../AppleTV/TVFocusEventHandler';
41
+ import {tvFocusEventHandler} from '../TV/TVFocusEventHandler';
42
+ import tagForComponentOrHandle from '../TV/tagForComponentOrHandle';
42
43
 
43
44
  type ViewStyleProp = $ElementType<React.ElementConfig<typeof View>, 'style'>;
44
45
 
@@ -212,6 +213,11 @@ function Pressable(props: Props, forwardedRef): React.Node {
212
213
  onHoverIn,
213
214
  onHoverOut,
214
215
  isTVSelectable,
216
+ nextFocusDown,
217
+ nextFocusForward,
218
+ nextFocusLeft,
219
+ nextFocusRight,
220
+ nextFocusUp,
215
221
  onBlur,
216
222
  onFocus,
217
223
  onLongPress,
@@ -354,6 +360,11 @@ function Pressable(props: Props, forwardedRef): React.Node {
354
360
  {...restPropsWithDefaults}
355
361
  {...eventHandlers}
356
362
  ref={viewRef}
363
+ nextFocusDown={tagForComponentOrHandle(props.nextFocusDown)}
364
+ nextFocusForward={tagForComponentOrHandle(props.nextFocusForward)}
365
+ nextFocusLeft={tagForComponentOrHandle(props.nextFocusLeft)}
366
+ nextFocusRight={tagForComponentOrHandle(props.nextFocusRight)}
367
+ nextFocusUp={tagForComponentOrHandle(props.nextFocusUp)}
357
368
  isTVSelectable={isTVSelectable !== false && accessible !== false}
358
369
  style={typeof style === 'function' ? style({pressed, focused}) : style}
359
370
  tvParallaxProperties={tvParallaxProperties}
@@ -12,7 +12,9 @@ import invariant from 'invariant';
12
12
  import {Commands} from '../View/ViewNativeComponent';
13
13
  import type {ColorValue} from '../../StyleSheet/StyleSheet';
14
14
  import type {PressEvent} from '../../Types/CoreEventTypes';
15
- import {Platform, View, processColor} from 'react-native';
15
+ import Platform from '../../Utilities/Platform';
16
+ import View from '../../Components/View/View';
17
+ import processColor from '../../StyleSheet/processColor';
16
18
  import * as React from 'react';
17
19
  import {useMemo} from 'react';
18
20
 
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its 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
8
+ * @format
9
+ */
10
+
11
+ const React = require('react');
12
+ const ReactNative = require('react-native');
13
+ import ReactNativeShims from '../../Renderer/shims/ReactNative';
14
+ const Platform = require('../../Utilities/Platform');
15
+ import {Commands} from '../View/ViewNativeComponent';
16
+ import type {ViewProps} from '../View/ViewPropTypes';
17
+
18
+ type TVFocusGuideViewProps = $ReadOnly<{
19
+ ...ViewProps,
20
+
21
+ /**
22
+ * The views the focus should go to
23
+ */
24
+ destinations: ?(Object[]),
25
+
26
+ /**
27
+ * How the TVFocusGuideView content safe padding should be applied. "null" to disable it.
28
+ */
29
+ safePadding?: 'vertical' | 'horizontal' | 'both' | null,
30
+ }>;
31
+
32
+ const TVFocusGuideView = (props: TVFocusGuideViewProps): React.Node => {
33
+ const safePadding =
34
+ props.safePadding === undefined ? 'both' : props.safePadding;
35
+ const focusGuidePadding =
36
+ safePadding === 'both'
37
+ ? {padding: 1}
38
+ : safePadding === 'vertical'
39
+ ? {paddingVertical: 1}
40
+ : safePadding === 'horizontal'
41
+ ? {paddingHorizontal: 1}
42
+ : null;
43
+
44
+ /**
45
+ * The client specified layout(using 'style' prop) should be applied the container view ReactNative.View.
46
+ * And the focusGuide's layout should be overridden to wrap it fully inside the container view.
47
+ * For example, if the client specifies 'marginLeft' property in the style prop,
48
+ * then the TVFocusGuideView will apply the 'marginLeft' for both the parentView and the focusGuideView.
49
+ * and so, the left margin is getting added twice and UI becomes incorrect.
50
+ * The same is applicable for other layout properties.
51
+ */
52
+ const focusGuideStyle = [focusGuidePadding, props.style, styles.focusGuide];
53
+
54
+ return (
55
+ /**
56
+ * The container needs to have at least a width of 1 and a height of 1.
57
+ * Also, being the container, it shouldn't be possible to give it some padding.
58
+ */
59
+ <ReactNative.View style={[props.style, styles.container]}>
60
+ {Platform.isTV ? (
61
+ Platform.isTVOS ? (
62
+ <FocusGuideViewTVOS {...props} style={focusGuideStyle} />
63
+ ) : (
64
+ <FocusGuideViewAndroidTV {...props} style={focusGuideStyle} />
65
+ )
66
+ ) : (
67
+ props.children
68
+ )}
69
+ </ReactNative.View>
70
+ );
71
+ };
72
+
73
+ const FocusGuideViewTVOS = (props: TVFocusGuideViewProps) => {
74
+ const focusGuideRef = React.useRef(null);
75
+
76
+ React.useEffect(() => {
77
+ const nativeDestinations = (props.destinations || [])
78
+ .map(d => ReactNative.findNodeHandle(d))
79
+ .filter(c => c !== 0 && c !== null && c !== undefined);
80
+ const hostComponentRef = ReactNativeShims.findHostInstance_DEPRECATED(
81
+ focusGuideRef?.current,
82
+ );
83
+ hostComponentRef &&
84
+ Commands.setDestinations(hostComponentRef, nativeDestinations);
85
+ }, [props.destinations]);
86
+
87
+ return (
88
+ <ReactNative.View style={props.style} ref={focusGuideRef}>
89
+ {props.children}
90
+ </ReactNative.View>
91
+ );
92
+ };
93
+
94
+ const FocusGuideViewAndroidTV = (props: TVFocusGuideViewProps) => {
95
+ const nativeDestinations = React.useMemo(
96
+ () =>
97
+ (props.destinations || [])
98
+ .map(d => ReactNative.findNodeHandle(d))
99
+ .filter(c => c !== 0 && c !== null && c !== undefined),
100
+ [props.destinations],
101
+ );
102
+
103
+ return (
104
+ <ReactNative.View
105
+ style={props.style}
106
+ focusable={props.focusable ?? true}
107
+ destinations={nativeDestinations}
108
+ >
109
+ {props.children}
110
+ </ReactNative.View>
111
+ );
112
+ };
113
+
114
+ const styles = ReactNative.StyleSheet.create({
115
+ container: {
116
+ minWidth: 1,
117
+ minHeight: 1,
118
+ paddingTop: 0,
119
+ paddingBottom: 0,
120
+ paddingLeft: 0,
121
+ paddingRight: 0,
122
+ },
123
+ focusGuide: {
124
+ left: 0,
125
+ top: 0,
126
+ right: 0,
127
+ bottom: 0,
128
+ marginLeft: 0,
129
+ marginTop: 0,
130
+ marginRight: 0,
131
+ marginBottom: 0,
132
+ },
133
+ });
134
+
135
+ module.exports = TVFocusGuideView;
@@ -18,7 +18,7 @@ import type {
18
18
  PressEvent,
19
19
  } from '../../Types/CoreEventTypes';
20
20
  import Platform from '../../Utilities/Platform';
21
- import TVEventHandler from '../../Components/AppleTV/TVEventHandler';
21
+ import TVEventHandler from '../../Components/TV/TVEventHandler';
22
22
 
23
23
  type TVTouchableConfig = $ReadOnly<{|
24
24
  getDisabled: () => boolean,
@@ -15,7 +15,7 @@ import Platform from '../../Utilities/Platform';
15
15
  import Position from './Position';
16
16
  import UIManager from '../../ReactNative/UIManager';
17
17
  import SoundManager from '../Sound/SoundManager';
18
- import {tvFocusEventHandler} from '../AppleTV/TVFocusEventHandler';
18
+ import {tvFocusEventHandler} from '../TV/TVFocusEventHandler';
19
19
 
20
20
  import {PressabilityDebugView} from '../../Pressability/PressabilityDebug';
21
21
 
@@ -19,6 +19,8 @@ import typeof TouchableWithoutFeedback from './TouchableWithoutFeedback';
19
19
  import Platform from '../../Utilities/Platform';
20
20
  import View from '../../Components/View/View';
21
21
  import type {ViewProps} from '../../Components/View/ViewPropTypes';
22
+ import typeof TVParallaxPropertiesType from '../TV/TVViewPropTypes';
23
+ import tagForComponentOrHandle from '../TV/tagForComponentOrHandle';
22
24
  import * as React from 'react';
23
25
 
24
26
  type AndroidProps = $ReadOnly<{|
@@ -29,9 +31,21 @@ type AndroidProps = $ReadOnly<{|
29
31
  nextFocusUp?: ?number,
30
32
  |}>;
31
33
 
34
+ type TVProps = $ReadOnly<{|
35
+ hasTVPreferredFocus?: ?boolean,
36
+ isTVSelectable?: ?boolean,
37
+ tvParallaxProperties?: ?TVParallaxPropertiesType,
38
+ nextFocusDown?: ?number,
39
+ nextFocusForward?: ?number,
40
+ nextFocusLeft?: ?number,
41
+ nextFocusRight?: ?number,
42
+ nextFocusUp?: ?number,
43
+ |}>;
44
+
32
45
  type Props = $ReadOnly<{|
33
46
  ...React.ElementConfig<TouchableWithoutFeedback>,
34
47
  ...AndroidProps,
48
+ ...TVProps,
35
49
  ...ViewProps,
36
50
 
37
51
  activeOpacity?: ?number,
@@ -313,11 +327,11 @@ class TouchableHighlight extends React.Component<Props, State> {
313
327
  hasTVPreferredFocus={this.props.hasTVPreferredFocus === true}
314
328
  isTVSelectable={this.props.isTVSelectable !== false && this.props.accessible !== false}
315
329
  tvParallaxProperties={this.props.tvParallaxProperties}
316
- nextFocusDown={this.props.nextFocusDown}
317
- nextFocusForward={this.props.nextFocusForward}
318
- nextFocusLeft={this.props.nextFocusLeft}
319
- nextFocusRight={this.props.nextFocusRight}
320
- nextFocusUp={this.props.nextFocusUp}
330
+ nextFocusDown={tagForComponentOrHandle(this.props.nextFocusDown)}
331
+ nextFocusForward={tagForComponentOrHandle(this.props.nextFocusForward)}
332
+ nextFocusLeft={tagForComponentOrHandle(this.props.nextFocusLeft)}
333
+ nextFocusRight={tagForComponentOrHandle(this.props.nextFocusRight)}
334
+ nextFocusUp={tagForComponentOrHandle(this.props.nextFocusUp)}
321
335
  focusable={
322
336
  this.props.focusable !== false && this.props.onPress !== undefined
323
337
  }
@@ -20,6 +20,7 @@ import type {PressEvent} from '../../Types/CoreEventTypes';
20
20
  import Platform from '../../Utilities/Platform';
21
21
  import View from '../../Components/View/View';
22
22
  import processColor from '../../StyleSheet/processColor';
23
+ import tagForComponentOrHandle from '../TV/tagForComponentOrHandle';
23
24
  import * as React from 'react';
24
25
  import invariant from 'invariant';
25
26
 
@@ -291,11 +292,11 @@ class TouchableNativeFeedback extends React.Component<Props, State> {
291
292
  this.props.onPress !== undefined &&
292
293
  !this.props.disabled,
293
294
  nativeID: this.props.nativeID,
294
- nextFocusDown: this.props.nextFocusDown,
295
- nextFocusForward: this.props.nextFocusForward,
296
- nextFocusLeft: this.props.nextFocusLeft,
297
- nextFocusRight: this.props.nextFocusRight,
298
- nextFocusUp: this.props.nextFocusUp,
295
+ nextFocusDown: tagForComponentOrHandle(this.props.nextFocusDown),
296
+ nextFocusForward: tagForComponentOrHandle(this.props.nextFocusForward),
297
+ nextFocusLeft: tagForComponentOrHandle(this.props.nextFocusLeft),
298
+ nextFocusRight: tagForComponentOrHandle(this.props.nextFocusRight),
299
+ nextFocusUp: tagForComponentOrHandle(this.props.nextFocusUp),
299
300
  onLayout: this.props.onLayout,
300
301
  testID: this.props.testID,
301
302
  },
@@ -318,7 +319,7 @@ class TouchableNativeFeedback extends React.Component<Props, State> {
318
319
  }
319
320
  },
320
321
  onPress: event => {
321
- if (this.props.onPress != null) {
322
+ if (this.props.onPress != null && Platform.OS !== 'android') {
322
323
  this.props.onPress(event);
323
324
  }
324
325
  },
@@ -19,8 +19,8 @@ import Easing from '../../Animated/Easing';
19
19
  import type {ViewStyleProp} from '../../StyleSheet/StyleSheet';
20
20
  import flattenStyle from '../../StyleSheet/flattenStyle';
21
21
  import Platform from '../../Utilities/Platform';
22
- import typeof TVParallaxPropertiesType from '../AppleTV/TVViewPropTypes';
23
- import tagForComponentOrHandle from '../AppleTV/tagForComponentOrHandle';
22
+ import typeof TVParallaxPropertiesType from '../TV/TVViewPropTypes';
23
+ import tagForComponentOrHandle from '../TV/tagForComponentOrHandle';
24
24
 
25
25
  import * as React from 'react';
26
26
 
@@ -11,7 +11,7 @@
11
11
  import type {ViewConfig} from '../../Renderer/shims/ReactNativeTypes';
12
12
  import ReactNativeViewViewConfigAndroid from './ReactNativeViewViewConfigAndroid';
13
13
  import ReactNativeViewViewConfigAppleTV from './ReactNativeViewViewConfigAppleTV';
14
- import {Platform} from 'react-native';
14
+ import Platform from '../../Utilities/Platform';
15
15
 
16
16
  const ReactNativeViewConfig: ViewConfig = {
17
17
  uiViewClassName: 'RCTView',
@@ -21,7 +21,7 @@ import type {
21
21
  import type {EdgeInsetsProp} from '../../StyleSheet/EdgeInsetsPropType';
22
22
  import type {Node} from 'react';
23
23
  import type {ViewStyleProp} from '../../StyleSheet/StyleSheet';
24
- import type {TVViewProps} from '../AppleTV/TVViewPropTypes';
24
+ import type {TVViewProps} from '../TV/TVViewPropTypes';
25
25
  import type {
26
26
  AccessibilityRole,
27
27
  AccessibilityState,
@@ -11,7 +11,8 @@
11
11
  import invariant from 'invariant';
12
12
  import type {ViewToken} from './ViewabilityHelper';
13
13
  import {keyExtractor as defaultKeyExtractor} from './VirtualizeUtils';
14
- import {View, VirtualizedList} from 'react-native';
14
+ import View from '../Components/View/View';
15
+ import VirtualizedList from './VirtualizedList';
15
16
  import * as React from 'react';
16
17
 
17
18
  type Item = any;
@@ -10,9 +10,11 @@
10
10
 
11
11
  import {ansiToJson} from 'anser';
12
12
  import * as React from 'react';
13
- import {StyleSheet, Text, View} from 'react-native';
13
+ import StyleSheet from '../../StyleSheet/StyleSheet';
14
+ import Text from '../../Text/Text';
15
+ import View from '../../Components/View/View';
14
16
 
15
- import type {TextStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet';
17
+ import type {TextStyleProp} from '../../StyleSheet/StyleSheet';
16
18
 
17
19
  // Afterglow theme from https://iterm2colorschemes.com/
18
20
  const COLORS = {
@@ -18,8 +18,8 @@ if (__DEV__) {
18
18
  "use strict";
19
19
 
20
20
  var React = require("react");
21
- require("react-native/Libraries/ReactPrivate/ReactNativePrivateInitializeCore");
22
- var ReactNativePrivateInterface = require("react-native/Libraries/ReactPrivate/ReactNativePrivateInterface");
21
+ require("../../ReactPrivate/ReactNativePrivateInitializeCore");
22
+ var ReactNativePrivateInterface = require("../../ReactPrivate/ReactNativePrivateInterface");
23
23
  var Scheduler = require("scheduler");
24
24
 
25
25
  var ReactSharedInternals =
@@ -13,7 +13,7 @@
13
13
 
14
14
  'use strict';
15
15
 
16
- import {ReactNativeViewConfigRegistry} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
16
+ import {ReactNativeViewConfigRegistry} from '../../ReactPrivate/ReactNativePrivateInterface';
17
17
  import {type ViewConfig} from './ReactNativeTypes';
18
18
 
19
19
  const {register} = ReactNativeViewConfigRegistry;
@@ -14,7 +14,7 @@
14
14
  'use strict';
15
15
 
16
16
  const Platform = require('./Platform');
17
- const TVEventHandler = require('../Components/AppleTV/TVEventHandler');
17
+ const TVEventHandler = require('../Components/TV/TVEventHandler');
18
18
 
19
19
  type BackPressEventName = 'backPress' | 'hardwareBackPress';
20
20
 
@@ -35,13 +35,11 @@ export type ReactTestRendererJSON =
35
35
  * delete this comment and run Flow. */
36
36
  $ReturnType<ReactTestRenderer.create.toJSON>;
37
37
 
38
- const {
39
- Switch,
40
- Text,
41
- TextInput,
42
- View,
43
- VirtualizedList,
44
- } = require('react-native');
38
+ const Switch = require('../Components/Switch/Switch');
39
+ const Text = require('../Text/Text');
40
+ const TextInput = require('../Components/TextInput/TextInput');
41
+ const View = require('../Components/View/View');
42
+ const VirtualizedList = require('../Lists/VirtualizedList');
45
43
 
46
44
  function byClickable(): Predicate {
47
45
  return withMessage(
package/README.md CHANGED
@@ -201,7 +201,12 @@ class Game2048 extends React.Component {
201
201
  - `enableTVMenuKey`/`disableTVMenuKey`: Method to enable and disable the menu key gesture recognizer, in order to fix an issue with Apple's guidelines for menu key navigation (see https://github.com/facebook/react-native/issues/18930). The `RNTester` app uses these methods to implement correct menu key behavior for back navigation.
202
202
  - `enableTVPanGesture`/`disableTVPanGesture`: Methods to enable and disable detection of finger touches that pan across the touch surface of the Siri remote. See `TVEventHandlerExample` in the `RNTester` app for a demo.
203
203
 
204
- - _TVFocusGuideView_: This component provides support for Apple's `UIFocusGuide` API, to help ensure that focusable controls can be navigated to, even if they are not directly in line with other controls. An example is provided in `RNTester` that shows two different ways of using this component.
204
+ - _TVFocusGuideView_: This component provides support for Apple's `UIFocusGuide` API and is implemented in the same way for Android TV, to help ensure that focusable controls can be navigated to, even if they are not directly in line with other controls. An example is provided in `RNTester` that shows two different ways of using this component.
205
+
206
+ | Prop | Value | Description |
207
+ |---|---|---|
208
+ | destinations | any[] | Array of `Component`s to register as destinations of the FocusGuideView |
209
+ | safePadding | 'both' (default) \| 'vertical' \| 'horizontal' \| null | When the FocusGuide children are exactly the same size as the FocusGuide's container, the focus will almost certainly be given directly to the children without going through the FocusGuide. This prop make sure it doesn't happen by adding a padding of 1 in all directions.<br />"null" to disable it. |
205
210
 
206
211
  - _Next Focus Direction_: the props `nextFocus*` on `View` should work as expected on iOS too (previously android only). One caveat is that if there is no focusable in the `nextFocusable*` direction next to the starting view, iOS doesn't check if we want to override the destination.
207
212
 
@@ -71,6 +71,10 @@ NS_ASSUME_NONNULL_BEGIN
71
71
 
72
72
  #if TARGET_OS_TV
73
73
  @property(nonatomic, nullable) UIFocusGuide *focusGuide;
74
+ @property(nonatomic, nullable) UIFocusGuide *focusGuideUp;
75
+ @property(nonatomic, nullable) UIFocusGuide *focusGuideDown;
76
+ @property(nonatomic, nullable) UIFocusGuide *focusGuideLeft;
77
+ @property(nonatomic, nullable) UIFocusGuide *focusGuideRight;
74
78
  #endif
75
79
 
76
80
  /**
@@ -309,41 +309,92 @@ using namespace facebook::react;
309
309
  return _props->isTVSelectable;
310
310
  }
311
311
 
312
- - (NSArray<id<UIFocusEnvironment>> *)preferredFocusEnvironments {
313
- if (_nextFocusActiveTarget == nil) return [super preferredFocusEnvironments];
314
- UIView * nextFocusActiveTarget = _nextFocusActiveTarget;
315
- _nextFocusActiveTarget = nil;
316
- NSArray<id<UIFocusEnvironment>> * focusEnvironment = @[nextFocusActiveTarget];
317
- return focusEnvironment;
318
- }
319
-
320
- - (BOOL) shouldUpdateFocusInContext:(UIFocusUpdateContext *)context {
321
- if (self.isFocused) {
322
- if (_nextFocusUp != nil && context.focusHeading == UIFocusHeadingUp) {
323
- self->_nextFocusActiveTarget = _nextFocusUp;
324
- [self setNeedsFocusUpdate];
325
- return false;
312
+ // In tvOS, to support directional focus APIs, we add a UIFocusGuide for each
313
+ // side of the view where a nextFocus has been set. Set layout constraints to
314
+ // make the guide 1 px thick, and set the destination to the nextFocus object.
315
+ //
316
+ // This is only done once the view is focused.
317
+ //
318
+ - (void)enableDirectionalFocusGuides
319
+ {
320
+ if (self->_nextFocusUp != nil) {
321
+ if (self.focusGuideUp == nil) {
322
+ self.focusGuideUp = [UIFocusGuide new];
323
+ [[self containingRootView] addLayoutGuide:self.focusGuideUp];
324
+
325
+ [self.focusGuideUp.bottomAnchor constraintEqualToAnchor:self.topAnchor].active = YES;
326
+ [self.focusGuideUp.widthAnchor constraintEqualToAnchor:self.widthAnchor].active = YES;
327
+ [self.focusGuideUp.heightAnchor constraintEqualToConstant:1.0].active = YES;
328
+ [self.focusGuideUp.leftAnchor constraintEqualToAnchor:self.leftAnchor].active = YES;
326
329
  }
327
- if (_nextFocusDown != nil && context.focusHeading == UIFocusHeadingDown) {
328
- self->_nextFocusActiveTarget = _nextFocusDown;
329
- [self setNeedsFocusUpdate];
330
- return false;
330
+
331
+ self.focusGuideUp.preferredFocusEnvironments = @[self->_nextFocusUp];
332
+ }
333
+
334
+ if (self->_nextFocusDown != nil) {
335
+ if (self.focusGuideDown == nil) {
336
+ self.focusGuideDown = [UIFocusGuide new];
337
+ [[self containingRootView] addLayoutGuide:self.focusGuideDown];
338
+
339
+ [self.focusGuideDown.topAnchor constraintEqualToAnchor:self.bottomAnchor].active = YES;
340
+ [self.focusGuideDown.widthAnchor constraintEqualToAnchor:self.widthAnchor].active = YES;
341
+ [self.focusGuideDown.heightAnchor constraintEqualToConstant:1.0].active = YES;
342
+ [self.focusGuideDown.leftAnchor constraintEqualToAnchor:self.leftAnchor].active = YES;
331
343
  }
332
- if (_nextFocusLeft != nil && context.focusHeading == UIFocusHeadingLeft) {
333
- self->_nextFocusActiveTarget = _nextFocusLeft;
334
- [self setNeedsFocusUpdate];
335
- return false;
344
+
345
+ self.focusGuideDown.preferredFocusEnvironments = @[self->_nextFocusDown];
346
+ }
347
+
348
+ if (self->_nextFocusLeft != nil) {
349
+ if (self.focusGuideLeft == nil) {
350
+ self.focusGuideLeft = [UIFocusGuide new];
351
+ [[self containingRootView] addLayoutGuide:self.focusGuideLeft];
352
+
353
+ [self.focusGuideLeft.topAnchor constraintEqualToAnchor:self.topAnchor].active = YES;
354
+ [self.focusGuideLeft.widthAnchor constraintEqualToConstant:1.0].active = YES;
355
+ [self.focusGuideLeft.heightAnchor constraintEqualToAnchor:self.heightAnchor].active = YES;
356
+ [self.focusGuideLeft.rightAnchor constraintEqualToAnchor:self.leftAnchor].active = YES;
336
357
  }
337
- if (_nextFocusRight != nil && context.focusHeading == UIFocusHeadingRight) {
338
- self->_nextFocusActiveTarget = _nextFocusRight;
339
- [self setNeedsFocusUpdate];
340
- return false;
358
+
359
+ self.focusGuideLeft.preferredFocusEnvironments = @[self->_nextFocusLeft];
360
+ }
361
+
362
+ if (self->_nextFocusRight != nil) {
363
+ if (self.focusGuideRight == nil) {
364
+ self.focusGuideRight = [UIFocusGuide new];
365
+ [[self containingRootView] addLayoutGuide:self.focusGuideRight];
366
+
367
+ [self.focusGuideRight.topAnchor constraintEqualToAnchor:self.topAnchor].active = YES;
368
+ [self.focusGuideRight.widthAnchor constraintEqualToConstant:1.0].active = YES;
369
+ [self.focusGuideRight.heightAnchor constraintEqualToAnchor:self.heightAnchor].active = YES;
370
+ [self.focusGuideRight.leftAnchor constraintEqualToAnchor:self.rightAnchor].active = YES;
341
371
  }
342
- self->_nextFocusActiveTarget = nil;
343
- return true;
372
+
373
+ self.focusGuideRight.preferredFocusEnvironments = @[self->_nextFocusRight];
374
+ }
375
+ }
376
+ // Called when focus leaves this view -- disable the directional focus guides
377
+ // (if they exist) so that they don't interfere with focus navigation from
378
+ // other views
379
+ //
380
+ - (void)disableDirectionalFocusGuides
381
+ {
382
+ if (self.focusGuideUp != nil) {
383
+ [[self containingRootView] removeLayoutGuide:self.focusGuideUp];
384
+ self.focusGuideUp = nil;
385
+ }
386
+ if (self.focusGuideDown != nil) {
387
+ [[self containingRootView] removeLayoutGuide:self.focusGuideDown];
388
+ self.focusGuideDown = nil;
389
+ }
390
+ if (self.focusGuideLeft != nil) {
391
+ [[self containingRootView] removeLayoutGuide:self.focusGuideLeft];
392
+ self.focusGuideLeft = nil;
393
+ }
394
+ if (self.focusGuideRight != nil) {
395
+ [[self containingRootView] removeLayoutGuide:self.focusGuideRight];
396
+ self.focusGuideRight = nil;
344
397
  }
345
- self->_nextFocusActiveTarget = nil;
346
- return true;
347
398
  }
348
399
 
349
400
  - (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
@@ -353,11 +404,13 @@ using namespace facebook::react;
353
404
  }
354
405
  if (context.nextFocusedView == self && self.isUserInteractionEnabled ) {
355
406
  [self becomeFirstResponder];
407
+ [self enableDirectionalFocusGuides];
356
408
  [coordinator addCoordinatedAnimations:^(void){
357
409
  [self addParallaxMotionEffects];
358
410
  [self sendFocusNotification:context];
359
411
  } completion:^(void){}];
360
412
  } else {
413
+ [self disableDirectionalFocusGuides];
361
414
  [coordinator addCoordinatedAnimations:^(void){
362
415
  [self removeParallaxMotionEffects];
363
416
  [self sendBlurNotification:context];
@@ -32,11 +32,15 @@
32
32
  /**
33
33
  * Focus direction tags
34
34
  */
35
- @property (nonatomic, strong) RCTTVView * nextFocusUp;
36
- @property (nonatomic, strong) RCTTVView * nextFocusDown;
37
- @property (nonatomic, strong) RCTTVView * nextFocusLeft;
38
- @property (nonatomic, strong) RCTTVView * nextFocusRight;
39
- @property (nonatomic, strong) RCTTVView * nextFocusActiveTarget;
35
+ @property (nonatomic, weak) RCTTVView * nextFocusUp;
36
+ @property (nonatomic, weak) RCTTVView * nextFocusDown;
37
+ @property (nonatomic, weak) RCTTVView * nextFocusLeft;
38
+ @property (nonatomic, weak) RCTTVView * nextFocusRight;
39
+
40
+ @property (nonatomic, strong) UIFocusGuide * focusGuideUp;
41
+ @property (nonatomic, strong) UIFocusGuide * focusGuideDown;
42
+ @property (nonatomic, strong) UIFocusGuide * focusGuideLeft;
43
+ @property (nonatomic, strong) UIFocusGuide * focusGuideRight;
40
44
 
41
45
  - (instancetype)initWithBridge:(RCTBridge *)bridge;
42
46