Debounced RAG-powered search hook that queries `/api/docs/search` and resolves result navigation across hub, embed, and bare-embedder contexts. ## Key Components ### `UseDocSearchConfig` Configuration interface with the following fields: | Field | Type | Description | |---|---|---| | `source` | `string` | Discriminator forwarded as `?source=` to the search endpoint | | `baseRoute` | `string` | Route prefix used to detect in-page swappable results | | `onNavigate` | `(path: string) => void` | Imperative fallback navigation (e.g. `router.push`) | | `tableIds` | `string[]` | Optional RAG table IDs to narrow the search scope | | `onInPageSwap` | `(path: string) => boolean` | Optional callback for in-page doc-tree swaps | | `searchEndpoint` | `string` | Endpoint override; defaults to `/api/docs/search` | ### `useDocSearch(config)` Returns: | Return | Description | |---|---| | `query` / `setQuery` | Controlled input state | | `results` | Mapped `SearchResult[]` from the API | | `isLoading` | True while debounce is pending or fetch is in-flight | | `handleResultSelect` | Click/keyboard handler resolving one of four action kinds: `navigate-same-tab`, `navigate-new-tab`, `ask-ai`, or `route` | | `keepDropdownOpen` | Stays `true` after new-tab navigations so the user can pick another result | ## Usage Example ```typescript import { useDocSearch } from './use-doc-search' import { useRouter } from 'next/navigation' function DocsSearchBar() { const router = useRouter() const { query, setQuery, results, isLoading, handleResultSelect } = useDocSearch({ source: 'openframe', baseRoute: '/onboarding-guides', tableIds: ['onboarding-guides'], onNavigate: (path) => router.push(path), onInPageSwap: (path) => { // Return true if handled in-page; false to fall through to router.push return docTreeNavigate(path) }, }) return ( ) } ``` ## Navigation Resolution The `handleResultSelect` handler respects modifier keys (`metaKey`, `ctrlKey`, `shiftKey`, middle-click) to force new-tab behavior, mirroring native anchor semantics on non-anchor rows. In `embed` mode, all same-tab results are routed through `resolveExternalNavigation` instead.