@sberbusiness/triplex-next-mcp-server 0.24.0-beta2 → 0.36.0-beta0

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 (55) hide show
  1. package/README.md +10 -0
  2. package/bundle/components/BodyPage.md +186 -0
  3. package/bundle/components/Button.md +90 -85
  4. package/bundle/components/ButtonDropdown.md +28 -70
  5. package/bundle/components/ButtonIcon.md +35 -48
  6. package/bundle/components/Checkbox.md +43 -122
  7. package/bundle/components/CheckboxXGroup.md +109 -46
  8. package/bundle/components/CheckboxYGroup.md +77 -49
  9. package/bundle/components/CollapsibleTree.md +581 -0
  10. package/bundle/components/CollapsibleTreeExtended.md +418 -0
  11. package/bundle/components/EmptyView.md +14 -15
  12. package/bundle/components/FooterPage.md +203 -0
  13. package/bundle/components/Gap.md +115 -57
  14. package/bundle/components/HeaderPage.md +226 -0
  15. package/bundle/components/HelpBox.md +45 -84
  16. package/bundle/components/ImageGallery.md +423 -0
  17. package/bundle/components/ImageGalleryExtended.md +606 -0
  18. package/bundle/components/List.md +194 -186
  19. package/bundle/components/ListItem.md +251 -0
  20. package/bundle/components/ListItemControlsButton.md +103 -0
  21. package/bundle/components/ListItemControlsButtonDropdown.md +107 -0
  22. package/bundle/components/ListItemSelectable.md +99 -0
  23. package/bundle/components/ListItemTable.md +390 -0
  24. package/bundle/components/ListMaster.md +877 -156
  25. package/bundle/components/ListMasterFooter.md +80 -0
  26. package/bundle/components/ListMasterHeader.md +86 -0
  27. package/bundle/components/ListSortable.md +153 -0
  28. package/bundle/components/ListSortableItem.md +175 -0
  29. package/bundle/components/ModalWindow.md +427 -237
  30. package/bundle/components/MonthYearField.md +145 -109
  31. package/bundle/components/Notification.md +625 -155
  32. package/bundle/components/Overlay.md +271 -170
  33. package/bundle/components/Page.md +283 -186
  34. package/bundle/components/Pagination.md +206 -229
  35. package/bundle/guides/codestyle.md +38 -11
  36. package/bundle/guides/commits.md +1 -2
  37. package/bundle/guides/context.md +34 -30
  38. package/bundle/guides/stories.md +110 -40
  39. package/bundle/guides/template.md +3 -7
  40. package/bundle/guides/tests.md +6 -2
  41. package/bundle/manifest.json +194 -24
  42. package/bundle/release-notes/1.26.0.mdx +33 -2
  43. package/bundle/release-notes/1.27.0.mdx +43 -0
  44. package/bundle/release-notes/1.28.0.mdx +25 -0
  45. package/bundle/release-notes/1.29.0.mdx +47 -0
  46. package/bundle/release-notes/1.30.0.mdx +56 -0
  47. package/bundle/release-notes/1.31.0.mdx +52 -0
  48. package/bundle/release-notes/1.32.0.mdx +35 -0
  49. package/bundle/release-notes/1.33.0.mdx +61 -0
  50. package/bundle/release-notes/1.34.0.mdx +35 -0
  51. package/bundle/release-notes/1.35.0.mdx +21 -0
  52. package/bundle/release-notes/1.35.1.mdx +11 -0
  53. package/bundle/release-notes/1.36.0.mdx +21 -0
  54. package/bundle/release-notes/1.37.0.mdx +30 -0
  55. package/package.json +1 -1
@@ -1,9 +1,7 @@
1
1
  ---
2
2
  component: List
3
- category: Data Display
4
- figma-node: ""
5
- figma-file: ""
6
- related: [ListMaster, Table, TreeView, Checkbox, LoaderScreen]
3
+ category: List
4
+ related: [ListSortable, ListItem, ListEmptyState, ListItemLoading, LoaderScreen]
7
5
  tokens: []
8
6
  stories: stories/List/List.stories.tsx
9
7
  version: "1.0"
@@ -13,235 +11,245 @@ version: "1.0"
13
11
 
14
12
  ## Назначение
15
13
 
