@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.
Files changed (41) hide show
  1. package/bundle/components/AlertProcess.md +460 -0
  2. package/bundle/components/Amount.md +145 -169
  3. package/bundle/components/Badge.md +155 -219
  4. package/bundle/components/Body.md +108 -116
  5. package/bundle/components/Button.md +1 -0
  6. package/bundle/components/CarouselExtended.md +355 -194
  7. package/bundle/components/Checkbox.md +7 -1
  8. package/bundle/components/CheckboxTreeExtended.md +149 -248
  9. package/bundle/components/CheckboxXGroup.md +2 -0
  10. package/bundle/components/CheckboxYGroup.md +7 -2
  11. package/bundle/components/ChipGroup.md +195 -126
  12. package/bundle/components/ComposedKeyDownListener.md +323 -0
  13. package/bundle/components/FooterPage.md +2 -1
  14. package/bundle/components/HeaderPage.md +2 -1
  15. package/bundle/components/Island.md +100 -12
  16. package/bundle/components/KeyDownListener.md +11 -72
  17. package/bundle/components/LightBox.md +6 -0
  18. package/bundle/components/LoaderSmall.md +230 -0
  19. package/bundle/components/MaskedField.md +481 -0
  20. package/bundle/components/MediaWidth.md +252 -108
  21. package/bundle/components/MobileView.md +192 -68
  22. package/bundle/components/ModalWindow.md +3 -1
  23. package/bundle/components/Notification.md +21 -3
  24. package/bundle/components/Page.md +3 -1
  25. package/bundle/components/Pagination.md +20 -0
  26. package/bundle/components/SelectExtendedField.md +691 -236
  27. package/bundle/components/SliderExtended.md +358 -222
  28. package/bundle/components/TabsExtended.md +380 -194
  29. package/bundle/components/UnorderedList.md +254 -0
  30. package/bundle/components/UnorderedListExtended.md +255 -0
  31. package/bundle/components/WindowResizeListener.md +249 -0
  32. package/bundle/guides/commits.md +66 -3
  33. package/bundle/guides/context.md +26 -0
  34. package/bundle/guides/stories.md +3 -1
  35. package/bundle/guides/template.md +1 -1
  36. package/bundle/manifest.json +64 -21
  37. package/bundle/release-notes/1.41.1.mdx +18 -0
  38. package/bundle/release-notes/1.42.0.mdx +81 -0
  39. package/bundle/release-notes/1.43.0.mdx +94 -0
  40. package/bundle/release-notes/1.44.0.mdx +7 -0
  41. package/package.json +1 -1
@@ -48,13 +48,15 @@ version: "1.0"
48
48
  | `bulk` | `boolean` | `false` | Влияет на отображаемую иконку (используется bulk-иконка). Видимость checkmark всё равно определяется состоянием `checked`. |
49
49
  | `size` | `EComponentSize` | `EComponentSize.MD` | Размер: `SM` / `MD` / `LG`. |
50
50
  | `children` | `React.ReactNode` | — | Контент лейбла рядом с чекбоксом. Если `children` нет — класс `.nonempty` не применяется. |
51
- | `labelAttributes` | `React.LabelHTMLAttributes<HTMLLabelElement>` | — | Дополнительные HTML-атрибуты для корневого `<label>` (например, `className`, `onFocus`). |
51
+ | `labelAttributes` | `React.LabelHTMLAttributes<HTMLLabelElement>` | — | Дополнительные HTML-атрибуты для корневого `<label>` (например, `className`, `onFocus`). `labelAttributes.className` объединяется с `className` компонента, а не заменяет его. |
52
52
  | `...inputAttributes` | `Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" \| "size">` | — | Все стандартные атрибуты `<input type="checkbox">` (включая `name`, `onChange`, `aria-label` и т.д.). |
53
53
 
54
54
  ### Ограничения использования
55
55
 
56
56
  - DOM-структура фиксирована: корневой `<label>` → `<input type="checkbox">` → декоративные `<span>` / `<svg>` для отрисовки фона и галочки.
57
57
  - `ref` прокидывается на внутренний `<input type="checkbox">`.
58
+ - `className` попадает на корневой `<label>`, все остальные props (`...inputAttributes`) — на `<input>`.
59
+ - Размер задаёт классы только на `<label>`: внутренние элементы (`input`, фон, галочка) стилизуются от него как потомки.
58
60
 
59
61
  ---
60
62
 
@@ -84,6 +86,7 @@ version: "1.0"
84
86
  - `forwardRef` на компоненте обязателен и должен указывать на `<input>`.
85
87
  - Корневой DOM-элемент компонента — `<label>`, внутри которого находится `<input>`.
86
88
  - `className` и `size` — публичные части внешнего контрактного API: не менять семантику без согласования.
89
+ - Ховер-стили объявляются только внутри `@media (hover: hover)`: на тач-устройствах браузер эмулирует `:hover` при тапе и не снимает его, из-за чего чекбокс залипал бы в состоянии ховера.
87
90
 
88
91
  ---
89
92
 
@@ -113,6 +116,7 @@ version: "1.0"
113
116
  | `Playground` | `PlaygroundExample.tsx` | Интерактивный контроль основных props |
114
117
  | `Default` | `DefaultExample.tsx` | Минимальное использование |
115
118
  | `Sizes` | `SizesExample.tsx` | Размеры `SM` / `MD` / `LG` |
