@sberbusiness/triplex-next-mcp-server 1.46.0-beta → 1.48.0-beta

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.
Files changed (48) hide show
  1. package/README.md +7 -7
  2. package/bundle/components/AmountField.md +222 -323
  3. package/bundle/components/Avatar.md +138 -146
  4. package/bundle/components/CardStatic.md +402 -0
  5. package/bundle/components/CheckboxTree.md +157 -215
  6. package/bundle/components/CheckboxTreeExtended.md +7 -7
  7. package/bundle/components/ChipGroup.md +1 -1
  8. package/bundle/components/ChipMonthYearPicker.md +4 -4
  9. package/bundle/components/ChipSuggest.md +7 -6
  10. package/bundle/components/CollapsibleTree.md +8 -4
  11. package/bundle/components/CollapsibleTreeExtended.md +8 -6
  12. package/bundle/components/Confirm.md +346 -281
  13. package/bundle/components/DateRange.md +351 -210
  14. package/bundle/components/FooterPage.md +1 -0
  15. package/bundle/components/FormField.md +11 -4
  16. package/bundle/components/FormGroup.md +3 -2
  17. package/bundle/components/LightBox.md +8 -0
  18. package/bundle/components/ListMaster.md +2 -2
  19. package/bundle/components/ListTableItem.md +6 -6
  20. package/bundle/components/MonthYearField.md +15 -4
  21. package/bundle/components/Slider.md +389 -97
  22. package/bundle/components/SliderRange.md +486 -105
  23. package/bundle/components/StatusTracker.md +386 -94
  24. package/bundle/components/Stepper.md +355 -102
  25. package/bundle/components/StepperExtended.md +633 -0
  26. package/bundle/components/SuggestField.md +1049 -96
  27. package/bundle/components/SwipeableArea.md +7 -7
  28. package/bundle/components/Tabs.md +265 -92
  29. package/bundle/components/TabsExtended.md +18 -18
  30. package/bundle/components/TabsLine.md +301 -127
  31. package/bundle/components/TagColor.md +187 -66
  32. package/bundle/components/TagGroup.md +184 -48
  33. package/bundle/components/TextareaField.md +278 -70
  34. package/bundle/components/TopOverlay.md +17 -1
  35. package/bundle/components/TreeView.md +16 -7
  36. package/bundle/components/TriggerClickOnKeyDownEvent.md +277 -0
  37. package/bundle/components/UploadZone.md +318 -0
  38. package/bundle/guides/codestyle.md +16 -1
  39. package/bundle/guides/commits.md +47 -1
  40. package/bundle/guides/tests.md +23 -2
  41. package/bundle/manifest.json +48 -21
  42. package/bundle/release-notes/1.47.0.mdx +115 -0
  43. package/bundle/release-notes/1.48.0.mdx +68 -0
  44. package/bundle/release-notes/1.49.0.mdx +7 -0
  45. package/bundle/tokens.json +3 -3
  46. package/dist/index.js +220 -6
  47. package/dist/index.js.map +1 -1
  48. package/package.json +1 -1
@@ -1,8 +1,6 @@
1
1
  ---
2
2
  component: Slider
3
- category: Form Controls
4
- figma-node: ""
5
- figma-file: ""
3
+ category: Slider
6
4
  related: [SliderExtended, SliderRange]
7
5
  tokens: []
8
6
  stories: stories/Slider/Slider.stories.tsx
@@ -13,145 +11,439 @@ version: "1.0"
13
11
 
14
12
  ## Назначение
15
13
 
16
- Готовый слайдер с **одним** ползунком: фиксированная компоновка
17
- `SliderExtended` (`Rail` → `Dot` → `Track` → `Marks`), tooltip над dot'ом
18
- если передан `renderTooltipContent`. Под капотом — `SliderExtended` с
19
- ровно одним `Dot`.
14
+ Слайдер с одним ползунком — готовая сборка `SliderExtended`: полоса, ползунок, трек и метки
15
+ уже собраны, потребителю остаётся задать диапазон, шаг, метки и владеть значением.
20
16
 
21
- Используй когда: нужно выбрать одно числовое значение в диапазоне
22
- `min..max`. Для двух точек (диапазон) — `SliderRange`. Для нестандартной
23
- компоновки (свой Tooltip, отдельные Marks) — `SliderExtended`.
17
+ Используй когда: пользователь выбирает одно число из диапазона и точность ввода не важна —
18
+ сумма, срок, процент, громкость.
24
19
 