16
- Семейство компонентов для списков (`<ul>` / `<li>`) с набором слотов
17
- для строк: контент, правый контролы-блок, хвосты слева/справа, чекбокс-
18
- выбор, вложенный DropdownButton, drag-and-drop. Поддерживает loading-overlay
19
- на уровне списка.
14
+ Контейнер `<ul>` для набора элементов списка. Управляет состоянием загрузки
15
+ через prop `loading` (показывает overlay-спиннер `LoaderScreen` поверх
16
+ содержимого).
20
17
 
21
- Используй когда: нужен табличный список с повторяющимися строками и
22
- фиксированной визуальной структурой. Для таблиц с колонками — `Table`,
23
- для древовидных — `TreeView`, для master-detail интерфейсов — `ListMaster`.
24
-
25
- ---
26
-
27
- ## Файловая структура
28
-
29
- ```text
30
- src/components/List/
31
- ├── List.tsx # <ul>, loading-overlay
32
- ├── ListSortable.tsx # DnD обёртка (dnd-kit)
33
- ├── index.ts # Barrel всех слотов
34
- ├── components/
35
- │ ├── ListItem.tsx # <li> + Provider ListItemContext
36
- │ ├── ListItemContext.ts # { selected, setSelected }
37
- │ ├── ListItemContent.tsx # Основной контент строки
38
- │ ├── ListItemControls.tsx # Правый блок кнопок
39
- │ ├── ListItemControlsButton.tsx # Стилизованная кнопка в Controls
40
- │ ├── ListItemControlsButtonDropdown.tsx # Кнопка с выпадающим меню
41
- │ ├── ListItemSelectable.tsx # Обёртка с Checkbox, пишет selected в Context
42
- │ ├── ListItemTable.tsx # Табличный вид строки
43
- │ ├── ListItemTailLeft.tsx # Левый хвост (иконка, аватар)
44
- │ ├── ListItemTailRight.tsx # Правый хвост
45
- │ ├── ListItemLoading.tsx # Placeholder-строка при loading
46
- │ ├── ListEmptyState.tsx # Пустое состояние
47
- │ ├── ListSortableItem.tsx # <li> с useSortable (DnD)
48
- │ ├── ListSortableItemControls.tsx # DnD-handle control (drag)
49
- │ └── ListSortableItemTarget.tsx # Цель сортировки
50
- └── styles/*.module.less
51
- ```
18
+ Используй `List` когда: нужен стандартный список с произвольным контентом.
19
+ Используй `ListSortable` когда: нужна сортировка элементов через drag-and-drop.
52
20
 
53
21
  ---
54
22
 
55
23
  ## Варианты и props
56
24
 
57
- ### List — `IListProps extends HTMLAttributes<HTMLUListElement>`
25
+ ### Опциональные props
58
26
 
59
- | Prop | Тип | Default | Описание |
27
+ | Prop | Тип | По умолчанию | Описание |
60
28
  |---|---|---|---|
61
- | `loading` | `boolean` | — | Накладывает `LoaderScreen type="middle"` поверх списка. |
62
- | `...ulAttributes` | — | — | Стандартные `<ul>`-атрибуты. |
29
+ | `loading` | `boolean` | `false` | Показывает `LoaderScreen` поверх содержимого. Используется при обновлении текущего списка новыми данными (например, после применения фильтра) |
30
+ | `children` | `React.ReactNode` | — | Элементы списка (обычно `<ListItem>` или `<ListItemTable>`) |
31
+ | `...HTMLUListElementAttributes` | — | — | Все стандартные атрибуты `<ul>` |
63
32
 
64
- ### ListItem — `IListItemProps extends LiHTMLAttributes<HTMLLIElement>`
65
-
66
- Создаёт собственный `ListItemContext` с `{ selected, setSelected }`. Подкомпоненты (`ListItemSelectable`) пишут в него.
67
-
68
- ### ListItemSelectable — `IListItemSelectableProps extends Omit<HTMLDivAttributes, "onSelect">`
69
-
70
- | Prop | Тип | Обязателен | Описание |
71
- |---|---|---|---|
72
- | `selected` | `boolean` | Да | Управляемое состояние выбора. |
73
- | `onSelect` | `(selected: boolean) => void` | Да | Callback при изменении. |
74
-
75
- - Внутри — `<Checkbox>` + `useEffect(() => setSelected(selected))` — синхронизирует с `ListItemContext`, чтобы сиблинги (например, стили строки) могли реагировать на выбор.
76
- - `<span className={styles.checkboxLabelClickArea} />` — растягивающаяся область клика (не только на чекбокс).
77
-
78
- ### ListItemContent — базовый слот для текста/описания строки.
79
-
80
- ### ListItemControls / ListItemControlsButton / …ButtonDropdown
33
+ ---
81
34
 
