@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.
Same wiring. Wildly different trees.
Each panel below is identical TreeController wiring — different fixture, row renderer, indent geometry, constraint stack. Drag rows, expand chevrons, click to select — it all works.
Grida
Monochrome zinc accent. Eye + lock per row, full reorder drag.
Figma
Dark layers panel. Components in purple, hidden layers dim, full reorder drag.
VS Code
Filesystem semantics — drop is always into the nearest folder. Target highlights in blue. No reordering.
Finder
Multi-column grid, zebra rows, double-click to expand. Same FS drag rule as VS Code.
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.