@sberbusiness/triplex-next-mcp-server 0.36.0-beta0 → 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 (35) hide show
  1. package/bundle/components/AlertContext.md +268 -0
  2. package/bundle/components/Button.md +5 -2
  3. package/bundle/components/ButtonDropdown.md +9 -1
  4. package/bundle/components/ButtonDropdownExtended.md +422 -0
  5. package/bundle/components/ButtonIcon.md +7 -1
  6. package/bundle/components/Caption.md +291 -0
  7. package/bundle/components/CodeText.md +197 -0
  8. package/bundle/components/Col.md +311 -162
  9. package/bundle/components/CollapsibleTree.md +6 -3
  10. package/bundle/components/CollapsibleTreeExtended.md +6 -2
  11. package/bundle/components/Dropdown.md +748 -346
  12. package/bundle/components/LightBox.md +2252 -233
  13. package/bundle/components/List.md +26 -1
  14. package/bundle/components/ListActionItem.md +157 -0
  15. package/bundle/components/ListItem.md +34 -9
  16. package/bundle/components/ListItemSelectable.md +2 -2
  17. package/bundle/components/ListMaster.md +4 -5
  18. package/bundle/components/ListTableItem.md +391 -0
  19. package/bundle/components/Notification.md +21 -21
  20. package/bundle/components/Page.md +1 -0
  21. package/bundle/components/Portal.md +131 -67
  22. package/bundle/components/Row.md +171 -69
  23. package/bundle/components/Text.md +320 -0
  24. package/bundle/components/TextField.md +364 -97
  25. package/bundle/components/Title.md +296 -0
  26. package/bundle/guides/commits.md +118 -24
  27. package/bundle/guides/context.md +1 -1
  28. package/bundle/guides/tests.md +42 -0
  29. package/bundle/manifest.json +89 -14
  30. package/bundle/release-notes/1.37.0.mdx +42 -1
  31. package/bundle/release-notes/1.38.0.mdx +36 -0
  32. package/bundle/release-notes/1.39.0.mdx +66 -0
  33. package/bundle/release-notes/1.40.0.mdx +27 -0
  34. package/bundle/release-notes/1.41.0.mdx +7 -0
  35. package/package.json +1 -1
