react-native-ui-lib 8.4.0-snapshot.7827 → 8.4.0-snapshot.7835

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-ui-lib",
3
- "version": "8.4.0-snapshot.7827",
3
+ "version": "8.4.0-snapshot.7835",
4
4
  "main": "src/index.js",
5
5
  "types": "src/index.d.ts",
6
6
  "author": "Ethan Sharabi <ethan.shar@gmail.com>",
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { ViewStyle, ViewProps, View as RNView } from 'react-native';
2
+ import { ViewStyle, ViewProps, View as RNView, Animated } from 'react-native';
3
3
  export interface ThumbProps extends ViewProps {
4
4
  /**
5
5
  * The thumb style
@@ -27,6 +27,10 @@ export interface ThumbProps extends ViewProps {
27
27
  disabled?: boolean;
28
28
  /** ref to thumb component */
29
29
  ref?: React.RefObject<RNView>;
30
+ /**
31
+ * External scale animation value (used by useRelativeDrag)
32
+ */
33
+ scaleAnimation?: Animated.Value;
30
34
  }
31
35
  declare const Thumb: React.ForwardRefExoticComponent<Omit<ThumbProps, "ref"> & React.RefAttributes<unknown>>;
32
36
  export default Thumb;
@@ -18,6 +18,7 @@ const Thumb = forwardRef((props, ref) => {
18
18
  thumbHitSlop,
19
19
  onTouchStart,
20
20
  onTouchEnd,
21
+ scaleAnimation,
21
22
  ...others
22
23
  } = props;
23
24
  const thumbRef = useCombinedRefs(ref);
@@ -82,7 +83,7 @@ const Thumb = forwardRef((props, ref) => {
82
83
  backgroundColor: disabled ? DEFAULT_COLOR : thumbTintColor || ACTIVE_COLOR
83
84
  }, {
84
85
  transform: [{
85
- scale: thumbScaleAnimation.current
86
+ scale: scaleAnimation ?? thumbScaleAnimation.current
86
87
  }]
87
88
  }]} />;
88
89
  });
@@ -57,6 +57,7 @@ class Slider extends PureComponent {
57
57
  height: THUMB_SIZE
58
58
  };
59
59
  _containerDragInitialValue = 0;
