DOCUMENTATION / API

API reference.

Everything needed to build a tree, inspect a model and connect interaction to your application. Start with the guide for a working example.

TreeView

TreeView creates the canvas, filter control, editor and tooltip inside a host element. Give that element a height. The package is JavaScript ESM with bundled declarations for editor autocomplete. The element, canvas, controller and destroyed properties expose the mounted view state.

JavaScriptDOM view
import { TreeView } from 'virtual-tree-canvas';

const view = new TreeView(host, { filter: true, initialExpandDepth: 2 });
view.setData(nodes);
view.on('selectionchange', ({ detail }) => console.log(detail.selection));
// On permanent unmount: view.destroy();
MethodWhat it does
configure(options) / flush()Apply a configuration patch. Changes are batched; flush() applies a pending patch immediately.
setData(nodes) / setModel(model, meta?)Install application rows or inspect a JavaScript value. Either call switches to the matching mode.
setColumns(columns) / setTheme(theme)Replace the columns or theme. Pass null to setColumns for the current presentation's defaults.
setDynamicState(patches)Patch live values by row ID without reinstalling the tree.
setInspectorValue(path, value, options?)Write a model value by property path. Returns whether the write was accepted; use { emit: false } to suppress edit events.
on(type, listener) / off(type, listener)Subscribe to component events or remove a listener. on returns an unsubscribe function.
registerIcon(name, source)Register an application SVG URL, SVG string, image or Canvas draw function.
destroy()Release observers, events, editors and rendering resources on permanent unmount.

Configuration options

Pass these to the constructor or view.configure(options). The component defaults to one selected row, an editable tree and a visible filter.

OptionPurpose
mode, presentation'tree' or 'inspector'; inspector layout 'pane' or 'table'.
nodes, model, metaInitial row data or inspected value and metadata. Explicit setData and setModel calls are also available.
columns, themeColumn definitions and a built-in theme name or theme object.
filter, filterPlacementShow the built-in filter (default true). Placement: 'auto', 'bar' or 'header'. Hiding it retains the current query; call clearFilter() to clear it.
editable, multiSelectAllow editing (default true) and multiple selected rows (default false).
rowReorder, rowActions, rowDragSibling order controls, row buttons and data drag payloads. Each is optional.
initialExpandDepth, flatRoot, enforceMetaControl initial expansion and inspector structure. Expansion depth applies when installing data.
showHeader, headerHeightShow or hide column headings and set their height. Hiding headings does not hide the filter bar.
rowHeight, indentWidth, fontFamilyLayout metrics and text font. Explicit row and indent sizes override theme values.
iconResolver, markUpdatedMap row icons without mutating nodes; mark changed inspector values.
scrollChainingLet wheel scrolling reach an ancestor at the tree's edges. Default false.
iconsBaseUrl, iconRegistry, nativeScrollbarsConstructor-only icon and scrollbar options. Built-in icons need no asset URL.

Rows, live values, search and filtering

For setData, each row needs a stable id. Use parentId for children. Optional row fields include label, type, icon, image, tags, data and reorderable. Dynamic patches have an id and a state object, such as { id: 'btc', state: { value: 42 } }.

The built-in filter is enabled by default and keeps matching descendants visible with their ancestors. Search highlights matches and can move focus. Use filtering to narrow the visible tree; use search to navigate results. Compare the bar above the large tree and the header filter in the units table.

JavaScriptFilter and search
view.setFilter('radar');
view.setFilter('radar', { caseSensitive: true, wholeWord: true });
view.setFilter((node, state) => state.status === 'warning');
view.clearFilter();

view.search('radar');
view.nextSearchResult();
view.clearSearch();
MethodWhat it does
setFilter(queryOrPredicate, options?) / clearFilter()Filter visible rows with text or a predicate; text options are caseSensitive and wholeWord.
search(query, options?) / clearSearch()Highlight matches and clear them. Search options include limit, fields, expand, focus and select.
getSearchState() / nextSearchResult() / previousSearchResult()Read the current query and results or navigate between them.
focusNode(id, options?) / scrollToNode(id, align?)Focus a row or scroll to it. Alignment is 'start', 'center', 'end' or 'nearest'.
expandAll() / collapseAll()Change expansion for the whole tree.

Columns, sorting and themes

Use builtInColumns or define columns with id, label, width, minWidth, align, kind and sortable. Kinds include tree, status, value, progress, type, updated and text. value(node, state) supplies the raw value; format(value, node, state) changes displayed text and tooltips without changing sort order. render(ctx, cell) draws custom Canvas2D content.

Sorting orders siblings within their parent, preserving the hierarchy. Click a heading to cycle ascending, descending and unsorted, or use view.controller.sortBy(id, direction). The raw value is compared, so formatting a number as a string does not turn numeric sorting into lexical sorting.

JavaScriptSemantic value colours
import { builtInColumns, lightTheme } from 'virtual-tree-canvas';

view.setColumns([
  builtInColumns.tree,
  {
    id: 'change', label: '24h %', kind: 'value', width: 90,
    value: (_node, state) => state.change,
    valueType: (value) => value > 0 ? 'positive' : value < 0 ? 'negative' : 'neutral',
    format: (value) => `${value.toFixed(2)}%`
  }
]);
view.setTheme({ ...lightTheme, valueColors: {
  ...lightTheme.valueColors, positive: '#15803d', negative: '#be123c'
} });

valueType can be a fixed semantic name or a callback. Its colour comes from theme.valueColors; it does not change formatting or sorting. Built-in darkTheme and lightTheme are available, and theme.statuses customizes status pills.