82
- | Компонент | Назначение |
83
- |---|---|
84
- | `ListItemControls` | Контейнер для кнопок справа. |
85
- | `ListItemControlsButton` | Стилизованная кнопка-иконка. |
86
- | `ListItemControlsButtonDropdown` | Кнопка + вложенное выпадающее меню. |
35
+ ## Инварианты
87
36
 
88
- ### ListItemTailLeft / ListItemTailRight — хвосты (иконки, аватары, статусы) по краям строки.
37
+ - **`forwardRef`** — обязателен, target — `HTMLUListElement`. Не убирать.
38
+ - **Корневой элемент `<ul>`** — не менять. Семантика списка важна для accessibility.
39
+ - `loading` — overlay-стратегия (содержимое не размонтируется), не путать с `ListItemLoading` (отдельный элемент-спиннер для пагинации).
40
+ - **`.listLoaderScreen` — `z-index: @z-index-step`**. Понижает z-index относительно глобального `@z-index-loader-screen` у `LoaderScreen`, чтобы спиннер перекрывал только содержимое списка, а не `LightBox` / `ModalWindow`. Не повышать без проверки наложения на модальные слои.
89
41
 
90
- ### ListItemTable
42
+ ---
91
43
 
92
- Табличный вид строки: внутренняя сетка для выравнивания колонок между строками.
44
+ ## Связанные компоненты
93
45
 
94
- ### ListItemLoading — скелетон-строка, показывается во время загрузки.
46
+ - `ListItem` — базовый элемент списка, провайдер контекста для `selected`-состояния.
47
+ - `ListSortable` — тот же `<ul>`, но с DnD-обвязкой через `@dnd-kit`.
48
+ - `ListEmptyState` — отображается вместо элементов, когда данных нет (например, после фильтра).
49
+ - `ListItemLoading` — элемент-спиннер для подгрузки следующей страницы (пагинация).
50
+ - `LoaderScreen` — используется внутри `List` для состояния `loading`.
95
51
 
96
- ### ListEmptyState — рендерится, когда `items.length === 0`, параметры для заголовка/описания/иконки.
52
+ ---
97
53
 
98
- ### ListSortable<T extends { id: string }> — `IListSortableProps<T>`
54
+ ## Stories
99
55
 
100
- | Prop | Тип | Обязателен | Описание |
101
- |---|---|---|---|
102
- | `items` | `T[]` | Да | Массив элементов, у каждого должно быть поле `id`. |
103
- | `onItemsChange` | `(items: T[]) => void` | Да | Callback после перестановки. |
104
- | `...IListProps` | — | — | Проброс на `<List>`. |
56
+ Основные истории: `stories/List/List.stories.tsx`
57
+ Файлы примеров: `stories/List/examples/List/`
105
58
 
106
- - Обёртка над `@dnd-kit/core` + `@dnd-kit/sortable`.
107
- - Modifiers: `restrictToParentElement` + `restrictToVerticalAxis` — нельзя перетащить в другой родитель или по горизонтали.
108
- - Внутри использует `AdvancedMouseSensor` / `AdvancedTouchSensor` — расширенные sensor'ы.
59
+ | Story | Example file | Что демонстрирует |
60
+ |---|---|---|
61
+ | `Playground` | `Playground.tsx` | Интерактивный контроль `loading` |
62
+ | `Default` | `Default.tsx` | Базовый список |
63
+ | `Loading` | `Loading.tsx` | Состояние загрузки (overlay) |
64
+ | `EmptyState` | `EmptyState.tsx` | Использование `ListEmptyState` |
65
+ | `Virtualized` | `Virtualized.tsx` | Виртуализированный список (большие наборы данных) |
66
+ | `Sortable` | `Sortable.tsx` | DnD-сортировка через `ListSortable` + `ListSortableItem` |
67
+ | `SortableWithInteractiveElements` | `SortableWithInteractiveElements.tsx` | DnD с интерактивными элементами внутри строк (`data-draggable="false"`) |
109
68
 
110
- ### ListSortableItem — `IListSortableItemProps extends Omit<LiHTMLAttributes, "children">`
69
+ ---
111
70
 
