Nested Lists and Tree
comins-sortable@0.1.6
Playground paths below are local routes for the module repository’s development server. They are not live routes on this documentation site.
Nested areas declare their parent item so collision can reject a move from a parent into its own descendant.
createSortableTree is the framework-neutral adapter for one immutable tree
value. It does not render components or own state.
Complete example
Section titled “Complete example”import { createSortableTree } from 'comins-sortable/core';
export type Node = { id: string; label: string; children: readonly Node[];};
const tree = createSortableTree<Node>({ rootAreaId: 'root', getNodeId: (node) => node.id, getChildren: (node) => node.children, withChildren: (node, children) => ({ ...node, children }), getChildrenAreaId: (node) => `children-${node.id}`,});
export const initialNodes: readonly Node[] = [ { id: 'planning', label: 'Planning', children: [{ id: 'scope', label: 'Define scope', children: [] }], }, { id: 'delivery', label: 'Delivery', children: [] },];
export function getTreeAreas(nodes: readonly Node[]) { return tree.getAreas(nodes);}
export function updateTreeArea( nodes: readonly Node[], areaId: string, nextItems: readonly Node[],) { return tree.updateArea(nodes, areaId, nextItems);}Render every result from getTreeAreas(nodes) as a framework Area. Pass its
areaId, items, and optional parent without changing them, then replace the
tree state with the value returned by updateTreeArea.
getAreas returns area descriptors; it does not construct nested DOM. Render
child areas inside their corresponding parent item when a hierarchical view is
required. A flat rendering of those descriptors is not a recursive tree view.
updateArea replaces only the direct items of the selected area. Existing
nodes retain their current descendant collections, including when framework
source and destination setters apply one cross-area move sequentially.
Use applyChange when one framework Root change should be folded into the
whole tree transaction. Unknown areas, duplicate node or area IDs, and cycles
fail without mutating the input.
What the Playground examples demonstrate
Section titled “What the Playground examples demonstrate”- Nested lists in React, Vue, and Svelte keep separate root and child arrays. They demonstrate DOM
nesting, the
parentrelationship, and transfers between lists. - Per-list state control (
nested-controlled) in React, Vue, and Svelte updates parent and child arrays separately. Reverse children changes only the child array, preserving the parent order. The initial structure and instructions explain these updates. - Per-list DOM updates is the Vanilla tab of the same
nested-controlledroute. It reorders child DOM and callsrefreshArea; it does not update controlled array state. The regular Vanilla nested-list example also operates on DOM. - Subtree movement (
tree) keeps one recursivechildrenvalue and derives each area throughcreateSortableTree. The initial three levels are Research → Review → Document/Observe, alongside an empty Design folder. Move Review into Design to carry both descendants with it. Parent relationships update after the move.
In this display, dragging a parent carries its child areas with it, so its own
descendant areas are not drop targets. Moving Research toward its own Review
area therefore does not demonstrate explicit cycle-rejection feedback. Core
rejects a hit-tested destination with nested-cycle when its parent chain
makes it a descendant of the dragged item. Observing that rejection requires a
logical descendant area that remains separately exposed during the drag.
In React, Vue, and Svelte, per-list state control and subtree movement are both controlled and use the same Core sorting engine. Both reject cycles. The distinction is updating individual list arrays versus managing parent changes and subtree preservation in one tree. The structure diagram summarizes the initial state; the actual card layout shows the current state after a move.
The refreshed Playground GIF demonstrates both the independent child-array update and Review moving with its descendants.
Playground:
/examples/nested/react/examples/nested-controlled/react/examples/functional-third-party/react/examples/tree/react