@@ -10,7 +10,6 @@ import Text from '../text';
1010import PageControl from '../pageControl' ;
1111import * as presenter from './CarouselPresenter' ;
1212
13-
1413const PAGE_CONTROL_POSITIONS = {
1514 OVER : 'over' ,
1615 UNDER : 'under'
@@ -40,6 +39,15 @@ export default class Carousel extends BaseComponent {
4039 * the spacing between the items
4140 */
4241 itemSpacings : PropTypes . number ,
42+ /**
43+ * Horizontal margin for the container
44+ */
45+ containerMarginHorizontal : PropTypes . number ,
46+ /**
47+ * Vertical padding for the container.
48+ * Sometimes needed when there are overflows that are cut in Android.
49+ */
50+ containerPaddingVertical : PropTypes . number ,
4351 /**
4452 * if true, will have infinite scroll
4553 */
@@ -84,7 +92,6 @@ export default class Carousel extends BaseComponent {
8492
8593 static defaultProps = {
8694 initialPage : 0 ,
87- itemSpacings : 16 ,
8895 pagingEnabled : true
8996 } ;
9097
@@ -95,7 +102,7 @@ export default class Carousel extends BaseComponent {
95102
96103 this . carousel = React . createRef ( ) ;
97104 const defaultPageWidth = props . loop ?
98- Constants . screenWidth : props . pageWidth + props . itemSpacings || Constants . screenWidth ;
105+ Constants . screenWidth : props . pageWidth + this . getItemSpacings ( props ) || Constants . screenWidth ;
99106
100107 this . state = {
101108 containerWidth : undefined ,
@@ -115,21 +122,39 @@ export default class Carousel extends BaseComponent {
115122 }
116123
117124 onOrientationChanged = ( ) => {
118- if ( ! this . props . pageWidth || this . props . loop ) {
125+ const { pageWidth, loop} = this . getThemeProps ( ) ;
126+ if ( ! pageWidth || loop ) {
119127 this . orientationChange = true ;
120128 // HACK: setting to containerWidth for Android's call when view disappear
121129 this . setState ( { pageWidth : this . state . containerWidth || Constants . screenWidth } ) ;
122130 }
123131 } ;
124132
125133 generateStyles ( ) {
126- this . styles = createStyles ( this . props ) ;
134+ this . styles = createStyles ( this . getThemeProps ( ) ) ;
135+ }
136+
137+ getItemSpacings ( props ) {
138+ const { itemSpacings = 16 } = props ;
139+ return itemSpacings ;
140+ }
141+
142+ getContainerMarginHorizontal = ( ) => {
143+ const { containerMarginHorizontal = 0 } = this . getThemeProps ( ) ;
144+ return containerMarginHorizontal ;
145+ }
146+
147+ // TODO: RN 61.5 - try to remove this from the children and move to the ScrollView's contentContainerStyle
148+ // style={{overflow: 'visible'}} does not work in ScrollView on Android, maybe it will be fixed in the future
149+ getContainerPaddingVertical = ( ) => {
150+ const { containerPaddingVertical = 0 } = this . getThemeProps ( ) ;
151+ return containerPaddingVertical ;
127152 }
128153
129154 updateOffset = ( animated = false ) => {
130155 const centerOffset = Constants . isIOS && this . shouldUsePageWidth ( ) ?
131156 ( Constants . screenWidth - this . state . pageWidth ) / 2 : 0 ;
132- const x = presenter . calcOffset ( this . props , this . state ) - centerOffset ;
157+ const x = presenter . calcOffset ( this . getThemeProps ( ) , this . state ) - centerOffset ;
133158
134159 if ( this . carousel ) {
135160 this . carousel . current . scrollTo ( { x, animated} ) ;
@@ -157,45 +182,47 @@ export default class Carousel extends BaseComponent {
157182 }
158183
159184 getSnapToOffsets = ( ) => {
160- const { itemSpacings} = this . props ;
161185 const { containerWidth, pageWidth} = this . state ;
162186
163187 if ( this . shouldEnablePagination ( ) ) {
164188 return undefined ;
165189 }
166190
167191 if ( containerWidth ) {
168- const spacings = pageWidth === containerWidth ? 0 : itemSpacings ;
192+ const spacings = pageWidth === containerWidth ? 0 : this . getItemSpacings ( this . getThemeProps ( ) ) ;
169193 const initialBreak = pageWidth - ( containerWidth - pageWidth - spacings ) / 2 ;
170- const snapToOffsets = _ . times ( presenter . getChildrenLength ( this . props ) , index => initialBreak + index * pageWidth ) ;
194+ const snapToOffsets = _ . times ( presenter . getChildrenLength ( this . props ) ,
195+ index => initialBreak + index * pageWidth + this . getContainerMarginHorizontal ( ) ) ;
171196 return snapToOffsets ;
172197 }
173198 } ;
174199
175200 shouldUsePageWidth ( ) {
176- const { loop, pageWidth} = this . props ;
201+ const { loop, pageWidth} = this . getThemeProps ( ) ;
177202 return ! loop && pageWidth ;
178203 }
179204
180205 shouldEnablePagination ( ) {
181- const { pagingEnabled} = this . props ;
206+ const { pagingEnabled} = this . getThemeProps ( ) ;
182207 return pagingEnabled && ! this . shouldUsePageWidth ( ) ;
183208 }
184209
185210 onContainerLayout = ( { nativeEvent : { layout : { width : containerWidth } } } ) => {
186211 const update = { containerWidth} ;
212+ const { pageWidth} = this . getThemeProps ( ) ;
187213
188- if ( ! this . props . pageWidth ) {
214+ if ( ! pageWidth ) {
189215 update . pageWidth = containerWidth ;
190216 update . initialOffset = {
191- x : presenter . calcOffset ( this . props , { currentPage : this . state . currentPage , pageWidth : containerWidth } )
217+ x : presenter . calcOffset ( this . getThemeProps ( ) , { currentPage : this . state . currentPage , pageWidth : containerWidth } )
192218 } ;
193219 }
194220 this . setState ( update ) ;
195221 } ;
196222
197223 shouldAllowAccessibilityLayout ( ) {
198- return this . props . allowAccessibleLayout && Constants . accessibility . isScreenReaderEnabled ;
224+ const { allowAccessibleLayout} = this . getThemeProps ( ) ;
225+ return allowAccessibleLayout && Constants . accessibility . isScreenReaderEnabled ;
199226 }
200227
201228 onContentSizeChange = ( ) => {
@@ -222,13 +249,13 @@ export default class Carousel extends BaseComponent {
222249 return ;
223250 }
224251
225- const { loop} = this . props ;
252+ const { loop} = this . getThemeProps ( ) ;
226253 const { pageWidth} = this . state ;
227254 const offsetX = event . nativeEvent . contentOffset . x ;
228255
229256 if ( offsetX >= 0 ) {
230257 if ( ! this . orientationChange ) { // Avoid new calculation on orientation change
231- const newPage = presenter . calcPageIndex ( offsetX , this . props , pageWidth ) ;
258+ const newPage = presenter . calcPageIndex ( offsetX , this . getThemeProps ( ) , pageWidth ) ;
232259 this . setState ( { currentPage : newPage } ) ;
233260 }
234261 this . orientationChange = false ;
@@ -243,12 +270,20 @@ export default class Carousel extends BaseComponent {
243270
244271 renderChild = ( child , key ) => {
245272 if ( child ) {
246- const paddingLeft = this . shouldUsePageWidth ( ) ? this . props . itemSpacings : undefined ;
273+ const paddingLeft = this . shouldUsePageWidth ( ) ? this . getItemSpacings ( this . getThemeProps ( ) ) : undefined ;
247274 const index = Number ( key ) ;
248275 const length = presenter . getChildrenLength ( this . props ) ;
276+ const containerMarginHorizontal = this . getContainerMarginHorizontal ( ) ;
277+ const marginLeft = index === 0 ? containerMarginHorizontal : 0 ;
278+ const marginRight = index === length - 1 ? containerMarginHorizontal : 0 ;
279+ const paddingVertical = this . getContainerPaddingVertical ( ) ;
249280
250281 return (
251- < View style = { { width : this . state . pageWidth , paddingLeft} } key = { key } collapsable = { false } >
282+ < View
283+ style = { { width : this . state . pageWidth , paddingLeft, marginLeft, marginRight, paddingVertical} }
284+ key = { key }
285+ collapsable = { false }
286+ >
252287 { this . shouldAllowAccessibilityLayout ( ) && ! Number . isNaN ( index ) &&
253288 < View style = { this . styles . hiddenText } >
254289 < Text > { `page ${ index + 1 } out of ${ length } ` } </ Text >
@@ -261,7 +296,7 @@ export default class Carousel extends BaseComponent {
261296 } ;
262297
263298 renderChildren ( ) {
264- const { children, loop} = this . props ;
299+ const { children, loop} = this . getThemeProps ( ) ;
265300 const length = presenter . getChildrenLength ( this . props ) ;
266301
267302 const childrenArray = React . Children . map ( children , ( child , index ) => {
@@ -277,16 +312,10 @@ export default class Carousel extends BaseComponent {
277312 }
278313
279314 renderPageControl ( ) {
280- const {
281- pageControlPosition,
282- pageControlProps,
283- size = 6 ,
284- spacing = 8 ,
285- color = Colors . dark20 ,
286- inactiveColor = Colors . dark60
287- } = this . getThemeProps ( ) ;
288-
315+ const { pageControlPosition, pageControlProps = { } } = this . getThemeProps ( ) ;
316+
289317 if ( pageControlPosition ) {
318+ const { size = 6 , spacing = 8 , color = Colors . dark20 , inactiveColor = Colors . dark60 , ...others } = pageControlProps ;
290319 const pagesCount = presenter . getChildrenLength ( this . props ) ;
291320 const containerStyle =
292321 pageControlPosition === PAGE_CONTROL_POSITIONS . UNDER
@@ -300,7 +329,7 @@ export default class Carousel extends BaseComponent {
300329 containerStyle = { containerStyle }
301330 inactiveColor = { inactiveColor }
302331 color = { color }
303- { ...pageControlProps }
332+ { ...others }
304333 numOfPages = { pagesCount }
305334 currentPage = { this . getCalcIndex ( this . state . currentPage ) }
306335 />
@@ -309,7 +338,7 @@ export default class Carousel extends BaseComponent {
309338 }
310339
311340 renderCounter ( ) {
312- const { pageWidth, showCounter, counterTextStyle} = this . props ;
341+ const { pageWidth, showCounter, counterTextStyle} = this . getThemeProps ( ) ;
313342 const { currentPage} = this . state ;
314343 const pagesCount = presenter . getChildrenLength ( this . props ) ;
315344
@@ -325,7 +354,7 @@ export default class Carousel extends BaseComponent {
325354 }
326355
327356 renderAccessibleLayout ( ) {
328- const { containerStyle, children} = this . props ;
357+ const { containerStyle, children} = this . getThemeProps ( ) ;
329358
330359 return (
331360 < View style = { containerStyle } onLayout = { this . onContainerLayout } >
@@ -346,13 +375,14 @@ export default class Carousel extends BaseComponent {
346375 }
347376
348377 renderCarousel ( ) {
349- const { containerStyle, itemSpacings , ...others } = this . props ;
378+ const { containerStyle, ...others } = this . getThemeProps ( ) ;
350379 const { initialOffset} = this . state ;
351- const scrollContainerStyle = this . shouldUsePageWidth ( ) ? { paddingRight : itemSpacings } : undefined ;
380+ const scrollContainerStyle = this . shouldUsePageWidth ( ) ? { paddingRight : this . getItemSpacings ( this . getThemeProps ( ) ) } : undefined ;
352381 const snapToOffsets = this . getSnapToOffsets ( ) ;
382+ const marginBottom = Math . max ( 0 , this . getContainerPaddingVertical ( ) - 16 ) ;
353383
354384 return (
355- < View style = { containerStyle } onLayout = { this . onContainerLayout } >
385+ < View style = { [ { marginBottom } , containerStyle ] } onLayout = { this . onContainerLayout } >
356386 < ScrollView
357387 { ...others }
358388 ref = { this . carousel }
@@ -381,7 +411,7 @@ export default class Carousel extends BaseComponent {
381411 }
382412}
383413
384- function createStyles ( ) {
414+ function createStyles ( { containerPaddingVertical = 0 } ) {
385415 return StyleSheet . create ( {
386416 counter : {
387417 paddingHorizontal : 8 ,
@@ -398,7 +428,7 @@ function createStyles() {
398428 alignSelf : 'center'
399429 } ,
400430 pageControlContainerStyleUnder : {
401- marginVertical : 16
431+ marginVertical : 16 - containerPaddingVertical
402432 } ,
403433 hiddenText : {
404434 position : 'absolute' ,
0 commit comments