@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,259 @@
1
+ ---
2
+ component: SmartSpot
3
+ category: SmartSpot
4
+ related: []
5
+ tokens:
6
+ - SmartSpot.Success_Spot1_Color
7
+ - SmartSpot.Success_Spot2_Color
8
+ - SmartSpot.Success_Spot3_Color
9
+ - SmartSpot.Success_Spot4_Color
10
+ - SmartSpot.Warning_Spot1_Color
11
+ - SmartSpot.Warning_Spot2_Color
12
+ - SmartSpot.Warning_Spot3_Color
13
+ - SmartSpot.Warning_Spot4_Color
14
+ - SmartSpot.Error_Spot1_Color
15
+ - SmartSpot.Error_Spot2_Color
16
+ - SmartSpot.Error_Spot3_Color
17
+ - SmartSpot.Error_Spot4_Color
18
+ - SmartSpot.Waiting_Spot1_Color
19
+ - SmartSpot.Waiting_Spot2_Color
20
+ - SmartSpot.Waiting_Spot3_Color
21
+ - SmartSpot.Waiting_Spot4_Color
22
+ stories: stories/SmartSpot/SmartSpot.stories.tsx
23
+ version: "1.0"
24
+ ---
25
+
26
+ # SmartSpot
27
+
28
+ ## Назначение
29
+
30
+ Декоративная анимированная подложка статуса. Рисует на прозрачном фоне четыре пятна в цветах статуса; сплошной заливки у компонента нет — фон под пятнами задаёт родитель. Слой пятен размыт гауссом (`filter: blur()`) и медленно двигается по выбранному пресету. Компонент заполняет родителя (`width/height: 100%`, `overflow: hidden`), а `children` выводит поверх подложки.
31
+
32
+ Используй когда: нужен выразительный фон для экрана или карточки с результатом операции — успех, предупреждение, ошибка, ожидание. Например, итоговый экран платежа или промо-блок со статусом.
33
+
34
+ Не используй когда:
35
+
36
+ - Нужен компактный индикатор статуса — возьми `Marker`, `MarkerStatus` или `Badge`.
37
+ - Нужно сообщение, которое читает пользователь, — используй `AlertProcess` или `AlertContext`. SmartSpot ничего не сообщает сам: это только фон.
38
+ - Нужна обычная статичная заливка — задай `background` контейнеру. SmartSpot тратит ресурсы на `filter: blur()` большого радиуса и rAF-анимацию.
39
+
40
+ ---
41
+
42
+ ## Варианты и props
43
+
44
+ ### Обязательные props
45
+
46
+ | Prop | Тип | Описание |
47
+ | ------ | ---------------- | --------------------------------------- |
48
+ | `type` | `ESmartSpotType` | Тип: задаёт цвета пятен и их геометрию. |
49
+
50
+ ### Опциональные props
51
+
52
+ | Prop | Тип | По умолчанию | Описание |
53
+ | ----------- | --------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------- |
54
+ | `animation` | `ESmartSpotAnimation` | `DRIFT` | Пресет анимации. |
55
+ | `blur` | `number` | `60` | Радиус размытия слоя пятен в CSS px, передаётся в `filter: blur()` как есть. |
56
+ | `distance` | `number` | `50` | Радиус эллипса движения по горизонтали, px. Вертикальный радиус — половина горизонтального. Влияет только на `DRIFT`. |
57
+ | `duration` | `number` | `6000` | Длительность одного цикла, мс. Для `NONE` игнорируется. |
58
+ | `shape` | `ESmartSpotShape` | `CIRCLE` | Форма пятен. |
59
+
60
+ Компонент расширяет `React.HTMLAttributes<HTMLDivElement>`: `className`, `style`, `aria-*`, `data-*` и остальные атрибуты уходят на корневой `<div>`. Переданный `style` сливается с inline-переменной размытия.
61
+
62
+ ### Значения enum'ов
63
+
64
+ - `ESmartSpotType`: `SUCCESS` (`"success"`), `WARNING` (`"warning"`), `ERROR` (`"error"`), `WAITING` (`"waiting"`, системный статус ожидания).
65
+ - `ESmartSpotAnimation`:
66
+ - `DRIFT` (`"drift"`) — весь слой пятен движется по эллипсу против часовой стрелки;
67
+ - `BREATHING` (`"breathing"`) — каждое пятно пульсирует масштабом 0.9 → 1.1 → 0.9 за цикл, слой стоит на месте;
68
+ - `NONE` (`"none"`) — один статичный кадр без `requestAnimationFrame`.
69
+ - `ESmartSpotShape`: `CIRCLE` (`"circle"`), `OVAL` (`"oval"`, высота 60% от диаметра), `SQUARE` (`"square"`), `TRIANGLE` (`"triangle"`, через `clip-path`).
70
+
71
+ ### Ограничения
72
+
73
+ - **Собственного размера нет.** Размер и скругление задаёт обёртка. Без высоты у родителя подложка схлопнется.
74
+ - **Геометрия пятен фиксирована** в абсолютных px от центра верхней грани (приватный `SPOTS_BY_TYPE` в `consts.ts`). На контейнерах сильно меньше или больше макета (~240px) видимая картинка меняется. Пятна не масштабируются под размер контейнера.
75
+ - **Смена `distance` и `duration` не перезапускает анимацию.** Значения читаются в каждом кадре через `useLatestRef`. Прогресс цикла накапливается, поэтому при смене `duration` движение продолжается с текущей точки. Смена `animation` перезапускает rAF с начала цикла.
76
+ - Кадр пишется напрямую в `style` слоя `.move` (runtime-переменные `--triplex-next-runtime-SmartSpot-Move_X`, `Move_Y`, `Spot_Scale`), ререндеров на каждом кадре нет.
77
+ - `children` оборачиваются в `div.content` (`position: relative`, 100% × 100%) только если значение truthy. Числовой `0` попадёт прямо в корень без обёртки.
78
+
79
+ ---
80
+
81
+ ## Дизайн-токены
82
+
83
+ Переопределяются через `ThemeProvider` (prop `tokens`) — см. `ThemeProvider-ai.md` → «Как переопределять токены». Значения по умолчанию — `src/components/DesignTokens/components/SmartSpot.ts`.
84
+
85
+ Группа `SmartSpot`: по токену на каждое пятно каждого типа (`{Type}_Spot{N}_Color`, N = 1…4). Значения ссылаются на core-палитру; в тёмной теме сейчас те же ссылки, что и в светлой — тёмные значения согласуются с дизайнером.
86
+
87
+ ```text
88
+ SmartSpot.Success_Spot1_Color — ColorSuccess.80
89
+ SmartSpot.Success_Spot2_Color — ColorSuccess.50
90
+ SmartSpot.Success_Spot3_Color — ColorBrand.60
91
+ SmartSpot.Success_Spot4_Color — ColorSuccess.80
92
+ SmartSpot.Warning_Spot1_Color — ColorWarning.30
93
+ SmartSpot.Warning_Spot2_Color — ColorWarning.70
94
+ SmartSpot.Warning_Spot3_Color — ColorWarning.50
95
+ SmartSpot.Warning_Spot4_Color — ColorWarning.80
96
+ SmartSpot.Error_Spot1_Color — ColorWarning.30
97
+ SmartSpot.Error_Spot2_Color — ColorWarning.30
98
+ SmartSpot.Error_Spot3_Color — ColorWarning.50
99
+ SmartSpot.Error_Spot4_Color — ColorError.70
100
+ SmartSpot.Waiting_Spot1_Color — ColorSystem.100
101
+ SmartSpot.Waiting_Spot2_Color — ColorSystem.60
102
+ SmartSpot.Waiting_Spot3_Color — ColorSystem.90
103
+ SmartSpot.Waiting_Spot4_Color — ColorSystem.90
104
+ ```
105
+
106
+ Цвет пятна привязан к его порядковому номеру: `.spot:nth-child(N)` соответствует N-му элементу `SPOTS_BY_TYPE[type]` и токену `{Type}_Spot{N}_Color`.
107
+
108
+ Runtime-переменные (не токены, выставляются компонентом):
109
+
110
+ - `--triplex-next-runtime-SmartSpot-Blur_Sigma` — на корне;
111
+ - `Spot_X`, `Spot_Y`, `Spot_Size`, `Spot_Opacity` — на каждом пятне;
112
+ - `Move_X`, `Move_Y`, `Spot_Scale` — на слое `.move`.
113
+
114
+ ---
115
+
116
+ ## Инварианты
117
+
118
+ - **`forwardRef`** обязателен. `ref` указывает на корневой `<div>`.
119
+ - **Имена публичного API**: `SmartSpot`, `ISmartSpotProps`, props (`type`, `animation`, `blur`, `distance`, `duration`, `shape`), enum'ы `ESmartSpotType`, `ESmartSpotAnimation`, `ESmartSpotShape` и их строковые значения. Значения enum'ов используются как имена CSS-классов (`styles[type]`, `styles[shape]`), поэтому переименование значения ломает стили.
120
+ - **Barrel** `src/components/SmartSpot/index.ts` экспортирует `./SmartSpot` и `./enums`. `consts.ts` и `utils.ts` приватные. Компонент подключён в `src/components/index.ts`.
121
+ - **Дефолты**: `animation = DRIFT`, `blur = 60`, `shape = CIRCLE`. Смена дефолта меняет вид у всех потребителей.
122
+ - **Ровно четыре пятна на тип.** Число пятен и их порядок в `SPOTS_BY_TYPE` связаны с `nth-child`-правилами в LESS. Добавление пятна требует правок в обоих местах и новых токенов в `SmartSpot.ts`.
123
+ - **Фон прозрачный**: корень не задаёт `background`, под пятнами виден родитель.
124
+ - **Слой пятен `aria-hidden="true"`** — проверяется тестом.
125
+ - **`displayName = "SmartSpot"`**.
126
+ - **Visual regression не покрыт.** Анимированные stories исключены из test-runner'а (`testRunner: { skip: true }`): test-runner ждёт стабилизации DOM, а rAF пишет в `style` каждый кадр.
127
+
128
+ ---
129
+
130
+ ## Accessibility
131
+
132
+ Компонент не интерактивный и декоративный. Слой пятен скрыт от скринридеров через `aria-hidden="true"`. Корень и `children` остаются в дереве доступности. Смысл статуса потребитель передаёт текстом в `children` (заголовок, описание): цвет подложки сам по себе не должен быть единственным носителем информации.
133
+
134
+ Ограничение: анимация не учитывает `prefers-reduced-motion`. Если это важно, передай `animation={ESmartSpotAnimation.NONE}` по медиа-запросу на стороне потребителя.
135
+
136
+ ---
137
+
138
+ ## Связанные компоненты
139
+
140
+ Семейства, альтернатив и контрактов по рендеру или типам нет, поэтому `related` пуст. Для компактной индикации статуса используй `Marker`, `MarkerStatus`, `Badge` (см. «Не используй когда»).
141
+
142
+ ---
143
+
144
+ ## Stories
145
+
146
+ Основные истории: `stories/SmartSpot/SmartSpot.stories.tsx`
147
+ Файлы примеров: `stories/SmartSpot/examples/`
148
+
149
+ | Story | Example file | Что демонстрирует |
150
+ | ------------ | ---------------- | ----------------------------------------------------- |
151
+ | `Playground` | `Playground.tsx` | Интерактивный контроль всех props |
152
+ | `Default` | `Default.tsx` | Подложка с типом `SUCCESS` и настройками по умолчанию |
153
+ | `Types` | `Types.tsx` | Все четыре типа |
154
+ | `Shapes` | `Shapes.tsx` | Все четыре формы пятен |
155
+ | `Animations` | `Animations.tsx` | Пресеты `DRIFT`, `BREATHING`, `NONE` |
156
+
157
+ ---
158
+
159
+ ## История изменений
160
+
161
+ | Дата | Изменение |
162
+ | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
163
+ | 2026-10-23 | Геометрия пятен (`SPOTS_BY_TYPE`) уменьшена вдвое под контейнеры вроде StatusTracker, `blur` по умолчанию снижен с 200 до 60 px, длительность цикла пресетов Drift и Breathing — с 8000 до 6000 мс. Prop `status` переименован в `type`, enum `ESmartSpotStatus` — в `ESmartSpotType`, story `Statuses` — в `Types`. |
164
+ | 2026-10-22 | Цвета пятен вынесены в компонентную группу токенов `SmartSpot` (`{Type}_Spot{N}_Color`), `background` пятна берётся из токена напрямую. |
165
+ | 2026-10-22 | Создан документ. Новый компонент (v1.52.0): AI-рефакторинг (`useLatestRef` вместо записи в ref во время рендера, `ref={ref}` вместо callback-ref, защита от отрицательного шага rAF), unit-тесты на компонент и утилиты, stories по modern pattern. |
166
+
167
+ ---
168
+
169
+ ## Примеры использования
170
+
171
+ ### Default
172
+
173
+ `stories/SmartSpot/examples/Default.tsx`
174
+
175
+ ```tsx
176
+ import React from "react";
177
+ import { SmartSpot, ESmartSpotType } from "@sberbusiness/triplex-next";
178
+
179
+ export const Default = () => (
180
+ <div style={{ width: 520, height: 300, borderRadius: 16, overflow: "hidden" }}>
181
+ <SmartSpot type={ESmartSpotType.SUCCESS} />
182
+ </div>
183
+ );
184
+ ```
185
+
186
+ ### Types
187
+
188
+ `stories/SmartSpot/examples/Types.tsx`
189
+
190
+ ```tsx
191
+ import React from "react";
192
+ import { SmartSpot, ESmartSpotType } from "@sberbusiness/triplex-next";
193
+
194
+ const TYPES = Object.values(ESmartSpotType);
195
+
196
+ export const Types = () => (
197
+ <div style={{ display: "flex", flexWrap: "wrap", gap: 24 }}>
198
+ {TYPES.map((type) => (
199
+ <div key={type}>
200
+ <div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: "700" }}>{type.toUpperCase()}</div>
201
+ <div style={{ width: 240, height: 240, borderRadius: 16, overflow: "hidden" }}>
202
+ <SmartSpot type={type} />
203
+ </div>
204
+ </div>
205
+ ))}
206
+ </div>
207
+ );
208
+ ```
209
+
210
+ ### Shapes
211
+
212
+ `stories/SmartSpot/examples/Shapes.tsx`
213
+
214
+ ```tsx
215
+ import React from "react";
216
+ import { SmartSpot, ESmartSpotShape, ESmartSpotType } from "@sberbusiness/triplex-next";
217
+
218
+ const SHAPES = Object.values(ESmartSpotShape);
219
+
220
+ export const Shapes = () => (
221
+ <div style={{ display: "flex", flexWrap: "wrap", gap: 24 }}>
222
+ {SHAPES.map((shape) => (
223
+ <div key={shape}>
224
+ <div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: "700" }}>{shape.toUpperCase()}</div>
225
+ <div style={{ width: 240, height: 240, borderRadius: 16, overflow: "hidden" }}>
226
+ <SmartSpot type={ESmartSpotType.SUCCESS} shape={shape} />
227
+ </div>
228
+ </div>
229
+ ))}
230
+ </div>
231
+ );
232
+ ```
233
+
234
+ ### Animations
235
+
236
+ `stories/SmartSpot/examples/Animations.tsx`
237
+
238
+ ```tsx
239
+ import React from "react";
240
+ import { SmartSpot, ESmartSpotAnimation, ESmartSpotType } from "@sberbusiness/triplex-next";
241
+
242
+ const ANIMATIONS = Object.values(ESmartSpotAnimation);
243
+
244
+ export const Animations = () => (
245
+ <div style={{ display: "flex", flexWrap: "wrap", gap: 24 }}>
246
+ {ANIMATIONS.map((animation) => (
247
+ <div key={animation}>
248
+ <div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: "700" }}>
249
+ {animation.toUpperCase()}
250
+ </div>
251
+ <div style={{ width: 240, height: 240, borderRadius: 16, overflow: "hidden" }}>
252
+ <SmartSpot type={ESmartSpotType.WARNING} animation={animation} />
253
+ </div>
254
+ </div>
255
+ ))}
256
+ </div>
257
+ );
258
+ ```
259
+
@@ -169,7 +169,7 @@ Step.Color_Disabled
169
169
  `size={ETooltipSize.SM}` и `toggleType="hover"`, а из props потребителя прокидывает
