@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.
- package/README.md +7 -7
- package/bundle/components/AmountField.md +222 -323
- package/bundle/components/Avatar.md +138 -146
- package/bundle/components/CardStatic.md +402 -0
- package/bundle/components/CheckboxTree.md +157 -215
- package/bundle/components/CheckboxTreeExtended.md +7 -7
- package/bundle/components/ChipGroup.md +1 -1
- package/bundle/components/ChipMonthYearPicker.md +4 -4
- package/bundle/components/ChipSuggest.md +7 -6
- package/bundle/components/CollapsibleTree.md +8 -4
- package/bundle/components/CollapsibleTreeExtended.md +8 -6
- package/bundle/components/Confirm.md +346 -281
- package/bundle/components/DateRange.md +351 -210
- package/bundle/components/FooterPage.md +1 -0
- package/bundle/components/FormField.md +11 -4
- package/bundle/components/FormGroup.md +3 -2
- package/bundle/components/LightBox.md +8 -0
- package/bundle/components/ListMaster.md +2 -2
- package/bundle/components/ListTableItem.md +6 -6
- package/bundle/components/MonthYearField.md +15 -4
- package/bundle/components/Slider.md +389 -97
- package/bundle/components/SliderRange.md +486 -105
- package/bundle/components/StatusTracker.md +386 -94
- package/bundle/components/Stepper.md +355 -102
- package/bundle/components/StepperExtended.md +633 -0
- package/bundle/components/SuggestField.md +1049 -96
- package/bundle/components/SwipeableArea.md +7 -7
- package/bundle/components/Tabs.md +265 -92
- package/bundle/components/TabsExtended.md +18 -18
- package/bundle/components/TabsLine.md +301 -127
- package/bundle/components/TagColor.md +187 -66
- package/bundle/components/TagGroup.md +184 -48
- package/bundle/components/TextareaField.md +278 -70
- package/bundle/components/TopOverlay.md +17 -1
- package/bundle/components/TreeView.md +16 -7
- package/bundle/components/TriggerClickOnKeyDownEvent.md +277 -0
- package/bundle/components/UploadZone.md +318 -0
- package/bundle/guides/codestyle.md +16 -1
- package/bundle/guides/commits.md +47 -1
- package/bundle/guides/tests.md +23 -2
- package/bundle/manifest.json +48 -21
- package/bundle/release-notes/1.47.0.mdx +115 -0
- package/bundle/release-notes/1.48.0.mdx +68 -0
- package/bundle/release-notes/1.49.0.mdx +7 -0
- package/bundle/tokens.json +3 -3
- package/dist/index.js +220 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: StepperExtended
|
|
3
|
+
category: Stepper
|
|
4
|
+
related: [Stepper, IconWrapper]
|
|
5
|
+
tokens:
|
|
6
|
+
- Stepper.Step_Background_Default
|
|
7
|
+
- Stepper.Step_Background_Hover
|
|
8
|
+
- Stepper.Step_Background_Disabled
|
|
9
|
+
- Stepper.Step_Background_Error
|
|
10
|
+
- Stepper.Step_Background_Error_Hover
|
|
11
|
+
- Stepper.Step_Background_Warning
|
|
12
|
+
- Stepper.Step_Background_Warning_Hover
|
|
13
|
+
- Stepper.Step_BorderColor_Success
|
|
14
|
+
- Stepper.Step_BorderColor_Error
|
|
15
|
+
- Stepper.Step_BorderColor_Warning
|
|
16
|
+
- Stepper.Step_BorderColor_Focus
|
|
17
|
+
- Stepper.Step_Color_Default
|
|
18
|
+
- Stepper.Step_Color_Hover
|
|
19
|
+
- Stepper.Step_Color_Disabled
|
|
20
|
+
stories: stories/Stepper/StepperExtended.stories.tsx
|
|
21
|
+
version: "1.0"
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# StepperExtended
|
|
25
|
+
|
|
26
|
+
## Назначение
|
|
27
|
+
|
|
28
|
+
Базовый степпер — горизонтальная лента шагов-«стрелок», показывающая, где пользователь
|
|
29
|
+
находится в многошаговом сценарии. Сам компонент рендерит только `<ol role="tablist">` и
|
|
30
|
+
контекст (размер, выбранный шаг, обработчик выбора); состав ленты собирает потребитель из
|
|
31
|
+
`StepperExtended.Step`. Ни прокрутки, ни кнопок «назад/вперёд», ни автоматического
|
|
32
|
+
вычисления пройденных шагов здесь нет.
|
|
33
|
+
|
|
34
|
+
Используй когда: нужен полный контроль над списком шагов — разное содержимое шагов,
|
|
35
|
+
собственная прокрутка, шаги вперемешку с другой разметкой, нестандартная логика
|
|
36
|
+
«пройден / не пройден».
|
|
37
|
+
|
|
38
|
+
Не используй когда:
|
|
39
|
+
|
|
40
|
+
- достаточно массива шагов «лейбл + иконка» — возьми `Stepper`: он собран поверх
|
|
41
|
+
`StepperExtended`, добавляет карусель с кнопками прокрутки и сам доводит выбранный шаг
|
|
42
|
+
до видимой области;
|
|
43
|
+
- нужен вертикальный индикатор прогресса со статусами — это `StatusTracker`, не степпер;
|
|
44
|
+
- нужны табы-переключатели контента — возьми `Tabs` / `TabsExtended`.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Состав (compound-компонент)
|
|
49
|
+
|
|
50
|
+
| Субкомпонент | Обязателен | Что делает |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| `StepperExtended.Step` (`StepperStep`) | Да | Один шаг: `<li role="button">` с содержимым, иконкой и декоративной стрелкой-границей справа. Обрабатывает клик, `Enter` / `Space` и подсветку фокуса |
|
|
53
|
+
| `StepperExtended.Step.Icon` (`StepperStepIcon`) | Нет | Готовая иконка статуса по `EStepperStepIconType`. Кладётся в prop `icon` шага. Экспортируется из пакета и отдельно — как `StepperStepIcon` |
|
|
54
|
+
|
|
55
|
+
Собственного AI.md у обоих нет, но по разным причинам (`docs/ai/CONTEXT.md` §
|
|
56
|
+
«Когда создавать `{ComponentName}-ai.md`»). `StepperStep` не экспортируется из barrel
|
|
57
|
+
`src/components/Stepper/index.ts` — он доступен только как `StepperExtended.Step` /
|
|
58
|
+
`Stepper.Step`. `StepperStepIcon` из barrel экспортируется, но нетривиального API
|
|
59
|
+
у него нет: единственный prop `type` выбирает иконку из `@sberbusiness/icons-next`,
|
|
60
|
+
ни состояния, ни колбэков, ни клавиатуры. Оба описаны здесь.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Варианты и props
|
|
65
|
+
|
|
66
|
+
`IStepperExtendedProps` расширяет `React.HTMLAttributes<HTMLOListElement>` — неизвестные
|
|
67
|
+
компоненту атрибуты уходят на корневой `<ol>`.
|
|
68
|
+
|
|
69
|
+
### Обязательные props
|
|
70
|
+
|
|
71
|
+
| Prop | Тип | Описание |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| `onSelectStep` | `(id: string) => void` | Запрос на смену шага. Вызывается с `id` шага по клику и по `Enter` / `Space`. Вызывается и для уже выбранного шага — фильтровать повтор, если он не нужен, должен потребитель |
|
|
74
|
+
|
|
75
|
+
### Опциональные props
|
|
76
|
+
|
|
77
|
+
| Prop | Тип | По умолчанию | Описание |
|
|
78
|
+
|---|---|---|---|
|
|
79
|
+
| `size` | `EComponentSize` | `EComponentSize.MD` | Размер шагов: SM / MD / LG. Уходит в контекст, каждый шаг берёт его оттуда |
|
|
80
|
+
| `selectedStepId` | `string` | — | Id текущего шага. Компонент полностью управляемый, своего состояния выбора у него нет. Без значения ни один шаг не помечен выбранным |
|
|
81
|
+
| `forwardedRef` | `React.Ref<HTMLOListElement>` | — | Исторический способ получить ссылку на `<ol>`. Дублирует `ref`, оба заполняются одним и тем же элементом |
|
|
82
|
+
|
|
83
|
+
### Props шага (`StepperExtended.Step`)
|
|
84
|
+
|
|
85
|
+
`IStepperStepProps` расширяет `React.LiHTMLAttributes<HTMLLIElement>`.
|
|
86
|
+
|
|
87
|
+
| Prop | Тип | По умолчанию | Описание |
|
|
88
|
+
|---|---|---|---|
|
|
89
|
+
| `id` | `string` | — | Обязателен. Сопоставляется с `selectedStepId` и приходит в `onSelectStep`. На `<li>` как DOM-атрибут **не попадает** — искать шаг через `document.getElementById` нельзя |
|
|
90
|
+
| `type` | `EStepperStepType` | — | Обязателен. `NEUTRAL` / `ERROR` / `WARNING` — цвет заливки шага |
|
|
91
|
+
| `disabled` | `boolean` | `false` | Шаг не выбирается ни мышью, ни с клавиатуры |
|
|
92
|
+
| `isInActiveStep` | `boolean` | `false` | Шаг ещё не пройден |
|
|
93
|
+
| `icon` | `React.ReactNode` | — | Иконка слева от содержимого. Обычно `StepperStepIcon` |
|
|
94
|
+
| `forwardedRef` | `React.Ref<HTMLLIElement>` | — | Ссылка на `<li>`. У шага это **единственный** способ получить элемент: `StepperStep` объявлен как `React.FC` и обычный `ref` не принимает |
|
|
95
|
+
|
|
96
|
+
### Три визуальных состояния шага и как они выводятся
|
|
97
|
+
|
|
98
|
+
Состояние шага компонент не вычисляет — он выводит его из пары «`id === selectedStepId`»
|
|
99
|
+
и prop `isInActiveStep`:
|
|
100
|
+
|
|
101
|
+
| Условие | Класс | Смысл |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `id === selectedStepId` | `active` | Текущий шаг. Подсвечен рамкой `Step_BorderColor_Success`, курсор `default` |
|
|
104
|
+
| `isInActiveStep` | `inactive` | Шаг ещё не пройден: приглушённый текст |
|
|
105
|
+
| иначе | `completed` | Шаг пройден |
|
|
106
|
+
|
|
107
|
+
Отсюда главное ограничение: **`isInActiveStep` проставляет потребитель**. Если его не
|
|
108
|
+
передать, все невыбранные шаги окажутся «пройденными». `Stepper` делает это за вас
|
|
109
|
+
(`index > selectedIndex`), при ручной сборке на `StepperExtended` это ваша работа.
|
|
110
|
+
|
|
111
|
+
`type` (`ERROR` / `WARNING`) действует поверх любого из трёх состояний, но игнорируется
|
|
112
|
+
у шага с `disabled`.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Дизайн-токены
|
|
117
|
+
|
|
118
|
+
Переопределяются через `ThemeProvider` (prop `tokens`) — см. `ThemeProvider-ai.md` →
|
|
119
|
+
«Как переопределять токены». Значения по умолчанию — `src/components/DesignTokens/components/Stepper.ts`.
|
|
120
|
+
|
|
121
|
+
У корневого `<ol>` собственного оформления нет: он задаёт только `display: flex` и
|
|
122
|
+
сбрасывает маркеры списка. Все перечисленные токены применяет `StepperExtended.Step`;
|
|
123
|
+
группа `Stepper` общая со `Stepper`, поэтому переименование токена ломает оба компонента
|
|
124
|
+
сразу.
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
Stepper.Step_Background_Default
|
|
128
|
+
Stepper.Step_Background_Hover
|
|
129
|
+
Stepper.Step_Background_Disabled
|
|
130
|
+
Stepper.Step_Background_Error
|
|
131
|
+
Stepper.Step_Background_Error_Hover
|
|
132
|
+
Stepper.Step_Background_Warning
|
|
133
|
+
Stepper.Step_Background_Warning_Hover
|
|
134
|
+
Stepper.Step_BorderColor_Success
|
|
135
|
+
Stepper.Step_BorderColor_Error
|
|
136
|
+
Stepper.Step_BorderColor_Warning
|
|
137
|
+
Stepper.Step_BorderColor_Focus
|
|
138
|
+
Stepper.Step_Color_Default
|
|
139
|
+
Stepper.Step_Color_Hover
|
|
140
|
+
Stepper.Step_Color_Disabled
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Токены `Stepper.ButtonWrapper_Background_Prev` и `Stepper.ButtonWrapper_Background_Next`
|
|
144
|
+
в эту группу входят, но относятся к кнопкам прокрутки `Stepper` — `StepperExtended` их не
|
|
145
|
+
использует.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Инварианты
|
|
150
|
+
|
|
151
|
+
- `forwardRef` на `StepperExtended` — не убирать. Ref указывает на корневой `<ol>`, то есть
|
|
152
|
+
на тот же элемент, который получает `className` и `...rest`.
|
|
153
|
+
- Prop `forwardedRef` остаётся в публичном API и заполняется тем же элементом, что и `ref`.
|
|
154
|
+
Удалить его — breaking change: на нём построен проброс ссылки из `Stepper`, который
|
|
155
|
+
передаёт в `StepperExtended` весь свой `...restProps`.
|
|
156
|
+
- `StepperExtended` — `forwardRef`-компонент со статическим свойством `Step`. Набор
|
|
157
|
+
статических свойств — часть публичного API; у `Step`, в свою очередь, статическое `Icon`.
|
|
158
|
+
- Корневой элемент — `<ol>`. Шаги обязаны быть `<li>`, то есть `StepperExtended.Step`:
|
|
159
|
+
произвольный узел сломает валидность списка.
|
|
160
|
+
- `role="tablist"` стоит **до** `...rest` — потребитель может его переопределить.
|
|
161
|
+
Значение по умолчанию сохранено из v0 ради обратной совместимости и не соответствует
|
|
162
|
+
ARIA-контракту табов (`tablist` ожидает детей `role="tab"`, а шаги используют
|
|
163
|
+
`role="button"`). Менять роль по умолчанию — breaking change в accessibility-контракте,
|
|
164
|
+
отдельная задача.
|
|
165
|
+
- Значение контекста мемоизировано (`useMemo`). Возврат к пересозданию объекта на каждый
|
|
166
|
+
рендер вернёт перерисовку всех шагов на любое обновление родителя.
|
|
167
|
+
- `StepperExtendedContext` через barrel не экспортируется — форма контекста внутренняя
|
|
168
|
+
деталь, на неё нельзя опираться снаружи.
|
|
169
|
+
- Компонент управляемый: он не хранит `selectedStepId` и не меняет его сам. Если
|
|
170
|
+
`onSelectStep` не обновляет состояние потребителя, визуально ничего не произойдёт.
|
|
171
|
+
- `StepperStep` пока объявлен как `React.FC` и принимает ссылку только через
|
|
172
|
+
`forwardedRef` — на `forwardRef` он ещё не переведён.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Accessibility
|
|
177
|
+
|
|
178
|
+
- Корневой элемент — `<ol>` с `role="tablist"` (см. инварианты: роль исторически
|
|
179
|
+
не совпадает с ролями детей).
|
|
180
|
+
- Каждый шаг — `<li role="button">` с `tabIndex=0`, то есть попадает в порядок обхода
|
|
181
|
+
клавиатурой. Шаг с `disabled` получает `tabIndex=-1` и `aria-disabled="true"` и
|
|
182
|
+
из обхода выпадает.
|
|
183
|
+
- Выбранный шаг помечен `aria-current="true"`; у остальных атрибута нет.
|
|
184
|
+
- Клавиатура: `Enter` и `Space` выбирают шаг, `Space` дополнительно гасит прокрутку
|
|
185
|
+
страницы (`preventDefault`). Стрелками шаги не переключаются — roving tabindex у
|
|
186
|
+
компонента нет.
|
|
187
|
+
- Подсветка фокуса — только при клавиатурной навигации: шаг запоминает источник фокуса
|
|
188
|
+
(`EFocusSource`) и добавляет рамку `Step_BorderColor_Focus` лишь если фокусу не
|
|
189
|
+
предшествовал `mousedown`.
|
|
190
|
+
- Компонент не хардкодит текст. Если содержимое шага не текстовое (только иконка),
|
|
191
|
+
доступное имя (`aria-label`) задаёт потребитель — библиотека мультиязычная.
|
|
192
|
+
- Связь шага с панелью контента (`aria-controls`, `id` панели) компонент не выставляет:
|
|
193
|
+
это на стороне потребителя.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Связанные компоненты
|
|
198
|
+
|
|
199
|
+
**Части составного компонента:**
|
|
200
|
+
|
|
201
|
+
- `StepperStep` (`StepperExtended.Step`) — шаг ленты: состояния, клик, клавиатура,
|
|
202
|
+
подсветка фокуса, стрелка-граница справа (`StepperStepArrowBorder`, внутренний).
|
|
203
|
+
Из barrel не экспортируется.
|
|
204
|
+
- `StepperStepIcon` — набор готовых иконок статуса (`FILLED`, `SUCCESS`, `WARNING`,
|
|
205
|
+
`ERROR`, `WAIT`) для prop `icon`. Экспортируется из пакета, своей логики кроме
|
|
206
|
+
`switch` по типу не имеет.
|
|
207
|
+
|
|
208
|
+
**Соседние компоненты:**
|
|
209
|
+
|
|
210
|
+
- `Stepper` — готовый степпер поверх `StepperExtended`: принимает массив `steps`, сам
|
|
211
|
+
считает `isInActiveStep`, оборачивает ленту в `CarouselExtended` с кнопками прокрутки
|
|
212
|
+
и доводит выбранный шаг до видимой области. Первый выбор для типовой задачи.
|
|
213
|
+
- `CarouselExtended` — горизонтальная прокручиваемая лента; в `Stepper` и во всех примерах
|
|
214
|
+
stories именно она даёт степперу прокрутку. Зависимости от неё у `StepperExtended` нет.
|
|
215
|
+
- `IconWrapper` — им шаг оборачивает `icon`, чтобы приглушить иконку в состоянии
|
|
216
|
+
`disabled`.
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Stories
|
|
221
|
+
|
|
222
|
+
Основные истории: `stories/Stepper/StepperExtended.stories.tsx`
|
|
223
|
+
Файлы примеров: `stories/Stepper/examples/StepperExtended/`
|
|
224
|
+
|
|
225
|
+
| Story | Example file | Что демонстрирует |
|
|
226
|
+
|---|---|---|
|
|
227
|
+
| `Playground` | `Playground.tsx` | Интерактивный контроль размера, выбранного шага, иконок и недоступного шага |
|
|
228
|
+
| `Default` | `Default.tsx` | Минимальная лента из четырёх шагов в `CarouselExtended` с вычислением `isInActiveStep` |
|
|
229
|
+
| `Sizes` | `Sizes.tsx` | Размеры SM / MD / LG |
|
|
230
|
+
| `Types` | `Types.tsx` | Типы шага `NEUTRAL` / `ERROR` / `WARNING` |
|
|
231
|
+
| `States` | `States.tsx` | Четыре состояния шага рядом: пройден, выбран, недоступен, не пройден |
|
|
232
|
+
| `WithIcons` | `WithIcons.tsx` | Все типы `StepperStepIcon` в шагах |
|
|
233
|
+
| `VisualTests` | `VisualTests.tsx` | Размеры × типы со всеми состояниями шага и `:focus-visible` на первом шаге (через `play`) |
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## История изменений
|
|
238
|
+
|
|
239
|
+
| Дата | Изменение |
|
|
240
|
+
|---|---|
|
|
241
|
+
| 2026-09-23 | Создан документ AI-ready для `StepperExtended` (TRI-85). |
|
|
242
|
+
| 2026-09-23 | AI-рефакторинг: компонент переведён с `React.FC` на `forwardRef` (prop `forwardedRef` сохранён и заполняется тем же элементом), появился `displayName`, статическое `Step` подключается через `Object.assign`. JSDoc проставлен на всех публичных props. Добавлены unit-тесты и stories по modern pattern. Публичный API (имена props, значения enum, barrel-экспорты) не изменён. |
|
|
243
|
+
| 2026-09-24 | Правки stories по ревью: все примеры обёрнуты в `CarouselExtended` с кнопками прокрутки, story `Example` удалена как дублирующая, нейтральные шаги переименованы в `Step 1/2/3/4`, иконки убраны из `Default`, `Sizes`, `Types`. Код компонента не менялся. |
|
|
244
|
+
| 2026-09-24 | Правки stories по второму кругу ревью: во всех примерах по умолчанию выбран первый шаг, в `States` порядок шагов «пройден → выбран → недоступен → не пройден» с выбранным вторым и без иконок. Код компонента не менялся. |
|
|
245
|
+
| 2026-09-24 | `VisualTests` приведена к тому же виду, что и `States`: иконки убраны, порядок шагов «пройден → выбран → недоступен → не пройден». Иконки остались только в `WithIcons`. Код компонента не менялся. |
|
|
246
|
+
| 2026-09-25 | Размер по умолчанию изменён с `LG` на `MD` (TRI-84) — вслед за `Stepper`, дефолт хранится и в пропе, и в значении контекста по умолчанию. Изменение наблюдаемое: без явного `size` шаги становятся меньше, описано в release notes 1.48.0. |
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Примеры использования
|
|
251
|
+
|
|
252
|
+
### Default
|
|
253
|
+
|
|
254
|
+
`stories/Stepper/examples/StepperExtended/Default.tsx`
|
|
255
|
+
|
|
256
|
+
```tsx
|
|
257
|
+
import React, { useState } from "react";
|
|
258
|
+
import { CaretleftStrokeSrvIcon24, CaretrightStrokeSrvIcon24 } from "@sberbusiness/icons-next";
|
|
259
|
+
import {
|
|
260
|
+
ButtonIcon,
|
|
261
|
+
CarouselExtended,
|
|
262
|
+
ICarouselExtendedButtonProvideProps,
|
|
263
|
+
StepperExtended,
|
|
264
|
+
EStepperStepType,
|
|
265
|
+
} from "@sberbusiness/triplex-next";
|
|
266
|
+
|
|
267
|
+
const STEPS = [
|
|
268
|
+
{ id: "step-1", label: "Step 1" },
|
|
269
|
+
{ id: "step-2", label: "Step 2" },
|
|
270
|
+
{ id: "step-3", label: "Step 3" },
|
|
271
|
+
{ id: "step-4", label: "Step 4" },
|
|
272
|
+
];
|
|
273
|
+
|
|
274
|
+
/** Величина прокрутки за один клик по кнопке. */
|
|
275
|
+
const SCROLL_STEP = 200;
|
|
276
|
+
|
|
277
|
+
/** Пока прокрутка не нужна, компонент передаёт hidden: кнопка не рендерится. */
|
|
278
|
+
const renderPrevButton = ({ hidden, ...buttonProps }: ICarouselExtendedButtonProvideProps) =>
|
|
279
|
+
hidden ? null : (
|
|
280
|
+
<ButtonIcon aria-label="Прокрутить назад" {...buttonProps}>
|
|
281
|
+
<CaretleftStrokeSrvIcon24 paletteIndex={5} />
|
|
282
|
+
</ButtonIcon>
|
|
283
|
+
);
|
|
284
|
+
|
|
285
|
+
const renderNextButton = ({ hidden, ...buttonProps }: ICarouselExtendedButtonProvideProps) =>
|
|
286
|
+
hidden ? null : (
|
|
287
|
+
<ButtonIcon aria-label="Прокрутить вперёд" {...buttonProps}>
|
|
288
|
+
<CaretrightStrokeSrvIcon24 paletteIndex={5} />
|
|
289
|
+
</ButtonIcon>
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
export const Default = () => {
|
|
293
|
+
const [selectedStepId, setSelectedStepId] = useState("step-1");
|
|
294
|
+
const selectedIndex = STEPS.findIndex((step) => step.id === selectedStepId);
|
|
295
|
+
|
|
296
|
+
return (
|
|
297
|
+
<CarouselExtended
|
|
298
|
+
style={{ display: "flex", alignItems: "center", maxWidth: "640px" }}
|
|
299
|
+
buttonPrev={renderPrevButton}
|
|
300
|
+
buttonNext={renderNextButton}
|
|
301
|
+
stepPrev={SCROLL_STEP}
|
|
302
|
+
stepNext={SCROLL_STEP}
|
|
303
|
+
>
|
|
304
|
+
<StepperExtended selectedStepId={selectedStepId} onSelectStep={setSelectedStepId}>
|
|
305
|
+
{STEPS.map(({ id, label }, index) => (
|
|
306
|
+
<StepperExtended.Step
|
|
307
|
+
key={id}
|
|
308
|
+
id={id}
|
|
309
|
+
type={EStepperStepType.NEUTRAL}
|
|
310
|
+
// Шаги правее выбранного ещё не пройдены.
|
|
311
|
+
isInActiveStep={index > selectedIndex}
|
|
312
|
+
>
|
|
313
|
+
{label}
|
|
314
|
+
</StepperExtended.Step>
|
|
315
|
+
))}
|
|
316
|
+
</StepperExtended>
|
|
317
|
+
</CarouselExtended>
|
|
318
|
+
);
|
|
319
|
+
};
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Sizes
|
|
323
|
+
|
|
324
|
+
`stories/Stepper/examples/StepperExtended/Sizes.tsx`
|
|
325
|
+
|
|
326
|
+
```tsx
|
|
327
|
+
import React, { useState } from "react";
|
|
328
|
+
import { CaretleftStrokeSrvIcon24, CaretrightStrokeSrvIcon24 } from "@sberbusiness/icons-next";
|
|
329
|
+
import {
|
|
330
|
+
ButtonIcon,
|
|
331
|
+
CarouselExtended,
|
|
332
|
+
ICarouselExtendedButtonProvideProps,
|
|
333
|
+
StepperExtended,
|
|
334
|
+
EComponentSize,
|
|
335
|
+
EStepperStepType,
|
|
336
|
+
} from "@sberbusiness/triplex-next";
|
|
337
|
+
|
|
338
|
+
const STEPS = [
|
|
339
|
+
{ id: "step-1", label: "Step 1" },
|
|
340
|
+
{ id: "step-2", label: "Step 2" },
|
|
341
|
+
{ id: "step-3", label: "Step 3" },
|
|
342
|
+
{ id: "step-4", label: "Step 4" },
|
|
343
|
+
];
|
|
344
|
+
|
|
345
|
+
/** Величина прокрутки за один клик по кнопке. */
|
|
346
|
+
const SCROLL_STEP = 200;
|
|
347
|
+
|
|
348
|
+
/** Пока прокрутка не нужна, компонент передаёт hidden: кнопка не рендерится. */
|
|
349
|
+
const renderPrevButton = ({ hidden, ...buttonProps }: ICarouselExtendedButtonProvideProps) =>
|
|
350
|
+
hidden ? null : (
|
|
351
|
+
<ButtonIcon aria-label="Прокрутить назад" {...buttonProps}>
|
|
352
|
+
<CaretleftStrokeSrvIcon24 paletteIndex={5} />
|
|
353
|
+
</ButtonIcon>
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
const renderNextButton = ({ hidden, ...buttonProps }: ICarouselExtendedButtonProvideProps) =>
|
|
357
|
+
hidden ? null : (
|
|
358
|
+
<ButtonIcon aria-label="Прокрутить вперёд" {...buttonProps}>
|
|
359
|
+
<CaretrightStrokeSrvIcon24 paletteIndex={5} />
|
|
360
|
+
</ButtonIcon>
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
interface ISizeItemProps {
|
|
364
|
+
size: EComponentSize;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const SizeItem = ({ size }: ISizeItemProps) => {
|
|
368
|
+
const [selectedStepId, setSelectedStepId] = useState("step-1");
|
|
369
|
+
const selectedIndex = STEPS.findIndex((step) => step.id === selectedStepId);
|
|
370
|
+
|
|
371
|
+
return (
|
|
372
|
+
<div>
|
|
373
|
+
<div style={{ marginBottom: 8, fontSize: 16, fontWeight: 700 }}>{size.toUpperCase()}</div>
|
|
374
|
+
<CarouselExtended
|
|
375
|
+
style={{ display: "flex", alignItems: "center", maxWidth: "640px" }}
|
|
376
|
+
buttonPrev={renderPrevButton}
|
|
377
|
+
buttonNext={renderNextButton}
|
|
378
|
+
stepPrev={SCROLL_STEP}
|
|
379
|
+
stepNext={SCROLL_STEP}
|
|
380
|
+
>
|
|
381
|
+
<StepperExtended size={size} selectedStepId={selectedStepId} onSelectStep={setSelectedStepId}>
|
|
382
|
+
{STEPS.map(({ id, label }, index) => (
|
|
383
|
+
<StepperExtended.Step
|
|
384
|
+
key={id}
|
|
385
|
+
id={id}
|
|
386
|
+
type={EStepperStepType.NEUTRAL}
|
|
387
|
+
isInActiveStep={index > selectedIndex}
|
|
388
|
+
>
|
|
389
|
+
{label}
|
|
390
|
+
</StepperExtended.Step>
|
|
391
|
+
))}
|
|
392
|
+
</StepperExtended>
|
|
393
|
+
</CarouselExtended>
|
|
394
|
+
</div>
|
|
395
|
+
);
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
const SIZES = Object.values(EComponentSize);
|
|
399
|
+
|
|
400
|
+
export const Sizes = () => (
|
|
401
|
+
<div style={{ display: "flex", flexDirection: "column", gap: 24 }}>
|
|
402
|
+
{SIZES.map((size) => (
|
|
403
|
+
<SizeItem key={size} size={size} />
|
|
404
|
+
))}
|
|
405
|
+
</div>
|
|
406
|
+
);
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
### Types
|
|
410
|
+
|
|
411
|
+
`stories/Stepper/examples/StepperExtended/Types.tsx`
|
|
412
|
+
|
|
413
|
+
```tsx
|
|
414
|
+
import React, { useState } from "react";
|
|
415
|
+
import { CaretleftStrokeSrvIcon24, CaretrightStrokeSrvIcon24 } from "@sberbusiness/icons-next";
|
|
416
|
+
import {
|
|
417
|
+
ButtonIcon,
|
|
418
|
+
CarouselExtended,
|
|
419
|
+
ICarouselExtendedButtonProvideProps,
|
|
420
|
+
StepperExtended,
|
|
421
|
+
EComponentSize,
|
|
422
|
+
EStepperStepType,
|
|
423
|
+
} from "@sberbusiness/triplex-next";
|
|
424
|
+
|
|
425
|
+
const STEPS = [
|
|
426
|
+
{ id: "step-1", label: "Step 1" },
|
|
427
|
+
{ id: "step-2", label: "Step 2" },
|
|
428
|
+
{ id: "step-3", label: "Step 3" },
|
|
429
|
+
];
|
|
430
|
+
|
|
431
|
+
/** Величина прокрутки за один клик по кнопке. */
|
|
432
|
+
const SCROLL_STEP = 200;
|
|
433
|
+
|
|
434
|
+
/** Пока прокрутка не нужна, компонент передаёт hidden: кнопка не рендерится. */
|
|
435
|
+
const renderPrevButton = ({ hidden, ...buttonProps }: ICarouselExtendedButtonProvideProps) =>
|
|
436
|
+
hidden ? null : (
|
|
437
|
+
<ButtonIcon aria-label="Прокрутить назад" {...buttonProps}>
|
|
438
|
+
<CaretleftStrokeSrvIcon24 paletteIndex={5} />
|
|
439
|
+
</ButtonIcon>
|
|
440
|
+
);
|
|
441
|
+
|
|
442
|
+
const renderNextButton = ({ hidden, ...buttonProps }: ICarouselExtendedButtonProvideProps) =>
|
|
443
|
+
hidden ? null : (
|
|
444
|
+
<ButtonIcon aria-label="Прокрутить вперёд" {...buttonProps}>
|
|
445
|
+
<CaretrightStrokeSrvIcon24 paletteIndex={5} />
|
|
446
|
+
</ButtonIcon>
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
interface ITypeItemProps {
|
|
450
|
+
type: EStepperStepType;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const TypeItem = ({ type }: ITypeItemProps) => {
|
|
454
|
+
const [selectedStepId, setSelectedStepId] = useState("step-1");
|
|
455
|
+
const selectedIndex = STEPS.findIndex((step) => step.id === selectedStepId);
|
|
456
|
+
|
|
457
|
+
return (
|
|
458
|
+
<div>
|
|
459
|
+
<div style={{ marginBottom: 8, fontSize: 16, fontWeight: 700 }}>{type.toUpperCase()}</div>
|
|
460
|
+
<CarouselExtended
|
|
461
|
+
style={{ display: "flex", alignItems: "center", maxWidth: "640px" }}
|
|
462
|
+
buttonPrev={renderPrevButton}
|
|
463
|
+
buttonNext={renderNextButton}
|
|
464
|
+
stepPrev={SCROLL_STEP}
|
|
465
|
+
stepNext={SCROLL_STEP}
|
|
466
|
+
>
|
|
467
|
+
<StepperExtended
|
|
468
|
+
size={EComponentSize.MD}
|
|
469
|
+
selectedStepId={selectedStepId}
|
|
470
|
+
onSelectStep={setSelectedStepId}
|
|
471
|
+
>
|
|
472
|
+
{STEPS.map(({ id, label }, index) => (
|
|
473
|
+
<StepperExtended.Step key={id} id={id} type={type} isInActiveStep={index > selectedIndex}>
|
|
474
|
+
{label}
|
|
475
|
+
</StepperExtended.Step>
|
|
476
|
+
))}
|
|
477
|
+
</StepperExtended>
|
|
478
|
+
</CarouselExtended>
|
|
479
|
+
</div>
|
|
480
|
+
);
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
const TYPES = Object.values(EStepperStepType);
|
|
484
|
+
|
|
485
|
+
export const Types = () => (
|
|
486
|
+
<div style={{ display: "flex", flexDirection: "column", gap: 24 }}>
|
|
487
|
+
{TYPES.map((type) => (
|
|
488
|
+
<TypeItem key={type} type={type} />
|
|
489
|
+
))}
|
|
490
|
+
</div>
|
|
491
|
+
);
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
### States
|
|
495
|
+
|
|
496
|
+
`stories/Stepper/examples/StepperExtended/States.tsx`
|
|
497
|
+
|
|
498
|
+
```tsx
|
|
499
|
+
import React, { useState } from "react";
|
|
500
|
+
import { CaretleftStrokeSrvIcon24, CaretrightStrokeSrvIcon24 } from "@sberbusiness/icons-next";
|
|
501
|
+
import {
|
|
502
|
+
ButtonIcon,
|
|
503
|
+
CarouselExtended,
|
|
504
|
+
ICarouselExtendedButtonProvideProps,
|
|
505
|
+
StepperExtended,
|
|
506
|
+
EComponentSize,
|
|
507
|
+
EStepperStepType,
|
|
508
|
+
} from "@sberbusiness/triplex-next";
|
|
509
|
+
|
|
510
|
+
/** Величина прокрутки за один клик по кнопке. */
|
|
511
|
+
const SCROLL_STEP = 200;
|
|
512
|
+
|
|
513
|
+
/** Пока прокрутка не нужна, компонент передаёт hidden: кнопка не рендерится. */
|
|
514
|
+
const renderPrevButton = ({ hidden, ...buttonProps }: ICarouselExtendedButtonProvideProps) =>
|
|
515
|
+
hidden ? null : (
|
|
516
|
+
<ButtonIcon aria-label="Прокрутить назад" {...buttonProps}>
|
|
517
|
+
<CaretleftStrokeSrvIcon24 paletteIndex={5} />
|
|
518
|
+
</ButtonIcon>
|
|
519
|
+
);
|
|
520
|
+
|
|
521
|
+
const renderNextButton = ({ hidden, ...buttonProps }: ICarouselExtendedButtonProvideProps) =>
|
|
522
|
+
hidden ? null : (
|
|
523
|
+
<ButtonIcon aria-label="Прокрутить вперёд" {...buttonProps}>
|
|
524
|
+
<CaretrightStrokeSrvIcon24 paletteIndex={5} />
|
|
525
|
+
</ButtonIcon>
|
|
526
|
+
);
|
|
527
|
+
|
|
528
|
+
export const States = () => {
|
|
529
|
+
const [selectedStepId, setSelectedStepId] = useState("selected");
|
|
530
|
+
|
|
531
|
+
return (
|
|
532
|
+
<CarouselExtended
|
|
533
|
+
style={{ display: "flex", alignItems: "center", maxWidth: "640px" }}
|
|
534
|
+
buttonPrev={renderPrevButton}
|
|
535
|
+
buttonNext={renderNextButton}
|
|
536
|
+
stepPrev={SCROLL_STEP}
|
|
537
|
+
stepNext={SCROLL_STEP}
|
|
538
|
+
>
|
|
539
|
+
<StepperExtended size={EComponentSize.MD} selectedStepId={selectedStepId} onSelectStep={setSelectedStepId}>
|
|
540
|
+
{/* Пройденный шаг: выбран не он и isInActiveStep не выставлен. */}
|
|
541
|
+
<StepperExtended.Step id="passed" type={EStepperStepType.NEUTRAL}>
|
|
542
|
+
Passed
|
|
543
|
+
</StepperExtended.Step>
|
|
544
|
+
{/* Текущий шаг: его id передан в selectedStepId. */}
|
|
545
|
+
<StepperExtended.Step id="selected" type={EStepperStepType.NEUTRAL}>
|
|
546
|
+
Selected
|
|
547
|
+
</StepperExtended.Step>
|
|
548
|
+
{/* Недоступный шаг: клики и фокус с клавиатуры заблокированы. */}
|
|
549
|
+
<StepperExtended.Step id="disabled" type={EStepperStepType.NEUTRAL} disabled>
|
|
550
|
+
Disabled
|
|
551
|
+
</StepperExtended.Step>
|
|
552
|
+
{/* Ещё не пройденный шаг. */}
|
|
553
|
+
<StepperExtended.Step id="not-passed" type={EStepperStepType.NEUTRAL} isInActiveStep>
|
|
554
|
+
Not passed
|
|
555
|
+
</StepperExtended.Step>
|
|
556
|
+
</StepperExtended>
|
|
557
|
+
</CarouselExtended>
|
|
558
|
+
);
|
|
559
|
+
};
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
### WithIcons
|
|
563
|
+
|
|
564
|
+
`stories/Stepper/examples/StepperExtended/WithIcons.tsx`
|
|
565
|
+
|
|
566
|
+
```tsx
|
|
567
|
+
import React, { useState } from "react";
|
|
568
|
+
import { CaretleftStrokeSrvIcon24, CaretrightStrokeSrvIcon24 } from "@sberbusiness/icons-next";
|
|
569
|
+
import {
|
|
570
|
+
ButtonIcon,
|
|
571
|
+
CarouselExtended,
|
|
572
|
+
ICarouselExtendedButtonProvideProps,
|
|
573
|
+
StepperExtended,
|
|
574
|
+
StepperStepIcon,
|
|
575
|
+
EComponentSize,
|
|
576
|
+
EStepperStepIconType,
|
|
577
|
+
EStepperStepType,
|
|
578
|
+
} from "@sberbusiness/triplex-next";
|
|
579
|
+
|
|
580
|
+
const STEPS = [
|
|
581
|
+
{ id: "filled", label: "Filled", iconType: EStepperStepIconType.FILLED },
|
|
582
|
+
{ id: "success", label: "Success", iconType: EStepperStepIconType.SUCCESS },
|
|
583
|
+
{ id: "wait", label: "Wait", iconType: EStepperStepIconType.WAIT },
|
|
584
|
+
{ id: "warning", label: "Warning", iconType: EStepperStepIconType.WARNING },
|
|
585
|
+
{ id: "error", label: "Error", iconType: EStepperStepIconType.ERROR },
|
|
586
|
+
];
|
|
587
|
+
|
|
588
|
+
/** Величина прокрутки за один клик по кнопке. */
|
|
589
|
+
const SCROLL_STEP = 200;
|
|
590
|
+
|
|
591
|
+
/** Пока прокрутка не нужна, компонент передаёт hidden: кнопка не рендерится. */
|
|
592
|
+
const renderPrevButton = ({ hidden, ...buttonProps }: ICarouselExtendedButtonProvideProps) =>
|
|
593
|
+
hidden ? null : (
|
|
594
|
+
<ButtonIcon aria-label="Прокрутить назад" {...buttonProps}>
|
|
595
|
+
<CaretleftStrokeSrvIcon24 paletteIndex={5} />
|
|
596
|
+
</ButtonIcon>
|
|
597
|
+
);
|
|
598
|
+
|
|
599
|
+
const renderNextButton = ({ hidden, ...buttonProps }: ICarouselExtendedButtonProvideProps) =>
|
|
600
|
+
hidden ? null : (
|
|
601
|
+
<ButtonIcon aria-label="Прокрутить вперёд" {...buttonProps}>
|
|
602
|
+
<CaretrightStrokeSrvIcon24 paletteIndex={5} />
|
|
603
|
+
</ButtonIcon>
|
|
604
|
+
);
|
|
605
|
+
|
|
606
|
+
export const WithIcons = () => {
|
|
607
|
+
const [selectedStepId, setSelectedStepId] = useState("filled");
|
|
608
|
+
|
|
609
|
+
return (
|
|
610
|
+
<CarouselExtended
|
|
611
|
+
style={{ display: "flex", alignItems: "center", maxWidth: "640px" }}
|
|
612
|
+
buttonPrev={renderPrevButton}
|
|
613
|
+
buttonNext={renderNextButton}
|
|
614
|
+
stepPrev={SCROLL_STEP}
|
|
615
|
+
stepNext={SCROLL_STEP}
|
|
616
|
+
>
|
|
617
|
+
<StepperExtended size={EComponentSize.MD} selectedStepId={selectedStepId} onSelectStep={setSelectedStepId}>
|
|
618
|
+
{STEPS.map(({ id, label, iconType }) => (
|
|
619
|
+
<StepperExtended.Step
|
|
620
|
+
key={id}
|
|
621
|
+
id={id}
|
|
622
|
+
type={EStepperStepType.NEUTRAL}
|
|
623
|
+
icon={<StepperStepIcon type={iconType} />}
|
|
624
|
+
>
|
|
625
|
+
{label}
|
|
626
|
+
</StepperExtended.Step>
|
|
627
|
+
))}
|
|
628
|
+
</StepperExtended>
|
|
629
|
+
</CarouselExtended>
|
|
630
|
+
);
|
|
631
|
+
};
|
|
632
|
+
```
|
|
633
|
+
|