@sberbusiness/triplex-next-mcp-server 1.41.0-beta → 1.43.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.
- package/bundle/components/AlertProcess.md +460 -0
- package/bundle/components/Amount.md +145 -169
- package/bundle/components/Badge.md +155 -219
- package/bundle/components/Body.md +108 -116
- package/bundle/components/Button.md +1 -0
- package/bundle/components/CarouselExtended.md +355 -194
- package/bundle/components/Checkbox.md +7 -1
- package/bundle/components/CheckboxTreeExtended.md +149 -248
- package/bundle/components/CheckboxXGroup.md +2 -0
- package/bundle/components/CheckboxYGroup.md +7 -2
- package/bundle/components/ChipGroup.md +195 -126
- package/bundle/components/ComposedKeyDownListener.md +323 -0
- package/bundle/components/FooterPage.md +2 -1
- package/bundle/components/HeaderPage.md +2 -1
- package/bundle/components/Island.md +100 -12
- package/bundle/components/KeyDownListener.md +11 -72
- package/bundle/components/LightBox.md +6 -0
- package/bundle/components/LoaderSmall.md +230 -0
- package/bundle/components/MaskedField.md +481 -0
- package/bundle/components/MediaWidth.md +252 -108
- package/bundle/components/MobileView.md +192 -68
- package/bundle/components/ModalWindow.md +3 -1
- package/bundle/components/Notification.md +21 -3
- package/bundle/components/Page.md +3 -1
- package/bundle/components/Pagination.md +20 -0
- package/bundle/components/SelectExtendedField.md +691 -236
- package/bundle/components/SliderExtended.md +358 -222
- package/bundle/components/TabsExtended.md +380 -194
- package/bundle/components/UnorderedList.md +254 -0
- package/bundle/components/UnorderedListExtended.md +255 -0
- package/bundle/components/WindowResizeListener.md +249 -0
- package/bundle/guides/commits.md +66 -3
- package/bundle/guides/context.md +26 -0
- package/bundle/guides/stories.md +3 -1
- package/bundle/guides/template.md +1 -1
- package/bundle/manifest.json +64 -21
- package/bundle/release-notes/1.41.1.mdx +18 -0
- package/bundle/release-notes/1.42.0.mdx +81 -0
- package/bundle/release-notes/1.43.0.mdx +94 -0
- package/bundle/release-notes/1.44.0.mdx +7 -0
- package/package.json +1 -1
|
@@ -108,36 +108,9 @@ version: "1.0"
|
|
|
108
108
|
|
|
109
109
|
### `ComposedKeyDownListener` (`src/components/KeyDownListener/ComposedKeyDownListener.tsx`)
|
|
110
110
|
|
|
111
|
-
Композитор:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
Собственного AI.md пока не имеет — вся его логика описана здесь. По правилу
|
|
116
|
-
`docs/ai/CONTEXT.md` § «Когда создавать `{ComponentName}-ai.md`» он его
|
|
117
|
-
заслуживает (оба условия выполнены: barrel-экспорт + собственный prop
|
|
118
|
-
`keyDownListeners`), но по scope задачи TRI-48 соседние экспортируемые
|
|
119
|
-
компоненты выносятся в отдельные задачи. Компонент добавлен отдельной строкой в
|
|
120
|
-
`docs/ai/ROADMAP.md`, документ будет заведён своей задачей. Следствие, о котором
|
|
121
|
-
нужно знать до тех пор: `scripts/generateMcpData.ts` собирает записи по файлам
|
|
122
|
-
`src/components/*/*-ai.md`, поэтому отдельной записи в `mcp-data.json` у
|
|
123
|
-
`ComposedKeyDownListener` нет — агент найдёт его только через этот документ.
|
|
124
|
-
|
|
125
|
-
| Prop | Тип | Описание |
|
|
126
|
-
|---|---|---|
|
|
127
|
-
| `keyDownListeners` | `IKeyDownListenerProps[]` | Конфигурация слушателей. Используются только `eventKeyCode` и `onMatch`, поле `children` каждого элемента игнорируется |
|
|
128
|
-
| `children` | `React.ReactNode` | Содержимое. Рендерится как есть; при пустом `keyDownListeners` — просто `children` |
|
|
129
|
-
|
|
130
|
-
Первый элемент массива оказывается самым внутренним слушателем. На порядок
|
|
131
|
-
срабатывания это влияет слабо — все слушатели подписаны на `window` независимо
|
|
132
|
-
друг от друга, а порядок вызова совпадает с порядком элементов массива.
|
|
133
|
-
|
|
134
|
-
**Ограничение: длина `keyDownListeners` должна быть стабильной между рендерами.**
|
|
135
|
-
Глубина вложенности равна длине массива, поэтому при её изменении на позиции,
|
|
136
|
-
где раньше были `children`, React монтирует новый `KeyDownListener`, а сами
|
|
137
|
-
`children` уезжают на уровень ниже и перемонтируются: DOM-узлы пересоздаются,
|
|
138
|
-
введённые значения инпутов, фокус и текущие анимации теряются. Если набор
|
|
139
|
-
слушателей динамический — держи массив постоянной длины (например, с
|
|
140
|
-
`onMatch`-заглушками) или используй `KeyDownListener` напрямую.
|
|
111
|
+
Композитор: рендерит по одному `KeyDownListener` на элемент `keyDownListeners`.
|
|
112
|
+
Используй, когда нужно несколько разных клавиш с разными обработчиками.
|
|
113
|
+
Документация — `src/components/KeyDownListener/ComposedKeyDownListener-ai.md`.
|
|
141
114
|
|
|
142
115
|
### Потребители внутри библиотеки
|
|
143
116
|
|
|
@@ -159,8 +132,13 @@ version: "1.0"
|
|
|
159
132
|
| `Playground` | `Playground.tsx` | Интерактивный выбор `eventKeyCode` и счётчик срабатываний `onMatch` |
|
|
160
133
|
| `Default` | `Default.tsx` | Слушатель одной клавиши: панель скрывается по `Esc` |
|
|
161
134
|
| `WithMultipleKeys` | `WithMultipleKeys.tsx` | Массив кодов в `eventKeyCode`; нажатая клавиша различается по `event.keyCode` |
|
|
162
|
-
|
|
163
|
-
|
|
135
|
+
|
|
136
|
+
Набор целиком исключён из скриншот-тестов (`testRunner: { skip: true }` в `meta`):
|
|
137
|
+
собственной разметки компонент не рендерит, на скриншот попадала бы только
|
|
138
|
+
обвязка примеров. Поведение слушателя покрыто unit-тестами.
|
|
139
|
+
|
|
140
|
+
Примеры `ComposedKeyDownListener` живут в собственном наборе stories —
|
|
141
|
+
`stories/ComposedKeyDownListener/`.
|
|
164
142
|
|
|
165
143
|
---
|
|
166
144
|
|
|
@@ -168,6 +146,7 @@ version: "1.0"
|
|
|
168
146
|
|
|
169
147
|
| Дата | Изменение |
|
|
170
148
|
|---|---|
|
|
149
|
+
| 2026-08-11 | TRI-112: у `ComposedKeyDownListener` появились собственный `ComposedKeyDownListener-ai.md` и набор stories `stories/ComposedKeyDownListener/`; раздел «Связанные компоненты» сокращён до ссылки, story `Example` (демонстрация композитора) перенесена в новый набор. Ограничение на стабильную длину `keyDownListeners` снято — композитор рендерит слушателей соседями к `children`. Набор stories `KeyDownListener` исключён из скриншот-тестов, story `VisualTests` и baseline удалены — визуального интерфейса у компонента нет. Реализация самого `KeyDownListener` не менялась. |
|
|
171
150
|
| 2026-08-04 | По ревью PR #502: интерфейс props `IComposedKeyDownListenerProps` стал экспортируемым — публичная поверхность пакета расширена аддитивно. `ComposedKeyDownListener` добавлен отдельной строкой в `docs/ai/ROADMAP.md`, собственный AI.md вынесен в отдельную задачу. |
|
|
172
151
|
| 2026-08-04 | Создан документ. AI-рефакторинг (TRI-48): JSDoc на props `IKeyDownListenerProps` и `ComposedKeyDownListener`, ветвление в `handleKeyDown` сведено к одной проверке (снят `eslint-disable`), в `ComposedKeyDownListener` убран `as JSX.Element` и добавлен `displayName`, unit-тесты (16 кейсов на оба компонента), stories по modern pattern. Публичный API не менялся; компонент остаётся class-компонентом, `forwardRef` осознанно отсутствует. |
|
|
173
152
|
|
|
@@ -228,43 +207,3 @@ export const WithMultipleKeys = () => {
|
|
|
228
207
|
};
|
|
229
208
|
```
|
|
230
209
|
|
|
231
|
-
### Example
|
|
232
|
-
|
|
233
|
-
`stories/KeyDownListener/examples/Example.tsx`
|
|
234
|
-
|
|
235
|
-
```tsx
|
|
236
|
-
import React, { useState } from "react";
|
|
237
|
-
import { ComposedKeyDownListener, EVENT_KEY_CODES } from "@sberbusiness/triplex-next";
|
|
238
|
-
|
|
239
|
-
export const Example = () => {
|
|
240
|
-
const [result, setResult] = useState<string | null>(null);
|
|
241
|
-
|
|
242
|
-
const keyDownListeners = [
|
|
243
|
-
{ eventKeyCode: EVENT_KEY_CODES.ENTER, onMatch: () => setResult("Подтверждено по Enter") },
|
|
244
|
-
{ eventKeyCode: EVENT_KEY_CODES.ESCAPE, onMatch: () => setResult("Отменено по Esc") },
|
|
245
|
-
];
|
|
246
|
-
|
|
247
|
-
if (result !== null) {
|
|
248
|
-
return (
|
|
249
|
-
<div style={{ display: "flex", flexDirection: "column", gap: "16px", maxWidth: "400px" }}>
|
|
250
|
-
<div>{result}</div>
|
|
251
|
-
<button type="button" onClick={() => setResult(null)}>
|
|
252
|
-
Показать панель снова
|
|
253
|
-
</button>
|
|
254
|
-
</div>
|
|
255
|
-
);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
return (
|
|
259
|
-
<ComposedKeyDownListener keyDownListeners={keyDownListeners}>
|
|
260
|
-
<div style={{ display: "flex", flexDirection: "column", gap: "16px", maxWidth: "400px" }}>
|
|
261
|
-
<div>Панель с горячими клавишами: Enter подтверждает, Esc отменяет.</div>
|
|
262
|
-
<div style={{ border: "1px dashed rgb(125, 131, 138)", borderRadius: "4px", padding: "16px" }}>
|
|
263
|
-
Ожидание нажатия клавиши.
|
|
264
|
-
</div>
|
|
265
|
-
</div>
|
|
266
|
-
</ComposedKeyDownListener>
|
|
267
|
-
);
|
|
268
|
-
};
|
|
269
|
-
```
|
|
270
|
-
|
|
@@ -126,6 +126,11 @@ version: "1.0"
|
|
|
126
126
|
последнего (при переключении роутов второй лайтбокс может смонтироваться раньше, чем
|
|
127
127
|
размонтируется первый). Аналогичный счётчик в `LightBoxViewManager` управляет классами
|
|
128
128
|
mount-ноды (`LightBoxMountNodeViewManager`, `LB-*`).
|
|
129
|
+
- **Локальные z-index внутри лайтбокса** (стековый контекст создаёт `.lightBox`): контролы и
|
|
130
|
+
sticky-шапка/футер `Page` — 100/101, лоадеры `LightBox.Content` и `LightBox.SideOverlay` — 201,
|
|
131
|
+
`TopOverlay` — 500. `LoaderScreen` приходит с глобальным `@z-index-loader-screen` (10100), поэтому
|
|
132
|
+
обе обёртки лоадера обязаны переопределять его локальным значением — иначе лоадер перекрывает
|
|
133
|
+
`TopOverlay`.
|
|
129
134
|
- Баррел `index.ts` реэкспортирует `LightBox`, `enums`, `LightBoxSideOverlay` — сохранять.
|
|
130
135
|
- React 17 совместимость (синхронизация в release-0): React 18-only API не использовать.
|
|
131
136
|
|
|
@@ -194,6 +199,7 @@ version: "1.0"
|
|
|
194
199
|
| 2026-07-22 | Создан документ (Phase 1 AI-Ready). В том же изменении — AI-рефакторинг: JSDoc на props, общий `LightBoxArrow` для Prev/Next, хук `useLightBoxSidebarVisibility` для сайдбаров, устранение eslint-подавлений; публичный API не менялся |
|
|
195
200
|
| 2026-07-22 | Добавлен `export` к props-интерфейсам `ILightBoxControlsProps`, `ILightBoxCloseProps`, `ILightBoxPrevProps`, `ILightBoxNextProps`, `ILightBoxSideOverlayLoaderProps` (аддитивно, для консистентности с остальными интерфейсами компонента) |
|
|
196
201
|
| 2026-07-22 | Багфиксы по ревью PR #474: клавиатурные триггеры контролов целятся в видимую кнопку (стрелки не работали на desktop, Esc — на mobile); таймер-хак блокировки скролла заменён счётчиком смонтированных лайтбоксов; `LightBoxViewManager` снимает классы mount-ноды при размонтировании последнего менеджера |
|
|
202
|
+
| 2026-08-17 | Исправлено: `LightBox.TopOverlay` перекрывался лоадером `LightBox.Content`. У `.loadingContentOverlay` теперь локальный z-index (201) — выше sticky-шапки и футера `Page`, но ниже `TopOverlay` (500); раньше `LoaderScreen` шёл с глобальным `@z-index-loader-screen` (10100) |
|
|
197
203
|
|
|
198
204
|
---
|
|
199
205
|
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: LoaderSmall
|
|
3
|
+
category: Loaders
|
|
4
|
+
related: [LoaderMiddle, LoaderScreen, Button, Dropdown, ListItemLoading, SuggestField, SelectExtendedField]
|
|
5
|
+
tokens:
|
|
6
|
+
- --triplex-next-Loader-Element_Background_Brand
|
|
7
|
+
- --triplex-next-Loader-Element_Background_Neutral
|
|
8
|
+
stories: stories/Loaders/LoaderSmall/LoaderSmall.stories.tsx
|
|
9
|
+
version: "1.0"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# LoaderSmall
|
|
13
|
+
|
|
14
|
+
## Назначение
|
|
15
|
+
|
|
16
|
+
Компактный индикатор загрузки: три точки в ряд, гаснущие по очереди. Размер задаётся
|
|
17
|
+
общим для библиотеки `EComponentSize` (16 / 24 / 32 px по стороне), цвет — темой
|
|
18
|
+
(`ELoaderSmallTheme`). Анимация целиком на CSS, внутреннего состояния у компонента нет.
|
|
19
|
+
|
|
20
|
+
Используй когда: нужно показать загрузку внутри уже существующего элемента управления —
|
|
21
|
+
кнопки, поля с подсказками, выпадающего списка, строки списка.
|
|
22
|
+
|
|
23
|
+
Не используй когда:
|
|
24
|
+
- Грузится целая область или страница и место под крупный индикатор есть — возьми
|
|
25
|
+
`LoaderMiddle` (квадрат 64×64).
|
|
26
|
+
- Нужны подложка поверх контента, подпись и кнопки отмены — возьми `LoaderScreen`
|
|
27
|
+
(`type="small"` рендерит внутри себя именно `LoaderSmall`).
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Варианты и props
|
|
32
|
+
|
|
33
|
+
Компонент расширяет `React.HTMLAttributes<HTMLSpanElement>`: любой стандартный атрибут
|
|
34
|
+
`<span>` (`id`, `data-*`, `style`, обработчики) уходит на корневой элемент через `...rest`.
|
|
35
|
+
|
|
36
|
+
### Обязательные props
|
|
37
|
+
|
|
38
|
+
| Prop | Тип | Описание |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| `theme` | `ELoaderSmallTheme` | `BRAND` — брендовый цвет точек для светлых поверхностей; `NEUTRAL` — светлые точки для тёмных и цветных поверхностей (тёмная кнопка, цветной блок) |
|
|
41
|
+
| `size` | `EComponentSize` | `SM` — 16×16 (точки 4px), `MD` — 24×24 (6px), `LG` — 32×32 (8px) |
|
|
42
|
+
|
|
43
|
+
Оба props обязательны — значений по умолчанию нет, вызов `<LoaderSmall />` не типизируется.
|
|
44
|
+
Как правило `size` пробрасывается из размера родительского контрола: так делают `Button`,
|
|
45
|
+
`Dropdown`, `SuggestField`, `SelectExtendedField`.
|
|
46
|
+
|
|
47
|
+
### Опциональные props
|
|
48
|
+
|
|
49
|
+
Собственных опциональных props нет. `className` объединяется с базовыми классами
|
|
50
|
+
(`clsx`), а не заменяет их.
|
|
51
|
+
|
|
52
|
+
### Особенности API
|
|
53
|
+
|
|
54
|
+
- `ref` на корневой `<span>` **не пробрасывается** — компонент объявлен как `React.FC`
|
|
55
|
+
без `forwardRef`. Так же объявлен сосед `LoaderMiddle`. Если нужен доступ к DOM,
|
|
56
|
+
измеряй элемент-обёртку.
|
|
57
|
+
- Из barrel экспортируется enum `ELoaderSmallSize` (`sm` / `md` / `lg`). Компонентом он
|
|
58
|
+
**не используется** — размер задаётся `EComponentSize`. Enum остаётся в публичном API
|
|
59
|
+
ради обратной совместимости; в новом коде не применяй.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Дизайн-токены
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
--triplex-next-Loader-Element_Background_Brand
|
|
67
|
+
--triplex-next-Loader-Element_Background_Neutral
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
- `Element_Background_Brand` — цвет точек темы `BRAND` (`ColorBrand.50` в обеих темах).
|
|
71
|
+
- `Element_Background_Neutral` — цвет точек темы `NEUTRAL` (`ColorNeutralAlpha.0`).
|
|
72
|
+
|
|
73
|
+
Токены объявлены в `src/components/DesignTokens/components/Loader.ts` и общие для семейства
|
|
74
|
+
Loader: `Element_Background_Brand` использует также `LoaderMiddle`. Геометрия (размеры,
|
|
75
|
+
`gap`, радиус) и тайминги анимации (цикл 0.9s, сдвиг фазы 0.15s) заданы в
|
|
76
|
+
`styles/LoaderSmall.module.less` и снаружи не настраиваются.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Инварианты
|
|
81
|
+
|
|
82
|
+
- **Публичный контракт — `React.FC` без `forwardRef`.** Добавление ref-проброса расширяет
|
|
83
|
+
публичный API и требует отдельной задачи и записи в release notes.
|
|
84
|
+
- **Корневой элемент — `<span role="status" aria-label="loading">`.** На эту связку опираются
|
|
85
|
+
`LoaderSmall.test.tsx` и `LoaderScreen.test.tsx` (кейсы `type="small"`) через
|
|
86
|
+
`getByRole("status", { name: "loading" })`, а `Button.test.tsx` — через
|
|
87
|
+
`getByRole("status")` без фильтра по имени.
|
|
88
|
+
- **Разметка внутренностей фиксирована:** ровно три `<span class="dot dot1|dot2|dot3">`.
|
|
89
|
+
Порядок и количество завязаны на задержки анимации (`.dot2` — 0.15s, `.dot3` — 0.3s);
|
|
90
|
+
удаление или перестановка ломают визуальную последовательность.
|
|
91
|
+
- **`...rest` разливается после `role` и `aria-label`** — потребитель может их переопределить.
|
|
92
|
+
Порядок атрибутов в JSX менять не нужно: это осознанная точка расширения.
|
|
93
|
+
- **`displayName = "LoaderSmall"`** — используется в React DevTools.
|
|
94
|
+
- **Значения `ELoaderSmallTheme`** (`brand` / `neutral`) и наличие `ELoaderSmallSize` в barrel —
|
|
95
|
+
часть публичного API, удаление или переименование — breaking change.
|
|
96
|
+
- **`ILoaderSmallProps` — не только props этого компонента.** `DropdownMobileLoader` строит из
|
|
97
|
+
него свой публичный интерфейс: `IDropownMobileLoaderProps extends Omit<ILoaderSmallProps,
|
|
98
|
+
"theme" | "size">` (`src/components/Dropdown/mobile/DropdownMobileLoader.tsx:8`). Любое
|
|
99
|
+
изменение формы `ILoaderSmallProps` автоматически меняет публичный API и этого компонента.
|
|
100
|
+
- **Токены `Loader-*` общие для семейства** — переименование ломает темизацию у потребителей
|
|
101
|
+
и затрагивает `LoaderMiddle`.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Accessibility
|
|
106
|
+
|
|
107
|
+
- Корневой элемент имеет `role="status"` — неявная `aria-live="polite"` область: скринридер
|
|
108
|
+
сообщит о появлении лоадера, не прерывая текущее чтение.
|
|
109
|
+
- `aria-label="loading"` захардкожен в компоненте. Это отступление от общего правила
|
|
110
|
+
библиотеки «не хардкодить язык в aria-атрибутах»; менять нельзя без согласования — строка
|
|
111
|
+
входит в доступное имя, по которому лоадер находят тесты потребителей. Локализация
|
|
112
|
+
доступного имени — предмет отдельной задачи по всему семейству Loader. Потребитель может
|
|
113
|
+
перекрыть значение, передав свой `aria-label` (уйдёт в `...rest`).
|
|
114
|
+
- Компонент неинтерактивен: не получает фокус, не обрабатывает клавиатуру, текста не содержит.
|
|
115
|
+
Подпись к загрузке даёт родитель (например `LoaderScreen` через `description`).
|
|
116
|
+
- Анимация непрерывная и не отключается по `prefers-reduced-motion` — известное ограничение
|
|
117
|
+
семейства Loader.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Связанные компоненты
|
|
122
|
+
|
|
123
|
+
- `LoaderMiddle` (`src/components/Loader/LoaderMiddle/LoaderMiddle.tsx`) — крупный квадратный
|
|
124
|
+
вариант без props, из того же barrel `src/components/Loader/index.ts`.
|
|
125
|
+
- `LoaderScreen` (`src/components/LoaderScreen/LoaderScreen.tsx`) — оверлей с лоадером,
|
|
126
|
+
подписью и кнопками; при `type="small"` рендерит `LoaderSmall` с темой `BRAND`.
|
|
127
|
+
- `Button` (`src/components/Button/Button.tsx`) — рендерит `LoaderSmall` **всегда**, а вне
|
|
128
|
+
состояния `loading` прячет обёртку классом (`Button.tsx:156`), поэтому `role="status"`
|
|
129
|
+
доступен и у обычной кнопки — не пиши тест вида `queryByRole("status")` → `null`.
|
|
130
|
+
Тему выбирает по теме кнопки (`SECONDARY` / `SECONDARY_LIGHT` → `BRAND`,
|
|
131
|
+
остальные → `NEUTRAL`), размер — по размеру кнопки.
|
|
132
|
+
- `Dropdown` (`DropdownList`, `DropdownMobileList`, `DropdownMobileLoader`), `SuggestField`,
|
|
133
|
+
`ChipSuggest`, `SelectExtendedField`, `ListItemLoading` — показывают `LoaderSmall` с темой
|
|
134
|
+
`BRAND` во время подгрузки данных.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Stories
|
|
139
|
+
|
|
140
|
+
Основные истории: `stories/Loaders/LoaderSmall/LoaderSmall.stories.tsx`
|
|
141
|
+
Файлы примеров: `stories/Loaders/LoaderSmall/examples/`
|
|
142
|
+
|
|
143
|
+
| Story | Example file | Что демонстрирует |
|
|
144
|
+
|---|---|---|
|
|
145
|
+
| `Playground` | — | Интерактивный подбор `theme` и `size` |
|
|
146
|
+
| `Default` | `DefaultExample.tsx` | Минимальный вызов: тема `BRAND`, размер `MD` |
|
|
147
|
+
| `Themes` | `ThemesExample.tsx` | `BRAND` на светлом фоне и `NEUTRAL` на тёмной подложке |
|
|
148
|
+
| `Sizes` | `SizesExample.tsx` | Размеры `SM` / `MD` / `LG` в обеих темах |
|
|
149
|
+
| `VisualTests` | — | Скриншот-регрессия: сетка размеров × тем, анимации заглушены декоратором |
|
|
150
|
+
|
|
151
|
+
Файлы примеров сохраняют исторический постфикс `Example` (`DefaultExample.tsx`) —
|
|
152
|
+
переименование ломало бы ссылки на них без пользы, миграция именования не входит в задачу
|
|
153
|
+
(`docs/ai/stories-guide.md`).
|
|
154
|
+
|
|
155
|
+
Стори `Default`, `Themes` и `Sizes` исключены из скриншот-тестов (`testRunner: { skip: true }`):
|
|
156
|
+
их содержимое целиком повторяется в `VisualTests`, дублирующие снимки не нужны. Скриншоты
|
|
157
|
+
снимаются только со стори `VisualTests` (`loaders-loadersmall--visual-tests--xs|xl.png`).
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## История изменений
|
|
162
|
+
|
|
163
|
+
| Дата | Изменение |
|
|
164
|
+
|---|---|
|
|
165
|
+
| 2026-08-06 | Создан документ. AI-рефакторинг: JSDoc на компоненте, props и значениях `ELoaderSmallTheme`, документирован неиспользуемый `ELoaderSmallSize`, порядок импортов приведён к codestyle, константы-маппинги переименованы в `THEME_TO_CLASS_NAME_MAP` / `SIZE_TO_CLASS_NAME_MAP`, в стилях объединено дублирующееся объявление анимации точек — сама анимация задана один раз на `.dot`, а у `.dot1` / `.dot2` / `.dot3` осталась только `animation-delay` (правило `.dot1` с нулевой задержкой обязательно: без него класс исчезнет из CSS-модуля и из разметки), unit-тесты расширены с 3 до 6 кейсов. В stories `controls: { disable: true }` перенесён на верхний уровень `parameters` — внутри `docs` он не применялся. Публичный API, DOM и визуальное поведение не изменены. |
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Примеры использования
|
|
170
|
+
|
|
171
|
+
### Default
|
|
172
|
+
|
|
173
|
+
`stories/Loaders/LoaderSmall/examples/DefaultExample.tsx`
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
import React from "react";
|
|
177
|
+
import { LoaderSmall, ELoaderSmallTheme, EComponentSize } from "@sberbusiness/triplex-next";
|
|
178
|
+
|
|
179
|
+
export const DefaultExample = () => <LoaderSmall theme={ELoaderSmallTheme.BRAND} size={EComponentSize.MD} />;
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Themes
|
|
183
|
+
|
|
184
|
+
`stories/Loaders/LoaderSmall/examples/ThemesExample.tsx`
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
import React from "react";
|
|
188
|
+
import { LoaderSmall, ELoaderSmallTheme, EComponentSize } from "@sberbusiness/triplex-next";
|
|
189
|
+
|
|
190
|
+
export const ThemesExample = () => (
|
|
191
|
+
<div style={{ display: "flex", gap: "32px", alignItems: "center" }}>
|
|
192
|
+
<div>
|
|
193
|
+
<div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: "700" }}>BRAND</div>
|
|
194
|
+
<LoaderSmall theme={ELoaderSmallTheme.BRAND} size={EComponentSize.MD} />
|
|
195
|
+
</div>
|
|
196
|
+
<div>
|
|
197
|
+
<div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: "700" }}>NEUTRAL</div>
|
|
198
|
+
<div style={{ display: "inline-flex", padding: "8px", borderRadius: "8px", background: "#1C1C1E" }}>
|
|
199
|
+
<LoaderSmall theme={ELoaderSmallTheme.NEUTRAL} size={EComponentSize.MD} />
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
202
|
+
</div>
|
|
203
|
+
);
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Sizes
|
|
207
|
+
|
|
208
|
+
`stories/Loaders/LoaderSmall/examples/SizesExample.tsx`
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
import React from "react";
|
|
212
|
+
import { LoaderSmall, ELoaderSmallTheme, EComponentSize } from "@sberbusiness/triplex-next";
|
|
213
|
+
|
|
214
|
+
const SIZES = Object.values(EComponentSize);
|
|
215
|
+
|
|
216
|
+
export const SizesExample = () => (
|
|
217
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "24px" }}>
|
|
218
|
+
{SIZES.map((size) => (
|
|
219
|
+
<div key={size} style={{ display: "flex", alignItems: "center", gap: "32px" }}>
|
|
220
|
+
<div style={{ width: "32px", fontSize: "16px", fontWeight: "700" }}>{size.toUpperCase()}</div>
|
|
221
|
+
<LoaderSmall theme={ELoaderSmallTheme.BRAND} size={size} />
|
|
222
|
+
<div style={{ display: "inline-flex", padding: "8px", borderRadius: "8px", background: "#1C1C1E" }}>
|
|
223
|
+
<LoaderSmall theme={ELoaderSmallTheme.NEUTRAL} size={size} />
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
))}
|
|
227
|
+
</div>
|
|
228
|
+
);
|
|
229
|
+
```
|
|
230
|
+
|