import { MouseEvent as ReactMouseEvent } from '../../../../node_modules/react'; import { FlowNodeKindDef } from '../nodeRegistry/types'; import { FlowNodePaletteCategory } from '../palette/types'; import { UseCenterOnNodeOptions } from './useCenterOnNode'; /** * What the app needs to know about which handle was clicked. `outcome` replaces CJO's * `BuilderConnection['outcome']` with a plain string — a source node may expose exactly one * default handle (outcome `'next'` by convention, not enforced) or several named branch handles * (`NodeCardBranchRow`'s own `id`, e.g. `'success'`/`'failure'`) — the design system has no * opinion on the vocabulary, only that the app supplies whatever string its own * `NodeCardBranchRow` ids already are. */ export interface HandlePickerContext { sourceId: string; outcome: string; } export interface UseHandlePickerOptions { /** * The full, unfiltered catalogue — typically the same `categories` array the app also passes * to its toolbar-opened `NodePalette` instance. `useHandlePicker` derives the handle-opened * instance's own filtered view from this on every open; it does not own a second catalogue. */ categories: FlowNodePaletteCategory[]; /** * The actual connectability rule — CJO's `canConnectNodes`, or any app-side business logic. * Called once per item, per handle click, to decide whether that item belongs in the * handle-opened popover for this specific `sourceId`/`outcome`. Omit to offer every item (no * filtering). A category that ends up with zero passing items is dropped entirely, exactly as * `NodePalette`'s own search filter drops an emptied category. */ canConnect?: (item: FlowNodeKindDef, context: HandlePickerContext) => boolean; /** * Fires when the user picks an enabled item. Owns node creation, connection-validity * checking, and wiring the edge into the app's own draft — this hook performs none of that. * Return the new node's id on success so the hook can center on it; return `null`/`false` to * reject the pick. A rejection is the app's to explain (a toast, an inline message) — this * hook has no feedback surface of its own. */ onPickConnectable: (item: FlowNodeKindDef, context: HandlePickerContext) => string | null | false; /** * Fires once, after a successful pick has already been centered on. This is where the app * sets its own selection/config-drawer-target state (CJO's `setSelectedNodeId` + * `setConfigNodeId`) — this hook does not hold that state itself. */ onConnected?: (nodeId: string, context: HandlePickerContext) => void; /** Forwarded to this hook's internal `useCenterOnNode()` call. */ centerOnNodeOptions?: UseCenterOnNodeOptions; } export interface UseHandlePickerPopoverProps { open: boolean; anchorEl: HTMLElement | null; onClose: () => void; /** Pre-filtered by `canConnect`, with empty categories already pruned. */ categories: FlowNodePaletteCategory[]; onPick: (item: FlowNodeKindDef) => void; /** * Closes the anchor and nothing else — matches CJO's own gap (dragging an item out of the * handle-opened popover never wires a connection) rather than silently fixing it. */ onDragStart: () => void; } export interface UseHandlePickerResult { /** Wire onto `NodeCard`'s `onSourceHandleClick` / `NodeCardBranchRow`'s `onHandleClick`. */ openFromHandle: (event: ReactMouseEvent, context: HandlePickerContext) => void; /** Spread directly onto ``, alongside the app's own `isItemEnabled`/`getDisabledHint`. */ popoverProps: UseHandlePickerPopoverProps; } /** * Turns a handle click into an open, anchored, filtered `NodePalette`, and turns a pick into a * created-and-connected node that gets centered — CJO's `handleConnectMenu` state + * `handleConnectAndAddNode` orchestration, minus the node-creation/connection-validity business * logic (`onPickConnectable`'s job) and minus owning selection state (`onConnected`'s job). */ export declare function useHandlePicker({ categories, canConnect, onPickConnectable, onConnected, centerOnNodeOptions, }: UseHandlePickerOptions): UseHandlePickerResult;