# Tree
URL: https://pro.rv-grid.com/api/tree/
Source: src/content/docs/api/tree.md
## Module Extensions

### `ColumnRegular` (Extended from `@revolist/revogrid`)

```ts
interface ColumnRegular {
  /**
       * Enables tree template on cells
       */
      tree?: boolean
}
```

---

### `HTMLRevoGridElement` (Extended from `global`)

```ts
interface HTMLRevoGridElement {
  tree?: TreeConfig
}
```

---

### `AdditionalData` (Extended from `@revolist/revogrid`)

```ts
interface AdditionalData {
  /**
       * Additional data property tree
       * @deprecated Use `grid.tree` instead.
       *
       * @example
       * ```typescript
       * const grid = document.createElement('revo-grid');
       * grid.additionalData = {
       *   tree: {
       *     idField: 'id',
       *     parentIdField: 'parentId',
       *     rootParentId: null,
       *     expandAll: true,
       *     expandedRowIds: new Set(),
       *   },
       * };
       * ```
       */
      tree?: TreeConfig
}
```

---

### `HTMLRevoGridElementEventMap` (Extended from `global`)

```ts
interface HTMLRevoGridElementEventMap {
  [TREE_ROW_SELECT_EVENT]: TreeRowSelectEvent;
  [TREE_TOGGLE_EVENT]: { rowId: any };
  [TREE_EXPAND_ALL_EVENT]: undefined;
  [TREE_COLLAPSE_ALL_EVENT]: undefined;
  [TREE_STATE_CHANGED_EVENT]: { expandedRowIds: Set<any> }
}
```

## Plugin API

### `TreeDataPlugin`

The TreeDataPlugin now uses Revogrid's row trimming mechanism without modifying the original data.

All tree metadata (level, expanded, hasChildren, visible) is computed separately and stored in a Map.
The plugin builds a parent→children mapping from the original flat data and then recursively computes,
for each row, its tree level and whether it should be visible based on the expanded/collapsed state
of its ancestors.

The cell template uses a supplied "getMeta" function to look up computed tree metadata for rendering
(indentation and expand/collapse icons) without changing the underlying row.

Usage Example:
```ts
import { TreeDataPlugin } from './tree/index';

const grid = document.createElement('revo-grid');
grid.plugins = [TreeDataPlugin];

grid.columns = [
  {
    prop: 'treeColumn',
    name: 'Hierarchy',
    tree: true,
    cellTemplate: TreeCellTemplate, // or you can let the plugin override it
  },
];
```

#### Dependencies

- **Event integration** `row-order`: Integrates with RowOrderPlugin row order events to reparent tree rows after drag and drop.
- **Event integration** `row-select`: Integrates with RowSelectPlugin row selection events for parent and descendant selection.
- **Event integration** `DimensionAnimationPlugin`: Auto-installs DimensionAnimationPlugin when tree.animation is enabled to animate tree collapse and expand trim changes.

```ts
class TreeDataPlugin {
  /**
     * Recomputes the tree metadata for every row in the original data and builds a trimmed map.
     * Call this method after the original data/order/visibility/set changes
     *
     * This method builds a parent→children mapping (without modifying the original data) and then
     * recursively computes for each row:
     *  - its level (indentation),
     *  - whether it is expanded (based on the expandedRowIds set),
     *  - whether it has children,
     *  - and whether it should be visible (i.e. none of its ancestors are collapsed).
     *
     * The trimmed map is then applied via providers.data.setTrimmed().
     */
  async updateTree(type?: DimensionRows);

  /**
     * Toggle the expanded state for a row and then re-calculate tree metadata.
     */
  toggleRowExpanded(row: DataType);

  getExpandedRowIds();

  toggleRowExpandedById(rowId: any);

  expandAll();

  collapseAll();

  /**
     * Gets all descendant row IDs (children, grandchildren, etc.) for a given row
     * @param rowId - The ID of the row to get descendants for
     * @returns Array of physical indices of all descendant rows
     */
  public getAllDescendantPhysicalIndices(rowId: any, type: DimensionRows = 'rgRow'): number[];
}
```

