@sberbusiness/triplex-next-mcp-server 1.44.0-beta → 1.46.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 (89) hide show
  1. package/README.md +7 -6
  2. package/bundle/components/AlertContext.md +11 -8
  3. package/bundle/components/AlertProcess.md +13 -10
  4. package/bundle/components/Badge.md +6 -3
  5. package/bundle/components/Button.md +46 -43
  6. package/bundle/components/ButtonDropdownExtended.md +3 -2
  7. package/bundle/components/ButtonIcon.md +7 -4
  8. package/bundle/components/Calendar.md +62 -59
  9. package/bundle/components/Caption.md +26 -23
  10. package/bundle/components/CardAction.md +615 -0
  11. package/bundle/components/Checkbox.md +32 -29
  12. package/bundle/components/CheckboxTreeExtended.md +9 -5
  13. package/bundle/components/Chip.md +51 -47
  14. package/bundle/components/ChipMonthYearPicker.md +344 -0
  15. package/bundle/components/ChipMultiselect.md +1251 -0
  16. package/bundle/components/ChipOptions.md +329 -0
  17. package/bundle/components/ChipSort.md +333 -0
  18. package/bundle/components/ChipSuggest.md +587 -0
  19. package/bundle/components/CodeText.md +26 -23
  20. package/bundle/components/Col.md +1 -2
  21. package/bundle/components/CollapsibleTree.md +8 -5
  22. package/bundle/components/DateField.md +222 -303
  23. package/bundle/components/DatePickerExtended.md +3 -1
  24. package/bundle/components/Dropdown.md +33 -28
  25. package/bundle/components/EmptyView.md +12 -5
  26. package/bundle/components/FooterPage.md +6 -2
  27. package/bundle/components/FormField.md +47 -42
  28. package/bundle/components/FormGroup.md +192 -52
  29. package/bundle/components/Header.md +491 -211
  30. package/bundle/components/HeaderPage.md +6 -2
  31. package/bundle/components/HelpBox.md +7 -1
  32. package/bundle/components/ImageGallery.md +33 -34
  33. package/bundle/components/ImageGalleryExtended.md +33 -34
  34. package/bundle/components/Island.md +16 -13
  35. package/bundle/components/IslandAccordion.md +443 -152
  36. package/bundle/components/IslandWidget.md +622 -157
  37. package/bundle/components/LightBox.md +14 -12
  38. package/bundle/components/Link.md +211 -96
  39. package/bundle/components/ListActionItem.md +7 -4
  40. package/bundle/components/ListItem.md +11 -8
  41. package/bundle/components/ListItemControlsButton.md +16 -13
  42. package/bundle/components/ListItemControlsButtonDropdown.md +9 -6
  43. package/bundle/components/ListItemSelectable.md +7 -4
  44. package/bundle/components/ListMasterFooter.md +8 -5
  45. package/bundle/components/ListMasterHeader.md +8 -5
  46. package/bundle/components/ListSortableItem.md +11 -8
  47. package/bundle/components/ListTableItem.md +7 -4
  48. package/bundle/components/LoaderMiddle.md +7 -4
  49. package/bundle/components/LoaderScreen.md +11 -8
  50. package/bundle/components/LoaderSmall.md +7 -4
  51. package/bundle/components/Marker.md +184 -69
  52. package/bundle/components/MarkerStatus.md +206 -88
  53. package/bundle/components/MaskedField.md +4 -5
  54. package/bundle/components/MasterTable.md +602 -0
  55. package/bundle/components/ModalWindow.md +7 -4
  56. package/bundle/components/MonthYearField.md +3 -1
  57. package/bundle/components/MultiselectField.md +2183 -132
  58. package/bundle/components/Notification.md +12 -9
  59. package/bundle/components/Overlay.md +9 -4
  60. package/bundle/components/Page.md +2 -2
  61. package/bundle/components/Pagination.md +15 -8
  62. package/bundle/components/Row.md +1 -1
  63. package/bundle/components/SelectExtendedField.md +3 -3
  64. package/bundle/components/SelectField.md +466 -148
  65. package/bundle/components/SliderExtended.md +39 -36
  66. package/bundle/components/SmallInput.md +194 -51
  67. package/bundle/components/Suggest.md +535 -99
  68. package/bundle/components/SwipeableArea.md +428 -79
  69. package/bundle/components/TableBasic.md +19 -11
  70. package/bundle/components/TabsExtended.md +24 -21
  71. package/bundle/components/Tag.md +6 -2
  72. package/bundle/components/Text.md +28 -25
  73. package/bundle/components/TextField.md +3 -4
  74. package/bundle/components/ThemeProvider.md +50 -1
  75. package/bundle/components/Title.md +26 -23
  76. package/bundle/components/Tooltip.md +24 -21
  77. package/bundle/components/TopOverlay.md +7 -4
  78. package/bundle/guides/codestyle.md +3 -0
  79. package/bundle/guides/context.md +84 -12
  80. package/bundle/guides/guidelines.md +321 -0
  81. package/bundle/guides/template.md +22 -12
  82. package/bundle/manifest.json +75 -17
  83. package/bundle/release-notes/1.45.0.mdx +117 -0
  84. package/bundle/release-notes/1.46.0.mdx +66 -0
  85. package/bundle/release-notes/1.47.0.mdx +7 -0
  86. package/bundle/tokens.json +6362 -0
  87. package/dist/index.js +177 -28
  88. package/dist/index.js.map +1 -1
  89. package/package.json +1 -1
