related-ui-components 2.6.0 → 2.6.1

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.
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+
3
+ import React, { useCallback, useState } from "react";
4
+ import { StyleSheet, View, Text } from "react-native";
5
+ import { Gesture, GestureDetector } from "react-native-gesture-handler";
6
+ import Animated, { runOnJS, useAnimatedStyle, useSharedValue } from "react-native-reanimated";
7
+ import { useTheme } from "../../theme/index.js";
8
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
+ const LABEL_HEIGHT = 26; // Default height for the label area above the thumb
10
+
11
+ const RangeSlider = ({
12
+ // Core props
13
+ min,
14
+ max,
15
+ step = 1,
16
+ sliderWidth,
17
+ initialMinValue,
18
+ initialMaxValue,
19
+ onValueChange,
20
+ // Sizing props
21
+ thumbSize = 28,
22
+ railHeight = 6,
23
+ // Styling props
24
+ containerStyle,
25
+ railStyle,
26
+ activeRailStyle,
27
+ thumbStyle,
28
+ labelContainerStyle,
29
+ labelTextStyle
30
+ }) => {
31
+ const {
32
+ theme
33
+ } = useTheme();
34
+ const styles = getStyles(theme, thumbSize, railHeight);
35
+
36
+ // State for labels, allowing them to have dynamic width
37
+ const [leftLabel, setLeftLabel] = useState(initialMinValue.toLocaleString());
38
+ const [rightLabel, setRightLabel] = useState(initialMaxValue.toLocaleString());
39
+
40
+ // --- Worklets for calculations ---
41
+ const valueToPosition = useCallback(value => {
42
+ "worklet";
43
+
44
+ return (value - min) / (max - min) * sliderWidth;
45
+ }, [min, max, sliderWidth]);
46
+ const positionToValue = useCallback(position => {
47
+ "worklet";
48
+
49
+ const rawValue = position / sliderWidth * (max - min) + min;
50
+ return Math.round(rawValue / step) * step;
51
+ }, [min, max, step, sliderWidth]);
52
+
53
+ // --- Shared Values for Animation ---
54
+ const leftPosition = useSharedValue(valueToPosition(initialMinValue));
55
+ const rightPosition = useSharedValue(valueToPosition(initialMaxValue));
56
+ const context = useSharedValue({
57
+ x: 0
58
+ });
59
+ const activeThumb = useSharedValue(null);
60
+
61
+ // --- Pan Gesture Handler ---
62
+ const panGesture = Gesture.Pan().onBegin(e => {
63
+ // Determine which thumb is closer to the touch point
64
+ const distToLeft = Math.abs(e.x - leftPosition.value);
65
+ const distToRight = Math.abs(e.x - rightPosition.value);
66
+ if (distToLeft <= distToRight) {
67
+ activeThumb.value = "left";
68
+ context.value = {
69
+ x: leftPosition.value
70
+ };
71
+ } else {
72
+ activeThumb.value = "right";
73
+ context.value = {
74
+ x: rightPosition.value
75
+ };
76
+ }
77
+ }).onUpdate(e => {
78
+ if (activeThumb.value === null) return;
79
+ const newPos = context.value.x + e.translationX;
80
+
81
+ // Update the correct thumb's position and label
82
+ if (activeThumb.value === "left") {
83
+ const clampedPos = Math.max(0, Math.min(newPos, rightPosition.value));
84
+ leftPosition.value = clampedPos;
85
+ runOnJS(setLeftLabel)(positionToValue(clampedPos).toLocaleString());
86
+ } else {
87
+ const clampedPos = Math.min(sliderWidth, Math.max(newPos, leftPosition.value));
88
+ rightPosition.value = clampedPos;
89
+ runOnJS(setRightLabel)(positionToValue(clampedPos).toLocaleString());
90
+ }
91
+ }).onEnd(() => {
92
+ if (activeThumb.value === null) return;
93
+ // Finalize values and call the onValueChange callback
94
+ const finalLeftValue = positionToValue(leftPosition.value);
95
+ const finalRightValue = positionToValue(rightPosition.value);
96
+ runOnJS(onValueChange)({
97
+ min: finalLeftValue,
98
+ max: finalRightValue
99
+ });
100
+ activeThumb.value = null;
101
+ });
102
+
103
+ // --- Animated Styles ---
104
+ const animatedLeftThumbStyle = useAnimatedStyle(() => ({
105
+ transform: [{
106
+ translateX: leftPosition.value
107
+ }]
108
+ }));
109
+ const animatedRightThumbStyle = useAnimatedStyle(() => ({
110
+ // Adjust position to account for the thumb's own width
111
+ transform: [{
112
+ translateX: rightPosition.value - thumbSize
113
+ }]
114
+ }));
115
+ const animatedActiveRailStyle = useAnimatedStyle(() => ({
116
+ left: leftPosition.value,
117
+ right: sliderWidth - rightPosition.value
118
+ }));
119
+ return /*#__PURE__*/_jsx(GestureDetector, {
120
+ gesture: panGesture,
121
+ children: /*#__PURE__*/_jsxs(View, {
122
+ style: [styles.container, {
123
+ width: sliderWidth
124
+ }, containerStyle],
125
+ children: [/*#__PURE__*/_jsxs(View, {
126
+ style: styles.railContainer,
127
+ children: [/*#__PURE__*/_jsx(View, {
128
+ style: [styles.rail, railStyle]
129
+ }), /*#__PURE__*/_jsx(Animated.View, {
130
+ style: [styles.activeRail, animatedActiveRailStyle, activeRailStyle]
131
+ })]
132
+ }), /*#__PURE__*/_jsxs(Animated.View, {
133
+ style: [styles.thumbContainer, animatedLeftThumbStyle],
134
+ children: [/*#__PURE__*/_jsx(View, {
135
+ style: [styles.labelContainer, labelContainerStyle],
136
+ children: /*#__PURE__*/_jsx(Text, {
137
+ style: [styles.labelText, labelTextStyle],
138
+ numberOfLines: 1,
139
+ children: leftLabel
140
+ })
141
+ }), /*#__PURE__*/_jsx(View, {
142
+ style: [styles.thumb, thumbStyle]
143
+ })]
144
+ }), /*#__PURE__*/_jsxs(Animated.View, {
145
+ style: [styles.thumbContainer, animatedRightThumbStyle],
146
+ children: [/*#__PURE__*/_jsx(View, {
147
+ style: [styles.labelContainer, labelContainerStyle],
148
+ children: /*#__PURE__*/_jsx(Text, {
149
+ style: [styles.labelText, labelTextStyle],
150
+ numberOfLines: 1,
151
+ children: rightLabel
152
+ })
153
+ }), /*#__PURE__*/_jsx(View, {
154
+ style: [styles.thumb, thumbStyle]
155
+ })]
156
+ })]
157
+ })
158
+ });
159
+ };
160
+ const getStyles = (theme, thumbSize, railHeight) => StyleSheet.create({
161
+ container: {
162
+ height: LABEL_HEIGHT + thumbSize,
163
+ justifyContent: "center"
164
+ },
165
+ railContainer: {
166
+ justifyContent: "center"
167
+ },
168
+ rail: {
169
+ height: railHeight,
170
+ borderRadius: railHeight / 2,
171
+ backgroundColor: theme.surfaceVariant
172
+ },
173
+ activeRail: {
174
+ height: railHeight,
175
+ backgroundColor: theme.primary,
176
+ position: "absolute"
177
+ },
178
+ thumbContainer: {
179
+ position: "absolute",
180
+ alignItems: "center",
181
+ // Center the thumb visually on its value point
182
+ transform: [{
183
+ translateX: -thumbSize / 2
184
+ }]
185
+ },
186
+ labelContainer: {
187
+ position: "absolute",
188
+ bottom: thumbSize + 4,
189
+ backgroundColor: theme.onBackground,
190
+ paddingHorizontal: 10,
191
+ paddingVertical: 4,
192
+ borderRadius: 4
193
+ },
194
+ labelText: {
195
+ color: theme.background,
196
+ fontSize: 14,
197
+ fontWeight: "bold"
198
+ },
199
+ thumb: {
200
+ width: thumbSize,
201
+ height: thumbSize,
202
+ borderRadius: thumbSize / 2,
203
+ backgroundColor: theme.background,
204
+ borderColor: theme.primary,
205
+ borderWidth: 5
206
+ }
207
+ });
208
+ export default RangeSlider;
209
+ //# sourceMappingURL=RangeSlider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useCallback","useState","StyleSheet","View","Text","Gesture","GestureDetector","Animated","runOnJS","useAnimatedStyle","useSharedValue","useTheme","jsx","_jsx","jsxs","_jsxs","LABEL_HEIGHT","RangeSlider","min","max","step","sliderWidth","initialMinValue","initialMaxValue","onValueChange","thumbSize","railHeight","containerStyle","railStyle","activeRailStyle","thumbStyle","labelContainerStyle","labelTextStyle","theme","styles","getStyles","leftLabel","setLeftLabel","toLocaleString","rightLabel","setRightLabel","valueToPosition","value","positionToValue","position","rawValue","Math","round","leftPosition","rightPosition","context","x","activeThumb","panGesture","Pan","onBegin","e","distToLeft","abs","distToRight","onUpdate","newPos","translationX","clampedPos","onEnd","finalLeftValue","finalRightValue","animatedLeftThumbStyle","transform","translateX","animatedRightThumbStyle","animatedActiveRailStyle","left","right","gesture","children","style","container","width","railContainer","rail","activeRail","thumbContainer","labelContainer","labelText","numberOfLines","thumb","create","height","justifyContent","borderRadius","backgroundColor","surfaceVariant","primary","alignItems","bottom","onBackground","paddingHorizontal","paddingVertical","color","background","fontSize","fontWeight","borderColor","borderWidth"],"sourceRoot":"..\\..\\..\\..\\src","sources":["components/RangeSlider/RangeSlider.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ export { default as RangeSlider } from "./RangeSlider.js";
4
+ export * from "./RangeSlider.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["default","RangeSlider"],"sourceRoot":"..\\..\\..\\..\\src","sources":["components/RangeSlider/index.ts"],"mappings":";;AAAA,SAASA,OAAO,IAAIC,WAAW,QAAQ,kBAAe;AACtD,cAAc,kBAAe","ignoreList":[]}
@@ -22,4 +22,5 @@ export * from "./CustomIcon/index.js";
22
22
  export * from "./CarouselCardStack/index.js";