---

### `TreeMeta`

This is the shape of computed tree metadata.
Notice that nothing is stored on the row itself.

```ts
interface TreeMeta {
  level: number;
  expanded: boolean;
  hasChildren: boolean;
  visible: boolean;
  parentId: any
}
```

---

### `TreeConfig`

```ts
interface TreeConfig {
  idField?: string;
  parentIdField?: string;
  rootParentId?: any;
  expandAll?: boolean;
  expandedRowIds?: Set<any>;
  /**
     * Mark tree parent rows as sticky through StickyCellsPlugin.
     *
     * Parent detection uses the row model fields configured by `idField` and
     * `parentIdField`, plus tree metadata computed by TreeDataPlugin. It does not
     * depend on virtual row indexes.
     *
     * This option only adds sticky behavior to tree-enabled columns. Register
     * StickyCellsPlugin separately to render those parent rows in pinned top rows.
     *
     * @default false
     */
    stickyParents?: boolean;
  /**
     * Animate tree collapse and expand through DimensionAnimationPlugin.
     *
     * TreeDataPlugin auto-registers DimensionAnimationPlugin when this option is
     * enabled and the dimension animation plugin is not already registered.
     *
     * @default false
     */
    animation?: boolean
}
```

---

### `TreeRowSelectEvent`

Event emitted when a tree row with children is selected.
This event allows for custom handling of parent-child selection relationships.

```ts
interface TreeRowSelectEvent {
  /** The row type (e.g., 'rgRow') */
    type: DimensionRows;
  /** The physical index of the parent row in the source data */
    parentIndex: number;
  /** Array of physical indices of all descendant rows */
    childrenIndices: number[];
  /** The original row selection event that triggered this tree selection */
    originalEvent?: any
}
```

---

### `TreeSelectionProvider`

Runtime contract exposed by TreeDataPlugin for plugins that need tree
descendant lookup without depending on the TreeDataPlugin class.

```ts
interface TreeSelectionProvider {
  getAllDescendantPhysicalIndices(rowId: unknown, type: DimensionRows): number[]
}
```

---

### `TreeAnimationCoordinator`

```ts
class TreeAnimationCoordinator {
  beginUpdate(type: DimensionRows): number;

  isCurrent(type: DimensionRows, version: number): boolean;

  canAnimate(type: DimensionRows, dimensionAnimation?: DimensionAnimationPlugin): dimensionAnimation is DimensionAnimationPlugin;

  markInitialized(type: DimensionRows, sourceLength: number);

  hasTrimChanges(
    currentTrimmed: Record<number, boolean>,
    nextTrimmed: Record<number, boolean>,
  ): boolean;

  async applyAnimatedTrim(;
}
```

---

### `resolveTreeFilterTrim`

Keeps ancestor rows visible when a descendant matches the active filter.

The filter plugin marks non-matching physical row indexes as trimmed. Tree
filtering preserves those data-row decisions and only removes trim entries
for ancestors that are needed to display a matching descendant path.

```ts
export function resolveTreeFilterTrim(;
```

---

### `TreeFilterTrimOptions`

```ts
export type TreeFilterTrimOptions = {
  filterTrimmed: TrimmedEntity;
  idField: string;
  parentIdField: string;
  rootParentId: any;
  source: DataType[];
};
```

---

### `TreeRowOrderController`

```ts
class TreeRowOrderController {
  isParentUpdatePending(type: DimensionRows): boolean;

  handleDragEnd();

  handleDropValidation(context: RowOrderDropValidationContext): TreeDropValidation;

  handleRowDrop(e: CustomEvent<RowOrderChange>);

  highlightDropTarget(context: RowOrderDropStateChange);

  clearDropTarget();
}
```

