@sberbusiness/triplex-next-mcp-server 0.24.0-beta1

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 (140) hide show
  1. package/README.md +124 -0
  2. package/bundle/.gitkeep +0 -0
  3. package/bundle/components/AbstractTree.md +198 -0
  4. package/bundle/components/AccordionBase.md +227 -0
  5. package/bundle/components/Alert.md +317 -0
  6. package/bundle/components/Amount.md +225 -0
  7. package/bundle/components/AmountField.md +289 -0
  8. package/bundle/components/Avatar.md +209 -0
  9. package/bundle/components/Badge.md +277 -0
  10. package/bundle/components/Body.md +167 -0
  11. package/bundle/components/Button.md +230 -0
  12. package/bundle/components/ButtonDropdown.md +159 -0
  13. package/bundle/components/ButtonIcon.md +122 -0
  14. package/bundle/components/Calendar.md +445 -0
  15. package/bundle/components/Card.md +374 -0
  16. package/bundle/components/CarouselExtended.md +250 -0
  17. package/bundle/components/Checkbox.md +126 -0
  18. package/bundle/components/CheckboxTree.md +280 -0
  19. package/bundle/components/CheckboxTreeExtended.md +321 -0
  20. package/bundle/components/CheckboxXGroup.md +68 -0
  21. package/bundle/components/CheckboxYGroup.md +67 -0
  22. package/bundle/components/Chip.md +404 -0
  23. package/bundle/components/ChipGroup.md +179 -0
  24. package/bundle/components/Col.md +221 -0
  25. package/bundle/components/CollapsableTree.md +255 -0
  26. package/bundle/components/Confirm.md +343 -0
  27. package/bundle/components/DateField.md +371 -0
  28. package/bundle/components/DatePickerExtended.md +342 -0
  29. package/bundle/components/DateRange.md +275 -0
  30. package/bundle/components/DesignTokens.md +385 -0
  31. package/bundle/components/Divider.md +196 -0
  32. package/bundle/components/DocumentNumberEdit.md +280 -0
  33. package/bundle/components/Dropdown.md +433 -0
  34. package/bundle/components/Ellipsis.md +208 -0
  35. package/bundle/components/EmptyView.md +99 -0
  36. package/bundle/components/ExpandAnimation.md +281 -0
  37. package/bundle/components/Footer.md +339 -0
  38. package/bundle/components/FormField.md +326 -0
  39. package/bundle/components/FormGroup.md +99 -0
  40. package/bundle/components/Gap.md +113 -0
  41. package/bundle/components/Header.md +280 -0
  42. package/bundle/components/HelpBox.md +154 -0
  43. package/bundle/components/IconWrapper.md +145 -0
  44. package/bundle/components/Island.md +197 -0
  45. package/bundle/components/IslandAccordion.md +230 -0
  46. package/bundle/components/IslandWidget.md +233 -0
  47. package/bundle/components/KeyDownListener.md +157 -0
  48. package/bundle/components/LightBox.md +322 -0
  49. package/bundle/components/Link.md +161 -0
  50. package/bundle/components/List.md +247 -0
  51. package/bundle/components/ListMaster.md +204 -0
  52. package/bundle/components/Loader.md +161 -0
  53. package/bundle/components/LoaderScreen.md +134 -0
  54. package/bundle/components/Marker.md +127 -0
  55. package/bundle/components/MarkerStatus.md +148 -0
  56. package/bundle/components/MediaWidth.md +169 -0
  57. package/bundle/components/MobileView.md +120 -0
  58. package/bundle/components/ModalWindow.md +308 -0
  59. package/bundle/components/MonthYearField.md +168 -0
  60. package/bundle/components/MultiselectField.md +213 -0
  61. package/bundle/components/Notification.md +233 -0
  62. package/bundle/components/NumberField.md +178 -0
  63. package/bundle/components/OrderedList.md +169 -0
  64. package/bundle/components/Overlay.md +237 -0
  65. package/bundle/components/Page.md +246 -0
  66. package/bundle/components/Pagination.md +298 -0
  67. package/bundle/components/Portal.md +119 -0
  68. package/bundle/components/Radio.md +174 -0
  69. package/bundle/components/Row.md +125 -0
  70. package/bundle/components/SMSField.md +160 -0
  71. package/bundle/components/SegmentedControl.md +235 -0
  72. package/bundle/components/SelectExtendedField.md +322 -0
  73. package/bundle/components/SelectField.md +213 -0
  74. package/bundle/components/Skeleton.md +129 -0
  75. package/bundle/components/Slider.md +157 -0
  76. package/bundle/components/SliderExtended.md +210 -0
  77. package/bundle/components/SliderRange.md +160 -0
  78. package/bundle/components/SmallInput.md +101 -0
  79. package/bundle/components/Spoiler.md +121 -0
  80. package/bundle/components/StatusTracker.md +151 -0
  81. package/bundle/components/Step.md +121 -0
  82. package/bundle/components/Stepper.md +163 -0
  83. package/bundle/components/Suggest.md +160 -0
  84. package/bundle/components/SuggestField.md +157 -0
  85. package/bundle/components/SwipeableArea.md +144 -0
  86. package/bundle/components/Table.md +199 -0
  87. package/bundle/components/Tabs.md +152 -0
  88. package/bundle/components/TabsExtended.md +273 -0
  89. package/bundle/components/TabsLine.md +189 -0
  90. package/bundle/components/Tag.md +135 -0
  91. package/bundle/components/TagColor.md +121 -0
  92. package/bundle/components/TagGroup.md +100 -0
  93. package/bundle/components/TextField.md +152 -0
  94. package/bundle/components/TextareaField.md +124 -0
  95. package/bundle/components/ThemeProvider.md +181 -0
  96. package/bundle/components/Tooltip.md +254 -0
  97. package/bundle/components/TopOverlay.md +145 -0
  98. package/bundle/components/TreeView.md +224 -0
  99. package/bundle/components/Triggers.md +121 -0
  100. package/bundle/guides/codestyle.md +205 -0
  101. package/bundle/guides/commits.md +166 -0
  102. package/bundle/guides/context.md +277 -0
  103. package/bundle/guides/stories.md +618 -0
  104. package/bundle/guides/template.md +154 -0
  105. package/bundle/guides/tests.md +301 -0
  106. package/bundle/icons.json +4156 -0
  107. package/bundle/manifest.json +796 -0
  108. package/bundle/release-notes/1.1.0.mdx +26 -0
  109. package/bundle/release-notes/1.1.1.mdx +14 -0
  110. package/bundle/release-notes/1.10.0.mdx +43 -0
  111. package/bundle/release-notes/1.11.0.mdx +19 -0
  112. package/bundle/release-notes/1.12.0.mdx +21 -0
  113. package/bundle/release-notes/1.13.0.mdx +43 -0
  114. package/bundle/release-notes/1.14.0.mdx +29 -0
  115. package/bundle/release-notes/1.15.0.mdx +56 -0
  116. package/bundle/release-notes/1.16.0.mdx +55 -0
  117. package/bundle/release-notes/1.17.0.mdx +15 -0
  118. package/bundle/release-notes/1.18.0.mdx +24 -0
  119. package/bundle/release-notes/1.19.0.mdx +48 -0
  120. package/bundle/release-notes/1.19.1.mdx +9 -0
  121. package/bundle/release-notes/1.2.0.mdx +80 -0
  122. package/bundle/release-notes/1.20.0.mdx +48 -0
  123. package/bundle/release-notes/1.21.0.mdx +66 -0
  124. package/bundle/release-notes/1.22.0.mdx +75 -0
  125. package/bundle/release-notes/1.23.0.mdx +50 -0
  126. package/bundle/release-notes/1.24.0.mdx +59 -0
  127. package/bundle/release-notes/1.25.0.mdx +52 -0
  128. package/bundle/release-notes/1.26.0.mdx +11 -0
  129. package/bundle/release-notes/1.3.0.mdx +21 -0
  130. package/bundle/release-notes/1.4.0.mdx +37 -0
  131. package/bundle/release-notes/1.5.0.mdx +24 -0
  132. package/bundle/release-notes/1.6.0.mdx +37 -0
  133. package/bundle/release-notes/1.6.1.mdx +11 -0
  134. package/bundle/release-notes/1.7.0.mdx +29 -0
  135. package/bundle/release-notes/1.8.0.mdx +38 -0
  136. package/bundle/release-notes/1.9.0.mdx +28 -0
  137. package/dist/index.d.ts +2 -0
  138. package/dist/index.js +324 -0
  139. package/dist/index.js.map +1 -0
  140. package/package.json +51 -0
