@sberbusiness/triplex-next-mcp-server 1.41.0-beta → 1.43.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 (41) hide show
  1. package/bundle/components/AlertProcess.md +460 -0
  2. package/bundle/components/Amount.md +145 -169
  3. package/bundle/components/Badge.md +155 -219
  4. package/bundle/components/Body.md +108 -116
  5. package/bundle/components/Button.md +1 -0
  6. package/bundle/components/CarouselExtended.md +355 -194
  7. package/bundle/components/Checkbox.md +7 -1
  8. package/bundle/components/CheckboxTreeExtended.md +149 -248
  9. package/bundle/components/CheckboxXGroup.md +2 -0
  10. package/bundle/components/CheckboxYGroup.md +7 -2
  11. package/bundle/components/ChipGroup.md +195 -126
  12. package/bundle/components/ComposedKeyDownListener.md +323 -0
  13. package/bundle/components/FooterPage.md +2 -1
  14. package/bundle/components/HeaderPage.md +2 -1
  15. package/bundle/components/Island.md +100 -12
  16. package/bundle/components/KeyDownListener.md +11 -72
  17. package/bundle/components/LightBox.md +6 -0
  18. package/bundle/components/LoaderSmall.md +230 -0
  19. package/bundle/components/MaskedField.md +481 -0
  20. package/bundle/components/MediaWidth.md +252 -108
  21. package/bundle/components/MobileView.md +192 -68
  22. package/bundle/components/ModalWindow.md +3 -1
  23. package/bundle/components/Notification.md +21 -3
  24. package/bundle/components/Page.md +3 -1
  25. package/bundle/components/Pagination.md +20 -0
  26. package/bundle/components/SelectExtendedField.md +691 -236
  27. package/bundle/components/SliderExtended.md +358 -222
  28. package/bundle/components/TabsExtended.md +380 -194
  29. package/bundle/components/UnorderedList.md +254 -0
  30. package/bundle/components/UnorderedListExtended.md +255 -0
  31. package/bundle/components/WindowResizeListener.md +249 -0
  32. package/bundle/guides/commits.md +66 -3
  33. package/bundle/guides/context.md +26 -0
  34. package/bundle/guides/stories.md +3 -1
  35. package/bundle/guides/template.md +1 -1
  36. package/bundle/manifest.json +64 -21
  37. package/bundle/release-notes/1.41.1.mdx +18 -0
  38. package/bundle/release-notes/1.42.0.mdx +81 -0
  39. package/bundle/release-notes/1.43.0.mdx +94 -0
  40. package/bundle/release-notes/1.44.0.mdx +7 -0
  41. package/package.json +1 -1
@@ -1,11 +1,9 @@
1
1
  ---
2
2
  component: MobileView
3
- category: Utilities
4
- figma-node: ""
5
- figma-file: ""
6
- related: [MediaWidth]
3
+ category: MobileView
4
+ related: [MediaWidth, MediaMaxWidth, useMatchMedia, useMobileView]
7
5
  tokens: []
8
- stories: ""
6
+ stories: stories/MobileView/MobileView.stories.tsx
9
7
  version: "1.0"
10
8
  ---
11
9
 
@@ -13,108 +11,234 @@ version: "1.0"
13
11
 
14
12
  ## Назначение
15
13
 
16
- Удобная обёртка над `MediaWidth maxWidth={SM_MAX}` — рендерит `children`
17
- на мобиле (< 768px), иначе `fallback`. Фактически **именованный пресет**
18
- для частого use-case'а mobile-vs-desktop.
14
+ Сервисный headless-компонент адаптивности. Рендерит `children`, когда ширина окна
15
+ браузера соответствует мобильному устройству (`max-width: 767px`), и `fallback` —
16
+ во всех остальных случаях. Собственной разметки не добавляет: в DOM попадает
17
+ ровно тот элемент, который выбран по медиа-запросу.
19
18
 
20
- Используй когда: нужно рендерить разные React-деревья для mobile/desktop.
21
- Для стилей — CSS `@media` напрямую. Для более гибких границ —
22
- `MediaWidth`/`MediaMinWidth`/`MediaMaxWidth`.
19
+ Реализован как сокращение над `MediaWidth` с `maxWidth={EScreenWidth.SM_MAX}` —
20
+ вся логика подписки на медиа-запрос живёт в `MediaMaxWidth` → `useMatchMedia`.
23
21
 
