1import * as React from 'react'; 2import { View, StyleSheet } from 'react-native'; 3import { useSafeAreaInsets } from './SafeAreaContext'; 4import { Edge, NativeSafeAreaViewProps } from './SafeArea.types'; 5 6// prettier-ignore 7const TOP = 0b1000, 8 RIGHT = 0b0100, 9 BOTTOM = 0b0010, 10 LEFT = 0b0001, 11 ALL = 0b1111; 12 13/* eslint-disable no-bitwise */ 14 15const edgeBitmaskMap: Record<Edge, number> = { 16 top: TOP, 17 right: RIGHT, 18 bottom: BOTTOM, 19 left: LEFT, 20}; 21 22export function SafeAreaView({ 23 style = {}, 24 mode, 25 edges, 26 ...rest 27}: NativeSafeAreaViewProps) { 28 const insets = useSafeAreaInsets(); 29 30 const edgeBitmask = 31 edges != null 32 ? edges.reduce((accum, edge) => accum | edgeBitmaskMap[edge], 0) 33 : ALL; 34 35 const appliedStyle = React.useMemo(() => { 36 const insetTop = edgeBitmask & TOP ? insets.top : 0; 37 const insetRight = edgeBitmask & RIGHT ? insets.right : 0; 38 const insetBottom = edgeBitmask & BOTTOM ? insets.bottom : 0; 39 const insetLeft = edgeBitmask & LEFT ? insets.left : 0; 40 41 const flatStyle = StyleSheet.flatten(style) as Record<string, number>; 42 43 if (mode === 'margin') { 44 const { 45 margin = 0, 46 marginVertical = margin, 47 marginHorizontal = margin, 48 marginTop = marginVertical, 49 marginRight = marginHorizontal, 50 marginBottom = marginVertical, 51 marginLeft = marginHorizontal, 52 } = flatStyle; 53 54 const marginStyle = { 55 marginTop: marginTop + insetTop, 56 marginRight: marginRight + insetRight, 57 marginBottom: marginBottom + insetBottom, 58 marginLeft: marginLeft + insetLeft, 59 }; 60 61 return [style, marginStyle]; 62 } else { 63 const { 64 padding = 0, 65 paddingVertical = padding, 66 paddingHorizontal = padding, 67 paddingTop = paddingVertical, 68 paddingRight = paddingHorizontal, 69 paddingBottom = paddingVertical, 70 paddingLeft = paddingHorizontal, 71 } = flatStyle; 72 73 const paddingStyle = { 74 paddingTop: paddingTop + insetTop, 75 paddingRight: paddingRight + insetRight, 76 paddingBottom: paddingBottom + insetBottom, 77 paddingLeft: paddingLeft + insetLeft, 78 }; 79 80 return [style, paddingStyle]; 81 } 82 }, [style, insets, mode, edgeBitmask]); 83 84 return <View style={appliedStyle} {...rest} />; 85} 86