UNPKG

@fullstackhouse/react-native-nested-safe-area

Version:

A wrapper on top of react-native-safe-area-context that allows nested safe area contexts

275 lines (210 loc) 8.13 kB
# react-native-nested-safe-area A wrapper on top of react-native-safe-area-context that allows nested safe area contexts with automatic inset consumption tracking. ## Features - **Nested Context Support**: Stack multiple safe area providers without overlapping insets - **Automatic Consumption**: Automatically tracks and subtracts consumed insets in nested contexts - **React Integration**: Built-in React Context and hooks - **Cross-Platform**: Works on iOS, Android, and Web - **TypeScript Support**: Fully typed with TypeScript - **Edge Control**: Selectively apply safe area insets to specific edges ## Installation ```sh npm install react-native-nested-safe-area # or yarn add react-native-nested-safe-area ``` ### Dependencies This library depends on `react-native-safe-area-context`. If you don't have it installed: ```sh npm install react-native-safe-area-context # or yarn add react-native-safe-area-context ``` Follow the [react-native-safe-area-context installation guide](https://github.com/th3rdwave/react-native-safe-area-context#getting-started) for platform-specific setup. ## Usage ### Basic Usage with NestedSafeAreaView ```jsx import React from 'react'; import { View, Text } from 'react-native'; import { NestedSafeAreaView } from 'react-native-nested-safe-area'; export default function App() { return ( <NestedSafeAreaView style={{ flex: 1, backgroundColor: 'white' }}> <NestedSafeAreaView edges={['top', 'left', 'right']} style={{ flex: 1, backgroundColor: 'lightblue' }} > <Text>First safe area - has padding for top, left, right edge</Text> <NestedSafeAreaView edges={['bottom']} style={{ backgroundColor: 'blue', marginTop: 'auto' }} > <Text>Nested safe area - has padding for bottom edge</Text> </NestedSafeAreaView> </NestedSafeAreaView> </NestedSafeAreaView> ); } ``` ### Using with Provider and Hook ```jsx import React from 'react'; import { View, Text } from 'react-native'; import { NestedSafeAreaProvider, useNestedSafeAreaInsets, } from 'react-native-nested-safe-area'; function MyComponent() { const insets = useNestedSafeAreaInsets(); return ( <View style={{ paddingTop: insets.top }}> <NestedSafeAreaProvider consumedInsets={{ top: insets.top }}> <Text>Content with consumed top inset</Text> </NestedSafeAreaProvider> </View> ); } export default function App() { return ( <NestedSafeAreaProvider> <MyComponent /> </NestedSafeAreaProvider> ); } ``` ### Using consumedEdges for Complete Edge Consumption The `consumedEdges` prop provides a convenient way to completely consume specific edges, setting them to zero in nested contexts: ```jsx import React from 'react'; import { View, Text } from 'react-native'; import { NestedSafeAreaProvider } from 'react-native-nested-safe-area'; export default function App() { return ( <NestedSafeAreaProvider> {/* Header consumes top edge completely */} <View style={{ backgroundColor: 'blue', padding: 20 }}> <Text>Header</Text> </View> {/* Main content - top edge is now zero for nested components */} <NestedSafeAreaProvider consumedEdges={['top']}> <View style={{ flex: 1 }}> <Text>Main content (top safe area consumed)</Text> {/* Footer consumes bottom edge */} <NestedSafeAreaProvider consumedEdges={['bottom']}> <View style={{ backgroundColor: 'green', marginTop: 'auto' }}> <Text>Footer (bottom safe area consumed)</Text> </View> </NestedSafeAreaProvider> </View> </NestedSafeAreaProvider> </NestedSafeAreaProvider> ); } ``` ### Using resetEdges to Restore Safe Areas The `resetEdges` prop allows you to reset specific edges back to the original safe area values, useful when you need to restore safe areas in deeply nested contexts: ```jsx import React from 'react'; import { View, Text } from 'react-native'; import { NestedSafeAreaProvider } from 'react-native-nested-safe-area'; export default function App() { return ( <NestedSafeAreaProvider> {/* First level consumes top and bottom edges */} <NestedSafeAreaProvider consumedEdges={['top', 'bottom']}> <View style={{ flex: 1 }}> <Text>No top or bottom safe areas here</Text> {/* Modal/overlay that needs original top safe area restored */} <NestedSafeAreaProvider resetEdges={['top']}> <View style={{ position: 'absolute', top: 0, left: 0, right: 0 }}> <Text>Modal with restored top safe area</Text> </View> </NestedSafeAreaProvider> </View> </NestedSafeAreaProvider> </NestedSafeAreaProvider> ); } ``` ### Edge-Specific Safe Areas ```jsx import React from 'react'; import { View, Text } from 'react-native'; import { NestedSafeAreaView } from 'react-native-nested-safe-area'; export default function App() { return ( <View style={{ flex: 1 }}> {/* Header with only top safe area */} <NestedSafeAreaView edges={['top']} style={{ backgroundColor: 'blue' }}> <Text>Header</Text> </NestedSafeAreaView> {/* Content area with left/right safe areas */} <NestedSafeAreaView edges={['left', 'right']} style={{ flex: 1 }}> <Text>Main content</Text> </NestedSafeAreaView> {/* Footer with only bottom safe area */} <NestedSafeAreaView edges={['bottom']} style={{ backgroundColor: 'green' }} > <Text>Footer</Text> </NestedSafeAreaView> </View> ); } ``` ## API Reference ### NestedSafeAreaView A View component that applies safe area insets as padding and automatically provides consumed insets to nested contexts. ```typescript <NestedSafeAreaView edges?: Array<'top' | 'right' | 'bottom' | 'left'> /> ``` Props: - `edges?: Array<'top' | 'right' | 'bottom' | 'left'>` - Which edges to apply safe area to (default: all edges) - Inherits all React Native `View` props ### NestedSafeAreaProvider Provides nested safe area context with automatic inset consumption tracking. ```typescript <NestedSafeAreaProvider consumedInsets?: Partial<EdgeInsets> consumedEdges?: Edge[] resetEdges?: Edge[] > {children} </NestedSafeAreaProvider> ``` Props: - `consumedInsets?: Partial<EdgeInsets>` - Insets to subtract from parent context - `consumedEdges?: Edge[]` - List of edges to completely consume (set to zero). Takes precedence over `consumedInsets` when provided - `resetEdges?: Edge[]` - List of edges to reset to the original safe area values. Takes precedence over both `consumedInsets` and `consumedEdges` - `children: ReactNode` - Child components #### Edge Type ```typescript type Edge = 'top' | 'right' | 'bottom' | 'left'; ``` ### useNestedSafeAreaInsets() Hook to access current safe area insets in nested context. ```typescript const insets = useNestedSafeAreaInsets(); ``` Returns: - `insets: EdgeInsets` - Current safe area insets (`{ top, right, bottom, left }`) ### useNestedSafeAreaContext() Hook to access the full nested safe area context. ```typescript const { insets, consumeInsets } = useNestedSafeAreaContext(); ``` Returns: - `insets: EdgeInsets` - Current safe area insets - `consumeInsets: (consumed: Partial<EdgeInsets>) => EdgeInsets` - Function to calculate consumed insets ## How It Works 1. **Base Context**: The root `NestedSafeAreaProvider` gets insets from `react-native-safe-area-context` 2. **Consumption Tracking**: Each nested provider subtracts consumed insets from its parent context 3. **Automatic Management**: `NestedSafeAreaView` automatically applies insets as padding and marks them as consumed 4. **Edge Control**: Use the `edges` prop to selectively apply insets to specific sides ## Platform Support - ✅ **iOS**: Full support with react-native-safe-area-context - ✅ **Android**: Full support with react-native-safe-area-context - ✅ **Web**: Full support with react-native-safe-area-context ## License MIT