1
1
import React from 'react' ;
2
-
3
2
import {
4
3
View ,
5
4
StyleSheet ,
6
5
TouchableNativeFeedback ,
7
6
Platform ,
8
- type ViewStyle ,
9
7
} from 'react-native' ;
10
8
11
- import { PressableScale } from 'react-native-pressable-scale' ;
12
9
import { useTheme , Text } from 'react-native-paper' ;
13
10
import * as Haptics from 'expo-haptics' ;
14
-
15
11
import { ChevronRight } from 'lucide-react-native' ;
16
12
17
13
interface Props {
18
- title ?: string
19
- subtitle ?: string
20
- underTitle ?: string
21
- left ?: React . ReactElement
22
- right ?: React . ReactElement
23
- /** Most likely an icon component from `lucide-react-native`. */
24
- icon ?: React . ReactElement
25
- style ?: ViewStyle
26
- color : string
27
- /** Add more space between `title` and `subtitle`. */
28
- isLarge ?: boolean
29
- onPress ?: ( ) => unknown
30
- onLongPress ?: ( ) => unknown
31
- fill ?: boolean
32
- /** Should take all the width from the parent. */
33
- width ?: boolean
34
- center ?: boolean
35
- chevron ?: boolean
36
- trimSubtitle ?: boolean
37
- bottom ?: React . ReactElement
14
+ title ?: string ;
15
+ subtitle ?: string ;
16
+ underTitle ?: string ;
17
+ left ?: React . ReactNode ;
18
+ right ?: React . ReactNode ;
19
+ icon ?: React . ReactNode ;
20
+ style ?: any ;
21
+ color : string ;
22
+ isLarge ?: boolean ;
23
+ onPress ?: ( ) => void ;
24
+ onLongPress ?: ( ) => void ;
25
+ fill ?: boolean ;
26
+ width ?: boolean ;
27
+ center ?: boolean ;
28
+ chevron ?: boolean ;
29
+ trimSubtitle ?: boolean ;
30
+ bottom ?: React . ReactNode ;
38
31
}
39
32
40
- /**
41
- * @see https://i.imgur.com/rshTN7n.png
42
- */
43
33
const ListItem : React . FC < Props > = ( {
44
34
title,
45
35
subtitle,
@@ -68,7 +58,7 @@ const ListItem: React.FC<Props> = ({
68
58
textColor = '#fff' ;
69
59
}
70
60
71
- const bgMaterial = theme . colors . elevation . level1 ;
61
+ const bgMaterial = theme . colors . elevation ? .level1 ;
72
62
73
63
function onPressActive ( ) {
74
64
onPress ?.( ) ;
@@ -79,28 +69,101 @@ const ListItem: React.FC<Props> = ({
79
69
if ( ! onPress ) pressScale = 0.92 ;
80
70
81
71
return Platform . OS === 'ios' ? (
82
- < PressableScale
83
- style = { { flex : 1 } }
84
- weight = "light"
85
- activeScale = { pressScale }
72
+ < View style = { [ styles . listItem , style ] } >
73
+ < TouchableNativeFeedback
74
+ onPress = { onPressActive }
75
+ onLongPress = { onLongPress }
76
+ background = { TouchableNativeFeedback . Ripple (
77
+ theme . colors . surfaceDisabled ,
78
+ true
79
+ ) }
80
+ >
81
+ < View
82
+ style = { [
83
+ {
84
+ backgroundColor : bgColor ,
85
+ borderColor : theme . dark ? '#191919' : '#e5e5e5' ,
86
+ marginHorizontal : width ? 0 : 14 ,
87
+ flex : width ? 1 : undefined ,
88
+ alignItems : center ? 'center' : undefined ,
89
+ flexDirection : 'row' ,
90
+ padding : 14 ,
91
+ borderRadius : 12 ,
92
+ borderWidth : 0 ,
93
+ } ,
94
+ ] }
95
+ >
96
+ { left && < View style = { styles . left } > { left } </ View > }
97
+ { icon && (
98
+ < View
99
+ style = { [
100
+ styles . icon ,
101
+ { backgroundColor : theme . dark ? '#ffffff10' : `${ color } 10` } ,
102
+ ] }
103
+ >
104
+ { icon }
105
+ </ View >
106
+ ) }
107
+ < View style = { [ styles . listItemText , { gap : isLarge ? 8 : 2 } ] } >
108
+ { title && (
109
+ < Text style = { [ styles . listItemTextTitle , { color : textColor } ] } >
110
+ { title }
111
+ </ Text >
112
+ ) }
113
+ { subtitle && (
114
+ < Text
115
+ style = { [ styles . listItemTextSubtitle , { color : textColor } ] }
116
+ numberOfLines = { trimSubtitle ? 1 : undefined }
117
+ ellipsizeMode = "tail"
118
+ >
119
+ { subtitle }
120
+ </ Text >
121
+ ) }
122
+ { underTitle && (
123
+ < Text
124
+ style = { [ styles . listItemTextUnderTitle , { color : textColor } ] }
125
+ >
126
+ { underTitle }
127
+ </ Text >
128
+ ) }
129
+ </ View >
130
+ { right && < View style = { styles . right } > { right } </ View > }
131
+ { chevron && (
132
+ < View style = { styles . right } >
133
+ < ChevronRight
134
+ size = { 24 }
135
+ strokeWidth = { 2.5 }
136
+ style = { { marginTop : - 6 , marginBottom : - 6 } }
137
+ color = { theme . dark ? '#ffffff40' : '#00000040' }
138
+ />
139
+ </ View >
140
+ ) }
141
+ </ View >
142
+ </ TouchableNativeFeedback >
143
+ </ View >
144
+ ) : (
145
+ < TouchableNativeFeedback
86
146
onPress = { onPressActive }
87
- onLongPress = { ( ) => onLongPress ?.( ) }
147
+ onLongPress = { onLongPress }
148
+ background = { TouchableNativeFeedback . Ripple (
149
+ theme . colors . surfaceDisabled ,
150
+ true
151
+ ) }
88
152
>
89
153
< View
90
154
style = { [
91
- styles . listItem ,
155
+ styles . listItemContainer ,
92
156
{
93
- backgroundColor : bgColor ,
157
+ backgroundColor : bgMaterial ,
94
158
borderColor : theme . dark ? '#191919' : '#e5e5e5' ,
95
159
marginHorizontal : width ? 0 : 14 ,
96
- flex : width ? 1 : void 0 ,
97
- alignItems : center ? 'center' : void 0 ,
160
+ flex : width ? 1 : undefined ,
161
+ alignItems : center ? 'center' : undefined ,
98
162
} ,
99
163
style ,
100
164
] }
101
165
>
102
166
{ left && < View style = { styles . left } > { left } </ View > }
103
-
104
167
{ icon && (
105
168
< View
106
169
style = { [
@@ -111,33 +174,28 @@ const ListItem: React.FC<Props> = ({
111
174
{ icon }
112
175
</ View >
113
176
) }
114
-
115
177
< View style = { [ styles . listItemText , { gap : isLarge ? 8 : 2 } ] } >
116
178
{ title && (
117
179
< Text style = { [ styles . listItemTextTitle , { color : textColor } ] } >
118
180
{ title }
119
181
</ Text >
120
182
) }
121
-
122
183
{ subtitle && (
123
184
< Text
124
185
style = { [ styles . listItemTextSubtitle , { color : textColor } ] }
125
- numberOfLines = { trimSubtitle ? 1 : void 0 }
186
+ numberOfLines = { trimSubtitle ? 1 : undefined }
126
187
ellipsizeMode = "tail"
127
188
>
128
189
{ subtitle }
129
190
</ Text >
130
191
) }
131
-
132
192
{ underTitle && (
133
193
< Text style = { [ styles . listItemTextUnderTitle , { color : textColor } ] } >
134
194
{ underTitle }
135
195
</ Text >
136
196
) }
137
197
</ View >
138
-
139
198
{ right && < View style = { styles . right } > { right } </ View > }
140
-
141
199
{ chevron && (
142
200
< View style = { styles . right } >
143
201
< ChevronRight
@@ -149,93 +207,24 @@ const ListItem: React.FC<Props> = ({
149
207
</ View >
150
208
) }
151
209
</ View >
152
- </ PressableScale >
153
- ) : (
154
- < View
155
- style = { [
156
- styles . listItemContainer ,
157
- { flex : 1 , borderRadius : 10 , overflow : 'hidden' } ,
158
- {
159
- backgroundColor : bgMaterial ,
160
- borderColor : theme . dark ? '#191919' : '#e5e5e5' ,
161
- marginHorizontal : width ? 0 : 14 ,
162
- flex : width ? 1 : void 0 ,
163
- alignItems : center ? 'center' : void 0 ,
164
- } ,
165
- style ,
166
- ] }
167
- >
168
- < TouchableNativeFeedback
169
- style = { { flex : 1 , borderRadius : 12 , overflow : 'hidden' } }
170
- onPress = { onPressActive }
171
- onLongPress = { ( ) => onLongPress ?.( ) }
172
- background = { TouchableNativeFeedback . Ripple (
173
- theme . colors . surfaceDisabled ,
174
- true
175
- ) }
176
- >
177
- < View style = { styles . listItemChild } >
178
- { left && < View style = { styles . left } > { left } </ View > }
179
-
180
- { icon && (
181
- < View
182
- style = { [
183
- styles . icon ,
184
- { backgroundColor : theme . dark ? '#ffffff10' : `${ color } 10` } ,
185
- ] }
186
- >
187
- { icon }
188
- </ View >
189
- ) }
190
-
191
- < View style = { [ styles . listItemText , { gap : isLarge ? 8 : 2 } ] } >
192
- { title && (
193
- < Text style = { [ styles . listItemTextTitle , { color : textColor } ] } >
194
- { title }
195
- </ Text >
196
- ) }
197
-
198
- { subtitle && (
199
- < Text
200
- style = { [ styles . listItemTextSubtitle , { color : textColor } ] }
201
- numberOfLines = { trimSubtitle ? 1 : void 0 }
202
- ellipsizeMode = "tail"
203
- >
204
- { subtitle }
205
- </ Text >
206
- ) }
207
-
208
- { bottom && < View > { bottom } </ View > }
209
- </ View >
210
-
211
- { right && < View style = { styles . right } > { right } </ View > }
212
- </ View >
213
- </ TouchableNativeFeedback >
214
- </ View >
210
+ </ TouchableNativeFeedback >
215
211
) ;
216
212
} ;
217
213
218
214
const styles = StyleSheet . create ( {
219
215
listItem : {
220
216
flexDirection : 'row' ,
221
-
222
217
padding : 14 ,
223
218
marginHorizontal : 14 ,
224
-
225
219
borderRadius : 12 ,
226
220
borderCurve : 'continuous' ,
227
221
borderWidth : 0 ,
228
222
} ,
229
223
listItemContainer : {
230
224
marginHorizontal : 14 ,
231
-
232
225
borderRadius : 10 ,
233
226
borderWidth : 0 ,
234
227
} ,
235
- listItemChild : {
236
- padding : 14 ,
237
- flexDirection : 'row' ,
238
- } ,
239
228
listItemText : {
240
229
gap : 2 ,
241
230
flex : 1 ,
@@ -263,11 +252,9 @@ const styles = StyleSheet.create({
263
252
} ,
264
253
icon : {
265
254
marginRight : 14 ,
266
-
267
255
width : 38 ,
268
256
height : 38 ,
269
257
borderRadius : 30 ,
270
-
271
258
justifyContent : 'center' ,
272
259
alignItems : 'center' ,
273
260
} ,
0 commit comments