24
- ---
25
-
26
- ## Файловая структура
22
+ Используй когда: на мобильной ширине нужно отрендерить **другое дерево**
23
+ компонентов, а не просто другие стили — мобильный вариант дропдауна вместо
24
+ десктопного, тултип-модалка вместо всплывающей подсказки, список вместо таблицы.
27
25
 
28
- ```text
29
- src/components/MobileView/
30
- ├── MobileView.tsx # FC, 3 строки — обёртка над MediaWidth
31
- └── index.ts # Barrel
32
- ```
33
-
34
- Нет стилей, тестов, stories.
26
+ Не используй когда:
27
+ - Разница между мобильным и десктопом чисто визуальная (отступы, шрифт,
28
+ раскладка) — это дешевле и надёжнее решается медиа-запросом в
29
+ `*.module.less`, без перемонтирования поддерева.
30
+ - Нужен не выбор между двумя готовыми элементами, а булево значение для props
31
+ или условной разметки вокруг — используй хук `useMobileView` (см. ниже).
32
+ - Нужна не мобильная, а произвольная граница ширины — используй `MediaWidth`
33
+ (`minWidth` / `maxWidth`) напрямую.
35
34
 
36
35
  ---
37
36
 
38
37
  ## Варианты и props
39
38
 
40
- ### `IMobileViewProps`
39
+ ### Обязательные props
40
+
41
+ | Prop | Тип | Описание |
42
+ |---|---|---|
43
+ | `children` | `React.ReactElement \| null` | Элемент для мобильной ширины (`<768px`). `null` — на мобильной ширине не рендерится ничего |
44
+ | `fallback` | `React.ReactElement \| null` | Элемент для остальных ширин. Обязателен: prop без значения по умолчанию, для «ничего» передаётся явный `null` |
45
+
46
+ Опциональных props нет. `className`, `...rest` и `ref` компонент не принимает —
47
+ у него нет собственного host-элемента.
48
+
49
+ ### Особенности поведения
50
+
51
+ - Граница — `EScreenWidth.SM_MAX` (`767px`), запрос `(max-width: 767px)`. При
52
+ ширине ровно `767px` рендерится `children`, при `768px` — `fallback`.
53
+ - **Ветки взаимоисключающие.** При пересечении границы одна ветка размонтируется,
54
+ вторая монтируется: локальный state, фокус, значения неконтролируемых полей и
55
+ текущие анимации внутри поддерева теряются. Состояние, которое должно
56
+ переживать смену ширины, храни выше `MobileView` (или передавай его как props
57
+ в обе ветки).
58
+ - Значение медиа-запроса читается синхронно на первом рендере (`useMatchMedia`
59
+ вызывает `window.matchMedia` в инициализаторе `useState`), поэтому «мигания»
60
+ десктопной ветки на мобильном экране нет.
61
+ - Пересчёт при ресайзе идёт по событию `change` у `MediaQueryList`, а не по
62
+ `resize` окна — слушатель снимается при размонтировании.
63
+ - **Компонент не SSR-safe:** `window.matchMedia` вызывается на первом рендере.
64
+ Это поведение унаследовано от `useMatchMedia` и общее для всего семейства
65
+ `MediaWidth`.
66
+
67
+ ### `useMobileView`
68
+
69
+ Хук из того же barrel (`src/components/MobileView/useMobileView.ts`). Возвращает
70
+ `boolean` — результат того же медиа-запроса `(max-width: 767px)`. Нужен, когда
71
+ от ширины зависят props или разметка вокруг, а не выбор между двумя готовыми
72
+ элементами: размер кнопки, `block`-режим, наличие иконки. Так его используют
73
+ `DateFieldTarget`, `MonthYearFieldTarget`, `CheckboxTreeExtended`, `IslandWidget`,
74
+ `IslandAccordionItem`, `Tooltip`.
75
+
76
+ Компонент и хук строят строку запроса независимо (`MediaMaxWidth` — из своего
77
+ prop, хук — из константы `MOBILE_QUERY`), но обе строки собираются из
78
+ `EScreenWidth.SM_MAX` и всегда совпадают. Правя одно, проверь второе.
79
+
80
+ ---
41
81
 