119
+ | `VisualTests` | `VisualTestsExample.tsx` | Состояния для visual regression: размеры `SM` / `MD` / `LG` в `checked` и `checked bulk` |
116
120
 
117
121
  ---
118
122
 
@@ -122,6 +126,8 @@ version: "1.0"
122
126
  |---|---|
123
127
  | 2026-04-16 | Приведение `Checkbox` к AI-ready: соблюдены правила `docs/ai/codestyle.md`, добавлена AI-документация и unit-тест на передачу `className` корневому `label`. |
124
128
  | 2026-04-27 | Приведён в соответствие с `docs/ai/template-ai.md`: убрана секция «Ключевые особенности реализации» (содержимое перенесено в `Ограничения использования`), переставлены секции (Accessibility после Инвариантов), добавлена колонка `Example file`. |
129
+ | 2026-08-14 | AI-рефакторинг: выбор иконки галочки через компонент-переменную вместо render-функции, с `<input>` убран не влияющий на стили класс размера, JSDoc на props дополнен дефолтами, расширено unit-покрытие (размеры, `bulk`, `labelAttributes`, `onChange`, `disabled`). |
130
+ | 2026-08-20 | Исправлено залипание ховера на тач-устройствах: правила `:hover` в `Checkbox.module.less` обёрнуты в `@media (hover: hover)`. |
125
131
 
126
132
  ---
127
133
 
@@ -1,10 +1,9 @@
1
1
  ---
2
2
  component: CheckboxTreeExtended
3
3
  category: Inputs
4
- figma-node: ""
5
- figma-file: ""
6
- related: [CheckboxTree, CollapsableTree, Checkbox]
7
- tokens: []
4
+ related: [CheckboxTree, CollapsibleTreeExtended, Checkbox]
5
+ tokens:
6
+ - --triplex-next-Checkbox-BorderColor_Focus
8
7
  stories: stories/CheckboxTreeExtended/CheckboxTreeExtended.stories.tsx
9
8
  version: "1.0"
10
9
  ---
@@ -13,304 +12,203 @@ version: "1.0"
13
12
 
14
13
  ## Назначение
15
14
 
16
- Декларативное дерево чекбоксов, обёртка над `CollapsableTree` с добавлением
17
- сетки/отступов под чекбоксы, адаптивного размера и render-props паттерна для
18
- чекбокса в каждой ноде.
15
+ Низкоуровневое декларативное дерево чекбоксов. Обёртка над
16
+ `CollapsibleTreeExtended` (и, соответственно, над `TreeView`), которая задаёт
17
+ разметку и отступы веток, а размер чекбоксов раздаёт через контекст.
19
18
 
20
- В отличие от `CheckboxTree` (data-driven), здесь потребитель **сам** строит
21
- JSX-структуру через `CheckboxTreeExtended.Node` + render-функцию
22
- `checkbox={...}`, управляет `checked`/`onChange` вручную, может вкладывать
23
- произвольный контент. Это "низкоуровневая" версия.
19
+ Дерево описывается вручную, узел за узлом: каждый узел — это
20
+ `CheckboxTreeExtended.Node` с render-функцией `checkbox`, а вложенные узлы
21
+ передаются в `children`. Состояние чекбоксов (`checked`, `bulk`) целиком на
22
+ стороне потребителя — компонент ничего не хранит и не пересчитывает.
24
23
 
25
- **Важный нюанс:** в текущем релизе дерево **постоянно раскрыто**
26
- (`isStaticCheckboxTreeExtended = true`). Сворачивание/разворачивание узлов
27
- пока не поддерживается, стрелка не рендерится. TODO в коде указывает на
28
- отложенный фичер.
24
+ Используй когда: нужна своя структура данных или своя логика связи родитель ↔
25
+ потомки (частичный выбор, ленивая загрузка ветки, произвольный контент рядом
26
+ с чекбоксом), либо дерево строится из уже готовой разметки.
29
27
 
30
- Используй когда: нужна полная кастомизация рендера (заголовки, иконки,
31
- доп. контент у нод), управляешь state вручную.
32
- Не используй когда: нужно простое дерево с плоскими данными — бери
33
- `CheckboxTree`.
34
-
35
- ---
36
-
37
- ## Файловая структура
38
-
39
- ```text
40
- src/components/CheckboxTreeExtended/
41
- ├── CheckboxTreeExtended.tsx # React.FC (SFC-интерфейс) + compound Node/Checkbox
42
- ├── CheckboxTreeExtendedContext.ts # Контекст: {size}
43
- ├── isStaticCheckboxTreeExtended.ts # const = true, временный feature-flag
44
- ├── index.ts # Barrel
45
- ├── styles/CheckboxTreeExtended.module.less
46
- └── components/
47
- ├── CheckboxTreeExtendedNode.tsx # FC, обёртка CollapsableTree.Node
48
- ├── CheckboxTreeExtendedCheckbox.tsx # FC, обёртка Checkbox + фокус-менеджмент
49
- └── CheckboxTreeExtendedArrow.tsx # class Component, стрелка разворачивания (сейчас скрыта)
50
- ```
51
-
52
- Особенности:
53
- - **`ICheckboxTreeExtendedSFC`** — кастомный интерфейс FC с `Checkbox` и
54
- `Node` как свойствами. Присваиваются статически после объявления.
55
- - **`isStaticCheckboxTreeExtended`** — хардкод-константа, временно
56
- выключающая сворачивание. **Удалить вместе с файлом**, когда фича будет
57
- реализована. Пока что из-за `true` много веток кода идут по "всегда
58
- раскрытой" логике.
59
- - **`useMatchMedia`** — адаптивный размер: на экранах `<= SM_MAX` размер
60
- форсируется в `MD` независимо от пропса.
28
+ Не используй когда: достаточно передать массив чекбоксов и получить готовую
29
+ логику каскадного выбора — для этого есть `CheckboxTree`, обёртка поверх этого
30
+ компонента.
61
31
 