25
- ---
26
-
27
- ## Файловая структура
20
+ Не используй когда:
28
21
 
29
- ```text
30
- src/components/Slider/
31
- ├── Slider.tsx # FC; склейка SliderExtended + Dot + Tooltip + Marks
32
- ├── index.ts # Barrel
33
- └── __tests__/
34
- ```
22
+ - Нужен выбор диапазона двумя ползунками — возьми `SliderRange`.
23
+ - Нужен нестандартный состав частей (без меток, без трека, своё содержимое ползунка) или
24
+ собственная разметка подсказки — собери слайдер из `SliderExtended`.
25
+ - Нужно ввести точное число — слайдер не заменяет `NumberField` / `AmountField`; при крупных
26
+ диапазонах их обычно ставят рядом со слайдером.
27
+ - Ползунку нужна текстовая подпись для скринридера — `Slider` её передать не позволяет
28
+ (см. Accessibility), собирай из `SliderExtended`.
35
29
 
36
30
  ---
37
31
 
38
32
  ## Варианты и props
39
33
 
40
- ### `ISliderProps`
34
+ ### Обязательные props
41
35
 
42
- ```ts
43
- extends Omit<ISliderExtendedProps, "onChange" | "step">
44
- extends Pick<ISliderExtendedDotProps, "onChange" | "value">
45
- ```
36
+ | Prop | Тип | Описание |
37
+ |---|---|---|
38
+ | `min` | `number` | Минимальное значение диапазона |
39
+ | `max` | `number` | Максимальное значение диапазона |
40
+ | `size` | `EComponentSize.MD \| EComponentSize.LG` | Размер. `SM` не поддерживается |
41
+ | `value` | `number` | Текущее значение ползунка |
42
+ | `onChange` | `(value: number) => void` | Вызывается со значением шага, на который переместился ползунок |
43
+ | `marks` | `ISliderMark[]` | Метки под полосой: `{ value: number; label: React.ReactNode }` |
46
44
 
47
- | Prop | Тип | Default | Описание |
45
+ ### Опциональные props
46
+
47
+ | Prop | Тип | По умолчанию | Описание |
48
48
  |---|---|---|---|
49
- | `value` | `number` | — | Текущее значение dot'а. |
50
- | `onChange` | `(value: number) => void` | — | Изменение значения. |
51
- | `marks` | `ISliderMark[]` | — | Метки под полосой (`{ value, label }`). |
52
- | `step?` | `number \| number[]` | `1` | Длина шага или явный массив значений. |
53
- | `renderTooltipContent?` | `(value: number) => ReactNode` | — | Если передан — рендерится `Tooltip` над dot'ом. |
54
- | `size` | `EComponentSize.MD \| LG` | — (обязателен из ISliderExtendedProps) | Только MD/LG. |
55
- | `min` / `max` | `number` | — | От SliderExtended. |
56
- | `disabled?` / `reverse?` | `boolean` | — | От SliderExtended. |
57
- | `children?` | `never` | — | Запрещено. |
58
-
59
- ### `ISliderMark`
60
-
61
- ```ts
62
- { value: number; label: ReactNode }
63
- ```
49
+ | `step` | `number \| number[]` | `1` | Длина шага либо массив значений шагов. В массиве первое значение равно `min`, последнее — `max` |
50
+ | `reverse` | `boolean` | `false` | Значения возрастают справа налево |
51
+ | `disabled` | `boolean` | `false` | Слайдер не активен: части не реагируют на курсор и выпадают из табуляции |
52
+ | `renderTooltipContent` | `(value: number) => React.ReactNode` | — | Содержимое подсказки над ползунком. Без этого prop подсказка не рендерится вовсе |
53
+
54
+ Остальные атрибуты `React.HTMLAttributes<HTMLDivElement>` (включая `className`, `id`,
55
+ `aria-*`, `data-*`) уходят на **корневой `div`** слайдера. `children` запрещён
56
+ (`children?: never`): разметку собирает сам компонент.
57
+
58
+ ### Особенности поведения
59
+
60
+ - **Значение контролируемое.** Компонент не хранит значение: он рисует позицию по `value` и
61
+ сообщает новое значение через `onChange`. Без обновления `value` снаружи ползунок не
62
+ двигается — включая `disabled`-слайдер, где источник правды тем более остаётся у
63
+ потребителя.
64
+ - **`step` числом строит шаги как `[...range(min, max, step), max]`.** Последний шаг всегда
65
+ равен `max`, даже если он не кратен шагу: при `min: 0, max: 10, step: 3` шаги равны
66
+ `0, 3, 6, 9, 10`.
67
+ - **`step` массивом задаёт произвольную шкалу.** Шаги равны визуально, а не по значению —
68
+ так делается шкала сумм с укрупняющимся шагом (см. story `Amounts`). Массив, собранный
69
+ инлайн в JSX, пересчитывает шаги на каждом рендере потребителя; вынеси его в константу.
70
+ - **Пустой массив шагов (`step: []`) не рендерит ничего** — `SliderExtended` возвращает `null`.
71
+ - **Значение вне диапазона не отбрасывается, а зажимается** при расчёте позиции: ползунок
72
+ встаёт на край. В `onChange` при этом уходят только значения из массива шагов.
73
+ - **Клик по полосе и по метке двигает ползунок** на ближайший шаг / на значение метки.
74
+ - **`marks` не обязаны совпадать с шагами.** Метка со значением вне `[min, max]` прижимается
75
+ к краю полосы; `value` метки используется как React-ключ, поэтому дубли значений дадут
76
+ предупреждение о неуникальных ключах. Подпись рендерится через `Text` (`B3` для `LG`,
77
+ `B4` для `MD`).
78
+ - **Подсказка видна только при `:hover` и `:focus` ползунка** — управляется стилями, не
79
+ props. Постоянно видимой подсказки нет, поэтому текущее значение обычно дублируют рядом со
80
+ слайдером (так сделано во всех stories).
81
+ - **Ширину и внешние отступы задаёт потребитель.** Своей ширины у слайдера нет; собственные
82
+ вертикальные отступы (под ползунок и под метки) он добавляет сам.
64
83
 
