dnd-dynamic-tree
v0.1.5
Published
[](https://www.npmjs.org/package/dnd-dynamic-tree) [](https://opensource.org/licenses/MIT) [
✨ Features
- 🚀 Zero-Config Start: Get up and running in seconds with
npx create-dnd-dynamic-tree. - 🎯 "Easy Mode": Use the pre-configured
SimpleTreefor immediate results. - 🔍 Built-in Search: Includes a smart
filterTreeutility that preserves parent structure. - ⌨️ Accessible: Full keyboard navigation support out of the box.
- 🎨 Highly Customizable: Full control over rendering with
SortableTree. - 📂 Nested & Infinite: Supports unlimited nesting depth.
- ⚡ Performance First: Virtualization-ready architecture and optimized re-renders.
🚀 Quick Start
Option A: The Fast Way (Recommended)
Scaffold a complete component with dependencies in one command:
npx create-dnd-dynamic-treeOption B: Manual Installation
npm install dnd-dynamic-tree @dnd-kit/core @dnd-kit/sortable @dnd-kit/utilities💡 Usage Examples
1. The "Easy Mode" (Prototyping)
Use SimpleTree and useTreeState for a working tree in 3 lines of code.
import { SimpleTree, useTreeState } from 'dnd-dynamic-tree';
const initialData = [
{ id: '1', value: 'Dashboard' },
{ id: '2', value: 'Settings', children: [
{ id: '2-1', value: 'Profile' },
{ id: '2-2', value: 'Security' }
]}
];
export const MyTree = () => {
const { items, onItemsChanged } = useTreeState(initialData);
return (
<SimpleTree
items={items}
onItemsChanged={onItemsChanged}
/>
);
};2. Search & Filtering
Use the built-in filterTree utility to implement search that keeps context.
import { SimpleTree, useTreeState, filterTree } from 'dnd-dynamic-tree';
export const SearchableTree = () => {
const { items, setItems, onItemsChanged } = useTreeState(initialData);
const [query, setQuery] = useState('');
// Filter items when query changes
const displayItems = useMemo(() => {
if (!query) return items;
return filterTree(items, (item) =>
item.value.toLowerCase().includes(query.toLowerCase())
);
}, [items, query]);
return (
<div>
<input
type="text"
placeholder="Search..."
onChange={(e) => setQuery(e.target.value)}
className="mb-4 p-2 border rounded"
/>
<SimpleTree
items={displayItems}
onItemsChanged={onItemsChanged}
/>
</div>
);
};3. Fully Custom Rendering
For complete control, use SortableTree and provide your own component.
import { SortableTree, SimpleTreeItemWrapper } from 'dnd-dynamic-tree';
const CustomItem = React.forwardRef((props, ref) => (
// Wrappers handle the drag mechanics for you
<SimpleTreeItemWrapper {...props} ref={ref}>
<div className="flex items-center justify-between p-2 bg-white border rounded shadow-sm">
<div className="flex items-center gap-2">
{props.item.children?.length ? '📂' : '📄'}
<span className="font-medium">{props.item.value}</span>
</div>
<button onClick={props.onRemove} className="text-red-500">×</button>
</div>
</SimpleTreeItemWrapper>
));
export const CustomTree = () => {
// ... state setup ...
return (
<SortableTree
items={items}
onItemsChanged={setItems}
TreeItemComponent={CustomItem}
indentationWidth={24}
/>
);
};4. Windows Explorer Style
Use FolderTreeItemWrapper to get connecting lines and folder mechanics.

import { SortableTree, FolderTreeItemWrapper } from 'dnd-dynamic-tree';
// Pass FolderTreeItemWrapper as the TreeItemComponent
<SortableTree
// ... props
TreeItemComponent={React.forwardRef((props, ref) => (
<FolderTreeItemWrapper {...props} ref={ref}>
<span>{props.item.value}</span>
</FolderTreeItemWrapper>
))}
/>⌨️ Accessibility
This library supports keyboard navigation:
- Tab: Focus on tree items.
- Space/Enter: Pick up an item.
- Up/Down: Move the item vertically.
- Right/Left: Nest/unnest the item (change depth).
- Space/Enter: Drop the item.
- Escape: Cancel drag.
🤝 Contributing
Contributions are welcome!
- Fork the repo
npm installnpm run devto start the demonpm testto run the test suite
📄 License
MIT © Shantanu Soam