@@ -0,0 +1,391 @@
1
+ ---
2
+ component: ListTableItem
3
+ category: List
4
+ related: [ListItem, ListItemSelectable, ListItemControls, ListItemControlsButton, SwipeableArea]
5
+ tokens:
6
+ - --triplex-next-ListItem-Background
7
+ - --triplex-next-ListItem-Background_Selected
8
+ stories: stories/List/ListTableItem.stories.tsx
9
+ version: "1.0"
10
+ ---
11
+
12
+ # ListTableItem
13
+
14
+ ## Назначение
15
+
16
+ Высокоуровневая обёртка `<li>` для табличных строк. Объединяет `ListItem` +
17
+ `SwipeableArea` + опциональный `ListItemSelectable`. Автоматически рисует
18
+ правый «хвост» (`ListItemTailRight`) и контейнер для swipe-actions
19
+ (`ListItemControls`).
20
+
21
+ Используй `ListTableItem` когда: нужна готовая строка с поддержкой swipe и
22
+ выбора. Не нужен — собирай руками из `ListItem` + `ListItemContent` +
23
+ `SwipeableArea` + `ListItemSelectable`.
24
+
25
+ ---
26
+
27
+ ## Варианты и props
28
+
29
+ `ListTableItem` имеет **discriminated union** API: либо без выбора (`onSelect`/`selected` запрещены типом), либо selectable (оба обязательны).
30
+
31
+ ### Общие опциональные props
32
+
33
+ | Prop | Тип | По умолчанию | Описание |
34
+ |---|---|---|---|
35
+ | `controlButtons` | `React.ReactNode` | — | Кнопки действий, оборачиваются в `<ListItemControls>` и подключаются как `rightSwipeableArea` у `SwipeableArea` |
36
+ | `onClickItem` | `(event: React.MouseEvent<HTMLDivElement>) => void` | — | Передаётся как `onClick` на контейнер контента (`ListItemContent`). Не вызывается при клике на чекбокс или swipe-actions |
37
+ | `swipeableAreaRef` | `React.Ref<ISwipeableAreaRef>` | — | Ref на внутренний `SwipeableArea` (для программного открытия/закрытия swipe-области, например в `WithSwipeEmulation`-сторе) |
38
+ | `children` | `React.ReactNode` | — | Содержимое строки (рендерится внутри `ListItemContent`) |
39
+
40
+ ### Selectable-вариант (оба prop'а обязательны вместе)
41
+
42
+ | Prop | Тип | Описание |
43
+ |---|---|---|
44
+ | `selected` | `boolean` | Состояние «выбран» — управляется снаружи |
45
+ | `onSelect` | `(selected: boolean) => void` | Вызывается при изменении состояния чекбокса |
46
+
47
+ В non-selectable варианте оба prop'а имеют тип `never` — TypeScript запрещает их передачу.
48
+
49
+ ---
50
+
51
+ ## Дизайн-токены
52
+
53
+ ```text
54
+ --triplex-next-ListItem-Background // фон строки
55
+ --triplex-next-ListItem-Background_Selected // фон выбранной строки (через ListItemSelectable + ListItemContent)
56
+ ```
57
+
58
+ Применяются в подкомпонентах `ListItemContent`/`ListItemSelectable`. Сам
59
+ `ListTableItem.module.less` задаёт только `margin-bottom: 4px` и
60
+ `border-radius: 8px` для `swipeableArea`.
61
+
62
+ ---
63
+
64
+ ## Инварианты
65
+
66
+ - **`forwardRef`** — обязателен, target — `HTMLLIElement`. Не убирать.
67
+ - **Discriminated union** `IListTableItemProps | IListTableItemSelectableProps` — selectable определяется наличием **обоих** prop'ов `onSelect` и `selected`. Не делай частичную проверку.
68
+ - **Корневой элемент `<li>`** — не менять.
69
+ - **`SwipeableArea`** всегда оборачивает контент, даже без `controlButtons` — нужно для свайп-жестов на мобильных.
70
+
71
+ ---
72
+
73
+ ## Связанные компоненты
74
+
75
+ - `ListItem` — базовый `<li>`, используется внутри.
76
+ - `ListItemContent` — контейнер контента, получает `onClick = onClickItem`.
77
+ - `ListItemSelectable` — добавляется автоматически, если переданы `selected` + `onSelect`.
78
+ - `ListItemControls` — обёртка для `controlButtons`, подключается как `rightSwipeableArea`.
79
+ - `ListItemTailRight` — декоративный «хвост» в правой части (всегда отрисовывается).
80
+ - `SwipeableArea` — внешняя зависимость, обеспечивает swipe-жесты.
81
+
82
+ ---
83
+
84
+ ## Stories
85
+
86
+ Основные истории: `stories/List/ListTableItem.stories.tsx`
87
+ Файлы примеров: `stories/List/examples/ListTableItem/`
88
+
89
+ | Story | Example file | Что демонстрирует |
90
+ |---|---|---|
91
+ | `Playground` | `Playground.tsx` | Интерактивный контроль |
92
+ | `Default` | `Default.tsx` | Базовая табличная строка с `controlButtons` |
93
+ | `Selectable` | `Selectable.tsx` | Selectable-вариант с чекбоксом |
94
+ | `WithSwipeEmulation` | `WithSwipeEmulation.tsx` | Программное управление swipe через `swipeableAreaRef` |
95
+
96
+ ---
97
+
98
+ ## История изменений
99
+
100
+ | Дата | Изменение |
101
+ |---|---|
102
+ | 2026-04-29 | Создан документ |
103
+ | 2026-07-16 | Компонент переименован `ListItemTable` → `ListTableItem`. Пропсы `IListItemTableProps`/`IListItemTableSelectableProps` → `IListTableItemProps`/`IListTableItemSelectableProps`, CSS-класс `.listItemTable` → `.listTableItem`, файлы `ListTableItem.*`. **Breaking change.** |
104
+
105
+ ---
106
+
107
+ ## Примеры использования
108
+
109
+ ### Default
110
+
111
+ `stories/List/examples/ListTableItem/Default.tsx`
112
+
113
+ ```tsx
114
+ import React from "react";
115
+ import {
116
+ EComponentSize,
117
+ EFontType,
118
+ EFontWeightText,
119
+ EMarkerStatus,
120
+ ETextSize,
121
+ List,
122
+ ListItemControlsButton,
123
+ ListItemControlsButtonDropdown,
124
+ ListTableItem,
125
+ MarkerStatus,
126
+ Text,
127
+ } from "@sberbusiness/triplex-next";
128
+ import { AttachmentStrokeSrvIcon20, DotshorizontalStrokeSrvIcon20 } from "@sberbusiness/icons-next";
129
+
130
+ export const Default = () => {
131
+ const options = [
132
+ {
133
+ id: "button-dropdown-card-option-1",
134
+ label: "Текст пункта меню 1",
135
+ onSelect: () => {},
136
+ },
137
+ {
138
+ id: "button-dropdown-card-option-2",
139
+ label: "Текст пункта меню 2",
140
+ onSelect: () => {},
141
+ },
142
+ {
143
+ id: "button-dropdown-card-option-3",
144
+ label: "Текст пункта меню 3",
145
+ onSelect: () => {},
146
+ },
147
+ ];
148
+
149
+ return (
150
+ <div style={{ maxWidth: "500px" }}>
151
+ <List>
152
+ <ListTableItem
153
+ onClickItem={() => {}}
154
+ controlButtons={
155
+ <>
156
+ <ListItemControlsButton icon={<AttachmentStrokeSrvIcon20 paletteIndex={5} />}>
157
+ Скачать
158
+ </ListItemControlsButton>
159
+ <ListItemControlsButtonDropdown
160
+ icon={<DotshorizontalStrokeSrvIcon20 paletteIndex={5} />}
161
+ options={options}
162
+ >
163
+ Действия
164
+ </ListItemControlsButtonDropdown>
165
+ </>
166
+ }
167
+ >
168
+ <Text size={ETextSize.B2} weight={EFontWeightText.SEMIBOLD}>
169
+ 1 220 000 000 RUB
170
+ </Text>
171
+
172
+ <Text size={ETextSize.B3} tag="div">
173
+ №1 ООО Голубая Роза Голубая
174
+ </Text>
175
+ <Text size={ETextSize.B3} tag="div">
176
+ Длинное назначение платежа
177
+ </Text>
178
+ <Text size={ETextSize.B3} type={EFontType.SECONDARY} tag="div">
179
+ НДС не облагается
180
+ </Text>
181
+ <Text size={ETextSize.B3} tag="div" type={EFontType.SECONDARY}>
182
+ 40702 810 2 0527 5000000 от 09.04.24
183
+ </Text>
184
+ <MarkerStatus status={EMarkerStatus.SUCCESS} size={EComponentSize.LG}>
185
+ Status text
186
+ </MarkerStatus>
187
+ </ListTableItem>
188
+ </List>
189
+ </div>
190
+ );
191
+ };
192
+ ```
193
+
194
+ ### Selectable
195
+
196
+ `stories/List/examples/ListTableItem/Selectable.tsx`
197
+
198
+ ```tsx
199
+ import React from "react";
200
+ import {
201
+ EComponentSize,
202
+ EFontType,
203
+ EFontWeightText,
204
+ EMarkerStatus,
205
+ ETextSize,
206
+ List,
207
+ ListItemControlsButton,
208
+ ListItemControlsButtonDropdown,
209
+ ListTableItem,
210
+ MarkerStatus,
211
+ Text,
212
+ } from "@sberbusiness/triplex-next";
213
+ import { AttachmentStrokeSrvIcon20, DotshorizontalStrokeSrvIcon20 } from "@sberbusiness/icons-next";
214
+
215
+ export const Selectable = () => {
216
+ const options = [
217
+ {
218
+ id: "button-dropdown-card-with-selectable-option-1",
219
+ label: "Текст пункта меню 1",
220
+ onSelect: () => alert("Выбран пункт меню 1."),
221
+ },
222
+ {
223
+ id: "button-dropdown-card-with-selectable-option-2",
224
+ label: "Текст пункта меню 2",
225
+ onSelect: () => alert("Выбран пункт меню 2."),
226
+ },
227
+ {
228
+ id: "button-dropdown-card-with-selectable-option-3",
229
+ label: "Текст пункта меню 3",
230
+ onSelect: () => alert("Выбран пункт меню 3."),
231
+ },
232
+ ];
233
+
234
+ const [selected, setSelected] = React.useState(false);
235
+
236
+ return (
237
+ <div style={{ maxWidth: "500px" }}>
238
+ <List>
239
+ <ListTableItem
240
+ selected={selected}
241
+ onSelect={setSelected}
242
+ onClickItem={() => console.log("Клик по карточке.")}
243
+ controlButtons={
244
+ <>
245
+ <ListItemControlsButton icon={<AttachmentStrokeSrvIcon20 paletteIndex={5} />}>
246
+ Скачать
247
+ </ListItemControlsButton>
248
+ <ListItemControlsButtonDropdown
249
+ icon={<DotshorizontalStrokeSrvIcon20 paletteIndex={5} />}
250
+ options={options}
251
+ >
252
+ Действия
253
+ </ListItemControlsButtonDropdown>
254
+ </>
255
+ }
256
+ >
257
+ <Text size={ETextSize.B2} weight={EFontWeightText.SEMIBOLD}>
258
+ 1 220 000 000 RUB
259
+ </Text>
260
+
261
+ <Text size={ETextSize.B3} tag="div">
262
+ №1 ООО Голубая Роза Голубая
263
+ </Text>
264
+ <Text size={ETextSize.B3} tag="div">
265
+ Длинное назначение платежа
266
+ </Text>
267
+ <Text size={ETextSize.B3} type={EFontType.SECONDARY} tag="div">
268
+ НДС не облагается
269
+ </Text>
270
+ <Text size={ETextSize.B3} tag="div" type={EFontType.SECONDARY}>
271
+ 40702 810 2 0527 5000000 от 09.04.24
272
+ </Text>
273
+ <MarkerStatus status={EMarkerStatus.SUCCESS} size={EComponentSize.LG}>
274
+ Status text
275
+ </MarkerStatus>
276
+ </ListTableItem>
277
+ </List>
278
+ </div>
279
+ );
280
+ };
281
+ ```
282
+
283
+ ### WithSwipeEmulation
284
+
285
+ `stories/List/examples/ListTableItem/WithSwipeEmulation.tsx`
286
+
287
+ ```tsx
288
+ import React from "react";
289
+ import {
290
+ EComponentSize,
291
+ EFontType,
292
+ EFontWeightText,
293
+ EMarkerStatus,
294
+ ETextSize,
295
+ ISwipeableAreaRef,
296
+ List,
297
+ ListItemControlsButton,
298
+ ListItemControlsButtonDropdown,
299
+ ListTableItem,
300
+ MarkerStatus,
301
+ Text,
302
+ } from "@sberbusiness/triplex-next";
303
+ import { AttachmentStrokeSrvIcon20, DotshorizontalStrokeSrvIcon20 } from "@sberbusiness/icons-next";
304
+
305
+ export const WithSwipeEmulation = () => {
306
+ const options = [
307
+ {
308
+ id: "button-dropdown-swipe-emulation-option-1",
309
+ label: "Текст пункта меню 1",
310
+ onSelect: () => alert("Выбран пункт меню 1."),
311
+ },
312
+ {
313
+ id: "button-dropdown-swipe-emulation-card-option-2",
314
+ label: "Текст пункта меню 2",
315
+ onSelect: () => alert("Выбран пункт меню 2."),
316
+ },
317
+ {
318
+ id: "button-dropdown-swipe-emulation-card-option-3",
319
+ label: "Текст пункта меню 3",
320
+ onSelect: () => alert("Выбран пункт меню 3."),
321
+ },
322
+ ];
323
+
324
+ const ref = React.useRef<ISwipeableAreaRef>(null);
325
+
326
+ return (
327
+ <div style={{ maxWidth: "500px" }}>
328
+ <button
329
+ onClick={() => {
330
+ if (ref.current) {
331
+ ref.current.swipeLeft();
332
+ }
333
+ }}
334
+ >
335
+ swipe
336
+ </button>
337
+ <button
338
+ onClick={() => {
339
+ if (ref.current) {
340
+ ref.current.closeSwipe();
341
+ }
342
+ }}
343
+ >
344
+ close
345
+ </button>
346
+ <br />
347
+
348
+ <List>
349
+ <ListTableItem
350
+ swipeableAreaRef={ref}
351
+ onClickItem={() => console.log("Клик по карточке.")}
352
+ controlButtons={
353
+ <>
354
+ <ListItemControlsButton icon={<AttachmentStrokeSrvIcon20 paletteIndex={5} />}>
355
+ Скачать
356
+ </ListItemControlsButton>
357
+ <ListItemControlsButtonDropdown
358
+ icon={<DotshorizontalStrokeSrvIcon20 paletteIndex={5} />}
359
+ options={options}
360
+ >
361
+ Действия
362
+ </ListItemControlsButtonDropdown>
363
+ </>
364
+ }
365
+ >
366
+ <Text size={ETextSize.B2} weight={EFontWeightText.SEMIBOLD}>
367
+ 1 220 000 000 RUB
368
+ </Text>
369
+
370
+ <Text size={ETextSize.B3} tag="div">
371
+ №1 ООО Голубая Роза Голубая
372
+ </Text>
373
+ <Text size={ETextSize.B3} tag="div">
374
+ Длинное назначение платежа
375
+ </Text>
376
+ <Text size={ETextSize.B3} type={EFontType.SECONDARY} tag="div">
377
+ НДС не облагается
378
+ </Text>
379
+ <Text size={ETextSize.B3} tag="div" type={EFontType.SECONDARY}>
380
+ 40702 810 2 0527 5000000 от 09.04.24
381
+ </Text>
382
+ <MarkerStatus status={EMarkerStatus.SUCCESS} size={EComponentSize.LG}>
383
+ Status text
384
+ </MarkerStatus>
385
+ </ListTableItem>
386
+ </List>
387
+ </div>
388
+ );
389
+ };
390
+ ```
391
+
@@ -429,7 +429,7 @@ import {
429
429
  ETextSize,
430
430
  Notification,
431
431
  Text,
432
- TextField,
432
+ TextareaField,
433
433
  } from "@sberbusiness/triplex-next";