65
- `value` должен быть в `[min, max]`.
84
+ ---
66
85
 
67
- ### `step`
86
+ ## Дизайн-токены
68
87
 
69
- - **`number`** — обычный шаг: для `min=0, max=100, step=1` — 100 шагов.
70
- - **`number[]`** — явный массив возможных значений, **первый = `min`**, **последний = `max`** (контракт).
88
+ Собственных токенов у компонента нет: своих стилей `Slider` не имеет и целиком состоит из
89
+ `SliderExtended`. Внешний вид настраивается токенами группы `Slider` — их список и порядок
90
+ переопределения см. в `SliderExtended-ai.md` → «Дизайн-токены». Значения по умолчанию —
91
+ `src/components/DesignTokens/components/Slider.ts`.
71
92
 
72
93
  ---
73
94
 
74
- ## Ключевые особенности реализации
95
+ ## Инварианты
75
96
 
76
- ### Жёстко зашитая структура
97
+ - **`Slider` пробрасывает `ref` на корневой `div`:** обёрнут в `React.forwardRef`, `ref`
98
+ уходит в `SliderExtended`, который вешает его на свой корень. `forwardRef` не убирать —
99
+ это публичный контракт. У `SliderExtended` и всех его частей `forwardRef` есть — тоже не
100
+ убирать. Исключение в семействе — `SliderRange`: это class-компонент, и `ref` на нём даёт
101
+ инстанс класса, а не корневой `div`.
102
+ - **`ISliderProps` наследуется от `ISliderExtendedProps` и `ISliderExtendedDotProps`**
103
+ (`Omit<..., "onChange" | "step">` + `Pick<..., "onChange" | "value">`). Переименование
104
+ props в `SliderExtended` ломает публичный API `Slider` — менять только вместе.
105
+ - **Порядок частей в разметке (`Rail` → `Dot` → `Track` → `Marks`) и наличие `Rail`
106
+ обязательны.** Позиции клика и перетаскивания считаются от DOM-узла полосы; без `Rail`
107
+ работает только клавиатура. `Tooltip` обязан лежать внутри `Dot`.
108
+ - **`renderTooltipContent` вызывается на каждом рендере** с текущим `value` — держи её
109
+ дешёвой и без side effects.
110
+ - **`children?: never`** — часть публичного API: состав слайдера фиксирован, расширяется он
111
+ только через `SliderExtended`.
112
+ - Реализация остаётся React 17-совместимой (без `useId`, `useSyncExternalStore` и прочих
113
+ React 18-only API): код синхронизируется в `release-0`.
77
114
 
