1
1
import _ from 'lodash' ;
2
2
import React , { Component } from 'react' ;
3
3
import { StyleProp , StyleSheet , ViewStyle } from 'react-native' ;
4
+ import memoize from 'memoize-one' ;
4
5
import * as Modifiers from '../../commons/modifiers' ;
5
6
import { Colors , Spacings , Typography } from 'style' ;
6
7
import View , { ViewProps } from '../view' ;
7
8
import TouchableOpacity , { TouchableOpacityProps } from '../touchableOpacity' ;
8
9
import Text from '../text' ;
9
10
import Image , { ImageProps } from '../image' ;
10
11
12
+ export enum HorizontalAlignment {
13
+ left = 'left' ,
14
+ center = 'center' ,
15
+ right = 'right'
16
+ }
17
+
11
18
export interface GridListItemProps {
12
19
/**
13
20
* Image props object for rendering an image item
@@ -85,6 +92,10 @@ export interface GridListItemProps {
85
92
* Should content be align to start (default is center)
86
93
*/
87
94
alignToStart ?: boolean ;
95
+ /**
96
+ * Content horizontal alignment (default is center)
97
+ */
98
+ horizontalAlignment ?: HorizontalAlignment | `${HorizontalAlignment } `;
88
99
/**
89
100
* Custom container style
90
101
*/
@@ -101,7 +112,7 @@ export interface GridListItemProps {
101
112
* Test ID for component
102
113
*/
103
114
testID ?: string ;
104
- children ?: React . ReactNode ;
115
+ children ?: React . ReactElement | React . ReactElement [ ] ;
105
116
}
106
117
107
118
interface RenderContentType {
@@ -120,6 +131,8 @@ interface RenderContentType {
120
131
class GridListItem extends Component < GridListItemProps > {
121
132
static displayName = 'GridListItem' ;
122
133
134
+ static horizontalAlignment = HorizontalAlignment ;
135
+
123
136
static defaultProps = {
124
137
itemSize : 48
125
138
} ;
@@ -139,14 +152,34 @@ class GridListItem extends Component<GridListItemProps> {
139
152
return { width : itemSize as number , height : itemSize as number } ;
140
153
}
141
154
155
+ getContainerHorizontalAlignment = memoize ( horizontalAlignment => {
156
+ switch ( horizontalAlignment ) {
157
+ case HorizontalAlignment . left :
158
+ return 'flex-start' ;
159
+ case HorizontalAlignment . right :
160
+ return 'flex-end' ;
161
+ case HorizontalAlignment . center :
162
+ return 'center' ;
163
+ default :
164
+ undefined ;
165
+ }
166
+ } ) ;
167
+
142
168
renderContent ( { text, typography, color, numberOfLines = 1 , style, testID} : RenderContentType ) {
143
- const { alignToStart} = this . props ;
169
+ const { alignToStart, horizontalAlignment} = this . props ;
170
+ const textAlign = alignToStart ? 'left' : horizontalAlignment ;
144
171
if ( text ) {
145
172
return (
146
173
< Text
147
174
testID = { testID }
148
175
// @ts -ignore
149
- style = { [ style , Typography [ typography ] , color && { color} , alignToStart && styles . contentAlignedToStart ] }
176
+ style = { [
177
+ style ,
178
+ //@ts -ignore
179
+ Typography [ typography ] ,
180
+ color && { color} ,
181
+ { textAlign}
182
+ ] }
150
183
numberOfLines = { numberOfLines }
151
184
>
152
185
{ text }
@@ -160,6 +193,7 @@ class GridListItem extends Component<GridListItemProps> {
160
193
testID,
161
194
imageProps,
162
195
alignToStart,
196
+ horizontalAlignment,
163
197
containerStyle,
164
198
containerProps = { } ,
165
199
renderCustomItem,
@@ -181,32 +215,27 @@ class GridListItem extends Component<GridListItemProps> {
181
215
onPress,
182
216
renderOverlay
183
217
} = this . props ;
184
- const hasPress = _ . isFunction ( onPress ) ;
185
- const hasOverlay = _ . isFunction ( renderOverlay ) ;
186
- const Container = hasPress ? TouchableOpacity : View ;
187
- const imageStyle = { ...this . getItemSizeObj ( ) } ;
188
- const width = _ . get ( imageStyle , 'width' ) ;
218
+ const Container = onPress ? TouchableOpacity : View ;
189
219
const TextContainer = overlayText ? View : React . Fragment ;
190
- const textContainerStyle = overlayText ? { style : [ styles . overlayText , overlayTextContainerStyle ] } : null ;
191
- const imageBorderRadius = imageProps ?. borderRadius ;
220
+ const itemSize = this . getItemSizeObj ( ) ;
221
+ const { width} = itemSize ;
222
+ const alignItems = alignToStart ? 'flex-start' : this . getContainerHorizontalAlignment ( horizontalAlignment ) ;
223
+ const textContainerStyle = overlayText && {
224
+ style : [ styles . overlayText , overlayTextContainerStyle ]
225
+ } ;
192
226
const { hitSlop, ...otherContainerProps } = containerProps ; // eslint-disable-line
193
227
194
228
return (
195
229
< Container
196
- style = { [ styles . container , alignToStart && styles . containerAlignedToStart , { width} , containerStyle ] }
230
+ style = { [ styles . container , { alignItems } , { width} , containerStyle ] }
197
231
{ ...otherContainerProps }
198
- onPress = { hasPress ? this . onItemPress : undefined }
232
+ onPress = { onPress && this . onItemPress }
199
233
accessible = { renderCustomItem ? true : undefined }
200
234
{ ...Modifiers . extractAccessibilityProps ( this . props ) }
201
235
>
202
- { imageProps && (
203
- < View style = { [ { borderRadius : imageBorderRadius } , imageStyle ] } >
204
- < Image { ...imageProps } style = { [ imageStyle , imageProps ?. style ] } />
205
- { children }
206
- </ View >
207
- ) }
236
+ { imageProps && < Image style = { itemSize } { ...imageProps } customOverlayContent = { children } /> }
208
237
{ ! _ . isNil ( renderCustomItem ) && < View style = { { width} } > { renderCustomItem ( ) } </ View > }
209
- { hasOverlay && < View style = { [ styles . overlay , this . getItemSizeObj ( ) ] } > { renderOverlay ?. ( ) } </ View > }
238
+ { renderOverlay && < View style = { [ styles . overlay , itemSize ] } > { renderOverlay ( ) } </ View > }
210
239
< TextContainer { ...textContainerStyle } >
211
240
{ this . renderContent ( {
212
241
testID : `${ testID } .title` ,
@@ -243,9 +272,6 @@ const styles = StyleSheet.create({
243
272
alignSelf : 'flex-start' ,
244
273
alignItems : 'center'
245
274
} ,
246
- containerAlignedToStart : {
247
- alignItems : 'flex-start'
248
- } ,
249
275
title : {
250
276
marginTop : Spacings . s1 ,
251
277
textAlign : 'center' ,
@@ -259,18 +285,15 @@ const styles = StyleSheet.create({
259
285
textAlign : 'center' ,
260
286
...Typography . subtext
261
287
} ,
262
- contentAlignedToStart : {
263
- textAlign : 'left'
264
- } ,
265
288
overlay : {
266
289
position : 'absolute' ,
267
290
left : 0 ,
268
291
top : 0
269
292
} ,
270
293
overlayText : {
271
294
position : 'absolute' ,
272
- bottom : 10 ,
273
- left : 10
295
+ bottom : 0 ,
296
+ padding : Spacings . s3
274
297
}
275
298
} ) ;
276
299
0 commit comments