Drag-and-drop sortable representation of hierarchical data for React 18/19 with virtualized rendering powered by virtua and react-dnd. Storybook demos cover both basic and advanced scenarios.
Install the package together with its peer dependencies:
npm install @nosferatu500/react-sortable-tree react-dnd react-dnd-html5-backend
# or
yarn add @nosferatu500/react-sortable-tree react-dnd react-dnd-html5-backendThe bundle is ESM-only and includes all styles via runtime injection (no separate CSS file is required).
import { useState } from 'react'
import SortableTree, { TreeItem } from '@nosferatu500/react-sortable-tree'
const initialData: TreeItem[] = [
{ title: 'Chicken', children: [{ title: 'Egg' }] },
{ title: 'Fish', children: [{ title: 'Fingerling' }] },
]
export function ExampleTree() {
const [treeData, setTreeData] = useState(initialData)
return (
<div style={{ height: 400 }}>
<SortableTree
treeData={treeData}
onChange={setTreeData}
getNodeKey={({ node }) => node.id ?? node.title}
/>
</div>
)
}Already have a surrounding react-dnd context? Use the context-less export instead:
import { SortableTreeWithoutDndContext } from '@nosferatu500/react-sortable-tree'All props are typed in ReactSortableTreeProps (see src/react-sortable-tree.tsx). Key options:
treeData(required): array ofTreeItemobjects{ title?, subtitle?, expanded?, children? }.onChange(required):(treeData) => voidcalled on every change.getNodeKey:(data) => string | numberto generate stable paths (defaults to index).generateNodeProps: customize nodes (buttons, styles, extra props).- Drag & drop control:
canDrag,canDrop,canNodeHaveChildren,shouldCopyOnOutsideDrop,onMoveNode,onDragStateChanged,dndType. - Appearance & layout:
rowHeight(number or function),rowDirection('ltr' | 'rtl'),scaffoldBlockPxWidth,slideRegionSize,style,innerStyle,className,theme,nodeContentRenderer,placeholderRenderer,treeNodeRenderer,virtuaReffor direct access to the virtual list. - Search:
searchQuery,searchMethod,searchFocusOffset,onlyExpandSearchedNodes,searchFinishCallback. - Behavior:
maxDepth,loadCollapsedLazyChildren,onVisibilityToggle. - Integration:
dragDropManagerfor externalreact-dndproviders.
Utilities exported from src/utils/tree-data-utils.ts:
addNodeUnderParent,insertNode: place a node under a path with depth control.removeNode,removeNodeAtPath,changeNodeAtPath: update or delete nodes immutably.getNodeAtPath,getDescendantCount,getDepth: inspect tree structure.map,walk,toggleExpandedForAll: traverse or mutate trees.getFlatDataFromTree,getTreeFromFlatData: convert between nested and flat data.getVisibleNodeCount,getVisibleNodeInfoAtIndex,find: search and pagination helpers.isDescendant: check parent-child relationships.
Default helpers from src/utils/default-handlers.ts include defaultGetNodeKey and defaultSearchMethod.
MIT