23
23
  export * from "./TravelBooking/index.js";
24
24
  export * from "./DateRangePicker/index.js";
25
+ export * from "./RangeSlider/index.js";
25
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":[],"sourceRoot":"..\\..\\..\\src","sources":["components/index.ts"],"mappings":";;AAAA,cAAc,iBAAQ;AACtB,cAAc,wBAAe;AAC7B,cAAe,mBAAU;AACzB,cAAc,mBAAU;AACxB,cAAc,sBAAa;AAC3B,cAAc,oBAAW;AACzB,cAAc,kBAAS;AACvB,cAAc,wBAAe;AAC7B,cAAc,kBAAS;AACvB,cAAc,6BAAoB;AAClC,cAAc,wBAAe;AAC7B,cAAc,0BAAiB;AAC/B,cAAc,kBAAS;AACvB,cAAc,sBAAa;AAC3B,cAAc,oBAAW;AACzB,cAAc,4BAAmB;AACjC,cAAc,mBAAU;AACxB,cAAc,qBAAY;AAC1B,cAAc,uBAAc;AAC5B,cAAc,8BAAqB;AACnC,cAAc,0BAAiB;AAC/B,cAAc,4BAAmB","ignoreList":[]}
1
+ {"version":3,"names":[],"sourceRoot":"..\\..\\..\\src","sources":["components/index.ts"],"mappings":";;AAAA,cAAc,iBAAQ;AACtB,cAAc,wBAAe;AAC7B,cAAe,mBAAU;AACzB,cAAc,mBAAU;AACxB,cAAc,sBAAa;AAC3B,cAAc,oBAAW;AACzB,cAAc,kBAAS;AACvB,cAAc,wBAAe;AAC7B,cAAc,kBAAS;AACvB,cAAc,6BAAoB;AAClC,cAAc,wBAAe;AAC7B,cAAc,0BAAiB;AAC/B,cAAc,kBAAS;AACvB,cAAc,sBAAa;AAC3B,cAAc,oBAAW;AACzB,cAAc,4BAAmB;AACjC,cAAc,mBAAU;AACxB,cAAc,qBAAY;AAC1B,cAAc,uBAAc;AAC5B,cAAc,8BAAqB;AACnC,cAAc,0BAAiB;AAC/B,cAAc,4BAAmB;AACjC,cAAc,wBAAe","ignoreList":[]}
@@ -0,0 +1,40 @@
1
+ import React from "react";
2
+ import { StyleProp, ViewStyle, TextStyle } from "react-native";
3
+ export interface RangeSliderProps {
4
+ /** The minimum value of the slider. */
5
+ min: number;
6
+ /** The maximum value of the slider. */
7
+ max: number;
8
+ /** The increment value for each step of the slider. */
9
+ step?: number;
10
+ /** The total width of the slider component in pixels. */
11
+ sliderWidth: number;
12
+ /** The initial value for the left (minimum) thumb. */
13
+ initialMinValue: number;
14
+ /** The initial value for the right (maximum) thumb. */
15
+ initialMaxValue: number;
16
+ /** Callback function triggered when the user releases a thumb, returning the new min and max values. */
17
+ onValueChange: (values: {
18
+ min: number;
19
+ max: number;
20
+ }) => void;
21
+ /** The diameter of the draggable thumb. */
22
+ thumbSize?: number;
23
+ /** The height of the slider rail. */
24
+ railHeight?: number;
25
+ /** Custom style for the main container. */
26
+ containerStyle?: StyleProp<ViewStyle>;
27
+ /** Custom style for the inactive part of the rail. */
28
+ railStyle?: StyleProp<ViewStyle>;
29
+ /** Custom style for the active (selected) part of the rail. */
30
+ activeRailStyle?: StyleProp<ViewStyle>;
31
+ /** Custom style for the thumbs. Overrides the default themed thumb. */
32
+ thumbStyle?: StyleProp<ViewStyle>;
33
+ /** Custom style for the container of the value labels. */
34
+ labelContainerStyle?: StyleProp<ViewStyle>;
35
+ /** Custom style for the text inside the labels. */
36
+ labelTextStyle?: StyleProp<TextStyle>;
37
+ }
38
+ declare const RangeSlider: React.FC<RangeSliderProps>;
39
+ export default RangeSlider;
40
+ //# sourceMappingURL=RangeSlider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RangeSlider.d.ts","sourceRoot":"","sources":["../../../../../src/components/RangeSlider/RangeSlider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AACrD,OAAO,EAIL,SAAS,EACT,SAAS,EACT,SAAS,EACV,MAAM,cAAc,CAAC;AAWtB,MAAM,WAAW,gBAAgB;IAE/B,uCAAuC;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,uCAAuC;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,eAAe,EAAE,MAAM,CAAC;IACxB,uDAAuD;IACvD,eAAe,EAAE,MAAM,CAAC;IACxB,wGAAwG;IACxG,aAAa,EAAE,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAG9D,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,2CAA2C;IAC3C,cAAc,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACtC,sDAAsD;IACtD,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,+DAA+D;IAC/D,eAAe,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACvC,uEAAuE;IACvE,UAAU,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAClC,0DAA0D;IAC1D,mBAAmB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC3C,mDAAmD;IACnD,cAAc,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CACvC;AAED,QAAA,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAiJ3C,CAAC;AAkDF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { default as RangeSlider } from "./RangeSlider";
2
+ export * from "./RangeSlider";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/RangeSlider/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,cAAc,eAAe,CAAC"}
@@ -20,4 +20,5 @@ export * from "./CustomIcon";
20
20
  export * from "./CarouselCardStack";
