@momo-kits/slider 0.77.2 → 0.77.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/Slider.web.js DELETED
@@ -1,761 +0,0 @@
1
- import React, {Component} from 'react';
2
- import PropTypes from 'prop-types';
3
- import {StyleSheet, PanResponder, View, I18nManager} from 'react-native';
4
- import {get} from 'lodash';
5
- import DefaultMarker from './DefaultMarker';
6
- import {createArray, valueToPosition, positionToValue} from './converters';
7
- import Colors from '../../core-v2/colors';
8
- import Text from '../../core-v2/components/typography';
9
- import LocalizedStrings from '../../core-v2/components/language/Language';
10
- import Spacing from '../../core-v2/spacing';
11
-
12
- const LANGUAGE = LocalizedStrings.getLanguage();
13
-
14
- export default class Slider extends Component {
15
- constructor(props) {
16
- super(props);
17
- const {optionsArray, min, max, step, length, values} = this.props;
18
- this.optionsArray = optionsArray || createArray(min, max, step);
19
- const defaultSliderLength = length;
20
- this.stepLength = defaultSliderLength / this.optionsArray.length;
21
- const initialValues = values.map(value =>
22
- valueToPosition(value, this.optionsArray, defaultSliderLength),
23
- );
24
- this.state = {
25
- valueOne: values[0],
26
- valueTwo: values[1],
27
- pastOne: initialValues[0],
28
- pastTwo: initialValues[1],
29
- positionOne: initialValues[0],
30
- positionTwo: initialValues[1],
31
- sliderLength: defaultSliderLength,
32
- };
33
- this.subscribePanResponder();
34
- }
35
-
36
- subscribePanResponder = () => {
37
- const customPanResponder = (start, move, end) =>
38
- PanResponder.create({
39
- onStartShouldSetPanResponder: () => true,
40
- onStartShouldSetPanResponderCapture: () => true,
41
- onMoveShouldSetPanResponder: () => true,
42
- onMoveShouldSetPanResponderCapture: () => true,
43
- onPanResponderGrant: () => start(),
44
- onPanResponderMove: (evt, gestureState) => move(gestureState),
45
- onPanResponderTerminationRequest: () => false,
46
- onPanResponderRelease: (evt, gestureState) => end(gestureState),
47
- onPanResponderTerminate: (evt, gestureState) => end(gestureState),
48
- onShouldBlockNativeResponder: () => true,
49
- });
50
-
51
- this._panResponderBetween = customPanResponder(
52
- gestureState => {
53
- this.startOne(gestureState);
54
- this.startTwo(gestureState);
55
- },
56
- gestureState => {
57
- this.moveOne(gestureState);
58
- this.moveTwo(gestureState);
59
- },
60
- gestureState => {
61
- this.endOne(gestureState);
62
- this.endTwo(gestureState);
63
- },
64
- );
65
-
66
- this._panResponderOne = customPanResponder(
67
- this.startOne,
68
- this.moveOne,
69
- this.endOne,
70
- );
71
- this._panResponderTwo = customPanResponder(
72
- this.startTwo,
73
- this.moveTwo,
74
- this.endTwo,
75
- );
76
- };
77
-
78
- startOne = () => {
79
- const {enabledOne, onChangeStart} = this.props;
80
- const {onePressed} = this.state;
81
- if (enabledOne) {
82
- onChangeStart();
83
- this.setState({
84
- onePressed: !onePressed,
85
- });
86
- }
87
- };
88
-
89
- startTwo = () => {
90
- const {enabledTwo, onChangeStart} = this.props;
91
- const {twoPressed} = this.state;
92
- if (enabledTwo) {
93
- onChangeStart();
94
- this.setState({
95
- twoPressed: !twoPressed,
96
- });
97
- }
98
- };
99
-
100
- moveOne = gestureState => {
101
- const {
102
- enabledOne,
103
- allowOverlap,
104
- minMarkerOverlapDistance,
105
- touchDimensions,
106
- snapped,
107
- onChange,
108
- onMarkersPosition,
109
- allowRange = [],
110
- min,
111
- max,
112
- } = this.props;
113
- const {pastOne, positionTwo, valueOne, valueTwo, sliderLength} = this.state;
114
- if (!enabledOne) {
115
- return;
116
- }
117
-
118
- const accumDistance = gestureState.dx;
119
- const accumDistanceDisplacement = gestureState.dy;
120
-
121
- const unconfined = I18nManager.isRTL
122
- ? pastOne - accumDistance
123
- : accumDistance + pastOne;
124
- const bottom = 0;
125
- const trueTop =
126
- positionTwo -
127
- (allowOverlap
128
- ? 0
129
- : minMarkerOverlapDistance > 0
130
- ? minMarkerOverlapDistance
131
- : this.stepLength);
132
- const top = trueTop === 0 ? 0 : trueTop || sliderLength;
133
- const confined =
134
- unconfined < bottom ? bottom : unconfined > top ? top : unconfined;
135
- const {slipDisplacement} = touchDimensions;
136
-
137
- if (
138
- Math.abs(accumDistanceDisplacement) < slipDisplacement ||
139
- !slipDisplacement
140
- ) {
141
- const value = positionToValue(confined, this.optionsArray, sliderLength);
142
-
143
- if (allowRange?.length > 0 && value < get(allowRange, '[0]', min)) {
144
- return;
145
- }
146
- if (allowRange?.length > 1 && value > get(allowRange, '[1]', max)) {
147
- return;
148
- }
149
-
150
- const snappedValue = valueToPosition(
151
- value,
152
- this.optionsArray,
153
- sliderLength,
154
- );
155
-
156
- this.setState({
157
- positionOne: snapped ? snappedValue : confined,
158
- });
159
-
160
- if (value !== valueOne) {
161
- this.setState(
162
- {
163
- valueOne: value,
164
- },
165
- () => {
166
- const {valueOne: newValueOne, positionOne: newPositionOne} =
167
- this.state;
168
- const change = [newValueOne];
169
- if (valueTwo) {
170
- change.push(valueTwo);
171
- }
172
- onChange(change);
173
-
174
- onMarkersPosition([newPositionOne, positionTwo]);
175
- },
176
- );
177
- }
178
- }
179
- };
180
-
181
- moveTwo = gestureState => {
182
- const {
183
- enabledTwo,
184
- allowOverlap,
185
- minMarkerOverlapDistance,
186
- // sliderLength,
187
- touchDimensions,
188
- snapped,
189
- onChange,
190
- onMarkersPosition,
191
- } = this.props;
192
- const {pastTwo, positionOne, sliderLength, valueTwo, valueOne} = this.state;
193
- if (!enabledTwo) {
194
- return;
195
- }
196
-
197
- const accumDistance = gestureState.dx;
198
- const accumDistanceDisplacement = gestureState.dy;
199
-
200
- const unconfined = I18nManager.isRTL
201
- ? pastTwo - accumDistance
202
- : accumDistance + pastTwo;
203
- const bottom =
204
- positionOne +
205
- (allowOverlap
206
- ? 0
207
- : minMarkerOverlapDistance > 0
208
- ? minMarkerOverlapDistance
209
- : this.stepLength);
210
- const top = sliderLength;
211
- const confined =
212
- unconfined < bottom ? bottom : unconfined > top ? top : unconfined;
213
- const {slipDisplacement} = touchDimensions;
214
-
215
- if (
216
- Math.abs(accumDistanceDisplacement) < slipDisplacement ||
217
- !slipDisplacement
218
- ) {
219
- const value = positionToValue(confined, this.optionsArray, sliderLength);
220
-
221
- const snappedValue = valueToPosition(
222
- value,
223
- this.optionsArray,
224
- sliderLength,
225
- );
226
-
227
- this.setState({
228
- positionTwo: snapped ? snappedValue : confined,
229
- });
230
-
231
- if (value !== valueTwo) {
232
- this.setState(
233
- {
234
- valueTwo: value,
235
- },
236
- () => {
237
- const {valueTwo: newValueTwo, positionTwo: newPositionTwo} =
238
- this.state;
239
- onChange([valueOne, newValueTwo]);
240
-
241
- onMarkersPosition([positionOne, newPositionTwo]);
242
- },
243
- );
244
- }
245
- }
246
- };
247
-
248
- endOne = gestureState => {
249
- const {onToggleOne, onChangeFinish} = this.props;
250
- const {positionOne, onePressed, valueOne, valueTwo} = this.state;
251
- if (gestureState.moveX === 0 && onToggleOne) {
252
- onToggleOne();
253
- return;
254
- }
255
-
256
- this.setState(
257
- {
258
- pastOne: positionOne,
259
- onePressed: !onePressed,
260
- },
261
- () => {
262
- const change = [valueOne];
263
- if (valueTwo) {
264
- change.push(valueTwo);
265
- }
266
- onChangeFinish(change);
267
- },
268
- );
269
- };
270
-
271
- endTwo = gestureState => {
272
- const {onToggleTwo, onChangeFinish} = this.props;
273
- const {twoPressed, positionTwo, valueOne, valueTwo} = this.state;
274
- if (gestureState.moveX === 0 && onToggleTwo) {
275
- onToggleTwo();
276
- return;
277
- }
278
-
279
- this.setState(
280
- {
281
- twoPressed: !twoPressed,
282
- pastTwo: positionTwo,
283
- },
284
- () => {
285
- onChangeFinish([valueOne, valueTwo]);
286
- },
287
- );
288
- };
289
-
290
- componentDidUpdate(prevProps, prevState) {
291
- const {positionOne: prevPositionOne, positionTwo: prevPositionTwo} =
292
- prevState;
293
-
294
- const {positionOne, positionTwo, onePressed, twoPressed, sliderLength} =
295
- this.state;
296
- const {onMarkersPosition, min, max, step, values, optionsArray} =
297
- this.props;
298
-
299
- if (
300
- typeof positionOne === 'undefined' &&
301
- typeof positionTwo !== 'undefined'
302
- ) {
303
- return;
304
- }
305
-
306
- if (positionOne !== prevPositionOne || positionTwo !== prevPositionTwo) {
307
- onMarkersPosition([positionOne, positionTwo]);
308
- }
309
-
310
- if (onePressed || twoPressed) {
311
- return;
312
- }
313
-
314
- const nextState = {};
315
- if (
316
- prevProps.min !== min ||
317
- prevProps.max !== max ||
318
- prevProps.step !== step ||
319
- prevProps.values[0] !== values[0] ||
320
- prevState.sliderLength !== sliderLength ||
321
- prevProps.values[1] !== values[1] ||
322
- (prevState.sliderLength !== sliderLength && prevProps.values[1])
323
- ) {
324
- this.optionsArray = optionsArray || createArray(min, max, step);
325
-
326
- this.stepLength = sliderLength / this.optionsArray.length;
327
-
328
- const positionOneValue = valueToPosition(
329
- values[0],
330
- this.optionsArray,
331
- sliderLength,
332
- );
333
- // eslint-disable-next-line prefer-destructuring
334
- nextState.valueOne = values[0];
335
- nextState.pastOne = positionOneValue;
336
- nextState.positionOne = positionOneValue;
337
-
338
- const positionTwoValue = valueToPosition(
339
- values[1],
340
- this.optionsArray,
341
- sliderLength,
342
- );
343
- // eslint-disable-next-line prefer-destructuring
344
- nextState.valueTwo = values[1];
345
- nextState.pastTwo = positionTwoValue;
346
- nextState.positionTwo = positionTwoValue;
347
-
348
- // eslint-disable-next-line react/no-did-update-set-state
349
- this.setState(nextState);
350
- }
351
- }
352
-
353
- onContentLayout(e) {
354
- const {length} = this.props;
355
- if (!length) {
356
- const layoutLength = e.nativeEvent.layout.width;
357
- this.setState({
358
- sliderLength: layoutLength,
359
- });
360
- }
361
- }
362
-
363
- _nFormatter(num) {
364
- let markerLabel = num;
365
- let digits = 0;
366
-
367
- if (markerLabel >= 1000000) {
368
- digits = 1;
369
- }
370
-
371
- const lookup = [
372
- {
373
- value: 1000000,
374
- symbol: LANGUAGE == 'en' ? 'M' : 'Tr',
375
- },
376
- {
377
- value: 1000,
378
- symbol: 'K',
379
- },
380
- {
381
- value: 1,
382
- symbol: '',
383
- },
384
- ];
385
-
386
- let item = lookup.slice().find(item => {
387
- return markerLabel >= item.value;
388
- });
389
-
390
- if (item) {
391
- markerLabel = (markerLabel / item.value).toFixed(digits) + item.symbol;
392
- } else {
393
- markerLabel = '0';
394
- }
395
-
396
- return markerLabel;
397
- }
398
-
399
- render() {
400
- const {
401
- positionOne,
402
- positionTwo,
403
- onePressed,
404
- valueOne,
405
- twoPressed,
406
- valueTwo,
407
- sliderLength,
408
- } = this.state;
409
- const {
410
- style,
411
- markerOffsetX,
412
- markerOffsetY,
413
- values,
414
- isMarkersSeparated = false,
415
- touchDimensions,
416
- containerStyle,
417
- markerContainerStyle,
418
- enabledOne,
419
- enabledTwo,
420
- valuePrefix,
421
- valueSuffix,
422
- enableLabel = true,
423
- activeColor,
424
- inactiveColor,
425
- } = this.props;
426
- const twoMarkers = values.length === 2; // when allowOverlap, positionTwo could be 0, identified as string '0' and throwing 'RawText 0 needs to be wrapped in <Text>' error
427
-
428
- const trackOneLength = positionOne;
429
- const trackOneStyle = styles.selectedTrack;
430
- const trackThreeLength = twoMarkers ? sliderLength - positionTwo : 0;
431
- const trackTwoLength = sliderLength - trackOneLength - trackThreeLength;
432
- const trackTwoStyle = styles.selectedTrack;
433
-
434
- const Marker = DefaultMarker;
435
-
436
- const MarkerLeft = DefaultMarker;
437
- const MarkerRight = DefaultMarker;
438
- const {borderRadius} = touchDimensions;
439
- const touchStyle = {
440
- borderRadius: borderRadius || 0,
441
- };
442
-
443
- const markerContainerOne = {
444
- top: markerOffsetY - 24,
445
- left: trackOneLength + markerOffsetX - 32,
446
- };
447
-
448
- const markerContainerTwo = {
449
- top: markerOffsetY - 24,
450
- right: trackThreeLength - markerOffsetX - 32,
451
- };
452
-
453
- const newContainerStyle = [styles.container, containerStyle];
454
-
455
- const markerLabel1 = this._nFormatter(valueOne);
456
- const markerLabel2 = this._nFormatter(valueTwo);
457
-
458
- const body = (
459
- <View style={{alignItems: 'center'}}>
460
- <View style={[styles.fullTrack, {width: sliderLength}]}>
461
- <View
462
- style={[
463
- styles.track,
464
- trackOneStyle,
465
- {
466
- width: trackOneLength,
467
- backgroundColor: twoMarkers ? inactiveColor : activeColor,
468
- },
469
- !enabledOne && !twoMarkers && styles.disabledTrack,
470
- ]}
471
- />
472
- <View
473
- style={[
474
- styles.track,
475
- trackTwoStyle,
476
- {
477
- width: trackTwoLength,
478
- backgroundColor: twoMarkers ? activeColor : inactiveColor,
479
- },
480
- !enabledOne && !enabledTwo && styles.disabledTrack,
481
- ]}
482
- {...(twoMarkers ? this._panResponderBetween.panHandlers : {})}
483
- />
484
- {twoMarkers && (
485
- <View
486
- style={[
487
- styles.track,
488
- {
489
- width: trackThreeLength,
490
- backgroundColor: inactiveColor,
491
- },
492
- ]}
493
- />
494
- )}
495
- <View
496
- style={[
497
- styles.markerContainer,
498
- markerContainerOne,
499
- markerContainerStyle,
500
- positionOne > sliderLength / 2 && styles.topMarkerContainer,
501
- ]}>
502
- <View
503
- style={[styles.touch, touchStyle]}
504
- ref={component => (this._markerOne = component)}
505
- {...this._panResponderOne.panHandlers}>
506
- {isMarkersSeparated === false ? (
507
- <>
508
- {onePressed && enableLabel && enabledOne && (
509
- <View
510
- style={[
511
- styles.valueContainer,
512
- {
513
- shadowColor: Colors.black_17,
514
- shadowOffset: {
515
- width: 2,
516
- height: 2,
517
- },
518
- shadowOpacity: 0.07,
519
- shadowRadius: 10,
520
- },
521
- ]}>
522
- <Text.Label3>{markerLabel1}</Text.Label3>
523
- </View>
524
- )}
525
- <Marker
526
- activeColor={activeColor}
527
- enabled={enabledOne}
528
- pressed={onePressed}
529
- currentValue={valueOne}
530
- valuePrefix={valuePrefix}
531
- valueSuffix={valueSuffix}
532
- />
533
- </>
534
- ) : (
535
- <>
536
- {onePressed && enableLabel && enabledOne && (
537
- <View
538
- style={[
539
- styles.valueContainer,
540
- {
541
- shadowColor: Colors.black_17,
542
- shadowOffset: {
543
- width: 2,
544
- height: 2,
545
- },
546
- shadowOpacity: 0.07,
547
- shadowRadius: 10,
548
- },
549
- ]}>
550
- <Text.Label3>{markerLabel1}</Text.Label3>
551
- </View>
552
- )}
553
- <MarkerLeft
554
- activeColor={activeColor}
555
- enabled={enabledOne}
556
- pressed={onePressed}
557
- currentValue={valueOne}
558
- valuePrefix={valuePrefix}
559
- valueSuffix={valueSuffix}
560
- />
561
- </>
562
- )}
563
- </View>
564
- </View>
565
- {twoMarkers && positionOne !== sliderLength && (
566
- <View
567
- style={[
568
- styles.markerContainer,
569
- markerContainerTwo,
570
- markerContainerStyle,
571
- ]}>
572
- <View
573
- style={[styles.touch, touchStyle]}
574
- ref={component => (this._markerTwo = component)}
575
- {...this._panResponderTwo.panHandlers}>
576
- {isMarkersSeparated === false ? (
577
- <>
578
- {twoPressed && enableLabel && enabledTwo && (
579
- <View
580
- style={[
581
- styles.valueContainer,
582
- {
583
- shadowColor: Colors.black_17,
584
- shadowOffset: {
585
- width: 2,
586
- height: 2,
587
- },
588
- shadowOpacity: 0.07,
589
- shadowRadius: 10,
590
- },
591
- ]}>
592
- <Text.Label3>{markerLabel2}</Text.Label3>
593
- </View>
594
- )}
595
- <Marker
596
- activeColor={activeColor}
597
- pressed={twoPressed}
598
- currentValue={valueTwo}
599
- enabled={enabledTwo}
600
- valuePrefix={valuePrefix}
601
- valueSuffix={valueSuffix}
602
- />
603
- </>
604
- ) : (
605
- <>
606
- {twoPressed && enableLabel && enabledTwo && (
607
- <View
608
- style={[
609
- styles.valueContainer,
610
- {
611
- shadowColor: Colors.black_17,
612
- shadowOffset: {
613
- width: 2,
614
- height: 2,
615
- },
616
- shadowOpacity: 0.07,
617
- shadowRadius: 10,
618
- },
619
- ]}>
620
- <Text.Label3>{markerLabel2}</Text.Label3>
621
- </View>
622
- )}
623
- <MarkerRight
624
- activeColor={activeColor}
625
- pressed={twoPressed}
626
- currentValue={valueTwo}
627
- enabled={enabledTwo}
628
- valuePrefix={valuePrefix}
629
- valueSuffix={valueSuffix}
630
- />
631
- </>
632
- )}
633
- </View>
634
- </View>
635
- )}
636
- </View>
637
- </View>
638
- );
639
-
640
- return (
641
- <View style={style} onLayout={e => this.onContentLayout(e)}>
642
- <View style={newContainerStyle}>{body}</View>
643
- </View>
644
- );
645
- }
646
- }
647
-
648
- const styles = StyleSheet.create({
649
- container: {
650
- position: 'relative',
651
- justifyContent: 'center',
652
- minHeight: 48,
653
- },
654
- fullTrack: {
655
- flexDirection: 'row',
656
- },
657
- track: {
658
- height: 4,
659
- backgroundColor: Colors.background_default,
660
- borderRadius: 2,
661
- },
662
- selectedTrack: {
663
- backgroundColor: Colors.pink_03,
664
- },
665
- markerContainer: {
666
- position: 'absolute',
667
- width: 64,
668
- height: 52,
669
- backgroundColor: 'transparent',
670
- justifyContent: 'center',
671
- alignItems: 'center',
672
- },
673
- topMarkerContainer: {
674
- zIndex: 1,
675
- },
676
- touch: {
677
- backgroundColor: 'transparent',
678
- justifyContent: 'center',
679
- alignItems: 'center',
680
- alignSelf: 'stretch',
681
- },
682
- full: {
683
- width: '100%',
684
- height: '100%',
685
- },
686
- valueContainer: {
687
- height: 24,
688
- borderRadius: Spacing.XS,
689
- backgroundColor: Colors.white,
690
- justifyContent: 'center',
691
- alignItems: 'center',
692
- position: 'absolute',
693
- top: -28,
694
- paddingVertical: Spacing.XS,
695
- paddingHorizontal: Spacing.S,
696
- },
697
- disabledTrack: {
698
- backgroundColor: Colors.black_08,
699
- },
700
- });
701
-
702
- Slider.defaultProps = {
703
- values: [0],
704
- onChangeStart: () => {},
705
- onChange: () => {},
706
- onChangeFinish: () => {},
707
- onMarkersPosition: () => {},
708
- step: 1,
709
- min: 0,
710
- max: 10,
711
- touchDimensions: {
712
- height: 50,
713
- width: 50,
714
- borderRadius: 15,
715
- slipDisplacement: 200,
716
- },
717
- markerOffsetX: 0,
718
- markerOffsetY: 0,
719
- onToggleOne: undefined,
720
- onToggleTwo: undefined,
721
- enabledOne: true,
722
- enabledTwo: true,
723
- allowOverlap: false,
724
- snapped: false,
725
- minMarkerOverlapDistance: 0,
726
- length: 280,
727
- activeColor: Colors.pink_03,
728
- inactiveColor: Colors.black_03,
729
- };
730
-
731
- Slider.propTypes = {
732
- activeColor: PropTypes.string,
733
- inactiveColor: PropTypes.string,
734
- style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
735
- markerOffsetX: PropTypes.number,
736
- markerOffsetY: PropTypes.number,
737
- values: PropTypes.arrayOf(PropTypes.number),
738
- isMarkersSeparated: PropTypes.bool,
739
- touchDimensions: PropTypes.object,
740
- containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
741
- markerContainerStyle: PropTypes.oneOfType([
742
- PropTypes.object,
743
- PropTypes.array,
744
- ]),
745
- enabledOne: PropTypes.bool,
746
- enabledTwo: PropTypes.bool,
747
- onChangeStart: PropTypes.func,
748
- onChange: PropTypes.func,
749
- onChangeFinish: PropTypes.func,
750
- onMarkersPosition: PropTypes.func,
751
- step: PropTypes.number,
752
- min: PropTypes.number,
753
- max: PropTypes.number,
754
- onToggleOne: PropTypes.func,
755
- onToggleTwo: PropTypes.func,
756
- allowOverlap: PropTypes.bool,
757
- snapped: PropTypes.bool,
758
- minMarkerOverlapDistance: PropTypes.number,
759
- length: PropTypes.number,
760
- allowRange: PropTypes.arrayOf(PropTypes.number),
761
- };