78
- ```tsx
79
- <SliderExtended step={step} size={size} {...rest}>
80
- <SliderExtended.Rail />
81
- <SliderExtended.Dot value={value} onChange={onChange}>
82
- {renderTooltipContent && <SliderExtended.Tooltip ...>{renderTooltipContent(value)}</SliderExtended.Tooltip>}
83
- </SliderExtended.Dot>
84
- <SliderExtended.Track />
85
- <SliderExtended.Marks>
86
- {marks.map(m => <SliderExtended.Mark key={m.value} value={m.value}>{m.label}</SliderExtended.Mark>)}
87
- </SliderExtended.Marks>
88
- </SliderExtended>
89
- ```
115
+ ---
116
+
117
+ ## Accessibility
90
118
 
91
- - Порядок: Rail → Dot → Track → Marks. Изменение порядка — менять `Slider.tsx`.
92
- - Tooltip — вложен в Dot, рендерится только при `renderTooltipContent`.
119
+ - **Ползунок — `role="slider"`** с `aria-valuemin`, `aria-valuenow`, `aria-valuemax` из
120
+ `min` / `value` / `max` (рендерится `SliderExtended.Dot`).
121
+ - **Подпись ползунку `Slider` передать нельзя.** Все лишние props уходят на корневой `div`,
122
+ а не на ползунок, поэтому `aria-label` / `aria-labelledby` окажутся на контейнере без роли.
123
+ Если подпись или `aria-valuetext` (нелинейная шкала, суммы, единицы измерения) обязательны —
124
+ собирай слайдер из `SliderExtended` и передавай атрибуты прямо в `SliderExtended.Dot`.
125
+ - **Клавиатура:** `ArrowLeft` / `ArrowDown` — шаг назад, `ArrowRight` / `ArrowUp` — шаг
126
+ вперёд. Обработчики вызывают `preventDefault`, чтобы страница не скроллилась.
127
+ `Home` / `End` / `PageUp` / `PageDown` не поддерживаются.
128
+ - **Трек в табуляцию не попадает:** перетаскивание трека клавиатурой имеет смысл только для
129
+ двух ползунков, а у `Slider` он один.
130
+ - **Метки кликабельны, но не фокусируются** и не читаются как элементы управления: это
131
+ ускоритель для мыши, дублирующий клавиатурное перемещение по шагам.
132
+ - **Подсказка не связана с ползунком через `aria`** — она показывается по `:hover`/`:focus`
133
+ и для скринридера бесполезна; значение доступно через `aria-valuenow`.
134
+ - **`disabled` только визуальный и мышиный.** Части получают `pointer-events: none` и
135
+ `tabIndex -1`, но нативного `disabled` у `span` нет: программно установленный фокус
136
+ оставляет клавиатурное перемещение работающим. Источником правды остаётся `value`
137
+ потребителя.
93
138
 
94
- ### `step` default `1`
139
+ ---
95
140
 
96
- - Если потребитель не передал — `1`.
141
+ ## Связанные компоненты
97
142
 
98
- ### `Tooltip` — над **самим** dot'ом, не на hover
143
+ - `SliderExtended` (`src/components/SliderExtended/`) — составной слайдер, из которого
144
+ собран `Slider`. Нужен, когда состава `Slider` не хватает: свой набор частей, своя
145
+ подсказка, `aria`-атрибуты на ползунке.
146
+ - `SliderRange` (`src/components/SliderRange/`) — тот же слайдер на два ползунка: принимает
147
+ `values` парой, следит за их порядком и прокидывает `draggableTrack`.
99
148
 
100
- - Рендерится при наличии `renderTooltipContent`. По UX — обычно показывается всегда (см. SliderExtendedTooltip-логику).
149
+ ---
101
150
 
102
- ### **`children: never`**
151
+ ## Stories
103
152
 
104
- - Внутрь Slider'а нельзя положить кастомные элементы — для этого использовать SliderExtended.
153
+ Основные истории: `stories/Slider/Slider.stories.tsx`
154
+ Файлы примеров: `stories/Slider/examples/Slider/`
105
155
 
