@momo-kits/slider 0.77.5 → 0.77.7

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/Label.tsx CHANGED
@@ -1,6 +1,7 @@
1
1
  import React, {PureComponent} from 'react';
2
2
  import {View} from 'react-native';
3
- import {Shadow, Text, Colors, Spacing, Radius} from '@momo-kits/foundation';
3
+ import {Shadow, Text} from '@momo-kits/foundation';
4
+ import styles from './styles';
4
5
 
5
6
  class Label extends PureComponent {
6
7
  state = {
@@ -16,18 +17,8 @@ class Label extends PureComponent {
16
17
  const {value} = this.state;
17
18
 
18
19
  return (
19
- <View
20
- {...props}
21
- style={[
22
- {
23
- backgroundColor: Colors.black_01,
24
- paddingVertical: Spacing.XS,
25
- paddingHorizontal: Spacing.S,
26
- borderRadius: Radius.XS,
27
- },
28
- Shadow.Light,
29
- ]}>
30
- <Text typography={'description_xs'}>{value}</Text>
20
+ <View {...props} style={[styles.label, Shadow.Light]}>
21
+ <Text typography={'label_s'}>{value}</Text>
31
22
  </View>
32
23
  );
33
24
  }
package/hooks.tsx CHANGED
@@ -1,16 +1,15 @@
1
1
  import React, {
2
+ MutableRefObject,
2
3
  useCallback,
3
- useState,
4
- useRef,
5
4
  useMemo,
6
- MutableRefObject,
7
- ReactNode,
5
+ useRef,
6
+ useState,
8
7
  } from 'react';
9
- import {Animated, I18nManager, View} from 'react-native';
8
+ import {Animated, I18nManager} from 'react-native';
10
9
  import {clamp} from './helpers';
11
10
  import styles from './styles';
12
11
  import FollowerContainer from './Label';
13
- import {Text} from '@momo-kits/foundation';
12
+ import {Spacing} from '@momo-kits/foundation';
14
13
 
15
14
  /**
16
15
  * low and high state variables are fallbacks for props (props are not required).
@@ -95,13 +94,21 @@ export const useWidthLayout = (
95
94
  * @param gestureStateRef
96
95
  * @param isPressed
97
96
  * @param allowOverflow
97
+ * @param disabledLow
98
+ * @param disabledHigh
98
99
  * @returns {[JSX.Element, function(*, *=): void]|*[]}
99
100
  */
100
101
  export const useThumbFollower = (
101
102
  containerWidthRef: MutableRefObject<number>,
102
- gestureStateRef: MutableRefObject<{lastValue: number; lastPosition: number}>,
103
+ gestureStateRef: MutableRefObject<{
104
+ isLow: boolean;
105
+ lastValue: number;
106
+ lastPosition: number;
107
+ }>,
103
108
  isPressed: boolean,
104
109
  allowOverflow: boolean,
110
+ disabledLow: boolean,
111
+ disabledHigh: boolean,
105
112
  ) => {
106
113
  const xRef = useRef(new Animated.Value(0));
107
114
  const widthRef = useRef(0);
@@ -111,6 +118,13 @@ export const useThumbFollower = (
111
118
 
112
119
  const update = useCallback(
113
120
  (thumbPositionInView, value) => {
121
+ if (
122
+ (gestureStateRef.current.isLow && disabledLow) ||
123
+ (!gestureStateRef.current.isLow && disabledHigh)
124
+ ) {
125
+ return;
126
+ }
127
+
114
128
  const {current: width} = widthRef;
115
129
  const {current: containerWidth} = containerWidthRef;
116
130
  const position = thumbPositionInView - width / 2;
@@ -119,7 +133,7 @@ export const useThumbFollower = (
119
133
  );
120
134
  contentContainerRef.current?.setValue(value);
121
135
  },
122
- [widthRef, containerWidthRef, allowOverflow],
136
+ [widthRef, containerWidthRef, allowOverflow, disabledLow, disabledHigh], // Include dependencies here.
123
137
  );
124
138
 
125
139
  const handleLayout = useWidthLayout(widthRef, () => {
@@ -130,8 +144,14 @@ export const useThumbFollower = (
130
144
  });
131
145
 
132
146
  const transform = {transform: [{translateX: x}]};
147
+
148
+ const shouldDisplayLabel =
149
+ isPressed &&
150
+ ((gestureStateRef.current.isLow && !disabledLow) ||
151
+ (!gestureStateRef.current.isLow && !disabledHigh));
152
+
133
153
  const follower = (
134
- <Animated.View style={[transform, {opacity: isPressed ? 1 : 0}]}>
154
+ <Animated.View style={[transform, {opacity: shouldDisplayLabel ? 1 : 0}]}>
135
155
  <FollowerContainer onLayout={handleLayout} ref={contentContainerRef} />
136
156
  </Animated.View>
137
157
  );
@@ -189,7 +209,7 @@ export const useLabelContainerProps = (floating: boolean) => {
189
209
  setLabelContainerHeight(height);
190
210
  }, []);
191
211
 
192
- const top = floating ? -labelContainerHeight : 0;
212
+ const top = floating ? -(labelContainerHeight + Spacing.XS) : Spacing.XS;
193
213
  const style = [
194
214
  floating ? styles.labelFloatingContainer : styles.labelFixedContainer,
195
215
  {top},
package/index.tsx CHANGED
@@ -32,20 +32,86 @@ const trueFunc = () => true;
32
32
  const falseFunc = () => false;
33
33
 
34
34
  export interface SliderProps extends ViewProps {
35
+ /**
36
+ * Specifies the minimum value permitted for selection in the slider. This value sets the lower
37
+ * bound for the component.
38
+ */
35
39
  min: number;
40
+
41
+ /**
42
+ * Specifies the maximum value allowed for selection. This value sets the upper bound for the component.
43
+ */
36
44
  max: number;
45
+
46
+ /**
47
+ * Optional. Defines the minimum permitted range between the low and high values of the slider.
48
+ * Particularly useful when 'low' and 'high' values both exist, ensuring a certain spread between them.
49
+ */
37
50
  minRange?: number;
51
+
52
+ /**
53
+ * Specifies the interval between individual step values. The slider's handle will move only in these increments.
54
+ */
38
55
  step: number;
56
+
57
+ /**
58
+ * Optional. Represents the initial lower value of the range when the component is used as a range slider.
59
+ * This value is part of the selected range, between 'min' and 'high'.
60
+ */
39
61
  low?: number;
62
+
63
+ /**
64
+ * Optional. Represents the initial upper value of the range when used as a range slider.
65
+ * This value is part of the selected range, between 'low' and 'max'.
66
+ */
40
67
  high?: number;
68
+
69
+ /**
70
+ * Optional. If `true`, allows the label to extend beyond the width of the Slider component itself,
71
+ * rather than being clipped at the component boundaries. Defaults to `false` if not provided.
72
+ */
41
73
  allowLabelOverflow?: boolean;
74
+
75
+ /**
76
+ * Optional. If `true`, disables the range functionality of the slider, turning it into a regular
77
+ * single-value slider. Defaults to `false` if not provided.
78
+ */
42
79
  disableRange?: boolean;
43
- disabled?: boolean;
80
+
81
+ /**
82
+ * Optional. If `true`, the 'high' handle of the slider will be disabled and cannot be moved.
83
+ * Useful for setting a maximum limit that users cannot increase. Defaults to `false` if not provided.
84
+ */
85
+ disabledHigh?: boolean;
86
+
87
+ /**
88
+ * Optional. If `true`, the 'low' handle of the slider will be disabled and cannot be moved.
89
+ * Useful for setting a minimum limit that users cannot decrease. Defaults to `false` if not provided.
90
+ */
91
+ disabledLow?: boolean;
92
+
93
+ /**
94
+ * Optional. If `true`, labels will be displayed in a floating manner above the slider handles,
95
+ * typically used to display the current value. Defaults to `false` if not provided.
96
+ */
44
97
  floatingLabel?: boolean;
45
- renderRail: () => ReactNode;
46
- renderRailSelected: () => ReactNode;
98
+
99
+ /**
100
+ * Optional. A callback function triggered when the slider value changes, either by the user or programmatically.
101
+ * It receives the new low and high values of the slider, as well as a boolean indicating if the change was made by the user.
102
+ */
47
103
  onValueChanged?: (low: number, high: number, byUser: boolean) => void;
104
+
105
+ /**
106
+ * Optional. A callback function triggered when the user starts touching the slider's draggable area.
107
+ * It receives the current low and high values of the slider.
108
+ */
48
109
  onSliderTouchStart?: (low: number, high: number) => void;
110
+
111
+ /**
112
+ * Optional. A callback function triggered when the user releases the slider's draggable area.
113
+ * It receives the current low and high values of the slider.
114
+ */
49
115
  onSliderTouchEnd?: (low: number, high: number) => void;
50
116
  }
51
117
 
@@ -59,12 +125,11 @@ const Slider: React.FC<SliderProps> = ({
59
125
  floatingLabel = false,
60
126
  allowLabelOverflow = false,
61
127
  disableRange = false,
62
- disabled = false,
128
+ disabledHigh = false,
129
+ disabledLow = false,
63
130
  onValueChanged,
64
131
  onSliderTouchStart,
65
132
  onSliderTouchEnd,
66
- renderRail,
67
- renderRailSelected,
68
133
  ...restProps
69
134
  }) => {
70
135
  const {theme} = useContext(ApplicationContext);
@@ -169,9 +234,18 @@ const Slider: React.FC<SliderProps> = ({
169
234
  gestureStateRef,
170
235
  isPressed,
171
236
  allowLabelOverflow,
237
+ disabledLow,
238
+ disabledHigh,
172
239
  );
173
240
 
174
241
  const renderThumb = (name: string) => {
242
+ const isDisabled =
243
+ (name === 'low' && disabledLow) || (name === 'high' && disabledHigh);
244
+
245
+ const thumbColor = isDisabled
246
+ ? theme.colors.text.disable
247
+ : theme.colors.primary;
248
+
175
249
  return (
176
250
  <View
177
251
  style={[
@@ -182,7 +256,7 @@ const Slider: React.FC<SliderProps> = ({
182
256
  borderRadius: Radius.M,
183
257
  borderWidth: 4,
184
258
  borderColor: theme.colors.background.surface,
185
- backgroundColor: theme.colors.primary,
259
+ backgroundColor: thumbColor,
186
260
  },
187
261
  ]}
188
262
  />
@@ -209,9 +283,6 @@ const Slider: React.FC<SliderProps> = ({
209
283
  ) => Math.abs(gestureState.dx) > 2 * Math.abs(gestureState.dy),
210
284
 
211
285
  onPanResponderGrant: ({nativeEvent}, gestureState) => {
212
- if (disabled) {
213
- return;
214
- }
215
286
  const {numberActiveTouches} = gestureState;
216
287
  if (numberActiveTouches > 1) {
217
288
  return;
@@ -237,6 +308,10 @@ const Slider: React.FC<SliderProps> = ({
237
308
  disableRange || isLowCloser(downX, lowPosition, highPosition);
238
309
  gestureStateRef.current.isLow = isLow;
239
310
 
311
+ if ((isLow && disabledLow) || (!isLow && disabledHigh)) {
312
+ return;
313
+ }
314
+
240
315
  const handlePositionChange = (positionInView: number) => {
241
316
  const {low, high, min, max, step} = inPropsRef.current;
242
317
  const minValue = isLow ? min : low + minRange;
@@ -278,13 +353,25 @@ const Slider: React.FC<SliderProps> = ({
278
353
  });
279
354
  },
280
355
 
281
- onPanResponderMove: disabled
282
- ? undefined
283
- : Animated.event([null, {moveX: pointerX}], {useNativeDriver: false}),
356
+ onPanResponderMove: (evt, gestureState) => {
357
+ if (gestureStateRef.current.isLow ? disabledLow : disabledHigh) {
358
+ return;
359
+ }
360
+
361
+ Animated.event([null, {moveX: pointerX}], {
362
+ useNativeDriver: false,
363
+ })(evt, gestureState);
364
+ },
284
365
 
285
366
  onPanResponderRelease: () => {
286
367
  setPressed(false);
287
368
  const {low, high} = inPropsRef.current;
369
+ if (
370
+ (gestureStateRef.current.isLow && disabledLow) ||
371
+ (!gestureStateRef.current.isLow && disabledHigh)
372
+ ) {
373
+ return;
374
+ }
288
375
  onSliderTouchEnd?.(low, high);
289
376
  },
290
377
  }),
@@ -293,8 +380,9 @@ const Slider: React.FC<SliderProps> = ({
293
380
  inPropsRef,
294
381
  thumbWidth,
295
382
  disableRange,
296
- disabled,
297
383
  onValueChanged,
384
+ disabledHigh,
385
+ disabledLow,
298
386
  setLow,
299
387
  setHigh,
300
388
  labelUpdate,
@@ -315,6 +403,11 @@ const Slider: React.FC<SliderProps> = ({
315
403
  );
316
404
  };
317
405
 
406
+ const trackColor =
407
+ disabledHigh && disabledLow
408
+ ? theme.colors.text.disable
409
+ : theme.colors.primary;
410
+
318
411
  return (
319
412
  <View {...restProps}>
320
413
  <View {...labelContainerProps}>{labelView}</View>
@@ -322,7 +415,7 @@ const Slider: React.FC<SliderProps> = ({
322
415
  <View style={railContainerStyles}>
323
416
  {renderTrack(theme.colors.background.default)}
324
417
  <Animated.View style={selectedRailStyle}>
325
- {renderTrack(theme.colors.primary)}
418
+ {renderTrack(trackColor)}
326
419
  </Animated.View>
327
420
  </View>
328
421
  <Animated.View style={lowStyles} onLayout={handleThumbLayout}>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/slider",
3
- "version": "0.77.5",
3
+ "version": "0.77.7",
4
4
  "private": false,
5
5
  "main": "index.tsx",
6
6
  "dependencies": {},
package/styles.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import {I18nManager, StyleSheet} from 'react-native';
2
+ import {Colors, Radius, Spacing} from '@momo-kits/foundation';
2
3
 
3
4
  export default StyleSheet.create({
4
5
  controlsContainer: {
@@ -26,4 +27,10 @@ export default StyleSheet.create({
26
27
  touchableArea: {
27
28
  ...StyleSheet.absoluteFillObject,
28
29
  },
30
+ label: {
31
+ backgroundColor: Colors.black_01,
32
+ paddingVertical: Spacing.XXS,
33
+ paddingHorizontal: Spacing.XS,
34
+ borderRadius: Radius.XS,
35
+ },
29
36
  });