42
- | Prop | Тип | Обязателен | Описание |
43
- |---|---|---|---|
44
- | `children` | `ReactElement \| null` | Да | Рендерится при ширине ≤ SM_MAX (767px). |
45
- | `fallback` | `ReactElement \| null` | Да | Рендерится в остальных случаях (desktop). |
82
+ ## Дизайн-токены
46
83
 
47
- Обе props — обязательные. Следует контракту `MediaWidth`.
84
+ Собственных стилей и CSS-переменных нет — компонент не рендерит разметку.
48
85
 
49
86
  ---
50
87
 
51
- ## Ключевые особенности реализации
88
+ ## Инварианты
52
89
 
53
- ### Брейкпоинт — `EScreenWidth.SM_MAX`
90
+ - **Без `forwardRef` — осознанное исключение** из общего правила библиотеки:
91
+ компонент не рендерит собственный host-элемент, форвардить `ref` некуда.
92
+ Не добавлять и не убирать без отдельного решения — это публичный контракт.
93
+ - **Имена и типы props `children`, `fallback`** и интерфейс `IMobileViewProps`
94
+ (экспортируется из barrel) — публичное API, не менять. `fallback` остаётся
95
+ обязательным: сделать его опциональным можно только осознанно, это меняет
96
+ контракт у потребителей.
97
+ - **Сигнатура `useMobileView(): boolean`** и его barrel-экспорт — публичное API.
98
+ Хук используется внутри библиотеки в шести компонентах.
99
+ - **Граница мобильной ширины — `EScreenWidth.SM_MAX`.** Не хардкодить `767px`
100
+ и не переводить на `MD_MIN` с `min-width`: значение согласовано с сеткой
101
+ дизайн-системы и с LESS-переменными брейкпоинтов.
102
+ - **Делегирование в `MediaWidth`** — не инлайнить `useMatchMedia` в
103
+ `MobileView.tsx`: семейство `MediaWidth` остаётся единственным местом с
104
+ логикой подписки на медиа-запросы.
105
+ - Реализация остаётся React 17-совместимой (без `useId`,
106
+ `useSyncExternalStore` и прочих React 18-only API): код синхронизируется
107
+ в `release-0`.
54
108
 
55
- ```tsx
56
- <MediaWidth maxWidth={EScreenWidth.SM_MAX} fallback={fallback}>
57
- {children}
58
- </MediaWidth>
59
- ```
109
+ ---
60
110
 
61
- - `SM_MAX` обычно равен `767px` (проверь в `helpers/breakpoints`).
62
- - **Фиксированный брейкпоинт** — если нужен другой (например, планшеты), используй `MediaWidth` с явным `maxWidth`, а не оборачивай MobileView.
111
+ ## Accessibility
63
112
 
64
- ### `children` на mobile, `fallback` на desktop
113
+ - Собственной ARIA-семантики нет — компонент прозрачен для accessibility-дерева.
114
+ - Невыбранная ветка **не рендерится в DOM**, а не скрывается визуально: скринридер
115
+ и последовательность табуляции видят только актуальный вариант. Дублирования
116
+ контента для ассистивных технологий не возникает, но и «десктопная» разметка
117
+ на мобильном недоступна.
118
+ - Смена ветки при ресайзе удаляет из DOM сфокусированный элемент — фокус
119
+ переходит на `<body>`. Если это критично (открытый оверлей, форма), верни
120
+ фокус явно на стороне потребителя.
121
+ - Медиа-запрос завязан на ширину окна, а не на тип ввода: на десктопе с узким
122
+ окном тоже рендерится мобильная ветка. Не завязывай на `MobileView` наличие
123
+ touch-специфичных обработчиков как единственного способа взаимодействия.
65
124
 
66
- Контракт отличается от "обычных" компонентов: **`children` — мобильное поведение**, а не базовое. При чтении кода это бывает контринтуитивно. Пример:
125
+ ---
67
126
 