@@ -1,11 +1,9 @@
1
1
  ---
2
2
  component: SwipeableArea
3
- category: Mobile / Layout
4
- figma-node: ""
5
- figma-file: ""
6
- related: [MobileView]
3
+ category: SwipeableArea
4
+ related: [ListTableItem]
7
5
  tokens: []
8
- stories: ""
6
+ stories: stories/SwipeableArea/SwipeableArea.stories.tsx
9
7
  version: "1.0"
10
8
  ---
11
9
 
@@ -13,127 +11,190 @@ version: "1.0"
13
11
 
14
12
  ## Назначение
15
13
 
16
- Мобильный контейнер с поддержкой horizontal-swipe: при свайпе влево открывается
17
- `rightSwipeableArea` (обычно — action-панель), при свайпе вправо —
18
- `leftSwipeableArea`. Основной контент смещается `transform: translateX`.
19
- Работает только через touch-события (нет mouse drag).
14
+ Контейнер карточки с реализацией горизонтального свайпа: движение пальца
15
+ сдвигает контент и открывает боковую область с действиями. Свайп влево
16
+ открывает `rightSwipeableArea`, свайп вправо — `leftSwipeableArea`.
20
17
 
21
- Используй когда: нужен iOS-подобный swipe-to-reveal в списке (удалить/
22
- архивировать и т.п.) на мобильных устройствах.
23
- Не используй когда: нужен desktop drag — `SwipeableArea` не обрабатывает
24
- mouse events.
18
+ Собственного оформления у компонента нет — только позиционирование боковых
19
+ областей, transition сдвига и блокировки скролла и кликов на время жеста. Фон,
20
+ отступы и содержимое карточки приходят снаружи (обычно `ListItemContent`).
25
21
 
26
- ---
27
-
28
- ## Файловая структура
22
+ Используй когда: на мобильной ширине нужно спрятать действия карточки под
23
+ свайп — так устроены элементы списков (`ListItem`, `ListTableItem`).
29
24
 
30
- ```text
31
- src/components/SwipeableArea/
32
- ├── SwipeableArea.tsx # forwardRef<ISwipeableAreaRef, ISwipeableAreaProps>
33
- ├── index.ts
34
- └── styles/SwipeableArea.module.less
35
- ```
25
+ Не используй когда: действия должны быть доступны без тач-жеста. Свайп
26
+ воспроизводится только пальцем: ни мышь, ни клавиатура его не выполняют,
27
+ а компонент не даёт визуального триггера для открытия области. Для готового
28
+ табличного элемента списка со свайпом бери `ListTableItem` — он сам собирает
29
+ `SwipeableArea` и `ListItemControls`.
36
30
 
37
31
  ---
38
32
 
39
33
  ## Варианты и props
40
34
 
41
- ### `ISwipeableAreaProps`
35
+ `ISwipeableAreaProps` расширяет `React.HTMLAttributes<HTMLDivElement>` —
36
+ `...rest` уходит на корневой `<div>`.
37
+
38
+ ### Обязательные props
42
39
 
43
40
  | Prop | Тип | Описание |
44
41
  |---|---|---|
45
- | `children` | `ReactNode` | Основной контент карточки. |
46
- | `leftSwipeableArea?` | `ReactNode` | Контент, появляющийся при свайпе вправо. Если не задан — свайп вправо игнорируется. |
47
- | `rightSwipeableArea?` | `ReactNode` | Контент, появляющийся при свайпе влево. Если не задан — свайп влево игнорируется. |
48
- | `...HTMLAttributes<HTMLDivElement>` | — | Прокидываются на корневой div. |
49
-
50
- ### `ISwipeableAreaRef` (imperative API)
51
-
52
- ```ts
53
- interface ISwipeableAreaRef {
54
- closeSwipe(): void; // закрыть любую открытую панель
55
- swipeLeft(): void; // открыть rightSwipeableArea (свайп влево)
56
- swipeRight(): void; // открыть leftSwipeableArea (свайп вправо)
57
- }
58
- ```
42
+ | `children` | `React.ReactNode` | Контент карточки. Лежит поверх боковых областей и сдвигается при свайпе |
59
43
 
