@grida/tree-view
Headless, agnostic tree-view controller for editors and IDEs. No DOM imports in the core, no widget library on top — just a state machine plus a small set of pure helpers, and you render the rows with whatever framework and stylesheet you want.
Wire it to a real editor.
Each section below is the same TreeController wired to a working surface — a canvas, an editor pane, a desktop. Select, hover, reorder, and delete flow both ways through the package's channels. Different fixture, row renderer, and constraint stack; identical core.
Layers, wired to a canvas.
One TreeController drives the panel and the artboard. Select, hover, reorder, delete on either side — the other follows.
Drag rows to reorder · click a shape to select · ⌫ to delete
Same wiring, dark chrome.
Identical controller and intent bridge — only the row renderer and the canvas palette changed. Reordering a layer re-stacks the design.
Drag rows to reorder · click a shape to select · ⌫ to delete
Explorer, opening files.
Filesystem semantics: drops resolve into the nearest folder. Selecting a file opens it — selection is the only wire to the editor pane.
It just looks native.
Multi-column rows, zebra striping, double-click to expand — the same core, dressed as macOS and dropped onto the desktop.
Built for editor scale.
The state machine, the math, the intents — packaged so adopters ship a tree in a day, not a quarter.
Zero runtime dependencies
~500 LOC of business logic, ESM + CJS, full TypeScript types. Nothing else gets pulled in.
You own your data
TreeSource is read-only — wrap your editor state; the package never mutates your store.
Headless drag & drop
Pure state machine plus geometry helpers. Compose move constraints, fire move / copy intents, plug into any pointer or touch backend.
Six subscription channels
rows · expanded · focus · drag · selection · intent — fine-grained so a row only re-renders for its own slice.
Keyboard, with type-ahead
Configurable keymap dispatch, default keymap shipped (never auto-wired), platform-consistent modifier composition.
Virtualization-ready
controller.getRows() is a stable flat list — plug straight into @tanstack/react-virtual or any windowing library.
Production-grown
Driven by the same controller as the Grida editor's layers panel. The demo gallery reproduces Figma, VS Code, and Finder from one core.
Optional React peer
Core runs unchanged in Node, Bun, Deno, browser, web worker. React bindings are an opt-in /react subpath.