68
- ```tsx
69
- <MobileView
70
- fallback={<DesktopLayout />}
71
- >
72
- <MobileLayout />
73
- </MobileView>
74
- ```
127
+ ## Связанные компоненты
128
+
129
+ - `MediaWidth` (`src/components/MediaWidth/`) — общий случай: `minWidth` и/или
130
+ `maxWidth`. `MobileView` — его частный случай для мобильной границы.
131
+ - `MediaMaxWidth`, `MediaMinWidth`, `MediaBetweenWidth` — реализации конкретных
132
+ диапазонов, к которым `MediaWidth` делегирует рендер.
133
+ - `useMatchMedia` (`src/components/MediaWidth/useMatchMedia.ts`) — хук подписки
134
+ на произвольный медиа-запрос, основа и компонента, и `useMobileView`.
75
135
 
76
- ### Не SSR-safe через `useMatchMedia` (см. MediaWidth-AI)
136
+ ### Потребители внутри библиотеки
77
137
 
78
- Поведение наследуется от `MediaWidth`: `window.innerWidth` читается при рендере.
138
+ Компонентом (`MobileView`): `Dropdown`, `Tooltip` (`TooltipBody`, `TooltipLink`),
139
+ `HelpBox`, `DateField`, `SuggestField`, `TabsLine`, `ImageGallery`,
140
+ `ImageGalleryExtendedMain`.
141
+ Хуком (`useMobileView`): `DateFieldTarget`, `MonthYearFieldTarget`,
142
+ `CheckboxTreeExtended`, `IslandWidget`, `IslandAccordionItem`, `Tooltip`.
143
+
144
+ В unit-тестах потребителей мобильная/десктопная ветка задаётся подменой
145
+ `window.matchMedia` (как в `Dropdown.test.tsx`) либо мокированием самого модуля
146
+ `MobileView` (как в `ImageGallery.test.tsx`, `LightBox.test.tsx`).
79
147
 
80
148
  ---
81
149
 
82
- ## Инварианты
150
+ ## Stories
83
151
 
84
- - **Брейкпоинт `SM_MAX`** фиксирован — публичное поведение.
85
- - **`children` — mobile, `fallback` — desktop** — не менять семантику без миграции потребителей.
86
- - **Обе prop'ы обязательны** (`ReactElement | null`, не `ReactNode`, не optional).
87
- - **FC, не forwardRef** — ref не пробрасывается.
152
+ Основные истории: `stories/MobileView/MobileView.stories.tsx`
153
+ Файлы примеров: `stories/MobileView/examples/`
88
154
 
89
- ---
155
+ Playground у компонента нет: `children` и `fallback` — React-элементы, для
156
+ Controls в них нечего настраивать. Скриншот-тесты снимают обе ветки: на
157
+ viewport `xs` (575px) рендерится мобильный вариант, на `xl` (1200px) —
158
+ `fallback`.
90
159
 
91
- ## Accessibility
160
+ | Story | Example file | Что демонстрирует |
161
+ |---|---|---|
162
+ | `Default` | `Default.tsx` | Выбор между `children` и `fallback` по ширине окна |
163
+ | `Example: useMobileView` | `Example.tsx` | Хук вместо компонента: на мобильной ширине кнопки становятся блочными и меняют размер |
92
164
 
93
- Тот же нюанс, что и `MediaWidth`: разные React-деревья → смена DOM на брейкпоинте. Для стилистических различий предпочитай CSS.
165
+ Пример использования `MobileView` есть и в stories `MediaWidth`
166
+ (`stories/MediaWidth/examples/MobileViewExample.tsx`) — он показывает связь
167
+ частного случая с общим и остаётся в документации `MediaWidth`.
94
168
 
95
169
  ---
96
170
 
97
- ## Дизайн-токены
171
+ ## История изменений
98
172
 
99
- Нет.
173
+ | Дата | Изменение |
174
+ |---|---|
175
+ | 2026-08-10 | Создан документ. AI-рефакторинг (TRI-59): `useMobileView.tsx` → `useMobileView.ts` (в файле нет JSX), явный тип возврата у хука, `displayName` у `MobileView`, дополнен JSDoc, добавлены unit-тесты (15 кейсов) и stories по modern pattern. Публичный API не изменён (props, сигнатура хука, barrel-экспорты; `forwardRef` по-прежнему осознанно отсутствует). |
100
176
 
101
177
  ---
102
178
 
103
- ## Связанные компоненты
179
+ ## Примеры использования
104
180
 