60
- Доступ через `React.useRef<ISwipeableAreaRef>` + `ref={...}`.
44
+ ### Опциональные props
61
45
 
62
- ---
46
+ | Prop | Тип | По умолчанию | Описание |
47
+ |---|---|---|---|
48
+ | `leftSwipeableArea` | `React.ReactNode` | — | Контент, открывающийся свайпом **вправо**. Если не передан, свайп вправо ничего не двигает |
49
+ | `rightSwipeableArea` | `React.ReactNode` | — | Контент, открывающийся свайпом **влево**. Если не передан, свайп влево ничего не двигает |
50
+ | `onSwipeLeft` | `() => void` | — | Открылась `rightSwipeableArea`. Вызывается только на открытии и только если свайп длиннее порога |
51
+ | `onSwipeRight` | `() => void` | — | Открылась `leftSwipeableArea`. Те же условия |
52
+ | `className` | `string` | — | Мерджится с собственным классом через `clsx` |
63
53
 
64
- ## Логика
54
+ Закрывающий свайп (когда область уже открыта) колбэки **не** вызывает — они
55
+ сообщают только о факте открытия.
65
56
 
66
- ### Константы
57
+ ### Императивный ref — `ISwipeableAreaRef`
67
58
 
68
- | Имя | Значение | Назначение |
69
- |---|---|---|
70
- | `SWIPE_MIN_DISTANCE` | `24` (px) | Порог, ниже которого свайп считается «недотянутым» и контент возвращается в исходное положение. |
59
+ `ref` компонента — не DOM-элемент, а объект с методами. Единственный способ
60
+ подвинуть контент без тач-жеста.
71
61
 
72
- ### Определение направления (scroll vs swipe)
62
+ | Метод | Что делает |
63
+ |---|---|
64
+ | `swipeLeft()` | Открывает `rightSwipeableArea` |
65
+ | `swipeRight()` | Открывает `leftSwipeableArea` |
66
+ | `closeSwipe()` | Закрывает открытую область |
67
+
68
+ Метод молча ничего не делает, если соответствующая область не отрисована.
69
+ Колбэки `onSwipeLeft` / `onSwipeRight` при вызове методов **не** срабатывают.
73
70
 
74
- При первом `touchmove`:
75
- - `|deltaY| > |deltaX|` → `dragType = vertical` (скролл), свайп не обрабатывается.
76
- - иначе → `horizontal` (свайп), контент двигается.
71
+ ### Как обрабатывается жест
77
72
 
78
- При отпускании (`touchend` на document) — сброс `dragType`.
73
+ | Фаза | Поведение |
74
+ |---|---|
75
+ | `touchstart` на контенте | Запоминаются координаты пальца и текущий сдвиг контента; на документ вешается разовый слушатель `touchend` |
76
+ | Первое `touchmove` | Определяется тип жеста: `abs(deltaY) > abs(deltaX)` — это скролл, контент до конца жеста не двигается; иначе — свайп |
77
+ | Последующие `touchmove` | Контент едет за пальцем, но не дальше ширины открываемой области; на время свайпа у контента `touch-action: none` |
78
+ | `touchend` (на документе) | Если длина свайпа больше `SWIPE_MIN_DISTANCE` (24px) — область открывается или закрывается, иначе контент возвращается в положение, с которого начинался жест |
79
+ | `touchstart` вне компонента | Открытая область закрывается |
79
80
 
80
- ### Завершение свайпа (`handleSwipe`)
81
+ Мультитач (`event.touches.length !== 1`) игнорируется при перемещении: на
82
+ старте координаты запоминаются всегда, но контент не поедет, пока в жесте
83
+ не останется ровно один палец.
81
84
 
82
- Запускается в `useEffect` при `dragType → undefined && contentTranslateX !== start`.
83
- Логика зависит от начального состояния:
84
- - Было закрыто, сдвиг > порога → открыть соответствующую панель (translateX = ±width).
85
- - Было закрыто, сдвиг < порога → вернуть к 0.
86
- - Было открыто — если сдвиг в сторону закрытия превышает порог → закрыть, иначе — вернуть к открытому состоянию.
85
+ Прозрачность боковой области считается как `|сдвиг| / ширина области`, поэтому
86
+ она проявляется по мере свайпа. Ширина берётся из `getBoundingClientRect()` в
87
+ момент жеста — область с нулевой шириной открыться не сможет; для неё
88
+ `getSwipeableAreaOpacity` возвращает `1`, как в состоянии покоя, вместо `NaN`
89
+ от деления на ноль.
87
90
 