106
- ### **`FC, не forwardRef`**
156
+ | Story | Example file | Что демонстрирует |
157
+ |---|---|---|
158
+ | `Playground` | `Playground.tsx` | Интерактивный подбор `min`, `max`, `step`, `marks`, `size`, `disabled`, `reverse` |
159
+ | `Default` | `Default.tsx` | Слайдер с метками и шагом по умолчанию |
160
+ | `Sizes` | `Sizes.tsx` | Размеры MD и LG |
161
+ | `WithTooltip` | `WithTooltip.tsx` | Подсказка над ползунком через `renderTooltipContent` |
162
+ | `WithCustomSteps` | `WithCustomSteps.tsx` | Шаги заданы массивом значений |
163
+ | `Disabled` | `Disabled.tsx` | Неактивный слайдер |
164
+ | `Reverse` | `Reverse.tsx` | Значения возрастают справа налево |
165
+ | `Amounts` | `Amounts.tsx` | Production-like шкала сумм с неравномерным шагом: слайдер работает с индексами шкалы |
166
+ | `VisualTests` | `VisualTests.tsx` | Размеры, шаги массивом, реверс и неактивное состояние; `play` ставит фокус на первый ползунок, чтобы в кадр попали обводка фокуса и подсказка |
107
167
 
108
- - Ref не пробрасывается.
168
+ `Playground` исключён из скриншот-тестов. `WithTooltip` тоже исключён: подсказка скрыта, пока
169
+ ползунок не в фокусе, поэтому её кадр повторяет `Default`.
109
170
 
110
171
  ---
111
172
 
112
- ## Инварианты
173
+ ## История изменений
113
174
 
