@momo-kits/slider 0.0.46-beta.7 → 0.0.46-beta.72

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