zudoku 0.53.2 → 0.53.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/dist/app/main.js +3 -9
  2. package/dist/app/main.js.map +1 -1
  3. package/dist/lib/components/Banner.js +1 -1
  4. package/dist/lib/components/Banner.js.map +1 -1
  5. package/dist/lib/components/CategoryHeading.js +1 -1
  6. package/dist/lib/components/CategoryHeading.js.map +1 -1
  7. package/dist/lib/components/Header.js +1 -1
  8. package/dist/lib/components/Header.js.map +1 -1
  9. package/dist/lib/components/Pagination.js +1 -1
  10. package/dist/lib/components/Pagination.js.map +1 -1
  11. package/dist/lib/components/StatusPage.js +4 -0
  12. package/dist/lib/components/StatusPage.js.map +1 -1
  13. package/dist/lib/components/navigation/NavigationWrapper.js +1 -1
  14. package/dist/lib/components/navigation/NavigationWrapper.js.map +1 -1
  15. package/dist/lib/plugins/markdown/MdxPage.js +1 -1
  16. package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
  17. package/dist/lib/plugins/search-inkeep/index.d.ts +5 -22
  18. package/dist/lib/plugins/search-inkeep/index.js +35 -29
  19. package/dist/lib/plugins/search-inkeep/index.js.map +1 -1
  20. package/dist/lib/plugins/search-inkeep/inkeep.d.ts +5 -21
  21. package/dist/lib/plugins/search-inkeep/inkeep.js +10 -19
  22. package/dist/lib/plugins/search-inkeep/inkeep.js.map +1 -1
  23. package/dist/lib/plugins/search-pagefind/PagefindSearch.js +1 -1
  24. package/dist/lib/plugins/search-pagefind/PagefindSearch.js.map +1 -1
  25. package/dist/lib/plugins/search-pagefind/ResultList.d.ts +1 -1
  26. package/dist/lib/plugins/search-pagefind/ResultList.js +12 -5
  27. package/dist/lib/plugins/search-pagefind/ResultList.js.map +1 -1
  28. package/dist/lib/ui/Alert.d.ts +1 -1
  29. package/dist/vite/build.js +7 -1
  30. package/dist/vite/build.js.map +1 -1
  31. package/dist/vite/plugin-mdx.js +2 -3
  32. package/dist/vite/plugin-mdx.js.map +1 -1
  33. package/lib/{Alert-CT_ViLrJ.js → Alert-FYKbqjIt.js} +2 -2
  34. package/lib/Alert-FYKbqjIt.js.map +1 -0
  35. package/lib/{MdxPage-8UuEK446.js → MdxPage-DyRuoE_F.js} +16 -16
  36. package/lib/{MdxPage-8UuEK446.js.map → MdxPage-DyRuoE_F.js.map} +1 -1
  37. package/lib/{OasProvider-BsWpguVO.js → OasProvider-CUA-DFGE.js} +2 -2
  38. package/lib/{OasProvider-BsWpguVO.js.map → OasProvider-CUA-DFGE.js.map} +1 -1
  39. package/lib/{OperationList-PnZbf3b2.js → OperationList-CRMvWoTv.js} +7 -7
  40. package/lib/{OperationList-PnZbf3b2.js.map → OperationList-CRMvWoTv.js.map} +1 -1
  41. package/lib/{Pagination-DY7gCrm4.js → Pagination-HZKe5ncg.js} +9 -8
  42. package/lib/Pagination-HZKe5ncg.js.map +1 -0
  43. package/lib/{SchemaList-D6k4DKWH.js → SchemaList-B792ORza.js} +6 -6
  44. package/lib/{SchemaList-D6k4DKWH.js.map → SchemaList-B792ORza.js.map} +1 -1
  45. package/lib/{SchemaView-BhgJ9WB8.js → SchemaView-Bo53TeMb.js} +4 -4
  46. package/lib/{SchemaView-BhgJ9WB8.js.map → SchemaView-Bo53TeMb.js.map} +1 -1
  47. package/lib/{SignUp-CpUD6DUM.js → SignUp-DfVvOCYB.js} +2 -2
  48. package/lib/{SignUp-CpUD6DUM.js.map → SignUp-DfVvOCYB.js.map} +1 -1
  49. package/lib/{Slot-DwZlQ-vX.js → Slot-BpO_AGKJ.js} +13 -5
  50. package/lib/Slot-BpO_AGKJ.js.map +1 -0
  51. package/lib/{SyntaxHighlight-CrjhGEwT.js → SyntaxHighlight-CZgjJ7-f.js} +753 -753
  52. package/lib/SyntaxHighlight-CZgjJ7-f.js.map +1 -0
  53. package/lib/{Toc-WCmwFkX-.js → Toc-DYMzDvOa.js} +2 -2
  54. package/lib/{Toc-WCmwFkX-.js.map → Toc-DYMzDvOa.js.map} +1 -1
  55. package/lib/{circular-BUMjK3JF.js → circular-CLdQ0oUd.js} +2 -2
  56. package/lib/{circular-BUMjK3JF.js.map → circular-CLdQ0oUd.js.map} +1 -1
  57. package/lib/{createServer-BPz8ZCrd.js → createServer-Co4BBP-i.js} +4 -4
  58. package/lib/{createServer-BPz8ZCrd.js.map → createServer-Co4BBP-i.js.map} +1 -1
  59. package/lib/{errors-DY-qOx9n.js → errors-DE1gK7ms.js} +3 -3
  60. package/lib/{errors-DY-qOx9n.js.map → errors-DE1gK7ms.js.map} +1 -1
  61. package/lib/{index-C_xVKbf9.js → index-DLshv89l.js} +581 -566
  62. package/lib/{index-C_xVKbf9.js.map → index-DLshv89l.js.map} +1 -1
  63. package/lib/{index-CcV90rin.js → index-DLzZDv8_.js} +2 -2
  64. package/lib/{index-CcV90rin.js.map → index-DLzZDv8_.js.map} +1 -1
  65. package/lib/{index-dVBKCNMa.js → index-DYP-V0jG.js} +10 -10
  66. package/lib/{index-dVBKCNMa.js.map → index-DYP-V0jG.js.map} +1 -1
  67. package/lib/ui/Alert.js.map +1 -1
  68. package/lib/ui/SyntaxHighlight.js +1 -1
  69. package/lib/zudoku.auth-azureb2c.js +1553 -1556
  70. package/lib/zudoku.auth-azureb2c.js.map +1 -1
  71. package/lib/zudoku.auth-clerk.js +1 -1
  72. package/lib/zudoku.auth-openid.js +1 -1
  73. package/lib/zudoku.components.js +2 -2
  74. package/lib/zudoku.plugin-api-catalog.js +3 -3
  75. package/lib/zudoku.plugin-api-keys.js +2 -2
  76. package/lib/zudoku.plugin-markdown.js +1 -1
  77. package/lib/zudoku.plugin-openapi.js +1 -1
  78. package/lib/zudoku.plugin-search-inkeep.js +54 -57
  79. package/lib/zudoku.plugin-search-inkeep.js.map +1 -1
  80. package/lib/zudoku.plugin-search-pagefind.js +106 -102
  81. package/lib/zudoku.plugin-search-pagefind.js.map +1 -1
  82. package/package.json +8 -7
  83. package/src/app/main.tsx +6 -14
  84. package/src/lib/components/Banner.tsx +0 -1
  85. package/src/lib/components/CategoryHeading.tsx +4 -1
  86. package/src/lib/components/Header.tsx +4 -1
  87. package/src/lib/components/Pagination.tsx +1 -0
  88. package/src/lib/components/StatusPage.tsx +5 -0
  89. package/src/lib/components/navigation/NavigationWrapper.tsx +4 -1
  90. package/src/lib/plugins/markdown/MdxPage.tsx +1 -1
  91. package/src/lib/plugins/search-inkeep/index.tsx +54 -58
  92. package/src/lib/plugins/search-inkeep/inkeep.ts +19 -21
  93. package/src/lib/plugins/search-pagefind/PagefindSearch.tsx +1 -0
  94. package/src/lib/plugins/search-pagefind/ResultList.tsx +13 -4
  95. package/src/lib/ui/Alert.tsx +1 -1
  96. package/lib/Alert-CT_ViLrJ.js.map +0 -1
  97. package/lib/Pagination-DY7gCrm4.js.map +0 -1
  98. package/lib/Slot-DwZlQ-vX.js.map +0 -1
  99. package/lib/SyntaxHighlight-CrjhGEwT.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"zudoku.plugin-search-pagefind.js","sources":["../src/lib/ui/Callout.tsx","../src/lib/plugins/search-pagefind/get-results.tsx","../src/lib/plugins/search-pagefind/ResultList.tsx","../src/lib/plugins/search-pagefind/PagefindSearch.tsx","../src/lib/plugins/search-pagefind/index.tsx"],"sourcesContent":["import {\n AlertTriangleIcon,\n InfoIcon,\n LightbulbIcon,\n type LucideIcon,\n ShieldAlertIcon,\n} from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../util/cn.js\";\n\nconst stylesMap = {\n note: {\n border: \"border-gray-300 dark:border-zinc-800\",\n bg: \"bg-gray-100 dark:bg-zinc-800/50\",\n iconColor: \"text-gray-600 dark:text-zinc-300\",\n titleColor: \"text-gray-600 dark:text-zinc-300\",\n textColor: \"text-gray-600 dark:text-zinc-300\",\n Icon: InfoIcon as LucideIcon,\n },\n tip: {\n border: \"border-green-500 dark:border-green-800\",\n bg: \"bg-green-200/25 dark:bg-green-950/70\",\n iconColor: \"text-green-600 dark:text-green-200\",\n titleColor: \"text-green-700 dark:text-green-200\",\n textColor: \"text-green-600 dark:text-green-50\",\n Icon: LightbulbIcon as LucideIcon,\n },\n info: {\n border: \"border-blue-400 dark:border-blue-900/60\",\n bg: \"bg-blue-50 dark:bg-blue-950/40\",\n iconColor: \"text-blue-400 dark:text-blue-200\",\n titleColor: \"text-blue-700 dark:text-blue-200\",\n textColor: \"text-blue-600 dark:text-blue-100\",\n Icon: InfoIcon as LucideIcon,\n },\n caution: {\n border: \"border-yellow-400 dark:border-yellow-400/25\",\n bg: \"bg-yellow-100/60 dark:bg-yellow-400/10\",\n iconColor: \"text-yellow-500 dark:text-yellow-300\",\n titleColor: \"text-yellow-600 dark:text-yellow-300\",\n textColor: \"text-yellow-700 dark:text-yellow-200\",\n Icon: AlertTriangleIcon as LucideIcon,\n },\n danger: {\n border: \"border-rose-400 dark:border-rose-800\",\n bg: \"bg-rose-50 dark:bg-rose-950/40\",\n iconColor: \"text-rose-400 dark:text-rose-300\",\n titleColor: \"text-rose-800 dark:text-rose-300\",\n textColor: \"text-rose-700 dark:text-rose-100\",\n Icon: ShieldAlertIcon as LucideIcon,\n },\n} as const;\n\ntype CalloutProps = {\n type: keyof typeof stylesMap;\n title?: string;\n children: ReactNode;\n className?: string;\n icon?: boolean;\n};\n\nexport const Callout = ({\n type,\n children,\n title,\n className,\n icon = true,\n}: CalloutProps) => {\n const { border, bg, iconColor, titleColor, textColor, Icon } =\n stylesMap[type];\n\n return (\n <div\n className={cn(\n \"not-prose rounded-md border p-4 text-md my-2\",\n icon &&\n \"grid grid-cols-[min-content_1fr] items-baseline grid-rows-[fit-content_1fr] gap-x-4 gap-y-2\",\n !icon && title && \"flex flex-col gap-2\",\n \"[&_a]:underline [&_a]:decoration-current [&_a]:decoration-from-font [&_a]:underline-offset-4 hover:[&_a]:decoration-1\",\n \"[&_.code-block-wrapper]:border\",\n \"[&_ul]:list-disc [&_ol]:list-decimal [&_ul]:ps-4 [&_ul>li]:ps-1 [&_ul>li]:my-1\",\n icon && title && \"items-center\",\n border,\n bg,\n className,\n )}\n >\n {icon && (\n <Icon\n className={cn(!title ? \"translate-y-1\" : \"align-middle\", iconColor)}\n size={20}\n aria-hidden=\"true\"\n />\n )}\n {title && <h3 className={cn(\"font-medium\", titleColor)}>{title}</h3>}\n <div\n className={cn(\n icon && \"col-start-2\",\n !title && icon && \"row-start-1\",\n textColor,\n \"overflow-x-auto\",\n )}\n >\n {children}\n </div>\n </div>\n );\n};\n","import type { AuthState } from \"../../authentication/state.js\";\nimport type { ZudokuContext } from \"../../core/ZudokuContext.js\";\nimport type { PagefindOptions } from \"./index.js\";\nimport type { PagefindSearchFragment, PagefindSearchResults } from \"./types.js\";\n\nexport const getResults = async ({\n search,\n options,\n auth,\n context,\n}: {\n search: PagefindSearchResults;\n options: PagefindOptions;\n auth: AuthState;\n context: ZudokuContext;\n}) => {\n const maxResults = options.maxResults ?? 10;\n const transformFn = options.transformResults ?? (() => true);\n\n const transformedResults: PagefindSearchFragment[] = [];\n\n const generator = searchResultGenerator({\n search,\n transformFn,\n auth,\n context,\n });\n\n for await (const result of generator) {\n transformedResults.push(result);\n if (transformedResults.length >= maxResults) break;\n }\n\n return transformedResults;\n};\n\nasync function* searchResultGenerator({\n search,\n transformFn,\n auth,\n context,\n}: {\n search: PagefindSearchResults;\n transformFn: NonNullable<PagefindOptions[\"transformResults\"]>;\n auth: AuthState<unknown>;\n context: ZudokuContext;\n}) {\n const batchSize = 5;\n let processedCount = 0;\n\n while (processedCount < search.results.length) {\n const batch = search.results.slice(\n processedCount,\n processedCount + batchSize,\n );\n processedCount += batch.length;\n\n const batchData = await Promise.all(batch.map((result) => result.data()));\n\n for (const result of batchData) {\n const transformed = transformFn({ result, auth, context });\n\n if (transformed === false) {\n // Skip this result\n continue;\n } else if (transformed === true || transformed == null) {\n // Keep the original result\n yield result;\n } else {\n // Return the transformed result\n yield transformed;\n }\n }\n }\n}\n","import { BracketsIcon, FileTextIcon } from \"lucide-react\";\nimport { useLayoutEffect, useRef } from \"react\";\nimport { Link, useNavigate } from \"react-router\";\nimport { CommandGroup, CommandItem, CommandList } from \"zudoku/ui/Command.js\";\nimport {\n type PagefindSearchFragment,\n type PagefindSubResult,\n} from \"./types.js\";\n\nconst sortSubResults = (a: PagefindSubResult, b: PagefindSubResult) => {\n const aScore = a.weighted_locations.reduce(\n (sum, loc) => sum + loc.balanced_score,\n 0,\n );\n const bScore = b.weighted_locations.reduce(\n (sum, loc) => sum + loc.balanced_score,\n 0,\n );\n return bScore - aScore;\n};\n\nconst hoverClassname = `cursor-pointer border border-transparent data-[selected=true]:border-border`;\n\nexport const ResultList = ({\n searchResults,\n searchTerm,\n onClose,\n maxSubResults = 4,\n}: {\n basePath?: string;\n searchResults: PagefindSearchFragment[];\n searchTerm: string;\n onClose: () => void;\n maxSubResults?: number;\n}) => {\n const navigate = useNavigate();\n const commandListRef = useRef<HTMLDivElement | null>(null);\n\n useLayoutEffect(() => {\n requestIdleCallback(() => {\n commandListRef.current?.scrollTo({ top: 0 });\n });\n }, [searchTerm]);\n\n return (\n <CommandList className=\"max-h-[450px]\" ref={commandListRef}>\n {searchTerm && searchResults.length > 0 && (\n <CommandGroup\n className=\"text-sm text-muted-foreground\"\n heading={`${searchResults.length} results for \"${searchTerm}\"`}\n />\n )}\n {searchTerm &&\n searchResults.map((result) => (\n <CommandGroup\n key={[result.meta.title ?? result.excerpt, result.url].join(\"-\")}\n >\n <CommandItem\n asChild\n value={`${result.meta.title}-${result.url}`}\n className={hoverClassname}\n onSelect={() => {\n void navigate(result.url);\n onClose();\n }}\n >\n <Link to={result.url}>\n {result.meta.section === \"openapi\" ? (\n <BracketsIcon />\n ) : (\n <FileTextIcon />\n )}\n {result.meta.title}\n </Link>\n </CommandItem>\n {result.sub_results\n .sort(sortSubResults)\n .slice(0, maxSubResults)\n .map((subResult) => (\n <CommandItem\n asChild\n key={`sub-${result.meta.title}-${subResult.url}`}\n value={`sub-${result.meta.title}-${subResult.url}`}\n className={hoverClassname}\n onSelect={() => {\n void navigate(subResult.url);\n onClose();\n }}\n >\n <Link to={subResult.url} onClick={onClose}>\n <div className=\"flex flex-col items-start gap-2 ms-2.5 ps-5 border-l border-muted-foreground/50\">\n <span className=\"font-bold\">{subResult.title}</span>\n <span\n className=\"text-[13px] [&_mark]:bg-primary [&_mark]:text-primary-foreground\"\n dangerouslySetInnerHTML={{ __html: subResult.excerpt }}\n />\n </div>\n </Link>\n </CommandItem>\n ))}\n </CommandGroup>\n ))}\n </CommandList>\n );\n};\n","import { VisuallyHidden } from \"@radix-ui/react-visually-hidden\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useRef, useState } from \"react\";\nimport { Button } from \"zudoku/ui/Button.js\";\nimport { Callout } from \"zudoku/ui/Callout.js\";\nimport {\n CommandDialog,\n CommandEmpty,\n CommandInput,\n} from \"zudoku/ui/Command.js\";\nimport { DialogTitle } from \"zudoku/ui/Dialog.js\";\nimport { useAuthState } from \"../../authentication/state.js\";\nimport { useZudoku } from \"../../components/context/ZudokuContext.js\";\nimport { SEARCH_PROTECTED_SECTION } from \"../../core/RouteGuard.js\";\nimport { joinUrl } from \"../../util/joinUrl.js\";\nimport { getResults } from \"./get-results.js\";\nimport type { PagefindOptions } from \"./index.js\";\nimport { ResultList } from \"./ResultList.js\";\nimport type { Pagefind } from \"./types.js\";\n\nconst DEFAULT_RANKING = {\n // Slightly lower than default because API docs tend to have repetitive terms (parameter names, HTTP methods, etc.)\n termFrequency: 0.8,\n // Lower than default because API documentation pages tend to be longer due to comprehensive endpoint documentation\n pageLength: 0.6,\n // Slightly higher than default because in technical documentation, exact matches should be prioritized\n termSimilarity: 1.2,\n // Slightly lower than default because API docs might have legitimate repetition of terms\n termSaturation: 1.2,\n};\n\nconst importPagefind = (basePath?: string): Promise<Pagefind> =>\n import.meta.env.DEV\n ? // @ts-expect-error TypeScript can't resolve the import\n import(/* @vite-ignore */ \"/pagefind/pagefind.js\")\n : import(/* @vite-ignore */ joinUrl(basePath, \"/pagefind/pagefind.js\"));\n\nconst usePagefind = (options: PagefindOptions) => {\n const {\n options: { basePath },\n } = useZudoku();\n const { data: pagefind, ...result } = useQuery<Pagefind>({\n queryKey: [\"pagefind\", options.ranking],\n retry: false,\n queryFn: async () => {\n const pagefind = await importPagefind(basePath);\n await pagefind.init();\n await pagefind.options({\n ranking: {\n termFrequency:\n options.ranking?.termFrequency ?? DEFAULT_RANKING.termFrequency,\n pageLength: options.ranking?.pageLength ?? DEFAULT_RANKING.pageLength,\n termSimilarity:\n options.ranking?.termSimilarity ?? DEFAULT_RANKING.termSimilarity,\n termSaturation:\n options.ranking?.termSaturation ?? DEFAULT_RANKING.termSaturation,\n },\n });\n\n return pagefind;\n },\n enabled: typeof window !== \"undefined\",\n });\n\n if (result.isError && result.error.message !== \"NOT_BUILT_YET\") {\n // eslint-disable-next-line no-console\n console.error(result.error);\n }\n\n return { ...result, pagefind };\n};\n\nexport const PagefindSearch = ({\n isOpen,\n onClose,\n options,\n}: {\n isOpen: boolean;\n onClose: () => void;\n options: PagefindOptions;\n}) => {\n const { pagefind, error, isError } = usePagefind(options);\n const [searchTerm, setSearchTerm] = useState(\"\");\n const auth = useAuthState();\n const context = useZudoku();\n const inputRef = useRef<HTMLInputElement>(null);\n\n const { data: searchResults } = useQuery({\n queryKey: [\"pagefind-search\", searchTerm, auth.isAuthenticated],\n queryFn: async () => {\n const filters = auth.isAuthenticated\n ? undefined\n : { not: { section: SEARCH_PROTECTED_SECTION } };\n\n const search = await pagefind?.search(searchTerm, { filters });\n if (!search) return [];\n return getResults({ search, options, auth, context });\n },\n placeholderData: keepPreviousData,\n enabled: !!pagefind && !!searchTerm,\n });\n\n return (\n <CommandDialog\n command={{ shouldFilter: false }}\n content={{ className: \"max-w-[750px]\" }}\n open={isOpen}\n onOpenChange={onClose}\n >\n <VisuallyHidden>\n <DialogTitle>Search</DialogTitle>\n </VisuallyHidden>\n <CommandInput\n ref={inputRef}\n placeholder=\"Search...\"\n value={searchTerm}\n onValueChange={setSearchTerm}\n disabled={isError}\n />\n <CommandEmpty>\n {searchTerm ? (\n <div className=\"flex flex-col items-center\">\n No results found.\n <Button\n variant=\"link\"\n onClick={() => {\n setSearchTerm(\"\");\n inputRef.current?.focus();\n }}\n >\n Clear search\n </Button>\n </div>\n ) : (\n \"Start typing to search\"\n )}\n </CommandEmpty>\n {isError ? (\n <div className=\"p-4 text-sm\">\n {error.message === \"NOT_BUILT_YET\" ? (\n <Callout type=\"info\">\n Search is currently not available in development mode by default.\n <br />\n To still use search in development, run <code>\n zudoku build\n </code>{\" \"}\n and copy the <code>dist/pagefind</code> directory to your{\" \"}\n <code>public</code> directory.\n </Callout>\n ) : (\n \"An error occurred while loading search.\"\n )}\n </div>\n ) : (\n <ResultList\n searchResults={searchResults ?? []}\n searchTerm={searchTerm}\n onClose={onClose}\n maxSubResults={options.maxSubResults}\n />\n )}\n </CommandDialog>\n );\n};\n","import type { ZudokuConfig } from \"../../../config/validators/validate.js\";\nimport { ClientOnly } from \"../../components/ClientOnly.js\";\nimport type { ZudokuPlugin } from \"../../core/plugins.js\";\nimport { PagefindSearch } from \"./PagefindSearch.js\";\n\nexport type PagefindOptions = Extract<\n ZudokuConfig[\"search\"],\n { type: \"pagefind\" }\n>;\n\nexport const pagefindSearchPlugin = (\n options: PagefindOptions,\n): ZudokuPlugin => {\n return {\n renderSearch: ({ isOpen, onClose }) => (\n <ClientOnly>\n <PagefindSearch isOpen={isOpen} onClose={onClose} options={options} />\n </ClientOnly>\n ),\n };\n};\n"],"names":["stylesMap","InfoIcon","LightbulbIcon","AlertTriangleIcon","ShieldAlertIcon","Callout","type","children","title","className","icon","border","bg","iconColor","titleColor","textColor","Icon","jsxs","cn","jsx","getResults","search","options","auth","context","maxResults","transformFn","transformedResults","generator","searchResultGenerator","result","processedCount","batch","batchData","transformed","sortSubResults","a","b","aScore","sum","loc","hoverClassname","ResultList","searchResults","searchTerm","onClose","maxSubResults","navigate","useNavigate","commandListRef","useRef","useLayoutEffect","CommandList","CommandGroup","CommandItem","Link","BracketsIcon","FileTextIcon","subResult","DEFAULT_RANKING","importPagefind","basePath","joinUrl","usePagefind","useZudoku","pagefind","useQuery","PagefindSearch","isOpen","error","isError","setSearchTerm","useState","useAuthState","inputRef","filters","SEARCH_PROTECTED_SECTION","keepPreviousData","CommandDialog","VisuallyHidden","DialogTitle","CommandInput","CommandEmpty","Button","pagefindSearchPlugin","ClientOnly"],"mappings":"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"}