112
- | Prop | Тип | Обязателен | Описание |
113
- |---|---|---|---|
114
- | `id` | `string` | Да | Уникальный идентификатор, должен совпадать с `items[i].id`. |
115
- | `disabled` | `boolean` | Нет | Блокирует drag. |
116
- | `children` | `ReactNode \| (provideProps) => ReactNode` | — | **Render-props или обычные children**. Provide-props: `{ dragging, disabled, listeners, setActivatorNodeRef }`. |
71
+ ## История изменений
117
72
 
118
- - Использует `useSortable` из dnd-kit, применяет `transform` стиль.
119
- - Render-props позволяют **селективно назначать drag handle** (через `listeners` + `setActivatorNodeRef`), а не делать перетаскиваемым всю строку.
120
- - `ListSortableItem.Target` (Object.assign) — подкомпонент `ListSortableItemTarget`.
73
+ | Дата | Изменение |
74
+ |---|---|
75
+ | 2026-04-29 | Создан документ |
76
+ | 2026-06-17 | `List.module.less`: локальный `z-index: @z-index-step` на `.listLoaderScreen` — исправлено перекрытие `LoaderScreen` поверх `LightBox` / `ModalWindow` |
121
77
 
122
78
  ---
123
79
 
124
- ## Ключевые особенности реализации
80
+ ## Примеры использования
125
81
 
126
- ### `AdvancedMouseSensor` / `AdvancedTouchSensor` — `data-draggable="false"` escape hatch
127
-
128
- ```ts
129
- while (element !== null) {
130
- if (element.dataset?.draggable === "false") return false;
131
- element = element.parentElement;
132
- }
133
- ```
82
+ ### Default
134
83
 
135
- - Любой потомок с `data-draggable="false"` **блокирует инициализацию drag'а**. Используется для кнопок/ссылок внутри строки — иначе клик по ним случайно запускает перетаскивание.
136
- - `MouseSensor`: игнорирует правую кнопку (`button === 2`).
137
- - `TouchSensor`: игнорирует мультитач (`touches.length > 1`).
138
-
139
- ### `ListItemContext` — связь выбора и стилей сиблингов
84
+ `stories/List/examples/List/Default.tsx`
140
85
 
141
86
  ```tsx
142
- <ListItemContext.Provider value={{ selected, setSelected }}>
143
- <li>{children}</li>
144
- </ListItemContext.Provider>
87
+ import React from "react";
88
+ import { List, ListItem } from "@sberbusiness/triplex-next";
89
+
90
+ export const Default = () => (
91
+ <div style={{ width: "500px" }}>
92
+ <List>
93
+ <ListItem>Элемент списка</ListItem>
94
+ <ListItem>Элемент списка</ListItem>
95
+ <ListItem>Элемент списка</ListItem>
96
+ </List>
97
+ </div>
98
+ );
145
99
  ```
146
100
 
147
- - `ListItemSelectable` пишет `selected` в контекст через `useEffect`.
148
- - Другие подкомпоненты (например, `ListItemContent`) могут подписаться и изменить стиль.
149
- - **Паттерн "выбор известен всей строке"** — без prop-drilling.
101
+ ### Loading
150
102
 
151
- ### `loading` на уровне `List`
103
+ `stories/List/examples/List/Loading.tsx`
152
104
 
153
105
  ```tsx
154
- <ul>
155
- {children}
156
- {loading ? <LoaderScreen type="middle" /> : null}
157
- </ul>
106
+ import React from "react";
107
+ import { List, ListItem } from "@sberbusiness/triplex-next";
108
+
109
+ export const Loading = () => (
110
+ <div style={{ width: "150px" }}>
111
+ <List loading>
112
+ <ListItem>Элемент списка</ListItem>
113
+ <ListItem>Элемент списка</ListItem>
114
+ <ListItem>Элемент списка</ListItem>
115
+ <ListItem>Элемент списка</ListItem>
116
+ <ListItem>Элемент списка</ListItem>
117
+ <ListItem>Элемент списка</ListItem>
118
+ </List>
119
+ </div>
120
+ );
158
121
  ```
159
122
 
160
- LoaderScreen рендерится **внутри `<ul>`**, но позиционируется абсолютно (overlay). Структурно `<ul>` содержит `<li>` и невалидный для семантики элемент — это сознательный trade-off в пользу простоты позиционирования.
161
-
162
- ### `data-tx={process.env.npm_package_version}` на `<ul>` и `<li>`
163
-
164
- Версия библиотеки в DOM для отладки. Сохранять при изменениях.
123
+ ### EmptyState
165
124
 
