Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/shaddix/dnd-kit-sortable-tree
Tree component for React with ability to drag-and-drop items throughout the tree. Based on an example from dnd-kit (https://github.com/clauderic/dnd-kit).
https://github.com/shaddix/dnd-kit-sortable-tree
drag-and-drop react tree-structure
Last synced: 2 days ago
JSON representation
Tree component for React with ability to drag-and-drop items throughout the tree. Based on an example from dnd-kit (https://github.com/clauderic/dnd-kit).
- Host: GitHub
- URL: https://github.com/shaddix/dnd-kit-sortable-tree
- Owner: Shaddix
- License: mit
- Created: 2021-09-12T17:41:06.000Z (about 3 years ago)
- Default Branch: master
- Last Pushed: 2024-01-25T16:30:02.000Z (10 months ago)
- Last Synced: 2024-11-06T22:44:26.398Z (9 days ago)
- Topics: drag-and-drop, react, tree-structure
- Language: TypeScript
- Homepage:
- Size: 1.67 MB
- Stars: 92
- Watchers: 3
- Forks: 22
- Open Issues: 18
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# dnd-kit-sortable-tree
[![npm version](https://badge.fury.io/js/dnd-kit-sortable-tree.svg)](https://www.npmjs.org/package/dnd-kit-sortable-tree) [![npm](https://img.shields.io/npm/dt/dnd-kit-sortable-tree.svg)](https://www.npmjs.org/package/dnd-kit-sortable-tree) [![MIT](https://img.shields.io/dub/l/vibe-d.svg)](https://opensource.org/licenses/MIT)
This is a Tree component extracted from [dndkit](https://github.com/clauderic/dnd-kit) examples and abstracted a bit.
Here's how it could look like (visuals are completely customizable via css though)
[![img.png](img.png)](https://shaddix.github.io/dnd-kit-sortable-tree)Play around in [examples](https://shaddix.github.io/dnd-kit-sortable-tree) to check the API and see what it can do.
## Install
npm install dnd-kit-sortable-tree @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities
## How-to use
Check out the Storybook for code samples and play around. You could also play with it on [playcode](https://playcode.io/1032571)
Shortly, you need to render:
```tsx
```
And `TreeItemComponent` is usually your data wrapped in `SimpleTreeItemWrapper` or `FolderTreeItemWrapper`:
```tsx
React.forwardRef((props, ref) => (
{props.item.value}
));
```Note that wrapping in `forwardRef` and passing `ref` to `SimpleTreeItemWrapper` is very important!
## Examples
1. Here's the very minimal code to add a Sortable Tree. You shouldn't use it as is in your project, but it could be easier to grasp what's going on.
```jsx
export const Minimal = () => {
const [items, setItems] = useState(initialMinimalData);
return (
(
{/* HERE GOES THE ACTUAL CONTENT OF YOUR COMPONENT */}
{props.item.id}
))}
/>
);
};
/*
* Configure the tree data.
*/
const initialMinimalData = [
{ id: '1', children: [{ id: '4' }, { id: '5' }] },
{ id: '2' },
{ id: '3' },
];
```
2. Here's the minimal viable example that you could potentially copy&paste to your project to start from.```tsx
export const MinimalViable = () => {
const [items, setItems] = useState(initialViableMinimalData);
return (
);
};
type MinimalTreeItemData = {
value: string;
};
/*
* Here's the component that will render a single row of your tree
*/
const MinimalTreeItemComponent = React.forwardRef<
HTMLDivElement,
TreeItemComponentProps
>((props, ref) => (
/* you could also use FolderTreeItemWrapper if you want to show vertical lines. */
{props.item.value}
));/*
* Configure the tree data.
*/
const initialViableMinimalData: TreeItems = [
{
id: '1',
value: 'Jane',
children: [
{ id: '4', value: 'John' },
{ id: '5', value: 'Sally' },
],
},
{ id: '2', value: 'Fred', children: [{ id: '6', value: 'Eugene' }] },
{ id: '3', value: 'Helen', canHaveChildren: false },
];
```## API
### Data configuration (each TreeItem element could define them):
- `canHaveChildren` - Default: `true`.
If set to `false`, prevents any node from being dragged into the current one.
Also accepts a function: `(dragItem) => bool` which could conditionally determine if a certain item could be a children of a node
- `disableSorting` - Default: `false`. If set to `true`, prevents node from being dragged (i.e. it can't be sorted or moved to another node)
### Tree configuration (props of ``)
- `items` - _mandatory_, items shown in a tree
- `onItemsChanged` - _mandatory_, callback that is called when dragging of certain item is finished. You should preserve new state and adjust the value of `items` prop as needed.
- `TreeItemComponent` - _mandatory_, component that renders a single tree row.
- `indentationWidth` - _optional_, padding used for children
- `pointerSensorOptions` - _optional_, configures the condition when item dragging starts. Defaults to:```json
{
"activationConstraint": {
"distance": 3
}
}
```- `disableSorting` - _optional_, you could set this to `true` to completely disable the sorting
- `keepGhostInPlace` - _optional_, you could set this to `true` to keep the Node that you are dragging in it's original place in a Tree. Check [VSCode](https://shaddix.github.io/dnd-kit-sortable-tree/?path=/story/simple--vs-code-like) sample to see it in action.
- `dndContextProps` - _optional_, override any prop of underlying [DndContext](https://docs.dndkit.com/api-documentation/context-provider#props).
- `sortableProps` - _optional_, override any prop that is passed to underlying [useSortable](https://docs.dndkit.com/presets/sortable/usesortable) hook.### TreeItemWrapper configuration (props of `` and ``)
- `manualDrag` - Default: `false`. Set to `true` if you want tree item to be draggable ONLY from dragHandle.
- `showDragHandle` - _optional_, set to `false` if you want to hide default dragHandle and show your own instead. Use `DRAG_ME` for your own drag handle.# FAQ
1. If you want to [disable animation completely](https://shaddix.github.io/dnd-kit-sortable-tree/?path=/story/simple--no-drop-animation), you need to do the following:
1. Pass `null` as `dropAnimation` prop (this disables the actual 'drop' animation for the Node that was dragged).
1. Pass `{ animateLayoutChanges: () => false }` to `sortableProps` (this disables the animation of all other nodes that were not dragged)# Troubleshooting
1. If your dragged item is shown at the end of a list, make sure you that:
1. You wrapped your `TreeItem` component in `React.forwardRef` and passing the `ref` to `SimpleTreeItemWrapper`
1. You pass the `styles` prop from `TreeItem` to `SimpleTreeItemWrapper`