88
- ### Opacity side-панелей
91
+ Логика жеста вынесена в чистые функции `resolveSwipeMove`, `resolveSwipeEnd` и
92
+ `getSwipeableAreaOpacity` (`src/components/SwipeableArea/utils.ts`) и покрыта
93
+ unit-тестами. Компонент
94
+ хранит только состояние: сдвиг контента, тип жеста и флаг анимации.
89
95
 
90
- `opacity = |contentTranslateX| / panelWidth` — плавное появление.
96
+ ### Известные ограничения
91
97
 
92
- ### Outside-touch
98
+ Пункт существует с первой версии компонента и не менялся при AI-рефакторинге —
99
+ при правках его стоит держать в голове.
93
100
 
94
- `document.addEventListener("touchstart")` закрывает swipe при tap'е вне контейнера.
101
+ - **Сдвиг контента не сбрасывается, если боковая область перестала
102
+ передаваться.** Открыли `leftSwipeableArea`, затем перестали передавать этот
103
+ prop — область размонтируется, а контент останется сдвинутым, оставив пустую
104
+ полосу внутри `overflow: hidden`. Закрыть можно через `closeSwipe()`.
95
105
 
96
- ### Анимация
106
+ ---
97
107
 
98
- CSS-класс `swipeAnimationFinish` (`animating = true`) → CSS transition.
99
- `animating = false` в `onTransitionEnd`.
108
+ ## Дизайн-токены
100
109
 
101
- Во время горизонтального drag:
102
- - `disableScroll` класс → не скроллится страница.
103
- - `disablePointerEvents` класс → элементы внутри контента не реагируют на клик.
110
+ Токенов нет. `SwipeableArea.module.less` содержит только позиционирование,
111
+ `transition` сдвига и `touch-action`. Цвета и фон приходят от контента —
112
+ например, `ListItem.Background` у `ListItemContent`.
104
113
 
105
114
  ---
106
115
 
107
116
  ## Инварианты
108
117
 
109
- - **`forwardRef<ISwipeableAreaRef>`** — ref отдаёт imperative API, НЕ DOM-элемент. Это нестандартно, не менять без миграции потребителей.
110
- - **Только touch-события** — mouse drag не поддерживается намеренно (компонент только для mobile).
111
- - **`SWIPE_MIN_DISTANCE = 24`** — менять с проверкой UX на реальных устройствах.
112
- - **`dragType === vertical`** → свайп игнорируется до конца жеста (пока пользователь не отпустит палец). Это предотвращает «дребезг» при диагональных движениях.
113
- - **`leftSwipeableArea` / `rightSwipeableArea` рендерятся ТОЛЬКО если переданы** (`typeof ... !== "undefined"`) — не оставлять пустые div'ы.
114
- - **`useImperativeHandle` переопределяет ref-форму** — потребитель не получит HTMLDivElement.
115
- - **Outside-tap закрывает swipe** (listener на document) — не отключать, это часть UX.
116
- - **`disablePointerEvents` активен, пока `contentTranslateX !== 0`** — дети не ловят клики при открытой side-панели. Взаимодействие идёт через кнопки в самой side-панели.
118
+ - **`forwardRef` на компоненте — не убирать.** Ref типизирован
119
+ `ISwipeableAreaRef` и наполняется через `useImperativeHandle`: получить через
120
+ него корневой `<div>` нельзя, и менять это — breaking change для
121
+ `ListTableItem` и потребителей библиотеки.
122
+ - **Публичные экспорты barrel** (`src/components/SwipeableArea/index.ts`):
123
+ `SwipeableArea`, `ISwipeableAreaProps`, `ISwipeableAreaRef`. Переименование —
124
+ breaking change. `utils.ts` — внутренний модуль, в barrel не попадает.
125
+ - **`displayName = "SwipeableArea"`.**
126
+ - **Корневой DOM — `<div>`.** На него уходят `className`, `...rest` и `data-tx`;
127
+ тег не настраивается.
128
+ - **Порог свайпа `SWIPE_MIN_DISTANCE = 24` — внутренняя константа.** Пропа для
129
+ него нет; изменение значения меняет ощущение жеста у всех потребителей.
130
+ - **Боковые области рендерятся, только если соответствующий prop передан**
131
+ (`!== undefined`), и остаются в DOM всё время жизни компонента. Скрытость
132
+ закрытой области — следствие `opacity` и перекрытия контентом, а не
133
+ размонтирования.
134
+ - **`touch-action: pan-y` на контенте и `touch-action: none` во время
135
+ горизонтального свайпа** — без этого браузер уводит жест в скролл страницы.
136
+ - **`::after` поверх контента при открытой области** — гасит нажатия на
137
+ вложенные элементы карточки, пока область открыта. Убрать — значит разрешить
138
+ случайные клики по карточке при открытых кнопках.
139
+ - **Слушатели документа снимаются при размонтировании** (`touchstart` — всегда,
140
+ `touchend` — если компонент размонтирован в середине жеста).
141
+ - **React 17-совместимость.** Компонент уходит в ветку `release-0`; React
142
+ 18-only API (`useId`, `useSyncExternalStore`, `useInsertionEffect`)
143
+ использовать нельзя.
117
144
 