1
+ {"version":3,"file":"zudoku.plugin-search-pagefind.js","sources":["../src/lib/ui/Callout.tsx","../src/lib/plugins/search-pagefind/get-results.tsx","../src/lib/plugins/search-pagefind/ResultList.tsx","../src/lib/plugins/search-pagefind/PagefindSearch.tsx","../src/lib/plugins/search-pagefind/index.tsx"],"sourcesContent":["import {\n AlertTriangleIcon,\n InfoIcon,\n LightbulbIcon,\n type LucideIcon,\n ShieldAlertIcon,\n} from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"../util/cn.js\";\n\nconst stylesMap = {\n note: {\n border: \"border-gray-300 dark:border-zinc-800\",\n bg: \"bg-gray-100 dark:bg-zinc-800/50\",\n iconColor: \"text-gray-600 dark:text-zinc-300\",\n titleColor: \"text-gray-600 dark:text-zinc-300\",\n textColor: \"text-gray-600 dark:text-zinc-300\",\n Icon: InfoIcon as LucideIcon,\n },\n tip: {\n border: \"border-green-500 dark:border-green-800\",\n bg: \"bg-green-200/25 dark:bg-green-950/70\",\n iconColor: \"text-green-600 dark:text-green-200\",\n titleColor: \"text-green-700 dark:text-green-200\",\n textColor: \"text-green-600 dark:text-green-50\",\n Icon: LightbulbIcon as LucideIcon,\n },\n info: {\n border: \"border-blue-400 dark:border-blue-900/60\",\n bg: \"bg-blue-50 dark:bg-blue-950/40\",\n iconColor: \"text-blue-400 dark:text-blue-200\",\n titleColor: \"text-blue-700 dark:text-blue-200\",\n textColor: \"text-blue-600 dark:text-blue-100\",\n Icon: InfoIcon as LucideIcon,\n },\n caution: {\n border: \"border-yellow-400 dark:border-yellow-400/25\",\n bg: \"bg-yellow-100/60 dark:bg-yellow-400/10\",\n iconColor: \"text-yellow-500 dark:text-yellow-300\",\n titleColor: \"text-yellow-600 dark:text-yellow-300\",\n textColor: \"text-yellow-700 dark:text-yellow-200\",\n Icon: AlertTriangleIcon as LucideIcon,\n },\n danger: {\n border: \"border-rose-400 dark:border-rose-800\",\n bg: \"bg-rose-50 dark:bg-rose-950/40\",\n iconColor: \"text-rose-400 dark:text-rose-300\",\n titleColor: \"text-rose-800 dark:text-rose-300\",\n textColor: \"text-rose-700 dark:text-rose-100\",\n Icon: ShieldAlertIcon as LucideIcon,\n },\n} as const;\n\ntype CalloutProps = {\n type: keyof typeof stylesMap;\n title?: string;\n children: ReactNode;\n className?: string;\n icon?: boolean;\n};\n\nexport const Callout = ({\n type,\n children,\n title,\n className,\n icon = true,\n}: CalloutProps) => {\n const { border, bg, iconColor, titleColor, textColor, Icon } =\n stylesMap[type];\n\n return (\n <div\n className={cn(\n \"not-prose rounded-md border p-4 text-md my-2\",\n icon &&\n \"grid grid-cols-[min-content_1fr] items-baseline grid-rows-[fit-content_1fr] gap-x-4 gap-y-2\",\n !icon && title && \"flex flex-col gap-2\",\n \"[&_a]:underline [&_a]:decoration-current [&_a]:decoration-from-font [&_a]:underline-offset-4 hover:[&_a]:decoration-1\",\n \"[&_.code-block-wrapper]:border\",\n \"[&_ul]:list-disc [&_ol]:list-decimal [&_ul]:ps-4 [&_ul>li]:ps-1 [&_ul>li]:my-1\",\n icon && title && \"items-center\",\n border,\n bg,\n className,\n )}\n >\n {icon && (\n <Icon\n className={cn(!title ? \"translate-y-1\" : \"align-middle\", iconColor)}\n size={20}\n aria-hidden=\"true\"\n />\n )}\n {title && <h3 className={cn(\"font-medium\", titleColor)}>{title}</h3>}\n <div\n className={cn(\n icon && \"col-start-2\",\n !title && icon && \"row-start-1\",\n textColor,\n \"overflow-x-auto\",\n )}\n >\n {children}\n </div>\n </div>\n );\n};\n","import type { AuthState } from \"../../authentication/state.js\";\nimport type { ZudokuContext } from \"../../core/ZudokuContext.js\";\nimport type { PagefindOptions } from \"./index.js\";\nimport type { PagefindSearchFragment, PagefindSearchResults } from \"./types.js\";\n\nexport const getResults = async ({\n search,\n options,\n auth,\n context,\n}: {\n search: PagefindSearchResults;\n options: PagefindOptions;\n auth: AuthState;\n context: ZudokuContext;\n}) => {\n const maxResults = options.maxResults ?? 10;\n const transformFn = options.transformResults ?? (() => true);\n\n const transformedResults: PagefindSearchFragment[] = [];\n\n const generator = searchResultGenerator({\n search,\n transformFn,\n auth,\n context,\n });\n\n for await (const result of generator) {\n transformedResults.push(result);\n if (transformedResults.length >= maxResults) break;\n }\n\n return transformedResults;\n};\n\nasync function* searchResultGenerator({\n search,\n transformFn,\n auth,\n context,\n}: {\n search: PagefindSearchResults;\n transformFn: NonNullable<PagefindOptions[\"transformResults\"]>;\n auth: AuthState<unknown>;\n context: ZudokuContext;\n}) {\n const batchSize = 5;\n let processedCount = 0;\n\n while (processedCount < search.results.length) {\n const batch = search.results.slice(\n processedCount,\n processedCount + batchSize,\n );\n processedCount += batch.length;\n\n const batchData = await Promise.all(batch.map((result) => result.data()));\n\n for (const result of batchData) {\n const transformed = transformFn({ result, auth, context });\n\n if (transformed === false) {\n // Skip this result\n continue;\n } else if (transformed === true || transformed == null) {\n // Keep the original result\n yield result;\n } else {\n // Return the transformed result\n yield transformed;\n }\n }\n }\n}\n","import { BracketsIcon, FileTextIcon } from \"lucide-react\";\nimport { useLayoutEffect, useRef } from \"react\";\nimport { Link, useNavigate } from \"react-router\";\nimport { CommandGroup, CommandItem, CommandList } from \"zudoku/ui/Command.js\";\nimport { joinUrl } from \"../../util/joinUrl.js\";\nimport {\n type PagefindSearchFragment,\n type PagefindSubResult,\n} from \"./types.js\";\n\nconst sortSubResults = (a: PagefindSubResult, b: PagefindSubResult) => {\n const aScore = a.weighted_locations.reduce(\n (sum, loc) => sum + loc.balanced_score,\n 0,\n );\n const bScore = b.weighted_locations.reduce(\n (sum, loc) => sum + loc.balanced_score,\n 0,\n );\n return bScore - aScore;\n};\n\nconst hoverClassname = `cursor-pointer border border-transparent data-[selected=true]:border-border`;\n\nexport const ResultList = ({\n basePath,\n searchResults,\n searchTerm,\n onClose,\n maxSubResults = 4,\n}: {\n basePath?: string;\n searchResults: PagefindSearchFragment[];\n searchTerm: string;\n onClose: () => void;\n maxSubResults?: number;\n}) => {\n const navigate = useNavigate();\n const commandListRef = useRef<HTMLDivElement | null>(null);\n\n useLayoutEffect(() => {\n requestIdleCallback(() => {\n commandListRef.current?.scrollTo({ top: 0 });\n });\n }, [searchTerm]);\n\n const stripBasePath = (url: string) => {\n if (basePath && url.startsWith(basePath)) {\n return joinUrl(url.slice(basePath.length));\n }\n return url;\n };\n\n return (\n <CommandList className=\"max-h-[450px]\" ref={commandListRef}>\n {searchTerm && searchResults.length > 0 && (\n <CommandGroup\n className=\"text-sm text-muted-foreground\"\n heading={`${searchResults.length} results for \"${searchTerm}\"`}\n />\n )}\n {searchTerm &&\n searchResults.map((result) => (\n <CommandGroup\n key={[result.meta.title ?? result.excerpt, result.url].join(\"-\")}\n >\n <CommandItem\n asChild\n value={`${result.meta.title}-${result.url}`}\n className={hoverClassname}\n onSelect={() => {\n void navigate(stripBasePath(result.url));\n onClose();\n }}\n >\n <Link to={stripBasePath(result.url)}>\n {result.meta.section === \"openapi\" ? (\n <BracketsIcon />\n ) : (\n <FileTextIcon />\n )}\n {result.meta.title}\n </Link>\n </CommandItem>\n {result.sub_results\n .sort(sortSubResults)\n .slice(0, maxSubResults)\n .map((subResult) => (\n <CommandItem\n asChild\n key={`sub-${result.meta.title}-${subResult.url}`}\n value={`sub-${result.meta.title}-${subResult.url}`}\n className={hoverClassname}\n onSelect={() => {\n void navigate(stripBasePath(subResult.url));\n onClose();\n }}\n >\n <Link to={stripBasePath(subResult.url)} onClick={onClose}>\n <div className=\"flex flex-col items-start gap-2 ms-2.5 ps-5 border-l border-muted-foreground/50\">\n <span className=\"font-bold\">{subResult.title}</span>\n <span\n className=\"text-[13px] [&_mark]:bg-primary [&_mark]:text-primary-foreground\"\n dangerouslySetInnerHTML={{ __html: subResult.excerpt }}\n />\n </div>\n </Link>\n </CommandItem>\n ))}\n </CommandGroup>\n ))}\n </CommandList>\n );\n};\n","import { VisuallyHidden } from \"@radix-ui/react-visually-hidden\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useRef, useState } from \"react\";\nimport { Button } from \"zudoku/ui/Button.js\";\nimport { Callout } from \"zudoku/ui/Callout.js\";\nimport {\n CommandDialog,\n CommandEmpty,\n CommandInput,\n} from \"zudoku/ui/Command.js\";\nimport { DialogTitle } from \"zudoku/ui/Dialog.js\";\nimport { useAuthState } from \"../../authentication/state.js\";\nimport { useZudoku } from \"../../components/context/ZudokuContext.js\";\nimport { SEARCH_PROTECTED_SECTION } from \"../../core/RouteGuard.js\";\nimport { joinUrl } from \"../../util/joinUrl.js\";\nimport { getResults } from \"./get-results.js\";\nimport type { PagefindOptions } from \"./index.js\";\nimport { ResultList } from \"./ResultList.js\";\nimport type { Pagefind } from \"./types.js\";\n\nconst DEFAULT_RANKING = {\n // Slightly lower than default because API docs tend to have repetitive terms (parameter names, HTTP methods, etc.)\n termFrequency: 0.8,\n // Lower than default because API documentation pages tend to be longer due to comprehensive endpoint documentation\n pageLength: 0.6,\n // Slightly higher than default because in technical documentation, exact matches should be prioritized\n termSimilarity: 1.2,\n // Slightly lower than default because API docs might have legitimate repetition of terms\n termSaturation: 1.2,\n};\n\nconst importPagefind = (basePath?: string): Promise<Pagefind> =>\n import.meta.env.DEV\n ? // @ts-expect-error TypeScript can't resolve the import\n import(/* @vite-ignore */ \"/pagefind/pagefind.js\")\n : import(/* @vite-ignore */ joinUrl(basePath, \"/pagefind/pagefind.js\"));\n\nconst usePagefind = (options: PagefindOptions) => {\n const {\n options: { basePath },\n } = useZudoku();\n const { data: pagefind, ...result } = useQuery<Pagefind>({\n queryKey: [\"pagefind\", options.ranking],\n retry: false,\n queryFn: async () => {\n const pagefind = await importPagefind(basePath);\n await pagefind.init();\n await pagefind.options({\n ranking: {\n termFrequency:\n options.ranking?.termFrequency ?? DEFAULT_RANKING.termFrequency,\n pageLength: options.ranking?.pageLength ?? DEFAULT_RANKING.pageLength,\n termSimilarity:\n options.ranking?.termSimilarity ?? DEFAULT_RANKING.termSimilarity,\n termSaturation:\n options.ranking?.termSaturation ?? DEFAULT_RANKING.termSaturation,\n },\n });\n\n return pagefind;\n },\n enabled: typeof window !== \"undefined\",\n });\n\n if (result.isError && result.error.message !== \"NOT_BUILT_YET\") {\n // eslint-disable-next-line no-console\n console.error(result.error);\n }\n\n return { ...result, pagefind };\n};\n\nexport const PagefindSearch = ({\n isOpen,\n onClose,\n options,\n}: {\n isOpen: boolean;\n onClose: () => void;\n options: PagefindOptions;\n}) => {\n const { pagefind, error, isError } = usePagefind(options);\n const [searchTerm, setSearchTerm] = useState(\"\");\n const auth = useAuthState();\n const context = useZudoku();\n const inputRef = useRef<HTMLInputElement>(null);\n\n const { data: searchResults } = useQuery({\n queryKey: [\"pagefind-search\", searchTerm, auth.isAuthenticated],\n queryFn: async () => {\n const filters = auth.isAuthenticated\n ? undefined\n : { not: { section: SEARCH_PROTECTED_SECTION } };\n\n const search = await pagefind?.search(searchTerm, { filters });\n if (!search) return [];\n return getResults({ search, options, auth, context });\n },\n placeholderData: keepPreviousData,\n enabled: !!pagefind && !!searchTerm,\n });\n\n return (\n <CommandDialog\n command={{ shouldFilter: false }}\n content={{ className: \"max-w-[750px]\" }}\n open={isOpen}\n onOpenChange={onClose}\n >\n <VisuallyHidden>\n <DialogTitle>Search</DialogTitle>\n </VisuallyHidden>\n <CommandInput\n ref={inputRef}\n placeholder=\"Search...\"\n value={searchTerm}\n onValueChange={setSearchTerm}\n disabled={isError}\n />\n <CommandEmpty>\n {searchTerm ? (\n <div className=\"flex flex-col items-center\">\n No results found.\n <Button\n variant=\"link\"\n onClick={() => {\n setSearchTerm(\"\");\n inputRef.current?.focus();\n }}\n >\n Clear search\n </Button>\n </div>\n ) : (\n \"Start typing to search\"\n )}\n </CommandEmpty>\n {isError ? (\n <div className=\"p-4 text-sm\">\n {error.message === \"NOT_BUILT_YET\" ? (\n <Callout type=\"info\">\n Search is currently not available in development mode by default.\n <br />\n To still use search in development, run <code>\n zudoku build\n </code>{\" \"}\n and copy the <code>dist/pagefind</code> directory to your{\" \"}\n <code>public</code> directory.\n </Callout>\n ) : (\n \"An error occurred while loading search.\"\n )}\n </div>\n ) : (\n <ResultList\n basePath={context.options.basePath}\n searchResults={searchResults ?? []}\n searchTerm={searchTerm}\n onClose={onClose}\n maxSubResults={options.maxSubResults}\n />\n )}\n </CommandDialog>\n );\n};\n","import type { ZudokuConfig } from \"../../../config/validators/validate.js\";\nimport { ClientOnly } from \"../../components/ClientOnly.js\";\nimport type { ZudokuPlugin } from \"../../core/plugins.js\";\nimport { PagefindSearch } from \"./PagefindSearch.js\";\n\nexport type PagefindOptions = Extract<\n ZudokuConfig[\"search\"],\n { type: \"pagefind\" }\n>;\n\nexport const pagefindSearchPlugin = (\n options: PagefindOptions,\n): ZudokuPlugin => {\n return {\n renderSearch: ({ isOpen, onClose }) => (\n <ClientOnly>\n <PagefindSearch isOpen={isOpen} onClose={onClose} options={options} />\n </ClientOnly>\n ),\n };\n};\n"],"names":["stylesMap","InfoIcon","LightbulbIcon","AlertTriangleIcon","ShieldAlertIcon","Callout","type","children","title","className","icon","border","bg","iconColor","titleColor","textColor","Icon","jsxs","cn","jsx","getResults","search","options","auth","context","maxResults","transformFn","transformedResults","generator","searchResultGenerator","result","processedCount","batch","batchData","transformed","sortSubResults","a","b","aScore","sum","loc","hoverClassname","ResultList","basePath","searchResults","searchTerm","onClose","maxSubResults","navigate","useNavigate","commandListRef","useRef","useLayoutEffect","stripBasePath","url","joinUrl","CommandList","CommandGroup","CommandItem","Link","BracketsIcon","FileTextIcon","subResult","DEFAULT_RANKING","importPagefind","usePagefind","useZudoku","pagefind","useQuery","PagefindSearch","isOpen","error","isError","setSearchTerm","useState","useAuthState","inputRef","filters","SEARCH_PROTECTED_SECTION","keepPreviousData","CommandDialog","VisuallyHidden","DialogTitle","CommandInput","CommandEmpty","Button","pagefindSearchPlugin","ClientOnly"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zudoku",
3
- "version": "0.53.2",
3
+ "version": "0.53.3",
4
4
  "type": "module",
5
5
  "homepage": "https://zudoku.dev",
6
6
  "repository": {
@@ -164,10 +164,10 @@
164
164
  "@radix-ui/react-visually-hidden": "1.2.3",
165
165
  "@scalar/openapi-parser": "0.10.17",
166
166
  "@sentry/node": "9.26.0",
167
- "@shikijs/langs": "3.5.0",
168
- "@shikijs/rehype": "3.5.0",
169
- "@shikijs/themes": "3.5.0",
170
- "@shikijs/transformers": "3.5.0",
167
+ "@shikijs/langs": "3.7.0",
168
+ "@shikijs/rehype": "3.7.0",
169
+ "@shikijs/themes": "3.7.0",
170
+ "@shikijs/transformers": "3.7.0",
171
171
  "@sindresorhus/slugify": "2.2.1",
172
172
  "@stefanprobst/rehype-extract-toc": "3.0.0",
173
173
  "@tailwindcss/typography": "0.5.16",
@@ -214,7 +214,7 @@
214
214
  "openapi-types": "12.1.3",
215
215
  "pagefind": "1.4.0-alpha.1",
216
216
  "picocolors": "1.1.1",
217
- "piscina": "5.0.0",
217
+ "piscina": "5.1.1",
218
218
  "posthog-node": "4.17.1",
219
219
  "react-error-boundary": "6.0.0",
220
220
  "react-hook-form": "7.57.0",
@@ -234,7 +234,7 @@
234
234
  "remark-rehype": "^11.1.2",
235
235
  "rollup": "4.41.1",
236
236
  "semver": "7.7.1",
237
- "shiki": "3.5.0",
237
+ "shiki": "3.7.0",
238
238
  "sitemap": "8.0.0",
239
239
  "spin-delay": "2.0.1",
240
240
  "strip-ansi": "7.1.0",
@@ -255,6 +255,7 @@
255
255
  "devDependencies": {
256
256
  "@graphql-codegen/cli": "5.0.7",
257
257
  "@graphql-codegen/client-preset": "4.8.2",
258
+ "@inkeep/cxkit-types": "0.5.90",
258
259
  "@testing-library/dom": "10.4.0",
259
260
  "@testing-library/jest-dom": "6.6.3",
260
261
  "@testing-library/react": "16.3.0",
package/src/app/main.tsx CHANGED
@@ -82,22 +82,13 @@ export const getRoutesByOptions = (
82
82
  .flatMap((plugin) => (isNavigationPlugin(plugin) ? plugin.getRoutes() : []))
83
83
  .concat(
84
84
  enableStatusPages
85
- ? [400, 403, 404, 405, 414, 416, 500, 501, 502, 503, 504].map(
86
- (statusCode) => ({
87
- path: `/${statusCode}`,
88
- element: <StatusPage statusCode={statusCode} />,
89
- }),
90
- )
85
+ ? [400, 404, 500].map((statusCode) => ({
86
+ path: `/${statusCode}`,
87
+ element: <StatusPage statusCode={statusCode} />,
88
+ }))
91
89
  : [],
92
90
  )
93
- .concat([
94
- {
95
- path: "*",
96
- loader: () => {
97
- throw new Response("Not Found", { status: 404 });
98
- },
99
- },
100
- ]);
91
+ .concat([{ path: "*", element: <StatusPage statusCode={404} /> }]);
101
92
 
102
93
  // @TODO Detect conflicts in routes and log warning
103
94
 
@@ -125,6 +116,7 @@ export const getRoutesByConfig = (config: ZudokuConfig): RouteObject[] => {
125
116
  <Layout />
126
117
  </Zudoku>
127
118
  ),
119
+ hydrateFallbackElement: <div>Loading...</div>,
128
120
  children: [
129
121
  {
130
122
  element: <RouteGuard />,
@@ -34,7 +34,6 @@ export const Banner = () => {
34
34
  "relative text-primary-foreground text-sm font-medium px-4 py-2 flex gap-2 items-center lg:h-(--banner-height)",
35
35
  mappedColor,
36
36
  )}
37
- data-pagefind-ignore="all"
38
37
  style={style}
39
38
  >
40
39
  <div className="w-full">{page.banner.message}</div>
@@ -9,7 +9,10 @@ export const CategoryHeading = ({
9
9
  className?: string;
10
10
  }) => {
11
11
  return (
12
- <div className={cx("text-sm font-semibold text-primary mb-2", className)}>
12
+ <div
13
+ className={cx("text-sm font-semibold text-primary mb-2", className)}
14
+ data-pagefind-ignore="all"
15
+ >
13
16
  {children}
14
17
  </div>
15
18
  );
@@ -81,7 +81,10 @@ export const Header = memo(function HeaderInner() {
81
81
  const borderBottom = "inset-shadow-[0_-1px_0_0_var(--border)]";
82
82
 
83
83
  return (
84
- <header className="sticky lg:top-0 z-10 bg-background/80 backdrop-blur w-full">
84
+ <header
85
+ className="sticky lg:top-0 z-10 bg-background/80 backdrop-blur w-full"
86
+ data-pagefind-ignore="all"
87
+ >
85
88
  <Banner />
86
89
  <div className={cn(borderBottom, "relative")}>
87
90
  <PageProgress />
@@ -22,6 +22,7 @@ export const Pagination = ({
22
22
  prev ? "justify-between" : "justify-end",
23
23
  className,
24
24
  )}
25
+ data-pagefind-ignore="all"
25
26
  >
26
27
  {prev && (
27
28
  <Button variant="ghost" asChild>
@@ -1,5 +1,6 @@
1
1
  import type { ReactNode } from "react";
2
2
  import { ErrorPage } from "./ErrorPage.js";
3
+ import { NotFoundPage } from "./NotFoundPage.js";
3
4
 
4
5
  type StatusPageProps = {
5
6
  statusCode: number;
@@ -79,6 +80,10 @@ const getDefaultContent = (
79
80
  };
80
81
 
81
82
  export const StatusPage = ({ statusCode, message }: StatusPageProps) => {
83
+ if (statusCode === 404) {
84
+ return <NotFoundPage />;
85
+ }
86
+
82
87
  const defaultContent = getDefaultContent(statusCode);
83
88
 
84
89
  return (
@@ -19,7 +19,10 @@ export const NavigationWrapper = ({
19
19
  }, []);
20
20
 
21
21
  return (
22
- <div className="grid sticky top-(--header-height) lg:h-[calc(100vh-var(--header-height))] grid-rows-[1fr_min-content] border-r">
22
+ <div
23
+ className="grid sticky top-(--header-height) lg:h-[calc(100vh-var(--header-height))] grid-rows-[1fr_min-content] border-r"
24
+ data-pagefind-ignore="all"
25
+ >
23
26
  <nav
24
27
  ref={navRef}
25
28
  className={cn(
@@ -178,7 +178,7 @@ export const MdxPage = ({
178
178
  </>
179
179
  )}
180
180
  </Typography>
181
- <div className="hidden xl:block">
181
+ <div className="hidden xl:block" data-pagefind-ignore="all">
182
182
  {showToc && <Toc entries={tocEntries} />}
183
183
  </div>
184
184
  </div>
@@ -1,102 +1,98 @@
1
- import { useEffect, useMemo, useRef, useState } from "react";
1
+ import type {
2
+ InkeepBaseSettings,
3
+ InkeepComponentInstance,
4
+ InkeepJS,
5
+ InkeepSettings,
6
+ } from "@inkeep/cxkit-types";
7
+ import { useEffect, useMemo, useState } from "react";
2
8
  import { ClientOnly } from "../../components/ClientOnly.js";
3
9
  import type { ZudokuPlugin } from "../../core/plugins.js";
4
- import { aiChatSettings, baseSettings } from "./inkeep.js";
5
-
6
- interface PluginInkeepBaseSettings {
7
- apiKey?: string;
8
- integrationId: string;
9
- organizationId: string;
10
- organizationDisplayName?: string;
11
- primaryBrandColor: string;
12
- }
13
-
14
- interface InkeepEmbedConfig {
15
- componentType: string;
16
- targetElement: HTMLElement;
17
- properties: unknown;
18
- }
19
-
20
- interface InkeepWidget {
21
- render: (config: InkeepEmbedConfig & { isOpen: boolean }) => void;
22
- }
10
+ import {
11
+ aiChatSettings,
12
+ baseSettings,
13
+ modalSettings,
14
+ searchSettings,
15
+ } from "./inkeep.js";
23
16
 
24
17
  declare global {
25
- let Inkeep: () => {
26
- embed: (config: InkeepEmbedConfig) => InkeepWidget;
27
- };
18
+ interface Window {
19
+ Inkeep: InkeepJS | undefined;
20
+ }
28
21
  }
29
22
 
30
23
  const InkeepSearch = ({
31
- prefilledQuery,
32
24
  isOpen,
33
25
  onClose,
34
26
  settings,
35
27
  }: {
36
28
  isOpen: boolean;
37
29
  onClose: () => void;
38
- prefilledQuery?: string | null;
39
- settings: PluginInkeepBaseSettings;
30
+ settings: InkeepBaseSettings;
40
31
  }) => {
41
- const ref = useRef<HTMLDivElement>(null);
42
- const widgetRef = useRef<InkeepWidget | null>(null);
43
- const [isInkeepAvailable, setIsInkeepAvailable] = useState(
44
- typeof Inkeep !== "undefined",
45
- );
46
-
47
- const config: InkeepEmbedConfig = useMemo(
32
+ const config = useMemo<InkeepSettings>(
48
33
  () => ({
49
- componentType: "CustomTrigger",
50
- targetElement: ref.current!,
51
- properties: {
52
- isOpen,
53
- onClose,
54
- onOpen: undefined,
55
- baseSettings: { ...baseSettings, ...settings },
56
- searchSettings: {
57
- prefilledQuery: prefilledQuery || undefined,
34
+ baseSettings: {
35
+ ...baseSettings,
36
+ ...settings,
37
+ colorMode: {
38
+ sync: {
39
+ target: "html",
40
+ attributes: ["class"],
41
+ isDarkMode: (attrs) => attrs["class"]?.includes("dark") ?? false,
42
+ },
43
+ },
44
+ },
45
+ modalSettings: {
46
+ ...modalSettings,
47
+ onOpenChange: (newOpen: boolean) => {
48
+ if (!newOpen) onClose();
58
49
  },
59
- aiChatSettings,
60
50
  },
51
+ searchSettings,
52
+ aiChatSettings,
61
53
  }),
62
- [isOpen, onClose, prefilledQuery, settings, ref],
54
+ [onClose, settings],
55
+ );
56
+ const [searchInstance, setSearchInstance] = useState<
57
+ InkeepComponentInstance | undefined
58
+ >(
59
+ typeof window !== "undefined" && window.Inkeep?.ModalSearchAndChat
60
+ ? window.Inkeep.ModalSearchAndChat(config)!
61
+ : undefined,
63
62
  );
64
63
 
65
64
  useEffect(() => {
66
- if (isInkeepAvailable) return;
65
+ if (searchInstance) return;
67
66
 
68
67
  const checkInkeep = setInterval(() => {
69
- if (typeof Inkeep !== "undefined") {
70
- setIsInkeepAvailable(true);
68
+ if (typeof window !== "undefined" && window.Inkeep?.ModalSearchAndChat) {
69
+ const inkeep = window.Inkeep.ModalSearchAndChat(config)!;
70
+ setSearchInstance(inkeep);
71
71
  clearInterval(checkInkeep);
72
72
  }
73
73
  }, 100);
74
74
 
75
75
  return () => clearInterval(checkInkeep);
76
- }, [isInkeepAvailable]);
76
+ }, [config, searchInstance]);
77
77
 
78
78
  useEffect(() => {
79
- if (!isInkeepAvailable || widgetRef.current) return;
80
-
81
- widgetRef.current = Inkeep().embed(config);
82
- }, [config, isInkeepAvailable]);
79
+ if (!searchInstance) return;
83
80
 
84
- useEffect(() => {
85
- widgetRef.current?.render({ ...config, isOpen });
86
- }, [config, isOpen]);
81
+ searchInstance.update({ modalSettings: { isOpen } });
82
+ }, [isOpen, searchInstance]);
87
83
 
88
- return <div ref={ref} />;
84
+ return null;
89
85
  };
90
86
 
91
87
  export const inkeepSearchPlugin = (
92
- settings: PluginInkeepBaseSettings,
88
+ settings: InkeepBaseSettings,
93
89
  ): ZudokuPlugin => {
94
90
  return {
95
91
  getHead: () => {
96
92
  return (
97
93
  <script
98
94
  type="module"
99
- src="https://unpkg.com/@inkeep/uikit-js@0.3.19/dist/embed.js"
95
+ src="https://cdn.jsdelivr.net/npm/@inkeep/cxkit-js@0.5.90/+esm"
100
96
  defer
101
97
  />
102
98
  );
@@ -1,26 +1,24 @@
1
- const baseSettings = {
2
- theme: {
3
- components: {
4
- AIChatPageWrapper: {
5
- defaultProps: {
6
- size: "shrink-vertically",
7
- variant: "no-shadow",
8
- },
9
- },
10
- SearchBarTrigger: {
11
- defaultProps: {
12
- size: "expand",
13
- variant: "subtle", // Choose from 'emphasized' or 'subtle'
14
- },
15
- },
16
- },
17
- },
18
- } as const;
1
+ import type {
2
+ InkeepAIChatSettings,
3
+ InkeepBaseSettings,
4
+ InkeepModalSettings,
5
+ InkeepSearchSettings,
6
+ } from "@inkeep/cxkit-types";
19
7
 
20
- const modalSettings = {};
8
+ const baseSettings: InkeepBaseSettings = {
9
+ primaryBrandColor: "#26D6FF",
10
+ };
21
11
 
22
- const searchSettings = {};
12
+ const modalSettings: InkeepModalSettings = {
13
+ shortcutKey: "k",
14
+ };
23
15
 
24
- const aiChatSettings = {};
16
+ const searchSettings: InkeepSearchSettings = {
17
+ placeholder: "Search...",
18
+ };
19
+
20
+ const aiChatSettings: InkeepAIChatSettings = {
21
+ aiAssistantName: "Assistant",
22
+ };
25
23
 
26
24
  export { aiChatSettings, baseSettings, modalSettings, searchSettings };
@@ -153,6 +153,7 @@ export const PagefindSearch = ({
153
153
  </div>
154
154
  ) : (
155
155
  <ResultList
156
+ basePath={context.options.basePath}
156
157
  searchResults={searchResults ?? []}
157
158
  searchTerm={searchTerm}
158
159
  onClose={onClose}
@@ -2,6 +2,7 @@ import { BracketsIcon, FileTextIcon } from "lucide-react";
2
2
  import { useLayoutEffect, useRef } from "react";
3
3
  import { Link, useNavigate } from "react-router";
4
4
  import { CommandGroup, CommandItem, CommandList } from "zudoku/ui/Command.js";
5
+ import { joinUrl } from "../../util/joinUrl.js";
5
6
  import {
6
7
  type PagefindSearchFragment,
7
8
  type PagefindSubResult,
@@ -22,6 +23,7 @@ const sortSubResults = (a: PagefindSubResult, b: PagefindSubResult) => {
22
23
  const hoverClassname = `cursor-pointer border border-transparent data-[selected=true]:border-border`;
23
24
 
24
25
  export const ResultList = ({
26
+ basePath,
25
27
  searchResults,
26
28
  searchTerm,
27
29
  onClose,
@@ -42,6 +44,13 @@ export const ResultList = ({
42
44
  });
43
45
  }, [searchTerm]);
44
46
 
47
+ const stripBasePath = (url: string) => {
48
+ if (basePath && url.startsWith(basePath)) {
49
+ return joinUrl(url.slice(basePath.length));
50
+ }
51
+ return url;
52
+ };
53
+
45
54
  return (
46
55
  <CommandList className="max-h-[450px]" ref={commandListRef}>
47
56
  {searchTerm && searchResults.length > 0 && (
@@ -60,11 +69,11 @@ export const ResultList = ({
60
69
  value={`${result.meta.title}-${result.url}`}
61
70
  className={hoverClassname}
62
71
  onSelect={() => {
63
- void navigate(result.url);
72
+ void navigate(stripBasePath(result.url));
64
73
  onClose();
65
74
  }}
66
75
  >
67
- <Link to={result.url}>
76
+ <Link to={stripBasePath(result.url)}>
68
77
  {result.meta.section === "openapi" ? (
69
78
  <BracketsIcon />
70
79
  ) : (
@@ -83,11 +92,11 @@ export const ResultList = ({
83
92
  value={`sub-${result.meta.title}-${subResult.url}`}
84
93
  className={hoverClassname}
85
94
  onSelect={() => {
86
- void navigate(subResult.url);
95
+ void navigate(stripBasePath(subResult.url));
87
96
  onClose();
88
97
  }}
89
98
  >
90
- <Link to={subResult.url} onClick={onClose}>
99
+ <Link to={stripBasePath(subResult.url)} onClick={onClose}>
91
100
  <div className="flex flex-col items-start gap-2 ms-2.5 ps-5 border-l border-muted-foreground/50">
92
101
  <span className="font-bold">{subResult.title}</span>
93
102
  <span
@@ -1,5 +1,5 @@
1
1
  import { cva, type VariantProps } from "class-variance-authority";
2
- import * as React from "react";
2
+ import type * as React from "react";
3
3
  import { cn } from "../util/cn.js";
4
4
 
5
5
  const alertVariants = cva(
@@ -1 +0,0 @@
1
- {"version":3,"file":"Alert-CT_ViLrJ.js","sources":["../../../node_modules/.pnpm/@tanstack+query-core@5.74.3/node_modules/@tanstack/query-core/build/modern/mutationObserver.js","../../../node_modules/.pnpm/@tanstack+react-query@5.74.3_react@19.1.0/node_modules/@tanstack/react-query/build/modern/useMutation.js","../src/lib/ui/Alert.tsx"],"sourcesContent":["// src/mutationObserver.ts\nimport { getDefaultState } from \"./mutation.js\";\nimport { notifyManager } from \"./notifyManager.js\";\nimport { Subscribable } from \"./subscribable.js\";\nimport { hashKey, shallowEqualObjects } from \"./utils.js\";\nvar MutationObserver = class extends Subscribable {\n #client;\n #currentResult = void 0;\n #currentMutation;\n #mutateOptions;\n constructor(client, options) {\n super();\n this.#client = client;\n this.setOptions(options);\n this.bindMethods();\n this.#updateResult();\n }\n bindMethods() {\n this.mutate = this.mutate.bind(this);\n this.reset = this.reset.bind(this);\n }\n setOptions(options) {\n const prevOptions = this.options;\n this.options = this.#client.defaultMutationOptions(options);\n if (!shallowEqualObjects(this.options, prevOptions)) {\n this.#client.getMutationCache().notify({\n type: \"observerOptionsUpdated\",\n mutation: this.#currentMutation,\n observer: this\n });\n }\n if (prevOptions?.mutationKey && this.options.mutationKey && hashKey(prevOptions.mutationKey) !== hashKey(this.options.mutationKey)) {\n this.reset();\n } else if (this.#currentMutation?.state.status === \"pending\") {\n this.#currentMutation.setOptions(this.options);\n }\n }\n onUnsubscribe() {\n if (!this.hasListeners()) {\n this.#currentMutation?.removeObserver(this);\n }\n }\n onMutationUpdate(action) {\n this.#updateResult();\n this.#notify(action);\n }\n getCurrentResult() {\n return this.#currentResult;\n }\n reset() {\n this.#currentMutation?.removeObserver(this);\n this.#currentMutation = void 0;\n this.#updateResult();\n this.#notify();\n }\n mutate(variables, options) {\n this.#mutateOptions = options;\n this.#currentMutation?.removeObserver(this);\n this.#currentMutation = this.#client.getMutationCache().build(this.#client, this.options);\n this.#currentMutation.addObserver(this);\n return this.#currentMutation.execute(variables);\n }\n #updateResult() {\n const state = this.#currentMutation?.state ?? getDefaultState();\n this.#currentResult = {\n ...state,\n isPending: state.status === \"pending\",\n isSuccess: state.status === \"success\",\n isError: state.status === \"error\",\n isIdle: state.status === \"idle\",\n mutate: this.mutate,\n reset: this.reset\n };\n }\n #notify(action) {\n notifyManager.batch(() => {\n if (this.#mutateOptions && this.hasListeners()) {\n const variables = this.#currentResult.variables;\n const context = this.#currentResult.context;\n if (action?.type === \"success\") {\n this.#mutateOptions.onSuccess?.(action.data, variables, context);\n this.#mutateOptions.onSettled?.(action.data, null, variables, context);\n } else if (action?.type === \"error\") {\n this.#mutateOptions.onError?.(action.error, variables, context);\n this.#mutateOptions.onSettled?.(\n void 0,\n action.error,\n variables,\n context\n );\n }\n }\n this.listeners.forEach((listener) => {\n listener(this.#currentResult);\n });\n });\n }\n};\nexport {\n MutationObserver\n};\n//# sourceMappingURL=mutationObserver.js.map","\"use client\";\n\n// src/useMutation.ts\nimport * as React from \"react\";\nimport { MutationObserver, notifyManager } from \"@tanstack/query-core\";\nimport { useQueryClient } from \"./QueryClientProvider.js\";\nimport { noop, shouldThrowError } from \"./utils.js\";\nfunction useMutation(options, queryClient) {\n const client = useQueryClient(queryClient);\n const [observer] = React.useState(\n () => new MutationObserver(\n client,\n options\n )\n );\n React.useEffect(() => {\n observer.setOptions(options);\n }, [observer, options]);\n const result = React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) => observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer]\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult()\n );\n const mutate = React.useCallback(\n (variables, mutateOptions) => {\n observer.mutate(variables, mutateOptions).catch(noop);\n },\n [observer]\n );\n if (result.error && shouldThrowError(observer.options.throwOnError, [result.error])) {\n throw result.error;\n }\n return { ...result, mutate, mutateAsync: result.mutate };\n}\nexport {\n useMutation\n};\n//# sourceMappingURL=useMutation.js.map","import { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"../util/cn.js\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current\",\n {\n variants: {\n variant: {\n default: \"bg-card text-card-foreground\",\n destructive:\n \"text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction Alert({\n className,\n variant,\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof alertVariants>) {\n return (\n <div\n data-slot=\"alert\"\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n );\n}\n\nfunction AlertTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-title\"\n className={cn(\n \"col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction AlertDescription({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-description\"\n className={cn(\n \"text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport { Alert, AlertDescription, AlertTitle };\n"],"names":["MutationObserver","Subscribable","#client","#currentResult","#currentMutation","#mutateOptions","client","options","#updateResult","prevOptions","shallowEqualObjects","hashKey","action","#notify","variables","state","getDefaultState","notifyManager","context","listener","useMutation","queryClient","useQueryClient","observer","React","result","onStoreChange","mutate","mutateOptions","noop","shouldThrowError","alertVariants","cva","Alert","className","variant","props","jsx","cn","AlertTitle","AlertDescription"],"mappings":"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","x_google_ignoreList":[0,1]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Pagination-DY7gCrm4.js","sources":["../src/lib/components/Pagination.tsx"],"sourcesContent":["import { ArrowLeftIcon, ArrowRightIcon } from \"lucide-react\";\nimport { Link } from \"react-router\";\nimport { cn } from \"../util/cn.js\";\nimport { Button } from \"./index.js\";\n\nexport const Pagination = ({\n prev,\n next,\n className,\n}: {\n prev: { to: string; label: string } | undefined;\n next: { to: string; label: string } | undefined;\n className?: string;\n}) => {\n const linkClass =\n \"group transition-all p-5 space-x-1 rtl:space-x-reverse transition-all hover:text-foreground\";\n\n return (\n <div\n className={cn(\n \"flex -mx-4 text-muted-foreground font-semibold\",\n prev ? \"justify-between\" : \"justify-end\",\n className,\n )}\n >\n {prev && (\n <Button variant=\"ghost\" asChild>\n <Link to={prev.to} relative=\"path\" className={linkClass}>\n <ArrowLeftIcon size={14} strokeWidth={2.5} />\n <span className=\"text-lg truncate\">{prev.label}</span>\n </Link>\n </Button>\n )}\n {next && (\n <Button variant=\"ghost\" asChild>\n <Link to={next.to} relative=\"path\" className={linkClass}>\n <span className=\"text-lg truncate\">{next.label}</span>\n <ArrowRightIcon size={14} strokeWidth={2.5} />\n </Link>\n </Button>\n )}\n </div>\n );\n};\n"],"names":["Pagination","prev","next","className","linkClass","jsxs","cn","jsx","Button","Link","ArrowLeftIcon","ArrowRightIcon"],"mappings":";;;;;AAKO,MAAMA,IAAa,CAAC;AAAA,EACzB,MAAAC;AAAA,EACA,MAAAC;AAAA,EACA,WAAAC;AACF,MAIM;AACJ,QAAMC,IACJ;AAGA,SAAAC,gBAAAA,EAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC;AAAA,QACT;AAAA,QACAL,IAAO,oBAAoB;AAAA,QAC3BE;AAAA,MACF;AAAA,MAEC,UAAA;AAAA,QAAAF,KACEM,gBAAAA,EAAAA,IAAAC,GAAA,EAAO,SAAQ,SAAQ,SAAO,IAC7B,UAAAH,gBAAAA,EAAAA,KAACI,GAAK,EAAA,IAAIR,EAAK,IAAI,UAAS,QAAO,WAAWG,GAC5C,UAAA;AAAA,UAAAG,gBAAAA,EAAA,IAACG,GAAc,EAAA,MAAM,IAAI,aAAa,KAAK;AAAA,UAC1CH,gBAAAA,EAAA,IAAA,QAAA,EAAK,WAAU,oBAAoB,YAAK,MAAM,CAAA;AAAA,QAAA,EAAA,CACjD,EACF,CAAA;AAAA,QAEDL,KACCK,gBAAAA,EAAAA,IAACC,GAAO,EAAA,SAAQ,SAAQ,SAAO,IAC7B,UAACH,gBAAAA,EAAAA,KAAAI,GAAA,EAAK,IAAIP,EAAK,IAAI,UAAS,QAAO,WAAWE,GAC5C,UAAA;AAAA,UAAAG,gBAAAA,EAAA,IAAC,QAAK,EAAA,WAAU,oBAAoB,UAAAL,EAAK,OAAM;AAAA,UAC9CK,gBAAAA,EAAA,IAAAI,GAAA,EAAe,MAAM,IAAI,aAAa,IAAK,CAAA;AAAA,QAAA,EAAA,CAC9C,EACF,CAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAEJ;AAEJ;"}