60
+ _containerThumbScale = new Animated.Value(1);
60
61
  constructor(props) {
61
62
  super(props);
62
63
  this.activeThumbRef = this.thumb;
@@ -216,6 +217,7 @@ class Slider extends PureComponent {
216
217
  };
217
218
  handleContainerGrant = () => {
218
219
  this._containerDragInitialValue = this.getValueForX(this._x);
220
+ this.animateContainerThumbScale(1.5);
219
221
  this.onSeekStart();
220
222
  };
221
223
  handleContainerMove = (_e, gestureState) => {
@@ -238,8 +240,16 @@ class Slider extends PureComponent {
238
240
  };
239
241
  handleContainerEnd = () => {
240
242
  this.bounceToStep();
243
+ this.animateContainerThumbScale(1);
241
244
  this.onSeekEnd();
242
245
  };
246
+ animateContainerThumbScale = toValue => {
247
+ Animated.timing(this._containerThumbScale, {
248
+ toValue,
249
+ duration: 100,
250
+ useNativeDriver: true
251
+ }).start();
252
+ };
243
253
 
244
254
  /* Actions */
245
255
 
@@ -576,7 +586,8 @@ class Slider extends PureComponent {
576
586
  disableActiveStyling,
577
587
  disabled,
578
588
  thumbTintColor,
579
- thumbHitSlop
589
+ thumbHitSlop,
590
+ useRelativeDrag
580
591
  } = this.props;
581
592
  const {
582
593
  thumbSize
@@ -596,7 +607,8 @@ class Slider extends PureComponent {
596
607
  activeThumbStyle,
597
608
  disableActiveStyling,
598
609
  thumbHitSlop: thumbHitSlop ?? calculatedHitSlop,
599
- onLayout: this.onThumbLayout
610
+ onLayout: this.onThumbLayout,
611
+ scaleAnimation: useRelativeDrag ? this._containerThumbScale : undefined
600
612
  };
601
613
  };
602
614
 
@@ -19,6 +19,7 @@ interface ThumbProps extends ViewProps {
19
19
  onSeekStart?: () => void;
20
20
  onSeekEnd?: () => void;
21
21
  enableShadow?: boolean;
22
+ isActive?: SharedValue<boolean>;
22
23
  }
23
24
  declare const Thumb: (props: ThumbProps) => React.JSX.Element;
24
25
  export default Thumb;
@@ -31,7 +31,9 @@ const Thumb = props => {
31
31
  stepInterpolatedValue,
32
32
  gap = 0,
33
33
  secondary,
34
- enableShadow
34
+ enableShadow,
35
+ pointerEvents,
36
+ isActive
35
37
  } = props;
36
38
  const rtlFix = Constants.isRTL ? -1 : 1;
37
39
  const isPressed = useSharedValue(false);
@@ -40,7 +42,7 @@ const Thumb = props => {
40
42
  height: THUMB_SIZE
41
43
  });
42
44
  const lastOffset = useSharedValue(0);
43
- const gesture = Gesture.Pan().onBegin(() => {
45
+ const gesture = Gesture.Pan().hitSlop(hitSlop ?? DEFAULT_THUMB_HIT_SLOP).onBegin(() => {
44
46
  onSeekStart?.();
45
47
  isPressed.value = true;
46
48
  lastOffset.value = offset.value;
@@ -64,15 +66,16 @@ const Thumb = props => {
64
66
  offset.value = Math.round(offset.value / stepInterpolatedValue.value) * stepInterpolatedValue.value;
65
67
  }
66
68
  });
67
- gesture.enabled(!disabled);
69
+ gesture.enabled(!disabled && pointerEvents !== 'none');
68
70
  const animatedStyle = useAnimatedStyle(() => {
69
- const customStyle = isPressed.value ? activeStyle?.value : defaultStyle?.value;
71
+ const active = isPressed.value || isActive?.value;
72
+ const customStyle = active ? activeStyle?.value : defaultStyle?.value;
70
73
  return {
71
74
  ...customStyle,
72
75
  transform: [{
73
76
  translateX: (offset.value - thumbSize.value.width / 2) * rtlFix
74
77
  }, {
75
- scale: withSpring(!disableActiveStyling && isPressed.value ? 1.3 : 1)
78
+ scale: withSpring(!disableActiveStyling && active ? 1.3 : 1)
76
79
  }]
77
80
  };
78
81
  });
@@ -86,7 +89,7 @@ const Thumb = props => {
86
89
  // eslint-disable-next-line react-hooks/exhaustive-deps
87
90
  }, []);
88
91
  return <GestureDetector gesture={gesture}>
89
- <View reanimated style={[styles.thumbPosition, enableShadow && styles.thumbShadow, animatedStyle]} hitSlop={hitSlop} onLayout={onThumbLayout} />
92
+ <View reanimated pointerEvents={pointerEvents} style={[styles.thumbPosition, enableShadow && styles.thumbShadow, animatedStyle]} hitSlop={hitSlop} onLayout={onThumbLayout} />
90
93
  </GestureDetector>;
91
94
  };
92
95
  const styles = StyleSheet.create({
@@ -126,6 +126,11 @@ export interface SliderProps extends AccessibilityProps {
126
126
  * Whether to use the new Slider implementation using Reanimated
127
127
  */
128
128
  migrate?: boolean;
129
+ /**
130
+ * If true, dragging anywhere on the slider moves the thumb relative to its current position
131
+ * instead of snapping to the touch point. Designed for single-thumb mode.
132
+ */
133
+ useRelativeDrag?: boolean;
129
134
  /**
130
135
  * Control the throttle time of the onValueChange and onRangeChange callbacks
131
136
  */
@@ -2,13 +2,14 @@ import _throttle from "lodash/throttle";
2
2
  import React, { useImperativeHandle, useCallback, useMemo, useEffect, useRef } from 'react';
3
3
  import { StyleSheet } from 'react-native';
4
4
  import { useSharedValue, useAnimatedStyle, runOnJS, useAnimatedReaction, withTiming } from 'react-native-reanimated';
5
- import { GestureHandlerRootView } from 'react-native-gesture-handler';
5
+ import { GestureHandlerRootView, GestureDetector, Gesture } from 'react-native-gesture-handler';
6
6
  import { forwardRef, Constants } from "../../commons/new";
7
7
  import { extractAccessibilityProps } from "../../commons/modifiers";
8
8
  import { Colors, Spacings } from "../../style";
9
9
  import { StyleUtils } from "../../utils";
10
10
  import { useThemeProps, useDidUpdate } from "../../hooks";
11
11
  import { validateValues, getOffsetForValue, getValueForOffset, getStepInterpolated } from "./SliderPresenter";
12
+ import View from "../../components/view";
12
13
  import Thumb from "./Thumb";
13
14
  import Track from "./Track";
14
15
  var ThumbType = /*#__PURE__*/function (ThumbType) {
@@ -54,6 +55,7 @@ const Slider = React.memo(props => {
54
55
  accessible = true,
55
56
  testID,
56
57
  enableThumbShadow = true,
58
+ useRelativeDrag,
57
59
  throttleTime = 200
58
60
  } = themeProps;
59
61
  const accessibilityProps = useMemo(() => {
@@ -215,6 +217,36 @@ const Slider = React.memo(props => {
215
217
  runOnJS(onSeekEnd)();
216
218
  }
217
219
  };
220
+ const containerDragStartOffset = useSharedValue(0);
221
+ const isContainerDragging = useSharedValue(false);
222
+ const clampOffset = offset => {
223
+ 'worklet';
224
+
225
+ return Math.max(0, Math.min(trackSize.value.width, offset));
226
+ };
227
+ const snapToStep = () => {
228
+ 'worklet';
229
+
230
+ if (shouldBounceToStep) {
231
+ const step = stepInterpolatedValue.value;
232
+ defaultThumbOffset.value = Math.round(defaultThumbOffset.value / step) * step;
233
+ }
234
+ };
235
+ const containerGesture = Gesture.Pan().onBegin(() => {
236
+ containerDragStartOffset.value = defaultThumbOffset.value;
237
+ isContainerDragging.value = true;
238
+ _onSeekStart();
239
+ }).onUpdate(e => {
240
+ if (trackSize.value.width === 0) {
241
+ return;
242
+ }
243
+ const dx = e.translationX * (shouldDisableRTL ? 1 : rtlFix);
244
+ defaultThumbOffset.value = clampOffset(containerDragStartOffset.value + dx);
245
+ }).onEnd(() => _onSeekEnd()).onFinalize(() => {
246
+ isContainerDragging.value = false;
247
+ snapToStep();
248
+ });
249
+ containerGesture.enabled(!disabled && !!useRelativeDrag);
218
250
  const trackAnimatedStyles = useAnimatedStyle(() => {
219
251
  if (useRange) {
220
252
  return {
@@ -236,15 +268,22 @@ const Slider = React.memo(props => {
236
268
 
237
269
  /** renders */
238
270
  const renderThumb = type => {
239
- return <Thumb start={type === ThumbType.DEFAULT ? start : defaultThumbOffset} end={type === ThumbType.DEFAULT ? rangeThumbOffset : end} offset={type === ThumbType.DEFAULT ? defaultThumbOffset : rangeThumbOffset} gap={rangeGap} secondary={type !== ThumbType.DEFAULT} onSeekStart={_onSeekStart} onSeekEnd={_onSeekEnd} shouldDisableRTL={shouldDisableRTL} disabled={disabled} disableActiveStyling={disableActiveStyling} defaultStyle={_thumbStyle} activeStyle={_activeThumbStyle} hitSlop={thumbHitSlop} shouldBounceToStep={shouldBounceToStep} stepInterpolatedValue={stepInterpolatedValue} enableShadow={enableThumbShadow} />;
271
+ return <Thumb start={type === ThumbType.DEFAULT ? start : defaultThumbOffset} end={type === ThumbType.DEFAULT ? rangeThumbOffset : end} offset={type === ThumbType.DEFAULT ? defaultThumbOffset : rangeThumbOffset} gap={rangeGap} secondary={type !== ThumbType.DEFAULT} onSeekStart={_onSeekStart} onSeekEnd={_onSeekEnd} shouldDisableRTL={shouldDisableRTL} disabled={disabled} pointerEvents={useRelativeDrag ? 'none' : undefined} isActive={useRelativeDrag ? isContainerDragging : undefined} disableActiveStyling={disableActiveStyling} defaultStyle={_thumbStyle} activeStyle={_activeThumbStyle} hitSlop={thumbHitSlop} shouldBounceToStep={shouldBounceToStep} stepInterpolatedValue={stepInterpolatedValue} enableShadow={enableThumbShadow} />;
240
272
  };
241
273
  const _renderTrack = () => {
242
- return <Track renderTrack={renderTrack} onLayout={onTrackLayout} onPress={onTrackPress} animatedStyle={trackAnimatedStyles} disabled={disabled} maximumTrackTintColor={maximumTrackTintColor} minimumTrackTintColor={minimumTrackTintColor} trackStyle={trackStyle} />;
274
+ return <Track renderTrack={renderTrack} onLayout={onTrackLayout} onPress={useRelativeDrag ? undefined : onTrackPress} animatedStyle={trackAnimatedStyles} disabled={disabled} maximumTrackTintColor={maximumTrackTintColor} minimumTrackTintColor={minimumTrackTintColor} trackStyle={trackStyle} />;
243
275
  };
244
- return <GestureHandlerRootView style={[styles.container, containerStyle, shouldDisableRTL && styles.disableRTL]} testID={testID} {...accessibilityProps}>
276
+ const renderSliderContent = () => <>
245
277
  {_renderTrack()}
246
278
  {renderThumb(ThumbType.DEFAULT)}
247
279
  {useRange && renderThumb(ThumbType.RANGE)}
280
+ </>;
281
+ return <GestureHandlerRootView style={[styles.container, containerStyle, shouldDisableRTL && styles.disableRTL]} testID={testID} {...accessibilityProps}>
282
+ {useRelativeDrag ? <GestureDetector gesture={containerGesture}>
283
+ <View style={styles.gestureContainer}>
284
+ {renderSliderContent()}
285
+ </View>
286
+ </GestureDetector> : renderSliderContent()}
248
287
  </GestureHandlerRootView>;
249
288
  });
250
289
  Slider.displayName = 'Incubator.Slider';
@@ -254,6 +293,10 @@ const styles = StyleSheet.create({
254
293
  height: THUMB_SIZE + SHADOW_RADIUS,
255
294
  justifyContent: 'center'
256
295
  },
296
+ gestureContainer: {
297
+ flex: 1,
298
+ justifyContent: 'center'
299
+ },
257
300
  disableRTL: {
258
301
  transform: [{
259
302
  scaleX: -1