21
21
  export * from "./TravelBooking";
22
22
  export * from "./DateRangePicker";
23
+ export * from "./RangeSlider";
23
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAA;AACtB,cAAc,eAAe,CAAC;AAC9B,cAAe,UAAU,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAA;AACtB,cAAc,eAAe,CAAC;AAC9B,cAAe,UAAU,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "related-ui-components",
3
- "version": "2.6.0",
3
+ "version": "2.6.1",
4
4
  "main": "./src/index.ts",
5
5
  "scripts": {
6
6
  "start": "expo start",
@@ -0,0 +1,253 @@
1
+ import React, { useCallback, useState } from "react";
2
+ import {
3
+ StyleSheet,
4
+ View,
5
+ Text,
6
+ StyleProp,
7
+ ViewStyle,
8
+ TextStyle,
9
+ } from "react-native";
10
+ import { Gesture, GestureDetector } from "react-native-gesture-handler";
11
+ import Animated, {
12
+ runOnJS,
13
+ useAnimatedStyle,
14
+ useSharedValue,
15
+ } from "react-native-reanimated";
16
+ import { ThemeType, useTheme } from "../../theme";
17
+
18
+ const LABEL_HEIGHT = 26; // Default height for the label area above the thumb
19
+
20
+ export interface RangeSliderProps {
21
+ // --- Core Functionality ---
22
+ /** The minimum value of the slider. */
23
+ min: number;
24
+ /** The maximum value of the slider. */
25
+ max: number;
26
+ /** The increment value for each step of the slider. */
27
+ step?: number;
28
+ /** The total width of the slider component in pixels. */
29
+ sliderWidth: number;
30
+ /** The initial value for the left (minimum) thumb. */
31
+ initialMinValue: number;
32
+ /** The initial value for the right (maximum) thumb. */
33
+ initialMaxValue: number;
34
+ /** Callback function triggered when the user releases a thumb, returning the new min and max values. */
35
+ onValueChange: (values: { min: number; max: number }) => void;
36
+
37
+ // --- Sizing ---
38
+ /** The diameter of the draggable thumb. */
39
+ thumbSize?: number;
40
+ /** The height of the slider rail. */
41
+ railHeight?: number;
42
+
43
+ // --- Styling ---
44
+ /** Custom style for the main container. */
45
+ containerStyle?: StyleProp<ViewStyle>;
46
+ /** Custom style for the inactive part of the rail. */
47
+ railStyle?: StyleProp<ViewStyle>;
48
+ /** Custom style for the active (selected) part of the rail. */
49
+ activeRailStyle?: StyleProp<ViewStyle>;
50
+ /** Custom style for the thumbs. Overrides the default themed thumb. */
51
+ thumbStyle?: StyleProp<ViewStyle>;
52
+ /** Custom style for the container of the value labels. */
53
+ labelContainerStyle?: StyleProp<ViewStyle>;
54
+ /** Custom style for the text inside the labels. */
55
+ labelTextStyle?: StyleProp<TextStyle>;
56
+ }
57
+
58
+ const RangeSlider: React.FC<RangeSliderProps> = ({
59
+ // Core props
60
+ min,
61
+ max,
62
+ step = 1,
63
+ sliderWidth,
64
+ initialMinValue,
65
+ initialMaxValue,
66
+ onValueChange,
67
+ // Sizing props
68
+ thumbSize = 28,
69
+ railHeight = 6,
70
+ // Styling props
71
+ containerStyle,
72
+ railStyle,
73
+ activeRailStyle,
74
+ thumbStyle,
75
+ labelContainerStyle,
76
+ labelTextStyle,
77
+ }) => {
78
+ const { theme } = useTheme();
79
+ const styles = getStyles(theme, thumbSize, railHeight);
80
+
81
+ // State for labels, allowing them to have dynamic width
82
+ const [leftLabel, setLeftLabel] = useState(initialMinValue.toLocaleString());
83
+ const [rightLabel, setRightLabel] = useState(
84
+ initialMaxValue.toLocaleString()
85
+ );
86
+
87
+ // --- Worklets for calculations ---
88
+ const valueToPosition = useCallback(
89
+ (value: number) => {
90
+ "worklet";
91
+ return ((value - min) / (max - min)) * sliderWidth;
92
+ },
93
+ [min, max, sliderWidth]
94
+ );
95
+
96
+ const positionToValue = useCallback(
97
+ (position: number) => {
98
+ "worklet";
99
+ const rawValue = (position / sliderWidth) * (max - min) + min;
100
+ return Math.round(rawValue / step) * step;
101
+ },
102
+ [min, max, step, sliderWidth]
103
+ );
104
+
105
+ // --- Shared Values for Animation ---
106
+ const leftPosition = useSharedValue(valueToPosition(initialMinValue));
107
+ const rightPosition = useSharedValue(valueToPosition(initialMaxValue));
108
+ const context = useSharedValue({ x: 0 });
109
+ const activeThumb = useSharedValue<"left" | "right" | null>(null);
110
+
111
+ // --- Pan Gesture Handler ---
112
+ const panGesture = Gesture.Pan()
113
+ .onBegin((e) => {
114
+ // Determine which thumb is closer to the touch point
115
+ const distToLeft = Math.abs(e.x - leftPosition.value);
116
+ const distToRight = Math.abs(e.x - rightPosition.value);
117
+ if (distToLeft <= distToRight) {
118
+ activeThumb.value = "left";
119
+ context.value = { x: leftPosition.value };
120
+ } else {
121
+ activeThumb.value = "right";
122
+ context.value = { x: rightPosition.value };
123
+ }
124
+ })
125
+ .onUpdate((e) => {
126
+ if (activeThumb.value === null) return;
127
+ const newPos = context.value.x + e.translationX;
128
+
129
+ // Update the correct thumb's position and label
130
+ if (activeThumb.value === "left") {
131
+ const clampedPos = Math.max(0, Math.min(newPos, rightPosition.value));
132
+ leftPosition.value = clampedPos;
133
+ runOnJS(setLeftLabel)(positionToValue(clampedPos).toLocaleString());
134
+ } else {
135
+ const clampedPos = Math.min(
136
+ sliderWidth,
137
+ Math.max(newPos, leftPosition.value)
138
+ );
139
+ rightPosition.value = clampedPos;
140
+ runOnJS(setRightLabel)(positionToValue(clampedPos).toLocaleString());
141
+ }
142
+ })
143
+ .onEnd(() => {
144
+ if (activeThumb.value === null) return;
145
+ // Finalize values and call the onValueChange callback
146
+ const finalLeftValue = positionToValue(leftPosition.value);
147
+ const finalRightValue = positionToValue(rightPosition.value);
148
+ runOnJS(onValueChange)({ min: finalLeftValue, max: finalRightValue });
149
+ activeThumb.value = null;
150
+ });
151
+
152
+ // --- Animated Styles ---
153
+ const animatedLeftThumbStyle = useAnimatedStyle(() => ({
154
+ transform: [{ translateX: leftPosition.value }],
155
+ }));
156
+
157
+ const animatedRightThumbStyle = useAnimatedStyle(() => ({
158
+ // Adjust position to account for the thumb's own width
159
+ transform: [{ translateX: rightPosition.value - thumbSize }],
160
+ }));
161
+
162
+ const animatedActiveRailStyle = useAnimatedStyle(() => ({
163
+ left: leftPosition.value,
164
+ right: sliderWidth - rightPosition.value,
165
+ }));
166
+
167
+ return (
168
+ <GestureDetector gesture={panGesture}>
169
+ <View style={[styles.container, { width: sliderWidth }, containerStyle]}>
170
+ <View style={styles.railContainer}>
171
+ <View style={[styles.rail, railStyle]} />
172
+ <Animated.View
173
+ style={[
174
+ styles.activeRail,
175
+ animatedActiveRailStyle,
176
+ activeRailStyle,
177
+ ]}
178
+ />
179
+ </View>
180
+
181
+ {/* Left Thumb */}
182
+ <Animated.View style={[styles.thumbContainer, animatedLeftThumbStyle]}>
183
+ <View style={[styles.labelContainer, labelContainerStyle]}>
184
+ <Text style={[styles.labelText, labelTextStyle]} numberOfLines={1}>
185
+ {leftLabel}
186
+ </Text>
187
+ </View>
188
+ <View style={[styles.thumb, thumbStyle]} />
189
+ </Animated.View>
190
+
191
+ {/* Right Thumb */}
192
+ <Animated.View style={[styles.thumbContainer, animatedRightThumbStyle]}>
193
+ <View style={[styles.labelContainer, labelContainerStyle]}>
194
+ <Text style={[styles.labelText, labelTextStyle]} numberOfLines={1}>
195
+ {rightLabel}
196
+ </Text>
197
+ </View>
198
+ <View style={[styles.thumb, thumbStyle]} />
199
+ </Animated.View>
200
+ </View>
201
+ </GestureDetector>
202
+ );
203
+ };
204
+
205
+ const getStyles = (theme: ThemeType, thumbSize: number, railHeight: number) =>
206
+ StyleSheet.create({
207
+ container: {
208
+ height: LABEL_HEIGHT + thumbSize,
209
+ justifyContent: "center",
210
+ },
211
+ railContainer: {
212
+ justifyContent: "center",
213
+ },
214
+ rail: {
215
+ height: railHeight,
216
+ borderRadius: railHeight / 2,
217
+ backgroundColor: theme.surfaceVariant,
218
+ },
219
+ activeRail: {
220
+ height: railHeight,
221
+ backgroundColor: theme.primary,
222
+ position: "absolute",
223
+ },
224
+ thumbContainer: {
225
+ position: "absolute",
226
+ alignItems: "center",
227
+ // Center the thumb visually on its value point
228
+ transform: [{ translateX: -thumbSize / 2 }],
229
+ },
230
+ labelContainer: {
231
+ position: "absolute",
232
+ bottom: thumbSize + 4,
233
+ backgroundColor: theme.onBackground,
234
+ paddingHorizontal: 10,
235
+ paddingVertical: 4,
236
+ borderRadius: 4,
237
+ },
238
+ labelText: {
239
+ color: theme.background,
240
+ fontSize: 14,
241
+ fontWeight: "bold",
242
+ },
243
+ thumb: {
244
+ width: thumbSize,
245
+ height: thumbSize,
246
+ borderRadius: thumbSize / 2,
247
+ backgroundColor: theme.background,
248
+ borderColor: theme.primary,
249
+ borderWidth: 5,
250
+ },
251
+ });
252
+
253
+ export default RangeSlider;
@@ -0,0 +1,2 @@
1
+ export { default as RangeSlider } from "./RangeSlider";
2
+ export * from "./RangeSlider";
@@ -19,4 +19,5 @@ export * from "./Skeleton";
19
19
  export * from "./CustomIcon"
20
20
  export * from "./CarouselCardStack";
21
21
  export * from "./TravelBooking";
22
- export * from "./DateRangePicker";
22
+ export * from "./DateRangePicker";
23
+ export * from "./RangeSlider";