166
- ### ListSortable — vertical-axis only
125
+ `stories/List/examples/List/EmptyState.tsx`
167
126
 
168
- ```ts
169
- modifiers: [restrictToParentElement, restrictToVerticalAxis]
127
+ ```tsx
128
+ import React from "react";
129
+ import {
130
+ Button,
131
+ EButtonTheme,
132
+ EComponentSize,
133
+ EFontWeightTitle,
134
+ ETextSize,
135
+ ETitleSize,
136
+ Gap,
137
+ ListEmptyState,
138
+ Text,
139
+ Title,
140
+ } from "@sberbusiness/triplex-next";
141
+ import { EmptytableSysIcon96 } from "@sberbusiness/icons-next";
142
+
143
+ export const EmptyState = () => (
144
+ <ListEmptyState>
145
+ <div style={{ display: "flex", justifyContent: "center" }}>
146
+ <EmptytableSysIcon96 />
147
+ </div>
148
+
149
+ <Gap size={16} />
150
+
151
+ <Title size={ETitleSize.H3} weight={EFontWeightTitle.REGULAR}>
152
+ Title text
153
+ </Title>
154
+
155
+ <Gap size={8} />
156
+
157
+ <Text size={ETextSize.B3}>Нет данных, но можно предложить какие-то действия для заполнения таблицы.</Text>
158
+
159
+ <Gap size={24} />
160
+
161
+ <Button theme={EButtonTheme.SECONDARY} size={EComponentSize.SM}>
162
+ Button Name
163
+ </Button>
164
+ <Button theme={EButtonTheme.GENERAL} size={EComponentSize.SM}>
165
+ Button Name
166
+ </Button>
167
+ </ListEmptyState>
168
+ );
170
169
  ```
171
170
 
172
- - Список только вертикальный. Для горизонтальных списков — нужен отдельный компонент (сейчас не реализован).
171
+ ### Virtualized
173
172
 
174
- ### ListSortableItem render-props
173
+ `stories/List/examples/List/Virtualized.tsx`
175
174
 
176
175
  ```tsx
