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