@momo-kits/slider 0.77.2 → 0.77.3

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 ADDED
@@ -0,0 +1,36 @@
1
+ import React, {PureComponent} from 'react';
2
+ import {View} from 'react-native';
3
+ import {Shadow, Text, Colors, Spacing, Radius} from '@momo-kits/foundation';
4
+
5
+ class Label extends PureComponent {
6
+ state = {
7
+ value: Number.NaN,
8
+ };
9
+
10
+ setValue = (value: number) => {
11
+ this.setState({value});
12
+ };
13
+
14
+ render() {
15
+ const {...props} = this.props;
16
+ const {value} = this.state;
17
+
18
+ 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>
31
+ </View>
32
+ );
33
+ }
34
+ }
35
+
36
+ export default Label;
package/helpers.ts ADDED
@@ -0,0 +1,35 @@
1
+ export const isLowCloser = (
2
+ downX: number,
3
+ lowPosition: number,
4
+ highPosition: number,
5
+ ): boolean => {
6
+ if (lowPosition === highPosition) {
7
+ return downX < lowPosition;
8
+ }
9
+ const distanceFromLow = Math.abs(downX - lowPosition);
10
+ const distanceFromHigh = Math.abs(downX - highPosition);
11
+ return distanceFromLow < distanceFromHigh;
12
+ };
13
+
14
+ export const clamp = (value: number, min: number, max: number): number => {
15
+ return Math.min(Math.max(value, min), max);
16
+ };
17
+
18
+ export const getValueForPosition = (
19
+ positionInView: number,
20
+ containerWidth: number,
21
+ thumbWidth: number,
22
+ min: number,
23
+ max: number,
24
+ step: number,
25
+ ): number => {
26
+ const availableSpace = containerWidth - thumbWidth;
27
+ const relStepUnit = step / (max - min);
28
+ let relPosition = (positionInView - thumbWidth / 2) / availableSpace;
29
+ const relOffset = relPosition % relStepUnit;
30
+ relPosition -= relOffset;
31
+ if (relOffset / relStepUnit >= 0.5) {
32
+ relPosition += relStepUnit;
33
+ }
34
+ return clamp(min + Math.round(relPosition / relStepUnit) * step, min, max);
35
+ };
package/hooks.tsx ADDED
@@ -0,0 +1,198 @@
1
+ import React, {
2
+ useCallback,
3
+ useState,
4
+ useRef,
5
+ useMemo,
6
+ MutableRefObject,
7
+ ReactNode,
8
+ } from 'react';
9
+ import {Animated, I18nManager, View} from 'react-native';
10
+ import {clamp} from './helpers';
11
+ import styles from './styles';
12
+ import FollowerContainer from './Label';
13
+ import {Text} from '@momo-kits/foundation';
14
+
15
+ /**
16
+ * low and high state variables are fallbacks for props (props are not required).
17
+ * This hook ensures that current low and high are not out of [min, max] range.
18
+ * It returns an object which contains:
19
+ * - ref containing correct low, high, min, max and step to work with.
20
+ * - setLow and setHigh setters
21
+ * @param lowProp
22
+ * @param highProp
23
+ * @param min
24
+ * @param max
25
+ * @param step
26
+ * @returns {{inPropsRef: React.MutableRefObject<{high: (*|number), low: (*|number)}>, setLow: (function(number): undefined), setHigh: (function(number): undefined)}}
27
+ */
28
+ export const useLowHigh = (
29
+ lowProp: number | undefined,
30
+ highProp: number | undefined,
31
+ min: number,
32
+ max: number,
33
+ step: number,
34
+ ) => {
35
+ const validLowProp = lowProp === undefined ? min : clamp(lowProp, min, max);
36
+ const validHighProp =
37
+ highProp === undefined ? max : clamp(highProp, min, max);
38
+ const inPropsRef = useRef({
39
+ low: validLowProp,
40
+ high: validHighProp,
41
+ step,
42
+ // These 2 fields will be overwritten below.
43
+ min: validLowProp,
44
+ max: validHighProp,
45
+ });
46
+ const {low: lowState, high: highState} = inPropsRef.current;
47
+ const inPropsRefPrev = {lowPrev: lowState, highPrev: highState};
48
+
49
+ // Props have higher priority.
50
+ // If no props are passed, use internal state variables.
51
+ const low = clamp(lowProp === undefined ? lowState : lowProp, min, max);
52
+ const high = clamp(highProp === undefined ? highState : highProp, min, max);
53
+
54
+ // Always update values of refs so pan responder will have updated values
55
+ Object.assign(inPropsRef.current, {low, high, min, max});
56
+
57
+ const setLow = (value: number) => (inPropsRef.current.low = value);
58
+ const setHigh = (value: number) => (inPropsRef.current.high = value);
59
+ return {inPropsRef, inPropsRefPrev, setLow, setHigh};
60
+ };
61
+
62
+ /**
63
+ * Sets the current value of widthRef and calls the callback with new width parameter.
64
+ * @param widthRef
65
+ * @param callback
66
+ * @returns {function({nativeEvent: *}): void}
67
+ */
68
+ export const useWidthLayout = (
69
+ widthRef: MutableRefObject<number>,
70
+ callback?: (width: number) => void,
71
+ ) => {
72
+ return useCallback(
73
+ ({nativeEvent}) => {
74
+ const {
75
+ layout: {width},
76
+ } = nativeEvent;
77
+ const {current: w} = widthRef;
78
+ if (w !== width) {
79
+ widthRef.current = width;
80
+ if (callback) {
81
+ callback(width);
82
+ }
83
+ }
84
+ },
85
+ [callback, widthRef],
86
+ );
87
+ };
88
+
89
+ /**
90
+ * This hook creates a component which follows the thumb.
91
+ * Content renderer is passed to FollowerContainer which re-renders only it's content with setValue method.
92
+ * This allows to re-render only follower, instead of the whole slider with all children (thumb, rail, etc.).
93
+ * Returned update function should be called every time follower should be updated.
94
+ * @param containerWidthRef
95
+ * @param gestureStateRef
96
+ * @param isPressed
97
+ * @param allowOverflow
98
+ * @returns {[JSX.Element, function(*, *=): void]|*[]}
99
+ */
100
+ export const useThumbFollower = (
101
+ containerWidthRef: MutableRefObject<number>,
102
+ gestureStateRef: MutableRefObject<{lastValue: number; lastPosition: number}>,
103
+ isPressed: boolean,
104
+ allowOverflow: boolean,
105
+ ) => {
106
+ const xRef = useRef(new Animated.Value(0));
107
+ const widthRef = useRef(0);
108
+ const contentContainerRef = useRef<FollowerContainer | null>(null);
109
+
110
+ const {current: x} = xRef;
111
+
112
+ const update = useCallback(
113
+ (thumbPositionInView, value) => {
114
+ const {current: width} = widthRef;
115
+ const {current: containerWidth} = containerWidthRef;
116
+ const position = thumbPositionInView - width / 2;
117
+ xRef.current.setValue(
118
+ allowOverflow ? position : clamp(position, 0, containerWidth - width),
119
+ );
120
+ contentContainerRef.current?.setValue(value);
121
+ },
122
+ [widthRef, containerWidthRef, allowOverflow],
123
+ );
124
+
125
+ const handleLayout = useWidthLayout(widthRef, () => {
126
+ update(
127
+ gestureStateRef.current.lastPosition,
128
+ gestureStateRef.current.lastValue,
129
+ );
130
+ });
131
+
132
+ const transform = {transform: [{translateX: x}]};
133
+ const follower = (
134
+ <Animated.View style={[transform, {opacity: isPressed ? 1 : 0}]}>
135
+ <FollowerContainer onLayout={handleLayout} ref={contentContainerRef} />
136
+ </Animated.View>
137
+ );
138
+ return [follower, update];
139
+ };
140
+
141
+ interface InProps {
142
+ low: number;
143
+ high: number;
144
+ min: number;
145
+ max: number;
146
+ step: number;
147
+ }
148
+
149
+ export const useSelectedRail = (
150
+ inPropsRef: MutableRefObject<InProps>,
151
+ containerWidthRef: MutableRefObject<number>,
152
+ thumbWidth: number,
153
+ disableRange: boolean,
154
+ ) => {
155
+ const {current: left} = useRef(new Animated.Value(0));
156
+ const {current: right} = useRef(new Animated.Value(0));
157
+ const update = useCallback(() => {
158
+ const {low, high, min, max} = inPropsRef.current;
159
+ const {current: containerWidth} = containerWidthRef;
160
+ const fullScale = (max - min) / (containerWidth - thumbWidth);
161
+ const leftValue = (low - min) / fullScale;
162
+ const rightValue = (max - high) / fullScale;
163
+ left.setValue(disableRange ? 0 : leftValue);
164
+ right.setValue(
165
+ disableRange ? containerWidth - thumbWidth - leftValue : rightValue,
166
+ );
167
+ }, [inPropsRef, containerWidthRef, disableRange, thumbWidth, left, right]);
168
+ const styles = useMemo(
169
+ () => ({
170
+ position: 'absolute',
171
+ left: I18nManager.isRTL ? right : left,
172
+ right: I18nManager.isRTL ? left : right,
173
+ }),
174
+ [left, right],
175
+ );
176
+ return [styles, update];
177
+ };
178
+
179
+ /**
180
+ * @param floating
181
+ * @returns {{onLayout: ((function({nativeEvent: *}): void)|undefined), style: [*, {top}]}}
182
+ */
183
+ export const useLabelContainerProps = (floating: boolean) => {
184
+ const [labelContainerHeight, setLabelContainerHeight] = useState(0);
185
+ const onLayout = useCallback(({nativeEvent}) => {
186
+ const {
187
+ layout: {height},
188
+ } = nativeEvent;
189
+ setLabelContainerHeight(height);
190
+ }, []);
191
+
192
+ const top = floating ? -labelContainerHeight : 0;
193
+ const style = [
194
+ floating ? styles.labelFloatingContainer : styles.labelFixedContainer,
195
+ {top},
196
+ ];
197
+ return {style, onLayout: onLayout};
198
+ };
package/index.tsx ADDED
@@ -0,0 +1,344 @@
1
+ import React, {
2
+ memo,
3
+ ReactNode,
4
+ useCallback,
5
+ useContext,
6
+ useEffect,
7
+ useMemo,
8
+ useRef,
9
+ useState,
10
+ } from 'react';
11
+ import {
12
+ Animated,
13
+ GestureResponderEvent,
14
+ PanResponder,
15
+ PanResponderGestureState,
16
+ View,
17
+ ViewProps,
18
+ } from 'react-native';
19
+
20
+ import styles from './styles';
21
+ import {
22
+ useLabelContainerProps,
23
+ useLowHigh,
24
+ useSelectedRail,
25
+ useThumbFollower,
26
+ useWidthLayout,
27
+ } from './hooks';
28
+ import {clamp, getValueForPosition, isLowCloser} from './helpers';
29
+ import {ApplicationContext, Radius, Shadow} from '@momo-kits/foundation';
30
+
31
+ const trueFunc = () => true;
32
+ const falseFunc = () => false;
33
+
34
+ export interface SliderProps extends ViewProps {
35
+ min: number;
36
+ max: number;
37
+ minRange?: number;
38
+ step: number;
39
+ low?: number;
40
+ high?: number;
41
+ allowLabelOverflow?: boolean;
42
+ disableRange?: boolean;
43
+ disabled?: boolean;
44
+ floatingLabel?: boolean;
45
+ renderRail: () => ReactNode;
46
+ renderRailSelected: () => ReactNode;
47
+ onValueChanged?: (low: number, high: number, byUser: boolean) => void;
48
+ onSliderTouchStart?: (low: number, high: number) => void;
49
+ onSliderTouchEnd?: (low: number, high: number) => void;
50
+ }
51
+
52
+ const Slider: React.FC<SliderProps> = ({
53
+ min,
54
+ max,
55
+ minRange = 0,
56
+ step,
57
+ low: lowProp,
58
+ high: highProp,
59
+ floatingLabel = false,
60
+ allowLabelOverflow = false,
61
+ disableRange = false,
62
+ disabled = false,
63
+ onValueChanged,
64
+ onSliderTouchStart,
65
+ onSliderTouchEnd,
66
+ renderRail,
67
+ renderRailSelected,
68
+ ...restProps
69
+ }) => {
70
+ const {theme} = useContext(ApplicationContext);
71
+
72
+ const {inPropsRef, inPropsRefPrev, setLow, setHigh} = useLowHigh(
73
+ lowProp,
74
+ disableRange ? max : highProp,
75
+ min,
76
+ max,
77
+ step,
78
+ );
79
+ const lowThumbXRef = useRef(new Animated.Value(0));
80
+ const highThumbXRef = useRef(new Animated.Value(0));
81
+ const pointerX = useRef(new Animated.Value(0)).current;
82
+ const {current: lowThumbX} = lowThumbXRef;
83
+ const {current: highThumbX} = highThumbXRef;
84
+
85
+ const gestureStateRef = useRef({isLow: true, lastValue: 0, lastPosition: 0});
86
+ const [isPressed, setPressed] = useState(false);
87
+
88
+ const containerWidthRef = useRef(0);
89
+ const [thumbWidth, setThumbWidth] = useState(0);
90
+
91
+ const [selectedRailStyle, updateSelectedRail] = useSelectedRail(
92
+ inPropsRef,
93
+ containerWidthRef,
94
+ thumbWidth,
95
+ disableRange,
96
+ );
97
+
98
+ const updateThumbs = useCallback(() => {
99
+ const {current: containerWidth} = containerWidthRef;
100
+ if (!thumbWidth || !containerWidth) {
101
+ return;
102
+ }
103
+ const {low, high} = inPropsRef.current;
104
+ if (!disableRange) {
105
+ const {current: highThumbX} = highThumbXRef;
106
+ const highPosition =
107
+ ((high - min) / (max - min)) * (containerWidth - thumbWidth);
108
+ highThumbX.setValue(highPosition);
109
+ }
110
+ const {current: lowThumbX} = lowThumbXRef;
111
+ const lowPosition =
112
+ ((low - min) / (max - min)) * (containerWidth - thumbWidth);
113
+ lowThumbX.setValue(lowPosition);
114
+ updateSelectedRail();
115
+ onValueChanged?.(low, high, false);
116
+ }, [
117
+ disableRange,
118
+ inPropsRef,
119
+ max,
120
+ min,
121
+ onValueChanged,
122
+ thumbWidth,
123
+ updateSelectedRail,
124
+ ]);
125
+
126
+ useEffect(() => {
127
+ const {lowPrev, highPrev} = inPropsRefPrev;
128
+ if (
129
+ (lowProp !== undefined && lowProp !== lowPrev) ||
130
+ (highProp !== undefined && highProp !== highPrev)
131
+ ) {
132
+ updateThumbs();
133
+ }
134
+ }, [highProp, inPropsRefPrev.lowPrev, inPropsRefPrev.highPrev, lowProp]);
135
+
136
+ useEffect(() => {
137
+ updateThumbs();
138
+ }, [updateThumbs]);
139
+
140
+ const handleContainerLayout = useWidthLayout(containerWidthRef, updateThumbs);
141
+ const handleThumbLayout = useCallback(
142
+ ({nativeEvent}) => {
143
+ const {
144
+ layout: {width},
145
+ } = nativeEvent;
146
+ if (thumbWidth !== width) {
147
+ setThumbWidth(width);
148
+ }
149
+ },
150
+ [thumbWidth],
151
+ );
152
+
153
+ const lowStyles = useMemo(() => {
154
+ return {transform: [{translateX: lowThumbX}]};
155
+ }, [lowThumbX]);
156
+
157
+ const highStyles = useMemo(() => {
158
+ return disableRange
159
+ ? null
160
+ : [styles.highThumbContainer, {transform: [{translateX: highThumbX}]}];
161
+ }, [disableRange, highThumbX]);
162
+
163
+ const railContainerStyles = useMemo(() => {
164
+ return [styles.railsContainer, {marginHorizontal: thumbWidth / 2}];
165
+ }, [thumbWidth]);
166
+
167
+ const [labelView, labelUpdate] = useThumbFollower(
168
+ containerWidthRef,
169
+ gestureStateRef,
170
+ isPressed,
171
+ allowLabelOverflow,
172
+ );
173
+
174
+ const renderThumb = (name: string) => {
175
+ return (
176
+ <View
177
+ style={[
178
+ Shadow.Light,
179
+ {
180
+ width: 20,
181
+ height: 20,
182
+ borderRadius: Radius.M,
183
+ borderWidth: 4,
184
+ borderColor: theme.colors.background.surface,
185
+ backgroundColor: theme.colors.primary,
186
+ },
187
+ ]}
188
+ />
189
+ );
190
+ };
191
+
192
+ const lowThumb = renderThumb('low');
193
+ const highThumb = renderThumb('high');
194
+
195
+ const labelContainerProps = useLabelContainerProps(floatingLabel);
196
+
197
+ const {panHandlers} = useMemo(
198
+ () =>
199
+ PanResponder.create({
200
+ onStartShouldSetPanResponderCapture: falseFunc,
201
+ onMoveShouldSetPanResponderCapture: falseFunc,
202
+ onPanResponderTerminationRequest: falseFunc,
203
+ onPanResponderTerminate: trueFunc,
204
+ onShouldBlockNativeResponder: trueFunc,
205
+
206
+ onMoveShouldSetPanResponder: (
207
+ evt: GestureResponderEvent,
208
+ gestureState: PanResponderGestureState,
209
+ ) => Math.abs(gestureState.dx) > 2 * Math.abs(gestureState.dy),
210
+
211
+ onPanResponderGrant: ({nativeEvent}, gestureState) => {
212
+ if (disabled) {
213
+ return;
214
+ }
215
+ const {numberActiveTouches} = gestureState;
216
+ if (numberActiveTouches > 1) {
217
+ return;
218
+ }
219
+ setPressed(true);
220
+ const {current: lowThumbX} = lowThumbXRef;
221
+ const {current: highThumbX} = highThumbXRef;
222
+ const {locationX: downX, pageX} = nativeEvent;
223
+ const containerX = pageX - downX;
224
+
225
+ const {low, high, min, max} = inPropsRef.current;
226
+ onSliderTouchStart?.(low, high);
227
+ const containerWidth = containerWidthRef.current;
228
+
229
+ const lowPosition =
230
+ thumbWidth / 2 +
231
+ ((low - min) / (max - min)) * (containerWidth - thumbWidth);
232
+ const highPosition =
233
+ thumbWidth / 2 +
234
+ ((high - min) / (max - min)) * (containerWidth - thumbWidth);
235
+
236
+ const isLow =
237
+ disableRange || isLowCloser(downX, lowPosition, highPosition);
238
+ gestureStateRef.current.isLow = isLow;
239
+
240
+ const handlePositionChange = (positionInView: number) => {
241
+ const {low, high, min, max, step} = inPropsRef.current;
242
+ const minValue = isLow ? min : low + minRange;
243
+ const maxValue = isLow ? high - minRange : max;
244
+ const value = clamp(
245
+ getValueForPosition(
246
+ positionInView,
247
+ containerWidth,
248
+ thumbWidth,
249
+ min,
250
+ max,
251
+ step,
252
+ ),
253
+ minValue,
254
+ maxValue,
255
+ );
256
+ if (gestureStateRef.current.lastValue === value) {
257
+ return;
258
+ }
259
+ const availableSpace = containerWidth - thumbWidth;
260
+ const absolutePosition =
261
+ ((value - min) / (max - min)) * availableSpace;
262
+ gestureStateRef.current.lastValue = value;
263
+ gestureStateRef.current.lastPosition =
264
+ absolutePosition + thumbWidth / 2;
265
+ (isLow ? lowThumbX : highThumbX).setValue(absolutePosition);
266
+ onValueChanged?.(isLow ? value : low, isLow ? high : value, true);
267
+ (isLow ? setLow : setHigh)(value);
268
+ labelUpdate &&
269
+ labelUpdate(gestureStateRef.current.lastPosition, value);
270
+
271
+ updateSelectedRail();
272
+ };
273
+ handlePositionChange(downX);
274
+ pointerX.removeAllListeners();
275
+ pointerX.addListener(({value: pointerPosition}) => {
276
+ const positionInView = pointerPosition - containerX;
277
+ handlePositionChange(positionInView);
278
+ });
279
+ },
280
+
281
+ onPanResponderMove: disabled
282
+ ? undefined
283
+ : Animated.event([null, {moveX: pointerX}], {useNativeDriver: false}),
284
+
285
+ onPanResponderRelease: () => {
286
+ setPressed(false);
287
+ const {low, high} = inPropsRef.current;
288
+ onSliderTouchEnd?.(low, high);
289
+ },
290
+ }),
291
+ [
292
+ pointerX,
293
+ inPropsRef,
294
+ thumbWidth,
295
+ disableRange,
296
+ disabled,
297
+ onValueChanged,
298
+ setLow,
299
+ setHigh,
300
+ labelUpdate,
301
+ updateSelectedRail,
302
+ ],
303
+ );
304
+
305
+ const renderTrack = (color: string) => {
306
+ return (
307
+ <View
308
+ style={{
309
+ width: '100%',
310
+ height: 4,
311
+ borderRadius: Radius.L,
312
+ backgroundColor: color,
313
+ }}
314
+ />
315
+ );
316
+ };
317
+
318
+ return (
319
+ <View {...restProps}>
320
+ <View {...labelContainerProps}>{labelView}</View>
321
+ <View onLayout={handleContainerLayout} style={styles.controlsContainer}>
322
+ <View style={railContainerStyles}>
323
+ {renderTrack(theme.colors.background.default)}
324
+ <Animated.View style={selectedRailStyle}>
325
+ {renderTrack(theme.colors.primary)}
326
+ </Animated.View>
327
+ </View>
328
+ <Animated.View style={lowStyles} onLayout={handleThumbLayout}>
329
+ {lowThumb}
330
+ </Animated.View>
331
+ {!disableRange && (
332
+ <Animated.View style={highStyles}>{highThumb}</Animated.View>
333
+ )}
334
+ <View
335
+ {...panHandlers}
336
+ style={styles.touchableArea}
337
+ collapsable={false}
338
+ />
339
+ </View>
340
+ </View>
341
+ );
342
+ };
343
+
344
+ export default memo(Slider);
package/package.json CHANGED
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "name": "@momo-kits/slider",
3
- "version": "0.77.2",
3
+ "version": "0.77.3",
4
4
  "private": false,
