3
3
import * as React from 'react' ;
4
4
import { classNames } from '@vkontakte/vkjs' ;
5
5
import { clamp } from '../../helpers/math' ;
6
+ import { mergeStyle } from '../../helpers/mergeStyle' ;
6
7
import { useAdaptivity } from '../../hooks/useAdaptivity' ;
8
+ import { useDirection } from '../../hooks/useDirection' ;
7
9
import { useExternRef } from '../../hooks/useExternRef' ;
8
- import type { HTMLAttributesWithRootRef } from '../../types' ;
10
+ import type { CSSCustomProperties , HTMLAttributesWithRootRef } from '../../types' ;
9
11
import { type CustomTouchEvent , type CustomTouchEventHandler , Touch } from '../Touch/Touch' ;
10
12
import { SliderThumb } from './SliderThumb/SliderThumb' ;
11
13
import {
@@ -101,9 +103,12 @@ export const Slider = ({
101
103
onChange,
102
104
withTooltip,
103
105
size = 'l' ,
106
+ style : styleProp ,
104
107
...restProps
105
108
} : SliderProps | SliderMultipleProps ) : React . ReactNode => {
106
109
const { sizeY = 'none' } = useAdaptivity ( ) ;
110
+ const [ directionRef , textDirection = 'ltr' ] = useDirection ( ) ;
111
+ const isRtl = textDirection === 'rtl' ;
107
112
108
113
const isControlled = valueProp !== undefined ;
109
114
const [ localValue , setValue ] = React . useState ( defaultValue ) ;
@@ -163,7 +168,10 @@ export const Slider = ({
163
168
// @ts -expect-error: TS2345 в VKUITouchEvent плохо описаны типы. `target` это просто `EventTarget`.
164
169
const foundDraggingType = getDraggingTypeByTargetDataset ( event . originalEvent . target ) ;
165
170
166
- const nextStartX = event . startX - nextContainerX ;
171
+ let nextStartX = event . startX - nextContainerX ;
172
+ if ( isRtl ) {
173
+ nextStartX = nextContainerWidth - nextStartX ;
174
+ }
167
175
const nextValue = offsetToValue ( nextStartX , nextContainerWidth , min , max , step ) ;
168
176
const nextDragging = snapDirection ( value , nextValue , foundDraggingType ) ;
169
177
@@ -205,7 +213,7 @@ export const Slider = ({
205
213
const { startX, containerWidth, dragging } = gesture ;
206
214
207
215
const { shiftX = 0 } = event ;
208
- const nextStartX = startX + shiftX ;
216
+ const nextStartX = startX + ( isRtl ? - shiftX : shiftX ) ;
209
217
const nextValue = offsetToValue ( nextStartX , containerWidth , min , max , step ) ;
210
218
211
219
changeValue ( updateInternalStateValue ( value , nextValue , min , max , dragging ) , event ) ;
@@ -231,6 +239,11 @@ export const Slider = ({
231
239
) ;
232
240
} ;
233
241
242
+ const style : CSSCustomProperties = {
243
+ '--vkui_internal--Slider_start_value' : String ( startValueInPercent ) ,
244
+ '--vkui_internal--Slider_end_value' : String ( endReversedValueInPercent ) ,
245
+ } ;
246
+
234
247
return (
235
248
< Touch
236
249
data-value = { multiple ? `${ startValue } ,${ endValue } ` : startValue }
@@ -240,27 +253,23 @@ export const Slider = ({
240
253
disabled && styles . disabled ,
241
254
sizeY !== 'regular' && sizeYClassNames [ sizeY ] ,
242
255
sizeClassNames [ size ] ,
256
+ multiple && styles . multiple ,
257
+ isRtl && styles . rtl ,
243
258
className ,
244
259
) }
260
+ style = { mergeStyle ( styleProp , style ) }
261
+ getRootRef = { directionRef }
245
262
onStart = { disabled ? undefined : handlePointerStart }
246
263
onMove = { disabled ? undefined : handlePointerMove }
247
264
onEnd = { disabled ? undefined : handlePointerEnd }
248
265
>
249
266
< div className = { styles . track } />
250
- < div
251
- className = { styles . trackFill }
252
- style = {
253
- multiple
254
- ? { left : `${ startValueInPercent } %` , right : `${ 100 - endReversedValueInPercent } %` }
255
- : { width : `${ startValueInPercent } %` }
256
- }
257
- />
267
+ < div className = { styles . trackFill } />
258
268
< div ref = { thumbsContainerRef } className = { styles . thumbs } >
259
269
< SliderThumb
260
270
data-type = "start"
261
- className = { styles . thumb }
271
+ className = { classNames ( styles . thumb , styles . thumbStart ) }
262
272
style = { {
263
- left : `${ startValueInPercent } %` ,
264
273
// Меняем местами порядок слоёв, иначе, при достижении `start` и `end` 100%, `end` будет перекрывать `start`.
265
274
zIndex : multiple && startValueInPercent >= 50 ? 2 : undefined ,
266
275
} }
@@ -284,8 +293,7 @@ export const Slider = ({
284
293
{ multiple && (
285
294
< SliderThumb
286
295
data-type = "end"
287
- className = { styles . thumb }
288
- style = { { left : `${ endReversedValueInPercent } %` } }
296
+ className = { classNames ( styles . thumb , styles . thumbEnd ) }
289
297
withTooltip = { withTooltip }
290
298
inputProps = { {
291
299
'data-type' : 'end' ,
0 commit comments