@sberbusiness/triplex-next-mcp-server 0.24.0-beta2 → 1.40.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 (73) hide show
  1. package/README.md +10 -0
  2. package/bundle/components/AlertContext.md +268 -0
  3. package/bundle/components/BodyPage.md +186 -0
  4. package/bundle/components/Button.md +93 -85
  5. package/bundle/components/ButtonDropdown.md +36 -70
  6. package/bundle/components/ButtonDropdownExtended.md +422 -0
  7. package/bundle/components/ButtonIcon.md +41 -48
  8. package/bundle/components/Caption.md +291 -0
  9. package/bundle/components/Checkbox.md +43 -122
  10. package/bundle/components/CheckboxXGroup.md +109 -46
  11. package/bundle/components/CheckboxYGroup.md +77 -49
  12. package/bundle/components/CodeText.md +197 -0
  13. package/bundle/components/Col.md +311 -162
  14. package/bundle/components/CollapsibleTree.md +584 -0
  15. package/bundle/components/CollapsibleTreeExtended.md +422 -0
  16. package/bundle/components/Dropdown.md +748 -346
  17. package/bundle/components/EmptyView.md +14 -15
  18. package/bundle/components/FooterPage.md +203 -0
  19. package/bundle/components/Gap.md +115 -57
  20. package/bundle/components/HeaderPage.md +226 -0
  21. package/bundle/components/HelpBox.md +45 -84
  22. package/bundle/components/ImageGallery.md +423 -0
  23. package/bundle/components/ImageGalleryExtended.md +606 -0
  24. package/bundle/components/LightBox.md +2252 -233
  25. package/bundle/components/List.md +216 -183
  26. package/bundle/components/ListActionItem.md +157 -0
  27. package/bundle/components/ListItem.md +276 -0
  28. package/bundle/components/ListItemControlsButton.md +103 -0
  29. package/bundle/components/ListItemControlsButtonDropdown.md +107 -0
  30. package/bundle/components/ListItemSelectable.md +99 -0
  31. package/bundle/components/ListItemTable.md +390 -0
  32. package/bundle/components/ListMaster.md +876 -156
  33. package/bundle/components/ListMasterFooter.md +80 -0
  34. package/bundle/components/ListMasterHeader.md +86 -0
  35. package/bundle/components/ListSortable.md +153 -0
  36. package/bundle/components/ListSortableItem.md +175 -0
  37. package/bundle/components/ListTableItem.md +391 -0
  38. package/bundle/components/ModalWindow.md +427 -237
  39. package/bundle/components/MonthYearField.md +145 -109
  40. package/bundle/components/Notification.md +625 -155
  41. package/bundle/components/Overlay.md +271 -170
  42. package/bundle/components/Page.md +284 -186
  43. package/bundle/components/Pagination.md +206 -229
  44. package/bundle/components/Portal.md +131 -67
  45. package/bundle/components/Row.md +171 -69
  46. package/bundle/components/Text.md +320 -0
  47. package/bundle/components/TextField.md +364 -97
  48. package/bundle/components/Title.md +296 -0
  49. package/bundle/guides/codestyle.md +38 -11
  50. package/bundle/guides/commits.md +119 -26
  51. package/bundle/guides/context.md +34 -30
  52. package/bundle/guides/stories.md +110 -40
  53. package/bundle/guides/template.md +3 -7
  54. package/bundle/guides/tests.md +48 -2
  55. package/bundle/manifest.json +275 -30
  56. package/bundle/release-notes/1.26.0.mdx +33 -2
  57. package/bundle/release-notes/1.27.0.mdx +43 -0
  58. package/bundle/release-notes/1.28.0.mdx +25 -0
  59. package/bundle/release-notes/1.29.0.mdx +47 -0
  60. package/bundle/release-notes/1.30.0.mdx +56 -0
  61. package/bundle/release-notes/1.31.0.mdx +52 -0
  62. package/bundle/release-notes/1.32.0.mdx +35 -0
  63. package/bundle/release-notes/1.33.0.mdx +61 -0
  64. package/bundle/release-notes/1.34.0.mdx +35 -0
  65. package/bundle/release-notes/1.35.0.mdx +21 -0
  66. package/bundle/release-notes/1.35.1.mdx +11 -0
  67. package/bundle/release-notes/1.36.0.mdx +21 -0
  68. package/bundle/release-notes/1.37.0.mdx +71 -0
  69. package/bundle/release-notes/1.38.0.mdx +36 -0
  70. package/bundle/release-notes/1.39.0.mdx +66 -0
  71. package/bundle/release-notes/1.40.0.mdx +27 -0
  72. package/bundle/release-notes/1.41.0.mdx +7 -0
  73. package/package.json +1 -1
