{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "search-context",
  "title": "Search context",
  "description": "SearchProvider and useSearchContext: the search dialog's open state, its Meta/Ctrl+K hotkey and shared dialog types.",
  "dependencies": [
    "@base-ui/react"
  ],
  "registryDependencies": [
    "@docscn/docs-utils"
  ],
  "files": [
    {
      "path": "registry/base/docs/contexts/search.tsx",
      "content": "// Adapted from Fumadocs UI (https://github.com/fuma-nama/fumadocs)\n// Copyright (c) 2023 Fuma, MIT License\n\"use client\";\n\nimport { Dialog } from \"@base-ui/react/dialog\";\nimport {\n  type ComponentType,\n  createContext,\n  type ReactNode,\n  Suspense,\n  use,\n  useMemo,\n  useState,\n  useSyncExternalStore,\n} from \"react\";\nimport { useHotKey } from \"../utils/hotkey\";\n\nexport interface HotKey {\n  display: ReactNode;\n\n  /**\n   * Key code or a function determining whether the key is pressed.\n   */\n  key: string | ((e: KeyboardEvent) => boolean);\n}\n\n/** built-in Base UI Dialog handle */\nconst dialogHandle = Dialog.createHandle();\n\nexport interface SharedProps {\n  open: boolean;\n  onOpenChange: (open: boolean) => void;\n  dialogHandle: Dialog.Handle<unknown>;\n}\n\nexport type SearchLink = [name: string, href: string];\n\nexport interface TagItem {\n  name: string;\n  value: string;\n}\n\nexport interface SearchProviderProps<\n  DialogProps extends SharedProps = SharedProps,\n> {\n  /**\n   * Custom links to be displayed if search is empty\n   */\n  links?: SearchLink[];\n\n  /**\n   * Hotkeys for triggering search dialog\n   *\n   * @defaultValue Meta/Ctrl + K\n   */\n  hotKey?: HotKey[];\n\n  /**\n   * The search dialog, e.g. `DefaultSearchDialog` or one for another search solution.\n   *\n   * It receives the `open` and `onOpenChange` prop, can be lazy loaded with `React.lazy()`\n   */\n  SearchDialog?: ComponentType<DialogProps>;\n\n  /**\n   * Additional props to the dialog\n   */\n  options?: Partial<DialogProps>;\n\n  children?: ReactNode;\n}\n\ninterface SearchContextType {\n  enabled: boolean;\n  open: boolean;\n  hotKey: HotKey[];\n  setOpenSearch: (value: boolean) => void;\n  dialogHandle: Dialog.Handle<unknown>;\n}\n\nconst SearchContext = createContext<SearchContextType>({\n  enabled: false,\n  open: false,\n  hotKey: [],\n  setOpenSearch: () => undefined,\n  dialogHandle,\n});\n\nexport function useSearchContext(): SearchContextType {\n  return use(SearchContext);\n}\n\nconst noop = () => () => {};\n\nfunction MetaOrControl() {\n  // `false` on the server and during hydration\n  const isClient = useSyncExternalStore(\n    noop,\n    () => true,\n    () => false,\n  );\n\n  return isClient && /Windows|Linux/i.test(navigator.userAgent) ? \"Ctrl\" : \"⌘\";\n}\n\nconst DEFAULT_HOT_KEYS: HotKey[] = [\n  {\n    key: (e) => e.metaKey || e.ctrlKey,\n    display: <MetaOrControl />,\n  },\n  {\n    key: \"k\",\n    display: \"K\",\n  },\n];\n\nexport function SearchProvider<DialogProps extends SharedProps = SharedProps>({\n  SearchDialog,\n  children,\n  options,\n  hotKey = DEFAULT_HOT_KEYS,\n  links,\n}: SearchProviderProps<DialogProps>) {\n  const [isOpen, setIsOpen] = useState(false);\n  useHotKey((e) => {\n    if (\n      hotKey.every((v) =>\n        typeof v.key === \"string\" ? e.key === v.key : v.key(e),\n      )\n    ) {\n      setIsOpen((open) => !open);\n      e.preventDefault();\n    }\n  });\n\n  return (\n    <SearchContext\n      value={useMemo(\n        () => ({\n          enabled: true,\n          open: isOpen,\n          hotKey,\n          dialogHandle,\n          setOpenSearch: setIsOpen,\n        }),\n        [isOpen, hotKey],\n      )}\n    >\n      {SearchDialog && (\n        <Suspense fallback={null}>\n          {/* @ts-expect-error -- assume all required props are filled */}\n          <SearchDialog\n            open={isOpen}\n            onOpenChange={setIsOpen}\n            links={links}\n            dialogHandle={dialogHandle}\n            {...options}\n          />\n        </Suspense>\n      )}\n\n      {children}\n    </SearchContext>\n  );\n}\n\n/**\n * Show children only when search is enabled via React Context\n */\nexport function SearchOnly({ children }: { children: ReactNode }) {\n  const search = useSearchContext();\n\n  if (search.enabled) return children;\n}\n",
      "type": "registry:component",
      "target": "@components/docs/contexts/search.tsx"
    }
  ],
  "type": "registry:component"
}