62
32
  ---
63
33
 
64
34
  ## Варианты и props
65
35
 
66
- ### Root: `ICheckboxTreeExtendedProps extends ICollapsableTreeProps`
67
-
68
- | Prop | Тип | Default | Описание |
69
- |---|---|---|---|
70
- | `size` | `EComponentSize` | `MD` | Размер чекбоксов в дереве (SM/MD/LG). На мобильных (`<= SM_MAX`) перезаписывается на MD. |
71
- | `className` | `string` | — | Добавочный класс. |
72
- | `...ICollapsableTreeProps` | — | — | Наследует все пропы CollapsableTree (включая children, navigation). |
36
+ ### `CheckboxTreeExtended`
73
37
 
74
- ### `CheckboxTreeExtended.Node` — `ICheckboxTreeExtendedNodeProps extends Omit<ICollapsableTreeNodeProps, "children" | "renderBody" | "renderHeader">`
38
+ Наследует `ICollapsibleTreeExtendedProps` (то есть все атрибуты `<ul>`).
75
39
 
76
- | Prop | Тип | Обязателен | Описание |
40
+ | Prop | Тип | По умолчанию | Описание |
77
41
  |---|---|---|---|
78
- | `id` | `string` | Да | Уникальный id ноды. Используется и в навигации CollapsableTree. |
79
- | `checkbox` | `(props: ICheckboxTreeExtendedCheckboxProvideProps) => JSX.Element` | Да | Render-функция. Получает `active` (клавиатурный фокус) и `opened` (раскрыта ли). |
80
- | `children` | `React.ReactNode` | Нет | Дочерние `CheckboxTreeExtended.Node`. Если есть — рендерится стрелка (сейчас выключено). |
81
- | `opened` | `boolean` | Нет | Контролируемое раскрытие. Игнорируется при `isStaticCheckboxTreeExtended=true`. |
82
- | `prevNodeId` / `nextNodeId` | `string` | Нет | ID соседних нод того же уровня для arrow-навигации. |
83
- | `...CollapsableTreeNodeProps` | — | — | Всё остальное (кроме `children`/`renderHeader`/`renderBody`). |
84
-
85
- ### `CheckboxTreeExtended.Checkbox` — `ICheckboxTreeExtendedCheckboxProps extends ICheckboxProps`
86
-
87
- Тонкая обёртка над `Checkbox` с дополнениями:
88
-
89
- | Prop | Тип | Описание |
90
- |---|---|---|
91
- | `active` | `boolean` | Клавиатурный фокус на ноде → автоматически `.focus()` на input. |
92
- | `opened` | `boolean` | Используется в типах, визуально сейчас не задействовано. |
93
- | `size` | — | **НЕ передаётся через props**. Подтягивается из контекста CheckboxTreeExtendedContext. |
94
- | `labelAttributes` | `ICheckboxProps["labelAttributes"]` | Расширяется — добавляется `onFocus` для `stopPropagation`. |
95
- | `...ICheckboxProps` | — | Все остальные пропы базового Checkbox (checked, bulk, onChange, labelAttributes etc.). |
96
-
97
- ### `ICheckboxTreeExtendedCheckboxProvideProps`
98
-
99
- Что приходит в `checkbox`-render-функцию:
100
-
101
- ```ts
102
- interface ICheckboxTreeExtendedCheckboxProvideProps {
103
- active?: boolean; // нода активна (keyboard nav)
104
- opened?: boolean; // нода раскрыта (сейчас всегда true)
105
- }
106
- ```
107
-
108
- ---
109
-
110
- ## Ключевые особенности реализации
111
-
112
- ### `useMatchMedia` для адаптивного size
113
-
114
- ```ts
115
- const adaptive = useMatchMedia(
116
- `(max-width: ${EScreenWidth.SM_MAX})`,
117
- window.innerWidth <= parseInt(EScreenWidth.SM_MAX),
118
- );
119
-
120
- <CheckboxTreeExtendedContext.Provider value={{ size: adaptive ? EComponentSize.MD : size }}>
121
- ```
122
-
123
- На мобильных контекст форсирует MD — игнорирует `size`, переданный в пропы.
124
- Это UX-решение: маленькие чекбоксы на тач-экране неудобны. **Не убирать**
125
- без дизайн-ревью.
42
+ | `size` | `EComponentSize` | `EComponentSize.MD` | Размер чекбоксов и вертикальных отступов веток. Раздаётся через контекст, в атрибуты DOM не попадает |
43
+ | `children` | `React.ReactNode` | — | Узлы `CheckboxTreeExtended.Node` |
44
+ | `className` | `string` | — | Мерджится с собственным классом корневого `<ul>` |
126
45
 