105
- - `MediaWidth` — общая абстракция (MobileView — её конкретизация).
106
- - `EScreenWidth.SM_MAX` — из `@sberbusiness/triplex-next/helpers/breakpoints`.
181
+ ### Default
107
182
 
108
- ---
183
+ `stories/MobileView/examples/Default.tsx`
109
184
 
110
- ## Stories
185
+ ```tsx
186
+ import React from "react";
187
+ import { MobileView } from "@sberbusiness/triplex-next";
188
+
189
+ export const Default = () => (
190
+ <MobileView
191
+ fallback={
192
+ <div style={{ border: "1px dashed rgb(125, 131, 138)", borderRadius: "4px", padding: "16px" }}>
193
+ Десктопная версия: ширина окна браузера 768px и больше.
194
+ </div>
195
+ }
196
+ >
197
+ <div style={{ border: "1px dashed rgb(125, 131, 138)", borderRadius: "4px", padding: "16px" }}>
198
+ Мобильная версия: ширина окна браузера меньше 768px.
199
+ </div>
200
+ </MobileView>
201
+ );
202
+ ```
111
203
 
112
- Нет.
204
+ ### Example: useMobileView
113
205
 
114
- ---
206
+ `stories/MobileView/examples/Example.tsx`
115
207
 
116
- ## История изменений
208
+ ```tsx
209
+ import React from "react";
210
+ import { Button, EButtonTheme, EComponentSize, useMobileView } from "@sberbusiness/triplex-next";
211
+
212
+ export const Example = () => {
213
+ const mobile = useMobileView();
214
+
215
+ return (
216
+ <div
217
+ style={{
218
+ display: "flex",
219
+ flexDirection: mobile ? "column" : "row",
220
+ gap: "8px",
221
+ maxWidth: "400px",
222
+ }}
223
+ >
224
+ <Button
225
+ theme={EButtonTheme.GENERAL}
226
+ size={mobile ? EComponentSize.SM : EComponentSize.MD}
227
+ block={mobile}
228
+ onClick={() => {}}
229
+ >
230
+ Сохранить
231
+ </Button>
232
+ <Button
233
+ theme={EButtonTheme.SECONDARY}
234
+ size={mobile ? EComponentSize.SM : EComponentSize.MD}
235
+ block={mobile}
236
+ onClick={() => {}}
237
+ >
238
+ Отменить
239
+ </Button>
240
+ </div>
241
+ );
242
+ };
243
+ ```
117
244
 
118
- | Дата | Изменение |
119
- |---|---|
120
- | 2026-04-18 | Создан документ |
@@ -101,7 +101,7 @@ version: "1.0"
101
101
 
102
102
  - **`ModalWindowContent`** — контейнер контента. Оборачивает дочерние секции в `Page` (`triplex-next/Page`). Имеет `isLoading?: boolean` и `loaderScreenProps?: ILoaderScreenMiddleProps` — при `isLoading` поверх контента показывается `LoaderScreen` типа `middle`; кастомизация лоадера (текст, кнопки и др.) передаётся через `loaderScreenProps`. Свой `displayName`. Свои props через интерфейс `IModalWindowContentProps` — экспортируется.
103
103
  - **`ModalWindowHeader`** — заголовок. Тривиальная обёртка над `HeaderPage` с фиксированным `type=FIRST` и доп. отступом справа под кнопку закрытия (через less). Экспонирует статическое поле `Title = HeaderPage.Title`. Тип `IModalWindowHeaderProps` (Omit `children`/`type` от `IHeaderPageTypeFirstProps`).
104
- - **`ModalWindowBody`** — тело. Тривиальная обёртка над `Island` с фиксированными `type=TYPE_1` и `size=MD`. Тип `IModalWindowBodyProps extends IIslandProps`.
104
+ - **`ModalWindowBody`** — тело. Тривиальная обёртка над `Island` с фиксированными `type=TYPE_1` и `size=MD`. Тип `IModalWindowBodyProps extends Omit<IIslandProps, "loading" | "loaderScreenProps">`. Состояние загрузки у `Island` намеренно отрезано: тело скроллируется (`overflow: auto`), а `LoaderScreen` позиционируется абсолютно и уехал бы вместе с контентом. Загрузку модального окна задавай на `ModalWindowContent`.
105
105
  - **`ModalWindowFooter`** — футер. Тривиальная обёртка над `FooterPage` с фиксированным `type=FIRST`. Экспонирует статическое поле `Description = FooterPage.Description`.