@@ -1,10 +1,23 @@
1
1
  ---
2
2
  component: Pagination
3
3
  category: Navigation
4
- figma-node: ""
5
- figma-file: ""
6
- related: [SelectField, ButtonIcon, ButtonBase, Typography]
7
- tokens: []
4
+ related:
5
+ - PaginationExtended
6
+ - PaginationNavigation
7
+ - PaginationNavigationButton
8
+ - PaginationNavigationExtended
9
+ - PaginationNavigationExtendedItem
10
+ - PaginationPageButton
11
+ - PaginationPageEllipsis
12
+ - PaginationSelect
13
+ - SelectField
14
+ - ButtonIcon
15
+ - ButtonBase
16
+ tokens:
17
+ - --triplex-next-Pagination-PageButton_Background_Hover
18
+ - --triplex-next-Pagination-PageButton_Background_Active
19
+ - --triplex-next-Pagination-PageButton_Background_Selected
20
+ - --triplex-next-Pagination-PageButton_BorderColor_Focus
8
21
  stories: stories/Pagination/Pagination.stories.tsx
9
22
  version: "1.0"
10
23
  ---
@@ -13,286 +26,250 @@ version: "1.0"
13
26
 
14
27
  ## Назначение
15
28
 
16
- Готовая навигация по страницам с двумя композитными слотами:
17
- **`PaginationSelect`** (выбор количества элементов на странице) +
18
- **`PaginationNavigation`** (стрелки prev/next и кнопки страниц с
19
- ellipsis'ами). Сам `Pagination` — лишь сшивка через
20
- `PaginationExtended` (контейнер `<nav>`), управление условным
21
- рендером и проксирование props'ов.
29
+ Составной компонент пагинации: навигация по страницам (кнопки «Назад»/«Вперёд», номера страниц, многоточия) и опциональный выбор количества элементов на странице. `Pagination` — готовая точка входа, которая собирает `PaginationSelect` и `PaginationNavigation` внутри контейнера `PaginationExtended`.
22
30
 
23
- `PaginationExtended` + примитивы (`PaginationNavigationExtended` /
24
- `Item` / `PaginationPageButton` / `PaginationPageEllipsis` /
25
- `PaginationNavigationButton`) экспортируются отдельно — для **кастомной
26
- сборки** пагинации, когда стандартная не подходит.
31
+ Используй когда: нужно дать пользователю переход по страницам списка/таблицы, при необходимости — с выбором размера страницы.
27
32
 
28
- Используй когда: типичная пагинация над таблицей/списком. Для
29
- нестандартной — собирай из `PaginationExtended` + примитивов.
30
-
31
- ---
32
-
33
- ## Файловая структура
34
-
35
- ```text
36
- src/components/Pagination/
37
- ├── Pagination.tsx # forwardRef; склейка Select + Navigation
38
- ├── components/
39
- │ ├── PaginationExtended.tsx # forwardRef; <nav> wrapper
40
- │ ├── PaginationSelect.tsx # forwardRef; SelectField (size SM)
41
- │ ├── PaginationNavigation.tsx # forwardRef; prev/pages/next + ellipsis
42
- │ ├── PaginationNavigationExtended.tsx # forwardRef; <ul>
43
- │ ├── PaginationNavigationExtendedItem.tsx # forwardRef; <li>
44
- │ ├── PaginationNavigationButton.tsx # forwardRef; ButtonIcon SQUIRCLE + caret-icon
45
- │ ├── PaginationPageButton.tsx # forwardRef; ButtonBase + Text B3
46
- │ └── PaginationPageEllipsis.tsx # forwardRef; Text B3 "..."
47
- ├── utils/paginationUtils.tsx # createPagesArray + generateRange + PAGINATION_ELLIPSIS_VALUE
48
- ├── enums.ts # EPaginationNavigationIconDirection (BACK | NEXT)
49
- ├── index.ts # Barrel: всё
50
- ├── styles/*.module.less
51
- └── __tests__/
52
- ```
53
-
54
- ---
55
-
56
- ## Compound-структура
57
-
58
- ```tsx
59
- <Pagination
60
- paginationSelectProps={{
61
- paginationLabel: "На странице",
62
- value: pageSize,
63
- options: [
64
- { value: 10, label: "10" },
65
- { value: 25, label: "25" },
66
- ],
67
- onChange: setPageSize,
68
- }}
69
- paginationNavigationProps={{
70
- currentPage,
71
- totalPages,
72
- onCurrentPageChange: setCurrentPage,
73
- boundaryCount: 1,
74
- siblingCount: 1,
75
- }}
76
- />
77
- ```
78
-
79
- Кастомная сборка:
80
-
81
- ```tsx
82
- <PaginationExtended>
83
- <PaginationNavigationExtended>
84
- <PaginationNavigationExtendedItem>
85
- <PaginationNavigationButton direction={EPaginationNavigationIconDirection.BACK} />
86
- </PaginationNavigationExtendedItem>
87
- <PaginationNavigationExtendedItem>
88
- <PaginationPageButton isCurrent>1</PaginationPageButton>
89
- </PaginationNavigationExtendedItem>
90
- ...
91
- </PaginationNavigationExtended>
92
- </PaginationExtended>
93
- ```
33
+ Не используй когда: данных немного и помещаются на один экран (при `totalPages <= 1` навигация не рендерится); нужна бесконечная прокрутка вместо постраничной.
94
34
 
95
35
  ---
96
36
 
97
37
  ## Варианты и props
98
38
 
99
- ### Pagination — `IPaginationProps extends IPaginationExtendedProps`
100
-
101
- | Prop | Тип | Описание |
102
- |---|---|---|
103
- | `paginationSelectProps?` | `IPaginationSelectProps` | Если **не передан** — Select не рендерится. |
104
- | `paginationNavigationProps` | `IPaginationNavigationProps` | Обязателен. Если `totalPages <= 1` — Navigation не рендерится. |
105
- | `...IPaginationExtendedProps` | `HTMLAttributes<HTMLElement>` | На `<nav>`. |
39
+ `Pagination` — управляемый компонент: текущая страница и размер страницы хранятся в стейте потребителя и передаются через колбэки. Компонент не хранит состояние страницы сам.
106
40
 
107
- ### PaginationSelect — `IPaginationSelectProps`
108
-
109
- ```ts
110
- extends Omit<ISelectFieldProps, "size" | "value">
111
- extends Required<Pick<ISelectFieldProps, "value">>
112
- ```
41
+ ### `Pagination` (точка входа)
113
42
 
114
- | Prop | Тип | Описание |
115
- |---|---|---|
116
- | `paginationLabel` | `ReactNode` | Лейбл слева от селекта (`<Text size=B3 id={instanceId}>`). |
117
- | `value` | `ISelectFieldProps["value"]` | Обязательно. |
118
- | `options`, `onChange`, ... | от SelectField | — |
119
-
120
- - **`size` захардкожен `EComponentSize.SM`**.
121
- - **`mobileTitle = paginationLabel`** — тот же текст для мобильного header'а.
122
- - **`targetProps.fieldLabel = ""`** — лейбл внутри SelectField очищается (label рисуется отдельно слева).
123
- - **`aria-labelledby={instanceId}`** + `Text id={instanceId}` — связь label ↔ control.
124
- - `instanceId = "Pagination-{lodash uniqueId()}"` — **SSR-небезопасно** (два рендера дадут разные id, гидрация может ругаться).
43
+ | Prop | Тип | Обяз. | Описание |
44
+ |---|---|---|---|
45
+ | `paginationNavigationProps` | `IPaginationNavigationProps` | да | Настройки навигации по страницам. Навигация рендерится только при `totalPages > 1`. |
46
+ | `paginationSelectProps` | `IPaginationSelectProps` | нет | Настройки селекта размера страницы. Если не передан — селект не отображается. |
47
+ | `...rest` | `IPaginationExtendedProps` | — | Прокидывается в корневой `<nav>` (className, aria-атрибуты и т.д.). |
125
48
 
126
- ### PaginationNavigation — `IPaginationNavigationProps extends HTMLAttributes<HTMLUListElement>`
49
+ ### `PaginationNavigation` props (через `paginationNavigationProps`)
127
50
 
128
- | Prop | Тип | Default | Описание |
51
+ | Prop | Тип | По умолчанию | Описание |
129
52
  |---|---|---|---|
130
- | `currentPage` | `number` | — | Контролируемая текущая страница (1-based). |
131
- | `totalPages` | `number` | — | Всего страниц. |
132
- | `onCurrentPageChange` | `(page: number) => void` | — | Сеттер. |
53
+ | `currentPage` | `number` | — | Номер текущей страницы (нумерация с 1). |
54
+ | `totalPages` | `number` | — | Общее число страниц. |
55
+ | `onCurrentPageChange` | `(page: number) => void` | — | Колбэк смены страницы. Вызывается с целевым номером. |
133
56
  | `boundaryCount` | `number` | `0` | Сколько страниц всегда показывать в начале и в конце. |
134
- | `siblingCount` | `number` | `0` | Сколько соседей слева/справа от текущей. |
135
- | `buttonPrevProps?` | `Omit<IPaginationNavigationButtonProps, "direction" \| "children">` | — | Доп. props на кнопку «назад». |
136
- | `buttonNextProps?` | `Omit<...>` | — | Доп. props на «вперёд». |
137
-
138
- - **prev disabled при `currentPage === 1`** (или `buttonPrevProps?.disabled`).
139
- - **next disabled при `currentPage === totalPages`** (или `buttonNextProps?.disabled`).
140
- - Рендерит prev → массив страниц от `createPagesArray(...)` → next.
141
-
142
- ### PaginationNavigationButton — `IPaginationNavigationButtonProps`
57
+ | `siblingCount` | `number` | `0` | Сколько соседних страниц показывать вокруг текущей. |
58
+ | `buttonPrevProps` / `buttonNextProps` | `Omit<IPaginationNavigationButtonProps, "direction" \| "children">` | — | Доп. настройки кнопок навигации. |
143
59
 
144
- ```ts
145
- extends Omit<IButtonIconProps, "shape" | "active" | "children">
146
- children?: never
147
- direction: EPaginationNavigationIconDirection
148
- ```
149
-
150
- - Иконка: `CaretleftStrokeSrvIcon24 paletteIndex={5}`. Для `NEXT` — добавляется `styles.directionIconNext` (поворот через CSS).
151
- - `shape={EButtonIconShape.SQUIRCLE}` — захардкожен.
152
- - `children?: never` — фиксированная иконка.
153
-
154
- ### PaginationPageButton — `TPaginationPageButtonProps`
155
-
156
- | Prop | Тип | Описание |
157
- |---|---|---|
158
- | `isCurrent?` | `boolean` | Подсветка текущей. **`aria-live="polite"`** при `isCurrent` — screen reader озвучит при смене. |
159
- | `children` | `ReactNode` | Номер страницы. |
160
- | `onClick` | `() => void` | Клик. |
60
+ Логика расстановки видимых страниц и многоточий — в `utils/paginationUtils.tsx` (`PaginationUtils.createPagesArray`). При больших `totalPages` и нулевых `boundaryCount`/`siblingCount` отображается минимальный набор; увеличение этих значений раскрывает больше номеров и добавляет многоточия по краям. Места многоточий помечаются sentinel-значением `PAGINATION_ELLIPSIS_VALUE` (`-1`) в массиве страниц.
161
61
 
162
- - Содержимое — `<Text size=B3>`.
62
+ ### `PaginationSelect` props (через `paginationSelectProps`)
163
63
 
164
- ### PaginationPageEllipsis — `IPaginationPageEllipsis extends HTMLAttributes<HTMLSpanElement>`
64
+ Расширяет `ISelectFieldProps` (без `size`, с обязательным `value`) и добавляет `paginationLabel: React.ReactNode` — текст лейбла перед селектом. Размер селекта зафиксирован как `EComponentSize.SM`. `value`, `options`, `onChange` — управляются потребителем.
165
65
 
166
- - `<Text size=B3>...children...</Text>`. Контракт: `children = "..."` — чисто визуальный плейсхолдер.
66
+ ### Subкомпоненты для кастомной компоновки
167
67
 
168
- ### PaginationExtended — `IPaginationExtendedProps extends HTMLAttributes<HTMLElement>`
169
-
170
- - `<nav>` контейнер. `data-tx={pkg.version}`.
171
-
172
- ### PaginationNavigationExtended/Item
173
-
174
- - `<ul>` / `<li>` — семантический список для пагинации.
175
-
176
- ### enums.ts
177
-
178
- - `EPaginationNavigationIconDirection.BACK | NEXT` (numeric enum: 0/1).
68
+ Для нестандартной раскладки используется `PaginationExtended` напрямую с вложенными `PaginationNavigation` и `PaginationSelect` (см. story `Extended`). Низкоуровневые части (`PaginationNavigationExtended`, `PaginationNavigationExtendedItem`, `PaginationPageButton`, `PaginationPageEllipsis`, `PaginationNavigationButton`) экспортируются для построения полностью кастомной навигации, но обычно используются неявно через `PaginationNavigation`.
179
69
 
180
70
  ---
181
71
 
182
- ## Ключевые особенности реализации
72
+ ## Дизайн-токены
183
73
 
184
- ### Условный рендер слотов
74
+ Собственные токены использует только `PaginationPageButton`:
185
75
 
186
- ```tsx
187
- {paginationSelectProps && <PaginationSelect {...paginationSelectProps} />}
188
- {paginationNavigationProps.totalPages > 1 && <PaginationNavigation {...paginationNavigationProps} />}
76
+ ```text
77
+ --triplex-next-Pagination-PageButton_Background_Hover
78
+ --triplex-next-Pagination-PageButton_Background_Active
79
+ --triplex-next-Pagination-PageButton_Background_Selected
80
+ --triplex-next-Pagination-PageButton_BorderColor_Focus
189
81
  ```
190
82
 
191
- - Select — опциональный.
192
- - Navigation — рендерится только при `totalPages > 1` (на 1 странице — нечего листать).
193
-
194
- ### `PaginationUtils.createPagesArray`
83
+ Остальные части наследуют визуал от переиспользуемых компонентов: кнопки навигации — от `ButtonIcon`, кнопка-страница — от `ButtonBase`, селект — от `SelectField`, текст — от `Typography` (`Text`).
195
84
 
196
- ```ts
197
- // startPages | (ellipsis | next page) | siblings around current | (ellipsis | prev page) | endPages
198
- ```
199
-
200
- - `boundaryCount` — кол-во **всегда видимых** в начале/конце.
201
- - `siblingCount` — кол-во **соседей** вокруг текущей.
202
- - Если соседи примыкают к boundary — ellipsis заменяется на одну страницу (без «1 ... 2 3 4» — будет «1 2 3 4»).
203
- - Возвращает массив `number[]`, где **`PAGINATION_ELLIPSIS_VALUE = -1`** — sentinel для ellipsis.
204
- - Использует `lodash-es/range`.
85
+ ---
205
86
 
206
- ### Sentinel `-1` для ellipsis
87
+ ## Инварианты
207
88
 
208
- ```ts
209
- case PAGINATION_ELLIPSIS_VALUE: return <PaginationPageEllipsis>...</PaginationPageEllipsis>;
210
- default: return <PaginationPageButton>{page}</PaginationPageButton>;
211
- ```
89
+ - `forwardRef` на всех компонентах семейства — не убирать. Refs: `Pagination` → `HTMLSpanElement` (фактически прокидывается в корневой `<nav>` через `PaginationExtended`, ref-тип которого `HTMLElement`), `PaginationNavigation`/`PaginationNavigationExtended` → `HTMLUListElement`, `PaginationNavigationExtendedItem` → `HTMLLIElement`, `PaginationSelect` → `HTMLDivElement`, кнопки → `HTMLButtonElement`, ellipsis → `HTMLSpanElement`.
90
+ - Публичный API не менять: имена и обязательность props (`paginationNavigationProps` — обязателен, `paginationSelectProps` — опционален), enum `EPaginationNavigationIconDirection` (`BACK`/`NEXT`), barrel-экспорты из `index.ts`.
91
+ - Корневой DOM-элемент `Pagination`/`PaginationExtended` — `<nav>`; навигация по страницам — семантический список `<ul>/<li>`. Не менять без обсуждения: семантика участвует в accessibility-контракте.
92
+ - Навигация рендерится только при `totalPages > 1` — поведение публичное, на него опираются потребители.
93
+ - Логику `PaginationUtils.createPagesArray` / `generatePageRanges` / `generateRange` не менять без перегенерации `__tests__/paginationUtils.test.tsx` — там зафиксированы граничные случаи раскладки.
94
+ - `PAGINATION_ELLIPSIS_VALUE = -1` — sentinel в массиве страниц, на него завязан рендер многоточия.
212
95
 
213
- - Магическое значение `-1` — публично экспортируется как `PAGINATION_ELLIPSIS_VALUE`.
96
+ ---
214
97
 
215
- ### `aria-live="polite"` на текущей кнопке
98
+ ## Accessibility
216
99
 
217
- ```tsx
218
- aria-live={isCurrent ? "polite" : undefined}
219
- ```
100
+ - Корень — `<nav>`, навигация — список `<ul>/<li>`, что даёт ассистивным технологиям корректную семантику пагинации.
101
+ - Кнопки «Назад»/«Вперёд» автоматически получают `disabled` на первой/последней странице соответственно.
102
+ - Текущая страница (`PaginationPageButton` с `isCurrent`) помечается `aria-live="polite"`, чтобы смена страницы озвучивалась скринридером.
103
+ - `PaginationSelect` связывает лейбл и контрол через `aria-labelledby` (генерируемый `instanceId`), лейбл также используется как `mobileTitle`.
104
+ - Текст кнопок навигации не хардкодится в компоненте — при необходимости потребитель передаёт `aria-label` через `buttonPrevProps`/`buttonNextProps` (библиотека мультиязычная).
220
105
 
221
- - При смене `currentPage` screen reader озвучит новую кнопку.
106
+ ---
222
107
 
223
- ### Иконка NEXT — поворот через CSS
108
+ ## Связанные компоненты
224
109
 
225
- ```tsx
226
- {isDirectionBack ? <CaretleftStrokeSrvIcon24 ... /> : <CaretleftStrokeSrvIcon24 className={styles.directionIconNext} />}
227
- ```
110
+ - `PaginationExtended` — контейнер `<nav>` для кастомной компоновки пагинации.
111
+ - `PaginationNavigation` — блок навигации по страницам (используется внутри `Pagination`, доступен отдельно).
112
+ - `PaginationSelect` — селект размера страницы поверх `SelectField`.
113
+ - `PaginationNavigationExtended` / `PaginationNavigationExtendedItem` — список `<ul>` и его элемент `<li>` для построения кастомной навигации.
114
+ - `PaginationPageButton` — кнопка-страница (поверх `ButtonBase`).
115
+ - `PaginationPageEllipsis` — многоточие, заменяющее группу скрытых страниц.
116
+ - `PaginationNavigationButton` — кнопка «Назад»/«Вперёд» (поверх `ButtonIcon`), направление задаётся `EPaginationNavigationIconDirection`.
228
117
 
229
- - Только одна иконка (`CaretleftStrokeSrvIcon24`); для NEXT — поворот на 180° через `styles.directionIconNext`.
118
+ ---
230
119
 
231
- ### `aria-labelledby` через `uniqueId`
120
+ ## Stories
232
121
 
233
- ```ts
234
- const [instanceId] = useState(() => `Pagination-${uniqueId()}`);
235
- ```
122
+ Основные истории: `stories/Pagination/Pagination.stories.tsx`
123
+ Файлы примеров: `stories/Pagination/examples/Pagination/`
236
124
 
237
- - **SSR-небезопасно**: lodash `uniqueId` глобальный счётчик.
238
- - Решает связь Text-label ↔ SelectField через `aria-labelledby`.
125
+ | Story | Example file | Что демонстрирует |
126
+ |---|---|---|
127
+ | `Playground` | `Playground.tsx` | Интерактивный контроль `currentPage`, `totalPages`, `boundaryCount`, `siblingCount`, `hidePaginationSelect`, `paginationLabel`, `className` |
128
+ | `Default` | `Default.tsx` | Базовая навигация без селекта (50 элементов, размер страницы 10) |
129
+ | `WithSelectField` | `WithSelectField.tsx` | Навигация с селектом размера страницы, `boundaryCount`/`siblingCount = 1` |
130
+ | `Extended` | `Extended.tsx` | Кастомная компоновка через `PaginationExtended` + `PaginationNavigation` + `PaginationSelect` |
131
+ | `VisualTests` | — | Скриншот-регрессия: короткая навигация, многоточия слева/справа/с обеих сторон, disabled-крайние кнопки, вариант с селектом |
239
132
 
240
133
  ---
241
134
 
242
- ## Инварианты
135
+ ## История изменений
243
136
 
244
- - **`Pagination.totalPages > 1`** — Navigation рендерится; иначе скрыт.
245
- - **`paginationNavigationProps`** — обязательный prop (тип, не optional).
246
- - **`paginationSelectProps`** — опционален; отсутствие = нет селекта.
247
- - **`PAGINATION_ELLIPSIS_VALUE = -1`** — публичная константа-sentinel.
248
- - **`PaginationSelect.size = SM`** — захардкожен.
249
- - **`PaginationSelect.targetProps.fieldLabel = ""`** — внутренний label очищается.
250
- - **`PaginationNavigationButton.shape = SQUIRCLE`**, иконка `CaretleftStrokeSrvIcon24` — фиксированы; `children: never`.
251
- - **`PaginationPageButton.aria-live="polite"`** при `isCurrent` — публичный a11y-контракт.
252
- - **`uniqueId()`** в SelectId — SSR-небезопасно.
253
- - **`<nav>` корень PaginationExtended** + `<ul>`/`<li>` для Navigation — семантическая структура.
254
- - **`createPagesArray` зависит от lodash-es `range`**.
255
- - **`EPaginationNavigationIconDirection`** — numeric enum (0/1), не string.
256
- - **ForwardRef** на всех уровнях.
137
+ | Дата | Изменение |
138
+ |---|---|
139
+ | 2026-06-22 | Создан документ |
257
140
 
258
141
  ---
259
142
 
260
- ## Accessibility
143
+ ## Примеры использования
261
144
 
262
- - `<nav>` корень + `<ul>`/`<li>` элементы — корректная семантика навигации/списка.
263
- - `aria-live="polite"` на текущей странице — озвучивание при смене.
264
- - `aria-labelledby` связывает label PaginationSelect с самим SelectField.
265
- - **Нет `aria-label="Pagination"`** на `<nav>` — потребитель должен передать через `...rest` (иначе screen reader скажет просто «navigation»).
266
- - **Иконки prev/next без `aria-label`** — `ButtonIcon` сам по себе не озвучивает направление. Потребитель должен передать `buttonPrevProps={{ "aria-label": "Предыдущая" }}` и т.п.
267
- - `disabled` корректно через `<button disabled>` — клавиатура и SR обработают.
145
+ ### Default
268
146
 
269
- ---
147
+ `stories/Pagination/examples/Pagination/Default.tsx`
270
148
 
271
- ## Дизайн-токены
149
+ ```tsx
150
+ import React, { useState } from "react";
151
+ import { Pagination } from "@sberbusiness/triplex-next";
272
152
 
273
- Нет собственных — наследуются от `Button`, `Text`, `SelectField`.
153
+ export const Default = () => {
154
+ const totalItems = 50;
155
+ const pageSize = 10;
156
+ const [page, setPage] = useState(1);
274
157
 
275
- ---
158
+ const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
276
159
 
277
- ## Связанные компоненты
160
+ return <Pagination paginationNavigationProps={{ currentPage: page, totalPages, onCurrentPageChange: setPage }} />;
161
+ };
162
+ ```
278
163
 
279
- - `SelectField` — нижележащий control в PaginationSelect.
280
- - `ButtonIcon`, `ButtonBase` — кнопки.
281
- - `Text` (Typography) — текст.
282
- - `CaretleftStrokeSrvIcon24` — единственная иконка стрелки.
283
- - `lodash-es/range`, `lodash-es/uniqueId`.
164
+ ### WithSelectField
284
165
 
285
- ---
166
+ `stories/Pagination/examples/Pagination/WithSelectField.tsx`
286
167
 
287
- ## Stories
168
+ ```tsx
169
+ import React, { useState } from "react";
170
+ import { Pagination, ISelectExtendedFieldDefaultOption } from "@sberbusiness/triplex-next";
171
+
172
+ export const WithSelectField = () => {
173
+ const [page, setPage] = useState(7);
174
+ const [pageSize, setPageSize] = useState(10);
175
+ const totalItems = 300;
176
+ const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
177
+
178
+ const handlePageSizeChange = (option: ISelectExtendedFieldDefaultOption) => {
179
+ setPageSize(Number(option.value));
180
+ // Смена размера страницы меняет totalPages — возвращаемся на первую, чтобы не оказаться вне диапазона.
181
+ setPage(1);
182
+ };
183
+
184
+ const options: ISelectExtendedFieldDefaultOption[] = [
185
+ { id: "0", value: "10", label: "10" },
186
+ { id: "1", value: "20", label: "20" },
187
+ { id: "2", value: "50", label: "50" },
188
+ { id: "3", value: "100", label: "100" },
189
+ ];
190
+
191
+ const selectedOption = options.find((option) => option.value === String(pageSize));
192
+
193
+ return (
194
+ <Pagination
195
+ paginationNavigationProps={{
196
+ currentPage: page,
197
+ totalPages,
198
+ boundaryCount: 1,
199
+ siblingCount: 1,
200
+ onCurrentPageChange: setPage,
201
+ }}
202
+ paginationSelectProps={{
203
+ paginationLabel: "Показать на странице:",
204
+ options,
205
+ value: selectedOption || options[0],
206
+ onChange: handlePageSizeChange,
207
+ targetProps: {
208
+ fieldLabel: "",
209
+ },
210
+ }}
211
+ />
212
+ );
213
+ };
214
+ ```
288
215
 
289
- `stories/Pagination/Pagination.stories.tsx`
290
- Примеры: `stories/Pagination/examples/`
216
+ ### Extended
291
217
 
292
- ---
218
+ `stories/Pagination/examples/Pagination/Extended.tsx`
293
219
 
294
- ## История изменений
220
+ ```tsx
221
+ import React, { useState } from "react";
222
+ import {
223
+ PaginationExtended,
224
+ PaginationNavigation,
225
+ PaginationSelect,
226
+ ISelectExtendedFieldDefaultOption,
227
+ } from "@sberbusiness/triplex-next";
228
+
229
+ export const Extended = () => {
230
+ const [page, setPage] = useState(1);
231
+ const [pageSize, setPageSize] = useState(10);
232
+ const totalItems = 300;
233
+ const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
234
+
235
+ const handlePageSizeChange = (option: ISelectExtendedFieldDefaultOption) => {
236
+ setPageSize(Number(option.value));
237
+ // Смена размера страницы меняет totalPages — возвращаемся на первую, чтобы не оказаться вне диапазона.
238
+ setPage(1);
239
+ };
240
+
241
+ const options: ISelectExtendedFieldDefaultOption[] = [
242
+ { id: "0", value: "10", label: "10" },
243
+ { id: "1", value: "20", label: "20" },
244
+ { id: "2", value: "50", label: "50" },
245
+ { id: "3", value: "100", label: "100" },
246
+ { id: "4", value: "300", label: "300" },
247
+ ];
248
+
249
+ const selectedOption = options.find((option) => option.value === String(pageSize));
250
+
251
+ return (
252
+ <PaginationExtended>
253
+ {totalPages > 1 && (
254
+ <PaginationNavigation
255
+ currentPage={page}
256
+ totalPages={totalPages}
257
+ boundaryCount={1}
258
+ siblingCount={1}
259
+ onCurrentPageChange={setPage}
260
+ />
261
+ )}
262
+ <PaginationSelect
263
+ paginationLabel="Показать на странице:"
264
+ value={selectedOption || options[0]}
265
+ options={options}
266
+ onChange={handlePageSizeChange}
267
+ targetProps={{
268
+ fieldLabel: "",
269
+ }}
270
+ />
271
+ </PaginationExtended>
272
+ );
273
+ };
274
+ ```
295
275
 
296
- | Дата | Изменение |
297
- |---|---|
298
- | 2026-04-18 | Создан документ |