fumadocs-ui 12.4.2 → 12.5.1

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 (45) hide show
  1. package/dist/{chunk-NZA3MCPM.js → chunk-4NMHXJDQ.js} +67 -145
  2. package/dist/chunk-FMI5QZTV.js +21 -0
  3. package/dist/{chunk-BZ53GHJX.js → chunk-INUQLSIT.js} +66 -18
  4. package/dist/{docs.client.js → chunk-IY5T63PK.js} +20 -179
  5. package/dist/{chunk-KH555T4I.js → chunk-QQAMPLSA.js} +1 -1
  6. package/dist/{chunk-NUPTR2L5.js → chunk-QZBW7643.js} +6 -10
  7. package/dist/chunk-UDMQQ2YW.js +90 -0
  8. package/dist/chunk-V7IGWU5C.js +13 -0
  9. package/dist/{chunk-6JD7NGHG.js → chunk-YKLVLKDA.js} +4 -6
  10. package/dist/{chunk-VUIQ7ZYI.js → chunk-YSCK5YFO.js} +1 -0
  11. package/dist/{chunk-3F57TIUQ.js → chunk-YXSAWF3G.js} +9 -6
  12. package/dist/components/accordion.js +2 -2
  13. package/dist/components/api.d.ts +16 -2
  14. package/dist/components/api.js +19 -6
  15. package/dist/components/banner.js +1 -1
  16. package/dist/components/codeblock.js +2 -2
  17. package/dist/components/dialog/search-algolia.d.ts +10 -2
  18. package/dist/components/dialog/search-algolia.js +41 -7
  19. package/dist/components/dialog/search-default.d.ts +6 -2
  20. package/dist/components/dialog/search-default.js +21 -7
  21. package/dist/components/dialog/search.d.ts +16 -5
  22. package/dist/components/dialog/search.js +8 -5
  23. package/dist/components/files.d.ts +1 -0
  24. package/dist/components/layout/language-toggle.js +1 -1
  25. package/dist/components/layout/root-toggle.js +11 -4
  26. package/dist/components/roll-button.js +1 -1
  27. package/dist/components/tabs.d.ts +3 -5
  28. package/dist/components/tabs.js +1 -1
  29. package/dist/{docs.client.d.ts → docs-layout.client.d.ts} +4 -5
  30. package/dist/docs-layout.client.js +83 -0
  31. package/dist/dynamic-sidebar-YIDNYTMX.js +123 -0
  32. package/dist/{layout.client.d.ts → home-layout.client.d.ts} +1 -2
  33. package/dist/{layout.client.js → home-layout.client.js} +10 -7
  34. package/dist/home-layout.d.ts +7 -0
  35. package/dist/home-layout.js +29 -0
  36. package/dist/layout.d.ts +29 -3
  37. package/dist/layout.js +17 -22
  38. package/dist/{layout-ZAteQVYk.d.ts → layout.shared-GQuo9xqE.d.ts} +12 -65
  39. package/dist/mdx.client.js +2 -2
  40. package/dist/page.client.js +17 -9
  41. package/dist/provider.d.ts +1 -1
  42. package/dist/provider.js +5 -4
  43. package/dist/sidebar-C7MbvaPk.d.ts +39 -0
  44. package/dist/style.css +1 -1
  45. package/package.json +15 -7
@@ -12,6 +12,9 @@ import {
12
12
  import {
13
13
  useI18n
14
14
  } from "./chunk-HLGNIWUN.js";
15
+ import {
16
+ useOnChange
17
+ } from "./chunk-V7IGWU5C.js";
15
18
  import {
16
19
  Collapsible,
17
20
  CollapsibleContent,
@@ -20,106 +23,18 @@ import {
20
23
  import {
21
24
  buttonVariants,
22
25
  itemVariants
23
- } from "./chunk-VUIQ7ZYI.js";
26
+ } from "./chunk-YSCK5YFO.js";
24
27
  import {
25
28
  twMerge
26
29
  } from "./chunk-TK3TM3MR.js";
27
30
 
28
- // src/components/layout/search-toggle.tsx
29
- import { useCallback } from "react";
30
- import { SearchIcon } from "lucide-react";
31
- import { jsx, jsxs } from "react/jsx-runtime";
32
- function SearchToggle(props) {
33
- const { setOpenSearch } = useSearchContext();
34
- return /* @__PURE__ */ jsx(
35
- "button",
36
- {
37
- type: "button",
38
- className: twMerge(
39
- buttonVariants({
40
- size: "icon",
41
- color: "ghost",
42
- className: props.className
43
- })
44
- ),
45
- "aria-label": "Open Search",
46
- onClick: useCallback(() => {
47
- setOpenSearch(true);
48
- }, [setOpenSearch]),
49
- children: /* @__PURE__ */ jsx(SearchIcon, {})
50
- }
51
- );
52
- }
53
- function LargeSearchToggle(props) {
54
- const { hotKey, setOpenSearch } = useSearchContext();
55
- const { text } = useI18n();
56
- return /* @__PURE__ */ jsxs(
57
- "button",
58
- {
59
- type: "button",
60
- ...props,
61
- className: twMerge(
62
- "inline-flex items-center gap-2 rounded-full border bg-secondary/50 p-1.5 text-sm text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
63
- props.className
64
- ),
65
- onClick: useCallback(() => {
66
- setOpenSearch(true);
67
- }, [setOpenSearch]),
68
- children: [
69
- /* @__PURE__ */ jsx(SearchIcon, { className: "ms-1 size-4" }),
70
- text.search,
71
- /* @__PURE__ */ jsx("div", { className: "ms-auto inline-flex gap-0.5", children: hotKey.map((k, i) => /* @__PURE__ */ jsx("kbd", { className: "rounded-md border bg-background px-1.5", children: k.display }, i)) })
72
- ]
73
- }
74
- );
75
- }
76
-
77
- // src/components/layout/nav.tsx
78
- import Link from "fumadocs-core/link";
79
- import {
80
- useEffect,
81
- useState
82
- } from "react";
83
- import { jsx as jsx2 } from "react/jsx-runtime";
84
- function NavBox({
85
- transparentMode = "none",
86
- ...props
87
- }) {
88
- const [transparent, setTransparent] = useState(transparentMode !== "none");
89
- useEffect(() => {
90
- if (transparentMode !== "top") return;
91
- const listener = () => {
92
- setTransparent(window.scrollY < 10);
93
- };
94
- listener();
95
- window.addEventListener("scroll", listener);
96
- return () => {
97
- window.removeEventListener("scroll", listener);
98
- };
99
- }, [transparentMode]);
100
- return /* @__PURE__ */ jsx2(
101
- "header",
102
- {
103
- ...props,
104
- className: twMerge(
105
- "sticky top-0 z-50 border-b transition-colors",
106
- transparent ? "border-transparent" : "border-foreground/10 bg-background/60 backdrop-blur-md",
107
- props.className
108
- )
109
- }
110
- );
111
- }
112
- function Title({ title, url = "/" }) {
113
- return /* @__PURE__ */ jsx2(Link, { href: url, className: "inline-flex items-center gap-2.5 font-semibold", children: title });
114
- }
115
-
116
31
  // src/components/layout/link-item.tsx
117
- import Link2 from "fumadocs-core/link";
32
+ import Link from "fumadocs-core/link";
118
33
  import { ChevronDown } from "lucide-react";
119
34
  import { usePathname } from "next/navigation";
120
35
  import { cva } from "class-variance-authority";
121
- import { useEffect as useEffect2, useState as useState2 } from "react";
122
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
36
+ import { useState } from "react";
37
+ import { jsx, jsxs } from "react/jsx-runtime";
123
38
  var linkItemVariants = cva(
124
39
  "-m-2 inline-flex items-center gap-1 p-2 text-muted-foreground transition-colors [&_svg]:size-4",
125
40
  {
@@ -144,7 +59,7 @@ function LinkItem({
144
59
  if (item.on && item.on !== "all" && item.on !== on) return null;
145
60
  if (item.type === "custom") return item.children;
146
61
  if (item.type === "menu" && on === "nav") {
147
- return /* @__PURE__ */ jsxs2(
62
+ return /* @__PURE__ */ jsxs(
148
63
  LinksMenu,
149
64
  {
150
65
  items: item.items,
@@ -153,14 +68,14 @@ function LinkItem({
153
68
  children: [
154
69
  item.icon,
155
70
  item.text,
156
- /* @__PURE__ */ jsx3(ChevronDown, { className: "ms-auto !size-3.5" })
71
+ /* @__PURE__ */ jsx(ChevronDown, { className: "ms-auto !size-3.5" })
157
72
  ]
158
73
  }
159
74
  );
160
75
  }
161
76
  if (item.type === "menu") {
162
- return /* @__PURE__ */ jsxs2(Collapsible, { className: "flex flex-col", children: [
163
- /* @__PURE__ */ jsxs2(
77
+ return /* @__PURE__ */ jsxs(Collapsible, { className: "flex flex-col", children: [
78
+ /* @__PURE__ */ jsxs(
164
79
  CollapsibleTrigger,
165
80
  {
166
81
  className: twMerge(itemVariants({ className }), "group/link"),
@@ -168,16 +83,16 @@ function LinkItem({
168
83
  children: [
169
84
  item.icon,
170
85
  item.text,
171
- /* @__PURE__ */ jsx3(ChevronDown, { className: "ms-auto transition-transform group-data-[state=closed]/link:-rotate-90" })
86
+ /* @__PURE__ */ jsx(ChevronDown, { className: "ms-auto transition-transform group-data-[state=closed]/link:-rotate-90" })
172
87
  ]
173
88
  }
174
89
  ),
175
- /* @__PURE__ */ jsx3(CollapsibleContent, { children: /* @__PURE__ */ jsx3("div", { className: "ms-2 flex flex-col border-s py-2 ps-2", children: item.items.map((child, i) => /* @__PURE__ */ jsx3(LinkItem, { item: child, on: "menu" }, i)) }) })
90
+ /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx("div", { className: "ms-2 flex flex-col border-s py-2 ps-2", children: item.items.map((child, i) => /* @__PURE__ */ jsx(LinkItem, { item: child, on: "menu" }, i)) }) })
176
91
  ] });
177
92
  }
178
93
  if (item.type === "button") {
179
- return /* @__PURE__ */ jsxs2(
180
- Link2,
94
+ return /* @__PURE__ */ jsxs(
95
+ Link,
181
96
  {
182
97
  href: item.url,
183
98
  external: item.external,
@@ -196,8 +111,8 @@ function LinkItem({
196
111
  const activeType = item.active ?? "url";
197
112
  const active = activeType !== "none" && isActive(item.url, pathname, activeType === "nested-url");
198
113
  if ((item.type === "secondary" || item.type === "icon") && on === "nav") {
199
- return /* @__PURE__ */ jsx3(
200
- Link2,
114
+ return /* @__PURE__ */ jsx(
115
+ Link,
201
116
  {
202
117
  "aria-label": item.label,
203
118
  href: item.url,
@@ -214,8 +129,8 @@ function LinkItem({
214
129
  }
215
130
  );
216
131
  }
217
- return /* @__PURE__ */ jsxs2(
218
- Link2,
132
+ return /* @__PURE__ */ jsxs(
133
+ Link,
219
134
  {
220
135
  href: item.url,
221
136
  external: item.external,
@@ -238,67 +153,74 @@ function LinksMenu({
238
153
  footer,
239
154
  ...props
240
155
  }) {
241
- const [open, setOpen] = useState2(false);
156
+ const [open, setOpen] = useState(false);
242
157
  const pathname = usePathname();
243
- useEffect2(() => {
158
+ useOnChange(pathname, () => {
244
159
  setOpen(false);
245
- }, [pathname]);
246
- return /* @__PURE__ */ jsxs2(Popover, { open, onOpenChange: setOpen, children: [
247
- /* @__PURE__ */ jsx3(PopoverTrigger, { ...props }),
248
- /* @__PURE__ */ jsxs2(PopoverContent, { className: "flex flex-col", children: [
249
- items.map((item, i) => /* @__PURE__ */ jsx3(LinkItem, { item, on: "menu" }, i)),
160
+ });
161
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
162
+ /* @__PURE__ */ jsx(PopoverTrigger, { ...props }),
163
+ /* @__PURE__ */ jsxs(PopoverContent, { className: "flex flex-col", children: [
164
+ items.map((item, i) => /* @__PURE__ */ jsx(LinkItem, { item, on: "menu" }, i)),
250
165
  footer
251
166
  ] })
252
167
  ] });
253
168
  }
254
169
 
255
- // src/components/layout/theme-toggle.tsx
256
- import { cva as cva2 } from "class-variance-authority";
257
- import { Moon, Sun } from "lucide-react";
258
- import { useTheme } from "next-themes";
259
- import { useCallback as useCallback2 } from "react";
260
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
261
- var buttonVariants2 = cva2("size-7 rounded-full p-1.5 text-muted-foreground", {
262
- variants: {
263
- dark: {
264
- true: "dark:bg-accent dark:text-accent-foreground",
265
- false: "bg-accent text-accent-foreground dark:bg-transparent dark:text-muted-foreground"
266
- }
267
- }
268
- });
269
- function ThemeToggle({
270
- className,
271
- ...props
272
- }) {
273
- const { setTheme, resolvedTheme } = useTheme();
274
- const onToggle = useCallback2(() => {
275
- setTheme(resolvedTheme === "dark" ? "light" : "dark");
276
- }, [setTheme, resolvedTheme]);
277
- return /* @__PURE__ */ jsxs3(
170
+ // src/components/layout/search-toggle.tsx
171
+ import { useCallback } from "react";
172
+ import { SearchIcon } from "lucide-react";
173
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
174
+ function SearchToggle(props) {
175
+ const { setOpenSearch } = useSearchContext();
176
+ return /* @__PURE__ */ jsx2(
278
177
  "button",
279
178
  {
280
179
  type: "button",
281
180
  className: twMerge(
282
- "inline-flex items-center rounded-full border p-0.5",
283
- className
181
+ buttonVariants({
182
+ size: "icon",
183
+ color: "ghost",
184
+ className: props.className
185
+ })
284
186
  ),
285
- "aria-label": "Toggle Theme",
286
- onClick: onToggle,
187
+ "data-search": "",
188
+ "aria-label": "Open Search",
189
+ onClick: useCallback(() => {
190
+ setOpenSearch(true);
191
+ }, [setOpenSearch]),
192
+ children: /* @__PURE__ */ jsx2(SearchIcon, {})
193
+ }
194
+ );
195
+ }
196
+ function LargeSearchToggle(props) {
197
+ const { hotKey, setOpenSearch } = useSearchContext();
198
+ const { text } = useI18n();
199
+ return /* @__PURE__ */ jsxs2(
200
+ "button",
201
+ {
202
+ type: "button",
203
+ "data-search-full": "",
287
204
  ...props,
205
+ className: twMerge(
206
+ "inline-flex items-center gap-2 rounded-full border bg-secondary/50 p-1.5 text-sm text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
207
+ props.className
208
+ ),
209
+ onClick: useCallback(() => {
210
+ setOpenSearch(true);
211
+ }, [setOpenSearch]),
288
212
  children: [
289
- /* @__PURE__ */ jsx4(Sun, { className: twMerge(buttonVariants2({ dark: false })) }),
290
- /* @__PURE__ */ jsx4(Moon, { className: twMerge(buttonVariants2({ dark: true })) })
213
+ /* @__PURE__ */ jsx2(SearchIcon, { className: "ms-1 size-4" }),
214
+ text.search,
215
+ /* @__PURE__ */ jsx2("div", { className: "ms-auto inline-flex gap-0.5", children: hotKey.map((k, i) => /* @__PURE__ */ jsx2("kbd", { className: "rounded-md border bg-background px-1.5", children: k.display }, i)) })
291
216
  ]
292
217
  }
293
218
  );
294
219
  }
295
220
 
296
221
  export {
297
- SearchToggle,
298
- LargeSearchToggle,
299
- NavBox,
300
- Title,
301
222
  LinkItem,
302
223
  LinksMenu,
303
- ThemeToggle
224
+ SearchToggle,
225
+ LargeSearchToggle
304
226
  };
@@ -0,0 +1,21 @@
1
+ // src/layout.shared.tsx
2
+ import { jsx } from "react/jsx-runtime";
3
+ function getLinks(links, githubUrl) {
4
+ let result = links ?? [];
5
+ if (githubUrl)
6
+ result = [
7
+ ...result,
8
+ {
9
+ type: "secondary",
10
+ url: githubUrl,
11
+ text: "Github",
12
+ icon: /* @__PURE__ */ jsx("svg", { role: "img", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" }) }),
13
+ external: true
14
+ }
15
+ ];
16
+ return result;
17
+ }
18
+
19
+ export {
20
+ getLinks
21
+ };
@@ -1,23 +1,27 @@
1
- import {
2
- useSidebar
3
- } from "./chunk-3F57TIUQ.js";
4
1
  import {
5
2
  useSearchContext
6
3
  } from "./chunk-ET4TW6M5.js";
4
+ import {
5
+ useSidebar
6
+ } from "./chunk-YXSAWF3G.js";
7
7
  import {
8
8
  useI18n
9
9
  } from "./chunk-HLGNIWUN.js";
10
10
  import {
11
11
  buttonVariants
12
- } from "./chunk-VUIQ7ZYI.js";
12
+ } from "./chunk-YSCK5YFO.js";
13
13
  import {
14
14
  twMerge
15
15
  } from "./chunk-TK3TM3MR.js";
16
16
 
17
17
  // src/components/dialog/search.tsx
18
- import { FileTextIcon, HashIcon, TextIcon } from "lucide-react";
18
+ import { FileText, Hash, Text } from "lucide-react";
19
19
  import { useRouter } from "next/navigation";
20
- import { useMemo, useCallback } from "react";
20
+ import {
21
+ useMemo,
22
+ useCallback
23
+ } from "react";
24
+ import { cva } from "class-variance-authority";
21
25
 
22
26
  // src/components/ui/command.tsx
23
27
  import { Command as CommandPrimitive } from "cmdk";
@@ -151,32 +155,35 @@ function SearchDialog({
151
155
  })),
152
156
  [links]
153
157
  );
154
- return /* @__PURE__ */ jsx2(CommandDialog, { open, onOpenChange, footer, children: /* @__PURE__ */ jsx2(Search2, { defaultItems, ...props }) });
158
+ return /* @__PURE__ */ jsx2(CommandDialog, { open, onOpenChange, footer, children: /* @__PURE__ */ jsx2(
159
+ Search2,
160
+ {
161
+ ...props,
162
+ items: props.results === "empty" ? defaultItems : props.results,
163
+ hideResults: props.results === "empty" && defaultItems.length === 0
164
+ }
165
+ ) });
155
166
  }
156
167
  var icons = {
157
- text: /* @__PURE__ */ jsx2(TextIcon, {}),
158
- heading: /* @__PURE__ */ jsx2(HashIcon, {}),
159
- page: /* @__PURE__ */ jsx2(FileTextIcon, {})
168
+ text: /* @__PURE__ */ jsx2(Text, {}),
169
+ heading: /* @__PURE__ */ jsx2(Hash, {}),
170
+ page: /* @__PURE__ */ jsx2(FileText, {})
160
171
  };
161
172
  function Search2({
162
173
  search,
163
174
  onSearchChange,
164
- defaultItems = [],
165
- results
175
+ items,
176
+ hideResults = false
166
177
  }) {
167
178
  const { text } = useI18n();
168
179
  const router = useRouter();
169
180
  const { setOpenSearch } = useSearchContext();
170
181
  const sidebar = useSidebar();
171
- const items = results === "empty" ? defaultItems : results;
172
- const hideList = results === "empty" && defaultItems.length === 0;
173
182
  const onOpen = (url) => {
174
183
  router.push(url);
175
184
  setOpenSearch(false);
176
185
  if (location.pathname === url.split("#")[0]) {
177
186
  sidebar.setOpen(false);
178
- } else {
179
- sidebar.closeOnRedirect.current = true;
180
187
  }
181
188
  };
182
189
  return /* @__PURE__ */ jsxs2(Fragment, { children: [
@@ -191,7 +198,7 @@ function Search2({
191
198
  placeholder: text.search
192
199
  }
193
200
  ),
194
- /* @__PURE__ */ jsxs2(CommandList, { className: twMerge(hideList && "hidden"), children: [
201
+ /* @__PURE__ */ jsxs2(CommandList, { className: twMerge(hideResults && "hidden"), children: [
195
202
  /* @__PURE__ */ jsx2(CommandEmpty, { children: text.searchNoResult }),
196
203
  /* @__PURE__ */ jsx2(CommandGroup, { value: "result", children: items.map((item) => /* @__PURE__ */ jsx2(
197
204
  CommandItem,
@@ -209,7 +216,48 @@ function Search2({
209
216
  ] })
210
217
  ] });
211
218
  }
219
+ var itemVariants = cva(
220
+ "rounded-md border px-2 py-0.5 text-xs font-medium text-muted-foreground transition-colors",
221
+ {
222
+ variants: {
223
+ active: {
224
+ true: "bg-accent text-accent-foreground"
225
+ }
226
+ }
227
+ }
228
+ );
229
+ function TagsList({
230
+ tag,
231
+ onTagChange,
232
+ items,
233
+ ...props
234
+ }) {
235
+ return /* @__PURE__ */ jsxs2(
236
+ "div",
237
+ {
238
+ ...props,
239
+ className: twMerge("flex flex-row items-center gap-1", props.className),
240
+ children: [
241
+ items.map((item) => /* @__PURE__ */ jsx2(
242
+ "button",
243
+ {
244
+ type: "button",
245
+ className: twMerge(itemVariants({ active: tag === item.value })),
246
+ onClick: () => {
247
+ onTagChange(item.value);
248
+ },
249
+ tabIndex: -1,
250
+ children: item.name
251
+ },
252
+ item.value
253
+ )),
254
+ props.children
255
+ ]
256
+ }
257
+ );
258
+ }
212
259
 
213
260
  export {
214
- SearchDialog
261
+ SearchDialog,
262
+ TagsList
215
263
  };