Column helpers include builtInColumns, defaultTreeTableColumns() and inspectorColumns(). For icons, builtinIconNames lists bundled names. registerIcon() accepts a custom source; iconsBaseUrl points to a replacement SVG directory. Applications sharing icons across views can supply an IconRegistry and use its register(), get(), prepare() and draw() methods.

Object inspector metadata

setModel(model, meta?) makes property rows from an object or array. No IDs are required. Metadata keys are property paths such as 'sensor.range' or wildcard paths such as 'tracks.*.speed'. Use presentation: 'pane' for compact controls or 'table' for Property / Value columns.

MetadataPurpose
min, max, step, integerNumeric editor and range bounds.
unit, precisionDisplay-only suffix and decimal places; the stored numeric value retains its precision.
readonly, disabled, updatedEditing state and changed-value indication.
options, color, buttonChoice editor, colour editor or action button.
label, description, type, iconProperty text and visual identity.
itemType, itemTitle, itemFactoryArray item editor type, object summary and value used when adding an item.
fullWidthButtonSpan the available inspector row for a button.

Array items use compact indexed rows; primitive values edit in the row, while objects and nested arrays expand. The inspector emits valuechange for a value edit, modelchange for model changes and action for metadata buttons.

Selection, order, actions and data drag

Selection is single row by default. With multiSelect: true, Ctrl/Command + click toggles rows, Shift + click selects a range, and Shift + drag selects a visible range. An ordinary click still selects one row.

Method or optionWhat it does
getSelection() / setSelection(ids) / clearSelection()Read, replace or clear selected IDs. Single-selection mode keeps at most one ID.
rowReorder: trueAdd a dedicated handle to reorder siblings in setData trees. Sorting and filtering temporarily disable manual order.
getRowOrder(parentId?) / moveRow(id, index) / moveRowBy(id, offset)Read or change sibling order programmatically. moveRow and moveRowBy return whether a move occurred.
rowActionsAccessible row buttons or checkboxes with id, label, optional icon, visible, disabled, pressed or checked.
rowDrag(node, state)Return a data payload or null to disable dragging for a row. A plain drag exports the source row or the selected group.

The component emits drag events with the selected items, nodeIds and pointer event. Your application decides where a drop is valid and updates its data. See the two-tree transfer example.

Events

Subscribe with view.on(type, listener). Each listener receives an event whose payload is event.detail. Unsubscribe with the function returned by on, or use off.

EventsWhen they fire
selectionchange, focuschangeSelected IDs or focused row changes.
filterchange, searchchangeVisible rows change due to filtering, or search results change.
expand, collapse, sortchangeTree expansion or column sort changes.
nodeclick, nodedblclick, nodecontextmenu, nodehoverPointer interaction with a row.
valuechange, modelchange, actionInspector edit, model update or metadata action.
rowaction, rowreorderRow button activation or sibling order change.
rowdragstart, rowdragmove, rowdragend, rowdragcancelData drag lifecycle. The host handles destination and drop.
columnschange, viewportchange, layoutchangeColumn or viewport layout changes.

Lower-level controller

Use TreeViewController when your application already owns the canvas and render loop. view.controller exposes the same controller inside a TreeView. Methods shared with TreeView work on both; the controller also provides the operations below.

JavaScriptCanvas integration
import { TreeViewController } from 'virtual-tree-canvas';

const tree = new TreeViewController({ canvas, host, autoRender: true });
tree.setData(nodes);
tree.sortBy('value', 'asc');
// On permanent unmount: tree.destroy();
MethodWhat it does
expand(id) / collapse(id) / toggle(id)Change one branch; each returns whether its expansion state changed.
sortBy(id, direction?) / clearSort()Sort siblings by a column or restore their original order. Direction is 'asc', 'desc' or 'toggle'.
resizeColumn(id, width) / moveColumn(id, index)Change column geometry or order.
setRowActions(actions) / setRowDrag(resolver)Replace row actions or data drag resolver without rebuilding rows.
setEditable(enabled) / setMultiSelect(enabled) / setRowReorder(enabled)Change interaction modes directly on the controller.
setInitialExpandDepth(depth) / setIconResolver(resolver)Set defaults for future data installations and map row icons without changing input rows.
setInspectorOptions(options) / setHeaderFilter(enabled)Set inspector options or place its filter in the first column heading.
setModel(model, meta?, options?)Controller form of model inspection; the third argument accepts presentation and inspector options.
updateInspectorValue(id, value) / closeEditor()Update an inspector row by node ID or close its active editor. setInspectorValue(path, value) is easier when a property path is known.
enableWorkers(url?) / disableWorkers()Enable or stop optional worker processing for search and filtering. Enabling returns a promise.
searchAsync(query, options?) / setFilterAsync(query, options?)Use a worker when enabled; otherwise use the synchronous implementation.
render() / requestRender() / getStats()Draw immediately, schedule a draw or inspect component metrics. renderMeasured() returns timing details.
resize(width, height) / setLayoutMetrics(options)Update canvas size or row, indent and heading metrics.
scrollTo(x, y) / hitTest(x, y)Control scrolling or find the canvas element at client coordinates. getViewportState() reads current dimensions and offsets.
initialize(canvas) / attachInput() / attachCellEditor() / attachTooltip()Attach controller facilities when assembling a custom host.

The large-tree demo exercises asynchronous filtering and exposes live render metrics. The inspector demo shows the pane and table presentations.