diff --git a/docs/docs/api/safe-area-provider.mdx b/docs/docs/api/safe-area-provider.mdx index a617084b..485fe733 100644 --- a/docs/docs/api/safe-area-provider.mdx +++ b/docs/docs/api/safe-area-provider.mdx @@ -27,3 +27,7 @@ Accepts all [View](https://reactnative.dev/docs/view) props. Has a default style Optional, defaults to `null`. Can be used to provide the initial value for frame and insets, this allows rendering immediately. See [optimization](/optimizations) for more information on how to use this prop. + +#### `ref` + +Optional ref to the underlying view. diff --git a/src/CompatNativeSafeAreaProvider.tsx b/src/CompatNativeSafeAreaProvider.tsx index 114ad8d1..9615371e 100644 --- a/src/CompatNativeSafeAreaProvider.tsx +++ b/src/CompatNativeSafeAreaProvider.tsx @@ -6,6 +6,7 @@ export function CompatNativeSafeAreaProvider({ children, style, onInsetsChange, + ref, }: NativeSafeAreaProviderProps) { const window = useWindowDimensions(); React.useEffect(() => { @@ -24,5 +25,9 @@ export function CompatNativeSafeAreaProvider({ // @ts-ignore: missing properties onInsetsChange({ nativeEvent: { insets, frame } }); }, [onInsetsChange, window.height, window.width]); - return {children}; + return ( + + {children} + + ); } diff --git a/src/NativeSafeAreaProvider.web.tsx b/src/NativeSafeAreaProvider.web.tsx index 82828693..5bcdf5cd 100644 --- a/src/NativeSafeAreaProvider.web.tsx +++ b/src/NativeSafeAreaProvider.web.tsx @@ -16,9 +16,23 @@ export function NativeSafeAreaProvider({ children, style, onInsetsChange, + ref, }: NativeSafeAreaProviderProps) { const viewRef = React.useRef(null); + const setRef = React.useCallback( + (view: View | null) => { + viewRef.current = view; + + if (typeof ref === 'function') { + return ref(view); + } else if (ref != null) { + ref.current = view; + } + }, + [ref], + ); + React.useEffect(() => { // Skip for SSR. if (typeof document === 'undefined') { @@ -108,7 +122,7 @@ export function NativeSafeAreaProvider({ }, [onInsetsChange]); return ( - + {children} ); diff --git a/src/SafeArea.types.ts b/src/SafeArea.types.ts index d3d23b62..5672e5d6 100644 --- a/src/SafeArea.types.ts +++ b/src/SafeArea.types.ts @@ -1,5 +1,5 @@ import type * as React from 'react'; -import type { NativeSyntheticEvent, ViewProps } from 'react-native'; +import type { NativeSyntheticEvent, View, ViewProps } from 'react-native'; import NativeSafeAreaView from './specs/NativeSafeAreaView'; export type Edge = 'top' | 'right' | 'bottom' | 'left'; @@ -32,6 +32,7 @@ export type InsetChangedEvent = NativeSyntheticEvent; export type InsetChangeNativeCallback = (event: InsetChangedEvent) => void; export interface NativeSafeAreaProviderProps extends ViewProps { + ref?: React.Ref; children?: React.ReactNode; onInsetsChange: InsetChangeNativeCallback; } diff --git a/src/SafeAreaContext.tsx b/src/SafeAreaContext.tsx index ed192d76..72f2c0b3 100644 --- a/src/SafeAreaContext.tsx +++ b/src/SafeAreaContext.tsx @@ -1,5 +1,10 @@ import * as React from 'react'; -import { Dimensions, StyleSheet, type ViewProps } from 'react-native'; +import { + Dimensions, + StyleSheet, + type View, + type ViewProps, +} from 'react-native'; import { NativeSafeAreaProvider } from './NativeSafeAreaProvider'; import type { EdgeInsets, @@ -23,6 +28,7 @@ if (isDev) { } export interface SafeAreaProviderProps extends ViewProps { + ref?: React.Ref; children?: React.ReactNode; initialMetrics?: Metrics | null; /** @@ -36,6 +42,7 @@ export function SafeAreaProvider({ initialMetrics, initialSafeAreaInsets, style, + ref, ...others }: SafeAreaProviderProps) { const parentInsets = useParentSafeAreaInsets(); @@ -90,6 +97,7 @@ export function SafeAreaProvider({ return (