127
- `useMatchMedia` — hook из `src/components/MediaWidth/useMatchMedia`. Второй
128
- аргумент — initial value для SSR.
46
+ Составные части: `CheckboxTreeExtended.Node` (`CheckboxTreeExtendedNode`) и
47
+ `CheckboxTreeExtended.Checkbox` (`CheckboxTreeExtendedCheckbox`).
129
48
 
130
- ### Контекст для size
49
+ ### `CheckboxTreeExtended.Node`
131
50
 
132
- Size не передаётся через пропы на `Node` и `Checkbox` — они читают его из
133
- контекста `CheckboxTreeExtendedContext`. Преимущество: менять в одном
134
- месте без prop-drilling. Недостаток: `CheckboxTreeExtended.Checkbox` не
135
- работает вне `CheckboxTreeExtended` (получит initial `MD`).
51
+ Наследует `ICollapsibleTreeExtendedNodeProps` без `children`, `renderBody`,
52
+ `renderHeader` — заголовок и тело узла формирует сам компонент. Тип props
53
+ экспортируется как `ICheckboxTreeExtendedNodeProps` — им типизируют
54
+ собственную обёртку узла.
136
55
 
137
- ### `isStaticCheckboxTreeExtended = true` — глобальный флаг
138
-
139
- Задействован в **двух местах**:
140
-
141
- 1. `CheckboxTreeExtendedNode`:
142
- - `opened={isStaticCheckboxTreeExtended ? true : opened}` — всегда раскрыто
143
- - Стрелка не рендерится
144
- - `checkbox` render-функция получает `active: activeNode, opened: true` вместо `active: !children && activeNode, opened`
145
-
146
- 2. `CheckboxTreeExtendedCheckbox`:
147
- - `!isStaticCheckboxTreeExtended && event.stopPropagation()` — не гасит
148
- focus bubbling в статичном режиме (ARR-у arrow активна, она сама управляет).
149
-
150
- **TODO из кода: удалить файл + константу, когда сворачивание будет готово.**
151
- До этого любой PR с "давайте сделаем сворачивание" должен **убрать оба места
152
- использования**, не просто поменять на `false`.
153
-
154
- ### `handleHeaderMouseDown` — предотвращение фокуса на контейнер
155
-
156
- ```ts
157
- if (event.target === event.currentTarget) {
158
- event.preventDefault();
159
- }
160
- ```
161
-
162
- Когда клик по области заголовка **сбоку от чекбокса** (а не по самому
163
- чекбоксу), браузер иначе дал бы фокус контейнеру. Это сбивало бы ARIA
164
- (фокус должен быть на input). `preventDefault` блокирует это. Проверка
165
- `target === currentTarget` — фокус блокируется только для прямых кликов в
166
- контейнер, не для вложенных.
167
-
168
- ### `useEffect` — auto-focus при `active: true`
169
-
170
- ```ts
171
- useEffect(() => {
172
- if (!active) return;
173
- if (!document.activeElement?.contains(checkboxNode.current as Node)) {
174
- checkboxNode.current?.focus();
175
- }
176
- }, [active]);
177
- ```
56
+ | Prop | Тип | По умолчанию | Описание |
57
+ |---|---|---|---|
58
+ | `id` | `string` | — | Обязательный идентификатор узла в дереве |
59
+ | `checkbox` | `(props: ICheckboxTreeExtendedCheckboxProvideProps) => JSX.Element` | — | Render-функция чекбокса узла. Обязательна |
60
+ | `children` | `React.ReactNode` | — | Вложенные `CheckboxTreeExtended.Node` |
61
+ | `opened` | `boolean` | — | Игнорируется, пока дерево статично (см. «Инварианты») |
62
+ | `className` | `string` | — | Мерджится с собственным классом узла `<li>` |
63
+ | `prevNodeId` / `nextNodeId` | `string` | — | Порядок узлов для клавиатурной навигации `TreeView` |
178
64
 
179
- Когда дерево получает `active: true` на ноде (через arrow-навигацию
180
- CollapsableTree), автоматически фокусируется input. Условие
181
- `!document.activeElement?.contains(...)` — защита от зацикливания focus,
182
- если уже внутри.
65
+ `ICheckboxTreeExtendedCheckboxProvideProps` — то, что узел передаёт в `checkbox`:
183
66
 
184
- **Нюанс:** `setCheckboxNode` — не forwardRef, а прямой callback-ref. Если
185
- нужен ref на input снаружи — нельзя передать через `ref={}` на
186
- `CheckboxTreeExtended.Checkbox` (его не форвардит).
67
+ | Поле | Описание |
68
+ |---|---|
69
+ | `active` | Узел активен при перемещении по дереву с клавиатуры. Нужен, чтобы чекбокс забрал фокус |
70
+ | `opened` | Узел раскрыт. Пока дерево статично — всегда `true` |
187
71
 
188
- ### `handleLabelFocus` — stopPropagation
72
+ Эти props положено разворачивать прямо в `CheckboxTreeExtended.Checkbox`
73
+ (`checkbox={(props) => <CheckboxTreeExtended.Checkbox {...props} …>}`) — сам
74
+ чекбокс их обрабатывает и в DOM не пропускает.
189
75
 
190
- ```ts
191
- !isStaticCheckboxTreeExtended && event.stopPropagation();
192
- ```
76
+ ### `CheckboxTreeExtended.Checkbox`
193
77
 
