```tsx
import React from 'react';
import { Tree } from '@salutejs/plasma-web';
export function App() {
const treeData = [
{
title: 'Основной каталог',
key: '0-0',
children: [
{
title: 'Документы',
key: '0-0-0',
children: [
{
title: 'Отчёты',
key: '0-0-0-0',
disabled: true,
},
{
title: 'Проекты',
key: '0-0-0-1',
children: [
{
title: 'Проект Альфа',
key: '0-0-0-1-0',
},
{
title: 'Проект Бета',
key: '0-0-0-1-1',
},
],
},
{
title: 'Категории',
key: '0-0-0-2',
children: [
{
title: 'Категория Гамма',
key: '0-0-0-2-0',
},
{
title: 'Категория Дельта',
key: '0-0-0-2-1',
},
],
},
],
},
{
title: 'Медиа',
key: '0-0-1',
children: [
{
title: 'Фотографии',
key: '0-0-1-0',
},
],
},
],
},
{
title: 'Корзина',
key: '0-1',
children: [
{
title: 'Удалённые файлы',
key: '0-1-0',
},
],
},
];
return (
);
}
```
```tsx
import React from 'react';
import { Tree } from '@salutejs/plasma-web';
export function App() {
const treeData = [
{
title: 'Основной каталог',
key: '0-0',
children: [
{
title: 'Документы',
key: '0-0-0',
children: [
{
title: 'Отчёты',
key: '0-0-0-0',
disabled: true,
},
{
title: 'Проекты',
key: '0-0-0-1',
children: [
{
title: 'Проект Альфа',
key: '0-0-0-1-0',
},
{
title: 'Проект Бета',
key: '0-0-0-1-1',
},
],
},
{
title: 'Категории',
key: '0-0-0-2',
children: [
{
title: 'Категория Гамма',
key: '0-0-0-2-0',
},
{
title: 'Категория Дельта',
key: '0-0-0-2-1',
},
],
},
],
},
{
title: 'Медиа',
key: '0-0-1',
children: [
{
title: 'Фотографии',
key: '0-0-1-0',
},
],
},
],
},
{
title: 'Корзина',
key: '0-1',
children: [
{
title: 'Удалённые файлы',
key: '0-1-0',
},
],
},
];
return (
);
}
```
```tsx
import React from 'react';
import { Tree } from '@salutejs/plasma-web';
export function App() {
const treeData = [
{
title: 'Основной каталог',
key: '0-0',
children: [
{
title: 'Документы',
key: '0-0-0',
children: [
{
title: 'Отчёты',
key: '0-0-0-0',
disabled: true,
},
{
title: 'Проекты',
key: '0-0-0-1',
children: [
{
title: 'Проект Альфа',
key: '0-0-0-1-0',
},
{
title: 'Проект Бета',
key: '0-0-0-1-1',
},
],
},
{
title: 'Категории',
key: '0-0-0-2',
children: [
{
title: 'Категория Гамма',
key: '0-0-0-2-0',
},
{
title: 'Категория Дельта',
key: '0-0-0-2-1',
},
],
},
],
},
{
title: 'Медиа',
key: '0-0-1',
children: [
{
title: 'Фотографии',
key: '0-0-1-0',
},
],
},
],
},
{
title: 'Корзина',
key: '0-1',
children: [
{
title: 'Удалённые файлы',
key: '0-1-0',
},
],
},
];
const [expanded, setExpanded] = React.useState([]);
const [checked, setChecked] = React.useState([]);
const [selected, setSelected] = React.useState([]);
return (
);
}
```
```tsx
import React from 'react';
import { Tree } from '@salutejs/plasma-web';
export function App() {
const treeData = [
{
title: 'Основной каталог',
key: '0-0',
children: [
{
title: 'Документы',
key: '0-0-0',
children: [
{
title: 'Отчёты',
key: '0-0-0-0',
disabled: true,
},
{
title: 'Проекты',
key: '0-0-0-1',
children: [
{
title: 'Проект Альфа',
key: '0-0-0-1-0',
},
{
title: 'Проект Бета',
key: '0-0-0-1-1',
},
],
},
{
title: 'Категории',
key: '0-0-0-2',
children: [
{
title: 'Категория Гамма',
key: '0-0-0-2-0',
},
{
title: 'Категория Дельта',
key: '0-0-0-2-1',
},
],
},
],
},
{
title: 'Медиа',
key: '0-0-1',
children: [
{
title: 'Фотографии',
key: '0-0-1-0',
},
],
},
],
},
{
title: 'Корзина',
key: '0-1',
children: [
{
title: 'Удалённые файлы',
key: '0-1-0',
},
],
},
];
return (
);
}
```
```tsx
import React from 'react';
import { Tree } from '@salutejs/plasma-web';
export function App() {
const treeData = [
{
title: 'Основной каталог',
key: '0-0',
children: [
{
title: 'Документы',
key: '0-0-0',
children: [
{
title: 'Отчёты',
key: '0-0-0-0',
disabled: true,
},
{
title: 'Проекты',
key: '0-0-0-1',
children: [
{
title: 'Проект Альфа',
key: '0-0-0-1-0',
},
{
title: 'Проект Бета',
key: '0-0-0-1-1',
},
],
},
{
title: 'Категории',
key: '0-0-0-2',
children: [
{
title: 'Категория Гамма',
key: '0-0-0-2-0',
},
{
title: 'Категория Дельта',
key: '0-0-0-2-1',
},
],
},
],
},
{
title: 'Медиа',
key: '0-0-1',
children: [
{
title: 'Фотографии',
key: '0-0-1-0',
},
],
},
],
},
{
title: 'Корзина',
key: '0-1',
children: [
{
title: 'Удалённые файлы',
key: '0-1-0',
},
],
},
];
const [expanded, setExpanded] = React.useState([]);
const [checked, setChecked] = React.useState([]);
const [selected, setSelected] = React.useState([]);
return (
);
}
```
Для включения виртуализации обязательными являются 2 свойства: `height` и `itemHeight` . Также есть опциональный флаг для явного отключения/включения виртуализации: `virtual` .
```tsx
import React from 'react';
import { Tree } from '@salutejs/plasma-web';
export function App() {
return (
({ key: i.toString(), title: i.toString() }))}
height={400}
itemHeight={48}
/>
);
}
```
## Drag'n'Drop Для включения режима Drag and Drop нужно включить свойство `draggable` . Также имеется ряд обработчиков, однако наиболее важным из них является `onDrop` .
Для более индивидуальной настройки логики работы механизма Drag'n'Drop данный обработчик настраивается на стороне клиента. Примеры ниже будут более наглядными: Данный пример базовый, покрывающий наиболее распространенные сценарии использования.
Также присутствует возможность создавать из крайних элементов группы, вкладывая в них другие элементы.
```tsx
import React from 'react';
import { Tree, TreeProps, TreeItem } from '@salutejs/plasma-web';
export function App() {
const treeData = [
{
title: 'Основной каталог',
key: '0-0',
children: [
{
title: 'Документы',
key: '0-0-0',
children: [
{
title: 'Отчёты',
key: '0-0-0-0',
disabled: true,
},
{
title: 'Проекты',
key: '0-0-0-1',
children: [
{
title: 'Проект Альфа',
key: '0-0-0-1-0',
},
{
title: 'Проект Бета',
key: '0-0-0-1-1',
},
],
},
{
title: 'Категории',
key: '0-0-0-2',
children: [
{
title: 'Категория Гамма',
key: '0-0-0-2-0',
},
{
title: 'Категория Дельта',
key: '0-0-0-2-1',
},
],
},
],
},
{
title: 'Медиа',
key: '0-0-1',
children: [
{
title: 'Фотографии',
key: '0-0-1-0',
},
],
},
],
},
{
title: 'Корзина',
key: '0-1',
children: [
{
title: 'Удалённые файлы',
key: '0-1-0',
},
],
},
];
const [items, setItems] = React.useState(treeData);
const onDrop: TreeProps['onDrop'] = (info) => {
const dropKey = info.node.key;
const dragKey = info.dragNode.key;
const dropPos = info.node.pos.split('-');
const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
// Функция-хелпер для прохода по дереву элементов
const loop = (
data: TreeItem[],
key: React.Key,
callback: (node: TreeItem, i: number, data: TreeItem[]) => void,
) => {
data.forEach((item, index, arr) => {
if (item.key === key) {
callback(item, index, arr);
return;
}
if (item.children) {
loop(item.children, key, callback);
}
});
};
const data = [...items];
// Ищем draggable-элемент
let dragObj: TreeItem;
loop(data, dragKey, (item, index, arr) => {
arr.splice(index, 1);
dragObj = item;
});
if (dropPosition === 0) {
// Вставляем элемент внутрь target-элемента
loop(data, dropKey, (item) => {
item.children = item.children || [];
item.children.unshift(dragObj);
});
} else {
// Вставляем элемент вначале или после target-элемента
let ar: TreeItem[] = [];
let i: number;
loop(data, dropKey, (_item, index, arr) => {
ar = arr;
i = index;
});
if (dropPosition === -1) {
ar.splice(i!, 0, dragObj!);
} else {
ar.splice(i! + 1, 0, dragObj!);
}
}
setItems(data);
};
const allowDrop: TreeProps['allowDrop'] = (info) => {
return !info.dropNode.disabled;
};
return (
);
};
```
## Drag'n'Drop Для включения режима Drag and Drop нужно включить свойство `draggable` . Также имеется ряд обработчиков, однако наиболее важным из них является `onDrop` .
Для более индивидуальной настройки логики работы механизма Drag'n'Drop данный обработчик настраивается на стороне клиента. Примеры ниже будут более наглядными: Данный пример базовый, покрывающий наиболее распространенные сценарии использования.
Также присутствует возможность создавать из крайних элементов группы, вкладывая в них другие элементы. ```tsx
import React from 'react';
import { Tree, TreeProps, TreeItem } from '@salutejs/plasma-web';
export function App() {
const treeData = [
{
title: 'Основной каталог',
key: '0-0',
children: [
{
title: 'Документы',
key: '0-0-0',
children: [
{
title: 'Отчёты',
key: '0-0-0-0',
disabled: true,
},
{
title: 'Проекты',
key: '0-0-0-1',
children: [
{
title: 'Проект Альфа',
key: '0-0-0-1-0',
},
{
title: 'Проект Бета',
key: '0-0-0-1-1',
},
],
},
{
title: 'Категории',
key: '0-0-0-2',
children: [
{
title: 'Категория Гамма',
key: '0-0-0-2-0',
},
{
title: 'Категория Дельта',
key: '0-0-0-2-1',
},
],
},
],
},
{
title: 'Медиа',
key: '0-0-1',
children: [
{
title: 'Фотографии',
key: '0-0-1-0',
},
],
},
],
},
{
title: 'Корзина',
key: '0-1',
children: [
{
title: 'Удалённые файлы',
key: '0-1-0',
},
],
},
];
const [items, setItems] = React.useState(treeData);
const onDrop: TreeProps['onDrop'] = (info) => {
const dropKey = info.node.key;
const dragKey = info.dragNode.key;
const dropPos = info.node.pos.split('-');
const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
// Функция-хелпер для прохода по дереву элементов
const loop = (
data: TreeItem[],
key: React.Key,
callback: (node: TreeItem, i: number, data: TreeItem[]) => void,
) => {
data.forEach((item, index, arr) => {
if (item.key === key) {
callback(item, index, arr);
return;
}
if (item.children) {
loop(item.children, key, callback);
}
});
};
const data = [...items];
// Ищем draggable-элемент
let dragObj: TreeItem;
loop(data, dragKey, (item, index, arr) => {
arr.splice(index, 1);
dragObj = item;
});
if (dropPosition === 0) {
// Вставляем элемент внутрь target-элемента
loop(data, dropKey, (item) => {
item.children = item.children || [];
item.children.unshift(dragObj);
});
} else {
// Вставляем элемент вначале или после target-элемента
let ar: TreeItem[] = [];
let i: number;
loop(data, dropKey, (_item, index, arr) => {
ar = arr;
i = index;
});
if (dropPosition === -1) {
ar.splice(i!, 0, dragObj!);
} else {
ar.splice(i! + 1, 0, dragObj!);
}
}
setItems(data);
};
const allowDrop: TreeProps['allowDrop'] = (info) => {
return !info.dropNode.disabled;
};
return (
);
};
```
Если нужно запретить создавать группы из крайних элементов, нужно воспользоваться свойством `allowDrop` .
```tsx
import React from 'react';
import { Tree, TreeProps, TreeItem } from '@salutejs/plasma-web';
export function App() {
const treeData = [
{
title: 'Основной каталог',
key: '0-0',
children: [
{
title: 'Документы',
key: '0-0-0',
children: [
{
title: 'Отчёты',
key: '0-0-0-0',
disabled: true,
},
{
title: 'Проекты',
key: '0-0-0-1',
children: [
{
title: 'Проект Альфа',
key: '0-0-0-1-0',
},
{
title: 'Проект Бета',
key: '0-0-0-1-1',
},
],
},
{
title: 'Категории',
key: '0-0-0-2',
children: [
{
title: 'Категория Гамма',
key: '0-0-0-2-0',
},
{
title: 'Категория Дельта',
key: '0-0-0-2-1',
},
],
},
],
},
{
title: 'Медиа',
key: '0-0-1',
children: [
{
title: 'Фотографии',
key: '0-0-1-0',
},
],
},
],
},
{
title: 'Корзина',
key: '0-1',
children: [
{
title: 'Удалённые файлы',
key: '0-1-0',
},
],
},
];
const [items, setItems] = React.useState(treeData);
const onDrop: TreeProps['onDrop'] = (info) => {
const dropKey = info.node.key;
const dragKey = info.dragNode.key;
const dropPos = info.node.pos.split('-');
const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
// Функция-хелпер для прохода по дереву элементов
const loop = (
data: TreeItem[],
key: React.Key,
callback: (node: TreeItem, i: number, data: TreeItem[]) => void,
) => {
data.forEach((item, index, arr) => {
if (item.key === key) {
callback(item, index, arr);
return;
}
if (item.children) {
loop(item.children, key, callback);
}
});
};
const data = [...items];
// Ищем draggable-элемент
let dragObj: TreeItem;
loop(data, dragKey, (item, index, arr) => {
arr.splice(index, 1);
dragObj = item;
});
if (dropPosition === 0) {
// Вставляем элемент внутрь target-элемента
loop(data, dropKey, (item) => {
item.children = item.children || [];
item.children.unshift(dragObj);
});
} else {
// Вставляем элемент вначале или после target-элемента
let ar: TreeItem[] = [];
let i: number;
loop(data, dropKey, (_item, index, arr) => {
ar = arr;
i = index;
});
if (dropPosition === -1) {
ar.splice(i!, 0, dragObj!);
} else {
ar.splice(i! + 1, 0, dragObj!);
}
}
setItems(data);
};
const allowDrop: TreeProps['allowDrop'] = (info) => {
if (info.dropNode.disabled || !info.dropNode.children && info.dropPosition === 0) {
return false;
}
return true;
};
return (
);
};
```
## Пример с autoExpandParent Иногда может возникнуть необходимость раскрыть дерево до нужного ключа пробросив только его в поле `expanded` . В стандартном сценарии ничего не произойдет, т.к. вышестоящие уровни будут закрыты.
Поэтому данное поведение можно реализовать с помощью свойства `autoExpandParent` .
```tsx
import React from 'react';
import { Tree, Button } from '@salutejs/plasma-web';
export function App() {
const [expanded, setExpanded] = React.useState([]);
const [autoExpandParent, setAutoExpandParent] = React.useState(true);
const treeData = [
{
title: 'Основной каталог',
key: '0-0',
children: [
{
title: 'Документы',
key: '0-0-0',
children: [
{
title: 'Отчёты',
key: '0-0-0-0',
disabled: true,
},
{
title: 'Проекты',
key: '0-0-0-1',
children: [
{
title: 'Проект Альфа',
key: '0-0-0-1-0',
},
{
title: 'Проект Бета',
key: '0-0-0-1-1',
},
],
},
{
title: 'Категории',
key: '0-0-0-2',
children: [
{
title: 'Категория Гамма',
key: '0-0-0-2-0',
},
{
title: 'Категория Дельта',
key: '0-0-0-2-1',
},
],
},
],
},
{
title: 'Медиа',
key: '0-0-1',
children: [
{
title: 'Фотографии',
key: '0-0-1-0',
},
],
},
],
},
{
title: 'Корзина',
key: '0-1',
children: [
{
title: 'Удалённые файлы',
key: '0-1-0',
},
],
},
];
const handleExpand = (expandedValue) => {
setAutoExpandParent(false);
setExpanded(expandedValue);
};
return (
{
setAutoExpandParent(true);
setExpanded(['0-0-0']);
}}
>
Открыть уровень "Документы"
);
}
```