118
145
  ---
119
146
 
120
147
  ## Accessibility
121
148
 
122
- - Компонент не добавляет ARIA — это чисто-тактильный жест.
123
- - Для screen-reader пользователей side-панели должны быть доступны альтернативным способом (обычно — через action button в самом контенте, `overlayMenu` и т.п.).
124
- - Imperative API (`swipeLeft`/`swipeRight`) — используется для программного открытия (например, onboarding-туториал).
149
+ Собственных ARIA-атрибутов компонент не выставляет и текстов не хардкодит —
150
+ библиотека мультиязычная, а содержимое боковых областей приходит снаружи.
151
+
152
+ Что важно знать потребителю:
153
+
154
+ - **Клавиатурного эквивалента свайпа нет.** Компонент слушает только `touch`-
155
+ события. Если действия из боковой области критичны, продублируй их доступным
156
+ элементом или открывай область через `ISwipeableAreaRef`.
157
+ - **Кнопки боковых областей фокусируются по Tab и в закрытом состоянии** —
158
+ области всегда в DOM, а `opacity: 0` фокус не забирает. Это осознанный
159
+ компромисс текущей реализации: если такой обход недопустим, скрывай
160
+ содержимое области на своей стороне.
161
+ - **Открытая область не помечается для скринридера.** `::after` блокирует
162
+ только указатель; порядок чтения и фокус остаются прежними.
125
163
 
126
164
  ---
127
165
 
128
166
  ## Связанные компоненты
129
167
 
130
- - `MobileView` — оборачивает SwipeableArea для условного рендера только на мобильных viewport'ах.
168
+ - `ListTableItem` (`src/components/List`) — единственный потребитель внутри
169
+ библиотеки, который опирается на императивный контракт: он всегда оборачивает
170
+ свой контент в `SwipeableArea`, прокидывает наружу `swipeableAreaRef` типа
171
+ `React.Ref<ISwipeableAreaRef>` и подключает `controlButtons` как
172
+ `rightSwipeableArea`. Любая правка `ISwipeableAreaRef` должна сверяться с ним.
173
+ - `ListItemControls`, `ListItemControlsButton`, `ListItemControlsButtonDropdown`
174
+ (`src/components/List`) — стандартное наполнение боковой области: контейнер
175
+ кнопок действий и сами кнопки.
176
+ - `ListItemTailLeft` / `ListItemTailRight` (`src/components/List`) —
177
+ декоративные «хвосты», подсказывающие, что карточку можно свайпнуть.
178
+ Размещаются внутри `SwipeableArea` рядом с контентом.
179
+ - `ListItem` / `ListItemContent` (`src/components/List`) — типичное окружение:
180
+ `ListItem` даёт элемент списка, `ListItemContent` — фон и отступы карточки,
181
+ без которых боковые области просвечивали бы сквозь контент.
131
182
 
132
183
  ---
133
184
 
134
185
  ## Stories
135
186
 
136
- Отдельных stories нет (mobile-only компонент, тестируется в составе mobile-экранов).
187
+ Основные истории: `stories/SwipeableArea/SwipeableArea.stories.tsx`
188
+ Файлы примеров: `stories/SwipeableArea/examples/`
189
+
190
+ | Story | Example file | Что демонстрирует |
191
+ |---|---|---|
192
+ | `Playground` | `Playground.tsx` | Переключение боковых областей, колбэки в Actions, кнопки императивного API |
193
+ | `Default` | `Default.tsx` | Минимальная карточка: свайп влево открывает кнопку действия |
194
+ | `With both areas` | `WithBothAreas.tsx` | Обе боковые области сразу |
195
+ | `Imperative API` | `ImperativeApi.tsx` | `swipeLeft` / `swipeRight` / `closeSwipe` через `ISwipeableAreaRef` |
196
+ | `Example` | `Example.tsx` | Список платежей, где открытой остаётся только одна карточка |
197
+ | `VisualTests` | `VisualTests.tsx` | Скриншоты закрытого состояния и обеих открытых областей |
137
198
 
138
199
  ---
139
200
 
