diff --git a/packages/react-native/Libraries/Components/TextInput/InputAccessoryView.js b/packages/react-native/Libraries/Components/TextInput/InputAccessoryView.js
index 5ded8e707aed..c9e3f4c0b97c 100644
--- a/packages/react-native/Libraries/Components/TextInput/InputAccessoryView.js
+++ b/packages/react-native/Libraries/Components/TextInput/InputAccessoryView.js
@@ -8,7 +8,7 @@
* @format
*/
-import SafeAreaView from '../../Components/SafeAreaView/SafeAreaView';
+import SafeAreaView from '../../../src/private/components/safeareaview/SafeAreaView_INTERNAL_DO_NOT_USE';
import StyleSheet, {
type ColorValue,
type ViewStyleProp,
diff --git a/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorFooterButton.js b/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorFooterButton.js
index 3db512ed3d43..3a3d5da97792 100644
--- a/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorFooterButton.js
+++ b/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorFooterButton.js
@@ -8,7 +8,7 @@
* @format
*/
-import SafeAreaView from '../../Components/SafeAreaView/SafeAreaView';
+import SafeAreaView from '../../../src/private/components/safeareaview/SafeAreaView_INTERNAL_DO_NOT_USE';
import View from '../../Components/View/View';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Text from '../../Text/Text';
diff --git a/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorHeader.js b/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorHeader.js
index a5b5329d440e..8657f427f681 100644
--- a/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorHeader.js
+++ b/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorHeader.js
@@ -11,7 +11,7 @@
import type {ViewProps} from '../../Components/View/ViewPropTypes';
import type {LogLevel} from '../Data/LogBoxLog';
-import SafeAreaView from '../../Components/SafeAreaView/SafeAreaView';
+import SafeAreaView from '../../../src/private/components/safeareaview/SafeAreaView_INTERNAL_DO_NOT_USE';
import View from '../../Components/View/View';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Text from '../../Text/Text';
diff --git a/packages/react-native/Libraries/LogBox/__tests__/__snapshots__/LogBoxNotificationContainer-test.js.snap b/packages/react-native/Libraries/LogBox/__tests__/__snapshots__/LogBoxNotificationContainer-test.js.snap
index 6799302e9474..7c65b0a79669 100644
--- a/packages/react-native/Libraries/LogBox/__tests__/__snapshots__/LogBoxNotificationContainer-test.js.snap
+++ b/packages/react-native/Libraries/LogBox/__tests__/__snapshots__/LogBoxNotificationContainer-test.js.snap
@@ -1,16 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LogBoxNotificationContainer should render both an error and warning notification 1`] = `
-
-
+
`;
exports[`LogBoxNotificationContainer should render null with no logs 1`] = `null`;
@@ -119,16 +123,20 @@ exports[`LogBoxNotificationContainer should render selected fatal error even whe
exports[`LogBoxNotificationContainer should render selected syntax error even when disabled 1`] = `null`;
exports[`LogBoxNotificationContainer should render the latest error notification 1`] = `
-
-
+
`;
exports[`LogBoxNotificationContainer should render the latest warning notification 1`] = `
-
-
+
`;
diff --git a/packages/react-native/src/private/components/safeareaview/SafeAreaView_INTERNAL_DO_NOT_USE.js b/packages/react-native/src/private/components/safeareaview/SafeAreaView_INTERNAL_DO_NOT_USE.js
index e6b5cdd5f522..f42bbbae52f0 100644
--- a/packages/react-native/src/private/components/safeareaview/SafeAreaView_INTERNAL_DO_NOT_USE.js
+++ b/packages/react-native/src/private/components/safeareaview/SafeAreaView_INTERNAL_DO_NOT_USE.js
@@ -9,23 +9,66 @@
*/
import type {ViewProps} from '../../../../Libraries/Components/View/ViewPropTypes';
+import type {
+ SafeAreaInsets,
+ SafeAreaInsetsChangeEvent,
+} from '../../../../Libraries/Types/CoreEventTypes';
+import type {HostInstance} from '../../types/HostInstance';
import View from '../../../../Libraries/Components/View/View';
-import UIManager from '../../../../Libraries/ReactNative/UIManager';
-import Platform from '../../../../Libraries/Utilities/Platform';
+import I18nManager from '../../../../Libraries/ReactNative/I18nManager';
import * as React from 'react';
+import {useCallback, useMemo, useState} from 'react';
-const exported: component(
- ref?: React.RefSetter>,
- ...ViewProps
-) = Platform.select({
- ios: require('../../../../src/private/components/safeareaview/specs/RCTSafeAreaViewNativeComponent')
- .default,
- android: UIManager.hasViewManagerConfig('RCTSafeAreaView')
- ? require('../../../../src/private/components/safeareaview/specs/RCTSafeAreaViewNativeComponent')
- .default
- : View,
- default: View,
-});
+/**
+ * Renders its children within the safe area of the device, by applying the part
+ * of the view that is covered by the system UI as padding.
+ *
+ * This is the internal counterpart of `react-native-safe-area-context`, for the
+ * few surfaces React Native renders itself (LogBox, the element inspector, ...)
+ * which cannot take a dependency on it. Everything else should use the library.
+ */
+component SafeAreaView(
+ ref?: React.RefSetter,
+ ...props: ViewProps
+) {
+ const {style, experimental_onSafeAreaInsetsChange, ...otherProps} = props;
+ const [insets, setInsets] = useState(null);
+
+ const handleSafeAreaInsetsChange = useCallback(
+ (event: SafeAreaInsetsChangeEvent) => {
+ setInsets(event.nativeEvent.insets);
+ experimental_onSafeAreaInsetsChange?.(event);
+ },
+ [experimental_onSafeAreaInsetsChange],
+ );
+
+ const paddingStyle = useMemo(() => {
+ if (insets == null) {
+ return null;
+ }
+ // Insets are physical edges, but Yoga remaps paddingLeft/paddingRight to
+ // start/end when I18nManager's swapLeftAndRightInRTL is on, which would
+ // pad the mirror-image edge in RTL. Swap the values so the physical edge
+ // keeps its inset.
+ const {isRTL, doLeftAndRightSwapInRTL} = I18nManager.getConstants();
+ const swap = isRTL && doLeftAndRightSwapInRTL;
+ return {
+ paddingTop: insets.top,
+ paddingRight: swap ? insets.left : insets.right,
+ paddingBottom: insets.bottom,
+ paddingLeft: swap ? insets.right : insets.left,
+ };
+ }, [insets]);
+
+ return (
+
+ );
+}
-export default exported;
+export default SafeAreaView;
diff --git a/packages/react-native/src/private/devsupport/devmenu/elementinspector/InspectorPanel.js b/packages/react-native/src/private/devsupport/devmenu/elementinspector/InspectorPanel.js
index 9e5d04f30038..b4195f431486 100644
--- a/packages/react-native/src/private/devsupport/devmenu/elementinspector/InspectorPanel.js
+++ b/packages/react-native/src/private/devsupport/devmenu/elementinspector/InspectorPanel.js
@@ -12,7 +12,7 @@
import type {ElementsHierarchy, InspectedElement} from './Inspector';
-import SafeAreaView from '../../../../../Libraries/Components/SafeAreaView/SafeAreaView';
+import SafeAreaView from '../../../components/safeareaview/SafeAreaView_INTERNAL_DO_NOT_USE';
import * as React from 'react';
const ScrollView =