434
434
  import { SuccessgradientStsIcon96 } from "@sberbusiness/icons-next";
435
435
 
@@ -438,35 +438,35 @@ export const FeedbackWithoutStars = () => {
438
438
  const [filledValue, setFilledValue] = useState("Нет возможности экспортировать данные из заказов");
439
439
  const [errorValue, setErrorValue] = useState("");
440
440
 
441
- const handleDefaultChange = (e: React.ChangeEvent<HTMLInputElement>) => {
442
- setDefaultValue(e.target.value);
441
+ const handleDefaultChange: React.ChangeEventHandler<HTMLTextAreaElement> = (event) => {
442
+ setDefaultValue(event.target.value);
443
443
  };
444
444
 
445
- const handleFilledChange = (e: React.ChangeEvent<HTMLInputElement>) => {
446
- setFilledValue(e.target.value);
445
+ const handleFilledChange: React.ChangeEventHandler<HTMLTextAreaElement> = (event) => {
446
+ setFilledValue(event.target.value);
447
447
  };
448
448
 
449
- const handleErrorChange = (e: React.ChangeEvent<HTMLInputElement>) => {
450
- setErrorValue(e.target.value);
449
+ const handleErrorChange: React.ChangeEventHandler<HTMLTextAreaElement> = (event) => {
450
+ setErrorValue(event.target.value);
451
451
  };
452
452
 
453
453
  return (
454
- <div style={{ display: "flex", flexDirection: "column", gap: "32px" }}>
454
+ <div style={{ display: "flex", flexDirection: "column", gap: 32 }}>
455
455
  <div>
456
- <h3 style={{ marginBottom: "16px", fontSize: "18px", fontWeight: "600" }}>Default</h3>
456
+ <h3 style={{ marginBottom: 16, fontSize: 18, fontWeight: 600 }}>Default</h3>
457
457
  <Notification withExtraBottomPadding>
458
458
  <Notification.Body>
459
459
  <Notification.Body.Header>Предложите идею</Notification.Body.Header>
460
460
  <Notification.Body.Content>
461
461
  <div>Чего не хватает вам и что оценят другие пользователи?</div>
462
- <TextField
462
+ <TextareaField
463
463
  className="notificationBodyTextArea"
464
464
  status={EFormFieldStatus.DEFAULT}
465
- inputProps={{
465
+ textareaProps={{
466
466
  value: defaultValue,
467
467
  onChange: handleDefaultChange,
468
468
  }}
469
- label={"Как мы можем улучшить сервис?"}
469
+ label="Как мы можем улучшить сервис?"
470
470
  />
471
471
  </Notification.Body.Content>
472
472
  <Notification.Body.Footer>
@@ -480,20 +480,20 @@ export const FeedbackWithoutStars = () => {
480
480
  </div>
481
481
 
482
482
  <div>
483
- <h3 style={{ marginBottom: "16px", fontSize: "18px", fontWeight: "600" }}>Filled</h3>
483
+ <h3 style={{ marginBottom: 16, fontSize: 18, fontWeight: 600 }}>Filled</h3>
484
484
  <Notification withExtraBottomPadding>
485
485
  <Notification.Body>
486
486
  <Notification.Body.Header>Предложите идею</Notification.Body.Header>
487
487
  <Notification.Body.Content>
488
488
  <div>Чего не хватает вам и что оценят другие пользователи?</div>
489
- <TextField
489
+ <TextareaField
490
490
  className="notificationBodyTextArea"
491
491
  status={EFormFieldStatus.DEFAULT}
492
- inputProps={{
492
+ textareaProps={{
493
493
  value: filledValue,
494
494
  onChange: handleFilledChange,
495
495
  }}
496
- label={undefined}
496
+ label="Как мы можем улучшить сервис?"
497
497
  />
498
498
  </Notification.Body.Content>
499
499
  <Notification.Body.Footer>
@@ -507,13 +507,13 @@ export const FeedbackWithoutStars = () => {
507
507
  </div>
508
508
 
509
509
  <div>
510
- <h3 style={{ marginBottom: "16px", fontSize: "18px", fontWeight: "600" }}>Error</h3>
510
+ <h3 style={{ marginBottom: 16, fontSize: 18, fontWeight: 600 }}>Error</h3>
511
511
  <Notification withExtraBottomPadding>
512
512
  <Notification.Body>
513
513
  <Notification.Body.Header>Предложите идею</Notification.Body.Header>
514
514
  <Notification.Body.Content>
515
515
  <div>Чего не хватает вам и что оценят другие пользователи?</div>
516
- <TextField
516
+ <TextareaField
517
517
  className="notificationBodyTextArea"
518
518
  status={EFormFieldStatus.ERROR}
519
519
  description={
@@ -521,11 +521,11 @@ export const FeedbackWithoutStars = () => {
521
521
  Введите текст сообщения.
522
522
  </Text>
523
523
  }
524
- inputProps={{
524
+ textareaProps={{
525
525
  value: errorValue,
526
526
  onChange: handleErrorChange,
527
527
  }}
528
- label={"Как мы можем улучшить сервис?"}
528
+ label="Как мы можем улучшить сервис?"
529
529
  />
530
530
  </Notification.Body.Content>
531
531
  <Notification.Body.Footer>
@@ -539,7 +539,7 @@ export const FeedbackWithoutStars = () => {
539
539
  </div>
540
540
 
541
541
  <div>
542
- <h3 style={{ marginBottom: "16px", fontSize: "18px", fontWeight: "600" }}>Success</h3>
542
+ <h3 style={{ marginBottom: 16, fontSize: 18, fontWeight: 600 }}>Success</h3>
543
543
  <Notification withExtraBottomPadding>
544
544
  <Notification.Body>
545
545
  <div className="finalStatus">
@@ -120,6 +120,7 @@ aria-атрибутов. Семантику задаёт потребитель
120
120
 
121
121
  | Дата | Изменение |
122
122
  |---|---|
123
+ | 2026-07-20 | Вертикальные padding изменены: 24px (было 32px) для desktop, 8px (было 16px) для mobile — через `@page-padding-desktop-y` / `@page-padding-mobile-y`. |
123
124
  | 2026-06-24 | Создан документ. AI-рефакторинг (JSDoc на компоненте и `IPageProps`), unit-тесты (className-merge, статические части), миграция stories на modern pattern. |
124
125
 
125
126
  ---