@molecule/app-tree-view
Core interface · tree-view · App (browser) · v1.0.2 · Apache-2.0
Tree view core interface for molecule.dev.
npm install @molecule/app-tree-viewHow it works
@molecule/app-tree-view is the tree-view core interface on the app (browser) side: the API your app calls, with no vendor inside.
Choose the implementation by bonding one of its 1 provider: @molecule/app-tree-view-default.
import { requireProvider, setProvider } from '@molecule/app-tree-view'
import { provider } from '@molecule/app-tree-view-default'
setProvider(provider) // once, at startup (bonds.ts)
const tree = requireProvider().createTree({
data: [{ id: 'root', label: 'Root', children: [{ id: 'child', label: 'Child' }] }],
onSelect: (node) => openNode(node),
})
tree.expandNode('root')Providers (1): @molecule/app-tree-view-default
Works with: @molecule/app-bond
Live demos
Running apps built with Molecule that install this package — open the app or study the template.
Reference
Tree view core interface for molecule.dev.
Provides a standardized API for hierarchical tree UI components
with support for selection, expansion, drag-and-drop, and checkboxes.
Bond a provider (e.g. @molecule/app-tree-view-default) to supply
the concrete implementation.
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Quick Start
import { requireProvider, setProvider } from '@molecule/app-tree-view'
import { provider } from '@molecule/app-tree-view-default'
setProvider(provider) // once, at startup (bonds.ts)
const tree = requireProvider().createTree({
data: [{ id: 'root', label: 'Root', children: [{ id: 'child', label: 'Child' }] }],
onSelect: (node) => openNode(node),
})
tree.expandNode('root')
Type
core
Installation
npm install @molecule/app-tree-view @molecule/app-bond
API
Interfaces
TreeNode
A node in a tree hierarchy.
interface TreeNode<T = unknown> {
/** Unique identifier for the node. */
id: string
/** Display label for the node. */
label: string
/** Child nodes. */
children?: TreeNode<T>[]
/** Optional data payload attached to the node. */
data?: T
/** Optional icon identifier. */
icon?: string
/** Whether the node is expanded. */
expanded?: boolean
/** Whether the node is selected. */
selected?: boolean
/**
* Whether the node's checkbox is checked. Distinct from `selected` — this is
* the multi-check state driven via `toggleChecked` and only meaningful when
* the tree was created with `showCheckboxes: true`.
*/
checked?: boolean
/** Whether the node is disabled (non-interactive). */
disabled?: boolean
}
TreeOptions
Configuration options for creating a tree view.
interface TreeOptions<T = unknown> {
/** Root-level tree data. */
data: TreeNode<T>[]
/** Callback when a node is selected. */
onSelect?: (node: TreeNode<T>) => void
/** Callback when a node is expanded or collapsed. */
onExpand?: (node: TreeNode<T>) => void
/** Whether multiple nodes can be selected simultaneously. Defaults to `false`. */
multiSelect?: boolean
/** Whether nodes can be dragged to reorder. Defaults to `false`. */
draggable?: boolean
/** Callback when a node is dropped onto another. */
onDrop?: (
source: TreeNode<T>,
target: TreeNode<T>,
position: 'before' | 'after' | 'inside',
) => void
/** Whether to show checkboxes for each node. Defaults to `false`. */
showCheckboxes?: boolean
}
TreeInstance
A live tree view instance returned by the provider.
interface TreeInstance<T = unknown> {
/**
* Returns the current tree data.
*
* @returns Array of root-level tree nodes.
*/
getData(): TreeNode<T>[]
/**
* Replaces the tree data.
*
* @param data - New root-level tree nodes.
*/
setData(data: TreeNode<T>[]): void
/**
* Expands a node by its ID.
*
* @param id - The node ID to expand.
*/
expandNode(id: string): void
/**
* Collapses a node by its ID.
*
* @param id - The node ID to collapse.
*/
collapseNode(id: string): void
/**
* Expands all nodes in the tree.
*/
expandAll(): void
/**
* Collapses all nodes in the tree.
*/
collapseAll(): void
/**
* Selects a node by its ID.
*
* @param id - The node ID to select.
*/
selectNode(id: string): void
/**
* Returns all currently selected nodes.
*
* @returns Array of selected tree nodes.
*/
getSelectedNodes(): TreeNode<T>[]
/**
* Toggles the checkbox state of a node by its ID.
*
* Only has an effect when the tree was created with `showCheckboxes: true`;
* otherwise it is a no-op. Disabled nodes are never toggled. The checkbox
* (`checked`) state is independent of selection (`selected`).
*
* @param id - The node ID whose checkbox to toggle.
*/
toggleChecked(id: string): void
/**
* Returns all nodes whose checkbox is currently checked.
*
* @returns Array of checked tree nodes.
*/
getCheckedNodes(): TreeNode<T>[]
/**
* Moves a node relative to a target node, reparenting or reordering it.
*
* Only performs the move when the tree was created with `draggable: true`;
* otherwise it is a rejected no-op returning `false`. Moving a node into its
* own subtree (or onto itself) is rejected. On a successful move the tree is
* mutated in place and the `onDrop` callback fires with the moved node, the
* target, and the position.
*
* @param sourceId - ID of the node to move.
* @param targetId - ID of the node to move relative to.
* @param position - Placement relative to the target: `before`/`after` as a
* sibling, or `inside` as a child.
* @returns `true` if the move was performed, `false` if rejected.
*/
moveNode(sourceId: string, targetId: string, position: 'before' | 'after' | 'inside'): boolean
/**
* Destroys the tree view instance and cleans up resources.
*/
destroy(): void
}
TreeViewProvider
Tree view provider interface.
All tree view providers must implement this interface to create and manage hierarchical tree UI components.
interface TreeViewProvider {
/** Provider name identifier. */
readonly name: string
/**
* Creates a new tree view instance.
*
* @param options - Configuration for the tree view.
* @returns A tree instance for managing the tree.
*/
createTree<T = unknown>(options: TreeOptions<T>): TreeInstance<T>
}
Functions
setProvider(provider)
Registers a tree view provider as the active singleton.
function setProvider(provider: TreeViewProvider): void
provider— The tree view provider implementation to bond.
getProvider()
Retrieves the bonded tree view provider, or null if none is bonded.
function getProvider(): TreeViewProvider | null
Returns: The active tree view provider, or null.
hasProvider()
Checks whether a tree view provider has been bonded.
function hasProvider(): boolean
Returns: true if a tree view provider is available.
requireProvider()
Retrieves the bonded tree view provider, throwing if none is configured.
function requireProvider(): TreeViewProvider
Returns: The active tree view provider.
Available Providers
| Provider | Package |
|---|---|
| Tree View | @molecule/app-tree-view-default |
Injection Notes
Requirements
Peer dependencies:
@molecule/app-bond^1.0.1
Runtime Dependencies
-
@molecule/app-bond -
The instance is HEADLESS state, not UI.
createTreereturns tree state operations (expandNode/selectNode/getData/…) — nothing appears on screen. The app renders the nodes itself, re-rendering after state calls; style viagetClassMap()from@molecule/app-uiand run node labels that are UI text throught('key', values, { defaultValue }). -
Wire it with THIS package's
setProvider()orbond('tree-view', …).setProvider()delegates into the shared@molecule/app-bondregistry, so both write the same slot;requireProviderthrows until one has run. -
Drive reordering with
moveNode(sourceId, targetId, position)— it mutates the tree and firesonDroponly whendraggable: true, and is a rejected no-op otherwise. Drive checkbox state withtoggleChecked(id)+getCheckedNodes(), active only whenshowCheckboxes: true; the checkbox (checked) state is independent of selection (selected).multiSelect,draggable, andshowCheckboxesall default tofalse. -
Call
destroy()when the owning screen unmounts.
E2E Tests
End-to-end checklist — drive the RENDERED tree in the live preview (real nodes, no mocks), adapt each item to this app's actual tree screen, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip:
- The root-level nodes from
datarender on screen with their labels; a node withchildrenshows an expand/collapse affordance and a leaf does not. A node withdisabled: truerenders non-interactive — clicking it neither selects it nor firesonSelect. - Expanding a parent reveals its child rows and collapsing hides them
again, and the expanded STATE is reflected: the re-rendered node shows its
expanded affordance and the node's
expandedflag ingetData()matches what's on screen.expandAll()/collapseAll()open/close the whole tree; each toggle firesonExpandwith the affected node. - Clicking a node selects it:
onSelectfires with THAT node (verify itsid/label), the row is visibly highlighted, and the node appears ingetSelectedNodes(). - Single vs multi matches config: with
multiSelectoff (default), selecting a second node REPLACES the first (getSelectedNodes()holds one); withmultiSelect: true, selections ACCUMULATE (the set grows). - A deeply nested node renders indented under its full parent chain — the on-screen depth/indent matches the data nesting, not a flat list.
- If
showCheckboxesis enabled, a checkbox renders per node and toggling one updates that node's selected state andgetSelectedNodes(). Where the app wires parent/child cascade, checking a parent also checks its rendered children (the core exposes selection state, not a built-in cascade). - If
draggableis enabled, dragging a node onto another firesonDropwith the source, target, and position (before/after/inside) and the tree re-renders in the new order;onDropnever fires whendraggableis off.