@@ -34,7 +34,6 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
3434 allowFontScaling = false ,
3535 amLabel,
3636 Audio,
37- bottomPickerGradientOverlayProps,
3837 clickSoundAsset,
3938 disableInfiniteScroll = false ,
4039 FlatList = RNFlatList ,
@@ -46,6 +45,7 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
4645 label,
4746 limit,
4847 LinearGradient,
48+ MaskedView,
4949 maximumValue,
5050 onDurationChange,
5151 padNumbersWithZero = false ,
@@ -57,7 +57,6 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
5757 repeatNumbersNTimesNotExplicitlySet,
5858 styles,
5959 testID,
60- topPickerGradientOverlayProps,
6160 } = props ;
6261
6362 const numberOfItems = useMemo ( ( ) => {
@@ -495,6 +494,127 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
495494 latestDuration : latestDuration ,
496495 } ) ) ;
497496
497+ const renderContent = useMemo ( ( ) => {
498+ return (
499+ < >
500+ < FlatList
501+ key = { flatListRenderKey }
502+ ref = { flatListRef }
503+ contentContainerStyle = {
504+ styles . durationScrollFlatListContentContainer
505+ }
506+ data = { numbersForFlatList }
507+ decelerationRate = { 0.88 }
508+ getItemLayout = { getItemLayout }
509+ initialScrollIndex = { initialScrollIndex }
510+ keyExtractor = { ( _ , index ) => index . toString ( ) }
511+ nestedScrollEnabled
512+ onMomentumScrollEnd = { onMomentumScrollEnd }
513+ onScroll = { onScroll }
514+ renderItem = { renderItem }
515+ scrollEnabled = { ! isDisabled }
516+ scrollEventThrottle = { 16 }
517+ showsVerticalScrollIndicator = { false }
518+ snapToAlignment = "start"
519+ // used in place of snapToInterval due to bug on Android
520+ snapToOffsets = { [
521+ ...Array ( numbersForFlatList . length ) ,
522+ ] . map ( ( _ , i ) => i * styles . pickerItemContainer . height ) }
523+ style = { styles . durationScrollFlatList }
524+ testID = "duration-scroll-flatlist"
525+ viewabilityConfigCallbackPairs = {
526+ viewabilityConfigCallbackPairs
527+ }
528+ windowSize = { numberOfItemsToShow }
529+ />
530+ < View
531+ pointerEvents = "none"
532+ style = { styles . pickerLabelContainer } >
533+ { typeof label === "string" ? (
534+ < Text
535+ allowFontScaling = { allowFontScaling }
536+ style = { styles . pickerLabel } >
537+ { label }
538+ </ Text >
539+ ) : (
540+ label ?? null
541+ ) }
542+ </ View >
543+ </ >
544+ ) ;
545+ } , [
546+ FlatList ,
547+ allowFontScaling ,
548+ flatListRenderKey ,
549+ getItemLayout ,
550+ initialScrollIndex ,
551+ isDisabled ,
552+ label ,
553+ numberOfItemsToShow ,
554+ numbersForFlatList ,
555+ onMomentumScrollEnd ,
556+ onScroll ,
557+ renderItem ,
558+ styles . durationScrollFlatList ,
559+ styles . durationScrollFlatListContentContainer ,
560+ styles . pickerItemContainer . height ,
561+ styles . pickerLabel ,
562+ styles . pickerLabelContainer ,
563+ viewabilityConfigCallbackPairs ,
564+ ] ) ;
565+
566+ const renderLinearGradient = useMemo ( ( ) => {
567+ if ( ! LinearGradient ) {
568+ return null ;
569+ }
570+
571+ let colors : string [ ] ;
572+
573+ if ( MaskedView ) {
574+ // if using masked view, we only care about the opacity
575+ colors = [
576+ "rgba(0,0,0,0)" ,
577+ "rgba(0,0,0,1)" ,
578+ "rgba(0,0,0,1)" ,
579+ "rgba(0,0,0,0)" ,
580+ ] ;
581+ } else {
582+ const backgroundColor =
583+ styles . pickerContainer . backgroundColor ?? "white" ;
584+ const transparentBackgroundColor = colorToRgba ( {
585+ color : backgroundColor ,
586+ opacity : 0 ,
587+ } ) ;
588+ colors = [
589+ backgroundColor ,
590+ transparentBackgroundColor ,
591+ transparentBackgroundColor ,
592+ backgroundColor ,
593+ ] ;
594+ }
595+
596+ // calculate the gradient height to cover the top item and bottom item
597+ const gradientHeight =
598+ padWithNItems > 0 ? 1 / ( padWithNItems * 2 + 1 ) : 0.3 ;
599+
600+ return (
601+ < LinearGradient
602+ colors = { colors }
603+ locations = { [ 0 , gradientHeight , 1 - gradientHeight , 1 ] }
604+ pointerEvents = "none"
605+ style = { styles . pickerGradientOverlay }
606+ { ...pickerGradientOverlayProps }
607+ />
608+ ) ;
609+ } , [
610+ LinearGradient ,
611+ MaskedView ,
612+ padWithNItems ,
613+ pickerGradientOverlayProps ,
614+ styles . pickerContainer . backgroundColor ,
615+ styles . pickerGradientOverlay ,
616+ ] ) ;
617+
498618 return (
499619 < View
500620 pointerEvents = { isDisabled ? "none" : undefined }
@@ -508,90 +628,18 @@ const DurationScroll = forwardRef<DurationScrollRef, DurationScrollProps>(
508628 isDisabled && styles . disabledPickerContainer ,
509629 ] }
510630 testID = { testID } >
511- < FlatList
512- key = { flatListRenderKey }
513- ref = { flatListRef }
514- contentContainerStyle = {
515- styles . durationScrollFlatListContentContainer
516- }
517- data = { numbersForFlatList }
518- decelerationRate = { 0.88 }
519- getItemLayout = { getItemLayout }
520- initialScrollIndex = { initialScrollIndex }
521- keyExtractor = { ( _ , index ) => index . toString ( ) }
522- nestedScrollEnabled
523- onMomentumScrollEnd = { onMomentumScrollEnd }
524- onScroll = { onScroll }
525- renderItem = { renderItem }
526- scrollEnabled = { ! isDisabled }
527- scrollEventThrottle = { 16 }
528- showsVerticalScrollIndicator = { false }
529- snapToAlignment = "start"
530- // used in place of snapToInterval due to bug on Android
531- snapToOffsets = { [ ...Array ( numbersForFlatList . length ) ] . map (
532- ( _ , i ) => i * styles . pickerItemContainer . height
533- ) }
534- style = { styles . durationScrollFlatList }
535- testID = "duration-scroll-flatlist"
536- viewabilityConfigCallbackPairs = {
537- viewabilityConfigCallbackPairs
538- }
539- windowSize = { numberOfItemsToShow }
540- />
541- < View pointerEvents = "none" style = { styles . pickerLabelContainer } >
542- { typeof label === "string" ? (
543- < Text
544- allowFontScaling = { allowFontScaling }
545- style = { styles . pickerLabel } >
546- { label }
547- </ Text >
548- ) : (
549- label ?? null
550- ) }
551- </ View >
552- { LinearGradient ? (
631+ { MaskedView ? (
632+ < MaskedView
633+ maskElement = { renderLinearGradient }
634+ style = { [ styles . maskedView ] } >
635+ { renderContent }
636+ </ MaskedView >
637+ ) : (
553638 < >
554- < LinearGradient
555- colors = { [
556- styles . pickerContainer . backgroundColor ??
557- "white" ,
558- colorToRgba ( {
559- color :
560- styles . pickerContainer
561- . backgroundColor ?? "white" ,
562- opacity : 0 ,
563- } ) ,
564- ] }
565- end = { { x : 1 , y : 1 } }
566- pointerEvents = "none"
567- start = { { x : 1 , y : 0.3 } }
568- { ...pickerGradientOverlayProps }
569- { ...topPickerGradientOverlayProps }
570- style = { [ styles . pickerGradientOverlay , { top : 0 } ] }
571- />
572- < LinearGradient
573- colors = { [
574- colorToRgba ( {
575- color :
576- styles . pickerContainer
577- . backgroundColor ?? "white" ,
578- opacity : 0 ,
579- } ) ,
580- styles . pickerContainer . backgroundColor ??
581- "white" ,
582- ] }
583- end = { { x : 1 , y : 0.7 } }
584- pointerEvents = "none"
585- start = { { x : 1 , y : 0 } }
586- { ...pickerGradientOverlayProps }
587- { ...bottomPickerGradientOverlayProps }
588- style = { [
589- styles . pickerGradientOverlay ,
590- { bottom : - 1 } ,
591- ] }
592- />
639+ { renderContent }
640+ { renderLinearGradient }
593641 </ >
594- ) : null }
642+ ) }
595643 </ View >
596644 ) ;
597645 }
0 commit comments