@@ -0,0 +1,317 @@
1
+ ---
2
+ component: Alert
3
+ category: Alerts
4
+ figma-node: ""
5
+ figma-file: ""
6
+ related: [Notification, Typography, ButtonIcon, Spoiler]
7
+ tokens:
8
+ - --triplex-next-AlertContext-Error_Color
9
+ - --triplex-next-AlertContext-Info_Color
10
+ - --triplex-next-AlertContext-Warning_Color
11
+ - --triplex-next-AlertContext-System_Color
12
+ - --triplex-next-AlertProcess-Error_Background
13
+ - --triplex-next-AlertProcess-Info_Background
14
+ - --triplex-next-AlertProcess-Warning_Background
15
+ - --triplex-next-AlertProcess-System_Background
16
+ - --triplex-next-AlertProcess-Feature_Background
17
+ stories:
18
+ - stories/Alerts/AlertContext.stories.tsx
19
+ - stories/Alerts/AlertProcess.stories.tsx
20
+ version: "1.0"
21
+ ---
22
+
23
+ # Alert
24
+
25
+ ## Назначение
26
+
27
+ Компоненты для отображения статусных/предупреждающих сообщений. Папка `Alert` содержит
28
+ две независимые реализации под разные сценарии:
29
+
30
+ - **`AlertContext`** — короткое inline-сообщение в виде строки с иконкой (`<span>`).
31
+ Применяется рядом с полями форм, таблицами, виджетами для уточнения контекста.
32
+ - **`AlertProcess`** — блочное предупреждение с фоном, заголовком, кнопкой закрытия
33
+ и опциональным спойлером для скрытия расширенного контента. Применяется как
34
+ самостоятельный информационный блок на странице.
35
+
36
+ Оба компонента разделяют один набор семантических типов (`EAlertType`).
37
+
38
+ Используй `AlertContext` когда: нужна короткая одна-две строки подсказки без фона
39
+ (пример: сообщение об ошибке валидации рядом с полем).
40
+ Используй `AlertProcess` когда: нужен заметный блок с фоном, многострочный контент,
41
+ возможность закрытия или спойлер (пример: системное уведомление в начале страницы).
42
+ Не используй когда: нужен toast/тост — используй `Notification`.
43
+
44
+ ---
45
+
46
+ ## Файловая структура
47
+
48
+ ```text
49
+ src/components/Alert/
50
+ ├── EAlertType.ts # Enum общих типов (INFO, WARNING, ERROR, SYSTEM, FEATURE)
51
+ ├── AlertTypeUtils.tsx # ALERT_TYPE_TO_CLASS_NAME_MAP — маппинг type → styles.alertType{Xxx}
52
+ ├── index.ts # Barrel: AlertContext, AlertProcess + Spoiler, EAlertType, EAlertProcessBorderRadius
53
+ ├── AlertContext/
54
+ │ ├── AlertContext.tsx # <span role="alert"> с иконкой и Text
55
+ │ ├── styles/AlertContext.module.less
56
+ │ └── __tests__/AlertContext.test.tsx
57
+ └── AlertProcess/
58
+ ├── AlertProcess.tsx # <div> с фоном, иконкой, закрытием, Object.assign({Spoiler})
59
+ ├── AlertProcessContext.ts # Context для коммуникации AlertProcess ↔ AlertProcess.Spoiler
60
+ ├── enums.ts # EAlertProcessBorderRadius (MD, LG)
61
+ ├── components/AlertProcessSpoiler.tsx # AlertProcess.Spoiler — раскрывающийся блок
62
+ ├── styles/AlertProcess.module.less
63
+ └── __tests__/AlertProcess.test.tsx
64
+ ```
65
+
66
+ Особенности:
67
+ - Два независимых компонента в одной папке — не объединять, у них разная структура,
68
+ семантика и визуал.
69
+ - Общий enum `EAlertType` и утилита `ALERT_TYPE_TO_CLASS_NAME_MAP` намеренно вынесены
70
+ на уровень выше — это единственный переиспользуемый код между `AlertContext` и
71
+ `AlertProcess`.
72
+
73
+ ---
74
+
75
+ ## Варианты и props
76
+
77
+ ### Общий enum `EAlertType`
78
+
79
+ | Значение | Цвет иконки (paletteIndex) | Поддерживает AlertContext | Поддерживает AlertProcess |
80
+ |---|---|---|---|
81
+ | `INFO` | `3` (синий) | Да | Да |
82
+ | `WARNING` | `2` (жёлтый) | Да | Да |
83
+ | `ERROR` | `1` (красный) | Да | Да |
84
+ | `SYSTEM` | `4` (фиолетовый) | Да | Да |
85
+ | `FEATURE` | `0` (neutral) | **Нет** — запрещён через `Exclude<EAlertType, EAlertType.FEATURE>` | Да (default icon = `DefaulticonStrokePrdIcon20`) |
86
+
87
+ ### `AlertContext` — `IAlertContextProps extends React.HTMLAttributes<HTMLSpanElement>`
88
+
89
+ | Prop | Тип | Обязателен | Описание |
90
+ |---|---|---|---|
91
+ | `type` | `Exclude<EAlertType, EAlertType.FEATURE>` | Да | Семантический тип. FEATURE запрещён на уровне типов. |
92
+ | `renderIcon` | `React.ReactNode` | Нет | Кастомная иконка. Если не передана — рендерится дефолтная 16px иконка, соответствующая `type`. |
93
+ | `children` | `React.ReactNode` | Нет | Текст сообщения — заворачивается в `<Text size={B4} type={...}>`. |
94
+ | `...HTMLSpanAttributes` | — | — | Все стандартные атрибуты `<span>`, включая `className`. |
95
+
96
+ ### `AlertProcess` — `IAlertProcessProps extends React.HTMLAttributes<HTMLDivElement>`
97
+
98
+ | Prop | Тип | По умолчанию | Описание |
99
+ |---|---|---|---|
100
+ | `type` | `EAlertType` | — (обязателен) | Любой из пяти типов, включая `FEATURE`. |
101
+ | `closable` | `boolean` | `false` | Если `true` — добавляется `ButtonIcon` с крестиком в правом верхнем углу. |
102
+ | `onClose` | `() => void` | — | Коллбек при нажатии на крестик. AlertProcess сам скрывает себя (`closed` state). |
103
+ | `renderIcon` | `React.ReactNode` | — | Кастомная иконка слева. По умолчанию — дефолтная 20px иконка по `type`. |
104
+ | `borderRadius` | `EAlertProcessBorderRadius` | `MD` (12px) | `MD` = 12px, `LG` = 24px. |
105
+ | `children` | `React.ReactNode` | — | **Без Typography не задаёт стили текста** — потребитель сам заворачивает текст в `Typography`-компоненты. Может содержать `AlertProcess.Spoiler`. |
106
+ | `...HTMLDivAttributes` | — | — | Все стандартные атрибуты `<div>`. |
107
+
108
+ ### `AlertProcess.Spoiler` — `IAlertProcessSpoilerProps extends React.HTMLAttributes<HTMLDivElement>`
109
+
110
+ Доступен через `Object.assign` как property компонента: `<AlertProcess.Spoiler>`.
111
+
112
+ | Prop | Тип | Описание |
113
+ |---|---|---|
114
+ | `open` | `boolean` | Контролируемое состояние раскрытия. Неконтролируемого режима нет. |
115
+ | `onOpen` | `(open: boolean) => void` | Коллбек при клике на треугольник. Потребитель обязан обновить `open`. |
116
+ | `children` | `React.ReactNode` | Скрываемый контент. |
117
+
118
+ `EAlertProcessBorderRadius` — enum: `MD = "md"`, `LG = "lg"`.
119
+
120
+ ---
121
+
122
+ ## Ключевые особенности реализации
123
+
124
+ ### `ALERT_TYPE_TO_CLASS_NAME_MAP` принимает `styles` аргументом
125
+
126
+ ```ts
127
+ [EAlertType.INFO]: (styles) => styles.alertTypeInfo
128
+ ```
129
+
130
+ Маппинг — не прямой `type → "alertTypeInfo"`, а **функция `(styles) => string`**. Это
131
+ потому что CSS-модули отдают хэшированные имена, и каждая локация (`AlertContext`,
132
+ `AlertProcess`) импортирует свои стили. Передача `styles` в маппинг позволяет
133
+ переиспользовать его без дублирования кода под разные CSS-модули.
134
+
135
+ При добавлении нового `EAlertType` — добавляй ключ в `ALERT_TYPE_TO_CLASS_NAME_MAP`
136
+ **и** соответствующий класс `.alertType{Xxx}` в оба LESS-файла
137
+ (`AlertContext.module.less`, `AlertProcess.module.less`).
138
+
139
+ ### `AlertContext.tsx`: маппинг type → `EFontType` для Text
140
+
141
+ ```ts
142
+ alertTypeToFontTypeMap = {
143
+ INFO: EFontType.INFO,
144
+ WARNING: EFontType.WARNING,
145
+ ERROR: EFontType.ERROR,
146
+ SYSTEM: EFontType.SECONDARY, // ← SYSTEM использует SECONDARY, не SYSTEM
147
+ }
148
+ ```
149
+
150
+ `SYSTEM` маппится в `SECONDARY` намеренно — цвет текста для системных сообщений
151
+ совпадает со вторичным текстом. Не менять без дизайнерского согласования.
152
+
153
+ ### `AlertProcess`: closed-state держится внутри компонента
154
+
155
+ При клике на крестик AlertProcess устанавливает `closed=true` и возвращает `null`.
156
+ Повторно показать тот же инстанс нельзя — потребитель должен либо перерендерить
157
+ его с новым key, либо управлять видимостью снаружи (не через `closable`, а своим
158
+ if/else). `onClose` здесь — сигнал "пользователь закрыл", а не контролируемое
159
+ состояние.
160
+
161
+ ### `AlertProcessContext` и `Spoiler` ↔ `AlertProcess` коммуникация
162
+
163
+ `AlertProcess.Spoiler` в `useEffect` устанавливает `hasSpoiler=true` в контексте
164
+ при монтировании и сбрасывает при размонтировании. `AlertProcess` читает `hasSpoiler`
165
+ и добавляет класс `.withSpoiler` (min-height: 40px), чтобы оставить место под
166
+ кнопку раскрытия.
167
+
168
+ Без `AlertProcess.Spoiler` внутри `AlertProcess` контекст не имеет эффекта —
169
+ дефолтные значения (`hasSpoiler: false`, `setHasSpoiler: noop`) безопасны.
170
+
171
+ ### `Object.assign(forwardRef, { Spoiler })` для compound-компонента
172
+
173
+ ```tsx
174
+ export const AlertProcess = Object.assign(
175
+ React.forwardRef(...),
176
+ { Spoiler: AlertProcessSpoiler },
177
+ );
178
+ ```
179
+
180
+ Делает `AlertProcess.Spoiler` доступным как property. Альтернативный паттерн
181
+ (`AlertProcess.Spoiler = AlertProcessSpoiler` без Object.assign) не работает
182
+ с forwardRef в TypeScript — теряется типизация Spoiler. Не упрощать.
183
+
184
+ `displayName` и `Spoiler` устанавливаются **повторно** после Object.assign
185
+ (`AlertProcess.displayName = ...`, `AlertProcess.Spoiler = ...`) — это тоже
186
+ особенность из-за ограничений TS, не убирать.
187
+
188
+ ### `AlertProcessSpoiler`: анимация через max-height в LESS
189
+
190
+ Максимальная высота = 1000px (`max-height: 1000px`) — жёсткий лимит. Контент
191
+ выше 1000px будет обрезан. При необходимости — увеличить константу в LESS.
192
+
193
+ ### `data-tx={process.env.npm_package_version}`
194
+
195
+ Оба компонента ставят `data-tx` с версией пакета — используется для аналитики
196
+ и дебага "из какой версии библиотеки отрендерилось". Не удалять.
197
+
198
+ ---
199
+
200
+ ## Инварианты
201
+
202
+ - **`AlertContext` — `<span role="alert">`**, не `<div>`. Инлайн-семантика важна:
203
+ компонент задуман как inline-блок рядом с полями форм.
204
+ - **`AlertContext` type НЕ принимает `FEATURE`** — тип `Exclude<EAlertType, EAlertType.FEATURE>`.
205
+ Если нужен FEATURE-контекст — создавай отдельный компонент, не расширяй AlertContext.
206
+ - **`AlertProcess` — `<div>`**, не `<section>` или `<aside>`. Семантическую роль
207
+ потребитель может задать через `role` в props.
208
+ - **`forwardRef`** — обязателен на `AlertContext` и `AlertProcess`. Не убирать.
209
+ - **`AlertProcessSpoiler` — обычный `React.FC`** без forwardRef. Исключение из
210
+ общего правила: компонент внутренний к `AlertProcess`, ref на его root не имеет
211
+ публичной ценности. Можно привести к forwardRef в рамках AI refactoring, но это
212
+ breaking — изменит сигнатуру типа `AlertProcess.Spoiler`.
213
+ - **`EAlertType` значения** (`"info"`, `"warning"`, `"error"`, `"system"`, `"feature"`) —
214
+ публичное API, не переименовывать.
215
+ - **`EAlertProcessBorderRadius`** (`"md"`, `"lg"`) — публичное API, не переименовывать.
216
+ - **Toggle-логика `Spoiler`** — полностью controlled (`open` + `onOpen`). Не добавлять
217
+ uncontrolled fallback без согласования API.
218
+ - **`paletteIndex` у иконок** — часть контракта с `@sberbusiness/icons-next`. Не
219
+ менять без согласования с дизайн-токенами цветовых палитр.
220
+ - **`data-tx`** — использовать `process.env.npm_package_version` (Vite подставляет
221
+ во время сборки). Не хардкодить.
222
+
223
+ ---
224
+
225
+ ## Accessibility
226
+
227
+ ### AlertContext
228
+ - **`role="alert"`** — объявление "alert" для screen reader. Screen reader прерывает
229
+ чтение и зачитывает новое содержимое при появлении элемента. Не убирать role.
230
+ - **Полностью inline** — текст доступен как текст, иконка декоративна. Если нужно
231
+ явно скрыть иконку от screen reader — потребитель передаёт `renderIcon` с
232
+ `aria-hidden="true"`.
233
+
234
+ ### AlertProcess
235
+ - **Нет `role`** по умолчанию — компонент трактуется как обычный блок контента.
236
+ Если сообщение критическое, потребитель обязан передать `role="alert"` или
237
+ `role="status"` через `...rest`.
238
+ - **Кнопка закрытия (`ButtonIcon`)** не имеет встроенного `aria-label` — это
239
+ баг/пробел: потребитель должен знать, что ButtonIcon требует `aria-label` от него.
240
+ В текущей реализации `AlertProcess` НЕ пробрасывает возможность задать
241
+ `aria-label` на кнопку закрытия. При AI refactoring — добавить prop `closeAriaLabel`.
242
+ - **Spoiler toggle** — `ButtonIcon` с иконкой каретки, тоже без `aria-expanded`
243
+ и `aria-label`. Тот же баг a11y, тот же план.
244
+ - **Клавиатура**: `ButtonIcon` — нативный `<button>`, работает Tab/Enter/Space.
245
+ Никаких фокус-ловушек или кастомной навигации компонент не добавляет.
246
+
247
+ ---
248
+
249
+ ## Дизайн-токены
250
+
251
+ **AlertContext** — только цвета текста:
252
+ ```
253
+ --triplex-next-AlertContext-{Error|Info|Warning|System}_Color
254
+ ```
255
+ У SYSTEM отдельного токена нет — используется цвет SECONDARY-типа из Typography.
256
+
257
+ **AlertProcess** — только фон блока:
258
+ ```
259
+ --triplex-next-AlertProcess-{Error|Info|Warning|System|Feature}_Background
260
+ ```
261
+
262
+ Цвет текста внутри `AlertProcess` задаёт потребитель через `Typography`-компоненты,
263
+ компонент-обёртка не хардкодит.
264
+
265
+ ---
266
+
267
+ ## Связанные компоненты
268
+
269
+ - `Typography` (`Text`, `Title`) — `AlertContext` использует `Text` внутри;
270
+ `AlertProcess` ожидает Typography-компоненты в `children` от потребителя.
271
+ - `ButtonIcon` (`src/components/Button/ButtonIcon.tsx`) — используется для кнопок
272
+ закрытия и раскрытия спойлера.
273
+ - `@sberbusiness/icons-next` — источник дефолтных иконок
274
+ (`InfoStrokeStsIcon16/20`, `WarningStrokeStsIcon16/20`, `ErrorStrokeStsIcon16/20`,
275
+ `SystemStrokeStsIcon16/20`, `DefaulticonStrokePrdIcon20`, `CrossStrokeSrvIcon16`,
276
+ `CaretdownStrokeSrvIcon16`).
277
+ - `Notification` (`src/components/Notification`) — похожий по назначению, но
278
+ toast-формат (поверх контента, авто-закрытие).
279
+ - `Spoiler` (`src/components/Spoiler`) — отдельный компонент для сворачиваемого
280
+ контента. `AlertProcess.Spoiler` не использует его, реализация своя (проще).
281
+
282
+ ---
283
+
284
+ ## Stories
285
+
286
+ `AlertContext`: `stories/Alerts/AlertContext.stories.tsx`
287
+ Файлы примеров: `stories/Alerts/examples/AlertContext/`
288
+
289
+ | Story | Example file | Что демонстрирует |
290
+ |---|---|---|
291
+ | `Playground` | `PlaygroundExample.tsx` | Интерактивный контроль `type` и `children` |
292
+ | `Default` | `DefaultExample.tsx` | Базовое использование с INFO |
293
+ | `Types` | `TypesExample.tsx` | Все 4 типа (без FEATURE) |
294
+ | `WithCustomIcon` | `WithCustomIconExample.tsx` | Переопределение иконки через `renderIcon` |
295
+
296
+ `AlertProcess`: `stories/Alerts/AlertProcess.stories.tsx`
297
+ Файлы примеров: `stories/Alerts/examples/AlertProcess/`
298
+
299
+ | Story | Example file | Что демонстрирует |
300
+ |---|---|---|
301
+ | `Playground` | `PlaygroundExample.tsx` | Интерактивный контроль `type`, `closable`, `borderRadius`, `children` |
302
+ | `Default` | `DefaultExample.tsx` | Базовое использование |
303
+ | `Types` | `TypesExample.tsx` | Все 5 типов (включая FEATURE) |
304
+ | `BorderRadius` | `BorderRadiusExample.tsx` | MD (12px) vs LG (24px) |
305
+ | `WithCustomIcon` | `WithCustomIconExample.tsx` | Кастомная иконка |
306
+ | `Closable` | `ClosableExample.tsx` | Кнопка закрытия |
307
+ | `WithButtonLink` | `WithButtonLinkExample.tsx` | Кнопка-ссылка в контенте |
308
+ | `WithLink` | `WithLinkExample.tsx` | Обычная ссылка в контенте |
309
+ | `WithSpoiler` | `WithSpoilerExample.tsx` | Использование `AlertProcess.Spoiler` |
310
+
311
+ ---
312
+
313
+ ## История изменений
314
+
315
+ | Дата | Изменение |
316
+ |---|---|
317
+ | 2026-04-18 | Создан документ |
@@ -0,0 +1,225 @@
1
+ ---
2
+ component: Amount
3
+ category: Display
4
+ figma-node: ""
5
+ figma-file: ""
6
+ related: [AmountField, Typography]
7
+ tokens: []
8
+ stories: stories/Amount/Amount.stories.tsx
9
+ version: "1.0"
10
+ ---
11
+
12
+ # Amount
13
+
14
+ ## Назначение
15
+
16
+ Display-компонент для отображения денежной суммы. Форматирует число с разделителями
17
+ групп (неразрывный пробел) и фиксированной дробной частью, опционально добавляет
18
+ сокращение валюты справа и подсказку через `title`. Поддерживает адаптивное
19
+ уменьшение шрифта при длинных значениях.
20
+
21
+ Компонент **только визуализирует**, не принимает ввод — для поля ввода денежной
22
+ суммы используй `AmountField`.
23
+
24
+ Используй когда: нужно вывести сумму в тексте, таблице, детали карточки. Когда
25
+ важна единая визуальная форма отображения чисел по всей библиотеке.
26
+ Не используй когда: сумму нужно вводить (возьми `AmountField`); нужна произвольная
27
+ числовая метка без валюты и форматирования (используй обычный `Text`).
28
+
29
+ ---
30
+
31
+ ## Файловая структура
32
+
33
+ ```text
34
+ src/components/Amount/
35
+ ├── Amount.tsx # React.FC, НЕ forwardRef
36
+ ├── index.ts # Barrel export
37
+ ├── styles/Amount.module.less # Только .adaptive класс
38
+ └── __tests__/Amount.test.tsx
39
+ ```
40
+
41
+ Зависимости:
42
+ - `@sberbusiness/triplex-next/utils/amountUtils` → `formatAmount` (использует `big.js`).
43
+ - `@sberbusiness/triplex-next/consts/AmountConst` → константы разделителей
44
+ (`DecimalComma`, `DecimalPoint`, `GroupSeparator`).
45
+
46
+ ---
47
+
48
+ ## Варианты и props
49
+
50
+ ### `IAmountProps extends React.HTMLAttributes<HTMLSpanElement>`
51
+
52
+ | Prop | Тип | По умолчанию | Описание |
53
+ |---|---|---|---|
54
+ | `value` | `string` | — (обязателен) | Числовое значение как строка. Может содержать `.` или `,`, пробелы, знак `+`/`-`. Внутри форматируется через `big.js` → устойчиво к floating-point. |
55
+ | `fractionLength` | `0 \| 1 \| 2 \| 3 \| 4` | `2` (из `AmountConst.FractionLength`) | Количество знаков после запятой. Тип **литерал-union** — нельзя передать произвольный `number`. Для `0` потребитель обязан передать **именно `0`**, не `null`/`undefined` (undefined даст дефолт 2). |
56
+ | `currency` | `string` | — | Если указан — справа от суммы добавляется `\u00A0{currency}` (неразрывный пробел + строка). Не задано → валюта не отображается. |
57
+ | `currencyTitle` | `string` | — | Подсказка (title-атрибут) для валюты — обычно полное название ("Российские рубли" для "RUB"). Применяется к `<span>`, обёрнутому вокруг currency. |
58
+ | `adaptive` | `boolean` | `false` | Если `true` и длина форматированной строки ≥ 14 — добавляется класс `.adaptive` (font-size: 10px, line-height: 12px через `!important`). |
59
+ | `dataTestId` | `string` | — | **Кастомный prop**, не пробрасывается на root `<span>`. Используется только для `data-test-id` на внутренние `<span>` (суффиксы `__amount`, `__currencyName`). |
60
+ | `className` | `string` | — | Объединяется с `.adaptive` через `clsx`. |
61
+ | `...HTMLSpanAttributes` | — | — | Всё остальное спредится на root `<span>`. |
62
+
63
+ ---
64
+
65
+ ## Ключевые особенности реализации
66
+
67
+ ### Компонент — `React.FC`, НЕ `forwardRef`
68
+
69
+ ```tsx
70
+ export const Amount: React.FC<IAmountProps> = ({ ... }) => { ... }
71
+ ```
72
+
73
+ Это **исключение из правила библиотеки про обязательный forwardRef**. Причина
74
+ исторически неизвестна; при AI refactoring компонент должен быть переведён на
75
+ `React.forwardRef<HTMLSpanElement, IAmountProps>`. Это non-breaking изменение.
76
+ До рефакторинга — не добавлять ref-логику, она не пройдёт TypeScript.
77
+
78
+ ### `dataTestId` — НЕ `data-testid`
79
+
80
+ Имя prop — camelCase `dataTestId`. Пропускается через проп-деструктуризацию и
81
+ применяется только к внутренним спанам:
82
+ - `{dataTestId}__amount` — на спан с самим числом.
83
+ - `{dataTestId}__currencyName` — на спан с валютой.
84
+
85
+ На root `<span>` `dataTestId` не попадает автоматически — потребитель, если нужно,
86
+ передаёт `data-test-id` через `...restProps`. Это намеренная двухуровневая
87
+ структура для тестов.
88
+
89
+ ### Замена дефис-минуса на настоящий знак минус
90
+
91
+ ```ts
92
+ if (formattedAmount[0] == "-") {
93
+ formattedAmount = formattedAmount.replace("\u002D", "\u2212");
94
+ }
95
+ ```
96
+
97
+ `\u002D` — ASCII hyphen-minus, `\u2212` — Unicode MINUS SIGN. Screen reader
98
+ корректно произносит `\u2212` как "минус", а `\u002D` обычно читается как "дефис"
99
+ или пропускается. **Не убирать** — это осознанная a11y-особенность.
100
+
101
+ Замена применяется ТОЛЬКО в первой позиции — если минус в середине (например,
102
+ разделитель диапазона "100–200"), он не будет заменён.
103
+
104
+ ### Неразрывный пробел перед валютой
105
+
106
+ ```tsx
107
+ renderCurrencyName = () => [
108
+ "\u00A0", // NBSP
109
+ <span ...>{currency}</span>,
110
+ ]
111
+ ```
112
+
113
+ Между числом и валютой вставляется NBSP (`\u00A0`), не обычный пробел. Это
114
+ предотвращает перенос валюты на следующую строку при переполнении.
115
+
116
+ ### Адаптивный шрифт через `!important`
117
+
118
+ `.adaptive { font-size: 10px !important; line-height: 12px !important; }` —
119
+ `!important` нужен, чтобы перебить родительский Typography-стиль. Если потребитель
120
+ хочет переопределить размер — `className` с более специфичным селектором тоже
121
+ должен использовать `!important`. Это компромисс ради надёжного поведения
122
+ в контексте таблиц/карточек.
123
+
124
+ Порог `adaptiveAmountLength = 14` — длина именно **форматированной** строки (после
125
+ вставки разделителей групп). Не равна количеству значащих цифр.
126
+
127
+ ### `formatAmount` — большая часть логики вне компонента
128
+
129
+ `Amount.tsx` — тонкая обёртка. Вся сложность форматирования в `utils/amountUtils.ts`:
130
+ - Использует `big.js` для чисел (устойчиво к floating-point).
131
+ - `Big.RM = 0` — режим без округления (truncate).
132
+ - Принимает запятую и точку как десятичный разделитель.
133
+ - Поддерживает знак "+" (сохраняется в выводе).
134
+ - Поддерживает `separateGroups` и `fillFraction` — но **Amount не прокидывает эти
135
+ флаги**. Для customизации форматирования нужно расширить Amount или использовать
136
+ `formatAmount` напрямую.
137
+
138
+ ### `data-tx={process.env.npm_package_version}`
139
+
140
+ На root `<span>` выставляется `data-tx` с версией пакета (Vite подставляет при
141
+ сборке). Не удалять.
142
+
143
+ ---
144
+
145
+ ## Инварианты
146
+
147
+ - **`IAmountProps extends React.HTMLAttributes<HTMLSpanElement>`** — не менять на
148
+ `HTMLDivElement`. Компонент inline по дизайну.
149
+ - **`value` только `string`** — не `number`, не `Big`. Компонент не принимает
150
+ `number` напрямую (в отличие от `formatAmount`, который принимает `string | Big`).
151
+ Потребитель должен сам привести число к строке.
152
+ - **`fractionLength` литеральный union `0 \| 1 \| 2 \| 3 \| 4`** — не расширять
153
+ до `number`, это ограничение защищает от визуально уродливых значений (20 знаков).
154
+ - **Замена `\u002D` → `\u2212` в минусе** — не удалять. A11y.
155
+ - **NBSP (`\u00A0`) перед валютой** — не заменять на обычный пробел.
156
+ - **`dataTestId` как camelCase prop** — не переименовывать в `data-testid` без
157
+ breaking-change согласования.
158
+ - **`.adaptive` с `!important`** — не убирать `!important` без параллельной
159
+ правки потребителей (которые полагаются на его работу в таблицах).
160
+ - **`adaptiveAmountLength = 14`** — константа внутри файла, не выносить в props
161
+ без дизайнерского согласования.
162
+ - **`formatAmount` вызов не мемоизируется** — если это станет bottleneck (большие
163
+ таблицы), оборачивай Amount в `React.memo` снаружи. Не добавлять `useMemo`
164
+ внутрь без профиля.
165
+
166
+ ---
167
+
168
+ ## Accessibility
169
+
170
+ - **Замена дефиса на настоящий минус (`\u2212`)** — screen reader корректно
171
+ озвучивает знак "минус". Это ключевая a11y-особенность компонента.
172
+ - **`currency` как отдельный `<span>`** внутри — позволяет потребителю, при
173
+ необходимости, добавить `aria-label` через children override.
174
+ - **`title={currencyTitle}`** — при наведении курсора показывает полное название
175
+ валюты (например, "Российские рубли" для "RUB"). Screen reader читает title
176
+ как дополнительное описание.
177
+ - **Нет `aria-label` по умолчанию** — если нужно озвучить значение целиком с валютой
178
+ ("восемь миллионов девятьсот шестьдесят семь тысяч четыреста пятьдесят два рубля
179
+ тридцать одна копейка"), потребитель должен сформировать его сам и передать
180
+ через `aria-label` в `...restProps`. Автоматического склонения названия валюты
181
+ компонент не делает.
182
+
183
+ ---
184
+
185
+ ## Дизайн-токены
186
+
187
+ Нет — компонент не хардкодит цветов и использует наследуемый от родителя шрифт.
188
+ Единственное исключение — класс `.adaptive` с фиксированными `10px/12px`
189
+ (не через токены). Это кандидат на рефакторинг с введением токенов.
190
+
191
+ ---
192
+
193
+ ## Связанные компоненты
194
+
195
+ - `AmountField` (`src/components/AmountField`) — input-аналог для ввода суммы.
196
+ Использует тот же `formatAmount` и ту же знак-замену.
197
+ - `Typography` — Amount наследует шрифт от родителя; обычно оборачивается в
198
+ `Text` / `Title` нужного размера.
199
+ - `formatAmount` / `amountComparator` (`src/utils/amountUtils.ts`) — утилиты,
200
+ которые Amount использует внутри, но также могут быть использованы напрямую
201
+ потребителем для консистентного форматирования в местах, где Amount-компонент
202
+ не подходит.
203
+ - `AmountConst` (`src/consts/AmountConst`) — источник констант:
204
+ `FractionLength=2`, `DecimalComma=","`, `DecimalPoint="."`, `GroupSeparator="\u00A0"`.
205
+
206
+ ---
207
+
208
+ ## Stories
209
+
210
+ `stories/Amount/Amount.stories.tsx`
211
+ Файлы примеров: `stories/Amount/examples/`
212
+
213
+ | Story | Example file | Что демонстрирует |
214
+ |---|---|---|
215
+ | `Playground` | `PlaygroundExample.tsx` | Интерактивный контроль всех props |
216
+ | `Default` | `DefaultExample.tsx` | Базовое использование с RUB |
217
+ | `Example` | `ShowcaseExample.tsx` | Расширенный пример (разные значения, знаки) |
218
+
219
+ ---
220
+
221
+ ## История изменений
222
+
223
+ | Дата | Изменение |
224
+ |---|---|
225
+ | 2026-04-18 | Создан документ |