@momo-kits/slider 0.89.1-rc.5 → 0.89.2
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/index.tsx +194 -194
- package/package.json +1 -1
package/index.tsx
CHANGED
|
@@ -115,7 +115,7 @@ export interface SliderProps extends ViewProps {
|
|
|
115
115
|
onSliderTouchEnd?: (low: number, high: number) => void;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
const Slider: React.FC<SliderProps> = ({
|
|
118
|
+
const Slider: React.FC<SliderProps> = memo(({
|
|
119
119
|
min,
|
|
120
120
|
max,
|
|
121
121
|
minRange = 0,
|
|
@@ -154,10 +154,10 @@ const Slider: React.FC<SliderProps> = ({
|
|
|
154
154
|
const [thumbWidth, setThumbWidth] = useState(0);
|
|
155
155
|
|
|
156
156
|
const [selectedRailStyle, updateSelectedRail] = useSelectedRail(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
157
|
+
inPropsRef,
|
|
158
|
+
containerWidthRef,
|
|
159
|
+
thumbWidth,
|
|
160
|
+
disableRange,
|
|
161
161
|
);
|
|
162
162
|
|
|
163
163
|
const updateThumbs = useCallback(() => {
|
|
@@ -169,12 +169,12 @@ const Slider: React.FC<SliderProps> = ({
|
|
|
169
169
|
if (!disableRange) {
|
|
170
170
|
const {current: highThumbX} = highThumbXRef;
|
|
171
171
|
const highPosition =
|
|
172
|
-
|
|
172
|
+
((high - min) / (max - min)) * (containerWidth - thumbWidth);
|
|
173
173
|
highThumbX.setValue(highPosition);
|
|
174
174
|
}
|
|
175
175
|
const {current: lowThumbX} = lowThumbXRef;
|
|
176
176
|
const lowPosition =
|
|
177
|
-
|
|
177
|
+
((low - min) / (max - min)) * (containerWidth - thumbWidth);
|
|
178
178
|
lowThumbX.setValue(lowPosition);
|
|
179
179
|
typeof updateSelectedRail === 'function' && updateSelectedRail();
|
|
180
180
|
onValueChanged?.(low, high, false);
|
|
@@ -191,8 +191,8 @@ const Slider: React.FC<SliderProps> = ({
|
|
|
191
191
|
useEffect(() => {
|
|
192
192
|
const {lowPrev, highPrev} = inPropsRefPrev;
|
|
193
193
|
if (
|
|
194
|
-
|
|
195
|
-
|
|
194
|
+
(lowProp !== undefined && lowProp !== lowPrev) ||
|
|
195
|
+
(highProp !== undefined && highProp !== highPrev)
|
|
196
196
|
) {
|
|
197
197
|
updateThumbs();
|
|
198
198
|
}
|
|
@@ -204,15 +204,15 @@ const Slider: React.FC<SliderProps> = ({
|
|
|
204
204
|
|
|
205
205
|
const handleContainerLayout = useWidthLayout(containerWidthRef, updateThumbs);
|
|
206
206
|
const handleThumbLayout = useCallback(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
207
|
+
({nativeEvent}) => {
|
|
208
|
+
const {
|
|
209
|
+
layout: {width},
|
|
210
|
+
} = nativeEvent;
|
|
211
|
+
if (thumbWidth !== width) {
|
|
212
|
+
setThumbWidth(width);
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
[thumbWidth],
|
|
216
216
|
);
|
|
217
217
|
|
|
218
218
|
const lowStyles = useMemo(() => {
|
|
@@ -221,8 +221,8 @@ const Slider: React.FC<SliderProps> = ({
|
|
|
221
221
|
|
|
222
222
|
const highStyles = useMemo(() => {
|
|
223
223
|
return disableRange
|
|
224
|
-
|
|
225
|
-
|
|
224
|
+
? null
|
|
225
|
+
: [styles.highThumbContainer, {transform: [{translateX: highThumbX}]}];
|
|
226
226
|
}, [disableRange, highThumbX]);
|
|
227
227
|
|
|
228
228
|
const railContainerStyles = useMemo(() => {
|
|
@@ -230,36 +230,36 @@ const Slider: React.FC<SliderProps> = ({
|
|
|
230
230
|
}, [thumbWidth]);
|
|
231
231
|
|
|
232
232
|
const [labelView, labelUpdate] = useThumbFollower(
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
233
|
+
containerWidthRef,
|
|
234
|
+
gestureStateRef,
|
|
235
|
+
isPressed,
|
|
236
|
+
allowLabelOverflow,
|
|
237
|
+
disabledLow,
|
|
238
|
+
disabledHigh,
|
|
239
239
|
);
|
|
240
240
|
|
|
241
241
|
const renderThumb = (name: string) => {
|
|
242
242
|
const isDisabled =
|
|
243
|
-
|
|
243
|
+
(name === 'low' && disabledLow) || (name === 'high' && disabledHigh);
|
|
244
244
|
|
|
245
245
|
const thumbColor = isDisabled
|
|
246
|
-
|
|
247
|
-
|
|
246
|
+
? theme.colors.text.disable
|
|
247
|
+
: theme.colors.primary;
|
|
248
248
|
|
|
249
249
|
return (
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
250
|
+
<View
|
|
251
|
+
style={[
|
|
252
|
+
Shadow.Light,
|
|
253
|
+
{
|
|
254
|
+
width: 20,
|
|
255
|
+
height: 20,
|
|
256
|
+
borderRadius: Radius.M,
|
|
257
|
+
borderWidth: 4,
|
|
258
|
+
borderColor: theme.colors.background.surface,
|
|
259
|
+
backgroundColor: thumbColor,
|
|
260
|
+
},
|
|
261
|
+
]}
|
|
262
|
+
/>
|
|
263
263
|
);
|
|
264
264
|
};
|
|
265
265
|
|
|
@@ -269,170 +269,170 @@ const Slider: React.FC<SliderProps> = ({
|
|
|
269
269
|
const labelContainerProps = useLabelContainerProps(floatingLabel);
|
|
270
270
|
|
|
271
271
|
const {panHandlers} = useMemo(
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
272
|
+
() =>
|
|
273
|
+
PanResponder.create({
|
|
274
|
+
onStartShouldSetPanResponderCapture: falseFunc,
|
|
275
|
+
onMoveShouldSetPanResponderCapture: falseFunc,
|
|
276
|
+
onPanResponderTerminationRequest: falseFunc,
|
|
277
|
+
onPanResponderTerminate: trueFunc,
|
|
278
|
+
onShouldBlockNativeResponder: trueFunc,
|
|
279
|
+
|
|
280
|
+
onMoveShouldSetPanResponder: (
|
|
281
|
+
evt: GestureResponderEvent,
|
|
282
|
+
gestureState: PanResponderGestureState,
|
|
283
|
+
) => Math.abs(gestureState.dx) > 2 * Math.abs(gestureState.dy),
|
|
284
|
+
|
|
285
|
+
onPanResponderGrant: ({nativeEvent}, gestureState) => {
|
|
286
|
+
const {numberActiveTouches} = gestureState;
|
|
287
|
+
if (numberActiveTouches > 1) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
setPressed(true);
|
|
291
|
+
const {current: lowThumbX} = lowThumbXRef;
|
|
292
|
+
const {current: highThumbX} = highThumbXRef;
|
|
293
|
+
const {locationX: downX, pageX} = nativeEvent;
|
|
294
|
+
const containerX = pageX - downX;
|
|
295
|
+
|
|
296
|
+
const {low, high, min, max} = inPropsRef.current;
|
|
297
|
+
onSliderTouchStart?.(low, high);
|
|
298
|
+
const containerWidth = containerWidthRef.current;
|
|
299
|
+
|
|
300
|
+
const lowPosition =
|
|
301
|
+
thumbWidth / 2 +
|
|
302
|
+
((low - min) / (max - min)) * (containerWidth - thumbWidth);
|
|
303
|
+
const highPosition =
|
|
304
|
+
thumbWidth / 2 +
|
|
305
|
+
((high - min) / (max - min)) * (containerWidth - thumbWidth);
|
|
306
|
+
|
|
307
|
+
const isLow =
|
|
308
|
+
disableRange || isLowCloser(downX, lowPosition, highPosition);
|
|
309
|
+
gestureStateRef.current.isLow = isLow;
|
|
310
|
+
|
|
311
|
+
if ((isLow && disabledLow) || (!isLow && disabledHigh)) {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const handlePositionChange = (positionInView: number) => {
|
|
316
|
+
const {low, high, min, max, step} = inPropsRef.current;
|
|
317
|
+
const minValue = isLow ? min : low + minRange;
|
|
318
|
+
const maxValue = isLow ? high - minRange : max;
|
|
319
|
+
const value = clamp(
|
|
320
|
+
getValueForPosition(
|
|
321
|
+
positionInView,
|
|
322
|
+
containerWidth,
|
|
323
|
+
thumbWidth,
|
|
324
|
+
min,
|
|
325
|
+
max,
|
|
326
|
+
step,
|
|
327
|
+
),
|
|
328
|
+
minValue,
|
|
329
|
+
maxValue,
|
|
330
|
+
);
|
|
331
|
+
if (gestureStateRef.current.lastValue === value) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
const availableSpace = containerWidth - thumbWidth;
|
|
335
|
+
const absolutePosition =
|
|
336
|
+
((value - min) / (max - min)) * availableSpace;
|
|
337
|
+
gestureStateRef.current.lastValue = value;
|
|
338
|
+
gestureStateRef.current.lastPosition =
|
|
339
|
+
absolutePosition + thumbWidth / 2;
|
|
340
|
+
(isLow ? lowThumbX : highThumbX).setValue(absolutePosition);
|
|
341
|
+
onValueChanged?.(isLow ? value : low, isLow ? high : value, true);
|
|
342
|
+
(isLow ? setLow : setHigh)(value);
|
|
343
|
+
labelUpdate &&
|
|
344
|
+
typeof labelUpdate === 'function' &&
|
|
345
|
+
labelUpdate(gestureStateRef.current.lastPosition, value);
|
|
346
|
+
|
|
347
|
+
typeof updateSelectedRail === 'function' && updateSelectedRail();
|
|
348
|
+
};
|
|
349
|
+
handlePositionChange(downX);
|
|
350
|
+
pointerX.removeAllListeners();
|
|
351
|
+
pointerX.addListener(({value: pointerPosition}) => {
|
|
352
|
+
const positionInView = pointerPosition - containerX;
|
|
353
|
+
handlePositionChange(positionInView);
|
|
354
|
+
});
|
|
355
|
+
},
|
|
356
|
+
|
|
357
|
+
onPanResponderMove: (evt, gestureState) => {
|
|
358
|
+
if (gestureStateRef.current.isLow ? disabledLow : disabledHigh) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
Animated.event([null, {moveX: pointerX}], {
|
|
363
|
+
useNativeDriver: false,
|
|
364
|
+
})(evt, gestureState);
|
|
365
|
+
},
|
|
366
|
+
|
|
367
|
+
onPanResponderRelease: () => {
|
|
368
|
+
setPressed(false);
|
|
369
|
+
const {low, high} = inPropsRef.current;
|
|
370
|
+
if (
|
|
371
|
+
(gestureStateRef.current.isLow && disabledLow) ||
|
|
372
|
+
(!gestureStateRef.current.isLow && disabledHigh)
|
|
373
|
+
) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
onSliderTouchEnd?.(low, high);
|
|
377
|
+
},
|
|
378
|
+
}),
|
|
379
|
+
[
|
|
380
|
+
pointerX,
|
|
381
|
+
inPropsRef,
|
|
382
|
+
thumbWidth,
|
|
383
|
+
disableRange,
|
|
384
|
+
onValueChanged,
|
|
385
|
+
disabledHigh,
|
|
386
|
+
disabledLow,
|
|
387
|
+
setLow,
|
|
388
|
+
setHigh,
|
|
389
|
+
labelUpdate,
|
|
390
|
+
updateSelectedRail,
|
|
391
|
+
],
|
|
392
392
|
);
|
|
393
393
|
|
|
394
394
|
const renderTrack = (color: string) => {
|
|
395
395
|
return (
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
396
|
+
<View
|
|
397
|
+
style={{
|
|
398
|
+
width: '100%',
|
|
399
|
+
height: 4,
|
|
400
|
+
borderRadius: Radius.L,
|
|
401
|
+
backgroundColor: color,
|
|
402
|
+
}}
|
|
403
|
+
/>
|
|
404
404
|
);
|
|
405
405
|
};
|
|
406
406
|
|
|
407
407
|
const trackColor =
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
408
|
+
disabledHigh && disabledLow
|
|
409
|
+
? theme.colors.text.disable
|
|
410
|
+
: theme.colors.primary;
|
|
411
411
|
|
|
412
412
|
return (
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
413
|
+
<View {...restProps}>
|
|
414
|
+
<View {...labelContainerProps}>{labelView}</View>
|
|
415
|
+
<View onLayout={handleContainerLayout} style={styles.controlsContainer}>
|
|
416
|
+
<View style={railContainerStyles}>
|
|
417
|
+
{renderTrack(theme.colors.background.default)}
|
|
418
|
+
<Animated.View style={selectedRailStyle as ViewStyle}>
|
|
419
|
+
{renderTrack(trackColor)}
|
|
420
|
+
</Animated.View>
|
|
421
|
+
</View>
|
|
422
|
+
<Animated.View style={lowStyles} onLayout={handleThumbLayout}>
|
|
423
|
+
{lowThumb}
|
|
420
424
|
</Animated.View>
|
|
425
|
+
{!disableRange && (
|
|
426
|
+
<Animated.View style={highStyles}>{highThumb}</Animated.View>
|
|
427
|
+
)}
|
|
428
|
+
<View
|
|
429
|
+
{...panHandlers}
|
|
430
|
+
style={styles.touchableArea}
|
|
431
|
+
collapsable={false}
|
|
432
|
+
/>
|
|
421
433
|
</View>
|
|
422
|
-
<Animated.View style={lowStyles} onLayout={handleThumbLayout}>
|
|
423
|
-
{lowThumb}
|
|
424
|
-
</Animated.View>
|
|
425
|
-
{!disableRange && (
|
|
426
|
-
<Animated.View style={highStyles}>{highThumb}</Animated.View>
|
|
427
|
-
)}
|
|
428
|
-
<View
|
|
429
|
-
{...panHandlers}
|
|
430
|
-
style={styles.touchableArea}
|
|
431
|
-
collapsable={false}
|
|
432
|
-
/>
|
|
433
434
|
</View>
|
|
434
|
-
</View>
|
|
435
435
|
);
|
|
436
|
-
}
|
|
436
|
+
})
|
|
437
437
|
|
|
438
|
-
export
|
|
438
|
+
export {Slider};
|