{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "root-provider",
  "title": "Root provider",
  "description": "RootProvider for the root layout: theme (next-themes) with a `d` hotkey, the default search dialog, tooltips, text direction and Next.js framework adapters.",
  "dependencies": [
    "@base-ui/react",
    "fumadocs-core@^16.17.8",
    "next-themes"
  ],
  "registryDependencies": [
    "tooltip",
    "@docscn/search-context",
    "@docscn/docs-utils",
    "@docscn/search-dialog-default",
    "@docscn/i18n-context"
  ],
  "files": [
    {
      "path": "registry/base/docs/provider/base.tsx",
      "content": "// Adapted from Fumadocs UI (https://github.com/fuma-nama/fumadocs)\n// Copyright (c) 2023 Fuma, MIT License\n\"use client\";\n\nimport { DirectionProvider } from \"@base-ui/react/direction-provider\";\nimport { ThemeProvider, type ThemeProviderProps, useTheme } from \"next-themes\";\nimport { lazy, type ReactNode } from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { TooltipProvider } from \"@/components/ui/tooltip\";\nimport type { DefaultSearchDialogProps } from \"../components/dialog/search-default\";\nimport { I18nProvider, type I18nProviderProps } from \"../contexts/i18n\";\nimport { SearchProvider, type SearchProviderProps } from \"../contexts/search\";\nimport { useHotKey } from \"../utils/hotkey\";\n\nconst DefaultSearchDialog = lazy(\n  () => import(\"../components/dialog/search-default\"),\n);\n\ninterface SearchOptions extends Omit<\n  SearchProviderProps<DefaultSearchDialogProps>,\n  \"children\"\n> {\n  /**\n   * Enable search functionality\n   *\n   * @defaultValue `true`\n   */\n  enabled?: boolean;\n}\n\ninterface ThemeOptions extends ThemeProviderProps {\n  /**\n   * Enable `next-themes`\n   *\n   * @defaultValue true\n   */\n  enabled?: boolean;\n\n  /**\n   * Hotkey for toggling between light/dark mode, pass `false` to disable it.\n   *\n   * It is ignored while typing in an editable element (e.g. `<input />`), or when a dialog is opened.\n   *\n   * @defaultValue `d`\n   */\n  hotKey?: string | ((e: KeyboardEvent) => boolean) | false;\n}\n\nexport interface RootProviderProps {\n  /**\n   * `dir` option for Base UI\n   */\n  dir?: \"rtl\" | \"ltr\";\n\n  /**\n   * @remarks `SearchProviderProps`\n   */\n  search?: Partial<SearchOptions>;\n\n  /**\n   * Customize options for `next-themes`\n   */\n  theme?: ThemeOptions;\n\n  i18n?: Omit<I18nProviderProps, \"children\">;\n\n  children?: ReactNode;\n}\n\n/**\n * Toggle between light/dark mode with a hotkey, must be placed under `next-themes` provider.\n */\nfunction ThemeHotKey({\n  hotKey,\n}: {\n  hotKey: Exclude<ThemeOptions[\"hotKey\"], false | undefined>;\n}) {\n  const { setTheme, resolvedTheme } = useTheme();\n\n  useHotKey(\n    (e) => {\n      // a custom function is responsible for its own modifiers\n      const matched =\n        typeof hotKey === \"string\"\n          ? !e.metaKey &&\n            !e.ctrlKey &&\n            !e.altKey &&\n            e.key.toLowerCase() === hotKey.toLowerCase()\n          : hotKey(e);\n      if (!matched) return;\n\n      e.preventDefault();\n      const next = resolvedTheme === \"dark\" ? \"light\" : \"dark\";\n      if (document?.startViewTransition) {\n        document.startViewTransition(() => flushSync(() => setTheme(next)));\n      } else {\n        setTheme(next);\n      }\n    },\n    { ignoreTyping: true },\n  );\n\n  return null;\n}\n\nexport function RootProvider({\n  children,\n  dir = \"ltr\",\n  theme = {},\n  search,\n  i18n,\n}: RootProviderProps) {\n  let body = children;\n\n  if (search?.enabled !== false) {\n    body = (\n      <SearchProvider SearchDialog={DefaultSearchDialog} {...search}>\n        {body}\n      </SearchProvider>\n    );\n  }\n\n  if (theme?.enabled !== false) {\n    const { hotKey = \"d\" } = theme;\n\n    body = (\n      <ThemeProvider\n        attribute=\"class\"\n        defaultTheme=\"system\"\n        enableSystem\n        disableTransitionOnChange\n        {...theme}\n      >\n        {hotKey !== false && <ThemeHotKey hotKey={hotKey} />}\n        {body}\n      </ThemeProvider>\n    );\n  }\n\n  if (i18n) {\n    body = <I18nProvider {...i18n}>{body}</I18nProvider>;\n  }\n\n  return (\n    <DirectionProvider direction={dir}>\n      <TooltipProvider>{body}</TooltipProvider>\n    </DirectionProvider>\n  );\n}\n\nexport {\n  /**\n   * re-exported from `next-themes`\n   */\n  useTheme,\n  type UseThemeProps,\n} from \"next-themes\";\n",
      "type": "registry:component",
      "target": "@components/docs/provider/base.tsx"
    },
    {
      "path": "registry/base/docs/provider/next.tsx",
      "content": "// Adapted from Fumadocs UI (https://github.com/fuma-nama/fumadocs)\n// Copyright (c) 2023 Fuma, MIT License\n\"use client\";\n\nimport type { Framework } from \"fumadocs-core/framework\";\nimport { NextProvider } from \"fumadocs-core/framework/next\";\nimport type { ComponentProps } from \"react\";\nimport { RootProvider as BaseProvider } from \"./base\";\n\nexport interface RootProviderProps extends ComponentProps<typeof BaseProvider> {\n  /**\n   * Custom framework components to override Next.js defaults\n   */\n  components?: {\n    Link?: Framework[\"Link\"];\n    Image?: Framework[\"Image\"];\n  };\n}\n\nexport function RootProvider({ components, ...props }: RootProviderProps) {\n  return (\n    <NextProvider Link={components?.Link} Image={components?.Image}>\n      <BaseProvider {...props}>{props.children}</BaseProvider>\n    </NextProvider>\n  );\n}\n",
      "type": "registry:component",
      "target": "@components/docs/provider/next.tsx"
    }
  ],
  "type": "registry:component"
}