import { default as React } from 'react';
/**
* A node in the {@link TreeWidget} hierarchy.
*
* The model is deliberately domain-neutral: the component knows about branches
* and leaves, and nothing else. A file explorer, an org chart, a scene graph and
* a category picker are all the same shape here — what differs is your `kind`
* and your `icon`.
*/
export interface ITreeNode {
/** Stable identifier, unique across the whole tree. */
id: string;
/** Text shown for the node. */
label: string;
/**
* Whether this node can contain children — a folder, a department, a group.
* Branches expand on click and accept drops; leaves do neither.
*
* Defaults to `false`. Set it explicitly for a branch whose children haven't
* been loaded yet, so it still renders as expandable.
*/
isBranch?: boolean;
/**
* Your own classification for this node, e.g. `"folder"`, `"department"`,
* `"question"`. The component never interprets it — it exists so context-menu
* actions can target node types through {@link ITreeAction.showFor}.
*/
kind?: string;
/** Child nodes. Only rendered while `isOpen` is `true`. */
children?: ITreeNode[];
/** Whether a branch is expanded. Controlled by you — see `onToggle`. */
isOpen?: boolean;
/**
* Icon rendered before the label. Any node works — a `lucide-react` icon, an
* avatar, a coloured dot. Omit it for a label-only row.
*/
icon?: React.ReactNode;
/** Extra classes merged onto this row. */
className?: string;
}
/** Where a context-menu action applies. */
export interface ITreeContext {
/** The right-clicked node's id, or `null` for the background. */
nodeId: string | null;
/** The right-clicked node, or `null` for the background. */
node: ITreeNode | null;
}
/**
* Where a context-menu entry is offered.
*
* `'branch'` and `'leaf'` match structurally; `'background'` is a right-click on
* empty space. Any other string is matched against the node's `kind`, so you can
* scope an action to your own node types.
*/
export type TreeActionScope = 'branch' | 'leaf' | 'background' | (string & {});
/** An entry in the tree's right-click menu. */
export interface ITreeAction {
/** Stable identifier. Used as the React key. */
id: string;
/** Label shown in the menu. */
label: string;
/** Optional icon element, rendered before the label. */
icon?: React.ReactNode;
/** Runs with the right-clicked target. */
onSelect: (context: ITreeContext) => void;
/** Draw a separator above this entry. */
divider?: boolean;
/**
* Restrict where the entry appears. Defaults to everywhere.
*
* @example
* ```ts
* showFor: ['branch', 'background'] // structural
* showFor: ['department'] // matches node.kind
* ```
*/
showFor?: TreeActionScope[];
}
export interface TreeWidgetProps {
/** Root nodes. Expansion state lives on the nodes themselves via `isOpen`. */
data: ITreeNode[];
/**
* Called when a branch is clicked. Flip that node's `isOpen` in your own
* state — the tree renders expansion but does not own it.
*/
onToggle?: (node: ITreeNode) => void;
/** Called when a node is double-clicked or Enter is pressed on a leaf. */
onActivate?: (node: ITreeNode) => void;
/**
* Called after a node is dragged onto a branch. Only branches accept drops.
* Reparenting is yours to perform — the tree does not mutate `data`.
*/
onMoveNode?: (draggedId: string, targetBranchId: string) => void;
/**
* Entries for the right-click menu. Empty by default: the component ships no
* actions of its own, because "New File" means nothing to an org chart.
*
* With no entries, no menu appears.
*/
actions?: ITreeAction[];
/** Indentation added per depth level, in px. Defaults to `12`. */
indent?: number;
/**
* Virtualise rows with `react-virtuoso`. Leave on for large trees; turn it
* off when every row must be present in the DOM — printing, full-text browser
* search, or a test environment that can't measure layout. Defaults to `true`.
*/
virtualized?: boolean;
/** Accessible label for the tree. Defaults to `"Tree"`. */
'aria-label'?: string;
/** Extra classes merged onto the root element. */
className?: string;
}
/**
* A virtualised, domain-neutral tree with drag-to-move and a data-driven
* right-click menu.
*
* It renders any hierarchy — files, an org chart, a scene graph, nested
* categories, an argument map. The component's only structural concept is
* `isBranch`: branches expand and accept drops, leaves do neither. Everything
* else — what a node *is*, what icon it carries, what actions it offers — is
* yours to supply.
*
* Rows are virtualised via `react-virtuoso`, so large trees stay responsive.
*
* Controlled: expansion lives on your nodes as `isOpen` and changes are
* reported through `onToggle`, so the tree never holds a second copy of your
* data.
*
* @example
* ```tsx
* // An org chart — no files in sight.
* ,
* children: [
* { id: 'ada', label: 'Ada Lovelace', kind: 'person', icon: },
* ],
* },
* ]}
* onToggle={(node) => setNodes(toggle(nodes, node.id))}
* actions={[
* { id: 'hire', label: 'Add report', showFor: ['department'], onSelect: addReport },
* ]}
* />
* ```
*/
export declare const TreeWidget: ({ data, onToggle, onActivate, onMoveNode, actions, indent, virtualized, "aria-label": ariaLabel, className, }: TreeWidgetProps) => import("react/jsx-runtime").JSX.Element;