@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,126 @@
1
+ ---
2
+ component: Checkbox
3
+ category: Inputs
4
+ figma-node: ""
5
+ figma-file: ""
6
+ related: [CheckboxXGroup, CheckboxYGroup, CheckboxTree, CheckboxTreeExtended]
7
+ tokens:
8
+ - --triplex-next-Checkbox-Background_Default
9
+ - --triplex-next-Checkbox-BorderColor_Default
10
+ - --triplex-next-Checkbox-Checkmark_Fill_Default
11
+ - --triplex-next-Checkbox-Background_Hover
12
+ - --triplex-next-Checkbox-BorderColor_Hover
13
+ - --triplex-next-Checkbox-Background_Checked_Default
14
+ - --triplex-next-Checkbox-BorderColor_Checked_Default
15
+ - --triplex-next-Checkbox-Background_Disabled
16
+ - --triplex-next-Checkbox-BorderColor_Disabled
17
+ - --triplex-next-Checkbox-Background_Checked_Disabled
18
+ - --triplex-next-Checkbox-BorderColor_Checked_Disabled
19
+ - --triplex-next-Checkbox-Checkmark_Fill_Disabled
20
+ - --triplex-next-Checkbox-BorderColor_Focus
21
+ - --triplex-next-Checkbox-Background_Checked_Hover
22
+ stories: stories/Checkbox/Checkbox.stories.tsx
23
+ version: "1.0"
24
+ ---
25
+
26
+ # Checkbox
27
+
28
+ ## Назначение
29
+ Нативный чекбокс в обертке `<label>`, который поддерживает визуальные состояния (default/checked/disabled/focus) и режим частичного выбора через `bulk`.
30
+
31
+ Используй когда: нужен чекбокс с текстовой подписью (`children`) и стандартным поведением `<input type="checkbox">`.
32
+ Не используй когда: нужен сложный многошаговый выбор или компонент с нестандартной семантикой (тогда лучше другой control).
33
+
34
+ ---
35
+
36
+ ## Варианты и props
37
+ ### Опциональные props
38
+ | Prop | Тип | По умолчанию | Описание |
39
+ |---|---|---|---|
40
+ | `checked` | `boolean` | — | Состояние чекбокса (controlled). Передаётся через стандартные props `<input>`. |
41
+ | `defaultChecked` | `boolean` | — | Состояние чекбокса (uncontrolled). Передаётся через стандартные props `<input>`. |
42
+ | `disabled` | `boolean` | `false` | Блокирует взаимодействие и меняет визуальное состояние. |
43
+ | `bulk` | `boolean` | `false` | Влияет на отображаемую иконку (используется bulk-иконка), при этом видимость checkmark всё равно определяется состоянием `checked`. |
44
+ | `size` | `EComponentSize` | `EComponentSize.MD` | Размер: `SM` / `MD` / `LG`. |
45
+ | `children` | `React.ReactNode` | — | Контент лейбла рядом с чекбоксом. Если `children` нет — класс `.nonempty` не применяется. |
46
+ | `labelAttributes` | `React.LabelHTMLAttributes<HTMLLabelElement>` | — | Дополнительные HTML-атрибуты для корневого `<label>` (например, `className`, `onFocus`). |
47
+ | `...inputAttributes` | `Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "size">` | — | Все стандартные атрибуты `<input type="checkbox">` (включая `name`, `onChange`, `aria-label` и т.д.). |
48
+
49
+ ---
50
+
51
+ ## Ключевые особенности реализации
52
+ ### Ref forwarding
53
+ `ref` прокидывается на внутренний `<input type="checkbox">`.
54
+
55
+ ### Иконка
56
+ - `bulk=false` — отрисовывается обычная checkmark-иконка.
57
+ - `bulk=true` — отрисовывается bulk-иконка.
58
+
59
+ ### Структура DOM
60
+ Компонент рендерит:
61
+ 1. корневой `<label>`
62
+ 2. `<input type="checkbox">`
63
+ 3. декоративные `<span>`/`svg` для отрисовки фона и галочки
64
+
65
+ ---
66
+
67
+ ## Accessibility
68
+ Компонент использует нативный `<input type="checkbox">`, поэтому поддерживает стандартную клавиатурную навигацию (Tab + Space) и семантику формы.
69
+
70
+ Библиотека мультиязычная: текст `aria-label`/`title` не захардкожен в компоненте. При необходимости потребитель передаёт `aria-*` через `...inputAttributes`.
71
+
72
+ ---
73
+
74
+ ## Инварианты
75
+ - `forwardRef` на компоненте обязателен и должен указывать на `<input>`.
76
+ - Корневой DOM-элемент компонента — `<label>`, внутри которого находится `<input>`.
77
+ - `className` и `size` — публичные части внешнего контрактного API: не менять семантику без согласования.
78
+
79
+ ---
80
+
81
+ ## Дизайн-токены
82
+ Компонент использует CSS-переменные:
83
+ `--triplex-next-Checkbox-Background_Default`,
84
+ `--triplex-next-Checkbox-BorderColor_Default`,
85
+ `--triplex-next-Checkbox-Checkmark_Fill_Default`,
86
+ `--triplex-next-Checkbox-Background_Hover`,
87
+ `--triplex-next-Checkbox-BorderColor_Hover`,
88
+ `--triplex-next-Checkbox-Background_Checked_Default`,
89
+ `--triplex-next-Checkbox-BorderColor_Checked_Default`,
90
+ `--triplex-next-Checkbox-Background_Disabled`,
91
+ `--triplex-next-Checkbox-BorderColor_Disabled`,
92
+ `--triplex-next-Checkbox-Background_Checked_Disabled`,
93
+ `--triplex-next-Checkbox-BorderColor_Checked_Disabled`,
94
+ `--triplex-next-Checkbox-Checkmark_Fill_Disabled`,
95
+ `--triplex-next-Checkbox-BorderColor_Focus`,
96
+ `--triplex-next-Checkbox-Background_Checked_Hover`.
97
+
98
+ ---
99
+
100
+ ## Связанные компоненты
101
+ - `CheckboxXGroup` — группировка чекбоксов по оси X.
102
+ - `CheckboxYGroup` — группировка чекбоксов по оси Y.
103
+ - `CheckboxTree` — декларативное дерево чекбоксов (обертка над `CheckboxTreeExtended`), поддерживает bulk-логику и распространение состояния checked по родителям/детям.
104
+ - `CheckboxTreeExtended` — расширенное дерево чекбоксов на базе `CollapsableTree` с Node/Checkbox подкомпонентами (использует нативный `Checkbox` внутри для каждого узла).
105
+
106
+ ---
107
+
108
+ ## Stories
109
+ `stories/Checkbox/Checkbox.stories.tsx`
110
+ Файлы примеров: `stories/Checkbox/examples/`
111
+
112
+ | Story | Example file | Что демонстрирует |
113
+ |---|---|---|
114
+ | `Playground` | `PlaygroundExample.tsx` | Интерактивный контроль основных props |
115
+ | `Default` | `DefaultExample.tsx` | Минимальное использование |
116
+ | `Sizes` | `SizesExample.tsx` | Размеры SM / MD / LG |
117
+ | `XGroup` | `XGroupExample.tsx` | Группа по оси X |
118
+ | `YGroup` | `YGroupExample.tsx` | Группа по оси Y |
119
+
120
+ ---
121
+
122
+ ## История изменений
123
+ | Дата | Изменение |
124
+ |---|---|
125
+ | 2026-04-16 | Приведение `Checkbox` к AI-ready: соблюдены правила `docs/ai/codestyle.md`, добавлена AI-документация и unit-тест на передачу `className` корневому `label`. |
126
+
@@ -0,0 +1,280 @@
1
+ ---
2
+ component: CheckboxTree
3
+ category: Inputs
4
+ figma-node: ""
5
+ figma-file: ""
6
+ related: [CheckboxTreeExtended, Checkbox, CheckboxYGroup, CheckboxXGroup]
7
+ tokens: []
8
+ stories: stories/CheckboxTree/CheckboxTree.stories.tsx
9
+ version: "1.0"
10
+ ---
11
+
12
+ # CheckboxTree
13
+
14
+ ## Назначение
15
+
16
+ "Готовый" компонент дерева чекбоксов с автоматической логикой
17
+ checked/bulk-состояний: при клике на родителя все потомки чекаются/
18
+ разчекаются; при частичном выборе потомков родитель получает `bulk: true`
19
+ (состояние "indeterminate").
20
+
21
+ Является **тонкой data-driven обёрткой** над `CheckboxTreeExtended`:
22
+ потребитель передаёт плоское описание дерева (`ICheckboxTreeCheckboxData[]`),
23
+ компонент сам рендерит `CheckboxTreeExtended.Node` + `.Checkbox`, управляет
24
+ состоянием и отдаёт обновлённый массив в `onChange`.
25
+
26
+ Используй когда: данные дерева — линейные/сериализуемые (например, из
27
+ бэкенда), нужна стандартная семантика bulk/чек-каскада, не нужны кастомные
28
+ UI-вставки в узлы.
29
+ Не используй когда: нужен кастомный рендер узла (заголовки, иконки,
30
+ доп. контент) — бери `CheckboxTreeExtended` напрямую; нужны 1–2 независимых
31
+ чекбокса (бери `Checkbox` / `CheckboxYGroup`).
32
+
33
+ ---
34
+
35
+ ## Файловая структура
36
+
37
+ ```text
38
+ src/components/CheckboxTree/
39
+ ├── CheckboxTree.tsx # React.FC обёртка над CheckboxTreeExtended
40
+ ├── types.ts # ICheckboxTreeCheckboxData
41
+ ├── utils.ts # traverseCheckboxes, checkParentCheckboxes, checkChildrenCheckboxes
42
+ ├── index.ts # Barrel: компонент + types + utils
43
+ └── __tests__/
44
+ ```
45
+
46
+ Особенности:
47
+ - **Нет своих стилей** — весь визуальный вид из `CheckboxTreeExtended` и его
48
+ внутреннего `Checkbox`.
49
+ - **Нет `forwardRef`** — FC без ref-форвардинга. Это осознанное упрощение
50
+ (потребитель обычно работает с самими `checkboxes` через onChange, не с DOM).
51
+ Если нужен ref — переключаться на `CheckboxTreeExtended`.
52
+ - **Utils экспортируются через barrel** (`traverseCheckboxes`,
53
+ `checkParentCheckboxes`, `checkChildrenCheckboxes`) — намеренно, потребитель
54
+ может использовать их для предварительной обработки данных или тестов.
55
+
56
+ ---
57
+
58
+ ## Варианты и props
59
+
60
+ ### `ICheckboxTreeProps extends Omit<ICheckboxTreeExtendedProps, "children" | "onChange">`
61
+
62
+ Наследует от `CheckboxTreeExtended` всё, кроме `children` (ставится из
63
+ `checkboxes`) и `onChange` (своя сигнатура).
64
+
65
+ | Prop | Тип | Обязателен | Default | Описание |
66
+ |---|---|---|---|---|
67
+ | `checkboxes` | `ICheckboxTreeCheckboxData[]` | Да | — | Плоский массив (каждый элемент может иметь `children`) — описание дерева. |
68
+ | `onChange` | `(options: ICheckboxTreeCheckboxData[]) => void` | Да | — | Получает **новую копию** массива после каскадной обработки. Потребитель должен сохранить её в свой state. |
69
+ | `size` | `EComponentSize` | Нет | `MD` | Размер чекбоксов (SM/MD/LG). Форвардится в CheckboxTreeExtended. |
70
+ | `children` | `never` | — | — | **Запрещён** через `never` — компонент сам генерирует DOM. |
71
+
72
+ ### `ICheckboxTreeCheckboxData`
73
+
74
+ Единственный тип данных дерева:
75
+
76
+ ```ts
77
+ interface ICheckboxTreeCheckboxData {
78
+ id: string; // уникальный — ключ и aria-поддержка
79
+ label: React.ReactNode; // подпись
80
+ checked: boolean; // текущее состояние
81
+ bulk?: boolean; // "indeterminate", рассчитывается автоматически
82
+ children?: ICheckboxTreeCheckboxData[]; // рекурсивно
83
+ }
84
+ ```
85
+
86
+ **`bulk` — вычисляется компонентом**, потребитель не должен устанавливать
87
+ его руками. На входе можно передать `false`/`undefined`; после onChange
88
+ массив вернётся с актуальным bulk.
89
+
90
+ ---
91
+
92
+ ## Ключевые особенности реализации
93
+
94
+ ### Мутация массива на месте
95
+
96
+ ```ts
97
+ checkbox.checked = checkbox.bulk ? true : checked;
98
+ checkChildrenCheckboxes(checkbox);
99
+ traverseCheckboxes(checkboxes, checkParentCheckboxes);
100
+ onChange([...checkboxes]);
101
+ ```
102
+
103
+ Компонент **мутирует** исходный `checkboxes` массив (меняет `checked`/`bulk`
104
+ на узлах) и только на outer-level передаёт новую ссылку через спред. Это
105
+ значит:
106
+ - Потребитель НЕ должен передавать readonly/immutable данные (Object.freeze
107
+ сломает).
108
+ - Потребитель должен либо хранить в state `useState` (React сравнит ссылку
109
+ верхнего уровня), либо всегда клонировать перед передачей.
110
+ - Внутренние референсы не меняются — потомки, которые хранят ссылку на
111
+ конкретный узел, увидят обновлённое значение.
112
+
113
+ Это архитектурный компромисс ради простоты алгоритма. **Не рефакторить
114
+ на immutable-подход без серьёзного повода** — сломает внешний контракт.
115
+
116
+ ### `bulk → checked = true` при клике на bulk-узел
117
+
118
+ ```ts
119
+ checkbox.checked = checkbox.bulk ? true : checked;
120
+ ```
121
+
122
+ Клик по узлу в `bulk`-состоянии (частично выбран) делает **всех** потомков
123
+ `checked: true`, не снимает выбор. Это соответствует стандартной UX
124
+ tri-state чекбокса: indeterminate → всё выбрано (не → ничего).
125
+
126
+ ### `checkChildrenCheckboxes` — рекурсивный каскад вниз
127
+
128
+ ```ts
129
+ checkbox.children.forEach((c) => {
130
+ c.checked = checkbox.checked;
131
+ checkChildrenCheckboxes(c);
132
+ });
133
+ ```
134
+
135
+ После клика на узел все его потомки получают то же `checked`-значение.
136
+ `bulk` у потомков НЕ сбрасывается в этой функции — его потом пересчитает
137
+ `checkParentCheckboxes` при обходе снизу-вверх.
138
+
139
+ ### `checkParentCheckboxes` — каскад вверх (post-order обход)
140
+
141
+ ```ts
142
+ if (c.children) traverseCheckboxes(c.children, cb);
143
+ cb(c);
144
+ ```
145
+
146
+ `traverseCheckboxes` идёт **post-order** (сначала потомки, потом узел) —
147
+ это ключевое: чтобы `checkParentCheckboxes` к моменту обработки узла видел
148
+ актуальное состояние потомков.
149
+
150
+ Логика узла:
151
+ - Все потомки checked → `checked: true`, `bulk: true` только если у кого-то
152
+ был bulk (не обычный полный чек).
153
+ - Часть потомков checked → `checked: true, bulk: true`.
154
+ - Никого не checked → `checked: false`.
155
+
156
+ **Нюанс:** "все checked" с хотя бы одним bulk → родитель тоже bulk. То есть
157
+ bulk распространяется вверх, даже если с точки зрения текущего уровня всё
158
+ выбрано.
159
+
160
+ ### `onChange([...checkboxes])` — shallow clone
161
+
162
+ ```ts
163
+ onChange([...checkboxes]);
164
+ ```
165
+
166
+ Только outer array клонируется — узлы внутри те же мутированные объекты.
167
+ Это совпадает с тем, что нужно React для перерендера при `useState`
168
+ (новая ссылка на массив).
169
+
170
+ ### render-функция `renderNode` с prev/next linking
171
+
172
+ ```tsx
173
+ <CheckboxTreeExtended.Node
174
+ prevNodeId={prevCheckbox?.id}
175
+ nextNodeId={nextCheckbox?.id}
176
+ />
177
+ ```
178
+
179
+ CheckboxTreeExtended использует prev/next для клавиатурной навигации
180
+ (стрелки вверх/вниз между узлами). CheckboxTree автоматически вычисляет
181
+ их из массива. Это значит, что arrow-navigation работает только в пределах
182
+ одного parent'а — между siblings. **Не менять порядок вызовов в children**:
183
+ первый элемент родителя получает prevNodeId=undefined, и это ожидаемо.
184
+
185
+ ### Функциональный чекбокс через render-проп
186
+
187
+ ```tsx
188
+ checkbox={(props) => (
189
+ <CheckboxTreeExtended.Checkbox {...props} onChange={...} bulk={...} checked={...}>
190
+ {checkbox.label}
191
+ </CheckboxTreeExtended.Checkbox>
192
+ )}
193
+ ```
194
+
195
+ Node принимает `checkbox` как функцию, получающую provide-props (id,
196
+ aria-атрибуты). CheckboxTree передаёт их наружу и добавляет свои
197
+ onChange/bulk/checked. **Не упрощать** — CheckboxTreeExtended полагается
198
+ на render-проп для управления фокусом и ARIA.
199
+
200
+ ### `onChange={handleChange(checkbox)}` — каррирование
201
+
202
+ Замыкание на конкретный `checkbox` через первый аргумент `handleChange`.
203
+ Позволяет внутри обработчика знать, какой именно узел меняется. Важно:
204
+ `checkbox` — ссылка на объект в массиве, который мутирует. Если потребитель
205
+ заменит массив на новый — замыкание станет устаревшим, но это решается
206
+ новым рендером (новая функция `handleChange` захватит свежий объект).
207
+
208
+ ---
209
+
210
+ ## Инварианты
211
+
212
+ - **`children: never`** — не делать компонент композитным, он data-driven.
213
+ Для композитного — `CheckboxTreeExtended`.
214
+ - **`checkboxes` мутируется на месте** — не передавать Object.freeze /
215
+ immutable. Не рефакторить на immer/immutability без серьёзного повода.
216
+ - **`bulk` вычисляется автоматически** — не устанавливать руками во
217
+ входных данных (перезатрётся).
218
+ - **`id` в каждом узле — уникальный** по всему дереву (не просто в рамках
219
+ одного parent'а). Используется как React `key` и для a11y.
220
+ - **`size` → CheckboxTreeExtended** — наследуется, значение по умолчанию MD.
221
+ - **`onChange` отдаёт новую shallow-copy массива** — не менять на передачу
222
+ исходной ссылки (сломает `useState`-сравнение).
223
+ - **Post-order обход в `traverseCheckboxes`** — не менять на pre-order,
224
+ иначе `checkParentCheckboxes` будет работать на неактуальных данных.
225
+ - **`checkbox.checked = checkbox.bulk ? true : checked`** — "bulk → всё в
226
+ true". Не инвертировать на "bulk → всё в false" без согласования UX.
227
+
228
+ ---
229
+
230
+ ## Accessibility
231
+
232
+ - Всё управление a11y — внутри `CheckboxTreeExtended` (role="tree"/"treeitem",
233
+ `aria-checked` (true/false/mixed), клавиатурная навигация).
234
+ - `bulk: true` → `aria-checked="mixed"` (indeterminate-состояние) на узле.
235
+ - `id` узла используется в `aria-controls` / `headers`-подобных связях —
236
+ обязательно уникален.
237
+ - Навигация:
238
+ - Tab — переход внутри дерева/наружу.
239
+ - Space/Enter — toggle чекбокса.
240
+ - Arrow Up/Down — между siblings через prev/nextNodeId.
241
+ - Если нужна expand/collapse семантика — это задача CheckboxTreeExtended
242
+ (через Node's expand-проп, если используется).
243
+
244
+ ---
245
+
246
+ ## Дизайн-токены
247
+
248
+ Нет своих. Всё через `CheckboxTreeExtended` и внутренний `Checkbox`.
249
+
250
+ ---
251
+
252
+ ## Связанные компоненты
253
+
254
+ - `CheckboxTreeExtended` (`src/components/CheckboxTreeExtended`) — нижний
255
+ уровень, composable, с полным контролем рендера узлов.
256
+ - `Checkbox` (`src/components/Checkbox`) — одиночный чекбокс.
257
+ - `CheckboxYGroup` / `CheckboxXGroup` — группы плоских чекбоксов (без
258
+ иерархии).
259
+ - `EComponentSize` — общий enum SM/MD/LG.
260
+
261
+ ---
262
+
263
+ ## Stories
264
+
265
+ `stories/CheckboxTree/CheckboxTree.stories.tsx`
266
+ Файлы примеров: `stories/CheckboxTree/examples/`
267
+
268
+ | Story | Example file | Что демонстрирует |
269
+ |---|---|---|
270
+ | `Playground` | `PlaygroundExample.tsx` | Интерактивный контроль `size` + управляемое дерево |
271
+ | `Default` | `DefaultExample.tsx` | Базовое дерево с одним уровнем вложенности |
272
+ | `Sizes` | `SizesExample.tsx` | Все три размера чекбоксов |
273
+
274
+ ---
275
+
276
+ ## История изменений
277
+
278
+ | Дата | Изменение |
279
+ |---|---|
280
+ | 2026-04-18 | Создан документ |