related-ui-components 3.2.9 → 3.3.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.
- package/lib/module/components/Card/templates/SelaDealCard.js +0 -10
- package/lib/module/components/Card/templates/SelaDealCard.js.map +1 -1
- package/lib/module/components/RangeSlider/RangeSlider.js +260 -26
- package/lib/module/components/RangeSlider/RangeSlider.js.map +1 -1
- package/lib/module/components/RangeSlider/SliderLabel.js +93 -30
- package/lib/module/components/RangeSlider/SliderLabel.js.map +1 -1
- package/lib/typescript/src/components/Card/templates/SelaDealCard.d.ts.map +1 -1
- package/lib/typescript/src/components/RangeSlider/RangeSlider.d.ts +13 -0
- package/lib/typescript/src/components/RangeSlider/RangeSlider.d.ts.map +1 -1
- package/lib/typescript/src/components/RangeSlider/SliderLabel.d.ts.map +1 -1
- package/package.json +81 -81
- package/src/components/Card/templates/SelaDealCard.tsx +0 -11
- package/src/components/RangeSlider/RangeSlider.tsx +349 -50
- package/src/components/RangeSlider/SliderLabel.tsx +122 -38
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { I18nManager, StyleSheet, Text, View } from "react-native";
|
|
3
3
|
import Animated, {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
SharedValue,
|
|
5
|
+
useAnimatedStyle,
|
|
6
|
+
useDerivedValue,
|
|
7
|
+
useSharedValue,
|
|
8
8
|
} from "react-native-reanimated";
|
|
9
9
|
import { ThemeType, useTheme } from "../../theme";
|
|
10
10
|
|
|
11
11
|
const LABEL_HEIGHT = 26;
|
|
12
|
+
const LABEL_PADDING = 8;
|
|
13
|
+
const MIN_GAP = 4;
|
|
12
14
|
|
|
13
15
|
interface SliderLabelsProps {
|
|
14
16
|
leftValue: string;
|
|
@@ -17,51 +19,100 @@ interface SliderLabelsProps {
|
|
|
17
19
|
rightPosition: SharedValue<number>;
|
|
18
20
|
sliderWidth: number;
|
|
19
21
|
thumbSize: number;
|
|
20
|
-
theme?: ThemeType
|
|
22
|
+
theme?: ThemeType;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
interface
|
|
25
|
+
interface SingleLabelProps {
|
|
24
26
|
value: string;
|
|
25
27
|
position: SharedValue<number>;
|
|
26
28
|
sliderWidth: number;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
onWidthChange: (width: number) => void;
|
|
30
|
+
isVisible: SharedValue<boolean>;
|
|
31
|
+
theme: ThemeType;
|
|
32
|
+
}
|
|
29
33
|
|
|
34
|
+
interface MergedLabelProps {
|
|
35
|
+
leftValue: string;
|
|
36
|
+
rightValue: string;
|
|
37
|
+
leftPosition: SharedValue<number>;
|
|
38
|
+
rightPosition: SharedValue<number>;
|
|
39
|
+
sliderWidth: number;
|
|
40
|
+
isVisible: SharedValue<boolean>;
|
|
41
|
+
theme: ThemeType;
|
|
30
42
|
}
|
|
31
43
|
|
|
32
|
-
const
|
|
44
|
+
const SingleLabel: React.FC<SingleLabelProps> = ({
|
|
33
45
|
value,
|
|
34
46
|
position,
|
|
35
47
|
sliderWidth,
|
|
36
|
-
|
|
37
|
-
|
|
48
|
+
onWidthChange,
|
|
49
|
+
isVisible,
|
|
50
|
+
theme,
|
|
38
51
|
}) => {
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const currTheme = theme || defaultTheme;
|
|
42
|
-
const styles = getStyles(currTheme);
|
|
52
|
+
const styles = getStyles(theme);
|
|
53
|
+
const localWidth = useSharedValue(0);
|
|
43
54
|
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
const
|
|
55
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
56
|
+
const halfLabel = localWidth.value / 2;
|
|
57
|
+
const rawCenter = position.value;
|
|
58
|
+
const shifted = rawCenter - halfLabel;
|
|
59
|
+
const left = Math.min(Math.max(shifted, 0), sliderWidth - localWidth.value);
|
|
47
60
|
|
|
61
|
+
return {
|
|
62
|
+
left,
|
|
63
|
+
opacity: isVisible.value ? 1 : 0,
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<Animated.View
|
|
69
|
+
style={[styles.labelContainer, animatedStyle]}
|
|
70
|
+
onLayout={(e) => {
|
|
71
|
+
const width = e.nativeEvent.layout.width;
|
|
72
|
+
localWidth.value = width;
|
|
73
|
+
onWidthChange(width);
|
|
74
|
+
}}
|
|
75
|
+
>
|
|
76
|
+
<Text style={styles.labelText}>{value}</Text>
|
|
77
|
+
</Animated.View>
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const MergedLabel: React.FC<MergedLabelProps> = ({
|
|
82
|
+
leftValue,
|
|
83
|
+
rightValue,
|
|
84
|
+
leftPosition,
|
|
85
|
+
rightPosition,
|
|
86
|
+
sliderWidth,
|
|
87
|
+
isVisible,
|
|
88
|
+
theme,
|
|
89
|
+
}) => {
|
|
90
|
+
const styles = getStyles(theme);
|
|
91
|
+
const labelWidth = useSharedValue(0);
|
|
92
|
+
|
|
93
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
94
|
+
const centerPosition = (leftPosition.value + rightPosition.value) / 2;
|
|
95
|
+
const halfLabel = labelWidth.value / 2;
|
|
96
|
+
const shifted = centerPosition - halfLabel;
|
|
48
97
|
const left = Math.min(Math.max(shifted, 0), sliderWidth - labelWidth.value);
|
|
49
98
|
|
|
50
99
|
return {
|
|
51
|
-
left
|
|
100
|
+
left,
|
|
101
|
+
opacity: isVisible.value ? 1 : 0,
|
|
52
102
|
};
|
|
53
103
|
});
|
|
54
104
|
|
|
105
|
+
const displayText =
|
|
106
|
+
leftValue === rightValue ? leftValue : `${leftValue} - ${rightValue}`;
|
|
107
|
+
|
|
55
108
|
return (
|
|
56
109
|
<Animated.View
|
|
57
|
-
style={[styles.labelContainer,
|
|
110
|
+
style={[styles.labelContainer, animatedStyle]}
|
|
58
111
|
onLayout={(e) => {
|
|
59
112
|
labelWidth.value = e.nativeEvent.layout.width;
|
|
60
113
|
}}
|
|
61
114
|
>
|
|
62
|
-
<Text style={styles.labelText}>
|
|
63
|
-
{value}
|
|
64
|
-
</Text>
|
|
115
|
+
<Text style={styles.labelText}>{displayText}</Text>
|
|
65
116
|
</Animated.View>
|
|
66
117
|
);
|
|
67
118
|
};
|
|
@@ -77,29 +128,62 @@ export const SliderLabels: React.FC<SliderLabelsProps> = ({
|
|
|
77
128
|
}) => {
|
|
78
129
|
const { theme: defaultTheme } = useTheme();
|
|
79
130
|
const currTheme = theme || defaultTheme;
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
|
|
131
|
+
const isRTL = I18nManager.isRTL;
|
|
132
|
+
|
|
133
|
+
// Track label widths in parent for overlap calculation
|
|
134
|
+
const leftLabelWidth = useSharedValue(0);
|
|
135
|
+
const rightLabelWidth = useSharedValue(0);
|
|
136
|
+
|
|
137
|
+
const shouldMerge = useDerivedValue(() => {
|
|
138
|
+
const leftCenter = leftPosition.value;
|
|
139
|
+
const rightCenter = rightPosition.value;
|
|
140
|
+
|
|
141
|
+
const leftEnd = leftCenter + leftLabelWidth.value / 2;
|
|
142
|
+
const rightStart = rightCenter - rightLabelWidth.value / 2;
|
|
143
|
+
|
|
144
|
+
if (isRTL) {
|
|
145
|
+
const rtlLeftEnd = rightCenter + rightLabelWidth.value / 2;
|
|
146
|
+
const rtlRightStart = leftCenter - leftLabelWidth.value / 2;
|
|
147
|
+
return rtlRightStart - rtlLeftEnd < MIN_GAP;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return rightStart - leftEnd < MIN_GAP;
|
|
86
151
|
});
|
|
87
152
|
|
|
88
|
-
const
|
|
153
|
+
const showSeparate = useDerivedValue(() => !shouldMerge.value);
|
|
154
|
+
const showMerged = useDerivedValue(() => shouldMerge.value);
|
|
89
155
|
|
|
90
156
|
return (
|
|
91
|
-
<View style={
|
|
92
|
-
<
|
|
157
|
+
<View style={getStyles(currTheme).wrapper} pointerEvents="none">
|
|
158
|
+
<SingleLabel
|
|
93
159
|
value={leftValue}
|
|
94
|
-
|
|
95
|
-
position={isRTL ? leftThumbLeftPosition : leftPosition}
|
|
160
|
+
position={leftPosition}
|
|
96
161
|
sliderWidth={sliderWidth}
|
|
162
|
+
onWidthChange={(width) => {
|
|
163
|
+
leftLabelWidth.value = width;
|
|
164
|
+
}}
|
|
165
|
+
isVisible={showSeparate}
|
|
166
|
+
theme={currTheme}
|
|
97
167
|
/>
|
|
98
|
-
<
|
|
168
|
+
<SingleLabel
|
|
99
169
|
value={rightValue}
|
|
100
|
-
|
|
101
|
-
|
|
170
|
+
position={rightPosition}
|
|
171
|
+
sliderWidth={sliderWidth}
|
|
172
|
+
onWidthChange={(width) => {
|
|
173
|
+
rightLabelWidth.value = width;
|
|
174
|
+
}}
|
|
175
|
+
isVisible={showSeparate}
|
|
176
|
+
theme={currTheme}
|
|
177
|
+
/>
|
|
178
|
+
|
|
179
|
+
<MergedLabel
|
|
180
|
+
leftValue={leftValue}
|
|
181
|
+
rightValue={rightValue}
|
|
182
|
+
leftPosition={leftPosition}
|
|
183
|
+
rightPosition={rightPosition}
|
|
102
184
|
sliderWidth={sliderWidth}
|
|
185
|
+
isVisible={showMerged}
|
|
186
|
+
theme={currTheme}
|
|
103
187
|
/>
|
|
104
188
|
</View>
|
|
105
189
|
);
|
|
@@ -119,7 +203,7 @@ const getStyles = (theme: ThemeType) =>
|
|
|
119
203
|
},
|
|
120
204
|
labelText: {
|
|
121
205
|
backgroundColor: theme.surface,
|
|
122
|
-
paddingHorizontal:
|
|
206
|
+
paddingHorizontal: LABEL_PADDING,
|
|
123
207
|
paddingVertical: 4,
|
|
124
208
|
borderRadius: 4,
|
|
125
209
|
color: theme.onSurface,
|