@sberbusiness/triplex-next-mcp-server 1.50.0-beta → 1.53.1

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 (74) hide show
  1. package/README.md +1 -0
  2. package/bundle/components/AlertProcess.md +6 -3
  3. package/bundle/components/AlertProcessSpoiler.md +216 -0
  4. package/bundle/components/Badge.md +4 -3
  5. package/bundle/components/ButtonDropdown.md +5 -3
  6. package/bundle/components/Carousel.md +671 -0
  7. package/bundle/components/CarouselExtended.md +7 -5
  8. package/bundle/components/CarouselIndicators.md +666 -0
  9. package/bundle/components/CarouselItem.md +579 -0
  10. package/bundle/components/CarouselNextButton.md +633 -0
  11. package/bundle/components/CarouselPrevButton.md +633 -0
  12. package/bundle/components/CarouselViewport.md +631 -0
  13. package/bundle/components/CheckboxTreeExtended.md +21 -7
  14. package/bundle/components/CheckboxTreeExtendedCheckbox.md +591 -0
  15. package/bundle/components/CheckboxTreeExtendedNode.md +577 -0
  16. package/bundle/components/Chip.md +1 -0
  17. package/bundle/components/ChipDatePicker.md +332 -0
  18. package/bundle/components/ChipDatePickerTarget.md +316 -0
  19. package/bundle/components/ChipMonthYearPicker.md +4 -3
  20. package/bundle/components/ChipMonthYearPickerTarget.md +318 -0
  21. package/bundle/components/ChipMultiselect.md +63 -73
  22. package/bundle/components/ChipSelect.md +385 -0
  23. package/bundle/components/ChipSelectTarget.md +388 -0
  24. package/bundle/components/ChipSuggest.md +10 -16
  25. package/bundle/components/ChipSuggestTarget.md +506 -0
  26. package/bundle/components/CollapsibleTree.md +2 -1
  27. package/bundle/components/CollapsibleTreeExtended.md +2 -1
  28. package/bundle/components/DateField.md +4 -2
  29. package/bundle/components/DatePickerExtended.md +16 -14
  30. package/bundle/components/DateRange.md +17 -10
  31. package/bundle/components/Dropdown.md +36 -63
  32. package/bundle/components/EmptyView.md +9 -4
  33. package/bundle/components/ExpandAnimation.md +9 -5
  34. package/bundle/components/FormField.md +1 -1
  35. package/bundle/components/ImageGallery.md +19 -52
  36. package/bundle/components/ImageGalleryExtended.md +123 -139
  37. package/bundle/components/ListItemControlsButtonDropdown.md +3 -2
  38. package/bundle/components/LoaderSmall.md +5 -4
  39. package/bundle/components/MonthYearRange.md +334 -0
  40. package/bundle/components/MultiselectField.md +81 -143
  41. package/bundle/components/Notification.md +2 -1
  42. package/bundle/components/NotificationGrouped.md +174 -0
  43. package/bundle/components/NumberField.md +259 -116
  44. package/bundle/components/OrderedList.md +149 -112
  45. package/bundle/components/Overlay.md +3 -2
  46. package/bundle/components/PageIndicators.md +306 -0
  47. package/bundle/components/Pagination.md +81 -3
  48. package/bundle/components/PaginationExtended.md +160 -0
  49. package/bundle/components/Portal.md +5 -2
  50. package/bundle/components/Puller.md +375 -0
  51. package/bundle/components/SMSField.md +277 -102
  52. package/bundle/components/SelectExtendedField.md +11 -7
  53. package/bundle/components/SelectField.md +7 -4
  54. package/bundle/components/SmartSpot.md +259 -0
  55. package/bundle/components/Step.md +2 -1
  56. package/bundle/components/Stepper.md +7 -7
  57. package/bundle/components/Suggest.md +7 -6
  58. package/bundle/components/SuggestField.md +8 -6
  59. package/bundle/components/TableBasic.md +12 -14
  60. package/bundle/components/Tooltip.md +9 -8
  61. package/bundle/guides/commits.md +4 -1
  62. package/bundle/guides/context.md +5 -5
  63. package/bundle/guides/stories.md +29 -21
  64. package/bundle/manifest.json +145 -13
  65. package/bundle/release-notes/1.50.0.mdx +4 -0
  66. package/bundle/release-notes/1.51.0.mdx +57 -0
  67. package/bundle/release-notes/1.52.0.mdx +55 -0
  68. package/bundle/release-notes/1.53.0.mdx +60 -0
  69. package/bundle/release-notes/1.54.0.mdx +45 -0
  70. package/bundle/release-notes/1.55.0.mdx +7 -0
  71. package/bundle/tokens.json +377 -222
  72. package/dist/index.js +39 -1
  73. package/dist/index.js.map +1 -1
  74. package/package.json +1 -1