106
106
  - **`ModalWindowClose`** — кнопка закрытия. Обёртка над `Button` (`theme=SECONDARY`, `size=MD`, иконка `CrossStrokeSrvIcon20`) внутри `TriggerClickOnKeyDownEvent` с `EVENT_KEY_CODES.ESCAPE`. **Текст `title` не имеет дефолта внутри компонента** — библиотека мультиязычная, локализованную подсказку (например, `title="Закрыть"`) передаёт потребитель через props. Тип `IModalWindowCloseProps` (Omit `size`/`theme`/`icon` от `IButtonSecondaryProps`).
107
107
  - **`ModalWindowViewManager`** — невидимый компонент-сенсор. Создаёт DOM-ноду `<div id="modalWindowViewManagerNodeId">` (если её нет в `body`) и рендерит туда через `Portal` resize-сенсор + `<style>`-инжект CSS-переменных `--modalWindow-screen-*` в `:root`. Подключается автоматически из `ModalWindow`; экспортируется отдельно для случая, когда лайаут хочет позиционировать ноду вручную (например, рисовать модалку только в области рабочей зоны без шапки).
@@ -133,6 +133,8 @@ version: "1.0"
133
133
  | 2026-05-06 | Возвращён `forwardRef` в `ModalWindowContent` и `ModalWindowViewManager` (обязательный инвариант проекта). Удалён захардкоженный `title="Закрыть"` из `ModalWindowClose` — для мультиязычной библиотеки текст подсказки должен приходить от потребителя. **Breaking:** теперь `title` не подставляется автоматически. |
134
134
  | 2026-06-25 | Fix: устранено падение `focus-trap` `"must have at least one container with at least one tabbable node"` при открытии модалки без tabbable-узлов (асинхронный контент/лоадер). Добавлены `fallbackFocus` на dialog-узел и `tabIndex={-1}` на `role="dialog"`. Регрессия проявилась после синхронной активации ловушки в рефакторинге 1.28.0. Добавлен интеграционный тест на реальном `focus-trap`. |
135
135
  | 2026-06-30 | Fix: модалка не отображалась под React 18 `StrictMode`. На искусственном unmount/mount-цикле cleanup в `useEffect` открепляет портальный `mountNode`, а инициализатор `useState` повторно не вызывается — узел оставался вне DOM. Теперь `useEffect` при (повторном) mount возвращает узел в wrapper, если тот откреплён. Wrapper вынесен в `getOrCreateWrapperNode`. Добавлен регрессионный тест на реальном `Portal` (`ModalWindow.strictMode.test.tsx`). |
136
+ | 2026-08-07 | `IModalWindowBodyProps` сузился до `Omit<IIslandProps, "isLoading" \| "loaderScreenProps">`: в `Island` появилось состояние загрузки, но в скроллируемом теле модалки абсолютный `LoaderScreen` уезжает вместе с контентом. Публичный API не изменён — props исключены до их первого релиза; путь для загрузки модального окна прежний, `ModalWindowContent`. |
137
+ | 2026-08-11 | Prop загрузки в `Island` переименован `isLoading` → `loading`, вслед за ним `Omit` в `IModalWindowBodyProps` — теперь `Omit<IIslandProps, "loading" \| "loaderScreenProps">`. Публичный API `ModalWindow` не изменён: у `ModalWindowContent` prop по-прежнему `isLoading`. |
136
138
 
137
139
  ---
138
140
 
