@react-native-ohos/slider 5.1.2-rc.1 → 5.1.2-rc.2
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/CHANGELOG.md +187 -183
- package/COMMITTERS.md +5 -5
- package/LICENSE +8 -8
- package/OAT.xml +72 -72
- package/README.OpenSource +10 -10
- package/README.md +12 -12
- package/babel.config.json +3 -3
- package/dist/Slider.js +1 -1
- package/dist/components/StepNumber.js +1 -1
- package/dist/components/StepsIndicator.js +1 -1
- package/dist/components/TrackMark.js +1 -1
- package/dist/utils/styles.js +1 -1
- package/example/.eslintrc +18 -18
- package/example/.node-version +6 -6
- package/example/.prettierrc.js +7 -7
- package/example/.watchmanconfig +5 -5
- package/example/app.json +3 -3
- package/example/babel.config.js +9 -9
- package/example/contexts.ts +9 -9
- package/example/harmony/AppScope/app.json5 +10 -10
- package/example/harmony/AppScope/resources/base/element/string.json +8 -8
- package/example/harmony/build-profile.template.json5 +35 -35
- package/example/harmony/codelinter.json +32 -32
- package/example/harmony/entry/build-profile.json5 +21 -21
- package/example/harmony/entry/hvigorfile.ts +8 -8
- package/example/harmony/entry/oh-package.json5 +10 -10
- package/example/harmony/entry/src/main/cpp/CMakeLists.txt +41 -41
- package/example/harmony/entry/src/main/cpp/PackageProvider.cpp +16 -16
- package/example/harmony/entry/src/main/ets/RNPackagesFactory.ets +13 -13
- package/example/harmony/entry/src/main/ets/entryability/EntryAbility.ets +27 -27
- package/example/harmony/entry/src/main/ets/pages/Index.ets +125 -125
- package/example/harmony/entry/src/main/ets/pages/SurfaceDeadlockTest.ets +135 -135
- package/example/harmony/entry/src/main/ets/pages/TouchDisplayer.ets +43 -43
- package/example/harmony/entry/src/main/module.json5 +51 -51
- package/example/harmony/entry/src/main/resources/base/element/color.json +7 -7
- package/example/harmony/entry/src/main/resources/base/element/string.json +15 -15
- package/example/harmony/entry/src/main/resources/base/profile/main_pages.json +5 -5
- package/example/harmony/format.ps1 +17 -17
- package/example/harmony/hvigor/hvigor-config.json5 +20 -20
- package/example/harmony/hvigorfile.ts +8 -8
- package/example/harmony/oh-package.json5 +11 -11
- package/example/index.js +10 -10
- package/example/jest.config.js +11 -11
- package/example/metro.config.js +30 -30
- package/example/package.json +58 -58
- package/example/react-native.config.js +11 -11
- package/example/scripts/create-build-profile.js +45 -45
- package/example/src/index.tsx +22 -22
- package/example/tsconfig.json +19 -19
- package/harmony/slider/oh-package.json5 +10 -10
- package/harmony/slider.har +0 -0
- package/package.json +92 -92
- package/react-native.config.js +11 -11
- package/src/RNCSliderNativeComponent.ts +51 -51
- package/src/Slider.tsx +356 -356
- package/src/components/StepNumber.tsx +23 -23
- package/src/components/StepsIndicator.tsx +89 -89
- package/src/components/TrackMark.tsx +59 -59
- package/src/index.ts +9 -9
- package/src/utils/constants.ts +17 -17
- package/src/utils/styles.ts +61 -61
- package/tsconfig.json +23 -23
- package/typings/index.d.ts +214 -214
- package/.github/Examples/Slider-Android-Example.gif +0 -0
- package/.github/Examples/Slider-Web-Example.gif +0 -0
- package/.github/Examples/Slider-Windows-Example.gif +0 -0
- package/.github/Examples/Slider-iOS-Example.gif +0 -0
- package/.github/ISSUE_TEMPLATE/BUG_REPORT.md +0 -38
- package/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +0 -14
- package/.github/ISSUE_TEMPLATE/QUESTION.md +0 -9
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -11
- package/.github/workflows/ReactNativeSlider-CI.yml +0 -231
- package/harmony/slider/README.OpenSource +0 -11
package/src/Slider.tsx
CHANGED
|
@@ -1,356 +1,356 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) 2025 Huawei Device Co., Ltd. All rights reserved
|
|
3
|
-
* Use of this source code is governed by a MIT license that can be
|
|
4
|
-
* found in the LICENSE file.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import React, {useEffect, useState} from 'react';
|
|
8
|
-
import {
|
|
9
|
-
Image,
|
|
10
|
-
Platform,
|
|
11
|
-
AccessibilityActionEvent,
|
|
12
|
-
ViewProps,
|
|
13
|
-
ViewStyle,
|
|
14
|
-
ColorValue,
|
|
15
|
-
NativeSyntheticEvent,
|
|
16
|
-
StyleProp,
|
|
17
|
-
View,
|
|
18
|
-
ImageSource,
|
|
19
|
-
ImageSourcePropType,
|
|
20
|
-
} from 'react-native';
|
|
21
|
-
import RCTSliderNativeComponent from './index';
|
|
22
|
-
|
|
23
|
-
import type {FC, Ref} from 'react';
|
|
24
|
-
import {MarkerProps} from './components/TrackMark';
|
|
25
|
-
import {StepsIndicator} from './components/StepsIndicator';
|
|
26
|
-
import {styles} from './utils/styles';
|
|
27
|
-
import {constants} from './utils/constants';
|
|
28
|
-
|
|
29
|
-
type Event = NativeSyntheticEvent<
|
|
30
|
-
Readonly<{
|
|
31
|
-
value: number;
|
|
32
|
-
/**
|
|
33
|
-
* Android Only.
|
|
34
|
-
*/
|
|
35
|
-
fromUser?: boolean;
|
|
36
|
-
}>
|
|
37
|
-
>;
|
|
38
|
-
|
|
39
|
-
type WindowsProps = Readonly<{
|
|
40
|
-
/**
|
|
41
|
-
* If true the slider will be inverted.
|
|
42
|
-
* Default value is false.
|
|
43
|
-
*/
|
|
44
|
-
vertical?: boolean;
|
|
45
|
-
}>;
|
|
46
|
-
|
|
47
|
-
type IOSProps = Readonly<{
|
|
48
|
-
/**
|
|
49
|
-
* Assigns a single image for the track. Only static images are supported.
|
|
50
|
-
* The center pixel of the image will be stretched to fill the track.
|
|
51
|
-
*/
|
|
52
|
-
trackImage?: ImageSource;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Assigns a minimum track image. Only static images are supported. The
|
|
56
|
-
* rightmost pixel of the image will be stretched to fill the track.
|
|
57
|
-
*/
|
|
58
|
-
minimumTrackImage?: ImageSource;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Assigns a maximum track image. Only static images are supported. The
|
|
62
|
-
* leftmost pixel of the image will be stretched to fill the track.
|
|
63
|
-
*/
|
|
64
|
-
maximumTrackImage?: ImageSource;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Permits tapping on the slider track to set the thumb position.
|
|
68
|
-
* Defaults to false on iOS. No effect on Android or Windows.
|
|
69
|
-
*/
|
|
70
|
-
tapToSeek?: boolean;
|
|
71
|
-
}>;
|
|
72
|
-
|
|
73
|
-
type Props = ViewProps &
|
|
74
|
-
IOSProps &
|
|
75
|
-
WindowsProps &
|
|
76
|
-
Readonly<{
|
|
77
|
-
/**
|
|
78
|
-
* Used to style and layout the `Slider`. See `StyleSheet.js` and
|
|
79
|
-
* `DeprecatedViewStylePropTypes.js` for more info.
|
|
80
|
-
*/
|
|
81
|
-
style?: StyleProp<ViewStyle>;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Write-only property representing the value of the slider.
|
|
85
|
-
* Can be used to programmatically control the position of the thumb.
|
|
86
|
-
* Entered once at the beginning still acts as an initial value.
|
|
87
|
-
* The value should be between minimumValue and maximumValue,
|
|
88
|
-
* which default to 0 and 1 respectively.
|
|
89
|
-
* Default value is 0.
|
|
90
|
-
*
|
|
91
|
-
* This is not a controlled component, you don't need to update the
|
|
92
|
-
* value during dragging.
|
|
93
|
-
*/
|
|
94
|
-
value?: number;
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Step value of the slider. The value should be
|
|
98
|
-
* between 0 and (maximumValue - minimumValue).
|
|
99
|
-
* Default value is 0.
|
|
100
|
-
*/
|
|
101
|
-
step?: number;
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Initial minimum value of the slider. Default value is 0.
|
|
105
|
-
*/
|
|
106
|
-
minimumValue?: number;
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Initial maximum value of the slider. Default value is 1.
|
|
110
|
-
*/
|
|
111
|
-
maximumValue?: number;
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* The lower limit value of the slider. The user won't be able to slide below this limit.
|
|
115
|
-
*/
|
|
116
|
-
lowerLimit?: number;
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* The upper limit value of the slider. The user won't be able to slide above this limit.
|
|
120
|
-
*/
|
|
121
|
-
upperLimit?: number;
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* The color used for the track to the left of the button.
|
|
125
|
-
* Overrides the default blue gradient image on iOS.
|
|
126
|
-
*/
|
|
127
|
-
minimumTrackTintColor?: ColorValue;
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* The color used for the track to the right of the button.
|
|
131
|
-
* Overrides the default blue gradient image on iOS.
|
|
132
|
-
*/
|
|
133
|
-
maximumTrackTintColor?: ColorValue;
|
|
134
|
-
/**
|
|
135
|
-
* The color used to tint the default thumb images on iOS, or the
|
|
136
|
-
* color of the foreground switch grip on Android.
|
|
137
|
-
*/
|
|
138
|
-
thumbTintColor?: ColorValue;
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* If true the user won't be able to move the slider.
|
|
142
|
-
* Default value is false.
|
|
143
|
-
*/
|
|
144
|
-
disabled?: boolean;
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Callback continuously called while the user is dragging the slider.
|
|
148
|
-
*/
|
|
149
|
-
onValueChange?: (_value: number) => void;
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Callback that is called when the user touches the slider,
|
|
153
|
-
* regardless if the value has changed. The current value is passed
|
|
154
|
-
* as an argument to the callback handler.
|
|
155
|
-
*/
|
|
156
|
-
onSlidingStart?: (_value: number) => void;
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Callback that is called when the user releases the slider,
|
|
160
|
-
* regardless if the value has changed. The current value is passed
|
|
161
|
-
* as an argument to the callback handler.
|
|
162
|
-
*/
|
|
163
|
-
onSlidingComplete?: (_value: number) => void;
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Used to locate this view in UI automation tests.
|
|
167
|
-
*/
|
|
168
|
-
testID?: string;
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Sets an image for the thumb. Only static images are supported.
|
|
172
|
-
*/
|
|
173
|
-
thumbImage?: ImageSource;
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* If true the slider will be inverted.
|
|
177
|
-
* Default value is false.
|
|
178
|
-
*/
|
|
179
|
-
inverted?: boolean;
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Component to be rendered for each step indicator.
|
|
183
|
-
*/
|
|
184
|
-
StepMarker?: FC<MarkerProps>;
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
*
|
|
188
|
-
*/
|
|
189
|
-
renderStepNumber?: boolean;
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* A string of one or more words to be announced by the screen reader.
|
|
193
|
-
* Otherwise, it will announce the value as a percentage.
|
|
194
|
-
* Requires passing a value to `accessibilityIncrements` to work correctly.
|
|
195
|
-
* Should be a plural word, as singular units will be handled.
|
|
196
|
-
*/
|
|
197
|
-
accessibilityUnits?: string;
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* An array of values that represent the different increments displayed
|
|
201
|
-
* by the slider. All the values passed into this prop must be strings.
|
|
202
|
-
* Requires passing a value to `accessibilityUnits` to work correctly.
|
|
203
|
-
* The number of elements must be the same as `maximumValue`.
|
|
204
|
-
*/
|
|
205
|
-
accessibilityIncrements?: Array<string>;
|
|
206
|
-
}>;
|
|
207
|
-
|
|
208
|
-
const SliderComponent = (
|
|
209
|
-
{
|
|
210
|
-
onValueChange,
|
|
211
|
-
onSlidingStart,
|
|
212
|
-
onSlidingComplete,
|
|
213
|
-
onAccessibilityAction,
|
|
214
|
-
value = constants.SLIDER_DEFAULT_INITIAL_VALUE,
|
|
215
|
-
minimumValue = 0,
|
|
216
|
-
maximumValue = 1,
|
|
217
|
-
step = 0,
|
|
218
|
-
inverted = false,
|
|
219
|
-
tapToSeek = false,
|
|
220
|
-
lowerLimit = Platform.select({
|
|
221
|
-
web: minimumValue,
|
|
222
|
-
default: constants.LIMIT_MIN_VALUE,
|
|
223
|
-
}),
|
|
224
|
-
upperLimit = Platform.select({
|
|
225
|
-
web: maximumValue,
|
|
226
|
-
default: constants.LIMIT_MAX_VALUE,
|
|
227
|
-
}),
|
|
228
|
-
...props
|
|
229
|
-
}: Props,
|
|
230
|
-
forwardedRef?: Ref<typeof RCTSliderNativeComponent>,
|
|
231
|
-
) => {
|
|
232
|
-
const [currentValue, setCurrentValue] = useState(
|
|
233
|
-
value ?? minimumValue ?? constants.SLIDER_DEFAULT_INITIAL_VALUE,
|
|
234
|
-
);
|
|
235
|
-
const [width, setWidth] = useState(0);
|
|
236
|
-
|
|
237
|
-
const stepResolution = step ? step : constants.DEFAULT_STEP_RESOLUTION;
|
|
238
|
-
|
|
239
|
-
const defaultStep = (maximumValue - minimumValue) / stepResolution;
|
|
240
|
-
const stepLength = step || defaultStep;
|
|
241
|
-
|
|
242
|
-
const options = Array.from(
|
|
243
|
-
{
|
|
244
|
-
length: (step ? defaultStep : stepResolution) + 1,
|
|
245
|
-
},
|
|
246
|
-
(_, index) => minimumValue + index * stepLength,
|
|
247
|
-
);
|
|
248
|
-
|
|
249
|
-
const defaultStyle =
|
|
250
|
-
Platform.OS === 'ios' || Platform.OS === 'harmony' ? styles.defaultSlideriOS : styles.defaultSlider;
|
|
251
|
-
const sliderStyle = {zIndex: 1, width: width};
|
|
252
|
-
const style = [defaultStyle, props.style];
|
|
253
|
-
|
|
254
|
-
const onValueChangeEvent = (event: Event) => {
|
|
255
|
-
onValueChange && onValueChange(event.nativeEvent.value);
|
|
256
|
-
setCurrentValue(event.nativeEvent.value);
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
const _disabled =
|
|
260
|
-
typeof props.disabled === 'boolean'
|
|
261
|
-
? props.disabled
|
|
262
|
-
: props.accessibilityState?.disabled === true;
|
|
263
|
-
|
|
264
|
-
const _accessibilityState =
|
|
265
|
-
typeof props.disabled === 'boolean'
|
|
266
|
-
? {...props.accessibilityState, disabled: props.disabled}
|
|
267
|
-
: props.accessibilityState;
|
|
268
|
-
|
|
269
|
-
const onSlidingStartEvent = onSlidingStart
|
|
270
|
-
? (event: Event) => {
|
|
271
|
-
onSlidingStart(event.nativeEvent.value);
|
|
272
|
-
}
|
|
273
|
-
: null;
|
|
274
|
-
const onSlidingCompleteEvent = onSlidingComplete
|
|
275
|
-
? (event: Event) => {
|
|
276
|
-
onSlidingComplete(event.nativeEvent.value);
|
|
277
|
-
}
|
|
278
|
-
: null;
|
|
279
|
-
const onAccessibilityActionEvent = onAccessibilityAction
|
|
280
|
-
? (event: AccessibilityActionEvent) => {
|
|
281
|
-
onAccessibilityAction(event);
|
|
282
|
-
}
|
|
283
|
-
: null;
|
|
284
|
-
|
|
285
|
-
const passedValue = Number.isNaN(value) || !value ? undefined : value;
|
|
286
|
-
|
|
287
|
-
useEffect(() => {
|
|
288
|
-
if (lowerLimit >= upperLimit) {
|
|
289
|
-
console.warn(
|
|
290
|
-
'Invalid configuration: lower limit is supposed to be smaller than upper limit',
|
|
291
|
-
);
|
|
292
|
-
}
|
|
293
|
-
}, [lowerLimit, upperLimit]);
|
|
294
|
-
|
|
295
|
-
return (
|
|
296
|
-
<View
|
|
297
|
-
onLayout={(event) => {
|
|
298
|
-
setWidth(event.nativeEvent.layout.width);
|
|
299
|
-
}}
|
|
300
|
-
style={[style, {justifyContent: 'center'}]}>
|
|
301
|
-
{props.StepMarker || !!props.renderStepNumber ? (
|
|
302
|
-
<StepsIndicator
|
|
303
|
-
options={options}
|
|
304
|
-
sliderWidth={width}
|
|
305
|
-
currentValue={currentValue}
|
|
306
|
-
renderStepNumber={props.renderStepNumber}
|
|
307
|
-
thumbImage={props.thumbImage}
|
|
308
|
-
StepMarker={props.StepMarker}
|
|
309
|
-
isLTR={inverted}
|
|
310
|
-
/>
|
|
311
|
-
) : null}
|
|
312
|
-
<RCTSliderNativeComponent
|
|
313
|
-
{...props}
|
|
314
|
-
minimumValue={minimumValue}
|
|
315
|
-
maximumValue={maximumValue}
|
|
316
|
-
step={step}
|
|
317
|
-
inverted={inverted}
|
|
318
|
-
tapToSeek={tapToSeek}
|
|
319
|
-
value={passedValue}
|
|
320
|
-
lowerLimit={lowerLimit}
|
|
321
|
-
upperLimit={upperLimit}
|
|
322
|
-
accessibilityState={_accessibilityState}
|
|
323
|
-
thumbImage={
|
|
324
|
-
Platform.OS === 'web'
|
|
325
|
-
? props.thumbImage
|
|
326
|
-
: props.StepMarker || !props.thumbImage
|
|
327
|
-
? undefined
|
|
328
|
-
: Image.resolveAssetSource(props.thumbImage as ImageSourcePropType)
|
|
329
|
-
}
|
|
330
|
-
ref={forwardedRef}
|
|
331
|
-
style={[
|
|
332
|
-
sliderStyle,
|
|
333
|
-
defaultStyle,
|
|
334
|
-
{alignContent: 'center', alignItems: 'center'},
|
|
335
|
-
]}
|
|
336
|
-
onChange={onValueChangeEvent}
|
|
337
|
-
onRNCSliderSlidingStart={onSlidingStartEvent}
|
|
338
|
-
onRNCSliderSlidingComplete={onSlidingCompleteEvent}
|
|
339
|
-
onRNCSliderValueChange={onValueChangeEvent}
|
|
340
|
-
disabled={_disabled}
|
|
341
|
-
onStartShouldSetResponder={() => true}
|
|
342
|
-
onResponderTerminationRequest={() => false}
|
|
343
|
-
onRNCSliderAccessibilityAction={onAccessibilityActionEvent}
|
|
344
|
-
thumbTintColor={
|
|
345
|
-
props.thumbImage && !!props.StepMarker
|
|
346
|
-
? 'transparent'
|
|
347
|
-
: props.thumbTintColor
|
|
348
|
-
}
|
|
349
|
-
/>
|
|
350
|
-
</View>
|
|
351
|
-
);
|
|
352
|
-
};
|
|
353
|
-
|
|
354
|
-
const SliderWithRef = React.forwardRef(SliderComponent);
|
|
355
|
-
|
|
356
|
-
export default SliderWithRef;
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025 Huawei Device Co., Ltd. All rights reserved
|
|
3
|
+
* Use of this source code is governed by a MIT license that can be
|
|
4
|
+
* found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, {useEffect, useState} from 'react';
|
|
8
|
+
import {
|
|
9
|
+
Image,
|
|
10
|
+
Platform,
|
|
11
|
+
AccessibilityActionEvent,
|
|
12
|
+
ViewProps,
|
|
13
|
+
ViewStyle,
|
|
14
|
+
ColorValue,
|
|
15
|
+
NativeSyntheticEvent,
|
|
16
|
+
StyleProp,
|
|
17
|
+
View,
|
|
18
|
+
ImageSource,
|
|
19
|
+
ImageSourcePropType,
|
|
20
|
+
} from 'react-native';
|
|
21
|
+
import RCTSliderNativeComponent from './index';
|
|
22
|
+
|
|
23
|
+
import type {FC, Ref} from 'react';
|
|
24
|
+
import {MarkerProps} from './components/TrackMark';
|
|
25
|
+
import {StepsIndicator} from './components/StepsIndicator';
|
|
26
|
+
import {styles} from './utils/styles';
|
|
27
|
+
import {constants} from './utils/constants';
|
|
28
|
+
|
|
29
|
+
type Event = NativeSyntheticEvent<
|
|
30
|
+
Readonly<{
|
|
31
|
+
value: number;
|
|
32
|
+
/**
|
|
33
|
+
* Android Only.
|
|
34
|
+
*/
|
|
35
|
+
fromUser?: boolean;
|
|
36
|
+
}>
|
|
37
|
+
>;
|
|
38
|
+
|
|
39
|
+
type WindowsProps = Readonly<{
|
|
40
|
+
/**
|
|
41
|
+
* If true the slider will be inverted.
|
|
42
|
+
* Default value is false.
|
|
43
|
+
*/
|
|
44
|
+
vertical?: boolean;
|
|
45
|
+
}>;
|
|
46
|
+
|
|
47
|
+
type IOSProps = Readonly<{
|
|
48
|
+
/**
|
|
49
|
+
* Assigns a single image for the track. Only static images are supported.
|
|
50
|
+
* The center pixel of the image will be stretched to fill the track.
|
|
51
|
+
*/
|
|
52
|
+
trackImage?: ImageSource;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Assigns a minimum track image. Only static images are supported. The
|
|
56
|
+
* rightmost pixel of the image will be stretched to fill the track.
|
|
57
|
+
*/
|
|
58
|
+
minimumTrackImage?: ImageSource;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Assigns a maximum track image. Only static images are supported. The
|
|
62
|
+
* leftmost pixel of the image will be stretched to fill the track.
|
|
63
|
+
*/
|
|
64
|
+
maximumTrackImage?: ImageSource;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Permits tapping on the slider track to set the thumb position.
|
|
68
|
+
* Defaults to false on iOS. No effect on Android or Windows.
|
|
69
|
+
*/
|
|
70
|
+
tapToSeek?: boolean;
|
|
71
|
+
}>;
|
|
72
|
+
|
|
73
|
+
type Props = ViewProps &
|
|
74
|
+
IOSProps &
|
|
75
|
+
WindowsProps &
|
|
76
|
+
Readonly<{
|
|
77
|
+
/**
|
|
78
|
+
* Used to style and layout the `Slider`. See `StyleSheet.js` and
|
|
79
|
+
* `DeprecatedViewStylePropTypes.js` for more info.
|
|
80
|
+
*/
|
|
81
|
+
style?: StyleProp<ViewStyle>;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Write-only property representing the value of the slider.
|
|
85
|
+
* Can be used to programmatically control the position of the thumb.
|
|
86
|
+
* Entered once at the beginning still acts as an initial value.
|
|
87
|
+
* The value should be between minimumValue and maximumValue,
|
|
88
|
+
* which default to 0 and 1 respectively.
|
|
89
|
+
* Default value is 0.
|
|
90
|
+
*
|
|
91
|
+
* This is not a controlled component, you don't need to update the
|
|
92
|
+
* value during dragging.
|
|
93
|
+
*/
|
|
94
|
+
value?: number;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Step value of the slider. The value should be
|
|
98
|
+
* between 0 and (maximumValue - minimumValue).
|
|
99
|
+
* Default value is 0.
|
|
100
|
+
*/
|
|
101
|
+
step?: number;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Initial minimum value of the slider. Default value is 0.
|
|
105
|
+
*/
|
|
106
|
+
minimumValue?: number;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Initial maximum value of the slider. Default value is 1.
|
|
110
|
+
*/
|
|
111
|
+
maximumValue?: number;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* The lower limit value of the slider. The user won't be able to slide below this limit.
|
|
115
|
+
*/
|
|
116
|
+
lowerLimit?: number;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The upper limit value of the slider. The user won't be able to slide above this limit.
|
|
120
|
+
*/
|
|
121
|
+
upperLimit?: number;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The color used for the track to the left of the button.
|
|
125
|
+
* Overrides the default blue gradient image on iOS.
|
|
126
|
+
*/
|
|
127
|
+
minimumTrackTintColor?: ColorValue;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* The color used for the track to the right of the button.
|
|
131
|
+
* Overrides the default blue gradient image on iOS.
|
|
132
|
+
*/
|
|
133
|
+
maximumTrackTintColor?: ColorValue;
|
|
134
|
+
/**
|
|
135
|
+
* The color used to tint the default thumb images on iOS, or the
|
|
136
|
+
* color of the foreground switch grip on Android.
|
|
137
|
+
*/
|
|
138
|
+
thumbTintColor?: ColorValue;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* If true the user won't be able to move the slider.
|
|
142
|
+
* Default value is false.
|
|
143
|
+
*/
|
|
144
|
+
disabled?: boolean;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Callback continuously called while the user is dragging the slider.
|
|
148
|
+
*/
|
|
149
|
+
onValueChange?: (_value: number) => void;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Callback that is called when the user touches the slider,
|
|
153
|
+
* regardless if the value has changed. The current value is passed
|
|
154
|
+
* as an argument to the callback handler.
|
|
155
|
+
*/
|
|
156
|
+
onSlidingStart?: (_value: number) => void;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Callback that is called when the user releases the slider,
|
|
160
|
+
* regardless if the value has changed. The current value is passed
|
|
161
|
+
* as an argument to the callback handler.
|
|
162
|
+
*/
|
|
163
|
+
onSlidingComplete?: (_value: number) => void;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Used to locate this view in UI automation tests.
|
|
167
|
+
*/
|
|
168
|
+
testID?: string;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Sets an image for the thumb. Only static images are supported.
|
|
172
|
+
*/
|
|
173
|
+
thumbImage?: ImageSource;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* If true the slider will be inverted.
|
|
177
|
+
* Default value is false.
|
|
178
|
+
*/
|
|
179
|
+
inverted?: boolean;
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Component to be rendered for each step indicator.
|
|
183
|
+
*/
|
|
184
|
+
StepMarker?: FC<MarkerProps>;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
*
|
|
188
|
+
*/
|
|
189
|
+
renderStepNumber?: boolean;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* A string of one or more words to be announced by the screen reader.
|
|
193
|
+
* Otherwise, it will announce the value as a percentage.
|
|
194
|
+
* Requires passing a value to `accessibilityIncrements` to work correctly.
|
|
195
|
+
* Should be a plural word, as singular units will be handled.
|
|
196
|
+
*/
|
|
197
|
+
accessibilityUnits?: string;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* An array of values that represent the different increments displayed
|
|
201
|
+
* by the slider. All the values passed into this prop must be strings.
|
|
202
|
+
* Requires passing a value to `accessibilityUnits` to work correctly.
|
|
203
|
+
* The number of elements must be the same as `maximumValue`.
|
|
204
|
+
*/
|
|
205
|
+
accessibilityIncrements?: Array<string>;
|
|
206
|
+
}>;
|
|
207
|
+
|
|
208
|
+
const SliderComponent = (
|
|
209
|
+
{
|
|
210
|
+
onValueChange,
|
|
211
|
+
onSlidingStart,
|
|
212
|
+
onSlidingComplete,
|
|
213
|
+
onAccessibilityAction,
|
|
214
|
+
value = constants.SLIDER_DEFAULT_INITIAL_VALUE,
|
|
215
|
+
minimumValue = 0,
|
|
216
|
+
maximumValue = 1,
|
|
217
|
+
step = 0,
|
|
218
|
+
inverted = false,
|
|
219
|
+
tapToSeek = false,
|
|
220
|
+
lowerLimit = Platform.select({
|
|
221
|
+
web: minimumValue,
|
|
222
|
+
default: constants.LIMIT_MIN_VALUE,
|
|
223
|
+
}),
|
|
224
|
+
upperLimit = Platform.select({
|
|
225
|
+
web: maximumValue,
|
|
226
|
+
default: constants.LIMIT_MAX_VALUE,
|
|
227
|
+
}),
|
|
228
|
+
...props
|
|
229
|
+
}: Props,
|
|
230
|
+
forwardedRef?: Ref<typeof RCTSliderNativeComponent>,
|
|
231
|
+
) => {
|
|
232
|
+
const [currentValue, setCurrentValue] = useState(
|
|
233
|
+
value ?? minimumValue ?? constants.SLIDER_DEFAULT_INITIAL_VALUE,
|
|
234
|
+
);
|
|
235
|
+
const [width, setWidth] = useState(0);
|
|
236
|
+
|
|
237
|
+
const stepResolution = step ? step : constants.DEFAULT_STEP_RESOLUTION;
|
|
238
|
+
|
|
239
|
+
const defaultStep = (maximumValue - minimumValue) / stepResolution;
|
|
240
|
+
const stepLength = step || defaultStep;
|
|
241
|
+
|
|
242
|
+
const options = Array.from(
|
|
243
|
+
{
|
|
244
|
+
length: (step ? defaultStep : stepResolution) + 1,
|
|
245
|
+
},
|
|
246
|
+
(_, index) => minimumValue + index * stepLength,
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
const defaultStyle =
|
|
250
|
+
Platform.OS === 'ios' || Platform.OS === 'harmony' ? styles.defaultSlideriOS : styles.defaultSlider;
|
|
251
|
+
const sliderStyle = {zIndex: 1, width: width};
|
|
252
|
+
const style = [defaultStyle, props.style];
|
|
253
|
+
|
|
254
|
+
const onValueChangeEvent = (event: Event) => {
|
|
255
|
+
onValueChange && onValueChange(event.nativeEvent.value);
|
|
256
|
+
setCurrentValue(event.nativeEvent.value);
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const _disabled =
|
|
260
|
+
typeof props.disabled === 'boolean'
|
|
261
|
+
? props.disabled
|
|
262
|
+
: props.accessibilityState?.disabled === true;
|
|
263
|
+
|
|
264
|
+
const _accessibilityState =
|
|
265
|
+
typeof props.disabled === 'boolean'
|
|
266
|
+
? {...props.accessibilityState, disabled: props.disabled}
|
|
267
|
+
: props.accessibilityState;
|
|
268
|
+
|
|
269
|
+
const onSlidingStartEvent = onSlidingStart
|
|
270
|
+
? (event: Event) => {
|
|
271
|
+
onSlidingStart(event.nativeEvent.value);
|
|
272
|
+
}
|
|
273
|
+
: null;
|
|
274
|
+
const onSlidingCompleteEvent = onSlidingComplete
|
|
275
|
+
? (event: Event) => {
|
|
276
|
+
onSlidingComplete(event.nativeEvent.value);
|
|
277
|
+
}
|
|
278
|
+
: null;
|
|
279
|
+
const onAccessibilityActionEvent = onAccessibilityAction
|
|
280
|
+
? (event: AccessibilityActionEvent) => {
|
|
281
|
+
onAccessibilityAction(event);
|
|
282
|
+
}
|
|
283
|
+
: null;
|
|
284
|
+
|
|
285
|
+
const passedValue = Number.isNaN(value) || !value ? undefined : value;
|
|
286
|
+
|
|
287
|
+
useEffect(() => {
|
|
288
|
+
if (lowerLimit >= upperLimit) {
|
|
289
|
+
console.warn(
|
|
290
|
+
'Invalid configuration: lower limit is supposed to be smaller than upper limit',
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
}, [lowerLimit, upperLimit]);
|
|
294
|
+
|
|
295
|
+
return (
|
|
296
|
+
<View
|
|
297
|
+
onLayout={(event) => {
|
|
298
|
+
setWidth(event.nativeEvent.layout.width);
|
|
299
|
+
}}
|
|
300
|
+
style={[style, {justifyContent: 'center'}]}>
|
|
301
|
+
{props.StepMarker || !!props.renderStepNumber ? (
|
|
302
|
+
<StepsIndicator
|
|
303
|
+
options={options}
|
|
304
|
+
sliderWidth={width}
|
|
305
|
+
currentValue={currentValue}
|
|
306
|
+
renderStepNumber={props.renderStepNumber}
|
|
307
|
+
thumbImage={props.thumbImage}
|
|
308
|
+
StepMarker={props.StepMarker}
|
|
309
|
+
isLTR={inverted}
|
|
310
|
+
/>
|
|
311
|
+
) : null}
|
|
312
|
+
<RCTSliderNativeComponent
|
|
313
|
+
{...props}
|
|
314
|
+
minimumValue={minimumValue}
|
|
315
|
+
maximumValue={maximumValue}
|
|
316
|
+
step={step}
|
|
317
|
+
inverted={inverted}
|
|
318
|
+
tapToSeek={tapToSeek}
|
|
319
|
+
value={passedValue}
|
|
320
|
+
lowerLimit={lowerLimit}
|
|
321
|
+
upperLimit={upperLimit}
|
|
322
|
+
accessibilityState={_accessibilityState}
|
|
323
|
+
thumbImage={
|
|
324
|
+
Platform.OS === 'web'
|
|
325
|
+
? props.thumbImage
|
|
326
|
+
: props.StepMarker || !props.thumbImage
|
|
327
|
+
? undefined
|
|
328
|
+
: Image.resolveAssetSource(props.thumbImage as ImageSourcePropType)
|
|
329
|
+
}
|
|
330
|
+
ref={forwardedRef}
|
|
331
|
+
style={[
|
|
332
|
+
sliderStyle,
|
|
333
|
+
defaultStyle,
|
|
334
|
+
{alignContent: 'center', alignItems: 'center'},
|
|
335
|
+
]}
|
|
336
|
+
onChange={onValueChangeEvent}
|
|
337
|
+
onRNCSliderSlidingStart={onSlidingStartEvent}
|
|
338
|
+
onRNCSliderSlidingComplete={onSlidingCompleteEvent}
|
|
339
|
+
onRNCSliderValueChange={onValueChangeEvent}
|
|
340
|
+
disabled={_disabled}
|
|
341
|
+
onStartShouldSetResponder={() => true}
|
|
342
|
+
onResponderTerminationRequest={() => false}
|
|
343
|
+
onRNCSliderAccessibilityAction={onAccessibilityActionEvent}
|
|
344
|
+
thumbTintColor={
|
|
345
|
+
props.thumbImage && !!props.StepMarker
|
|
346
|
+
? 'transparent'
|
|
347
|
+
: props.thumbTintColor
|
|
348
|
+
}
|
|
349
|
+
/>
|
|
350
|
+
</View>
|
|
351
|
+
);
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
const SliderWithRef = React.forwardRef(SliderComponent);
|
|
355
|
+
|
|
356
|
+
export default SliderWithRef;
|