@@ -141,4 +202,292 @@ CSS-класс `swipeAnimationFinish` (`animating = true`) → CSS transition.
141
202
 
142
203
  | Дата | Изменение |
143
204
  |---|---|
144
- | 2026-04-18 | Создан документ |
205
+ | 2026-08-31 | Создан документ. Зафиксированы: контракт императивного `ref` вместо DOM-ref, порог свайпа 24px, правила определения жеста и мультитача, зависимость открытия от ширины боковой области, отсутствие клавиатурного эквивалента и фокусируемость кнопок закрытой области |
206
+ | 2026-09-02 | Прозрачность боковой области нулевой ширины больше не даёт `NaN` — `getSwipeableAreaOpacity` возвращает `1`. Пункт убран из «Известных ограничений» |
207
+
208
+ ---
209
+
210
+ ## Примеры использования
211
+
212
+ ### Default
213
+
214
+ `stories/SwipeableArea/examples/Default.tsx`
215
+
216
+ ```tsx
217
+ import React from "react";
218
+ import {
219
+ List,
220
+ ListItem,
221
+ ListItemContent,
222
+ ListItemControls,
223
+ ListItemControlsButton,
224
+ ListItemTailRight,
225
+ SwipeableArea,
226
+ } from "@sberbusiness/triplex-next";
227
+ import { AttachmentStrokeSrvIcon20 } from "@sberbusiness/icons-next";
228
+
229
+ export const Default = () => (
230
+ <div style={{ maxWidth: "500px" }}>
231
+ <List>
232
+ <ListItem>
233
+ <SwipeableArea
234
+ rightSwipeableArea={
235
+ <ListItemControls>
236
+ <ListItemControlsButton
237
+ icon={<AttachmentStrokeSrvIcon20 paletteIndex={5} />}
238
+ onClick={() => {}}
239
+ >
240
+ Скачать
241
+ </ListItemControlsButton>
242
+ </ListItemControls>
243
+ }
244
+ onSwipeLeft={() => {}}
245
+ >
246
+ <ListItemTailRight />
247
+ {/* Минимальная высота, из-за блока с кнопками, появляющегося при свайпе. */}
248
+ <ListItemContent style={{ minHeight: "56px" }}>Свайп влево открывает кнопки</ListItemContent>
249
+ </SwipeableArea>
250
+ </ListItem>
251
+ </List>
252
+ </div>
253
+ );
254
+ ```
255
+
256
+ ### With both areas
257
+
258
+ `stories/SwipeableArea/examples/WithBothAreas.tsx`
259
+
260
+ ```tsx
261
+ import React from "react";
262
+ import {
263
+ List,
264
+ ListItem,
265
+ ListItemContent,
266
+ ListItemControls,
267
+ ListItemControlsButton,
268
+ ListItemTailLeft,
269
+ ListItemTailRight,
270
+ SwipeableArea,
271
+ } from "@sberbusiness/triplex-next";
272
+ import { AttachmentStrokeSrvIcon20, DefaulticonStrokePrdIcon20 } from "@sberbusiness/icons-next";
273
+
274
+ export const WithBothAreas = () => (
275
+ <div style={{ maxWidth: "500px" }}>
276
+ <List>
277
+ <ListItem>
278
+ <SwipeableArea
279
+ leftSwipeableArea={
280
+ <ListItemControls>
281
+ <ListItemControlsButton
282
+ icon={<DefaulticonStrokePrdIcon20 paletteIndex={5} />}
283
+ onClick={() => {}}
284
+ >
285
+ В архив
286
+ </ListItemControlsButton>
287
+ </ListItemControls>
288
+ }
289
+ rightSwipeableArea={
290
+ <ListItemControls>
291
+ <ListItemControlsButton
292
+ icon={<AttachmentStrokeSrvIcon20 paletteIndex={5} />}
293
+ onClick={() => {}}
294
+ >
295
+ Скачать
296
+ </ListItemControlsButton>
297
+ </ListItemControls>
298
+ }
299
+ onSwipeLeft={() => {}}
300
+ onSwipeRight={() => {}}
301
+ >
302
+ <ListItemTailLeft />
303
+ <ListItemTailRight />
304
+ {/* Минимальная высота, из-за блока с кнопками, появляющегося при свайпе. */}
305
+ <ListItemContent style={{ minHeight: "56px" }}>Свайп влево и вправо</ListItemContent>
306
+ </SwipeableArea>
307
+ </ListItem>
308
+ </List>
309
+ </div>
310
+ );
311
+ ```
312
+
313
+ ### Imperative API
314
+
315
+ `stories/SwipeableArea/examples/ImperativeApi.tsx`
316
+
317
+ ```tsx
318
+ import React, { useRef } from "react";
319
+ import {
320
+ Button,
321
+ EButtonTheme,
322
+ EComponentSize,
323
+ ISwipeableAreaRef,
324
+ List,
325
+ ListItem,
326
+ ListItemContent,
327
+ ListItemControls,
328
+ ListItemControlsButton,
329
+ ListItemTailLeft,
330
+ ListItemTailRight,
331
+ SwipeableArea,
332
+ } from "@sberbusiness/triplex-next";
333
+ import { AttachmentStrokeSrvIcon20, DefaulticonStrokePrdIcon20 } from "@sberbusiness/icons-next";
334
+
335
+ export const ImperativeApi = () => {
336
+ const swipeableAreaRef = useRef<ISwipeableAreaRef>(null);
337
+
338
+ return (
339
+ <div style={{ maxWidth: "500px" }}>
340
+ <div style={{ display: "flex", gap: "8px", marginBottom: "16px" }}>
341
+ <Button
342
+ theme={EButtonTheme.SECONDARY}
343
+ size={EComponentSize.SM}
344
+ onClick={() => swipeableAreaRef.current?.swipeRight()}
345
+ >
346
+ swipeRight
347
+ </Button>
348
+ <Button
349
+ theme={EButtonTheme.SECONDARY}
350
+ size={EComponentSize.SM}
351
+ onClick={() => swipeableAreaRef.current?.swipeLeft()}
352
+ >
353
+ swipeLeft
354
+ </Button>
355
+ <Button
356
+ theme={EButtonTheme.SECONDARY}
357
+ size={EComponentSize.SM}
358
+ onClick={() => swipeableAreaRef.current?.closeSwipe()}
359
+ >
360
+ closeSwipe
361
+ </Button>
362
+ </div>
363
+
364
+ <List>
365
+ <ListItem>
366
+ <SwipeableArea
367
+ ref={swipeableAreaRef}
368
+ leftSwipeableArea={
369
+ <ListItemControls>
370
+ <ListItemControlsButton
371
+ icon={<DefaulticonStrokePrdIcon20 paletteIndex={5} />}
372
+ onClick={() => {}}
373
+ >
374
+ В архив
375
+ </ListItemControlsButton>
376
+ </ListItemControls>
377
+ }
378
+ rightSwipeableArea={
379
+ <ListItemControls>
380
+ <ListItemControlsButton
381
+ icon={<AttachmentStrokeSrvIcon20 paletteIndex={5} />}
382
+ onClick={() => {}}
383
+ >
384
+ Скачать
385
+ </ListItemControlsButton>
386
+ </ListItemControls>
387
+ }
388
+ >
389
+ <ListItemTailLeft />
390
+ <ListItemTailRight />
391
+ {/* Минимальная высота, из-за блока с кнопками, появляющегося при свайпе. */}
392
+ <ListItemContent style={{ minHeight: "56px" }}>Управление через ref</ListItemContent>
393
+ </SwipeableArea>
394
+ </ListItem>
395
+ </List>
396
+ </div>
397
+ );
398
+ };
399
+ ```
400
+
401
+ ### Example
402
+
403
+ `stories/SwipeableArea/examples/Example.tsx`
404
+
405
+ ```tsx
406
+ import React, { useRef } from "react";
407
+ import {
408
+ EFontType,
409
+ EFontWeightText,
410
+ ETextSize,
411
+ ISwipeableAreaRef,
412
+ List,
413
+ ListItem,
414
+ ListItemContent,
415
+ ListItemControls,
416
+ ListItemControlsButton,
417
+ ListItemControlsButtonDropdown,
418
+ ListItemTailRight,
419
+ SwipeableArea,
420
+ Text,
421
+ } from "@sberbusiness/triplex-next";
422
+ import { AttachmentStrokeSrvIcon20, DotshorizontalStrokeSrvIcon20 } from "@sberbusiness/icons-next";
423
+
424
+ const PAYMENTS = [
425
+ { id: "swipeable-area-payment-1", amount: "1 220 000,00 ₽", counterparty: "ООО «Голубая роза»" },
426
+ { id: "swipeable-area-payment-2", amount: "84 300,00 ₽", counterparty: "ООО «Северный ветер»" },
427
+ { id: "swipeable-area-payment-3", amount: "12 500,00 ₽", counterparty: "ИП Иванов И. И." },
428
+ ];
429
+
430
+ export const Example = () => {
431
+ const swipeableAreaRefs = useRef<Record<string, ISwipeableAreaRef | null>>({});
432
+
433
+ // Открытой остаётся только одна карточка: свайп по одной закрывает остальные.
434
+ const handleSwipeLeft = (paymentId: string) => {
435
+ Object.entries(swipeableAreaRefs.current).forEach(([id, swipeableArea]) => {
436
+ if (id !== paymentId) {
437
+ swipeableArea?.closeSwipe();
438
+ }
439
+ });
440
+ };
441
+
442
+ return (
443
+ <div style={{ maxWidth: "500px" }}>
444
+ <List>
445
+ {PAYMENTS.map((payment) => (
446
+ <ListItem key={payment.id}>
447
+ <SwipeableArea
448
+ ref={(instance) => {
449
+ swipeableAreaRefs.current[payment.id] = instance;
450
+ }}
451
+ rightSwipeableArea={
452
+ <ListItemControls>
453
+ <ListItemControlsButton
454
+ icon={<AttachmentStrokeSrvIcon20 paletteIndex={5} />}
455
+ onClick={() => {}}
456
+ >
457
+ Скачать
458
+ </ListItemControlsButton>
459
+ <ListItemControlsButtonDropdown
460
+ icon={<DotshorizontalStrokeSrvIcon20 paletteIndex={5} />}
461
+ options={[
462
+ { id: `${payment.id}-option-1`, label: "Повторить", onSelect: () => {} },
463
+ { id: `${payment.id}-option-2`, label: "Удалить", onSelect: () => {} },
464
+ ]}
465
+ >
466
+ Действия
467
+ </ListItemControlsButtonDropdown>
468
+ </ListItemControls>
469
+ }
470
+ onSwipeLeft={() => handleSwipeLeft(payment.id)}
471
+ >
472
+ <ListItemTailRight />
473
+ {/* Минимальная высота, из-за блока с кнопками, появляющегося при свайпе. */}
474
+ <ListItemContent style={{ minHeight: "56px" }}>
475
+ <Text size={ETextSize.B2} weight={EFontWeightText.SEMIBOLD} tag="div">
476
+ {payment.amount}
477
+ </Text>
478
+ <Text size={ETextSize.B3} tag="div">
479
+ {payment.counterparty}
480
+ </Text>
481
+ <Text size={ETextSize.B3} type={EFontType.SECONDARY} tag="div">
482
+ Оплата по счёту от 09.04.24
483
+ </Text>
484
+ </ListItemContent>
485
+ </SwipeableArea>
486
+ </ListItem>
487
+ ))}
488
+ </List>
489
+ </div>
490
+ );
491
+ };
492
+ ```
493
+
@@ -3,10 +3,10 @@ component: TableBasic
3
3
  category: Table