5
- "main": "index.js",
5
+ "main": "index.tsx",
6
6
  "dependencies": {},
7
7
  "peerDependencies": {
8
- "@momo-kits/core-v2": ">=0.0.5-beta",
9
- "lodash": "^4.17.15",
8
+ "@momo-kits/foundation": "latest",
10
9
  "prop-types": "^15.7.2",
11
10
  "react": "16.9.0",
12
11
  "react-native": ">=0.55"
package/publish.sh CHANGED
@@ -26,4 +26,4 @@ cd ..
26
26
  rm -rf dist
27
27
 
28
28
 
29
- ##curl -X POST -H 'Content-Type: application/json' 'https://chat.googleapis.com/v1/spaces/AAAAbP8987c/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=UGSFRvk_oYb9uGsAgs31bVvMm6jDkmD8zihGm3eyaQA%3D&threadKey=JoaXTEYaNNkl' -d '{"text": "@momo-kits/stepper new version release: '*"$VERSION"*' https://www.npmjs.com/package/@momo-kits/stepper"}'
29
+ ##curl -X POST -H 'Content-Type: application/json' 'https://chat.googleapis.com/v1/spaces/AAAAbP8987c/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=UGSFRvk_oYb9uGsAgs31bVvMm6jDkmD8zihGm3eyaQA%3D&threadKey=JoaXTEYaNNkl' -d '{"text": "@momo-kits/slider new version release: '*"$VERSION"*' https://www.npmjs.com/package/@momo-kits/slider"}'
package/styles.ts ADDED
@@ -0,0 +1,29 @@
1
+ import {I18nManager, StyleSheet} from 'react-native';
2
+
3
+ export default StyleSheet.create({
4
+ controlsContainer: {
5
+ flexDirection: 'row',
6
+ justifyContent: I18nManager.isRTL ? 'flex-end' : 'flex-start',
7
+ alignItems: 'center',
8
+ },
9
+ highThumbContainer: {
10
+ position: 'absolute',
11
+ },
12
+ railsContainer: {
13
+ ...StyleSheet.absoluteFillObject,
14
+ flexDirection: 'row',
15
+ alignItems: 'center',
16
+ },
17
+ labelFixedContainer: {
18
+ alignItems: I18nManager.isRTL ? 'flex-end' : 'flex-start',
19
+ },
20
+ labelFloatingContainer: {
21
+ position: 'absolute',
22
+ left: 0,
23
+ right: 0,
24
+ alignItems: I18nManager.isRTL ? 'flex-end' : 'flex-start',
25
+ },
26
+ touchableArea: {
27
+ ...StyleSheet.absoluteFillObject,
28
+ },
29
+ });