114
- - **Один Dot, фиксированная структура** — Rail/Dot/Track/Marks. Менять только через SliderExtended.
115
- - **`step` default `1`**.
116
- - **`marks: ISliderMark[]`** — обязателен, может быть `[]`.
117
- - **`renderTooltipContent?`** — опционально; без него Tooltip не рендерится.
118
- - **`size: MD | LG`** — `SM` не поддерживается.
119
- - **`children: never`**.
120
- - **`value` ∈ `[min, max]`** — потребитель ответственен (валидации нет).
121
- - **Если `step` — массив**, первое значение = `min`, последнее = `max`.
122
- - **`FC, не forwardRef`**.
175
+ | Дата | Изменение |
176
+ |---|---|
177
+ | 2026-09-11 | Создан документ. AI-рефакторинг (TRI-77): добавлен `displayName`, props задокументированы JSDoc, из разметки убран избыточный проброс `size` (значение приходит тем же spread'ом). Публичный API props, интерфейсов и barrel-экспортов не изменён. Добавлены unit-тесты, stories переведены на modern pattern. |
178
+ | 2026-09-14 | Правки по ревью (TRI-77): `Slider` обёрнут в `React.forwardRef` и пробрасывает `ref` на корневой `div` — раньше был `React.FC` и `ref` терялся. Тип компонента изменился на `React.ForwardRefExoticComponent`, запись в release notes 1.47.0. |
123
179
 
124
180
  ---
125
181
 
126
- ## Accessibility
182
+ ## Примеры использования
127
183
 
128
- - Наследуется от `SliderExtended.Dot` (см. SliderExtended-AI; обычно `<span>` с `tabIndex`).
129
- - Keyboard navigation — стрелки (детали в SliderExtendedDot).
184
+ ### Default
130
185
 
131
- ---
186
+ `stories/Slider/examples/Slider/Default.tsx`
132
187
 
133
- ## Дизайн-токены
188
+ ```tsx
189
+ import React, { useState } from "react";
190
+ import { EComponentSize, Slider } from "@sberbusiness/triplex-next";
191
+
192
+ const MARKS = [
193
+ { value: 0, label: "0" },
194
+ { value: 35, label: "35" },
195
+ { value: 66, label: "66" },
196
+ { value: 100, label: "100" },
197
+ ];
198
+
199
+ export const Default = () => {
200
+ const [value, setValue] = useState(35);
201
+
202
+ return (
203
+ <div style={{ maxWidth: "750px", padding: "30px" }}>
204
+ <div>value = {value}</div>
205
+ <br />
206
+ <Slider min={0} max={100} size={EComponentSize.MD} marks={MARKS} value={value} onChange={setValue} />
207
+ </div>
208
+ );
209
+ };
210
+ ```
134
211
 
135
- Нет собственных — наследуются от `SliderExtended`.
212
+ ### Sizes
136
213
 
137
- ---
214
+ `stories/Slider/examples/Slider/Sizes.tsx`
138
215
 
139
- ## Связанные компоненты
216
+ ```tsx
217
+ import React, { useState } from "react";
218
+ import { EComponentSize, Slider } from "@sberbusiness/triplex-next";
219
+
220
+ const MARKS = [
221
+ { value: 0, label: "0" },
222
+ { value: 50, label: "50" },
223
+ { value: 100, label: "100" },
224
+ ];
225
+
226
+ interface ISizeItemProps {
227
+ size: EComponentSize.MD | EComponentSize.LG;
228
+ }
229
+
230
+ const SIZES: ISizeItemProps["size"][] = [EComponentSize.MD, EComponentSize.LG];
231
+
232
+ const SizeItem = ({ size }: ISizeItemProps) => {
233
+ const [value, setValue] = useState(35);
234
+
235
+ return (
236
+ <div>
237
+ <div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: "700" }}>{size.toUpperCase()}</div>
238
+ <Slider min={0} max={100} size={size} marks={MARKS} value={value} onChange={setValue} />
239
+ </div>
240
+ );
241
+ };
242
+
243
+ export const Sizes = () => (
244
+ <div style={{ maxWidth: "750px", padding: "30px", display: "flex", flexDirection: "column", gap: "24px" }}>
245
+ {SIZES.map((size) => (
246
+ <SizeItem key={size} size={size} />
247
+ ))}
248
+ </div>
249
+ );
250
+ ```
140
251
 
141
- - `SliderExtended` — низкоуровневая основа (slots).
142
- - `SliderRange` — два ползунка.
252
+ ### WithTooltip
143
253
 
144
- ---
254
+ `stories/Slider/examples/Slider/WithTooltip.tsx`
145
255
 
146
- ## Stories
256
+ ```tsx
257
+ import React, { useState } from "react";
258
+ import { EComponentSize, Slider } from "@sberbusiness/triplex-next";
259
+
260
+ const MARKS = [
261
+ { value: 0, label: "0" },
262
+ { value: 35, label: "35" },
263
+ { value: 66, label: "66" },
264
+ { value: 100, label: "100" },
265
+ ];
266
+
267
+ export const WithTooltip = () => {
268
+ const [value, setValue] = useState(35);
269
+
270
+ return (
271
+ <div style={{ maxWidth: "750px", padding: "30px" }}>
272
+ <div>value = {value}</div>
273
+ <br />
274
+ <Slider
275
+ min={0}
276
+ max={100}
277
+ size={EComponentSize.MD}
278
+ marks={MARKS}
279
+ value={value}
280
+ onChange={setValue}
281
+ renderTooltipContent={(tooltipValue) => `${tooltipValue} %`}
282
+ />
283
+ </div>
284
+ );
285
+ };
286
+ ```
147
287
 
148
- `stories/Slider/Slider.stories.tsx`
149
- Примеры: `stories/Slider/examples/`
288
+ ### WithCustomSteps
150
289
 
151
- ---
290
+ `stories/Slider/examples/Slider/WithCustomSteps.tsx`
152
291
 
153
- ## История изменений
292
+ ```tsx
293
+ import React, { useState } from "react";
294
+ import { EComponentSize, Slider } from "@sberbusiness/triplex-next";
295
+
296
+ // Массив шагов вынесен из JSX: инлайновый массив пересчитывает шаги на каждом рендере.
297
+ const STEPS = [0, 25, 50, 75, 100];
298
+
299
+ const MARKS = STEPS.map((step) => ({ value: step, label: String(step) }));
300
+
301
+ export const WithCustomSteps = () => {
302
+ const [value, setValue] = useState(50);
303
+
304
+ return (
305
+ <div style={{ maxWidth: "750px", padding: "30px" }}>
306
+ <div>value = {value}</div>
307
+ <br />
308
+ <Slider
309
+ min={0}
310
+ max={100}
311
+ step={STEPS}
312
+ size={EComponentSize.MD}
313
+ marks={MARKS}
314
+ value={value}
315
+ onChange={setValue}
316
+ />
317
+ </div>
318
+ );
319
+ };
320
+ ```
321
+
322
+ ### Disabled
323
+
324
+ `stories/Slider/examples/Slider/Disabled.tsx`
325
+
326
+ ```tsx
327
+ import React from "react";
328
+ import { EComponentSize, Slider } from "@sberbusiness/triplex-next";
329
+
330
+ const MARKS = [
331
+ { value: 0, label: "0" },
332
+ { value: 35, label: "35" },
333
+ { value: 66, label: "66" },
334
+ { value: 100, label: "100" },
335
+ ];
336
+
337
+ export const Disabled = () => (
338
+ <div style={{ maxWidth: "750px", padding: "30px" }}>
339
+ <Slider min={0} max={100} size={EComponentSize.MD} marks={MARKS} value={35} onChange={() => {}} disabled />
340
+ </div>
341
+ );
342
+ ```
343
+
344
+ ### Reverse
345
+
346
+ `stories/Slider/examples/Slider/Reverse.tsx`
347
+
348
+ ```tsx
349
+ import React, { useState } from "react";
350
+ import { EComponentSize, Slider } from "@sberbusiness/triplex-next";
351
+
352
+ const MARKS = [
353
+ { value: 0, label: "0" },
354
+ { value: 35, label: "35" },
355
+ { value: 66, label: "66" },
356
+ { value: 100, label: "100" },
357
+ ];
358
+
359
+ export const Reverse = () => {
360
+ const [value, setValue] = useState(35);
361
+
362
+ return (
363
+ <div style={{ maxWidth: "750px", padding: "30px" }}>
364
+ <div>value = {value}</div>
365
+ <br />
366
+ <Slider
367
+ min={0}
368
+ max={100}
369
+ size={EComponentSize.MD}
370
+ marks={MARKS}
371
+ value={value}
372
+ onChange={setValue}
373
+ reverse
374
+ />
375
+ </div>
376
+ );
377
+ };
378
+ ```
379
+
380
+ ### Amounts
381
+
382
+ `stories/Slider/examples/Slider/Amounts.tsx`
383
+
384
+ ```tsx
385
+ import React, { useState } from "react";
386
+ import { EComponentSize, Slider } from "@sberbusiness/triplex-next";
387
+
388
+ /** Возвращает значения от from до to (не включая), с шагом step. */
389
+ const range = (from: number, to: number, step: number): number[] => {
390
+ const values: number[] = [];
391
+
392
+ for (let value = from; value < to; value += step) {
393
+ values.push(value);
394
+ }
395
+
396
+ return values;
397
+ };
398
+
399
+ /**
400
+ * Шкала сумм с неравномерным шагом: чем больше сумма, тем крупнее шаг.
401
+ * Слайдер работает с индексами шкалы, поэтому шаги равны визуально.
402
+ */
403
+ const AMOUNTS = [
404
+ 0,
405
+ 10000,
406
+ ...range(20000, 240000, 20000),
407
+ ...range(240000, 1000000, 40000),
408
+ ...range(1000000, 2150000, 50000),
409
+ ...range(2150000, 2600000, 75000),
410
+ ...range(2600000, 3000000, 100000),
411
+ ...range(3000000, 3800000, 200000),
412
+ ...range(3800000, 9000000, 400000),
413
+ ...range(9000000, 10000000, 500000),
414
+ ...range(10000000, 25000000, 2500000),
415
+ ...range(25000000, 40000000, 5000000),
416
+ ...range(40000000, 90000001, 10000000),
417
+ 100000000,
418
+ ];
419
+
420
+ const amountFormat = new Intl.NumberFormat("ru-RU");
421
+
422
+ const MARKS = [
423
+ { value: 0, label: "0 млн" },
424
+ { value: AMOUNTS.indexOf(1000000), label: "1 млн" },
425
+ { value: AMOUNTS.indexOf(3000000), label: "3 млн" },
426
+ { value: AMOUNTS.length - 1, label: "100 млн" },
427
+ ];
428
+
429
+ export const Amounts = () => {
430
+ const [amountIndex, setAmountIndex] = useState(AMOUNTS.indexOf(1000000));
431
+
432
+ return (
433
+ <div style={{ maxWidth: "750px", padding: "30px" }}>
434
+ <div>{amountFormat.format(AMOUNTS[amountIndex])}</div>
435
+ <br />
436
+ <Slider
437
+ min={0}
438
+ max={AMOUNTS.length - 1}
439
+ size={EComponentSize.MD}
440
+ marks={MARKS}
441
+ value={amountIndex}
442
+ onChange={setAmountIndex}
443
+ renderTooltipContent={(value) => amountFormat.format(AMOUNTS[value])}
444
+ />
445
+ </div>
446
+ );
447
+ };
448
+ ```
154
449
 
155
- | Дата | Изменение |
156
- |---|---|
157
- | 2026-04-18 | Создан документ |