---

### `isTreeRowType`

```ts
export function isTreeRowType(type: unknown): type is DimensionRows;
```

---

### `resolveTreeTrimState`

```ts
export function resolveTreeTrimState(
  allTrimmed: Record<string, Record<number, boolean>> =;
```

---

### `computeTreeState`

```ts
export function computeTreeState(;
```

---

### `collectExpandableRowIds`

```ts
export function collectExpandableRowIds(;
```

---

### `TRIMMED_COLLAPSED`

```ts
TRIMMED_COLLAPSED: string;
```

---

### `TREE_ROW_TYPES`

```ts
TREE_ROW_TYPES: DimensionRows[];
```

---

### `TreeState`

```ts
export type TreeState = {
  itemParentOrder: number[];
  metaData: Map<any, TreeMeta>;
  rowMetaEntries: Array<[DataType, TreeMeta]>;
  trimmed: Record<number, boolean>;
};
```

---

### `TreeTrimState`

```ts
export type TreeTrimState = {
  currentTreeTrimmed: Record<number, boolean>;
  outsideTrimmed: TrimmedEntity;
};
```

---

### `TreeRuntimeState`

```ts
class TreeRuntimeState {
  setConfig(options: TreeConfig =;

  snapshotExpandedRowIds(): Set<any>;

  toggleExpanded(rowId: any);

  setExpandedRowIds(expandedRowIds: Set<any>);

  clearExpandedRowIds();

  setExpandAllPending(pending: boolean);
}
```

---

### `isNoopTreeDrop`

```ts
export function isNoopTreeDrop(;
```

---

### `resolveTreeDropParentId`

```ts
export function resolveTreeDropParentId(;
```

---

### `validateTreeRowDrop`

```ts
export function validateTreeRowDrop(;
```

---

### `resolveTreeDropValidation`

```ts
export function resolveTreeDropValidation(;
```

---

### `moveProxySubtreesAfterTarget`

```ts
export function moveProxySubtreesAfterTarget(;
```

---

### `moveProxySubtreesToTarget`

```ts
export function moveProxySubtreesToTarget(;
```

---

### `TreeCellTemplate`

The TreeCellTemplate now receives an extra "getMeta" callback that provides the computed
tree metadata for the given row. It does not assume that any tree information has been stored
on the row itself.

```ts
TreeCellTemplate: (toggleRowExpanded: (data: DataType) => void, getMeta: (row: DataType) => TreeMeta) => CellTemplate<DataType<any, ColumnProp>>;
```

---

### `applyTreeStickyParentColumns`

```ts
export function applyTreeStickyParentColumns(
  columnsByType: ColumnCollection['columns'],
  resolveStickyCell: (model: CellTemplateProp, stickyCell: StickyCellPredicate | undefined) => boolean,
);
```

---

### `resolveTreeStickyCell`

```ts
export function resolveTreeStickyCell(
  model: CellTemplateProp,
  stickyCell: StickyCellPredicate | undefined,
  context: TreeStickyCellContext,
): boolean;
```

---

### `getStickyTreeConfig`

```ts
export function getStickyTreeConfig(revogrid: HTMLRevoGridElement): TreeConfig | undefined;
```

---

### `resolveActiveTreeStickyRows`

```ts
export function resolveActiveTreeStickyRows(;
```

---

### `TreeStickyCellContext`

```ts
interface TreeStickyCellContext {
  config: TreeConfig | undefined;
  getMeta(row: DataType): TreeMeta
}
```

---

### `ActiveTreeStickyRowsContext`

```ts
interface ActiveTreeStickyRowsContext {
  rowIndex: number;
  maxRows: number;
  config: TreeConfig;
  includeRow?: boolean;
  rowStore: {
      get(key: 'source'): DataType[];
      get(key: 'items'): number[];
    };
  resolveStickyColumns(rowIndex: number): boolean
}
```
