1
1
import * as React from 'react' ;
2
- import { View , StyleSheet } from 'react-native' ;
3
- import { useSafeAreaInsets } from './SafeAreaContext' ;
4
- import type {
2
+ import { StyleSheet , View } from 'react-native' ;
3
+ import {
5
4
Edge ,
5
+ EdgeMode ,
6
+ EdgeRecord ,
6
7
NativeSafeAreaViewInstance ,
7
8
NativeSafeAreaViewProps ,
8
9
} from './SafeArea.types' ;
10
+ import { useSafeAreaInsets } from './SafeAreaContext' ;
9
11
10
- // prettier-ignore
11
- const TOP = 0b1000 ,
12
- RIGHT = 0b0100 ,
13
- BOTTOM = 0b0010 ,
14
- LEFT = 0b0001 ,
15
- ALL = 0b1111 ;
16
-
17
- /* eslint-disable no-bitwise */
18
-
19
- const edgeBitmaskMap : Record < Edge , number > = {
20
- top : TOP ,
21
- right : RIGHT ,
22
- bottom : BOTTOM ,
23
- left : LEFT ,
12
+ const defaultEdges : Record < Edge , EdgeMode > = {
13
+ top : 'additive' ,
14
+ left : 'additive' ,
15
+ bottom : 'additive' ,
16
+ right : 'additive' ,
24
17
} ;
25
18
26
- export const SafeAreaView = React . forwardRef <
19
+ function getEdgeValue (
20
+ inset : number ,
21
+ current : number ,
22
+ mode : EdgeMode | undefined ,
23
+ ) {
24
+ switch ( mode ) {
25
+ case 'off' :
26
+ return current ;
27
+ case 'maximum' :
28
+ return Math . max ( current , inset ) ;
29
+ case 'additive' :
30
+ default :
31
+ return current + inset ;
32
+ }
33
+ }
34
+
35
+ export const JsSafeAreaView = React . forwardRef <
27
36
NativeSafeAreaViewInstance ,
28
37
NativeSafeAreaViewProps
29
38
> ( ( { style = { } , mode, edges, ...rest } , ref ) => {
30
39
const insets = useSafeAreaInsets ( ) ;
31
40
32
- const edgeBitmask =
33
- edges != null
34
- ? Array . isArray ( edges )
35
- ? edges . reduce (
36
- ( acc : number , edge : Edge ) => acc | edgeBitmaskMap [ edge ] ,
37
- 0 ,
38
- )
39
- : Object . keys ( edges ) . reduce (
40
- ( acc , edge ) => acc | edgeBitmaskMap [ edge as Edge ] ,
41
- 0 ,
42
- )
43
- : ALL ;
41
+ const edgesRecord = React . useMemo ( ( ) => {
42
+ if ( edges == null ) {
43
+ return defaultEdges ;
44
+ }
45
+
46
+ return Array . isArray ( edges )
47
+ ? edges . reduce < EdgeRecord > ( ( acc , edge : Edge ) => {
48
+ acc [ edge ] = 'additive' ;
49
+ return acc ;
50
+ } , { } )
51
+ : // ts has trouble with refining readonly arrays.
52
+ ( edges as EdgeRecord ) ;
53
+ } , [ edges ] ) ;
44
54
45
55
const appliedStyle = React . useMemo ( ( ) => {
46
- const insetTop = edgeBitmask & TOP ? insets . top : 0 ;
47
- const insetRight = edgeBitmask & RIGHT ? insets . right : 0 ;
48
- const insetBottom = edgeBitmask & BOTTOM ? insets . bottom : 0 ;
49
- const insetLeft = edgeBitmask & LEFT ? insets . left : 0 ;
50
-
51
56
const flatStyle = StyleSheet . flatten ( style ) as Record < string , number > ;
52
57
53
58
if ( mode === 'margin' ) {
@@ -62,10 +67,14 @@ export const SafeAreaView = React.forwardRef<
62
67
} = flatStyle ;
63
68
64
69
const marginStyle = {
65
- marginTop : marginTop + insetTop ,
66
- marginRight : marginRight + insetRight ,
67
- marginBottom : marginBottom + insetBottom ,
68
- marginLeft : marginLeft + insetLeft ,
70
+ marginTop : getEdgeValue ( insets . top , marginTop , edgesRecord . top ) ,
71
+ marginRight : getEdgeValue ( insets . right , marginRight , edgesRecord . right ) ,
72
+ marginBottom : getEdgeValue (
73
+ insets . bottom ,
74
+ marginBottom ,
75
+ edgesRecord . bottom ,
76
+ ) ,
77
+ marginLeft : getEdgeValue ( insets . left , marginLeft , edgesRecord . left ) ,
69
78
} ;
70
79
71
80
return [ style , marginStyle ] ;
@@ -81,15 +90,34 @@ export const SafeAreaView = React.forwardRef<
81
90
} = flatStyle ;
82
91
83
92
const paddingStyle = {
84
- paddingTop : paddingTop + insetTop ,
85
- paddingRight : paddingRight + insetRight ,
86
- paddingBottom : paddingBottom + insetBottom ,
87
- paddingLeft : paddingLeft + insetLeft ,
93
+ paddingTop : getEdgeValue ( insets . top , paddingTop , edgesRecord . top ) ,
94
+ paddingRight : getEdgeValue (
95
+ insets . right ,
96
+ paddingRight ,
97
+ edgesRecord . right ,
98
+ ) ,
99
+ paddingBottom : getEdgeValue (
100
+ insets . bottom ,
101
+ paddingBottom ,
102
+ edgesRecord . bottom ,
103
+ ) ,
104
+ paddingLeft : getEdgeValue ( insets . left , paddingLeft , edgesRecord . left ) ,
88
105
} ;
89
106
90
107
return [ style , paddingStyle ] ;
91
108
}
92
- } , [ style , insets , mode , edgeBitmask ] ) ;
109
+ } , [
110
+ edgesRecord . bottom ,
111
+ edgesRecord . left ,
112
+ edgesRecord . right ,
113
+ edgesRecord . top ,
114
+ insets . bottom ,
115
+ insets . left ,
116
+ insets . right ,
117
+ insets . top ,
118
+ mode ,
119
+ style ,
120
+ ] ) ;
93
121
94
122
return < View style = { appliedStyle } { ...rest } ref = { ref } /> ;
95
123
} ) ;
0 commit comments