import type { ReactNode } from 'react'; export type TreeNode = { id: string; label: ReactNode; icon?: ReactNode; data?: T; /** * Present (even as an empty array) means this node's children are * already known - eager mode relies entirely on this and never calls * `loadChildren`. Leave it undefined for a node whose children haven't * been fetched yet (lazy mode). */ children?: TreeNode[]; /** * Only consulted while `children` is undefined and `loadChildren` is * given: says whether this node is expected to have children at all. * Defaults to true (assume expandable) so a node the caller hasn't * inspected yet still shows a toggle; set it to false for a node you * already know is a leaf, to skip showing a toggle for it entirely. */ hasChildren?: boolean; }; /** Fetches one node's children. Called once per node, the first time it's expanded (and again on retry after a failed load). Presence of this prop on TreeView is what switches it into lazy mode. */ export type LoadTreeChildren = (node: TreeNode) => Promise[]>; export type TreeViewProps = { /** Top-level nodes. In eager mode every node's full subtree must already be present via `children`. In lazy mode only the nodes you already know about need to be here - deeper levels arrive via `loadChildren`. */ data: TreeNode[]; /** Omit for eager mode. Provide for lazy mode. */ loadChildren?: LoadTreeChildren; /** Uncontrolled initial expanded ids. Ignored if `expandedIds` is given. */ defaultExpandedIds?: string[]; /** Controlled expanded ids - pass together with `onExpandedIdsChange` to own the expand/collapse state yourself (e.g. to sync it with a URL). */ expandedIds?: string[]; onExpandedIdsChange?: (ids: string[]) => void; selectedId?: string; onSelectNode?: (node: TreeNode) => void; /** Customize how a node's row content renders; defaults to `node.icon` + `node.label`. */ renderLabel?: (node: TreeNode) => ReactNode; /** Allows node labels to wrap onto multiple lines. Set to false to truncate them to one line. */ wrapLabels?: boolean; emptyMessage?: ReactNode; /** Formats the error shown under a node whose `loadChildren` call rejected. */ loadErrorMessage?: (error: unknown, node: TreeNode) => ReactNode; className?: string; 'data-testid'?: string; };