search-dialog.tsx 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. 'use client';
  2. import { create } from '@orama/orama';
  3. import { useDocsSearch } from 'fumadocs-core/search/client';
  4. import { oramaStaticClient } from 'fumadocs-core/search/client/orama-static';
  5. import {
  6. SearchDialog,
  7. SearchDialogClose,
  8. SearchDialogContent,
  9. SearchDialogHeader,
  10. SearchDialogIcon,
  11. SearchDialogInput,
  12. SearchDialogList,
  13. SearchDialogOverlay,
  14. } from 'fumadocs-ui/components/dialog/search';
  15. import { useI18n } from 'fumadocs-ui/contexts/i18n';
  16. import { useMemo } from 'react';
  17. interface SharedProps {
  18. open: boolean;
  19. onOpenChange: (open: boolean) => void;
  20. }
  21. // The static search index is keyed by locale code (en/fa/ru/zh). Fumadocs'
  22. // default static dialog feeds those codes to Orama as a tokenizer language, but
  23. // Orama only accepts full names ("english") and throws on "en" — which silently
  24. // breaks search entirely. All docs content is English (other locales fall back
  25. // to it), so re-create the dialog — the documented escape hatch for custom Orama
  26. // setups — with an initOrama that always builds an English index.
  27. export default function SearchDialogClient(props: SharedProps) {
  28. const { locale } = useI18n();
  29. const client = useMemo(
  30. () =>
  31. oramaStaticClient({
  32. from: '/api/search',
  33. locale,
  34. initOrama: () => create({ schema: { _: 'string' }, language: 'english' }),
  35. }),
  36. [locale],
  37. );
  38. const { search, setSearch, query } = useDocsSearch({ client });
  39. return (
  40. <SearchDialog search={search} onSearchChange={setSearch} isLoading={query.isLoading} {...props}>
  41. <SearchDialogOverlay />
  42. <SearchDialogContent>
  43. <SearchDialogHeader>
  44. <SearchDialogIcon />
  45. <SearchDialogInput />
  46. <SearchDialogClose />
  47. </SearchDialogHeader>
  48. <SearchDialogList items={query.data !== 'empty' ? query.data : null} />
  49. </SearchDialogContent>
  50. </SearchDialog>
  51. );
  52. }