177
- <ListSortableItem id="1">
178
- {({ listeners, setActivatorNodeRef }) => (
179
- <>
180
- <ListSortableItem.Target ref={setActivatorNodeRef} {...listeners}>
181
- ≡
182
- </ListSortableItem.Target>
183
- {/* остальной контент — не перетаскиваемый */}
184
- </>
185
- )}
186
- </ListSortableItem>
176
+ import React from "react";
177
+ import { FixedSizeList } from "react-window";
178
+ import { List, ListItem } from "@sberbusiness/triplex-next";
179
+
180
+ const itemData = Array.from({ length: 100 }).map((_, index) => `List item ${index}`);
181
+
182
+ export const Virtualized = () => (
183
+ <FixedSizeList
184
+ itemData={itemData}
185
+ itemCount={itemData.length}
186
+ itemSize={20}
187
+ width="100%"
188
+ height={200}
189
+ innerElementType={List}
190
+ >
191
+ {({ data, index, style }) => <ListItem style={style}>{data[index]}</ListItem>}
192
+ </FixedSizeList>
193
+ );
187
194
  ```
188
195
 
189
- Стандартный паттерн dnd-kit. `setActivatorNodeRef` задаёт элемент-триггер перетаскивания (handle), `listeners` — события.
190
-
191
- ---
192
-
193
- ## Инварианты
194
-
195
- - **`<ul>` + `<li>`** семантика — не заменять на `<div>`.
196
- - **`ListItemContext` shape** (`selected`, `setSelected`) — публичная точка расширения для сторонних кастомных подкомпонентов.
197
- - **`data-draggable="false"`** — атрибут-escape-hatch для ListSortable. Потребители в product-коде могут опираться на него, не менять семантику.
198
- - **`ListSortable` требует `items[].id: string`** — id как в React key, так и в dnd-kit. Переход на number/symbol — breaking.
199
- - **`arrayMove` от dnd-kit** — не собственная реализация. При смене DnD-библиотеки переписать.
200
- - **`IListSortableItemProps.children` — `ReactNode` или функция** — публичный render-props API.
201
- - **`LoaderScreen` внутри `<ul>`** — визуальное решение, не менять без согласования.
202
- - **ForwardRef** на всех компонентах; `ListSortable` — generic через `as <T>(props) => ...` cast.
203
- - **`Object.assign` на `ListSortableItem` → `Target`** — сохранить.
204
-
205
- ---
196
+ ### Sortable
206
197
 
207
- ## Accessibility
208
-
209
- - Семантика списка `<ul>`/`<li>` — правильная. Screen reader'ы объявляют "list, N items".
210
- - `ListItemSelectable` — `<Checkbox>` внутри: нативная клавиатурная навигация, label через расширяющую clickable-область.
211
- - `ListItemControlsButton` / `ListItemControlsButtonDropdown` — проверь, что `aria-label` проставлен (иконки без текста).
212
- - **DnD не доступен с клавиатуры** из коробки (dnd-kit поддерживает `KeyboardSensor`, но здесь не подключён). Known debt.
213
- - Loader'овый overlay скрывает контент — добавь `aria-busy="true"` на `<ul>` через `...rest` на время загрузки.
214
-
215
- ---
216
-
217
- ## Дизайн-токены
218
-
219
- Нет прямых — визуал строки зависит от подкомпонентов (`ListItemSelectable`, `ListItemControls` используют собственные стили в `styles/*.module.less`).
220
-
221
- ---
198
+ `stories/List/examples/List/Sortable.tsx`
222
199
 
223
- ## Связанные компоненты
224
-
225
- - `ListMaster` — master-detail layout на базе List.
226
- - `Table` — табличный вид с колонками.
227
- - `TreeView` — древовидный список.
228
- - `Checkbox` — используется в `ListItemSelectable`.
229
- - `LoaderScreen` — overlay для loading.
230
- - `@dnd-kit/core`, `@dnd-kit/sortable`, `@dnd-kit/modifiers` — DnD-инфраструктура.
231
-
232
- ---
233
-
234
- ## Stories
200
+ ```tsx
201
+ import React, { useState } from "react";
202
+ import { ListSortable, ListSortableItem } from "@sberbusiness/triplex-next";
203
+
204
+ export const Sortable = () => {
205
+ const [items, setItems] = useState(
206
+ Array.from({ length: 10 }, (_, index) => ({ id: `list-sortable-item-0-${index}`, index })),
207
+ );
208
+
209
+ return (
210
+ <ListSortable items={items} onItemsChange={setItems}>
211
+ {items.map(({ id, index }) => (
212
+ <ListSortableItem key={id} id={id}>
213
+ {({ listeners, dragging, setActivatorNodeRef }) => (
214
+ <ListSortableItem.Target {...listeners} dragging={dragging} ref={setActivatorNodeRef}>
215
+ List item {index}
216
+ </ListSortableItem.Target>
217
+ )}
218
+ </ListSortableItem>
219
+ ))}
220
+ </ListSortable>
221
+ );
222
+ };
223
+ ```
235
224
 
236
- - `stories/List/List.stories.tsx`
237
- - `stories/List/ListItem.stories.tsx`
238
- - `stories/List/ListItemControls.stories.tsx`
239
- - Примеры: `stories/List/examples/`
225
+ ### SortableWithInteractiveElements
240
226
 
241
- ---
227
+ `stories/List/examples/List/SortableWithInteractiveElements.tsx`
242
228
 
243
- ## История изменений
229
+ ```tsx
230
+ import React, { useState } from "react";
231
+ import { Checkbox, ListSortable, ListSortableItem, ListSortableItemControls } from "@sberbusiness/triplex-next";
232
+
233
+ export const SortableWithInteractiveElements = () => {
234
+ const [items, setItems] = useState(
235
+ Array.from({ length: 10 }, (_, index) => ({ id: `list-sortable-item-1-${index}`, index })),
236
+ );
237
+
238
+ return (
239
+ <ListSortable items={items} onItemsChange={setItems}>
240
+ {items.map(({ id, index }) => (
241
+ <ListSortableItem key={id} id={id}>
242
+ {({ listeners, dragging, setActivatorNodeRef }) => (
243
+ <ListSortableItem.Target {...listeners} dragging={dragging} ref={setActivatorNodeRef}>
244
+ <ListSortableItemControls>
245
+ <Checkbox>List item {index}</Checkbox>
246
+ </ListSortableItemControls>
247
+ </ListSortableItem.Target>
248
+ )}
249
+ </ListSortableItem>
250
+ ))}
251
+ </ListSortable>
252
+ );
253
+ };
254
+ ```
244
255
 
245
- | Дата | Изменение |
246
- |---|---|
247
- | 2026-04-18 | Создан документ |