170
170
  только выравнивание указателя (`alignTip`) — остальное настроить нельзя. `disableAdaptiveMode`
171
171
  не передаётся, поэтому на экранах до `SM_MAX` включительно подсказка открывается
172
- в адаптивном (полноэкранном) режиме.
172
+ в адаптивном режиме — нижней шторкой `Puller`.
173
173
  - `Text` — рендерит номер шага (`ETextSize.B1`, `EFontWeightText.SEMIBOLD`). Цвет номера
174
174
  задаётся снаружи, селектором `& > span` в стилях `Step`.
175
175
  - `IslandAccordion` — потребитель: нумерует секции аккордеона, передавая `Step` номер,
@@ -207,6 +207,7 @@ Story ID участвуют в именах baseline-скриншотов (`step
207
207
  | Дата | Изменение |
208
208
  |---|---|
209
209
  | 2026-09-24 | Создан документ. AI-рефакторинг: `Step` переведён с `React.FC` на `forwardRef` (внешний ref мерджится с внутренним, который уходит в `Tooltip` как `targetRef`), JSDoc на компоненте и дефолтах props, `renderContent()` заменён на вычисляемый один раз элемент, приведён к порядку LESS. Добавлены unit-тесты (`__tests__/Step.test.tsx`), stories созданы по modern pattern (`stories/Step/`). |
210
+ | 2026-10-21 | Переход на `Puller` (TRIPLEX-961): адаптивный режим `Tooltip` — нижняя шторка `Puller`. |
210
211
 
211
212
  ---
212
213
 
@@ -147,7 +147,7 @@ Stepper.Step_Color_Disabled
147
147
  ## Stories
148
148
 
149
149
  Основные истории: `stories/Stepper/Stepper.stories.tsx`
150
- Файлы примеров: `stories/Stepper/examples/`
150
+ Файлы примеров: `stories/Stepper/examples/Stepper/`
151
151
 
152
152
  | Story | Example file | Что демонстрирует |
153
153
  |---|---|---|
@@ -158,7 +158,6 @@ Stepper.Step_Color_Disabled
158
158
  | `WithIcons` | `WithIcons.tsx` | Все значения `EStepperStepIconType` на шагах |
159
159
  | `ManySteps` | `ManySteps.tsx` | Шаги не помещаются в контейнер и прокручиваются |
160
160
  | `VisualTests` | `VisualTests.tsx` | Размеры × состояния, отключённый шаг, типы, `:focus-visible` на шаге (через `play`) |
161
- | `StepperExtendedType` | — | Стори базового `StepperExtended`; живёт в этом файле до отдельной задачи по `StepperExtended` |
162
161
 
163
162
  ---
164
163
 
@@ -169,6 +168,7 @@ Stepper.Step_Color_Disabled
169
168
  | 2026-09-24 | Создан документ AI-ready для `Stepper` (TRI-84). |
170
169
  | 2026-09-24 | AI-рефакторинг: подводка шага и кнопки прокрутки вынесены в чистые функции и отдельный компонент модульного уровня, величина прокрутки хранится одним числом вместо объекта, ссылки на узлы удалённых шагов больше не удерживаются, JSDoc проставлен на публичных полях `steps` и `size`. Публичный API (имена props, значения enum, barrel-экспорты) и разметка не изменились. Добавлены unit-тесты на состояния шагов, типы, клавиатуру, `forwardedRef`, `...rest` и подводку шага в видимую область; stories переписаны по modern pattern. |
171
170
  | 2026-09-25 | Размер по умолчанию изменён с `LG` на `MD` по решению ревью — вместе со `StepperExtended`, чтобы компоненты не разъехались. Изменение наблюдаемое: без явного `size` шаги и кнопки прокрутки становятся меньше, описано в release notes 1.48.0. |
171
+ | 2026-10-19 | Примеры перенесены в `stories/Stepper/examples/Stepper/`, отдельно от `StepperExtended`; путь обновлён, удалена устаревшая запись о несуществующей story `StepperExtendedType`. |
172
172
 
173
173
  ---
174
174
 
@@ -176,7 +176,7 @@ Stepper.Step_Color_Disabled
176
176
 
177
177
  ### Default
178
178
 
179
- `stories/Stepper/examples/Default.tsx`
179
+ `stories/Stepper/examples/Stepper/Default.tsx`
180
180
 
181
181
  ```tsx
182
182
  import React, { useState } from "react";
@@ -210,7 +210,7 @@ export const Default = () => {
210
210
 
211
211
  ### Sizes
212
212
 
213
- `stories/Stepper/examples/Sizes.tsx`
213
+ `stories/Stepper/examples/Stepper/Sizes.tsx`
214
214
 
215
215
  ```tsx
216
216
  import React, { useState } from "react";
@@ -269,7 +269,7 @@ export const Sizes = () => (
269
269
 
270
270
  ### Types
271
271
 
272
- `stories/Stepper/examples/Types.tsx`
272
+ `stories/Stepper/examples/Stepper/Types.tsx`
273
273
 
274
274
  ```tsx
275
275
  import React, { useState } from "react";
@@ -334,7 +334,7 @@ export const Types = () => (
334
334
 
335
335
  ### WithIcons
336
336
 
337
- `stories/Stepper/examples/WithIcons.tsx`
337
+ `stories/Stepper/examples/Stepper/WithIcons.tsx`
338
338
 
339
339
  ```tsx
340
340
  import React, { useState } from "react";
@@ -382,7 +382,7 @@ export const WithIcons = () => {
382
382
 
383
383
  ### ManySteps
384
384
 
385
- `stories/Stepper/examples/ManySteps.tsx`
385
+ `stories/Stepper/examples/Stepper/ManySteps.tsx`
386
386
 
387
387
  ```tsx
388
388
  import React, { useState } from "react";
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  component: Suggest
3
3
  category: Suggest
4
- related: [SuggestField, Chip, Dropdown]
4
+ related: [SuggestField, Chip, Puller, Dropdown]
5
5
  tokens: []
6
6
  stories: stories/Suggest/Suggest.stories.tsx
7
7
  version: "1.0"
@@ -145,11 +145,11 @@ Headless-основа выпадающего списка с фильтраци
145
145
  - `Chip` — родитель `ChipSuggest`, единственного компонента библиотеки, собранного на
146
146
  `Suggest`. `ChipSuggest` опирается не только на barrel, но и на внутренний
147
147
  `SuggestMobileDropdownContent`.
148
- - `Dropdown` — мобильное наполнение Suggest рендерится из его частей
149
- (`DropdownMobileHeader`, `DropdownMobileInput`, `DropdownMobileList`, …); в десктопной
150
- композиции `Dropdown` обычно и служит выпадающим списком.
151
- - `SuggestMobileDropdownContent` — внутреннее наполнение полноэкранного мобильного
152
- дропдауна: поле ввода, список опций, лоадер и текст при пустом списке. Данные берёт из
148
+ - `Puller` — мобильное наполнение Suggest рендерится из его частей
149
+ (`PullerHeader`, `PullerInput`, `PullerList`, …).
150
+ - `Dropdown` — в десктопной композиции обычно служит выпадающим списком.
151
+ - `SuggestMobileDropdownContent` — внутреннее наполнение мобильного дропдауна (шторки
152
+ `Puller`): поле ввода, список опций, лоадер и текст при пустом списке. Данные берёт из
153
153
  `SuggestContext`, поэтому рендерится только внутри `Suggest`. Отдельного AI.md не имеет,
154
154
  из barrel не экспортируется.
155
155
 
@@ -184,6 +184,7 @@ Suggest headless: собственной разметки он не рендер
184
184
  | Дата | Изменение |
185
185
  |---|---|
186
186
  | 2026-09-02 | Создан документ |
187
+ | 2026-10-21 | **Breaking** (TRIPLEX-961): prop `mobileViewProps`, унаследованный `ISuggestDropdownProps` от `Dropdown`, переименован в `pullerProps`. Мобильное наполнение собрано из частей нижней шторки `Puller` (бывший `DropdownMobile*`). |
187
188
 
188
189
  ---
189
190
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  component: SuggestField
3
3
  category: TextFields
4
- related: [Suggest, SelectField, MultiselectField, SelectExtendedField, TextField, FormField, Dropdown, LoaderSmall]
4
+ related: [Suggest, SelectField, MultiselectField, SelectExtendedField, TextField, FormField, Dropdown, Puller, LoaderSmall]
5
5
  tokens: []
6
6
  stories: stories/SuggestField/SuggestField.stories.tsx
7
7
  version: "1.0"
@@ -17,7 +17,7 @@ version: "1.0"
17
17
  возвращает новый `options`.
18
18
 
19
19
  Адаптивный: на ширине экрана < 768px вместо десктопного поля с выпадающим списком рендерится
20
- мобильный вариант — поле только для чтения, по фокусу открывающее полноэкранный дропдаун с
20
+ мобильный вариант — поле только для чтения, по фокусу открывающее нижнюю шторку `Puller` с
21
21
  собственным полем ввода. Переключение делает `MobileView`, потребителю ничего делать не нужно.
22
22
 
23
23
  Используй когда: нужно поле с подсказками-опциями — поиск контрагента, счёта, адреса, в том
@@ -101,7 +101,7 @@ version: "1.0"
101
101
 
102
102
  ### Поведение мобильного варианта
103
103
 
104
- Поле-триггер — `readOnly`, по фокусу открывается полноэкранный `Dropdown` с собственным полем
104
+ Поле-триггер — `readOnly`, по фокусу открывается `Dropdown` в виде шторки `Puller` с собственным полем
105
105
  ввода (автофокус). При `tooltipOpen` вместо списка показывается `SuggestFieldMobileDropdownHint`
106
106
  с текстом `tooltipHint`. Закрытие дропдауна без выбора опции значение не сбрасывает, даже при
107
107
  пустом поле ввода: на закрытии поле ввода дропдауна возвращается к `label` текущего `value`
@@ -205,8 +205,9 @@ version: "1.0"
205
205
  - `FormField` — источник `FormFieldInput` (поле ввода и `SuggestField.Input`), `FormFieldClear`
206
206
  (кнопка очистки) и статусов `EFormFieldStatus`.
207
207
  - `Dropdown` — выпадающий список: `DropdownDesktop` + `DropdownList` + `DropdownListItem` на
208
- десктопе, `DropdownMobile*` в полноэкранном мобильном варианте. `ISuggestFieldDesktopDropdownProps`
209
- наследует `IDropdownDesktopProps`.
208
+ десктопе. `ISuggestFieldDesktopDropdownProps` наследует `IDropdownDesktopProps`.
209
+ - `Puller` — нижняя шторка мобильного варианта (`PullerHeader`, `PullerInput`, `PullerList`, …).
210
+ `ISuggestFieldMobileDropdownProps` наследует `Omit<IPullerProps, "onSelect">`.
210
211
  - `LoaderSmall` — индикатор подгрузки подсказок: `SuggestFieldDesktop` и `SuggestFieldMobile`
211
212
  показывают его с темой `BRAND`, пока `loading`.
212
213
  - `Tooltip` — подсказка `tooltipHint` у десктопного поля. В `related` не вынесен: связь узкая,
@@ -248,6 +249,7 @@ version: "1.0"
248
249
  | 2026-09-23 | Создан документ |
249
250
  | 2026-09-29 | Аудит симметрии `related` (TRI-156): добавлены обратные ссылки (`MultiselectField`, `SelectExtendedField`) и контракт по рендеру `LoaderSmall`. Публичный API и поведение не затронуты. |
250
251
  | 2026-10-02 | Сброс значения только кнопкой очистки на обеих платформах: при `clearInputOnFocus` значение терялось от фокуса без выбора. Blur на десктопе и закрытие дропдауна на мобильном больше не вызывают `onSelect(undefined)`; мобильная кнопка очистки сама зовёт `onSelect(undefined)` и `onFilter("")` (последний — при непустом `label`), как десктопная; на закрытии мобильного дропдауна его поле ввода возвращается к `label`. `SuggestField` отдаёт мобильному варианту все props, как десктопному: на мобильной ширине больше не теряются `className`, `id`, `data-test-id`, `active` и `renderInput`. Обновлены `onSelect`, поведение обеих платформ и «Инварианты» |
252
+ | 2026-10-21 | Переход на `Puller` (TRIPLEX-961): мобильный вариант собран из частей нижней шторки `Puller` (бывший `DropdownMobile*`). |
251
253
 
252
254
  ---
253
255
 
@@ -759,7 +761,7 @@ export const ProductionExample = () => {
759
761
  };
760
762
 
761
763
  const handleClear: React.MouseEventHandler<HTMLButtonElement> = () => {
762
- // На мобильном фокус открыл бы полноэкранный дропдаун сразу после очистки.
764
+ // На мобильном фокус открыл бы мобильный дропдаун сразу после очистки.
763
765
  if (!adaptive) {
764
766
  inputRef.current?.focus();
765
767
  }
@@ -1773,11 +1773,11 @@ import {
1773
1773
  ChipGroup,
1774
1774
  ChipMultiselect,
1775
1775
  Col,
1776
- DropdownMobileBody,
1777
- DropdownMobileClose,
1778
- DropdownMobileFooter,
1779
- DropdownMobileHeader,
1780
- DropdownMobileInput,
1776
+ PullerBody,
1777
+ PullerClose,
1778
+ PullerFooter,
1779
+ PullerHeader,
1780
+ PullerInput,
1781
1781
  EButtonTheme,
1782
1782
  EComponentSize,
1783
1783
  EDropdownAlignment,
@@ -2100,21 +2100,19 @@ export const ExampleProduction = () => {
2100
2100
  ref={dropdownRef}
2101
2101
  alignment={EDropdownAlignment.LEFT}
2102
2102
  focusTrapProps={{ focusTrapOptions: { initialFocus: false } }}
2103
- mobileViewProps={{
2103
+ pullerProps={{
2104
2104
  children: (
2105
2105
  <>
2106
- <DropdownMobileHeader
2107
- controlButtons={<DropdownMobileClose onClick={() => setOpened(false)} />}
2108
- >
2109
- <DropdownMobileInput
2106
+ <PullerHeader controlButtons={<PullerClose onClick={() => setOpened(false)} />}>
2107
+ <PullerInput
2110
2108
  autoFocus
2111
2109
  placeholder="Поиск по статусу"
2112
2110
  value={statusFilter}
2113
2111
  onChange={handleStatusFilterChange}
2114
2112
  />
2115
- </DropdownMobileHeader>
2116
- <DropdownMobileBody>{renderStatusDropdownContent()}</DropdownMobileBody>
2117
- <DropdownMobileFooter>
2113
+ </PullerHeader>
2114
+ <PullerBody>{renderStatusDropdownContent()}</PullerBody>
2115
+ <PullerFooter>
2118
2116
  <Button
2119
2117
  theme={EButtonTheme.GENERAL}
2120
2118
  size={EComponentSize.SM}
@@ -2129,7 +2127,7 @@ export const ExampleProduction = () => {
2129
2127
  >
2130
2128
  Сбросить
2131
2129
  </Button>
2132
- </DropdownMobileFooter>
2130
+ </PullerFooter>
2133
2131
  </>
2134
2132
  ),
2135
2133
  }}
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  component: Tooltip
3
3
  category: Tooltip
4
- related: [HelpBox, Dropdown, Portal, MobileView, ThemeProvider, ButtonIcon]
4
+ related: [HelpBox, Puller, Portal, MobileView, ThemeProvider, ButtonIcon]
5
5
  tokens:
6
6
  - Tooltip.Background
7
7
  - Tooltip.Color
@@ -21,7 +21,7 @@ version: "1.0"
21
21
 
22
22
  ## Назначение
23
23
 
24
- Всплывающая подсказка, привязанная к целевому элементу. Рендерится через `Portal` — по умолчанию в `document.body`, либо в контейнер из `renderContainer` — и позиционируется относительно `targetRef`. На мобильной ширине экрана (<768px) вместо всплывающей подсказки открывается полноэкранный оверлей снизу на базе `DropdownMobile`.
24
+ Всплывающая подсказка, привязанная к целевому элементу. Рендерится через `Portal` — по умолчанию в `document.body`, либо в контейнер из `renderContainer` — и позиционируется относительно `targetRef`. На мобильной ширине экрана (<768px) вместо всплывающей подсказки открывается нижняя шторка `Puller`.
25
25
 
26
26
  Используй когда: нужно пояснить элемент интерфейса коротким текстом, при необходимости со ссылкой на подробное описание.
27
27
  Не используй когда:
@@ -101,14 +101,14 @@ Tooltip.Link_Mobile_Color_Active
101
101
  Tooltip.Link_Mobile_Shadow_Focus
102
102
  ```
103
103
 
104
- Мобильная версия дополнительно наследует токены группы `DropdownMobile`, так как построена на его субкомпонентах.
104
+ Мобильная версия дополнительно наследует токены группы `Puller`, так как построена на его субкомпонентах.
105
105
 
106
106
  ---
107
107
 
108
108
  ## Инварианты
109
109
 
110
- - Публичный barrel `src/components/Tooltip/index.ts` реэкспортирует `Tooltip`, `enums` и `types` целиком. Компонент используется внутри `HelpBox`, `SMSField.Tooltip` и косвенно (через типы) в `Dropdown`, поэтому удаление любого экспорта ломает библиотеку изнутри.
111
- - `IDropdownMobileHeaderProps` объявлен **в `src/components/Tooltip/types.ts`**, но используется `DropdownMobileHeader` из семейства `Dropdown`. Переносить тип нельзя без синхронной правки `Dropdown` (и это breaking change для deep-импортов).
110
+ - Публичный barrel `src/components/Tooltip/index.ts` реэкспортирует `Tooltip`, `enums` и `types` целиком. Компонент используется внутри `HelpBox` и `SMSField.Tooltip`, поэтому удаление любого экспорта ломает библиотеку изнутри.
111
+ - `ITooltipMobileHeaderProps` расширяет `IPullerHeaderProps` из `src/components/Puller/PullerHeader.tsx`: props шапки мобильной версии — это props `PullerHeader`.
112
112
  - Файл контекста называется `TootlipContext.ts` — опечатка в имени зафиксирована в публикуемых путях подпакета; переименование ломает deep-импорты потребителей.
113
113
  - `Tooltip` — `React.FC` со статическими субкомпонентами (`Tooltip.Target` и т.д.). Набор статических свойств — часть публичного API.
114
114
  - Разбор `children` по типу элемента (`child.type === TooltipTarget`) означает, что обёртка субкомпонента в собственный компонент-прокси **не сработает** — узел просто не попадёт ни в один слот. Это осознанное ограничение, на нём построен весь состав.
@@ -128,7 +128,7 @@ Tooltip.Link_Mobile_Shadow_Focus
128
128
  - Закрытие также срабатывает по `mousedown` вне подсказки и вне целевого элемента.
129
129
  - Открытие по наведению: подсказка закрывается не сразу после ухода курсора, а через 500мс — за это время курсор можно довести до самой подсказки (её нода тоже слушает `mouseenter`/`mouseleave`).
130
130
  - Фокус компонент не перехватывает и не возвращает: при открытии фокус остаётся на целевом элементе. Поэтому интерактивное содержимое сложнее `Tooltip.Link` в подсказку класть не стоит.
131
- - Мобильная версия — оверлей `DropdownMobile`; кнопке закрытия `aria-label` задаёт потребитель через props `Tooltip.XButton`. Кнопка там рендерится всегда, поэтому без `Tooltip.XButton` она остаётся без доступного имени — в адаптивном сценарии `Tooltip.XButton` с `aria-label` стоит передавать, даже если на десктопе крестик не нужен.
131
+ - Мобильная версия — оверлей `Puller`; кнопке закрытия `aria-label` задаёт потребитель через props `Tooltip.XButton`. Кнопка там рендерится всегда, поэтому без `Tooltip.XButton` она остаётся без доступного имени — в адаптивном сценарии `Tooltip.XButton` с `aria-label` стоит передавать, даже если на десктопе крестик не нужен.
132
132
 
133
133
  ---
134
134
 
@@ -147,7 +147,7 @@ Tooltip.Link_Mobile_Shadow_Focus
147
147
  - `TooltipLink` — ссылка; защита от reverse tabnabbing через `getSafeRel`.
148
148
  - `TooltipXButton` — кнопка закрытия десктопной версии (обёртка над `ButtonIcon`).
149
149
  - `TooltipMobileHeader` — шапка мобильной версии; кнопку закрытия подставляет сам, наследуя props у `Tooltip.XButton`.
150
- - `TooltipMobileCloseButton` — кнопка закрытия мобильной версии (обёртка над `DropdownMobileClose`).
150
+ - `TooltipMobileCloseButton` — кнопка закрытия мобильной версии (обёртка над `PullerClose`).
151
151
 
152
152
  **Десктопная версия (`components/desktop/`):**
153
153
 
@@ -161,7 +161,7 @@ Tooltip.Link_Mobile_Shadow_Focus
161
161
  - `utils/Positioning.ts` — чистые функции выбора зоны и расчёта координат.
162
162
  - `utils/useTooltipTheme.ts` — класс темы на контейнере портала со счётчиком использования.
163
163
  - `Portal`, `MobileView` — инфраструктура рендера.
164
- - `Dropdown` — мобильная версия подсказки построена на его оверлее (`DropdownMobile`, `DropdownMobileClose`).
164
+ - `Puller` — мобильная версия подсказки построена на нём (`Puller`, `PullerBody`, `PullerHeader`, `PullerClose`).
165
165
  - `ThemeProvider` — источник темы: `useTooltipTheme` берёт `scopeClassName` через `useToken` и ставит класс на контейнере портала.
166
166
 
167
167
  **Потребители внутри библиотеки:**
@@ -200,6 +200,7 @@ Tooltip.Link_Mobile_Shadow_Focus
200
200
  | 2026-08-03 | Правки по второму ревью PR #496 (документация и stories, кода не касаются): в «Ограничения» добавлено, что `onKeyDown` на десктопе не доходит до корневого элемента подсказки, а в адаптивном режиме доходит; уточнено, что в адаптивном режиме кнопка закрытия рендерится всегда и без `Tooltip.XButton` остаётся без `aria-label`; в `VisualTests` добавлен блок с `alignTip: end` — раньше это значение enum не было покрыто ни примером, ни тестом. |
201
201
  | 2026-08-03 | Правки по третьему ревью PR #496. Исправлено: при смене `toggleType` на лету hover-обработчики синхронизируются и на самой подсказке, а не только на целевом элементе (`setTooltipRef` повторно не вызывается, поэтому раньше на ноде подсказки оставались устаревшие слушатели). Тесты: `Tooltip.Link` в десктопном хелпере вынесен в прямые дети `Tooltip` — раньше слот `elements.link` не исполнялся ни в одном десктопном кейсе; добавлены кейсы на ветку `disableAdaptiveMode`. Публичный API не изменён. |
202
202
  | 2026-09-29 | Аудит симметрии `related` (TRI-156): из `related` убраны имена без строки в `docs/ai/ROADMAP.md` (`DropdownMobile`) и потребитель `SMSField` — `SMSField.Tooltip` рендерит `Tooltip`, ссылка стоит с его стороны. Пояснения к убранным именам сохранены прозой в «Связанные компоненты»; публичный API и поведение не затронуты. |
203
+ | 2026-10-21 | **Breaking** (TRIPLEX-961): мобильная версия построена на `Puller` (бывший `DropdownMobile*`). `IDropdownMobileHeaderProps` перенесён из `types.ts` в `Puller/PullerHeader.tsx` как `IPullerHeaderProps` и больше не реэкспортируется из barrel `Tooltip`. |
203
204
 
204
205
  ---
205
206
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## Задачи и тикеты
6
6
 
7
- Задачи ведутся в Linear, команда `TRI` (https://linear.app/triplex-next).
7
+ Задачи ведутся в Linear, команда `TRI`.
8
8
  Номер задачи `TRI-XXX` — обязательный префикс веток и коммитов: по нему
9
9
  GitHub-интеграция Linear линкует PR и двигает статусы задачи
10
10
  (ветка → In Progress, PR → In Review, merge → Done).
@@ -12,6 +12,9 @@ GitHub-интеграция Linear линкует PR и двигает стат
12
12
  **Legacy:** исторические ветки и коммиты используют префикс `TRIPLEX-XXX`.
13
13
  Существующие не переименовываем; всё новое — только `TRI-XXX`.
14
14
 
15
+ В файлах проекта задачи Linear упоминаются только по номеру `TRI-XXX`,
16
+ без ссылок на задачи и workspace.
17
+
15
18
  ---
16
19
 
17
20
  ## Именование веток
@@ -79,7 +79,7 @@ src/components/Button/
79
79
 
80
80
  Источник значений: `src/components/DesignTokens/DesignTokensCore.ts` (палитра,
81
81
  12 групп) и `src/components/DesignTokens/components/{Group}.ts` (токены
82
- компонентов, 56 групп). Путь токена — `{Группа}.{Токен}`:
82
+ компонентов, 57 групп). Путь токена — `{Группа}.{Токен}`:
83
83
 
84
84
  ```text
85
85
  ColorBrand.50
@@ -225,12 +225,12 @@ export interface IButtonGeneralProps extends IButtonBaseProps {
225
225
 
226
226
  ```typescript
227
227
  // Деструктурируй из пропсов:
228
- const { theme, size, newProp, className, ...rest } = props;
228
+ const { theme, size, newProp, className, ...restProps } = props;
229
229
 
230
230
  // Применяй через clsx:
231
231
  <button
232
232
  className={clsx(styles.button, styles[size], { [styles.newVariant]: newProp === 'variant' }, className)}
233
- {...rest}
233
+ {...restProps}
234
234
  >
235
235
  ```
236
236
 
@@ -332,7 +332,7 @@ AI-агента.
332
332
  1. Компонент экспортируется из barrel `src/components/{Family}/index.ts`
333
333
  (внутренние/приватные — нет).
334
334
  2. У компонента есть нетривиальный API или поведение: собственные props
335
- сверх `className + ref + ...rest`, либо state, контекст, клавиатура,
335
+ сверх `className + ref + ...restProps`, либо state, контекст, клавиатура,
336
336
  callback'и, accessibility-контракт, render-prop, discriminated union.
337
337
 
338
338
  Тривиальные wrapper'ы (`className + spread + forwardRef` без своей логики)
@@ -354,7 +354,7 @@ AI-агента.
354
354
  Индекс переходов для агента, а не «похожие компоненты»: только имена, пояснения —
355
355
  в разделе «Связанные компоненты». Имя обязано быть адресатом: компонентом из
356
356
  таблицы `docs/ai/ROADMAP.md`, у которого AI.md есть или запланирован. Связь с
357
- обёрткой вне таблицы записывается на её родителя (`IDropdownMobileMaskedInputProps
357
+ обёрткой вне таблицы записывается на её родителя (`IPullerMaskedInputProps
358
358
  extends IFormFieldMaskedInputProps` → `FormField`).
359
359
 
360
360
  Адресат попадает в `related`, только если подходит под одну из четырёх категорий: