fumadocs-ui 16.4.1 → 16.4.2

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 (266) hide show
  1. package/css/preset.css +2 -4
  2. package/dist/_virtual/rolldown_runtime.js +36 -0
  3. package/dist/components/accordion.d.ts +24 -7
  4. package/dist/components/accordion.d.ts.map +1 -1
  5. package/dist/components/accordion.js +65 -38
  6. package/dist/components/accordion.js.map +1 -0
  7. package/dist/components/banner.d.ts +33 -22
  8. package/dist/components/banner.d.ts.map +1 -1
  9. package/dist/components/banner.js +63 -47
  10. package/dist/components/banner.js.map +1 -0
  11. package/dist/components/callout.d.ts +41 -17
  12. package/dist/components/callout.d.ts.map +1 -1
  13. package/dist/components/callout.js +57 -28
  14. package/dist/components/callout.js.map +1 -0
  15. package/dist/components/card.d.ts +19 -9
  16. package/dist/components/card.d.ts.map +1 -1
  17. package/dist/components/card.js +39 -8
  18. package/dist/components/card.js.map +1 -0
  19. package/dist/components/codeblock.d.ts +61 -40
  20. package/dist/components/codeblock.d.ts.map +1 -1
  21. package/dist/components/codeblock.js +116 -58
  22. package/dist/components/codeblock.js.map +1 -0
  23. package/dist/components/dialog/search-algolia.d.ts +37 -23
  24. package/dist/components/dialog/search-algolia.d.ts.map +1 -1
  25. package/dist/components/dialog/search-algolia.js +64 -31
  26. package/dist/components/dialog/search-algolia.js.map +1 -0
  27. package/dist/components/dialog/search-default.d.ts +42 -27
  28. package/dist/components/dialog/search-default.d.ts.map +1 -1
  29. package/dist/components/dialog/search-default.js +64 -38
  30. package/dist/components/dialog/search-default.js.map +1 -0
  31. package/dist/components/dialog/search-orama.d.ts +41 -25
  32. package/dist/components/dialog/search-orama.d.ts.map +1 -1
  33. package/dist/components/dialog/search-orama.js +68 -35
  34. package/dist/components/dialog/search-orama.js.map +1 -0
  35. package/dist/components/dialog/search.d.ts +103 -64
  36. package/dist/components/dialog/search.d.ts.map +1 -1
  37. package/dist/components/dialog/search.js +264 -185
  38. package/dist/components/dialog/search.js.map +1 -0
  39. package/dist/components/dynamic-codeblock.d.ts +30 -19
  40. package/dist/components/dynamic-codeblock.d.ts.map +1 -1
  41. package/dist/components/dynamic-codeblock.js +60 -27
  42. package/dist/components/dynamic-codeblock.js.map +1 -0
  43. package/dist/components/files.d.ts +32 -16
  44. package/dist/components/files.d.ts.map +1 -1
  45. package/dist/components/files.js +40 -14
  46. package/dist/components/files.js.map +1 -0
  47. package/dist/components/github-info.d.ts +18 -7
  48. package/dist/components/github-info.d.ts.map +1 -1
  49. package/dist/components/github-info.js +63 -48
  50. package/dist/components/github-info.js.map +1 -0
  51. package/dist/components/heading.d.ts +11 -4
  52. package/dist/components/heading.d.ts.map +1 -1
  53. package/dist/components/heading.js +28 -8
  54. package/dist/components/heading.js.map +1 -0
  55. package/dist/components/image-zoom-CtfZieBH.css +80 -0
  56. package/dist/components/image-zoom-CtfZieBH.css.map +1 -0
  57. package/dist/components/image-zoom.d.ts +23 -14
  58. package/dist/components/image-zoom.d.ts.map +1 -1
  59. package/dist/components/image-zoom.js +32 -19
  60. package/dist/components/image-zoom.js.map +1 -0
  61. package/dist/components/image-zoom2.js +1 -0
  62. package/dist/components/inline-toc.d.ts +14 -6
  63. package/dist/components/inline-toc.d.ts.map +1 -1
  64. package/dist/components/inline-toc.js +28 -8
  65. package/dist/components/inline-toc.js.map +1 -0
  66. package/dist/components/sidebar/base.d.ts +102 -65
  67. package/dist/components/sidebar/base.d.ts.map +1 -1
  68. package/dist/components/sidebar/base.js +256 -180
  69. package/dist/components/sidebar/base.js.map +1 -0
  70. package/dist/components/sidebar/link-item.d.ts +23 -10
  71. package/dist/components/sidebar/link-item.d.ts.map +1 -1
  72. package/dist/components/sidebar/link-item.js +32 -12
  73. package/dist/components/sidebar/link-item.js.map +1 -0
  74. package/dist/components/sidebar/page-tree.d.ts +28 -17
  75. package/dist/components/sidebar/page-tree.d.ts.map +1 -1
  76. package/dist/components/sidebar/page-tree.js +57 -33
  77. package/dist/components/sidebar/page-tree.js.map +1 -0
  78. package/dist/components/sidebar/tabs/dropdown.d.ts +18 -9
  79. package/dist/components/sidebar/tabs/dropdown.d.ts.map +1 -1
  80. package/dist/components/sidebar/tabs/dropdown.js +75 -31
  81. package/dist/components/sidebar/tabs/dropdown.js.map +1 -0
  82. package/dist/components/sidebar/tabs/index.d.ts +24 -18
  83. package/dist/components/sidebar/tabs/index.d.ts.map +1 -1
  84. package/dist/components/sidebar/tabs/index.js +45 -45
  85. package/dist/components/sidebar/tabs/index.js.map +1 -0
  86. package/dist/components/steps.d.ts +16 -7
  87. package/dist/components/steps.d.ts.map +1 -1
  88. package/dist/components/steps.js +17 -5
  89. package/dist/components/steps.js.map +1 -0
  90. package/dist/components/tabs.d.ts +49 -28
  91. package/dist/components/tabs.d.ts.map +1 -1
  92. package/dist/components/tabs.js +88 -51
  93. package/dist/components/tabs.js.map +1 -0
  94. package/dist/components/toc/clerk.d.ts +1 -2
  95. package/dist/components/toc/clerk.js +12 -1
  96. package/dist/components/toc/clerk.js.map +1 -0
  97. package/dist/components/toc/default.d.ts +1 -2
  98. package/dist/components/toc/default.js +12 -1
  99. package/dist/components/toc/default.js.map +1 -0
  100. package/dist/components/toc/index.d.ts +1 -2
  101. package/dist/components/toc/index.js +12 -1
  102. package/dist/components/toc/index.js.map +1 -0
  103. package/dist/components/type-table.d.ts +36 -29
  104. package/dist/components/type-table.d.ts.map +1 -1
  105. package/dist/components/type-table.js +106 -25
  106. package/dist/components/type-table.js.map +1 -0
  107. package/dist/components/ui/accordion.d.ts +31 -7
  108. package/dist/components/ui/accordion.d.ts.map +1 -1
  109. package/dist/components/ui/accordion.js +40 -14
  110. package/dist/components/ui/accordion.js.map +1 -0
  111. package/dist/components/ui/button.d.ts +12 -7
  112. package/dist/components/ui/button.d.ts.map +1 -1
  113. package/dist/components/ui/button.js +21 -18
  114. package/dist/components/ui/button.js.map +1 -0
  115. package/dist/components/ui/collapsible.d.ts +12 -8
  116. package/dist/components/ui/collapsible.d.ts.map +1 -1
  117. package/dist/components/ui/collapsible.js +21 -11
  118. package/dist/components/ui/collapsible.js.map +1 -0
  119. package/dist/components/ui/navigation-menu.d.ts +8 -5
  120. package/dist/components/ui/navigation-menu.d.ts.map +1 -1
  121. package/dist/components/ui/navigation-menu.js +36 -9
  122. package/dist/components/ui/navigation-menu.js.map +1 -0
  123. package/dist/components/ui/popover.d.ts +6 -3
  124. package/dist/components/ui/popover.d.ts.map +1 -1
  125. package/dist/components/ui/popover.js +19 -6
  126. package/dist/components/ui/popover.js.map +1 -0
  127. package/dist/components/ui/scroll-area.d.ts +7 -4
  128. package/dist/components/ui/scroll-area.d.ts.map +1 -1
  129. package/dist/components/ui/scroll-area.js +33 -7
  130. package/dist/components/ui/scroll-area.js.map +1 -0
  131. package/dist/components/ui/tabs.d.ts +37 -19
  132. package/dist/components/ui/tabs.d.ts.map +1 -1
  133. package/dist/components/ui/tabs.js +75 -73
  134. package/dist/components/ui/tabs.js.map +1 -0
  135. package/dist/contexts/i18n.d.ts +1 -2
  136. package/dist/contexts/i18n.js +12 -1
  137. package/dist/contexts/i18n.js.map +1 -0
  138. package/dist/contexts/search.d.ts +7 -1
  139. package/dist/contexts/search.d.ts.map +1 -1
  140. package/dist/contexts/search.js +12 -1
  141. package/dist/contexts/search.js.map +1 -0
  142. package/dist/contexts/tree.d.ts +1 -2
  143. package/dist/contexts/tree.js +12 -1
  144. package/dist/contexts/tree.js.map +1 -0
  145. package/dist/i18n.d.ts +1 -2
  146. package/dist/i18n.js +3 -1
  147. package/dist/layouts/docs/client.d.ts +30 -13
  148. package/dist/layouts/docs/client.d.ts.map +1 -1
  149. package/dist/layouts/docs/client.js +61 -34
  150. package/dist/layouts/docs/client.js.map +1 -0
  151. package/dist/layouts/docs/index.d.ts +57 -33
  152. package/dist/layouts/docs/index.d.ts.map +1 -1
  153. package/dist/layouts/docs/index.js +178 -68
  154. package/dist/layouts/docs/index.js.map +1 -0
  155. package/dist/layouts/docs/page/client.d.ts +43 -21
  156. package/dist/layouts/docs/page/client.d.ts.map +1 -1
  157. package/dist/layouts/docs/page/client.js +213 -105
  158. package/dist/layouts/docs/page/client.js.map +1 -0
  159. package/dist/layouts/docs/page/index.d.ts +82 -46
  160. package/dist/layouts/docs/page/index.d.ts.map +1 -1
  161. package/dist/layouts/docs/page/index.js +98 -45
  162. package/dist/layouts/docs/page/index.js.map +1 -0
  163. package/dist/layouts/docs/sidebar.d.ts +57 -16
  164. package/dist/layouts/docs/sidebar.d.ts.map +1 -1
  165. package/dist/layouts/docs/sidebar.js +135 -82
  166. package/dist/layouts/docs/sidebar.js.map +1 -0
  167. package/dist/layouts/home/client.d.ts +18 -5
  168. package/dist/layouts/home/client.d.ts.map +1 -1
  169. package/dist/layouts/home/client.js +252 -103
  170. package/dist/layouts/home/client.js.map +1 -0
  171. package/dist/layouts/home/index.d.ts +15 -10
  172. package/dist/layouts/home/index.d.ts.map +1 -1
  173. package/dist/layouts/home/index.js +24 -7
  174. package/dist/layouts/home/index.js.map +1 -0
  175. package/dist/layouts/home/navbar.d.ts +13 -6
  176. package/dist/layouts/home/navbar.d.ts.map +1 -1
  177. package/dist/layouts/home/navbar.js +34 -12
  178. package/dist/layouts/home/navbar.js.map +1 -0
  179. package/dist/layouts/notebook/client.d.ts +44 -20
  180. package/dist/layouts/notebook/client.d.ts.map +1 -1
  181. package/dist/layouts/notebook/client.js +148 -93
  182. package/dist/layouts/notebook/client.js.map +1 -0
  183. package/dist/layouts/notebook/index.d.ts +34 -30
  184. package/dist/layouts/notebook/index.d.ts.map +1 -1
  185. package/dist/layouts/notebook/index.js +216 -90
  186. package/dist/layouts/notebook/index.js.map +1 -0
  187. package/dist/layouts/notebook/page/client.d.ts +43 -21
  188. package/dist/layouts/notebook/page/client.d.ts.map +1 -1
  189. package/dist/layouts/notebook/page/client.js +213 -105
  190. package/dist/layouts/notebook/page/client.js.map +1 -0
  191. package/dist/layouts/notebook/page/index.d.ts +82 -46
  192. package/dist/layouts/notebook/page/index.d.ts.map +1 -1
  193. package/dist/layouts/notebook/page/index.js +98 -45
  194. package/dist/layouts/notebook/page/index.js.map +1 -0
  195. package/dist/layouts/notebook/sidebar.d.ts +62 -20
  196. package/dist/layouts/notebook/sidebar.d.ts.map +1 -1
  197. package/dist/layouts/notebook/sidebar.js +130 -88
  198. package/dist/layouts/notebook/sidebar.js.map +1 -0
  199. package/dist/layouts/shared/index.d.ts +62 -50
  200. package/dist/layouts/shared/index.d.ts.map +1 -1
  201. package/dist/layouts/shared/index.js +36 -20
  202. package/dist/layouts/shared/index.js.map +1 -0
  203. package/dist/layouts/shared/language-toggle.d.ts +9 -4
  204. package/dist/layouts/shared/language-toggle.d.ts.map +1 -1
  205. package/dist/layouts/shared/language-toggle.js +44 -21
  206. package/dist/layouts/shared/language-toggle.js.map +1 -0
  207. package/dist/layouts/shared/search-toggle.d.ts +20 -8
  208. package/dist/layouts/shared/search-toggle.d.ts.map +1 -1
  209. package/dist/layouts/shared/search-toggle.js +53 -24
  210. package/dist/layouts/shared/search-toggle.js.map +1 -0
  211. package/dist/layouts/shared/theme-toggle.d.ts +13 -4
  212. package/dist/layouts/shared/theme-toggle.d.ts.map +1 -1
  213. package/dist/layouts/shared/theme-toggle.js +58 -34
  214. package/dist/layouts/shared/theme-toggle.js.map +1 -0
  215. package/dist/mdx.d.ts +34 -29
  216. package/dist/mdx.d.ts.map +1 -1
  217. package/dist/mdx.js +68 -34
  218. package/dist/mdx.js.map +1 -0
  219. package/dist/mdx.server.d.ts +9 -5
  220. package/dist/mdx.server.d.ts.map +1 -1
  221. package/dist/mdx.server.js +21 -13
  222. package/dist/mdx.server.js.map +1 -0
  223. package/dist/og.d.ts +1 -2
  224. package/dist/og.js +3 -1
  225. package/dist/page.d.ts +30 -20
  226. package/dist/page.d.ts.map +1 -1
  227. package/dist/page.js +34 -18
  228. package/dist/page.js.map +1 -0
  229. package/dist/provider/base.d.ts +43 -33
  230. package/dist/provider/base.d.ts.map +1 -1
  231. package/dist/provider/base.js +37 -17
  232. package/dist/provider/base.js.map +1 -0
  233. package/dist/provider/next.d.ts +20 -12
  234. package/dist/provider/next.d.ts.map +1 -1
  235. package/dist/provider/next.js +19 -5
  236. package/dist/provider/next.js.map +1 -0
  237. package/dist/provider/react-router.d.ts +20 -12
  238. package/dist/provider/react-router.d.ts.map +1 -1
  239. package/dist/provider/react-router.js +19 -5
  240. package/dist/provider/react-router.js.map +1 -0
  241. package/dist/provider/tanstack.d.ts +20 -12
  242. package/dist/provider/tanstack.d.ts.map +1 -1
  243. package/dist/provider/tanstack.js +19 -5
  244. package/dist/provider/tanstack.js.map +1 -0
  245. package/dist/provider/waku.d.ts +20 -12
  246. package/dist/provider/waku.d.ts.map +1 -1
  247. package/dist/provider/waku.js +19 -5
  248. package/dist/provider/waku.js.map +1 -0
  249. package/dist/style.css +11 -13
  250. package/dist/utils/use-copy-button.d.ts +1 -2
  251. package/dist/utils/use-copy-button.js +3 -1
  252. package/dist/utils/use-footer-items.d.ts +1 -2
  253. package/dist/utils/use-footer-items.js +3 -1
  254. package/dist/utils/use-is-scroll-top.d.ts +1 -2
  255. package/dist/utils/use-is-scroll-top.js +3 -1
  256. package/package.json +51 -52
  257. package/dist/components/toc/clerk.d.ts.map +0 -1
  258. package/dist/components/toc/default.d.ts.map +0 -1
  259. package/dist/components/toc/index.d.ts.map +0 -1
  260. package/dist/contexts/i18n.d.ts.map +0 -1
  261. package/dist/contexts/tree.d.ts.map +0 -1
  262. package/dist/i18n.d.ts.map +0 -1
  263. package/dist/og.d.ts.map +0 -1
  264. package/dist/utils/use-copy-button.d.ts.map +0 -1
  265. package/dist/utils/use-footer-items.d.ts.map +0 -1
  266. package/dist/utils/use-is-scroll-top.d.ts.map +0 -1
@@ -1,192 +1,271 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { ChevronRight, Hash, Search as SearchIcon } from '@fumadocs/ui/icons';
4
- import { createContext, Fragment, use, useCallback, useEffect, useEffectEvent, useMemo, useRef, useState, } from 'react';
5
- import { I18nLabel, useI18n } from '../../contexts/i18n.js';
6
- import { cn } from '@fumadocs/ui/cn';
7
- import { Dialog, DialogContent, DialogOverlay, DialogTitle, } from '@radix-ui/react-dialog';
8
- import { cva } from 'class-variance-authority';
9
- import { useRouter } from 'fumadocs-core/framework';
10
- import { useOnChange } from 'fumadocs-core/utils/use-on-change';
11
- import scrollIntoView from 'scroll-into-view-if-needed';
12
- import { buttonVariants } from '../../components/ui/button.js';
2
+
3
+ import { buttonVariants } from "../ui/button.js";
4
+ import { i18n_exports } from "../../contexts/i18n.js";
5
+ import { useRouter } from "fumadocs-core/framework";
6
+ import { cn } from "@fumadocs/ui/cn";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ import { ChevronRight, Hash, Search } from "lucide-react";
9
+ import { Fragment as Fragment$1, createContext, use, useCallback, useEffect, useEffectEvent, useMemo, useRef, useState } from "react";
10
+ import { cva } from "class-variance-authority";
11
+ import { useOnChange } from "fumadocs-core/utils/use-on-change";
12
+ import scrollIntoView from "scroll-into-view-if-needed";
13
+ import { Dialog, DialogContent, DialogOverlay, DialogTitle } from "@radix-ui/react-dialog";
14
+
15
+ //#region src/components/dialog/search.tsx
13
16
  const Context = createContext(null);
14
17
  const ListContext = createContext(null);
15
18
  const TagsListContext = createContext(null);
16
- export function SearchDialog({ open, onOpenChange, search, onSearchChange, isLoading = false, onSelect: onSelectProp, children, }) {
17
- const router = useRouter();
18
- const onSelect = useEffectEvent((item) => {
19
- if (item.type === 'action') {
20
- item.onSelect();
21
- }
22
- else if (item.external) {
23
- window.open(item.url, '_blank')?.focus();
24
- }
25
- else {
26
- router.push(item.url);
27
- }
28
- onOpenChange(false);
29
- onSelectProp?.(item);
30
- });
31
- return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsx(Context.Provider, { value: useMemo(() => ({
32
- open,
33
- onOpenChange,
34
- search,
35
- onSearchChange,
36
- // eslint-disable-next-line react-hooks/rules-of-hooks -- used in child components
37
- onSelect,
38
- isLoading,
39
- }), [isLoading, onOpenChange, onSearchChange, open, search]), children: children }) }));
40
- }
41
- export function SearchDialogHeader(props) {
42
- return (_jsx("div", { ...props, className: cn('flex flex-row items-center gap-2 p-3', props.className) }));
43
- }
44
- export function SearchDialogInput(props) {
45
- const { text } = useI18n();
46
- const { search, onSearchChange } = useSearch();
47
- return (_jsx("input", { ...props, value: search, onChange: (e) => onSearchChange(e.target.value), placeholder: text.search, className: "w-0 flex-1 bg-transparent text-lg placeholder:text-fd-muted-foreground focus-visible:outline-none" }));
48
- }
49
- export function SearchDialogClose({ children = 'ESC', className, ...props }) {
50
- const { onOpenChange } = useSearch();
51
- return (_jsx("button", { type: "button", onClick: () => onOpenChange(false), className: cn(buttonVariants({
52
- color: 'outline',
53
- size: 'sm',
54
- className: 'font-mono text-fd-muted-foreground',
55
- }), className), ...props, children: children }));
56
- }
57
- export function SearchDialogFooter(props) {
58
- return (_jsx("div", { ...props, className: cn('bg-fd-secondary/50 p-3 empty:hidden', props.className) }));
59
- }
60
- export function SearchDialogOverlay(props) {
61
- return (_jsx(DialogOverlay, { ...props, className: cn('fixed inset-0 z-50 backdrop-blur-xs bg-fd-overlay data-[state=open]:animate-fd-fade-in data-[state=closed]:animate-fd-fade-out', props.className) }));
62
- }
63
- export function SearchDialogContent({ children, ...props }) {
64
- const { text } = useI18n();
65
- return (_jsxs(DialogContent, { "aria-describedby": undefined, ...props, className: cn('fixed left-1/2 top-4 md:top-[calc(50%-250px)] z-50 w-[calc(100%-1rem)] max-w-screen-sm -translate-x-1/2 rounded-xl border bg-fd-popover text-fd-popover-foreground shadow-2xl shadow-black/50 overflow-hidden data-[state=closed]:animate-fd-dialog-out data-[state=open]:animate-fd-dialog-in', '*:border-b *:has-[+:last-child[data-empty=true]]:border-b-0 *:data-[empty=true]:border-b-0 *:last:border-b-0', props.className), children: [_jsx(DialogTitle, { className: "hidden", children: text.search }), children] }));
66
- }
67
- export function SearchDialogList({ items = null, Empty = () => (_jsx("div", { className: "py-12 text-center text-sm text-fd-muted-foreground", children: _jsx(I18nLabel, { label: "searchNoResult" }) })), Item = (props) => _jsx(SearchDialogListItem, { ...props }), ...props }) {
68
- const ref = useRef(null);
69
- const { onSelect } = useSearch();
70
- const [active, setActive] = useState(() => items && items.length > 0 ? items[0].id : null);
71
- const onKey = useEffectEvent((e) => {
72
- if (!items || e.isComposing)
73
- return;
74
- if (e.key === 'ArrowDown' || e.key == 'ArrowUp') {
75
- let idx = items.findIndex((item) => item.id === active);
76
- if (idx === -1)
77
- idx = 0;
78
- else if (e.key === 'ArrowDown')
79
- idx++;
80
- else
81
- idx--;
82
- setActive(items.at(idx % items.length)?.id ?? null);
83
- e.preventDefault();
84
- }
85
- if (e.key === 'Enter') {
86
- const selected = items.find((item) => item.id === active);
87
- if (selected)
88
- onSelect(selected);
89
- e.preventDefault();
90
- }
91
- });
92
- useEffect(() => {
93
- const element = ref.current;
94
- if (!element)
95
- return;
96
- const observer = new ResizeObserver(() => {
97
- const viewport = element.firstElementChild;
98
- element.style.setProperty('--fd-animated-height', `${viewport.clientHeight}px`);
99
- });
100
- const viewport = element.firstElementChild;
101
- if (viewport)
102
- observer.observe(viewport);
103
- window.addEventListener('keydown', onKey);
104
- return () => {
105
- observer.disconnect();
106
- window.removeEventListener('keydown', onKey);
107
- };
108
- }, []);
109
- useOnChange(items, () => {
110
- if (items && items.length > 0) {
111
- setActive(items[0].id);
112
- }
113
- });
114
- return (_jsx("div", { ...props, ref: ref, "data-empty": items === null, className: cn('overflow-hidden h-(--fd-animated-height) transition-[height]', props.className), children: _jsx("div", { className: cn('w-full flex flex-col overflow-y-auto max-h-[460px] p-1', !items && 'hidden'), children: _jsxs(ListContext.Provider, { value: useMemo(() => ({
115
- active,
116
- setActive,
117
- }), [active]), children: [items?.length === 0 && Empty(), items?.map((item) => (_jsx(Fragment, { children: Item({ item, onClick: () => onSelect(item) }) }, item.id)))] }) }) }));
118
- }
119
- export function SearchDialogListItem({ item, className, children, renderHighlights: render = renderHighlights, ...props }) {
120
- const { active: activeId, setActive } = useSearchList();
121
- const active = item.id === activeId;
122
- if (item.type === 'action') {
123
- children ?? (children = item.node);
124
- }
125
- else {
126
- children ?? (children = _jsxs(_Fragment, { children: [_jsx("div", { className: "inline-flex items-center text-fd-muted-foreground text-xs empty:hidden", children: item.breadcrumbs?.map((item, i) => (_jsxs(Fragment, { children: [i > 0 && _jsx(ChevronRight, { className: "size-4 rtl:rotate-180" }), item] }, i))) }), item.type !== 'page' && (_jsx("div", { role: "none", className: "absolute start-3 inset-y-0 w-px bg-fd-border" })), _jsxs("p", { className: cn('min-w-0 truncate', item.type !== 'page' && 'ps-4', item.type === 'page' || item.type === 'heading'
127
- ? 'font-medium'
128
- : 'text-fd-popover-foreground/80'), children: [item.type === 'heading' && (_jsx(Hash, { className: "inline me-1 size-4 text-fd-muted-foreground" })), item.contentWithHighlights
129
- ? render(item.contentWithHighlights)
130
- : item.content] })] }));
131
- }
132
- return (_jsx("button", { type: "button", ref: useCallback((element) => {
133
- if (active && element) {
134
- scrollIntoView(element, {
135
- scrollMode: 'if-needed',
136
- block: 'nearest',
137
- boundary: element.parentElement,
138
- });
139
- }
140
- }, [active]), "aria-selected": active, className: cn('relative select-none px-2.5 py-2 text-start text-sm rounded-lg', active && 'bg-fd-accent text-fd-accent-foreground', className), onPointerMove: () => setActive(item.id), ...props, children: children }));
141
- }
142
- export function SearchDialogIcon(props) {
143
- const { isLoading } = useSearch();
144
- return (_jsx(SearchIcon, { ...props, className: cn('size-5 text-fd-muted-foreground', isLoading && 'animate-pulse duration-400', props.className) }));
145
- }
146
- const itemVariants = cva('rounded-md border px-2 py-0.5 text-xs font-medium text-fd-muted-foreground transition-colors', {
147
- variants: {
148
- active: {
149
- true: 'bg-fd-accent text-fd-accent-foreground',
150
- },
151
- },
152
- });
153
- export function TagsList({ tag, onTagChange, allowClear = false, ...props }) {
154
- return (_jsx("div", { ...props, className: cn('flex items-center gap-1 flex-wrap', props.className), children: _jsx(TagsListContext.Provider, { value: useMemo(() => ({
155
- value: tag,
156
- onValueChange: onTagChange,
157
- allowClear,
158
- }), [allowClear, onTagChange, tag]), children: props.children }) }));
159
- }
160
- export function TagsListItem({ value, className, ...props }) {
161
- const { onValueChange, value: selectedValue, allowClear } = useTagsList();
162
- const selected = value === selectedValue;
163
- return (_jsx("button", { type: "button", "data-active": selected, className: cn(itemVariants({ active: selected, className })), onClick: () => {
164
- onValueChange(selected && allowClear ? undefined : value);
165
- }, tabIndex: -1, ...props, children: props.children }));
19
+ function SearchDialog({ open, onOpenChange, search, onSearchChange, isLoading = false, onSelect: onSelectProp, children }) {
20
+ const router = useRouter();
21
+ const onSelect = useEffectEvent((item) => {
22
+ if (item.type === "action") item.onSelect();
23
+ else if (item.external) window.open(item.url, "_blank")?.focus();
24
+ else router.push(item.url);
25
+ onOpenChange(false);
26
+ onSelectProp?.(item);
27
+ });
28
+ return /* @__PURE__ */ jsx(Dialog, {
29
+ open,
30
+ onOpenChange,
31
+ children: /* @__PURE__ */ jsx(Context.Provider, {
32
+ value: useMemo(() => ({
33
+ open,
34
+ onOpenChange,
35
+ search,
36
+ onSearchChange,
37
+ onSelect,
38
+ isLoading
39
+ }), [
40
+ isLoading,
41
+ onOpenChange,
42
+ onSearchChange,
43
+ open,
44
+ search
45
+ ]),
46
+ children
47
+ })
48
+ });
49
+ }
50
+ function SearchDialogHeader(props) {
51
+ return /* @__PURE__ */ jsx("div", {
52
+ ...props,
53
+ className: cn("flex flex-row items-center gap-2 p-3", props.className)
54
+ });
55
+ }
56
+ function SearchDialogInput(props) {
57
+ const { text } = (0, i18n_exports.useI18n)();
58
+ const { search, onSearchChange } = useSearch();
59
+ return /* @__PURE__ */ jsx("input", {
60
+ ...props,
61
+ value: search,
62
+ onChange: (e) => onSearchChange(e.target.value),
63
+ placeholder: text.search,
64
+ className: "w-0 flex-1 bg-transparent text-lg placeholder:text-fd-muted-foreground focus-visible:outline-none"
65
+ });
66
+ }
67
+ function SearchDialogClose({ children = "ESC", className, ...props }) {
68
+ const { onOpenChange } = useSearch();
69
+ return /* @__PURE__ */ jsx("button", {
70
+ type: "button",
71
+ onClick: () => onOpenChange(false),
72
+ className: cn(buttonVariants({
73
+ color: "outline",
74
+ size: "sm",
75
+ className: "font-mono text-fd-muted-foreground"
76
+ }), className),
77
+ ...props,
78
+ children
79
+ });
80
+ }
81
+ function SearchDialogFooter(props) {
82
+ return /* @__PURE__ */ jsx("div", {
83
+ ...props,
84
+ className: cn("bg-fd-secondary/50 p-3 empty:hidden", props.className)
85
+ });
86
+ }
87
+ function SearchDialogOverlay(props) {
88
+ return /* @__PURE__ */ jsx(DialogOverlay, {
89
+ ...props,
90
+ className: cn("fixed inset-0 z-50 backdrop-blur-xs bg-fd-overlay data-[state=open]:animate-fd-fade-in data-[state=closed]:animate-fd-fade-out", props.className)
91
+ });
92
+ }
93
+ function SearchDialogContent({ children, ...props }) {
94
+ const { text } = (0, i18n_exports.useI18n)();
95
+ return /* @__PURE__ */ jsxs(DialogContent, {
96
+ "aria-describedby": void 0,
97
+ ...props,
98
+ className: cn("fixed left-1/2 top-4 md:top-[calc(50%-250px)] z-50 w-[calc(100%-1rem)] max-w-screen-sm -translate-x-1/2 rounded-xl border bg-fd-popover text-fd-popover-foreground shadow-2xl shadow-black/50 overflow-hidden data-[state=closed]:animate-fd-dialog-out data-[state=open]:animate-fd-dialog-in", "*:border-b *:has-[+:last-child[data-empty=true]]:border-b-0 *:data-[empty=true]:border-b-0 *:last:border-b-0", props.className),
99
+ children: [/* @__PURE__ */ jsx(DialogTitle, {
100
+ className: "hidden",
101
+ children: text.search
102
+ }), children]
103
+ });
104
+ }
105
+ function SearchDialogList({ items = null, Empty = () => /* @__PURE__ */ jsx("div", {
106
+ className: "py-12 text-center text-sm text-fd-muted-foreground",
107
+ children: /* @__PURE__ */ jsx(i18n_exports.I18nLabel, { label: "searchNoResult" })
108
+ }), Item = (props$1) => /* @__PURE__ */ jsx(SearchDialogListItem, { ...props$1 }), ...props }) {
109
+ const ref = useRef(null);
110
+ const { onSelect } = useSearch();
111
+ const [active, setActive] = useState(() => items && items.length > 0 ? items[0].id : null);
112
+ const onKey = useEffectEvent((e) => {
113
+ if (!items || e.isComposing) return;
114
+ if (e.key === "ArrowDown" || e.key == "ArrowUp") {
115
+ let idx = items.findIndex((item) => item.id === active);
116
+ if (idx === -1) idx = 0;
117
+ else if (e.key === "ArrowDown") idx++;
118
+ else idx--;
119
+ setActive(items.at(idx % items.length)?.id ?? null);
120
+ e.preventDefault();
121
+ }
122
+ if (e.key === "Enter") {
123
+ const selected = items.find((item) => item.id === active);
124
+ if (selected) onSelect(selected);
125
+ e.preventDefault();
126
+ }
127
+ });
128
+ useEffect(() => {
129
+ const element = ref.current;
130
+ if (!element) return;
131
+ const observer = new ResizeObserver(() => {
132
+ const viewport$1 = element.firstElementChild;
133
+ element.style.setProperty("--fd-animated-height", `${viewport$1.clientHeight}px`);
134
+ });
135
+ const viewport = element.firstElementChild;
136
+ if (viewport) observer.observe(viewport);
137
+ window.addEventListener("keydown", onKey);
138
+ return () => {
139
+ observer.disconnect();
140
+ window.removeEventListener("keydown", onKey);
141
+ };
142
+ }, []);
143
+ useOnChange(items, () => {
144
+ if (items && items.length > 0) setActive(items[0].id);
145
+ });
146
+ return /* @__PURE__ */ jsx("div", {
147
+ ...props,
148
+ ref,
149
+ "data-empty": items === null,
150
+ className: cn("overflow-hidden h-(--fd-animated-height) transition-[height]", props.className),
151
+ children: /* @__PURE__ */ jsx("div", {
152
+ className: cn("w-full flex flex-col overflow-y-auto max-h-[460px] p-1", !items && "hidden"),
153
+ children: /* @__PURE__ */ jsxs(ListContext.Provider, {
154
+ value: useMemo(() => ({
155
+ active,
156
+ setActive
157
+ }), [active]),
158
+ children: [items?.length === 0 && Empty(), items?.map((item) => /* @__PURE__ */ jsx(Fragment$1, { children: Item({
159
+ item,
160
+ onClick: () => onSelect(item)
161
+ }) }, item.id))]
162
+ })
163
+ })
164
+ });
165
+ }
166
+ function SearchDialogListItem({ item, className, children, renderHighlights: render = renderHighlights, ...props }) {
167
+ const { active: activeId, setActive } = useSearchList();
168
+ const active = item.id === activeId;
169
+ if (item.type === "action") children ??= item.node;
170
+ else children ??= /* @__PURE__ */ jsxs(Fragment, { children: [
171
+ /* @__PURE__ */ jsx("div", {
172
+ className: "inline-flex items-center text-fd-muted-foreground text-xs empty:hidden",
173
+ children: item.breadcrumbs?.map((item$1, i) => /* @__PURE__ */ jsxs(Fragment$1, { children: [i > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 rtl:rotate-180" }), item$1] }, i))
174
+ }),
175
+ item.type !== "page" && /* @__PURE__ */ jsx("div", {
176
+ role: "none",
177
+ className: "absolute start-3 inset-y-0 w-px bg-fd-border"
178
+ }),
179
+ /* @__PURE__ */ jsxs("p", {
180
+ className: cn("min-w-0 truncate", item.type !== "page" && "ps-4", item.type === "page" || item.type === "heading" ? "font-medium" : "text-fd-popover-foreground/80"),
181
+ children: [item.type === "heading" && /* @__PURE__ */ jsx(Hash, { className: "inline me-1 size-4 text-fd-muted-foreground" }), item.contentWithHighlights ? render(item.contentWithHighlights) : item.content]
182
+ })
183
+ ] });
184
+ return /* @__PURE__ */ jsx("button", {
185
+ type: "button",
186
+ ref: useCallback((element) => {
187
+ if (active && element) scrollIntoView(element, {
188
+ scrollMode: "if-needed",
189
+ block: "nearest",
190
+ boundary: element.parentElement
191
+ });
192
+ }, [active]),
193
+ "aria-selected": active,
194
+ className: cn("relative select-none px-2.5 py-2 text-start text-sm rounded-lg", active && "bg-fd-accent text-fd-accent-foreground", className),
195
+ onPointerMove: () => setActive(item.id),
196
+ ...props,
197
+ children
198
+ });
199
+ }
200
+ function SearchDialogIcon(props) {
201
+ const { isLoading } = useSearch();
202
+ return /* @__PURE__ */ jsx(Search, {
203
+ ...props,
204
+ className: cn("size-5 text-fd-muted-foreground", isLoading && "animate-pulse duration-400", props.className)
205
+ });
206
+ }
207
+ const itemVariants = cva("rounded-md border px-2 py-0.5 text-xs font-medium text-fd-muted-foreground transition-colors", { variants: { active: { true: "bg-fd-accent text-fd-accent-foreground" } } });
208
+ function TagsList({ tag, onTagChange, allowClear = false, ...props }) {
209
+ return /* @__PURE__ */ jsx("div", {
210
+ ...props,
211
+ className: cn("flex items-center gap-1 flex-wrap", props.className),
212
+ children: /* @__PURE__ */ jsx(TagsListContext.Provider, {
213
+ value: useMemo(() => ({
214
+ value: tag,
215
+ onValueChange: onTagChange,
216
+ allowClear
217
+ }), [
218
+ allowClear,
219
+ onTagChange,
220
+ tag
221
+ ]),
222
+ children: props.children
223
+ })
224
+ });
225
+ }
226
+ function TagsListItem({ value, className, ...props }) {
227
+ const { onValueChange, value: selectedValue, allowClear } = useTagsList();
228
+ const selected = value === selectedValue;
229
+ return /* @__PURE__ */ jsx("button", {
230
+ type: "button",
231
+ "data-active": selected,
232
+ className: cn(itemVariants({
233
+ active: selected,
234
+ className
235
+ })),
236
+ onClick: () => {
237
+ onValueChange(selected && allowClear ? void 0 : value);
238
+ },
239
+ tabIndex: -1,
240
+ ...props,
241
+ children: props.children
242
+ });
166
243
  }
167
244
  function renderHighlights(highlights) {
168
- return highlights.map((node, i) => {
169
- if (node.styles?.highlight) {
170
- return (_jsx("span", { className: "text-fd-primary underline", children: node.content }, i));
171
- }
172
- return _jsx(Fragment, { children: node.content }, i);
173
- });
174
- }
175
- export function useSearch() {
176
- const ctx = use(Context);
177
- if (!ctx)
178
- throw new Error('Missing <SearchDialog />');
179
- return ctx;
180
- }
181
- export function useTagsList() {
182
- const ctx = use(TagsListContext);
183
- if (!ctx)
184
- throw new Error('Missing <TagsList />');
185
- return ctx;
186
- }
187
- export function useSearchList() {
188
- const ctx = use(ListContext);
189
- if (!ctx)
190
- throw new Error('Missing <SearchDialogList />');
191
- return ctx;
245
+ return highlights.map((node, i) => {
246
+ if (node.styles?.highlight) return /* @__PURE__ */ jsx("span", {
247
+ className: "text-fd-primary underline",
248
+ children: node.content
249
+ }, i);
250
+ return /* @__PURE__ */ jsx(Fragment$1, { children: node.content }, i);
251
+ });
252
+ }
253
+ function useSearch() {
254
+ const ctx = use(Context);
255
+ if (!ctx) throw new Error("Missing <SearchDialog />");
256
+ return ctx;
257
+ }
258
+ function useTagsList() {
259
+ const ctx = use(TagsListContext);
260
+ if (!ctx) throw new Error("Missing <TagsList />");
261
+ return ctx;
262
+ }
263
+ function useSearchList() {
264
+ const ctx = use(ListContext);
265
+ if (!ctx) throw new Error("Missing <SearchDialogList />");
266
+ return ctx;
192
267
  }
268
+
269
+ //#endregion
270
+ export { SearchDialog, SearchDialogClose, SearchDialogContent, SearchDialogFooter, SearchDialogHeader, SearchDialogIcon, SearchDialogInput, SearchDialogList, SearchDialogListItem, SearchDialogOverlay, TagsList, TagsListItem, useSearch, useSearchList, useTagsList };
271
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","names":["I18nLabel","props","viewport","Fragment","item","SearchIcon"],"sources":["../../../src/components/dialog/search.tsx"],"sourcesContent":["'use client';\n\nimport { ChevronRight, Hash, Search as SearchIcon } from 'lucide-react';\nimport {\n type ComponentProps,\n createContext,\n Fragment,\n type ReactNode,\n use,\n useCallback,\n useEffect,\n useEffectEvent,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { I18nLabel, useI18n } from '@/contexts/i18n';\nimport { cn } from '@fumadocs/ui/cn';\nimport { Dialog, DialogContent, DialogOverlay, DialogTitle } from '@radix-ui/react-dialog';\nimport type { HighlightedText, ReactSortedResult as BaseResultType } from 'fumadocs-core/search';\nimport { cva } from 'class-variance-authority';\nimport { useRouter } from 'fumadocs-core/framework';\nimport type { SharedProps } from '@/contexts/search';\nimport { useOnChange } from 'fumadocs-core/utils/use-on-change';\nimport scrollIntoView from 'scroll-into-view-if-needed';\nimport { buttonVariants } from '@/components/ui/button';\n\nexport type SearchItemType =\n | (BaseResultType & {\n external?: boolean;\n })\n | {\n id: string;\n type: 'action';\n node: ReactNode;\n onSelect: () => void;\n };\n\n// needed for backward compatible since some previous guides referenced it\nexport type { SharedProps };\n\nexport interface SearchDialogProps extends SharedProps {\n search: string;\n onSearchChange: (v: string) => void;\n onSelect?: (item: SearchItemType) => void;\n isLoading?: boolean;\n\n children: ReactNode;\n}\n\nconst Context = createContext<{\n open: boolean;\n onOpenChange: (open: boolean) => void;\n search: string;\n onSearchChange: (v: string) => void;\n onSelect: (item: SearchItemType) => void;\n isLoading: boolean;\n} | null>(null);\n\nconst ListContext = createContext<{\n active: string | null;\n setActive: (v: string | null) => void;\n} | null>(null);\n\nconst TagsListContext = createContext<{\n value?: string;\n onValueChange: (value: string | undefined) => void;\n allowClear: boolean;\n} | null>(null);\n\nexport function SearchDialog({\n open,\n onOpenChange,\n search,\n onSearchChange,\n isLoading = false,\n onSelect: onSelectProp,\n children,\n}: SearchDialogProps) {\n const router = useRouter();\n const onSelect = useEffectEvent((item: SearchItemType) => {\n if (item.type === 'action') {\n item.onSelect();\n } else if (item.external) {\n window.open(item.url, '_blank')?.focus();\n } else {\n router.push(item.url);\n }\n\n onOpenChange(false);\n onSelectProp?.(item);\n });\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <Context.Provider\n value={useMemo(\n () => ({\n open,\n onOpenChange,\n search,\n onSearchChange,\n // eslint-disable-next-line react-hooks/rules-of-hooks -- used in child components\n onSelect,\n isLoading,\n }),\n [isLoading, onOpenChange, onSearchChange, open, search],\n )}\n >\n {children}\n </Context.Provider>\n </Dialog>\n );\n}\n\nexport function SearchDialogHeader(props: ComponentProps<'div'>) {\n return <div {...props} className={cn('flex flex-row items-center gap-2 p-3', props.className)} />;\n}\n\nexport function SearchDialogInput(props: ComponentProps<'input'>) {\n const { text } = useI18n();\n const { search, onSearchChange } = useSearch();\n\n return (\n <input\n {...props}\n value={search}\n onChange={(e) => onSearchChange(e.target.value)}\n placeholder={text.search}\n className=\"w-0 flex-1 bg-transparent text-lg placeholder:text-fd-muted-foreground focus-visible:outline-none\"\n />\n );\n}\n\nexport function SearchDialogClose({\n children = 'ESC',\n className,\n ...props\n}: ComponentProps<'button'>) {\n const { onOpenChange } = useSearch();\n\n return (\n <button\n type=\"button\"\n onClick={() => onOpenChange(false)}\n className={cn(\n buttonVariants({\n color: 'outline',\n size: 'sm',\n className: 'font-mono text-fd-muted-foreground',\n }),\n className,\n )}\n {...props}\n >\n {children}\n </button>\n );\n}\n\nexport function SearchDialogFooter(props: ComponentProps<'div'>) {\n return <div {...props} className={cn('bg-fd-secondary/50 p-3 empty:hidden', props.className)} />;\n}\n\nexport function SearchDialogOverlay(props: ComponentProps<typeof DialogOverlay>) {\n return (\n <DialogOverlay\n {...props}\n className={cn(\n 'fixed inset-0 z-50 backdrop-blur-xs bg-fd-overlay data-[state=open]:animate-fd-fade-in data-[state=closed]:animate-fd-fade-out',\n props.className,\n )}\n />\n );\n}\n\nexport function SearchDialogContent({ children, ...props }: ComponentProps<typeof DialogContent>) {\n const { text } = useI18n();\n\n return (\n <DialogContent\n aria-describedby={undefined}\n {...props}\n className={cn(\n 'fixed left-1/2 top-4 md:top-[calc(50%-250px)] z-50 w-[calc(100%-1rem)] max-w-screen-sm -translate-x-1/2 rounded-xl border bg-fd-popover text-fd-popover-foreground shadow-2xl shadow-black/50 overflow-hidden data-[state=closed]:animate-fd-dialog-out data-[state=open]:animate-fd-dialog-in',\n '*:border-b *:has-[+:last-child[data-empty=true]]:border-b-0 *:data-[empty=true]:border-b-0 *:last:border-b-0',\n props.className,\n )}\n >\n <DialogTitle className=\"hidden\">{text.search}</DialogTitle>\n {children}\n </DialogContent>\n );\n}\n\nexport function SearchDialogList({\n items = null,\n Empty = () => (\n <div className=\"py-12 text-center text-sm text-fd-muted-foreground\">\n <I18nLabel label=\"searchNoResult\" />\n </div>\n ),\n Item = (props) => <SearchDialogListItem {...props} />,\n ...props\n}: Omit<ComponentProps<'div'>, 'children'> & {\n items: SearchItemType[] | null | undefined;\n /**\n * Renderer for empty list UI\n */\n Empty?: () => ReactNode;\n /**\n * Renderer for items\n */\n Item?: (props: { item: SearchItemType; onClick: () => void }) => ReactNode;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n const { onSelect } = useSearch();\n const [active, setActive] = useState<string | null>(() =>\n items && items.length > 0 ? items[0].id : null,\n );\n\n const onKey = useEffectEvent((e: KeyboardEvent) => {\n if (!items || e.isComposing) return;\n\n if (e.key === 'ArrowDown' || e.key == 'ArrowUp') {\n let idx = items.findIndex((item) => item.id === active);\n if (idx === -1) idx = 0;\n else if (e.key === 'ArrowDown') idx++;\n else idx--;\n\n setActive(items.at(idx % items.length)?.id ?? null);\n e.preventDefault();\n }\n\n if (e.key === 'Enter') {\n const selected = items.find((item) => item.id === active);\n\n if (selected) onSelect(selected);\n e.preventDefault();\n }\n });\n\n useEffect(() => {\n const element = ref.current;\n if (!element) return;\n\n const observer = new ResizeObserver(() => {\n const viewport = element.firstElementChild!;\n\n element.style.setProperty('--fd-animated-height', `${viewport.clientHeight}px`);\n });\n\n const viewport = element.firstElementChild;\n if (viewport) observer.observe(viewport);\n\n window.addEventListener('keydown', onKey);\n return () => {\n observer.disconnect();\n window.removeEventListener('keydown', onKey);\n };\n }, []);\n\n useOnChange(items, () => {\n if (items && items.length > 0) {\n setActive(items[0].id);\n }\n });\n\n return (\n <div\n {...props}\n ref={ref}\n data-empty={items === null}\n className={cn(\n 'overflow-hidden h-(--fd-animated-height) transition-[height]',\n props.className,\n )}\n >\n <div\n className={cn('w-full flex flex-col overflow-y-auto max-h-[460px] p-1', !items && 'hidden')}\n >\n <ListContext.Provider\n value={useMemo(\n () => ({\n active,\n setActive,\n }),\n [active],\n )}\n >\n {items?.length === 0 && Empty()}\n\n {items?.map((item) => (\n <Fragment key={item.id}>{Item({ item, onClick: () => onSelect(item) })}</Fragment>\n ))}\n </ListContext.Provider>\n </div>\n </div>\n );\n}\n\nexport function SearchDialogListItem({\n item,\n className,\n children,\n renderHighlights: render = renderHighlights,\n ...props\n}: ComponentProps<'button'> & {\n renderHighlights?: typeof renderHighlights;\n item: SearchItemType;\n}) {\n const { active: activeId, setActive } = useSearchList();\n const active = item.id === activeId;\n\n if (item.type === 'action') {\n children ??= item.node;\n } else {\n children ??= (\n <>\n <div className=\"inline-flex items-center text-fd-muted-foreground text-xs empty:hidden\">\n {item.breadcrumbs?.map((item, i) => (\n <Fragment key={i}>\n {i > 0 && <ChevronRight className=\"size-4 rtl:rotate-180\" />}\n {item}\n </Fragment>\n ))}\n </div>\n\n {item.type !== 'page' && (\n <div role=\"none\" className=\"absolute start-3 inset-y-0 w-px bg-fd-border\" />\n )}\n <p\n className={cn(\n 'min-w-0 truncate',\n item.type !== 'page' && 'ps-4',\n item.type === 'page' || item.type === 'heading'\n ? 'font-medium'\n : 'text-fd-popover-foreground/80',\n )}\n >\n {item.type === 'heading' && (\n <Hash className=\"inline me-1 size-4 text-fd-muted-foreground\" />\n )}\n {item.contentWithHighlights ? render(item.contentWithHighlights) : item.content}\n </p>\n </>\n );\n }\n\n return (\n <button\n type=\"button\"\n ref={useCallback(\n (element: HTMLButtonElement | null) => {\n if (active && element) {\n scrollIntoView(element, {\n scrollMode: 'if-needed',\n block: 'nearest',\n boundary: element.parentElement,\n });\n }\n },\n [active],\n )}\n aria-selected={active}\n className={cn(\n 'relative select-none px-2.5 py-2 text-start text-sm rounded-lg',\n active && 'bg-fd-accent text-fd-accent-foreground',\n className,\n )}\n onPointerMove={() => setActive(item.id)}\n {...props}\n >\n {children}\n </button>\n );\n}\n\nexport function SearchDialogIcon(props: ComponentProps<'svg'>) {\n const { isLoading } = useSearch();\n\n return (\n <SearchIcon\n {...props}\n className={cn(\n 'size-5 text-fd-muted-foreground',\n isLoading && 'animate-pulse duration-400',\n props.className,\n )}\n />\n );\n}\n\nexport interface TagsListProps extends ComponentProps<'div'> {\n tag?: string;\n onTagChange: (tag: string | undefined) => void;\n allowClear?: boolean;\n}\n\nconst itemVariants = cva(\n 'rounded-md border px-2 py-0.5 text-xs font-medium text-fd-muted-foreground transition-colors',\n {\n variants: {\n active: {\n true: 'bg-fd-accent text-fd-accent-foreground',\n },\n },\n },\n);\n\nexport function TagsList({ tag, onTagChange, allowClear = false, ...props }: TagsListProps) {\n return (\n <div {...props} className={cn('flex items-center gap-1 flex-wrap', props.className)}>\n <TagsListContext.Provider\n value={useMemo(\n () => ({\n value: tag,\n onValueChange: onTagChange,\n allowClear,\n }),\n [allowClear, onTagChange, tag],\n )}\n >\n {props.children}\n </TagsListContext.Provider>\n </div>\n );\n}\n\nexport function TagsListItem({\n value,\n className,\n ...props\n}: ComponentProps<'button'> & {\n value: string;\n}) {\n const { onValueChange, value: selectedValue, allowClear } = useTagsList();\n const selected = value === selectedValue;\n\n return (\n <button\n type=\"button\"\n data-active={selected}\n className={cn(itemVariants({ active: selected, className }))}\n onClick={() => {\n onValueChange(selected && allowClear ? undefined : value);\n }}\n tabIndex={-1}\n {...props}\n >\n {props.children}\n </button>\n );\n}\n\nfunction renderHighlights(highlights: HighlightedText<ReactNode>[]): ReactNode {\n return highlights.map((node, i) => {\n if (node.styles?.highlight) {\n return (\n <span key={i} className=\"text-fd-primary underline\">\n {node.content}\n </span>\n );\n }\n\n return <Fragment key={i}>{node.content}</Fragment>;\n });\n}\n\nexport function useSearch() {\n const ctx = use(Context);\n if (!ctx) throw new Error('Missing <SearchDialog />');\n return ctx;\n}\n\nexport function useTagsList() {\n const ctx = use(TagsListContext);\n if (!ctx) throw new Error('Missing <TagsList />');\n return ctx;\n}\n\nexport function useSearchList() {\n const ctx = use(ListContext);\n if (!ctx) throw new Error('Missing <SearchDialogList />');\n return ctx;\n}\n"],"mappings":"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"}
@@ -1,21 +1,32 @@
1
- import { type CodeBlockProps } from '../components/codeblock.js';
2
- import type { HighlightOptionsCommon, HighlightOptionsThemes } from 'fumadocs-core/highlight';
3
- export interface DynamicCodeblockProps {
4
- lang: string;
5
- code: string;
6
- /**
7
- * Extra props for the underlying `<CodeBlock />` component.
8
- *
9
- * Ignored if you defined your own `pre` component in `options.components`.
10
- */
11
- codeblock?: CodeBlockProps;
12
- /**
13
- * Wrap in React `<Suspense />` and provide a fallback.
14
- *
15
- * @defaultValue true
16
- */
17
- wrapInSuspense?: boolean;
18
- options?: Omit<HighlightOptionsCommon, 'lang'> & HighlightOptionsThemes;
1
+ import { CodeBlockProps } from "./codeblock.js";
2
+ import * as react_jsx_runtime40 from "react/jsx-runtime";
3
+ import { HighlightOptionsCommon, HighlightOptionsThemes } from "fumadocs-core/highlight";
4
+
5
+ //#region src/components/dynamic-codeblock.d.ts
6
+ interface DynamicCodeblockProps {
7
+ lang: string;
8
+ code: string;
9
+ /**
10
+ * Extra props for the underlying `<CodeBlock />` component.
11
+ *
12
+ * Ignored if you defined your own `pre` component in `options.components`.
13
+ */
14
+ codeblock?: CodeBlockProps;
15
+ /**
16
+ * Wrap in React `<Suspense />` and provide a fallback.
17
+ *
18
+ * @defaultValue true
19
+ */
20
+ wrapInSuspense?: boolean;
21
+ options?: Omit<HighlightOptionsCommon, 'lang'> & HighlightOptionsThemes;
19
22
  }
20
- export declare function DynamicCodeBlock({ lang, code, codeblock, options, wrapInSuspense, }: DynamicCodeblockProps): import("react/jsx-runtime").JSX.Element;
23
+ declare function DynamicCodeBlock({
24
+ lang,
25
+ code,
26
+ codeblock,
27
+ options,
28
+ wrapInSuspense
29
+ }: DynamicCodeblockProps): react_jsx_runtime40.JSX.Element;
30
+ //#endregion
31
+ export { DynamicCodeBlock, DynamicCodeblockProps };
21
32
  //# sourceMappingURL=dynamic-codeblock.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-codeblock.d.ts","sourceRoot":"","sources":["../../src/components/dynamic-codeblock.tsx"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,cAAc,EAAO,MAAM,wBAAwB,CAAC;AAC7E,OAAO,KAAK,EAEV,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AAajC,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,MAAM,CAAC,GAAG,sBAAsB,CAAC;CACzE;AAkBD,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,OAAO,EACP,cAAqB,GACtB,EAAE,qBAAqB,2CAgCvB"}
1
+ {"version":3,"file":"dynamic-codeblock.d.ts","names":[],"sources":["../../src/components/dynamic-codeblock.tsx"],"sourcesContent":[],"mappings":";;;;;UAmBiB,qBAAA;;;EAAA;;;;;EAewD,SAAA,CAAA,EAP3D,cAO2D;EAmBzD;;;;;EAKd,cAAA,CAAA,EAAA,OAAA;EACC,OAAA,CAAA,EAzBS,IAyBT,CAzBc,sBAyBd,EAAA,MAAA,CAAA,GAzBgD,sBAyBhD;;AAAqB,iBANR,gBAAA,CAMQ;EAAA,IAAA;EAAA,IAAA;EAAA,SAAA;EAAA,OAAA;EAAA;AAAA,CAAA,EAArB,qBAAqB,CAAA,EAAA,mBAAA,CAAA,GAAA,CAAA,OAAA"}