194
- Focus на label должен НЕ подниматься до родительской ноды в static-режиме
195
- (там фокус handle'ится иначе), но должен пузыриться в collapsable-режиме.
196
- Эта ветка условия активна, только когда включат сворачивание.
78
+ Обёртка над `Checkbox`: добавляет классы дерева, забирает `size` из контекста и
79
+ переводит на себя фокус, когда узел стал активным при навигации с клавиатуры.
80
+ Принимает все props `Checkbox` (`checked`, `bulk`, `onChange`, `disabled`,
81
+ `labelAttributes`, `children` …) плюс служебные `active` и `opened` из
82
+ render-функции узла.
197
83
 
198
- ### `CheckboxTreeExtendedArrow` — class component
84
+ `size`, переданный явно, перекрывает размер из контекста — так сделано намеренно
85
+ (spread props идёт после), но в дереве это не нужно и ломает единый ритм.
199
86
 
200
- Class, а не FC — использует `componentDidUpdate` для auto-focus на стрелке
201
- при `active: true` (аналог `useEffect` в checkbox). Имеет `tabIndex={-1}` —
202
- фокус не приходит tab'ом, только программно через active.
203
-
204
- Клавиатура:
205
- - `ArrowRight` → toggle(true) (раскрыть)
206
- - `ArrowLeft` → toggle(false) (свернуть)
207
- - `Enter`/`Space` → toggle(!opened)
87
+ ---
208
88
 
209
- Сейчас не рендерится из-за `isStaticCheckboxTreeExtended`, но код готов.
89
+ ## Дизайн-токены
210
90
 
211
- ### `createSizeToClassNameMap` для Node header
91
+ Собственных токенов компонент не вводит. Единственная CSS-переменная в стилях —
92
+ у стрелки раскрытия (см. «Инварианты», сейчас не отрисовывается):
212
93
 
213
- ```ts
214
- const sizeToClassNameMap = createSizeToClassNameMap(styles);
215
94
  ```
216
-
217
- Применяется к `.checkboxTreeExtendedNodeHeader` → класс `.sm/.md/.lg`, от
218
- которого зависит `margin-bottom` и мобильный padding.
219
-
220
- ### CSS `:has(.sm)` для глубины отступа
221
-
222
- ```less
223
- .checkboxTreeExtendedNode:has(.sm) { margin-left: 16px; }
224
- .checkboxTreeExtendedNode:has(.md),
225
- .checkboxTreeExtendedNode:has(.lg) { margin-left: 24px; }
95
+ --triplex-next-Checkbox-BorderColor_Focus
226
96
  ```
227
97
 
228
- `:has()` — современный CSS-селектор (Chrome 105+, Safari 15.4+, Firefox 121+).
229
- В IE и старых браузерах не работает — там отступы будут 0. Поддержка
230
- браузеров у библиотеки это допускает.
98
+ Размеры и цвета самих чекбоксов приходят из `Checkbox`, вертикальные отступы
99
+ задаются размером узла (`sm` — 8px, `md` / `lg` — 12px), отступ вложенной ветки
100
+ — 16px для `sm` и 24px для `md` / `lg`.
231
101
 
232
102
  ---
233
103
 
234
104
  ## Инварианты
235
105
 
236
- - **`isStaticCheckboxTreeExtended = true`** — временная константа. При
237
- включении сворачивания удалять файл и убирать ветки из Node/Checkbox.
238
- - **`size` приходит через контекст, НЕ через пропы Node/Checkbox** — не
239
- пробрасывать второй раз.
240
- - **`useMatchMedia` → MD на мобильных** — не удалять, UX-требование.
241
- - **`ICheckboxTreeExtendedSFC`** — кастомный тип FC со статическими
242
- `.Checkbox`, `.Node`. Без него TS не позволит прямое присваивание.
243
- - **`event.target === event.currentTarget` + `preventDefault` в
244
- handleHeaderMouseDown** — не удалять, отвечает за правильный фокус
245
- чекбокса.
246
- - **Callback-ref в CheckboxTreeExtendedCheckbox** — не менять на forwardRef
247
- без понимания: потребители передают свой onChange/checked напрямую, ref
248
- на input наружу не проброшен намеренно.
249
- - **`CheckboxTreeExtendedArrow` — class, не FC** — осознанно: нужен
250
- `componentDidUpdate` для focus-эффекта. Не переписывать на FC без
251
- понимания лайфцикла CollapsableTree.
252
- - **`isStaticCheckboxTreeExtended ? true : opened`** в Node — не
253
- реверсировать: в static-режиме `opened` игнорируется.
254
- - **`labelAttributes.onFocus` расширяется handle'ом** — если потребитель
255
- передаёт свой `onFocus`, он вызывается **после** internal handle.
256
- - **`prevNodeId`/`nextNodeId` — для CollapsableTree arrow nav** — если не
257
- передать, клавиатурная навигация Up/Down работать не будет.
106
+ - **Дерево статично.** Флаг `isStaticCheckboxTreeExtended = true`
107
+ (`isStaticCheckboxTreeExtended.ts`) принудительно раскрывает все узлы и
108
+ прячет стрелку раскрытия: `opened` на узле игнорируется, в `checkbox`
109
+ всегда приходит `opened: true`, `CheckboxTreeExtendedArrow` не
110
+ отрисовывается. Файл и обе ветки кода намеренно оставлены — по TODO флаг
111
+ снимут, когда сворачиваемое дерево станет стандартом. Не удаляй ветки
112
+ `!isStaticCheckboxTreeExtended` как «мёртвый код».
113
+ - **`forwardRef` нет ни у одной части** — `CheckboxTreeExtended`,
114
+ `.Node` и `.Checkbox` объявлены как `React.FC`. Это осознанно и повторяет
115
+ `CollapsibleTreeExtended`: под капотом class-компоненты `TreeView` /
116
+ `TreeViewNode` с собственной работой с DOM. Добавление `forwardRef` меняет
117
+ форму экспортируемого `ICheckboxTreeExtendedSFC` — это отдельное решение
118
+ мейнтейнера, а не рефакторинг.
119
+ - **Публичный API** — имена `ICheckboxTreeExtendedProps`,
120
+ `ICheckboxTreeExtendedSFC`, `ICheckboxTreeExtendedCheckboxProvideProps`,
121
+ `ICheckboxTreeExtendedNodeProps`,
122
+ статические `Checkbox` / `Node` и barrel-экспорты `index.ts` менять нельзя:
123
+ на них опирается `CheckboxTree`, а также stories `Chips` и `MultiselectField`.
124
+ - **`size` раздаётся только через контекст** `CheckboxTreeExtendedContext`. Не
125
+ прокидывай его пропом по дереву — узлы и чекбоксы читают контекст сами.
126
+ - **В мобильном представлении размер всегда `MD`** (`useMobileView`), чтобы
127
+ область нажатия оставалась достаточной. Значение `size` при этом не
128
+ «запоминается» — оно возвращается при выходе из мобильного представления.
129
+ - **Содержимое узла — только через `checkbox` и `children`.** `renderHeader` /
130
+ `renderBody` у `CollapsibleTreeExtended.Node` заняты и исключены из типа.
131
+ - **Корневой DOM** — `<ul role="tree">` от `TreeView`, узлы — `<li>`.
258
132
 
259
133
  ---
260
134
 
261
- ## Accessibility
135
+ ## Известные ограничения
262
136
 
263
- - Наследует a11y от `CollapsableTree` (role="tree", role="treeitem",
264
- aria-expanded).
265
- - Чекбокс внутри — стандартный (`<input type="checkbox">`), получает
266
- `aria-checked` и `aria-checked="mixed"` для bulk.
267
- - **Клавиатура (CollapsableTree)**:
268
- - Arrow Up/Down — навигация между нодами через prev/nextNodeId.
269
- - Focus на input при активации ноды.
270
- - **Клавиатура (CheckboxTreeExtendedArrow)** — зарезервирована, но не
271
- активна в static-режиме.
272
- - **Mobile**: padding 16px вокруг дерева, увеличенная область клика
273
- на label (padding-top/bottom 16px) — тач-таргеты.
274
- - Структура: `.checkboxTreeExtendedNodeHeader` — flex-контейнер с
275
- чекбоксом и (будущей) стрелкой.
137
+ Найдено при AI-рефакторинге (TRI-23). Оставлено намеренно — не «чини» их
138
+ походя, по каждому пункту есть решение.
276
139
 
277
- ---
140
+ - **`CheckboxTreeExtendedArrow` разбирает клавиши через `event.keyCode`**
141
+ (`EVENT_KEY_CODES`) — устаревший API. Миграция на `event.key` относится ко
142
+ всему семейству `TreeView`.
143
+ - **`<li> cannot appear as a descendant of <li>`** — предупреждение React на
144
+ первом рендере вложенных узлов. `<ul role="group">` (`TreeViewGroup`)
145
+ отрисовывается только при `hasChildNodes`, а он берётся из
146
+ `abstractNode.getChildren()`, который наполняется, когда дочерние узлы уже
147
+ смонтировались. Лечится только в `TreeView` и задевает всё семейство
148
+ (`CollapsibleTree`, `CollapsibleTreeExtended`, `CheckboxTree`,
149
+ `CheckboxTreeExtended`), поэтому по решению ревьюера оставлено как есть.
150
+ См. «Accessibility».
278
151
 
279
- ## Дизайн-токены
152
+ ---
280
153
 
281
- Собственных нет. Чекбокс внутри использует `--triplex-next-Checkbox-*`
282
- (включая `--triplex-next-Checkbox-BorderColor_Focus` для стрелки).
154
+ ## Accessibility
283
155
 
284
- Отступы/размеры — хардкод в LESS (16px/24px mobile padding, 8/12px header
285
- margin). Кандидат на токенизацию.
156
+ - Семантику и клавиатурную навигацию (стрелки, Home/End, перемещение по узлам)
157
+ обеспечивает `TreeView`. Компонент добавляет к ней только передачу фокуса.
158
+ - **Фокус при навигации с клавиатуры.** Узел сообщает в render-функцию
159
+ `active`; `CheckboxTreeExtended.Checkbox` по этому флагу вызывает
160
+ `focus()` на `<input>`. Правило ровно одно: фокус берётся, когда `active`
161
+ и текущий `document.activeElement` **не содержит** чекбокс. Mount и update
162
+ эффект не различает — при монтировании активного узла фокус не уезжает
163
+ только потому, что `activeElement` по умолчанию `<body>`, а
164
+ `body.contains(input)` истинно; если в этот момент фокус стоит на
165
+ постороннем элементе, чекбокс заберёт его сразу на маунте. У стрелки
166
+ поведение другое — там guard через `prevActive` даёт настоящий
167
+ mount-иммунитет (фокус только на переходе `active` false → true). Когда
168
+ флаг статичности снимут, у узлов с детьми фокус вместо чекбокса будет
169
+ получать стрелка раскрытия.
170
+ - **Клик мимо чекбокса не наводит фокус**: `mousedown` по самому контейнеру
171
+ заголовка (а не по label/чекбоксу) отменяется через `preventDefault`.
172
+ - Подпись чекбокса — `children` у `CheckboxTreeExtended.Checkbox`, она же
173
+ связывает `<label>` и `<input>`. Для чекбокса без видимой подписи
174
+ `aria-label` передаёт потребитель — библиотека мультиязычная.
175
+ - Стрелка раскрытия (пока не отрисовывается) — `role="button"`,
176
+ `tabIndex={-1}`, обрабатывает `ArrowRight` / `ArrowLeft` (раскрыть /
177
+ свернуть) и `Enter` / `Space` (инвертировать). Фокус она берёт в `useEffect`
178
+ (пассивная фаза, после отрисовки), а не в layout-фазе, как было у прежнего
179
+ class-компонента, — так же, как это делает `CheckboxTreeExtended.Checkbox`.
180
+ - Известное ограничение семейства: на первом рендере вложенные `<li>` попадают
181
+ внутрь родительского `<li>` без обёртки `<ul role="group">` — `TreeView`
182
+ добавляет группу только после регистрации дочерних узлов. Поведение общее с
183
+ `CollapsibleTreeExtended`, лечится на уровне `TreeView`.
286
184
 
287
185
  ---
288
186
 
289
187
  ## Связанные компоненты
290
188
 
291
- - `CheckboxTree` (`src/components/CheckboxTree`) — data-driven обёртка.
292
- Большинство потребителей берут её, а не extended.
293
- - `CollapsableTree` (`src/components/CollapsableTree`) — базовое дерево с
294
- сворачиванием и клавиатурной навигацией. CheckboxTreeExtended — обёртка
295
- над ним.
296
- - `Checkbox` (`src/components/Checkbox`) — базовый чекбокс.
297
- - `useMatchMedia` (`src/components/MediaWidth/useMatchMedia`) —
298
- responsive-хук.
299
- - `EScreenWidth` (`src/helpers/breakpoints`) — брейкпойнты.
300
- - `EComponentSize` — общий enum SM/MD/LG.
189
+ - `CheckboxTree` (`src/components/CheckboxTree`) — обёртка верхнего уровня:
190
+ принимает массив `ICheckboxTreeCheckboxData` и сама пересчитывает `checked` /
191
+ `bulk` вверх и вниз по дереву. Если своя структура данных не нужна — бери её.
192
+ - `CollapsibleTreeExtended` (`src/components/CollapsibleTreeExtended`) —
193
+ нижний слой: узлы, accordion-логика и семантика дерева от `TreeView`.
194
+ `ICheckboxTreeExtendedProps` наследует `ICollapsibleTreeExtendedProps`.
195
+ - `Checkbox` (`src/components/Checkbox`) — сам чекбокс; `CheckboxTreeExtended.Checkbox`
196
+ добавляет к нему только классы дерева, размер из контекста и работу с фокусом.
197
+ - `CheckboxTreeExtendedArrow` — внутренняя стрелка раскрытия ветки, из barrel не
198
+ экспортируется и сейчас не отрисовывается (см. «Инварианты»).
301
199
 
302
200
  ---
303
201
 
304
202
  ## Stories
305
203
 
306
- `stories/CheckboxTreeExtended/CheckboxTreeExtended.stories.tsx`
204
+ Основные истории: `stories/CheckboxTreeExtended/CheckboxTreeExtended.stories.tsx`
307
205
  Файлы примеров: `stories/CheckboxTreeExtended/examples/`
308
206
 
309
207
  | Story | Example file | Что демонстрирует |
310
208
  |---|---|---|
311
- | `Playground` | `PlaygroundExample.tsx` | Интерактивный контроль `size` + ручное управление checked |
312
- | `Default` | `DefaultExample.tsx` | Базовое дерево 2 уровня |
313
- | `Sizes` | `SizesExample.tsx` | Все размеры |
209
+ | `Playground` | `PlaygroundExample.tsx` | Интерактивный контроль `size` |
210
+ | `Default` | `DefaultExample.tsx` | Дерево из двух веток с вложенным узлом, состояние чекбоксов в `useState` потребителя |
211
+ | `Sizes` | `SizesExample.tsx` | Размеры SM / MD / LG рядом |
314
212
 
315
213
  ---
316
214
 
@@ -318,7 +216,10 @@ margin). Кандидат на токенизацию.
318
216
 