4
4
  related: [MasterTable, ListTableItem, LoaderScreen, LoaderMiddle, Text]
5
5
  tokens:
6
- - --triplex-next-TableBasic-Header_Background
7
- - --triplex-next-TableBasic-Color
8
- - --triplex-next-TableBasic-Background_Hover
9
- - --triplex-next-TableBasic-Background_Selected
6
+ - TableBasic.Header_Background
7
+ - TableBasic.Color
8
+ - TableBasic.Background_Hover
9
+ - TableBasic.Background_Selected
10
10
  stories: stories/TableBasic/TableBasic.stories.tsx
11
11
  version: "1.0"
12
12
  ---
@@ -93,15 +93,23 @@ version: "1.0"
93
93
 
94
94
  ## Дизайн-токены
95
95
 
96
- ```
97
- --triplex-next-TableBasic-Header_Background
98
- --triplex-next-TableBasic-Color
99
- --triplex-next-TableBasic-Background_Hover
100
- --triplex-next-TableBasic-Background_Selected
96
+ Переопределяются через `ThemeProvider` (prop `tokens`) — см. `ThemeProvider-ai.md` →
97
+ «Как переопределять токены». Значения по умолчанию — `src/components/DesignTokens/components/TableBasic.ts`.
98
+
99
+ ```text
100
+ TableBasic.Header_Background
101
+ TableBasic.Color
102
+ TableBasic.Background_Hover
103
+ TableBasic.Background_Selected
101
104
  ```
102
105
 
103
- Остальные токены группы `TableBasic-*` (`TableFooter_*`, `TableBasicSettings_*`)
104
- принадлежат соседним компонентам семейства, а не самому `TableBasic`.
106
+ В группе `TableBasic` лежат и токены соседних компонентов семейства —
107
+ `TableFooter_*` применяются в `TableFooter`, `TableBasicSettings_*` — в
108
+ `TableBasicSettings`. Переопределяются они там же, в группе `TableBasic`:
109
+ имя группы — не имя компонента. Здесь они не перечислены, потому что сам
110
+ `TableBasic` их не использует, а собственных AI.md у этих компонентов пока нет —
111
+ поэтому `syncAiMdTokens` и предупреждает, что токены есть в LESS директории,
112
+ но не описаны ни в одном документе.
105
113
 
106
114
  ---
107
115