|
1 | 1 | import React, { type FC, useEffect, useMemo, useRef } from 'react'; |
2 | 2 | import cn from 'classnames'; |
3 | | -import noUiSlider, { API } from 'nouislider'; |
| 3 | +import noUiSlider, { type API } from 'nouislider'; |
4 | 4 |
|
5 | 5 | import { useSliderMarkers } from './hooks'; |
| 6 | +import { type SliderProps } from './types'; |
6 | 7 | import { createPipsConfig } from './utils'; |
7 | 8 |
|
8 | 9 | import styles from './index.module.css'; |
9 | 10 |
|
10 | | -type SubRange = number | [number] | [number, number]; |
11 | | -type RangeOptions = { |
12 | | - min: SubRange; |
13 | | - max: SubRange; |
14 | | - [key: string]: SubRange; |
15 | | -}; |
16 | | - |
17 | | -type PipsType = -1 | 0 | 1 | 2; |
18 | | - |
19 | | -export type Pips = { |
20 | | - mode: 'range' | 'steps' | 'positions' | 'count' | 'values'; |
21 | | - values: number | number[]; |
22 | | - filter?: (value: number, type: PipsType) => PipsType; |
23 | | - format?: { |
24 | | - to: (value: number) => string | number; |
25 | | - from?: (value: string) => number | false; |
26 | | - }; |
27 | | - stepped?: boolean; |
28 | | -}; |
29 | | - |
30 | | -export type SliderProps = { |
31 | | - /** |
32 | | - * Мин. допустимое число |
33 | | - */ |
34 | | - min?: number; |
35 | | - |
36 | | - /** |
37 | | - * Макс. допустимое число |
38 | | - */ |
39 | | - max?: number; |
40 | | - |
41 | | - /** |
42 | | - * Шаг (должен нацело делить отрезок между мин и макс) |
43 | | - */ |
44 | | - step?: number; |
45 | | - |
46 | | - /** |
47 | | - * Отображение подписей |
48 | | - * https://refreshless.com/nouislider/pips/ |
49 | | - */ |
50 | | - pips?: Pips; |
51 | | - |
52 | | - /** |
53 | | - * Настройка шагов |
54 | | - * https://refreshless.com/nouislider/pips/#section-range |
55 | | - */ |
56 | | - range?: RangeOptions; |
57 | | - |
58 | | - /** |
59 | | - * Флаг точной привязки к range |
60 | | - * https://refreshless.com/nouislider/examples/#section-skipping |
61 | | - */ |
62 | | - snap?: boolean; |
63 | | - |
64 | | - /** |
65 | | - * Значение слайдера |
66 | | - */ |
67 | | - value?: number; |
68 | | - |
69 | | - /** |
70 | | - * Второе значение слайдера (значение второго ползунка) |
71 | | - * если передать ValueTo, то слайдер будет работать как range |
72 | | - */ |
73 | | - valueTo?: number; |
74 | | - |
75 | | - /** |
76 | | - * Заблокированное состояние |
77 | | - */ |
78 | | - disabled?: boolean; |
79 | | - |
80 | | - /** |
81 | | - * Дополнительный класс |
82 | | - */ |
83 | | - className?: string; |
84 | | - |
85 | | - /** |
86 | | - * Поведение ползунка |
87 | | - */ |
88 | | - behaviour?: 'unconstrained-tap' | 'tap'; |
89 | | - |
90 | | - /** |
91 | | - * Размер |
92 | | - * @description s, m deprecated, используйте вместо них 2, 4 соответственно |
93 | | - */ |
94 | | - size?: 's' | 'm' | 2 | 4; |
95 | | - |
96 | | - /** |
97 | | - * Включение/отключение отображения точек на слайдере |
98 | | - * @default false |
99 | | - */ |
100 | | - dots?: boolean; |
101 | | - |
102 | | - /** |
103 | | - * Тип отображения точек на слайдере: 'step' - по шагу, 'custom' - произвольные |
104 | | - * @default 'step' |
105 | | - */ |
106 | | - dotsSlider?: 'step' | 'custom'; |
107 | | - |
108 | | - /** |
109 | | - * Массив значений для произвольного размещения точек |
110 | | - */ |
111 | | - customDots?: number[]; |
112 | | - |
113 | | - /** |
114 | | - * Включение/отключение отображения чисел под точками |
115 | | - * Действует на все точки кроме dotsSlider |
116 | | - * @default true |
117 | | - */ |
118 | | - showNumbers?: boolean; |
119 | | - |
120 | | - /** |
121 | | - * Скрытие чисел только для кастомных точек |
122 | | - * При hideCustomDotsNumbers=true числа скрываются только у customDots, остальные числа остаются видимыми |
123 | | - * @default false |
124 | | - */ |
125 | | - hideCustomDotsNumbers?: boolean; |
126 | | - |
127 | | - /** |
128 | | - * Обработчик поля ввода |
129 | | - */ |
130 | | - onChange?: (payload: { value: number; valueTo?: number }) => void; |
131 | | - |
132 | | - /** |
133 | | - * @deprecated |
134 | | - * Обработчик начала перетаскивания ползунка |
135 | | - */ |
136 | | - onStart?: () => void; |
137 | | - |
138 | | - /** |
139 | | - * Обработчик окончания перетаскивания ползунка |
140 | | - * @description https://refreshless.com/nouislider/events-callbacks/#section-change |
141 | | - */ |
142 | | - onEnd?: () => void; |
143 | | - |
144 | | - /** |
145 | | - * Идентификатор для систем автоматизированного тестирования |
146 | | - */ |
147 | | - dataTestId?: string; |
148 | | -}; |
149 | | - |
150 | 11 | export const SIZE_TO_CLASSNAME_MAP = { |
151 | 12 | s: 'size-2', |
152 | 13 | m: 'size-4', |
@@ -311,12 +172,11 @@ export const Slider: FC<SliderProps> = ({ |
311 | 172 | } |
312 | 173 | }, [onChange, hasValueTo, value, valueTo, createSlideHandler, updateMarkersState]); |
313 | 174 |
|
314 | | - // todo: переделать логику отображения цифр и точек |
315 | 175 | return ( |
316 | 176 | <div |
317 | 177 | className={cn(styles.component, className, styles[SIZE_TO_CLASSNAME_MAP[size]], { |
318 | 178 | [styles.dotsDisabled]: !dots, |
319 | | - // [styles.numbersDisabled]: dots && dotsSlider === 'custom' && !customDots?.length, |
| 179 | + [styles.numbersDisabled]: dots && dotsSlider === 'custom' && !customDots?.length, |
320 | 180 | })} |
321 | 181 | ref={sliderRef} |
322 | 182 | data-test-id={dataTestId} |
|
0 commit comments