@momo-kits/swipe 0.0.4-beta → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/SwipeAction.js CHANGED
@@ -627,7 +627,9 @@ SwipeAction.propTypes = {
627
627
  onPress: PropTypes.func,
628
628
  children: PropTypes.element.isRequired,
629
629
  actionBackground: PropTypes.string,
630
- actionTextStyle: PropTypes.object
630
+ actionTextStyle: PropTypes.object,
631
+ swipeGestureBegan: PropTypes.func,
632
+ swipeGestureEnd: PropTypes.func,
631
633
  };
632
634
 
633
635
  SwipeAction.defaultProps = {
@@ -66,6 +66,8 @@ class SwipeActionList extends Component {
66
66
  onPress,
67
67
  onClose,
68
68
  actionBackground,
69
+ swipeGestureBegan,
70
+ swipeGestureEnd,
69
71
  } = this.props;
70
72
  return (
71
73
  <View>
@@ -86,6 +88,8 @@ class SwipeActionList extends Component {
86
88
  rowIndex={index}
87
89
  renderLeftAction={renderLeftAction}
88
90
  renderRightAction={renderRightAction}
91
+ swipeGestureBegan={swipeGestureBegan}
92
+ swipeGestureEnd={swipeGestureEnd}
89
93
  >
90
94
  {renderItem?.(item, index)}
91
95
  </SwipeAction>
@@ -127,7 +131,9 @@ SwipeActionList.propTypes = {
127
131
  onOpen: PropTypes.func,
128
132
  onClose: PropTypes.func,
129
133
  onPress: PropTypes.func,
130
- actionBackground: PropTypes.string
134
+ actionBackground: PropTypes.string,
135
+ swipeGestureBegan: PropTypes.func,
136
+ swipeGestureEnd: PropTypes.func,
131
137
  };
132
138
 
133
139
  SwipeActionList.defaultProps = {
package/Swiper.js ADDED
@@ -0,0 +1,774 @@
1
+ /* eslint-disable react/state-in-constructor */
2
+ /* eslint-disable react/static-property-placement */
3
+ /* eslint-disable no-multi-assign */
4
+ /* eslint-disable brace-style */
5
+ /* eslint-disable no-param-reassign */
6
+ /* eslint-disable react/no-array-index-key */
7
+ /* eslint-disable guard-for-in */
8
+ /* eslint-disable default-case */
9
+ /* eslint-disable react/destructuring-assignment */
10
+ /* eslint-disable no-restricted-syntax */
11
+ /**
12
+ * react-native-swiper
13
+ * @author leecade<leecade@163.com>
14
+ */
15
+ import React, { Component } from 'react';
16
+ import PropTypes from 'prop-types';
17
+ import {
18
+ Text,
19
+ View,
20
+ ScrollView,
21
+ Dimensions,
22
+ TouchableOpacity,
23
+ Platform,
24
+ ActivityIndicator
25
+ } from 'react-native';
26
+ import { ViewPager as ViewPagerAndroid } from '@momo-kits/core';
27
+
28
+ /**
29
+ * Default styles
30
+ * @type {StyleSheetPropType}
31
+ */
32
+ const styles = {
33
+ container: {
34
+ backgroundColor: 'transparent',
35
+ position: 'relative',
36
+ flex: 1
37
+ },
38
+
39
+ wrapperIOS: {
40
+ backgroundColor: 'transparent',
41
+ },
42
+
43
+ wrapperAndroid: {
44
+ backgroundColor: 'transparent',
45
+ flex: 1
46
+ },
47
+
48
+ slide: {
49
+ backgroundColor: 'transparent',
50
+ },
51
+
52
+ pagination_x: {
53
+ position: 'absolute',
54
+ bottom: 25,
55
+ left: 0,
56
+ right: 0,
57
+ flexDirection: 'row',
58
+ flex: 1,
59
+ justifyContent: 'center',
60
+ alignItems: 'center',
61
+ backgroundColor: 'transparent'
62
+ },
63
+
64
+ pagination_y: {
65
+ position: 'absolute',
66
+ right: 15,
67
+ top: 0,
68
+ bottom: 0,
69
+ flexDirection: 'column',
70
+ flex: 1,
71
+ justifyContent: 'center',
72
+ alignItems: 'center',
73
+ backgroundColor: 'transparent'
74
+ },
75
+
76
+ title: {
77
+ height: 30,
78
+ justifyContent: 'center',
79
+ position: 'absolute',
80
+ paddingLeft: 10,
81
+ bottom: -30,
82
+ left: 0,
83
+ flexWrap: 'nowrap',
84
+ width: 250,
85
+ backgroundColor: 'transparent'
86
+ },
87
+
88
+ buttonWrapper: {
89
+ backgroundColor: 'transparent',
90
+ flexDirection: 'row',
91
+ position: 'absolute',
92
+ top: 0,
93
+ left: 0,
94
+ flex: 1,
95
+ paddingHorizontal: 10,
96
+ paddingVertical: 10,
97
+ justifyContent: 'space-between',
98
+ alignItems: 'center'
99
+ },
100
+
101
+ buttonText: {
102
+ fontSize: 50,
103
+ color: '#007aff'
104
+ }
105
+ };
106
+
107
+ // missing `module.exports = exports['default'];` with babel6
108
+ // export default React.createClass({
109
+ export default class Swiper extends Component {
110
+ /**
111
+ * Props Validation
112
+ * @type {Object}
113
+ */
114
+ static propTypes = {
115
+ horizontal: PropTypes.bool,
116
+ children: PropTypes.node.isRequired,
117
+ containerStyle: PropTypes.oneOfType([
118
+ PropTypes.object,
119
+ PropTypes.number,
120
+ ]),
121
+ style: PropTypes.oneOfType([
122
+ PropTypes.object,
123
+ PropTypes.number,
124
+ ]),
125
+ scrollViewStyle: PropTypes.oneOfType([
126
+ PropTypes.object,
127
+ PropTypes.number,
128
+ ]),
129
+ pagingEnabled: PropTypes.bool,
130
+ showsHorizontalScrollIndicator: PropTypes.bool,
131
+ showsVerticalScrollIndicator: PropTypes.bool,
132
+ bounces: PropTypes.bool,
133
+ scrollsToTop: PropTypes.bool,
134
+ removeClippedSubviews: PropTypes.bool,
135
+ automaticallyAdjustContentInsets: PropTypes.bool,
136
+ showsPagination: PropTypes.bool,
137
+ showsButtons: PropTypes.bool,
138
+ disableNextButton: PropTypes.bool,
139
+ loadMinimal: PropTypes.bool,
140
+ loadMinimalSize: PropTypes.number,
141
+ loadMinimalLoader: PropTypes.element,
142
+ loop: PropTypes.bool,
143
+ autoplay: PropTypes.bool,
144
+ autoplayTimeout: PropTypes.number,
145
+ autoplayDirection: PropTypes.bool,
146
+ index: PropTypes.number,
147
+ renderPagination: PropTypes.func,
148
+ dotStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
149
+ activeDotStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
150
+ dotColor: PropTypes.string,
151
+ activeDotColor: PropTypes.string,
152
+ /**
153
+ * Called when the index has changed because the user swiped.
154
+ */
155
+ onIndexChanged: PropTypes.func
156
+ }
157
+
158
+ /**
159
+ * Default props
160
+ * @return {object} props
161
+ * @see http://facebook.github.io/react-native/docs/scrollview.html
162
+ */
163
+ static defaultProps = {
164
+ horizontal: true,
165
+ pagingEnabled: true,
166
+ showsHorizontalScrollIndicator: false,
167
+ showsVerticalScrollIndicator: false,
168
+ bounces: false,
169
+ scrollsToTop: false,
170
+ removeClippedSubviews: true,
171
+ automaticallyAdjustContentInsets: false,
172
+ showsPagination: true,
173
+ showsButtons: false,
174
+ disableNextButton: false,
175
+ loop: true,
176
+ loadMinimal: false,
177
+ loadMinimalSize: 1,
178
+ autoplay: false,
179
+ autoplayTimeout: 2.5,
180
+ autoplayDirection: true,
181
+ index: 0,
182
+ onIndexChanged: () => null
183
+ }
184
+
185
+ /**
186
+ * Init states
187
+ * @return {object} states
188
+ */
189
+ state = this.initState(this.props)
190
+
191
+ /**
192
+ * Initial render flag
193
+ * @type {bool}
194
+ */
195
+ initialRender = true
196
+
197
+ /**
198
+ * autoplay timer
199
+ * @type {null}
200
+ */
201
+ autoplayTimer = null
202
+
203
+ loopJumpTimer = null
204
+
205
+ UNSAFE_componentWillReceiveProps(nextProps) {
206
+ if (!nextProps.autoplay && this.autoplayTimer) clearTimeout(this.autoplayTimer);
207
+ // Fix render last item first
208
+ if (nextProps.index === this.props.index) return;
209
+ this.setState(this.initState(nextProps, this.props.index !== nextProps.index));
210
+ }
211
+
212
+ componentDidMount() {
213
+ this.autoplay();
214
+ }
215
+
216
+ componentWillUnmount() {
217
+ this.autoplayTimer && clearTimeout(this.autoplayTimer);
218
+ this.loopJumpTimer && clearTimeout(this.loopJumpTimer);
219
+ }
220
+
221
+ UNSAFE_componentWillUpdate(nextProps, nextState) {
222
+ // If the index has changed, we notify the parent via the onIndexChanged callback
223
+ if (this.state.index !== nextState.index) this.props.onIndexChanged(nextState.index);
224
+ }
225
+
226
+ initState(props, updateIndex = false) {
227
+ // set the current state
228
+ const state = this.state || { width: 0, height: 0, offset: { x: 0, y: 0 } };
229
+
230
+ const initState = {
231
+ autoplayEnd: false,
232
+ loopJump: false,
233
+ offset: {}
234
+ };
235
+
236
+ initState.total = props.children ? props.children.length || 1 : 0;
237
+
238
+ if (state.total === initState.total && !updateIndex) {
239
+ // retain the index
240
+ initState.index = state.index;
241
+ } else {
242
+ initState.index = initState.total > 1 ? Math.min(props.index, initState.total - 1) : 0;
243
+ }
244
+
245
+ // Default: horizontal
246
+ const { width, height } = Dimensions.get('window');
247
+
248
+ initState.dir = props.horizontal === false ? 'y' : 'x';
249
+
250
+ if (props.width) {
251
+ initState.width = props.width;
252
+ } else if (this.state && this.state.width) {
253
+ initState.width = this.state.width;
254
+ } else {
255
+ initState.width = width;
256
+ }
257
+
258
+ if (props.height) {
259
+ initState.height = props.height;
260
+ } else if (this.state && this.state.height) {
261
+ initState.height = this.state.height;
262
+ } else {
263
+ initState.height = height;
264
+ }
265
+
266
+ initState.offset[initState.dir] = initState.dir === 'y'
267
+ ? height * props.index
268
+ : width * props.index;
269
+
270
+ this.internals = {
271
+ ...this.internals,
272
+ isScrolling: false
273
+ };
274
+ return initState;
275
+ }
276
+
277
+ // include internals with state
278
+ fullState() {
279
+ return { ...this.state, ...this.internals };
280
+ }
281
+
282
+ onLayout = (event) => {
283
+ const { width, height } = event.nativeEvent.layout;
284
+ const offset = this.internals.offset = {};
285
+ const state = { width, height };
286
+
287
+ if (this.state.total > 1) {
288
+ let setup = this.state.index;
289
+ if (this.props.loop) {
290
+ setup++;
291
+ }
292
+ offset[this.state.dir] = this.state.dir === 'y'
293
+ ? height * setup
294
+ : width * setup;
295
+ }
296
+
297
+ // only update the offset in state if needed, updating offset while swiping
298
+ // causes some bad jumping / stuttering
299
+ if (!this.state.offset || width !== this.state.width || height !== this.state.height) {
300
+ state.offset = offset;
301
+ }
302
+
303
+ // related to https://github.com/leecade/react-native-swiper/issues/570
304
+ // contentOffset is not working in react 0.48.x so we need to use scrollTo
305
+ // to emulate offset.
306
+ if (Platform.OS === 'ios') {
307
+ if (this.initialRender && this.state.total > 1) {
308
+ this.scrollView.scrollTo({ ...offset, animated: false });
309
+ this.initialRender = false;
310
+ }
311
+ }
312
+
313
+ this.setState(state);
314
+ }
315
+
316
+ loopJump = () => {
317
+ if (!this.state.loopJump) return;
318
+ const i = this.state.index + (this.props.loop ? 1 : 0);
319
+ const { scrollView } = this;
320
+ this.loopJumpTimer = setTimeout(() => scrollView.setPageWithoutAnimation
321
+ && scrollView.setPageWithoutAnimation(i), 50);
322
+ }
323
+
324
+ /**
325
+ * Automatic rolling
326
+ */
327
+ autoplay = () => {
328
+ if (!Array.isArray(this.props.children)
329
+ || !this.props.autoplay
330
+ || this.internals.isScrolling
331
+ || this.state.autoplayEnd) return;
332
+
333
+ this.autoplayTimer && clearTimeout(this.autoplayTimer);
334
+ this.autoplayTimer = setTimeout(() => {
335
+ if (!this.props.loop && (
336
+ this.props.autoplayDirection
337
+ ? this.state.index === this.state.total - 1
338
+ : this.state.index === 0
339
+ )
340
+ ) return this.setState({ autoplayEnd: true });
341
+
342
+ this.scrollBy(this.props.autoplayDirection ? 1 : -1);
343
+ }, this.props.autoplayTimeout * 1000);
344
+ }
345
+
346
+ /**
347
+ * Scroll begin handle
348
+ * @param {object} e native event
349
+ */
350
+ onScrollBegin = (e) => {
351
+ // update scroll state
352
+ this.internals.isScrolling = true;
353
+ this.props.onScrollBeginDrag && this.props.onScrollBeginDrag(e, this.fullState(), this);
354
+ }
355
+
356
+ /**
357
+ * Scroll end handle
358
+ * @param {object} e native event
359
+ */
360
+ onScrollEnd = (e) => {
361
+ // update scroll state
362
+ this.internals.isScrolling = false;
363
+
364
+ // making our events coming from android compatible to updateIndex logic
365
+ if (!e.nativeEvent.contentOffset) {
366
+ if (this.state.dir === 'x') {
367
+ e.nativeEvent.contentOffset = { x: e.nativeEvent.position * this.state.width };
368
+ } else {
369
+ e.nativeEvent.contentOffset = { y: e.nativeEvent.position * this.state.height };
370
+ }
371
+ }
372
+
373
+ this.updateIndex(e.nativeEvent.contentOffset, this.state.dir, () => {
374
+ this.autoplay();
375
+ this.loopJump();
376
+
377
+ // if `onMomentumScrollEnd` registered will be called here
378
+ this.props.onMomentumScrollEnd && this.props.onMomentumScrollEnd(e, this.fullState(), this);
379
+ });
380
+ }
381
+
382
+ /*
383
+ * Drag end handle
384
+ * @param {object} e native event
385
+ */
386
+ onScrollEndDrag = (e) => {
387
+ const { contentOffset } = e.nativeEvent;
388
+ const { horizontal, children } = this.props;
389
+ const { index } = this.state;
390
+ const { offset } = this.internals;
391
+ const previousOffset = horizontal ? offset.x : offset.y;
392
+ const newOffset = horizontal ? contentOffset.x : contentOffset.y;
393
+
394
+ if (previousOffset === newOffset
395
+ && (index === 0 || index === children.length - 1)) {
396
+ this.internals.isScrolling = false;
397
+ }
398
+ }
399
+
400
+ /**
401
+ * Update index after scroll
402
+ * @param {object} offset content offset
403
+ * @param {string} dir 'x' || 'y'
404
+ */
405
+ updateIndex = (offset, dir, cb) => {
406
+ const { state } = this;
407
+ let { index } = state;
408
+ if (!this.internals.offset) // Android not setting this onLayout first? https://github.com/leecade/react-native-swiper/issues/582
409
+ { this.internals.offset = {}; }
410
+ const diff = offset[dir] - this.internals.offset[dir];
411
+ const step = dir === 'x' ? state.width : state.height;
412
+ let loopJump = false;
413
+
414
+ // Do nothing if offset no change.
415
+ if (!diff) return;
416
+
417
+ // Note: if touch very very quickly and continuous,
418
+ // the variation of `index` more than 1.
419
+ // parseInt() ensures it's always an integer
420
+ index = parseInt(index + Math.round(diff / step));
421
+
422
+ if (this.props.loop) {
423
+ if (index <= -1) {
424
+ index = state.total - 1;
425
+ offset[dir] = step * state.total;
426
+ loopJump = true;
427
+ } else if (index >= state.total) {
428
+ index = 0;
429
+ offset[dir] = step;
430
+ loopJump = true;
431
+ }
432
+ }
433
+
434
+ const newState = {};
435
+ newState.index = index;
436
+ newState.loopJump = loopJump;
437
+
438
+ this.internals.offset = offset;
439
+
440
+ // only update offset in state if loopJump is true
441
+ if (loopJump) {
442
+ // when swiping to the beginning of a looping set for the third time,
443
+ // the new offset will be the same as the last one set in state.
444
+ // Setting the offset to the same thing will not do anything,
445
+ // so we increment it by 1 then immediately set it to what it should be,
446
+ // after render.
447
+ if (offset[dir] === this.internals.offset[dir]) {
448
+ newState.offset = { x: 0, y: 0 };
449
+ newState.offset[dir] = offset[dir] + 1;
450
+ this.setState(newState, () => {
451
+ this.setState({ offset }, cb);
452
+ });
453
+ } else {
454
+ newState.offset = offset;
455
+ this.setState(newState, cb);
456
+ }
457
+ } else {
458
+ this.setState(newState, cb);
459
+ }
460
+ }
461
+
462
+ /**
463
+ * Scroll by index
464
+ * @param {number} index offset index
465
+ * @param {bool} animated
466
+ */
467
+
468
+ scrollBy = (index, animated = true) => {
469
+ if (this.internals.isScrolling || this.state.total < 2) return;
470
+ const { state } = this;
471
+ const diff = (this.props.loop ? 1 : 0) + index + this.state.index;
472
+ let x = 0;
473
+ let y = 0;
474
+ if (state.dir === 'x') x = diff * state.width;
475
+ if (state.dir === 'y') y = diff * state.height;
476
+
477
+ if (Platform.OS !== 'ios') {
478
+ this.scrollView && this.scrollView[animated ? 'setPage' : 'setPageWithoutAnimation'](diff);
479
+ } else {
480
+ this.scrollView && this.scrollView.scrollTo({ x, y, animated });
481
+ }
482
+
483
+ // update scroll state
484
+ this.internals.isScrolling = true;
485
+ this.setState({
486
+ autoplayEnd: false
487
+ });
488
+
489
+ // trigger onScrollEnd manually in android
490
+ if (!animated || Platform.OS !== 'ios') {
491
+ setImmediate(() => {
492
+ this.onScrollEnd({
493
+ nativeEvent: {
494
+ position: diff
495
+ }
496
+ });
497
+ });
498
+ }
499
+ }
500
+
501
+ scrollViewPropOverrides = () => {
502
+ const { props } = this;
503
+ const overrides = {};
504
+
505
+ /*
506
+ const scrollResponders = [
507
+ 'onMomentumScrollBegin',
508
+ 'onTouchStartCapture',
509
+ 'onTouchStart',
510
+ 'onTouchEnd',
511
+ 'onResponderRelease',
512
+ ]
513
+ */
514
+
515
+ for (const prop in props) {
516
+ // if(~scrollResponders.indexOf(prop)
517
+ if (typeof props[prop] === 'function'
518
+ && prop !== 'onMomentumScrollEnd'
519
+ && prop !== 'renderPagination'
520
+ && prop !== 'onScrollBeginDrag'
521
+ ) {
522
+ const originResponder = props[prop];
523
+ overrides[prop] = (e) => originResponder(e, this.fullState(), this);
524
+ }
525
+ }
526
+
527
+ return overrides;
528
+ }
529
+
530
+ /**
531
+ * Render pagination
532
+ * @return {object} react-dom
533
+ */
534
+ renderPagination = () => {
535
+ // By default, dots only show when `total` >= 2
536
+ if (this.state.total <= 1) return null;
537
+
538
+ const dots = [];
539
+ const ActiveDot = this.props.activeDot || (
540
+ <View style={[{
541
+ backgroundColor: this.props.activeDotColor || '#007aff',
542
+ width: 8,
543
+ height: 8,
544
+ borderRadius: 4,
545
+ marginLeft: 3,
546
+ marginRight: 3,
547
+ marginTop: 3,
548
+ marginBottom: 3
549
+ }, this.props.activeDotStyle]}
550
+ />
551
+ );
552
+ const Dot = this.props.dot || (
553
+ <View style={[{
554
+ backgroundColor: this.props.dotColor || 'rgba(0,0,0,.2)',
555
+ width: 8,
556
+ height: 8,
557
+ borderRadius: 4,
558
+ marginLeft: 3,
559
+ marginRight: 3,
560
+ marginTop: 3,
561
+ marginBottom: 3
562
+ }, this.props.dotStyle]}
563
+ />
564
+ );
565
+ for (let i = 0; i < this.state.total; i++) {
566
+ dots.push(i === this.state.index
567
+ ? React.cloneElement(ActiveDot, { key: i })
568
+ : React.cloneElement(Dot, { key: i })
569
+ );
570
+ }
571
+
572
+ return (
573
+ <View pointerEvents="none" style={[styles[`pagination_${this.state.dir}`], this.props.paginationStyle]}>
574
+ {dots}
575
+ </View>
576
+ );
577
+ }
578
+
579
+ renderTitle = () => {
580
+ const child = this.props.children[this.state.index];
581
+ const title = child && child.props && child.props.title;
582
+ return title
583
+ ? (
584
+ <View style={styles.title}>
585
+ {this.props.children[this.state.index].props.title}
586
+ </View>
587
+ )
588
+ : null;
589
+ }
590
+
591
+ renderNextButton = () => {
592
+ let button = null;
593
+
594
+ if (this.props.loop
595
+ || this.state.index !== this.state.total - 1) {
596
+ button = this.props.nextButton || <Text style={styles.buttonText}>›</Text>;
597
+ }
598
+
599
+ return (
600
+ <TouchableOpacity
601
+ onPress={() => button !== null && this.scrollBy(1)}
602
+ disabled={this.props.disableNextButton}
603
+ >
604
+ <View>
605
+ {button}
606
+ </View>
607
+ </TouchableOpacity>
608
+ );
609
+ }
610
+
611
+ renderPrevButton = () => {
612
+ let button = null;
613
+
614
+ if (this.props.loop || this.state.index !== 0) {
615
+ button = this.props.prevButton || <Text style={styles.buttonText}>‹</Text>;
616
+ }
617
+
618
+ return (
619
+ <TouchableOpacity onPress={() => button !== null && this.scrollBy(-1)}>
620
+ <View>
621
+ {button}
622
+ </View>
623
+ </TouchableOpacity>
624
+ );
625
+ }
626
+
627
+ renderButtons = () => (
628
+ <View
629
+ pointerEvents="box-none"
630
+ style={[styles.buttonWrapper, {
631
+ width: this.state.width,
632
+ height: this.state.height
633
+ }, this.props.buttonWrapperStyle]}
634
+ >
635
+ {this.renderPrevButton()}
636
+ {this.renderNextButton()}
637
+ </View>
638
+ )
639
+
640
+ refScrollView = (view) => {
641
+ this.scrollView = view;
642
+ }
643
+
644
+ onPageScrollStateChanged = (state) => {
645
+ switch (state) {
646
+ case 'dragging':
647
+ return this.onScrollBegin();
648
+
649
+ case 'idle':
650
+ case 'settling':
651
+ if (this.props.onTouchEnd) this.props.onTouchEnd();
652
+ }
653
+ }
654
+
655
+ renderScrollView = (pages) => {
656
+ if (Platform.OS === 'ios') {
657
+ return (
658
+ <ScrollView
659
+ ref={this.refScrollView}
660
+ {...this.props}
661
+ {...this.scrollViewPropOverrides()}
662
+ contentContainerStyle={[styles.wrapperIOS, this.props.style]}
663
+ contentOffset={this.state.offset}
664
+ onScrollBeginDrag={this.onScrollBegin}
665
+ onMomentumScrollEnd={this.onScrollEnd}
666
+ onScrollEndDrag={this.onScrollEndDrag}
667
+ style={this.props.scrollViewStyle}
668
+ >
669
+ {pages}
670
+ </ScrollView>
671
+ );
672
+ }
673
+ return (
674
+ <ViewPagerAndroid
675
+ ref={this.refScrollView}
676
+ {...this.props}
677
+ initialPage={this.props.loop ? this.state.index + 1 : this.state.index}
678
+ onPageScrollStateChanged={this.onPageScrollStateChanged}
679
+ onPageSelected={this.onScrollEnd}
680
+ key={pages.length}
681
+ style={[styles.wrapperAndroid, this.props.style]}
682
+ >
683
+ {pages}
684
+ </ViewPagerAndroid>
685
+ );
686
+ }
687
+
688
+ checkPagesBeforeAfter = (children) => {
689
+ let str = '';
690
+ if (children && Array.isArray(children)) {
691
+ for (const child in children) {
692
+ str += children[child].key || child;
693
+ }
694
+ }
695
+ return str;
696
+ };
697
+
698
+ /**
699
+ * Default render
700
+ * @return {object} react-dom
701
+ */
702
+ render() {
703
+ const {
704
+ index,
705
+ total,
706
+ width,
707
+ height
708
+ } = this.state;
709
+ const {
710
+ children,
711
+ containerStyle,
712
+ loop,
713
+ loadMinimal,
714
+ loadMinimalSize,
715
+ loadMinimalLoader,
716
+ renderPagination,
717
+ showsButtons,
718
+ showsPagination,
719
+ } = this.props;
720
+ // let dir = state.dir
721
+ // let key = 0
722
+ const loopVal = loop ? 1 : 0;
723
+ let pages = [];
724
+
725
+ const pageStyle = [{ width, height }, styles.slide];
726
+ const pageStyleLoading = {
727
+ width,
728
+ height,
729
+ flex: 1,
730
+ justifyContent: 'center',
731
+ alignItems: 'center'
732
+ };
733
+
734
+ // For make infinite at least total > 1
735
+ if (total > 1) {
736
+ // Re-design a loop model for avoid img flickering
737
+ pages = Object.keys(children);
738
+ // console.log(`checkPagesBeforeAfter children: ${JSON.stringify(this.checkPagesBeforeAfter(pages))}`);
739
+
740
+ if (loop) {
741
+ pages.unshift(`${total - 1}`);
742
+ pages.push('0');
743
+ }
744
+
745
+ pages = pages.map((page, i) => {
746
+ if (loadMinimal) {
747
+ if (i >= (index + loopVal - loadMinimalSize)
748
+ && i <= (index + loopVal + loadMinimalSize)) {
749
+ return <View style={pageStyle} key={i}>{children[page]}</View>;
750
+ }
751
+ return (
752
+ <View style={pageStyleLoading} key={i}>
753
+ {loadMinimalLoader || <ActivityIndicator />}
754
+ </View>
755
+ );
756
+ }
757
+ return <View style={pageStyle} key={i}>{children[page]}</View>;
758
+ });
759
+ } else {
760
+ pages = <View style={pageStyle} key={0}>{children}</View>;
761
+ }
762
+
763
+ return (
764
+ <View style={[styles.container, containerStyle]} onLayout={this.onLayout}>
765
+ {this.renderScrollView(pages)}
766
+ {showsPagination && (renderPagination
767
+ ? renderPagination(index, total, this)
768
+ : this.renderPagination())}
769
+ {this.renderTitle()}
770
+ {showsButtons && this.renderButtons()}
771
+ </View>
772
+ );
773
+ }
774
+ }
package/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import SwipeAction from './SwipeAction';
2
2
  import SwipeActionList from './SwipeActionList';
3
+ import Swiper from './Swiper';
3
4
 
4
5
  export {
5
- SwipeAction, SwipeActionList
6
+ SwipeAction, SwipeActionList, Swiper
6
7
  };
package/package.json CHANGED
@@ -1,16 +1,15 @@
1
1
  {
2
- "name": "@momo-kits/swipe",
3
- "version": "0.0.4-beta",
4
- "private": false,
5
- "main": "index.js",
6
- "dependencies": {},
7
- "peerDependencies": {
8
- "prop-types": "^15.7.2",
9
- "react": "16.9.0",
10
- "react-native": ">=0.55",
11
- "@momo-kits/core": ">=0.0.5-beta"
12
- },
13
- "devDependencies": {},
14
- "license": "MOMO"
15
- }
16
-
2
+ "name": "@momo-kits/swipe",
3
+ "version": "0.0.4",
4
+ "private": false,
5
+ "main": "index.js",
6
+ "dependencies": {},
7
+ "peerDependencies": {
8
+ "prop-types": "^15.7.2",
9
+ "react": "^16.9.0",
10
+ "react-native": ">=0.55",
11
+ "@momo-kits/core": ">=0.0.5-beta"
12
+ },
13
+ "devDependencies": {},
14
+ "license": "MoMo"
15
+ }
package/publish.sh CHANGED
@@ -12,7 +12,7 @@ echo VERSION: $VERSION
12
12
  rsync -r --verbose --exclude '*.mdx' --exclude '*Demo.js' --exclude 'props-type.js' --exclude 'prop-types.js' ./* dist
13
13
 
14
14
  # #babel component to dist
15
- babel ./dist -d dist --copy-files
15
+ #babel ./dist -d dist --copy-files
16
16
 
17
17
  #copy option
18
18
  #cp -r ./src/ dist