@@ -0,0 +1,375 @@
1
+ ---
2
+ component: Puller
3
+ category: Puller
4
+ related: [Overlay, Portal, ButtonIcon, LoaderSmall, Badge, FormField]
5
+ tokens:
6
+ - Puller.Backdrop
7
+ - Puller.Body_Background
8
+ - Puller.Border_Color
9
+ - Puller.Footer_Background
10
+ - Puller.Header_Background
11
+ - PullerList.Active_Background
12
+ - PullerList.Selected_Background
13
+ - FormField.Input_Color_Default
14
+ - FormField.Placeholder_Color
15
+ stories: stories/Puller/Puller.stories.tsx
16
+ version: "1.0"
17
+ ---
18
+
19
+ # Puller
20
+
21
+ ## Назначение
22
+
23
+ Нижняя шторка (bottom sheet) на базе `OverlayBase` для экранов любой ширины: выезжает снизу на всю ширину поверх подложки.
24
+
25
+ Используй когда: нужна шторка, которая открывается не от выпадающего меню.
26
+ Не используй когда:
27
+
28
+ - нужен выпадающий блок, который на десктопе — меню, а на мобильном — шторка. Используй `Dropdown` с `pullerProps`: он сам переключает версии через `MobileView`;
29
+ - нужна подсказка — используй `Tooltip`, его мобильная версия уже построена на `Puller`;
30
+ - нужно модальное окно или боковая панель — используй `ModalWindow` или `Overlay`.
31
+
32
+ ---
33
+
34
+ ## Варианты и props
35
+
36
+ ### `Puller`
37
+
38
+ `IPullerProps` расширяет `React.HTMLAttributes<HTMLDivElement>`. Атрибуты распределяются так: `className` попадает на фиксированный wrapper (`.pullerWrapper`), всё остальное (`id`, `role`, `aria-*`, `style`, обработчики) — на контентный `<div>` (`.puller`), туда же ведёт `ref`.
39
+
40
+ #### Обязательные props
41
+
42
+ | Prop | Тип | Описание |
43
+ |---|---|---|
44
+ | `opened` | `boolean` | Состояние открытости: компонент полностью управляемый, собственного state открытости нет |
45
+ | `setOpened` | `(opened: boolean) => void` | Вызывается с `false` по `touchstart` / `mousedown` на подложке (только когда `opened === true`) |
46
+
47
+ #### Опциональные props
48
+
49
+ | Prop | Тип | По умолчанию | Описание |
50
+ |---|---|---|---|
51
+ | `renderContainer` | `Element \| DocumentFragment` | `document.body` | DOM-узел, в который рендерится шторка |
52
+
53
+ Остальные — HTML-атрибуты `<div>`.
54
+
55
+ ### Субкомпоненты
56
+
57
+ | Компонент | Собственные props | Описание |
58
+ |---|---|---|
59
+ | `PullerHeader` | `controlButtons?: ReactNode` | Шапка. `children` — слева (сжимается, `min-width: 0`), `controlButtons` — справа: обычно `PullerLoader` и `PullerClose` |
60
+ | `PullerBody` | — | Скроллируемое тело (`overflow: auto`, `flex-grow: 1`) |
61
+ | `PullerFooter` | — | Футер для кнопок, с верхней границей |
62
+ | `PullerClose` | `IButtonIconProps` без `children` | Кнопка закрытия: `ButtonIcon` с иконкой-крестиком. Сама шторку не закрывает: `onClick` и `aria-label` передаёт потребитель |
63
+ | `PullerList` | `loading?: boolean` | Контейнер списка с `role="listbox"`. При `loading` в конец добавляется `LoaderSmall` MD, скрытый от скринридеров (`aria-hidden`): загрузку передаёт `aria-busy` на `listbox` |
64
+ | `PullerListItem` | `id: string`, `onSelect?`, `selected?`, `showNotificationIcon?` | Элемент списка с `role="option"`. `onSelect` вызывается по клику до `onClick`. Строковый `children` дублируется в `title` |
65
+ | `PullerLoader` | `ILoaderSmallProps` без `theme` / `size` | Лоадер для шапки: `LoaderSmall`, тема `BRAND`, размер SM |
66
+ | `PullerInput` | `InputHTMLAttributes` | Нативный `<input>` для шапки, без рамки и фона |
67
+ | `PullerMaskedInput` | `IFormFieldMaskedInputProps` | Маскированное поле для шапки: обёртка над `FormFieldMaskedInput` со статическим `presets` (тот же объект, что у `FormFieldMaskedInput`) |
68
+
69
+ ### Ограничения
70
+
71
+ - `.pullerWrapper` — `position: fixed`: `transform`, `filter`, `perspective`, `contain` или собственный stacking context у `renderContainer` и его родителей сдвинут, обрежут или перекроют шторку.
72
+ - Пока шторка открыта, скролл блокируется на `body`, а не на `renderContainer`.
73
+ - Шторка не закрывается по `Escape` и не перехватывает фокус — это добавляет потребитель (как `MultiselectField.Dropdown` и `DatePickerExtended`).
74
+ - Высота ограничена `50vh`: длинное содержимое кладётся в прокручиваемый `PullerBody`.
75
+
76
+ ---
77
+
78
+ ## Дизайн-токены
79
+
80
+ Переопределяются через `ThemeProvider` (prop `tokens`) — см. `ThemeProvider-ai.md` →
81
+ «Как переопределять токены». Значения по умолчанию лежат в файлах групп `Puller` и `PullerList` в `src/components/DesignTokens/components/`.
82
+
83
+ ```text
84
+ Puller.Backdrop
85
+ Puller.Body_Background
86
+ Puller.Border_Color
87
+ Puller.Footer_Background
88
+ Puller.Header_Background
89
+ PullerList.Active_Background
90
+ PullerList.Selected_Background
91
+ ```
92
+
93
+ `PullerInput` дополнительно использует токены поля ввода: `FormField.Input_Color_Default`, `FormField.Placeholder_Color`.
94
+
95
+ ---
96
+
97
+ ## Инварианты
98
+
99
+ - `forwardRef` на `Puller` и всех субкомпонентах, кроме `PullerLoader`, — не убирать. Ref `Puller` указывает на контентный `<div>` (`.puller`), а не на wrapper. На это опирается `Dropdown`: его ref в мобильном режиме ведёт сюда.
100
+ - `Puller` рендерится через `Portal`, по умолчанию в `document.body`. Смена контейнера по умолчанию — breaking change для потребителей, которые ищут шторку в DOM.
101
+ - В закрытом состоянии (`opened`, `opening` и `closing` равны `false`) `PullerInner` возвращает `null`. Анимация закрытия доигрывает до `transitionend` на подложке и только потом снимает разметку.
102
+ - Непрозрачность подложки задаётся альфа-каналом токена `Puller.Backdrop`; `opacity` подложки только анимирует появление (0 → 1).
103
+ - Анимация открытия требует сначала отрендерить шторку закрытой: `openingState` / `openedState` выставляются через `setTimeout`. Не заменять на синхронную установку, иначе переход не проиграется.
104
+ - Пока `opened === true`, на `document.body` висит класс `pullerScrollLock` (`overflow: hidden`). Класс вешается только через `lockBodyScroll` (`src/utils/scroll/bodyScrollLock.ts`): прямой `classList.remove` снял бы блокировку при другой открытой шторке.
105
+ - Компонент управляемый: не добавлять внутренний state открытости.
106
+ - На корневые классы `.puller`, `.pullerWrapper`, `.pullerBackdrop` опираются тесты `MultiselectFieldDropdown.test.tsx` и `SuggestFieldMobile.test.tsx`. Переименование — breaking change.
107
+ - `IPullerHeaderProps` объявлен в `PullerHeader.tsx`, его расширяет `ITooltipMobileHeaderProps` (`src/components/Tooltip/types.ts`). Перенос типа ломает deep-импорты.
108
+ - Публичный barrel `src/components/Puller/index.ts` (включая `PullerMaskedInput`) должен сохраняться. `PullerInner` — внутренняя разметка, в barrel не входит.
109
+
110
+ ---
111
+
112
+ ## Accessibility
113
+
114
+ - Роль диалога шторка сама не ставит: `role="dialog"` и `aria-label` / `aria-labelledby` потребитель передаёт на `Puller` (они попадают на контентный `<div>`).
115
+ - `PullerList` — `role="listbox"`, `PullerListItem` — `role="option"` с `aria-selected`. Клавиатурной навигации по списку нет.
116
+ - `PullerClose` — кнопка-иконка без текста: `aria-label` передаёт потребитель. `ButtonDropdown`, `SelectExtendedFieldDropdownDefault`, `DatePickerExtendedDropdown`, `ListItemControlsButtonDropdown`, `SuggestMobileDropdownContent` и `SuggestFieldMobileDropdown` его пока не передают.
117
+ - `PullerInput` — нативный `<input>` без видимой подписи: `aria-label` передаёт потребитель.
118
+
119
+ ---
120
+
121
+ ## Связанные компоненты
122
+
123
+ - `Overlay` — семейство, к которому относится `OverlayBase`: `Puller` рендерит `OverlayBase` с `direction={EOverlayDirection.BOTTOM}` и получает от него флаги `opening` / `closing` и сеттеры анимации.
124
+ - `Portal` — выносит шторку из дерева родителя, см. «Инварианты».
125
+ - `ButtonIcon` — база `PullerClose`, `IPullerCloseProps` расширяет `IButtonIconProps`.
126
+ - `LoaderSmall` — рендерится в `PullerLoader` (тема `BRAND`, SM) и в элементе-лоадере `PullerList` (MD). `IPullerLoaderProps` расширяет `ILoaderSmallProps`.
127
+ - `Badge` — `Badge.Dot` в углу `PullerListItem` при `showNotificationIcon`.
128
+ - `FormField` — `PullerMaskedInput` оборачивает `FormFieldMaskedInput` и наследует `IFormFieldMaskedInputProps`. Токены поля ввода использует `PullerInput`.
129
+ - `Text` — `PullerListItem` рендерится как `Text` размера `B3`.
130
+ - `Dropdown`, `Tooltip` — в адаптивном режиме рендерят `Puller` вместо десктопной версии.
131
+ - `MobileView` — переключает версии в `Dropdown` и `Tooltip`; сам `Puller` ширину экрана не проверяет.
132
+
133
+ ---
134
+
135
+ ## Stories
136
+
137
+ Основные истории: `stories/Puller/Puller.stories.tsx`
138
+ Файлы примеров: `stories/Puller/examples/`
139
+
140
+ Примеры стартуют закрытыми. Шторку открывает `play`; на docs-странице (`viewMode === "docs"`) он ничего не делает.
141
+
142
+ | Story | Example file | Что демонстрирует |
143
+ |---|---|---|
144
+ | `Playground` | `Playground.tsx` | Интерактивный контроль: начальное `opened`, заголовок, `listLoading` (`loading` списка), наличие футера |
145
+ | `Default` | `Default.tsx` | Кнопка открывает шторку: шапка с заголовком и `PullerClose`, тело, футер с кнопкой |
146
+ | `WithList` | `WithList.tsx` | `PullerList` с выбранным элементом, значком уведомления и `loading`; выбор закрывает шторку |
147
+ | `WithInput` | `WithInput.tsx` | Шапка с `PullerInput`, `PullerLoader` и `PullerClose` — раскладка мобильного suggest |
148
+ | `RenderContainer` («Render container») | `RenderContainer.tsx` | Рендер шторки в заданный контейнер через `renderContainer` |
149
+ | `VisualTests` | `VisualTests.tsx` | Длинный заголовок, лоадер, скролл длинного списка, выбранный элемент, значок, футер с двумя кнопками |
150
+
151
+ ---
152
+
153
+ ## История изменений
154
+
155
+ | Дата | Изменение |
156
+ |---|---|
157
+ | 2026-10-21 | Создан документ (TRIPLEX-961). |
158
+ | 2026-10-31 | **Breaking**: `Puller` сам рендерится через `Portal`: по умолчанию в `document.body`, контейнер задаёт новый prop `renderContainer` (TRIPLEX-961). |
159
+
160
+ ---
161
+
162
+ ## Примеры использования
163
+
164
+ ### Default
165
+
166
+ `stories/Puller/examples/Default.tsx`
167
+
168
+ ```tsx
169
+ import React, { useState } from "react";
170
+ import {
171
+ Button,
172
+ EButtonTheme,
173
+ EComponentSize,
174
+ ETextSize,
175
+ Puller,
176
+ PullerBody,
177
+ PullerClose,
178
+ PullerFooter,
179
+ PullerHeader,
180
+ Text,
181
+ } from "@sberbusiness/triplex-next";
182
+
183
+ export const Default = () => {
184
+ const [opened, setOpened] = useState(false);
185
+
186
+ return (
187
+ <div>
188
+ <Button
189
+ theme={EButtonTheme.SECONDARY}
190
+ size={EComponentSize.MD}
191
+ aria-haspopup="dialog"
192
+ aria-expanded={opened}
193
+ onClick={() => setOpened(true)}
194
+ >
195
+ Open
196
+ </Button>
197
+ <Puller opened={opened} setOpened={setOpened} role="dialog" aria-labelledby="puller-default-title">
198
+ <PullerHeader controlButtons={<PullerClose aria-label="Close" onClick={() => setOpened(false)} />}>
199
+ <Text id="puller-default-title" size={ETextSize.B1}>
200
+ Title
201
+ </Text>
202
+ </PullerHeader>
203
+ <PullerBody>
204
+ <Text tag="div" size={ETextSize.B3} style={{ padding: "16px" }}>
205
+ Puller content. The puller closes via the close button, the footer button or a tap on the
206
+ backdrop.
207
+ </Text>
208
+ </PullerBody>
209
+ <PullerFooter>
210
+ <Button
211
+ theme={EButtonTheme.GENERAL}
212
+ size={EComponentSize.MD}
213
+ block
214
+ onClick={() => setOpened(false)}
215
+ >
216
+ Done
217
+ </Button>
218
+ </PullerFooter>
219
+ </Puller>
220
+ </div>
221
+ );
222
+ };
223
+ ```
224
+
225
+ ### WithList
226
+
227
+ `stories/Puller/examples/WithList.tsx`
228
+
229
+ ```tsx
230
+ import React, { useState } from "react";
231
+ import {
232
+ Button,
233
+ EButtonTheme,
234
+ EComponentSize,
235
+ ETextSize,
236
+ Puller,
237
+ PullerBody,
238
+ PullerClose,
239
+ PullerHeader,
240
+ PullerList,
241
+ PullerListItem,
242
+ Text,
243
+ } from "@sberbusiness/triplex-next";
244
+
245
+ const OPTIONS = [
246
+ { id: "with-list-option-1", label: "Value 1" },
247
+ { id: "with-list-option-2", label: "Value 2" },
248
+ { id: "with-list-option-3", label: "Value 3", hasNotifications: true },
249
+ ];
250
+
251
+ export const WithList = () => {
252
+ const [opened, setOpened] = useState(false);
253
+ const [selectedId, setSelectedId] = useState("with-list-option-2");
254
+
255
+ const handleSelect = (id: string) => {
256
+ setSelectedId(id);
257
+ setOpened(false);
258
+ };
259
+
260
+ return (
261
+ <div>
262
+ <Button
263
+ theme={EButtonTheme.SECONDARY}
264
+ size={EComponentSize.MD}
265
+ aria-haspopup="dialog"
266
+ aria-expanded={opened}
267
+ onClick={() => setOpened(true)}
268
+ >
269
+ Open
270
+ </Button>
271
+ <Puller opened={opened} setOpened={setOpened} role="dialog" aria-labelledby="puller-with-list-title">
272
+ <PullerHeader controlButtons={<PullerClose aria-label="Close" onClick={() => setOpened(false)} />}>
273
+ <Text id="puller-with-list-title" size={ETextSize.B1}>
274
+ Select a value
275
+ </Text>
276
+ </PullerHeader>
277
+ <PullerBody>
278
+ <PullerList loading aria-labelledby="puller-with-list-title">
279
+ {OPTIONS.map((option) => (
280
+ <PullerListItem
281
+ key={option.id}
282
+ id={option.id}
283
+ selected={option.id === selectedId}
284
+ showNotificationIcon={option.hasNotifications}
285
+ onSelect={() => handleSelect(option.id)}
286
+ >
287
+ {option.label}
288
+ </PullerListItem>
289
+ ))}
290
+ </PullerList>
291
+ </PullerBody>
292
+ </Puller>
293
+ </div>
294
+ );
295
+ };
296
+ ```
297
+
298
+ ### WithInput
299
+
300
+ `stories/Puller/examples/WithInput.tsx`
301
+
302
+ ```tsx
303
+ import React, { useState } from "react";
304
+ import {
305
+ Button,
306
+ EButtonTheme,
307
+ EComponentSize,
308
+ Puller,
309
+ PullerBody,
310
+ PullerClose,
311
+ PullerHeader,
312
+ PullerInput,
313
+ PullerList,
314
+ PullerListItem,
315
+ PullerLoader,
316
+ } from "@sberbusiness/triplex-next";
317
+
318
+ const OPTIONS = [
319
+ { id: "with-input-option-1", label: "Moscow" },
320
+ { id: "with-input-option-2", label: "Mombasa" },
321
+ { id: "with-input-option-3", label: "Montreal" },
322
+ ];
323
+
324
+ export const WithInput = () => {
325
+ const [opened, setOpened] = useState(false);
326
+ const [inputValue, setInputValue] = useState("Mo");
327
+
328
+ const handleSelect = (label: string) => {
329
+ setInputValue(label);
330
+ setOpened(false);
331
+ };
332
+
333
+ return (
334
+ <div>
335
+ <Button
336
+ theme={EButtonTheme.SECONDARY}
337
+ size={EComponentSize.MD}
338
+ aria-haspopup="dialog"
339
+ aria-expanded={opened}
340
+ onClick={() => setOpened(true)}
341
+ >
342
+ Open
343
+ </Button>
344
+ <Puller opened={opened} setOpened={setOpened} role="dialog" aria-label="City search">
345
+ <PullerHeader
346
+ controlButtons={
347
+ <>
348
+ {/* В реальном сценарии лоадер показывается на время запроса подсказок. */}
349
+ <PullerLoader />
350
+ <PullerClose aria-label="Close" onClick={() => setOpened(false)} />
351
+ </>
352
+ }
353
+ >
354
+ <PullerInput
355
+ value={inputValue}
356
+ placeholder="Enter a city"
357
+ aria-label="City"
358
+ onChange={(event) => setInputValue(event.target.value)}
359
+ />
360
+ </PullerHeader>
361
+ <PullerBody>
362
+ <PullerList aria-label="Suggestions">
363
+ {OPTIONS.map((option) => (
364
+ <PullerListItem key={option.id} id={option.id} onSelect={() => handleSelect(option.label)}>
365
+ {option.label}
366
+ </PullerListItem>
367
+ ))}
368
+ </PullerList>
369
+ </PullerBody>
370
+ </Puller>
371
+ </div>
372
+ );
373
+ };
374
+ ```
375
+