@@ -13,6 +13,12 @@ import Text, {TextProps} from '../../components/text';
13
13
14
14
const AnimatedFlatList = Animated . createAnimatedComponent ( FlatList ) ;
15
15
16
+ enum WheelPickerAlign {
17
+ CENTER = 'center' ,
18
+ RIGHT = 'right' ,
19
+ LEFT = 'left'
20
+ }
21
+
16
22
export interface WheelPickerProps {
17
23
/**
18
24
* Initial value (doesn't work with selectedValue)
@@ -72,10 +78,14 @@ export interface WheelPickerProps {
72
78
* Support passing items as children props
73
79
*/
74
80
children ?: JSX . Element | JSX . Element [ ] ;
81
+ /**
82
+ * Align the content to center, right ot left (default: center)
83
+ */
84
+ align ?: WheelPickerAlign ;
75
85
testID ?: string ;
76
86
}
77
87
78
- const WheelPicker = React . memo ( ( {
88
+ const WheelPicker = ( {
79
89
items : propItems ,
80
90
itemHeight = 44 ,
81
91
numberOfVisibleRows = 5 ,
@@ -86,6 +96,7 @@ const WheelPicker = React.memo(({
86
96
labelStyle,
87
97
labelProps,
88
98
onChange,
99
+ align,
89
100
style,
90
101
children,
91
102
initialValue,
@@ -115,6 +126,7 @@ const WheelPicker = React.memo(({
115
126
116
127
const prevIndex = useRef ( currentIndex ) ;
117
128
const [ scrollOffset , setScrollOffset ] = useState ( currentIndex * itemHeight ) ;
129
+ const [ flatListWidth , setFlatListWidth ] = useState ( 0 ) ;
118
130
const keyExtractor = useCallback ( ( item : ItemProps , index : number ) => `${ item } .${ index } ` , [ ] ) ;
119
131
120
132
/* This effect enforce the index to be controlled by selectedValue passed by the user */
@@ -168,6 +180,14 @@ const WheelPicker = React.memo(({
168
180
} ,
169
181
[ onChange ] ) ;
170
182
183
+ const alignmentStyle = useMemo ( ( ) =>
184
+ align === WheelPickerAlign . RIGHT
185
+ ? { alignSelf : 'flex-end' }
186
+ : align === WheelPickerAlign . LEFT
187
+ ? { alignSelf : 'flex-start' }
188
+ : { alignSelf : 'center' } ,
189
+ [ align ] ) ;
190
+
171
191
const renderItem = useCallback ( ( { item, index} ) => {
172
192
return (
173
193
< Item
@@ -178,6 +198,9 @@ const WheelPicker = React.memo(({
178
198
inactiveColor = { inactiveTextColor }
179
199
style = { textStyle }
180
200
{ ...item }
201
+ fakeLabel = { label }
202
+ fakeLabelStyle = { labelStyle }
203
+ fakeLabelProps = { labelProps }
181
204
centerH = { ! label }
182
205
onSelect = { selectItem }
183
206
testID = { `${ testID } .item_${ index } ` }
@@ -194,15 +217,22 @@ const WheelPicker = React.memo(({
194
217
) ;
195
218
} , [ ] ) ;
196
219
220
+ const labelContainerStyle = useMemo ( ( ) => {
221
+ return [ { position : 'absolute' , top : 0 , bottom : 0 } , alignmentStyle ] ;
222
+ } , [ alignmentStyle ] ) ;
223
+
197
224
const labelContainer = useMemo ( ( ) => {
198
225
return (
199
- < View centerV >
200
- < Text marginL-s2 text80M { ...labelProps } color = { activeTextColor } style = { labelStyle } >
201
- { label }
202
- </ Text >
226
+ // @ts -expect-error
227
+ < View style = { labelContainerStyle } width = { flatListWidth } pointerEvents = "none" >
228
+ < View style = { styles . label } centerV pointerEvents = "none" >
229
+ < Text marginL-s2 marginR-s5 text80M { ...labelProps } color = { activeTextColor } style = { labelStyle } >
230
+ { label }
231
+ </ Text >
232
+ </ View >
203
233
</ View >
204
234
) ;
205
- } , [ ] ) ;
235
+ } , [ flatListWidth , labelContainerStyle , label , labelProps , activeTextColor , labelStyle ] ) ;
206
236
207
237
const fader = useMemo ( ( ) => ( position : FaderPosition ) => {
208
238
return < Fader visible position = { position } size = { 60 } /> ;
@@ -214,14 +244,23 @@ const WheelPicker = React.memo(({
214
244
} ,
215
245
[ itemHeight ] ) ;
216
246
247
+ const updateFlatListWidth = useCallback ( ( width : number ) => {
248
+ setFlatListWidth ( width ) ;
249
+ } , [ ] ) ;
250
+
217
251
const contentContainerStyle = useMemo ( ( ) => {
218
- return { paddingVertical : height / 2 - itemHeight / 2 } ;
219
- } , [ height , itemHeight ] ) ;
252
+ return [
253
+ {
254
+ paddingVertical : height / 2 - itemHeight / 2
255
+ } ,
256
+ alignmentStyle
257
+ ] ;
258
+ } , [ height , itemHeight , alignmentStyle ] ) ;
220
259
221
260
return (
222
261
< View testID = { testID } bg-white style = { style } >
223
- < View row marginH-s5 centerH >
224
- < View >
262
+ < View row centerH >
263
+ < View flexG >
225
264
< AnimatedFlatList
226
265
testID = { `${ testID } .list` }
227
266
height = { height }
@@ -235,23 +274,26 @@ const WheelPicker = React.memo(({
235
274
onLayout = { scrollToPassedIndex }
236
275
// @ts -ignore
237
276
ref = { scrollView }
277
+ // @ts -expect-error
238
278
contentContainerStyle = { contentContainerStyle }
239
279
snapToInterval = { itemHeight }
240
280
decelerationRate = { Constants . isAndroid ? 0.98 : 'normal' }
241
281
renderItem = { renderItem }
242
282
getItemLayout = { getItemLayout }
243
283
initialScrollIndex = { currentIndex }
284
+ onContentSizeChange = { updateFlatListWidth }
244
285
/>
245
286
</ View >
246
- { label && labelContainer }
247
287
</ View >
288
+ { label && labelContainer }
248
289
{ fader ( FaderPosition . BOTTOM ) }
249
290
{ fader ( FaderPosition . TOP ) }
250
291
{ separators }
251
292
</ View >
252
293
) ;
253
- } ) ;
294
+ } ;
254
295
296
+ WheelPicker . alignments = WheelPickerAlign ;
255
297
export default WheelPicker ;
256
298
257
299
const styles = StyleSheet . create ( {
@@ -260,5 +302,11 @@ const styles = StyleSheet.create({
260
302
borderBottomWidth : 1 ,
261
303
height : Spacings . s9 ,
262
304
borderColor : Colors . grey60
305
+ } ,
306
+ label : {
307
+ position : 'absolute' ,
308
+ right : 0 ,
309
+ top : 0 ,
310
+ bottom : 0
263
311
}
264
312
} ) ;
0 commit comments