diff --git a/packages/react-native/Libraries/Components/Button.js b/packages/react-native/Libraries/Components/Button.js index 0c3ddba19678..ee8b2272f271 100644 --- a/packages/react-native/Libraries/Components/Button.js +++ b/packages/react-native/Libraries/Components/Button.js @@ -56,16 +56,6 @@ type ButtonPropsCore = Readonly<{ */ color?: ?ColorValue, - /** - * TV preferred focus. - * - * @platform tv - * - * @default `false` - * @deprecated Use `focusable` instead - */ - hasTVPreferredFocus?: ?boolean, - /** * Designates the next view to receive focus when the user navigates down. See * the [Android documentation][android:nextFocusDown]. @@ -219,7 +209,6 @@ const Button: component( onPress, touchSoundDisabled, title, - hasTVPreferredFocus, nextFocusDown, nextFocusForward, nextFocusLeft, @@ -290,7 +279,6 @@ const Button: component( accessibilityRole="button" accessibilityState={_accessibilityState} importantForAccessibility={_importantForAccessibility} - hasTVPreferredFocus={hasTVPreferredFocus} nextFocusDown={nextFocusDown} nextFocusForward={nextFocusForward} nextFocusLeft={nextFocusLeft} diff --git a/packages/react-native/Libraries/Components/Touchable/TouchableHighlight.js b/packages/react-native/Libraries/Components/Touchable/TouchableHighlight.js index fcce86c35fd3..e8a01c46ff2c 100644 --- a/packages/react-native/Libraries/Components/Touchable/TouchableHighlight.js +++ b/packages/react-native/Libraries/Components/Touchable/TouchableHighlight.js @@ -34,13 +34,6 @@ type AndroidProps = Readonly<{ nextFocusUp?: ?number, }>; -type IOSProps = Readonly<{ - /** - * @deprecated Use `focusable` instead - */ - hasTVPreferredFocus?: ?boolean, -}>; - type TouchableHighlightBaseProps = Readonly<{ /** * Opacity of the wrapped view when touch is active. Requires `underlayColor` to be set. @@ -75,7 +68,6 @@ type TouchableHighlightBaseProps = Readonly<{ export type TouchableHighlightProps = Readonly<{ ...TouchableWithoutFeedbackProps, ...AndroidProps, - ...IOSProps, ...TouchableHighlightBaseProps, }>; @@ -281,7 +273,6 @@ class TouchableHighlightImpl extends React.Component< )} onLayout={this.props.onLayout} hitSlop={this.props.hitSlop} - hasTVPreferredFocus={this.props.hasTVPreferredFocus} nextFocusDown={this.props.nextFocusDown} nextFocusForward={this.props.nextFocusForward} nextFocusLeft={this.props.nextFocusLeft} diff --git a/packages/react-native/Libraries/Components/Touchable/TouchableNativeFeedback.js b/packages/react-native/Libraries/Components/Touchable/TouchableNativeFeedback.js index e975a0bd3858..bd30c9552337 100644 --- a/packages/react-native/Libraries/Components/Touchable/TouchableNativeFeedback.js +++ b/packages/react-native/Libraries/Components/Touchable/TouchableNativeFeedback.js @@ -26,14 +26,6 @@ import * as React from 'react'; import {cloneElement} from 'react'; type TouchableNativeFeedbackTVProps = { - /** - * *(Apple TV only)* TV preferred focus (see documentation for the View component). - * - * @platform ios - * @deprecated Use `focusable` instead - */ - hasTVPreferredFocus?: ?boolean, - /** * Designates the next view to receive focus when the user navigates down. See the Android documentation. * @@ -345,7 +337,6 @@ class TouchableNativeFeedback extends React.Component< accessibilityLiveRegion: accessibilityLiveRegion, accessibilityElementsHidden: this.props['aria-hidden'] ?? this.props.accessibilityElementsHidden, - hasTVPreferredFocus: this.props.hasTVPreferredFocus, hitSlop: this.props.hitSlop, focusable: this.props.focusable !== false && diff --git a/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js b/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js index c957356748bf..6f86c40f369d 100644 --- a/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js +++ b/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js @@ -25,14 +25,6 @@ import * as React from 'react'; export type TouchableOpacityInstance = HostInstance; export type TouchableOpacityTVProps = Readonly<{ - /** - * *(Apple TV only)* TV preferred focus (see documentation for the View component). - * - * @platform ios - * @deprecated Use `focusable` instead - */ - hasTVPreferredFocus?: ?boolean, - /** * Designates the next view to receive focus when the user navigates down. See the Android documentation. * @@ -261,7 +253,6 @@ class TouchableOpacity extends React.Component< nextFocusLeft={this.props.nextFocusLeft} nextFocusRight={this.props.nextFocusRight} nextFocusUp={this.props.nextFocusUp} - hasTVPreferredFocus={this.props.hasTVPreferredFocus} hitSlop={this.props.hitSlop} focusable={ this.props.focusable !== false && diff --git a/packages/react-native/Libraries/Components/View/ViewPropTypes.js b/packages/react-native/Libraries/Components/View/ViewPropTypes.js index 3d5fdd8db373..0cf129b84dcf 100644 --- a/packages/react-native/Libraries/Components/View/ViewPropTypes.js +++ b/packages/react-native/Libraries/Components/View/ViewPropTypes.js @@ -305,14 +305,6 @@ export type ViewPropsAndroid = Readonly<{ */ renderToHardwareTextureAndroid?: ?boolean, - /** - * Whether to force the Android TV focus engine to move focus to this view. - * - * @platform android - * @deprecated Use `focusable` instead - */ - hasTVPreferredFocus?: ?boolean, - /** * Designates the next view to receive focus when the user navigates down. * The value is the `nativeID` of the target view. @@ -390,14 +382,6 @@ export type TVViewPropsIOS = Readonly<{ */ isTVSelectable?: boolean, - /** - * *(Apple TV only)* May be set to true to force the Apple TV focus engine to move focus to this view. - * - * @platform ios - * @deprecated Use `focusable` instead - */ - hasTVPreferredFocus?: boolean, - /** * *(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 2.0. * diff --git a/packages/react-native/Libraries/Components/View/__tests__/View-benchmark-itest.js b/packages/react-native/Libraries/Components/View/__tests__/View-benchmark-itest.js index 3733eb04ca08..a59a854bb946 100644 --- a/packages/react-native/Libraries/Components/View/__tests__/View-benchmark-itest.js +++ b/packages/react-native/Libraries/Components/View/__tests__/View-benchmark-itest.js @@ -53,7 +53,6 @@ function createViewsWithLargeAmountOfPropsAndStyles(count: number): React.Node { aria-live={'polite'} collapsable={false} focusable={i % 2 === 0} - hasTVPreferredFocus={i % 2 === 0} id={String(i)} importantForAccessibility={'no-hide-descendants'} nativeID={String(i)} diff --git a/packages/react-native/Libraries/Components/View/__tests__/ViewProps-benchmark-itest.js b/packages/react-native/Libraries/Components/View/__tests__/ViewProps-benchmark-itest.js index 0544b9115c2b..adccf9456476 100644 --- a/packages/react-native/Libraries/Components/View/__tests__/ViewProps-benchmark-itest.js +++ b/packages/react-native/Libraries/Components/View/__tests__/ViewProps-benchmark-itest.js @@ -36,7 +36,6 @@ function buildViewsWithFullPropBag( aria-live="polite" collapsable={false} focusable={i % 2 === 0} - hasTVPreferredFocus={i % 2 === 0} id={String(i)} importantForAccessibility="no-hide-descendants" nativeID={String(i)} diff --git a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js index 6e3ee698720d..c8cd4d94bfa1 100644 --- a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js +++ b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.android.js @@ -360,7 +360,6 @@ const validAttributesForNonEventProps = { // ReactViewManager @ReactProps accessible: true, - hasTVPreferredFocus: true, nextFocusDown: true, nextFocusForward: true, nextFocusLeft: true, diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt index 058c584d8679..21ef11182da3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt @@ -124,14 +124,16 @@ public open class ReactViewManager : ReactClippingViewManager() view.axOrderList = axOrderList } - @ReactProp(name = "hasTVPreferredFocus") - public open fun setTVPreferredFocus(view: ReactViewGroup, hasTVPreferredFocus: Boolean) { - if (hasTVPreferredFocus) { - view.isFocusable = true - view.isFocusableInTouchMode = true - view.requestFocus() - } - } + /** + * Retained for binary compatibility with [ReactViewManager] subclasses. + * + * This method no longer registers a React prop or changes view focus. + */ + @Deprecated("Use focusable or focus() instead") + public open fun setTVPreferredFocus( + view: ReactViewGroup, + hasTVPreferredFocus: Boolean, + ): Unit = Unit @ReactProp(name = ViewProps.BACKGROUND_IMAGE, customType = "BackgroundImage") public open fun setBackgroundImage(view: ReactViewGroup, backgroundImage: ReadableArray?) { diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FocusOrderingHelper.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FocusOrderingHelper.cpp index bece59c33118..1e4e04c49d9c 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FocusOrderingHelper.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FocusOrderingHelper.cpp @@ -207,8 +207,7 @@ void FocusOrderingHelper::traverseAndUpdateNextFocusableElement( // We only care about focusable elements since only they can be both // focused and present in the hierarchy if (currNode->getTraits().check(ShadowNodeTraits::Trait::KeyboardFocusable) || - (props != nullptr && - (props->focusable || props->accessible || props->hasTVPreferredFocus))) { + (props != nullptr && (props->focusable || props->accessible))) { LayoutMetrics nodeLayoutMetrics = uimanager.getRelativeLayoutMetrics( *currNode, parentShadowNode.get(), {.includeTransform = true}); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp index f8eb6df79520..8dc2c403abc8 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp @@ -48,12 +48,6 @@ HostPlatformViewProps::HostPlatformViewProps( "focusable", sourceProps.focusable, {})), - hasTVPreferredFocus(convertRawProp( - context, - rawProps, - "hasTVPreferredFocus", - sourceProps.hasTVPreferredFocus, - {})), needsOffscreenAlphaCompositing(convertRawProp( context, rawProps, @@ -120,7 +114,6 @@ void HostPlatformViewProps::setProp( RAW_SET_PROP_SWITCH_CASE(nativeBackground, "nativeBackgroundAndroid"); RAW_SET_PROP_SWITCH_CASE(nativeForeground, "nativeForegroundAndroid"); RAW_SET_PROP_SWITCH_CASE_BASIC(focusable); - RAW_SET_PROP_SWITCH_CASE_BASIC(hasTVPreferredFocus); RAW_SET_PROP_SWITCH_CASE_BASIC(needsOffscreenAlphaCompositing); RAW_SET_PROP_SWITCH_CASE_BASIC(renderToHardwareTextureAndroid); RAW_SET_PROP_SWITCH_CASE_BASIC(screenReaderFocusable); @@ -482,10 +475,6 @@ folly::dynamic HostPlatformViewProps::getDiffProps( result["focusable"] = focusable; } - if (hasTVPreferredFocus != oldProps->hasTVPreferredFocus) { - result["hasTVPreferredFocus"] = hasTVPreferredFocus; - } - if (needsOffscreenAlphaCompositing != oldProps->needsOffscreenAlphaCompositing) { result["needsOffscreenAlphaCompositing"] = needsOffscreenAlphaCompositing; diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h index 40310cd643c0..d1cdbb86f2d1 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.h @@ -42,7 +42,6 @@ class HostPlatformViewProps : public BaseViewProps { std::optional nativeForeground{}; bool focusable{false}; - bool hasTVPreferredFocus{false}; bool needsOffscreenAlphaCompositing{false}; bool renderToHardwareTextureAndroid{false}; bool screenReaderFocusable{false}; diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewTraitsInitializer.h b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewTraitsInitializer.h index 5f14636e212a..f155014e5f61 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewTraitsInitializer.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewTraitsInitializer.h @@ -22,13 +22,13 @@ inline bool formsStackingContext(const ViewProps &viewProps) inline bool formsView(const ViewProps &viewProps) { return viewProps.nativeBackground.has_value() || viewProps.nativeForeground.has_value() || viewProps.focusable || - viewProps.hasTVPreferredFocus || viewProps.needsOffscreenAlphaCompositing || - viewProps.renderToHardwareTextureAndroid || viewProps.screenReaderFocusable; + viewProps.needsOffscreenAlphaCompositing || viewProps.renderToHardwareTextureAndroid || + viewProps.screenReaderFocusable; } inline bool isKeyboardFocusable(const ViewProps &viewProps) { - return (viewProps.focusable || viewProps.hasTVPreferredFocus); + return viewProps.focusable; } } // namespace facebook::react::HostPlatformViewTraitsInitializer diff --git a/packages/react-native/ReactNativeApi.d.ts b/packages/react-native/ReactNativeApi.d.ts index 250fdb877b78..2891dd53661e 100644 --- a/packages/react-native/ReactNativeApi.d.ts +++ b/packages/react-native/ReactNativeApi.d.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<3ce9599aceb36dd1f09ded3db3332daa>> * * This file was generated by scripts/js-api/build-types/index.js. */ @@ -1671,7 +1671,6 @@ declare type ButtonPropsCore = { readonly "aria-selected"?: boolean readonly color?: ColorValue readonly disabled?: boolean - readonly hasTVPreferredFocus?: boolean readonly importantForAccessibility?: "auto" | "no-hide-descendants" | "no" | "yes" readonly nextFocusDown?: number @@ -2675,9 +2674,6 @@ declare type IOSPlatform = { get isVision(): boolean get Version(): string } -declare type IOSProps = { - readonly hasTVPreferredFocus?: boolean -} declare interface IPerformanceLogger { addTimespan( key: string, @@ -5243,10 +5239,7 @@ declare type TouchableHighlightBaseProps = { } declare type TouchableHighlightInstance = HostInstance declare interface TouchableHighlightProps extends Readonly< - TouchableWithoutFeedbackProps & - AndroidProps & - IOSProps & - TouchableHighlightBaseProps + TouchableWithoutFeedbackProps & AndroidProps & TouchableHighlightBaseProps > {} declare class TouchableNativeFeedback extends React.Component< TouchableNativeFeedbackProps, @@ -5308,7 +5301,6 @@ declare type TouchableNativeFeedbackState = { readonly pressability: Pressability_default } declare type TouchableNativeFeedbackTVProps = { - hasTVPreferredFocus?: boolean nextFocusDown?: number nextFocusForward?: number nextFocusLeft?: number @@ -5328,7 +5320,6 @@ declare type TouchableOpacityProps = Readonly< TouchableOpacityBaseProps > declare type TouchableOpacityTVProps = { - readonly hasTVPreferredFocus?: boolean readonly nextFocusDown?: number readonly nextFocusForward?: number readonly nextFocusLeft?: number @@ -5398,7 +5389,6 @@ declare namespace TurboModuleRegistry { export { get_2 as get, getEnforcing } } declare type TVViewPropsIOS = { - readonly hasTVPreferredFocus?: boolean readonly isTVSelectable?: boolean readonly tvParallaxMagnification?: number readonly tvParallaxShiftDistanceX?: number @@ -5578,7 +5568,6 @@ declare interface ViewProps extends Readonly< > {} declare type ViewPropsAndroid = { readonly focusable?: boolean - readonly hasTVPreferredFocus?: boolean readonly nativeBackgroundAndroid?: AndroidDrawable readonly nativeForegroundAndroid?: AndroidDrawable readonly nextFocusDown?: number @@ -5773,16 +5762,16 @@ export { AccessibilityValue, // cf8bcb74 ActionSheetIOS, // b558559e ActionSheetIOSOptions, // 1756eb5a - ActivityIndicator, // c26e203c + ActivityIndicator, // b8c4f05a ActivityIndicatorInstance, // 1b5e0dd5 - ActivityIndicatorProps, // 329be4ac + ActivityIndicatorProps, // ab46ec7e Alert, // a398a509 AlertButton, // bf1a3b60 AlertButtonStyle, // ec9fb242 AlertOptions, // 8a116d2a AlertType, // 5ab91217 AndroidKeyboardEvent, // e03becc8 - Animated, // 0f1a0259 + Animated, // 990adcb6 AppConfig, // 35c0ca70 AppRegistry, // edec2a30 AppState, // 12012be5 @@ -5796,9 +5785,9 @@ export { BackPressEventName, // 4620fb76 BlurEvent, // d5e68e96 BoxShadowValue, // b679703f - Button, // d206ac5f - ButtonInstance, // eb97aec0 - ButtonProps, // 563c2a2f + Button, // 35d2ff2d + ButtonInstance, // 8d4861a8 + ButtonProps, // 5f462ce0 Clipboard, // 41addb89 CodegenTypes, // 9067fd06 ColorSchemeName, // 6615edd6 @@ -5816,9 +5805,9 @@ export { DimensionsPayload, // 653bc26c DisplayMetrics, // 1dc35cef DisplayMetricsAndroid, // 872e62eb - DrawerLayoutAndroid, // cd0272d1 + DrawerLayoutAndroid, // 9385b054 DrawerLayoutAndroidInstance, // aa243cbf - DrawerLayoutAndroidProps, // 491e918a + DrawerLayoutAndroidProps, // a4ddbda9 DrawerSlideEvent, // 38213685 DropShadowValue, // e9df2606 DynamicColorIOS, // d96c228c @@ -5834,9 +5823,9 @@ export { EventSubscription, // b8d084aa ExtendedExceptionData, // 5a6ccf5a FilterFunction, // bf24c0e3 - FlatList, // 0310fdb6 - FlatListInstance, // e0fdaa52 - FlatListProps, // dc08b4b1 + FlatList, // 76dfb3dc + FlatListInstance, // 1d6b2ce4 + FlatListProps, // 14bbe483 FocusEvent, // f2e4363d FontVariant, // 7c7558bb GestureResponderEvent, // 5cd2a663 @@ -5847,17 +5836,17 @@ export { IEventEmitter, // fbef6131 IOSKeyboardEvent, // e67bfe3a IgnorePattern, // ec6f6ece - Image, // a086a246 - ImageBackground, // 627f52e5 - ImageBackgroundInstance, // 867f518d - ImageBackgroundProps, // d787f734 + Image, // 048b0a2a + ImageBackground, // 3d3dc917 + ImageBackgroundInstance, // 400a5719 + ImageBackgroundProps, // 43ae7a8a ImageErrorEvent, // b6227714 ImageInstance, // df709524 ImageLoadEvent, // 31709c38 ImageProgressEventIOS, // 9243d460 - ImageProps, // c3de80fb + ImageProps, // 1fcb686b ImagePropsAndroid, // ee00e1d5 - ImagePropsBase, // 32741b7f + ImagePropsBase, // c744a0da ImagePropsIOS, // 1998f91a ImageRequireSource, // 681d683b ImageResizeMode, // d51106e2 @@ -5875,9 +5864,9 @@ export { KeyEvent, // 20fa4267 KeyUpEvent, // 0b5d0144 Keyboard, // 49414c97 - KeyboardAvoidingView, // 1744521b - KeyboardAvoidingViewInstance, // 15c3d21e - KeyboardAvoidingViewProps, // cda19922 + KeyboardAvoidingView, // 9dab9980 + KeyboardAvoidingViewInstance, // 2772afb3 + KeyboardAvoidingViewProps, // 84e4ee76 KeyboardEvent, // c3f895d4 KeyboardEventEasing, // af4091c8 KeyboardEventName, // 59299ad6 @@ -5902,10 +5891,10 @@ export { MeasureInWindowOnSuccessCallback, // a285f598 MeasureLayoutOnSuccessCallback, // 3592502a MeasureOnSuccessCallback, // 82824e59 - Modal, // ee56dff1 + Modal, // 62f03222 ModalBaseProps, // a6e4334f ModalInstance, // 0f04c1bf - ModalProps, // 3e80b2d1 + ModalProps, // b9129837 ModalPropsAndroid, // 515fb173 ModalPropsIOS, // a65a8f5c ModeChangeEvent, // ccf30dc4 @@ -5941,15 +5930,15 @@ export { PointerEvent, // a506d9d7 PressabilityConfig, // 0fd655fe PressabilityEventHandlers, // be359ba3 - Pressable, // f5c95a14 + Pressable, // c52c0096 PressableAndroidRippleConfig, // ee32eaca PressableInstance, // ed26f040 - PressableProps, // 063d8c2f + PressableProps, // 97cdaaa1 PressableStateCallbackType, // f83728cd ProcessedColorValue, // 33f74304 - ProgressBarAndroid, // c807c0a6 + ProgressBarAndroid, // a2626c30 ProgressBarAndroidInstance, // f17242be - ProgressBarAndroidProps, // 02bc1abf + ProgressBarAndroidProps, // 7205b2a5 PublicRootInstance, // 8040afd7 PublicTextInstance, // f9adf69a PushNotificationEventName, // 84e7e150 @@ -5957,9 +5946,9 @@ export { PushNotificationPermissions, // c2e7ae4f Rationale, // 5df1b1c1 ReactNativeVersion, // abd76827 - RefreshControl, // 8fe2a42d - RefreshControlInstance, // 8aa4a6b9 - RefreshControlProps, // 8aed873e + RefreshControl, // db24bb7e + RefreshControlInstance, // d076b876 + RefreshControlProps, // f95b4cd0 RefreshControlPropsAndroid, // 8ac931ca RefreshControlPropsIOS, // 72a36381 Registry, // 6c39216d @@ -5971,24 +5960,24 @@ export { RootViewStyleProvider, // d5909148 Runnable, // 594dd93a Runnables, // 4367c557 - SafeAreaView, // 25729076 + SafeAreaView, // d917b6ec SafeAreaViewInstance, // 2b5d4391 ScaledSize, // 07e417c7 ScrollEvent, // 956fdb27 - ScrollResponderType, // 9125e854 + ScrollResponderType, // e41ccb2a ScrollToLocationParamsType, // d7ecdad1 - ScrollView, // 0b86db09 - ScrollViewImperativeMethods, // cd84ceba - ScrollViewInstance, // 9ef84dc0 - ScrollViewProps, // b1e4c530 + ScrollView, // 651915c2 + ScrollViewImperativeMethods, // cb73da62 + ScrollViewInstance, // 099b48e2 + ScrollViewProps, // 7e38d97b ScrollViewPropsAndroid, // 02f3df2e ScrollViewPropsIOS, // c378379b ScrollViewScrollToOptions, // 3313411e SectionBase, // 9f13db00 - SectionList, // f5d7910c + SectionList, // 542a3017 SectionListData, // 1a4de01a - SectionListInstance, // 6be3310d - SectionListProps, // d9205401 + SectionListInstance, // ea2f03e4 + SectionListProps, // d6282d2b SectionListRenderItem, // 715b2086 SectionListRenderItemInfo, // 4a48a922 Separators, // 6a45f7e3 @@ -6007,17 +5996,17 @@ export { StyleProp, // fa0e9b4a StyleSheet, // 8bb13f55 SubmitBehavior, // c4ddf490 - Switch, // 1f9fd5fe + Switch, // 408983ac SwitchChangeEvent, // 3b472666 SwitchInstance, // 73dce99f - SwitchProps, // 0cf0ca94 + SwitchProps, // fc2b9dfe Systrace, // 626d178c - TVViewPropsIOS, // 330ce7b5 + TVViewPropsIOS, // 1c612e4e TargetedEvent, // 16e98910 TaskProvider, // 266dedf2 Text, // 39a4d091 TextContentType, // 239b3ecc - TextInput, // c5051f93 + TextInput, // 9981d7ab TextInputAndroidProps, // 9ebbc103 TextInputBlurEvent, // b4c7a58c TextInputChangeEvent, // 92363e10 @@ -6027,7 +6016,7 @@ export { TextInputIOSProps, // fb3c9327 TextInputInstance, // 53fe7b73 TextInputKeyPressEvent, // cbbc322a - TextInputProps, // 98ed4f48 + TextInputProps, // 253dd17d TextInputSelectionChangeEvent, // 4a8f10c2 TextInputSubmitEditingEvent, // e811fdbd TextInstance, // 7c7e2069 @@ -6035,15 +6024,15 @@ export { TextProps, // e4fdaaad TextStyle, // 898adfd1 ToastAndroid, // 88a8969a - TouchableHighlight, // dfe22b5e + TouchableHighlight, // c5f5b1c2 TouchableHighlightInstance, // 811af7ca - TouchableHighlightProps, // 5f4cfc79 - TouchableNativeFeedback, // 5f193fd5 - TouchableNativeFeedbackInstance, // 373fa09b - TouchableNativeFeedbackProps, // 0b5f505c - TouchableOpacity, // 23a4c4d8 + TouchableHighlightProps, // c35edf1d + TouchableNativeFeedback, // bd8a9aa5 + TouchableNativeFeedbackInstance, // 7010d8d4 + TouchableNativeFeedbackProps, // 827f5e03 + TouchableOpacity, // db1102e5 TouchableOpacityInstance, // 0cd8a347 - TouchableOpacityProps, // 80e07098 + TouchableOpacityProps, // 1bc8fbaa TouchableWithoutFeedback, // a397bd6c TouchableWithoutFeedbackProps, // 9dfdc3eb TransformsStyle, // 65e70f18 @@ -6052,10 +6041,10 @@ export { UIManager, // 6a18fc05 UTFSequence, // ad625158 Vibration, // 31e4bbf8 - View, // f2cbdff6 + View, // fe623c3d ViewInstance, // 0283d2fc - ViewProps, // 42f4a247 - ViewPropsAndroid, // 46410bb6 + ViewProps, // 7fb992e4 + ViewPropsAndroid, // 66d760c6 ViewPropsIOS, // 58ee19bf ViewStyle, // 4e2746d6 ViewabilityConfig, // eb3f7ed8 @@ -6063,10 +6052,10 @@ export { VirtualViewMode, // 6be59722 VirtualizedList, // 68c7345e VirtualizedListInstance, // 423ee7c0 - VirtualizedListProps, // 2adf5953 + VirtualizedListProps, // 7a7c618a VirtualizedSectionList, // 9fd9cd61 VirtualizedSectionListInstance, // 12b706d5 - VirtualizedSectionListProps, // 6fa4cb18 + VirtualizedSectionListProps, // 8373f27c WrapperComponentProvider, // 9b4247f6 codegenNativeCommands, // 322f3f4e codegenNativeComponent, // e8334853 diff --git a/packages/react-native/types_DEPRECATED/Libraries/Components/Button.d.ts b/packages/react-native/types_DEPRECATED/Libraries/Components/Button.d.ts index a76b883a2d64..f9bbd6275c68 100644 --- a/packages/react-native/types_DEPRECATED/Libraries/Components/Button.d.ts +++ b/packages/react-native/types_DEPRECATED/Libraries/Components/Button.d.ts @@ -16,7 +16,6 @@ export interface ButtonProps extends Pick< TouchableNativeFeedbackProps & TouchableOpacityProps, | 'accessibilityLabel' | 'accessibilityState' - | 'hasTVPreferredFocus' | 'nextFocusDown' | 'nextFocusForward' | 'nextFocusLeft' diff --git a/packages/react-native/types_DEPRECATED/Libraries/Components/Touchable/TouchableOpacity.d.ts b/packages/react-native/types_DEPRECATED/Libraries/Components/Touchable/TouchableOpacity.d.ts index 0436416e6ed7..35f4bda529d7 100644 --- a/packages/react-native/types_DEPRECATED/Libraries/Components/Touchable/TouchableOpacity.d.ts +++ b/packages/react-native/types_DEPRECATED/Libraries/Components/Touchable/TouchableOpacity.d.ts @@ -12,14 +12,6 @@ import {View} from '../../Components/View/View'; import {TouchableWithoutFeedbackProps} from './TouchableWithoutFeedback'; export interface TVProps { - /** - * *(Apple TV only)* TV preferred focus (see documentation for the View component). - * - * @platform ios - * @deprecated Use `focusable` instead - */ - hasTVPreferredFocus?: boolean | undefined; - /** * Designates the next view to receive focus when the user navigates down. See the Android documentation. * diff --git a/packages/react-native/types_DEPRECATED/Libraries/Components/View/ViewPropTypes.d.ts b/packages/react-native/types_DEPRECATED/Libraries/Components/View/ViewPropTypes.d.ts index 36221d845bf4..eb9ef54e7856 100644 --- a/packages/react-native/types_DEPRECATED/Libraries/Components/View/ViewPropTypes.d.ts +++ b/packages/react-native/types_DEPRECATED/Libraries/Components/View/ViewPropTypes.d.ts @@ -33,14 +33,6 @@ export interface TVViewPropsIOS { */ isTVSelectable?: boolean | undefined; - /** - * *(Apple TV only)* May be set to true to force the Apple TV focus engine to move focus to this view. - * - * @platform ios - * @deprecated Use `focusable` instead - */ - hasTVPreferredFocus?: boolean | undefined; - /** * *(Apple TV only)* May be used to change the appearance of the Apple TV parallax effect when this view goes in or out of focus. Defaults to 2.0. * diff --git a/packages/rn-tester/js/examples/FlatList/BaseFlatListExample.js b/packages/rn-tester/js/examples/FlatList/BaseFlatListExample.js index 1c77581facfd..ff6b3fb27798 100644 --- a/packages/rn-tester/js/examples/FlatList/BaseFlatListExample.js +++ b/packages/rn-tester/js/examples/FlatList/BaseFlatListExample.js @@ -60,6 +60,7 @@ const Item = ({item, separators}: ListRenderItemInfo) => { }; type Props = Readonly<{ + data?: ReadonlyArray, exampleProps: Partial>, exampleTestID?: ?string, onTest?: ?() => void, @@ -95,7 +96,7 @@ const BaseFlatListExample: component( ref={ref} testID="flat_list" // $FlowFixMe[incompatible-type] - data={DATA} + data={props.data ?? DATA} keyExtractor={(item, index) => item + index} style={styles.list} // $FlowFixMe[incompatible-type] diff --git a/packages/rn-tester/js/examples/FlatList/FlatList-onEndReached.js b/packages/rn-tester/js/examples/FlatList/FlatList-onEndReached.js index 132778d07b87..2a60d653160f 100644 --- a/packages/rn-tester/js/examples/FlatList/FlatList-onEndReached.js +++ b/packages/rn-tester/js/examples/FlatList/FlatList-onEndReached.js @@ -12,33 +12,129 @@ import type {RNTesterModuleExample} from '../../types/RNTesterTypes'; -import BaseFlatListExample from './BaseFlatListExample'; +import BaseFlatListExample, {ITEM_HEIGHT} from './BaseFlatListExample'; import * as React from 'react'; import {useRef, useState} from 'react'; +import {Button, FlatList} from 'react-native'; + +const DATA = Array.from({length: 20}, (_, index) => `Item ${index}`); +const SCROLL_TO_ITEM = DATA[18]; + +type EventCounts = { + dragEvents: number, + onEndReached: number, + onMomentumScrollEnd: number, + onStartReached: number, +}; export component FlatList_onEndReached() { - const [output, setOutput] = useState(''); - const exampleProps = { - onEndReached: (info: {distanceFromEnd: number, ...}) => - setOutput('onEndReached'), - onEndReachedThreshold: 0, + const [output, setOutput] = useState('ready'); + const listRef = useRef>(null); + const actionRef = useRef<'end' | 'start'>('end'); + const attemptsRef = useRef(0); + const eventCountsRef = useRef({ + dragEvents: 0, + onEndReached: 0, + onMomentumScrollEnd: 0, + onStartReached: 0, + }); + const recordEventsRef = useRef(false); + const momentumEndedRef = useRef(false); + + const report = () => { + const {dragEvents, onEndReached, onMomentumScrollEnd, onStartReached} = + eventCountsRef.current; + setOutput( + `${actionRef.current}: attempts=${attemptsRef.current}, ` + + `onEndReached=${onEndReached}, onStartReached=${onStartReached}, ` + + `onMomentumScrollEnd=${onMomentumScrollEnd}, dragEvents=${dragEvents}`, + ); + }; + + const onEndReached = () => { + if (recordEventsRef.current) { + eventCountsRef.current.onEndReached++; + if (momentumEndedRef.current) { + report(); + } + } + }; + + const onStartReached = () => { + if (recordEventsRef.current) { + eventCountsRef.current.onStartReached++; + if (momentumEndedRef.current) { + report(); + } + } }; - const ref = useRef(null); - const onTest = () => { - const scrollResponder = ref?.current?.getScrollResponder(); - if (scrollResponder != null) { - scrollResponder.scrollToEnd(); + const onMomentumScrollEnd = () => { + if (recordEventsRef.current) { + eventCountsRef.current.onMomentumScrollEnd++; + momentumEndedRef.current = true; + report(); } }; + const onDragEvent = () => { + if (recordEventsRef.current) { + eventCountsRef.current.dragEvents++; + } + }; + + const scrollToEnd = () => { + recordEventsRef.current = true; + momentumEndedRef.current = false; + actionRef.current = 'end'; + attemptsRef.current++; + setOutput('running'); + listRef.current?.scrollToItem({ + animated: true, + item: SCROLL_TO_ITEM, + viewOffset: -ITEM_HEIGHT, + }); + }; + + const scrollToStart = () => { + momentumEndedRef.current = false; + actionRef.current = 'start'; + attemptsRef.current++; + setOutput('running'); + listRef.current?.scrollToOffset({animated: true, offset: 0}); + }; + + const exampleProps = { + initialNumToRender: 19, + onEndReached, + onEndReachedThreshold: 0.2, + onMomentumScrollEnd, + onScrollBeginDrag: onDragEvent, + onScrollEndDrag: onDragEvent, + onStartReached, + onStartReachedThreshold: 0.1, + windowSize: 2, + }; + return ( + onTest={scrollToEnd} + testLabel="Scroll to item"> +