export interface KeyboardOptions { isEditing: () => boolean; isReadonly: () => boolean; getSelectedId: () => string | null; /** * Multi-select view of the current selection. Returned in * preorder (root-first) so consumers can iterate top-down. * Empty when nothing is selected. */ getSelectedIds: () => string[]; /** * Called when Tab/Enter fires and no node is selected — defaults the * action to the root node so the user can build a tree from scratch * without first clicking something. */ defaultTargetId?: () => string; onAddChild: (id: string) => void; onAddSibling: (id: string) => void; onAddSiblingBefore: (id: string) => void; onRemove: (id: string) => void; onStartEdit: (id: string) => void; onClearSelection: () => void; onDuplicate: (id: string) => void; /** Copy the currently selected subtrees into the host's clipboard * buffer. No-op when the selection is empty. */ onCopy: (ids: string[]) => void; /** Cut the currently selected subtrees (copy + remove from tree). * No-op when the selection is empty. */ onCut: (ids: string[]) => void; /** Paste the host's clipboard buffer under `targetId` (defaults to * the primary selected node, or the root when nothing is selected). * `targetId === null` means "default to root". */ onPaste: (targetId: string | null) => void; /** Returns true when the host's internal clipboard buffer has at * least one copied node ready to paste. When false, Ctrl+V is * NOT intercepted so the browser's native `paste` event fires — * this lets the onPaste(ClipboardEvent) handler pick up image * data from the system clipboard. */ hasClipboard: () => boolean; onUndo: () => void; onRedo: () => void; /** * Move selection to a neighbour. Returns the new selected id (or null * if no neighbour exists in that direction). * dx = -1 → select first child * dx = +1 → select parent * dy = -1 → select previous sibling * dy = +1 → select next sibling */ onNavigate: (dx: number, dy: number) => void; /** Move the currently selected node one slot up (dy=-1) or down * (dy=+1) among its siblings. The host is responsible for * mapping the visual direction to the correct data-level * before/after, taking into account the left/right side * reversal of root children. No-op when the node is the root * or already at the boundary. */ onMoveSibling: (dy: number) => void; onSelectRoot: () => void; } export declare function useKeyboard(opts: KeyboardOptions): void;