319
217
  | Дата | Изменение |
320
218
  |---|---|
321
- | 2026-04-18 | Создан документ |
219
+ | 2026-08-17 | Создан документ. Проведён AI-рефакторинг: JSDoc на props, `CheckboxTreeExtendedArrow` переведён с class-компонента на FC, добавлен `displayName` у `CheckboxTreeExtendedNode`, класс состояния раскрытия узла берётся из CSS-модуля; добавлены unit-тесты на все части компонента |
220
+ | 2026-08-17 | `className` у `CheckboxTreeExtended.Node` больше не затирает собственный класс узла — классы мерджатся через `clsx` (правка по ревью PR #535) |
221
+ | 2026-08-17 | Убран мёртвый селектор `.checkboxTreeCheckbox` из мобильной медиа-выборки (рабочие `> span` и `> svg` оставлены), `.caretIconWrapper:focus` заменён на `:focus-visible` (правки по ревью PR #535) |
222
+ | 2026-08-17 | `ICheckboxTreeExtendedNodeProps` экспортируется — тип уходит в barrel и становится частью публичного API (решение владельца по ревью PR #535) |
322
223
 
323
224
  ---
324
225
 
@@ -36,6 +36,7 @@ version: "1.0"
36
36
 
37
37
  - Корневой элемент — `<div role="group">`, разметка построена на `inline-flex` и `flex-flow: row wrap`.
38
38
  - `indent` управляет применением LESS-класса `indent-{n}` и задаёт отрицательные/положительные маргины для выравнивания сетки.
39
+ - Положительные маргины навешиваются селектором `.indent-{n} .label`, то есть только на потомков с корневым классом `Checkbox`. Для произвольных children (текст, свой контрол, обёртка без `Checkbox` внутри) отступ не применится, а отрицательные маргины контейнера останутся — контент выедет за границы группы.
39
40
 
40
41
  ---
41
42
 
@@ -86,6 +87,7 @@ version: "1.0"
86
87
  |---|---|
87
88
  | 2026-04-16 | Приведение `CheckboxXGroup` к AI-ready: добавлен `forwardRef`, типизирован `children`, созданы AI-документ и инварианты. |
88
89
  | 2026-04-27 | Приведён в соответствие с `docs/ai/template-ai.md`: убрана секция «Ключевые особенности реализации» (содержимое перенесено в `Ограничения использования`), переставлены секции, добавлена колонка `Example file` и пустой раздел `Дизайн-токены`. |
90
+ | 2026-08-18 | AI-рефакторинг: JSDoc на props и компоненте, комментарий про кросс-модульный класс `.label` в LESS, добавлены unit-тесты `__tests__/CheckboxXGroup.test.tsx`. Публичный API не изменён. |
89
91
 
90
92
  ---
91
93
 
@@ -28,12 +28,16 @@ version: "1.0"
28
28
 
29
29
  | Prop | Тип | По умолчанию | Описание |
30
30
  |---|---|---|---|
31
- | `children` | `React.ReactNode` | — | Внутри обычно рендерятся `Checkbox` (или компоненты, использующие `Checkbox`). |
32
- | `...divAttributes` | `React.HTMLAttributes<HTMLDivElement>` | — | Все стандартные HTML-атрибуты для корневого элемента. |
31
+ | `children` | `React.ReactNode` | — | Внутри обычно рендерятся `Checkbox`. Компоненты, оборачивающие `Checkbox`, тоже допустимы, но обёртка вокруг каждого `Checkbox` разрывает соседство `label`-ов и вертикальный отступ пропадает — см. «Ограничения использования». |
32
+ | `...divAttributes` | `Omit<React.HTMLAttributes<HTMLDivElement>, "role">` | — | Стандартные HTML-атрибуты для корневого элемента, кроме `role`: роль всегда `group`. |
33
33
 
34
34
  ### Ограничения использования
35
35
 
36
36
  - Корневой элемент — `<div role="group">`, разметка построена на `inline-flex` и `flex-flow: column wrap`.
37
+ - Вертикальный отступ задаётся правилами вида `.checkboxYGroup .label.md + .label.md` (потомковый + соседний комбинатор), поэтому его получают только соседние `label`-элементы `Checkbox` одного размера — на любой глубине вложенности внутри группы. Для произвольных children (текст, свой контрол, обёртка без `Checkbox` внутри) отступ не применится.
38
+ - Обёртка вокруг каждого `Checkbox` (`<Wrapper><Checkbox /></Wrapper>` × 2) разрывает соседство `label`-ов — отступ пропадает. Два `Checkbox` внутри одной общей обёртки отступ, наоборот, получат, хотя прямыми детьми группы не являются.
39
+ - На мобильном брейкпоинте величина внутреннего отступа одинакова для всех размеров, но правила те же — отступ по-прежнему применяется только между соседями одного размера.
40
+ - Там же (`@screen-sm-max`) группа дополнительно получает собственный внешний отступ `margin: 14px 16px` — на десктопе своих внешних отступов у неё нет.
37
41
 
38
42
  ---
39
43
 
@@ -82,6 +86,7 @@ version: "1.0"
82
86
  |---|---|
83
87
  | 2026-04-16 | Приведение `CheckboxYGroup` к AI-ready: добавлен `forwardRef`, типизирован `children`, созданы AI-документ и инварианты. |
84
88
  | 2026-04-27 | Приведён в соответствие с `docs/ai/template-ai.md`: убрана секция «Ключевые особенности реализации» (содержимое перенесено в `Ограничения использования`), переставлены секции, добавлена колонка `Example file` и пустой раздел `Дизайн-токены`. |
89
+ | 2026-08-19 | AI-рефакторинг: JSDoc на props и компоненте, комментарий про кросс-модульные классы `.label`/`.sm`/`.md`/`.lg` в LESS, добавлены unit-тесты `__tests__/CheckboxYGroup.test.tsx`. Публичный API не изменён. |
85
90
 
86
91
  ---
87
92