@@ -202,7 +202,13 @@ export const Status = () => (
202
202
  <Notification.Body.Content>
203
203
  This message provides context or highlights important information to note.
204
204
  </Notification.Body.Content>
205
- <Notification.Body.List values={Array.from({ length: 3 }, () => "List item text;")} />
205
+ <Notification.Body.List
206
+ items={[
207
+ { key: "1", children: "List item text" },
208
+ { key: "2", children: "List item text" },
209
+ { key: "3", children: "List item text" },
210
+ ]}
211
+ />
206
212
  </Notification.Body>
207
213
  <Notification.Close onClick={() => {}} />
208
214
  </Notification>
@@ -218,7 +224,13 @@ export const Status = () => (
218
224
  <Notification.Body.Content>
219
225
  This message provides context or highlights important information to note.
220
226
  </Notification.Body.Content>
221
- <Notification.Body.List values={Array.from({ length: 3 }, () => "List item text;")} />
227
+ <Notification.Body.List
228
+ items={[
229
+ { key: "1", children: "List item text" },
230
+ { key: "2", children: "List item text" },
231
+ { key: "3", children: "List item text" },
232
+ ]}
233
+ />
222
234
  </Notification.Body>
223
235
  <Notification.Close onClick={() => {}} />
224
236
  </Notification>
@@ -234,7 +246,13 @@ export const Status = () => (
234
246
  <Notification.Body.Content>
235
247
  This message provides context or highlights important information to note.
236
248
  </Notification.Body.Content>
237
- <Notification.Body.List values={Array.from({ length: 3 }, () => "List item text;")} />
249
+ <Notification.Body.List
250
+ items={[
251
+ { key: "1", children: "List item text" },
252
+ { key: "2", children: "List item text" },
253
+ { key: "3", children: "List item text" },
254
+ ]}
255
+ />
238
256
  </Notification.Body>
239
257
  <Notification.Close onClick={() => {}} />
240
258
  </Notification>
@@ -61,6 +61,7 @@ version: "1.0"
61
61
  Собственных CSS-переменных дизайн-токенов у `Page` нет. Внешние отступы и брейкпоинты заданы
62
62
  LESS-переменными в `styles/Page.module.less` (`@page-padding-*`, `@screen-sm-max`). Sticky-стили
63
63
  для прилипающих Header/Footer (классы `.headerPageTypeFirst.sticky`, `.footerPageTypeFirst.sticky`)
64
+ применяются при ширине viewport от 992px (`@screen-lg`) и высоте от 801px и
64
65
  используют токены соответствующих компонентов (`--triplex-next-HeaderPage-StickyShadow`,
65
66
  `--triplex-next-FooterPage-StickyShadow`) — они описаны в AI.md этих компонентов.
66
67
 
@@ -73,7 +74,7 @@ LESS-переменными в `styles/Page.module.less` (`@page-padding-*`, `@s
73
74
  - `Page` собран через `Object.assign(forwardRef(...), { Body, Header, Footer })` — статические
74
75
  свойства `Header` / `Body` / `Footer` должны сохраняться.
75
76
  - Корневые классы `page` и `global-page` на корневом `<div>` — не переименовывать (используются
76
- в стилях, в т.ч. в sticky-селекторах `.global-LB-more-media-point-0`).
77
+ в стилях; sticky-стили частей задаются медиазапросом `min-width: 992px` и `min-height: 801px`).
77
78
  - Экспорты `Page`, `IPageProps` идут в barrel `src/components/Page/index.ts` — сохранять.
78
79
  Там же реэкспортируются части и их enum'ы (`EHeaderPageType`, `EFooterPageType`, `EBodyPageType`,
79
80
  `EBodyPageVerticalMargin`).
@@ -120,6 +121,7 @@ aria-атрибутов. Семантику задаёт потребитель
120
121
 
121
122
  | Дата | Изменение |
122
123
  |---|---|
124
+ | 2026-08-06 | Sticky-позиционирование Header/Footer доступно вне `LightBox` при ширине viewport от 992px и отключено при высоте viewport не больше 800px. |
123
125
  | 2026-07-20 | Вертикальные padding изменены: 24px (было 32px) для desktop, 8px (было 16px) для mobile — через `@page-padding-desktop-y` / `@page-padding-mobile-y`. |
124
126
  | 2026-06-24 | Создан документ. AI-рефакторинг (JSDoc на компоненте и `IPageProps`), unit-тесты (className-merge, статические части), миграция stories на modern pattern. |
125
127
 
@@ -13,6 +13,7 @@ related:
13
13
  - SelectField
14
14
  - ButtonIcon
15
15
  - ButtonBase
16
+ - MasterTable
16
17
  tokens:
17
18
  - --triplex-next-Pagination-PageButton_Background_Hover
18
19
  - --triplex-next-Pagination-PageButton_Background_Active
@@ -63,6 +64,21 @@ version: "1.0"
63
64
 
64
65
  Расширяет `ISelectFieldProps` (без `size`, с обязательным `value`) и добавляет `paginationLabel: React.ReactNode` — текст лейбла перед селектом. Размер селекта зафиксирован как `EComponentSize.SM`. `value`, `options`, `onChange` — управляются потребителем.
65
66
 
67
+ ### Состояние загрузки внутри `MasterTable`
68
+
69
+ Собственного prop загрузки у пагинации нет. Внутри `MasterTable` с `loading` элементы пагинации
70
+ блокируются автоматически: `PaginationNavigationButton` и `PaginationPageButton` получают
71
+ `disabled`, `PaginationSelect` — `status={EFormFieldStatus.DISABLED}`, из-за которого выпадающий
72
+ список не открывается. Читается это из `MasterTableContext` (`loading`), поэтому работает и через
73
+ `Pagination`, и через ручную компоновку на `PaginationExtended`.
74
+
75
+ Лоадер при этом рисует `TableBasic` — он лежит в собственном `position: relative`-контейнере и
76
+ перекрывает только таблицу. Пагинация в `MasterTable.PaginationPanel` остаётся видимой и читаемой.
77
+
78
+ Вне `MasterTable` контекст отдаёт `loading: false`, поэтому автономная пагинация ведёт себя
79
+ как раньше: блокировка приходит только из `disabled` на `buttonPrevProps`/`buttonNextProps` и из
80
+ крайних страниц.
81
+
66
82
  ### Subкомпоненты для кастомной компоновки
67
83
 
68
84
  Для нестандартной раскладки используется `PaginationExtended` напрямую с вложенными `PaginationNavigation` и `PaginationSelect` (см. story `Extended`). Низкоуровневые части (`PaginationNavigationExtended`, `PaginationNavigationExtendedItem`, `PaginationPageButton`, `PaginationPageEllipsis`, `PaginationNavigationButton`) экспортируются для построения полностью кастомной навигации, но обычно используются неявно через `PaginationNavigation`.
@@ -92,6 +108,8 @@ version: "1.0"
92
108
  - Навигация рендерится только при `totalPages > 1` — поведение публичное, на него опираются потребители.
93
109
  - Логику `PaginationUtils.createPagesArray` / `generatePageRanges` / `generateRange` не менять без перегенерации `__tests__/paginationUtils.test.tsx` — там зафиксированы граничные случаи раскладки.
94
110
  - `PAGINATION_ELLIPSIS_VALUE = -1` — sentinel в массиве страниц, на него завязан рендер многоточия.
111
+ - Блокировка по `MasterTableContext.loading` перекрывает `disabled`, пришедший из props: в состоянии загрузки кнопка заблокирована независимо от того, что передал потребитель. Обратное неверно — вне загрузки решает prop.
112
+ - Импорт `MasterTableContext` в частях пагинации — абсолютный (`@sberbusiness/triplex-next/components/Table/MasterTableContext`), как в самом `Table`. Относительный путь сюда не ставить.
95
113
 
96
114
  ---
97
115
 
@@ -114,6 +132,7 @@ version: "1.0"
114
132
  - `PaginationPageButton` — кнопка-страница (поверх `ButtonBase`).
115
133
  - `PaginationPageEllipsis` — многоточие, заменяющее группу скрытых страниц.
116
134
  - `PaginationNavigationButton` — кнопка «Назад»/«Вперёд» (поверх `ButtonIcon`), направление задаётся `EPaginationNavigationIconDirection`.
135
+ - `MasterTable` — таблица, в паре с которой пагинация обычно и используется (`MasterTable.PaginationPanel`). Её `loading` через `MasterTableContext` блокирует элементы пагинации.
117
136
 
118
137
  ---
119
138
 
@@ -137,6 +156,7 @@ version: "1.0"
137
156
  | Дата | Изменение |
138
157
  |---|---|
139
158
  | 2026-06-22 | Создан документ |
159
+ | 2026-08-12 | В состоянии загрузки `MasterTable` элементы пагинации становятся `disabled` — читается из `MasterTableContext.loading`. Публичный API не изменился. Заодно `PaginationSelect` перестал молча терять переданный `status`. |
140
160
 
141
161
  ---
142
162