fumadocs-ui 13.4.10 → 14.0.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 (91) hide show
  1. package/dist/{chunk-774JT2B6.js → chunk-5KVEK5A7.js} +11 -8
  2. package/dist/chunk-5QPVK7QM.js +542 -0
  3. package/dist/chunk-BN7HGCQ4.js +212 -0
  4. package/dist/chunk-CDPVENXR.js +8 -0
  5. package/dist/{chunk-KWZZNVSY.js → chunk-CPGKWLLV.js} +7 -3
  6. package/dist/chunk-DN6Z5VW6.js +61 -0
  7. package/dist/{chunk-HOIRMHZT.js → chunk-E3VO2QQT.js} +10 -2
  8. package/dist/chunk-GHOAONNQ.js +48 -0
  9. package/dist/{chunk-ERUVE5R6.js → chunk-IHIFNFRB.js} +4 -2
  10. package/dist/{chunk-CP67AHDD.js → chunk-IVBHRX3O.js} +1 -1
  11. package/dist/{chunk-NSEJBI4V.js → chunk-KZTWSBYY.js} +28 -16
  12. package/dist/chunk-MCX7E6ZW.js +57 -0
  13. package/dist/chunk-PZTQPB4U.js +125 -0
  14. package/dist/{chunk-EDNTYBXS.js → chunk-QKOA6KEZ.js} +2 -17
  15. package/dist/{chunk-YIOV4KEY.js → chunk-TYZZJ335.js} +26 -16
  16. package/dist/chunk-V6RONFCQ.js +69 -0
  17. package/dist/chunk-WRBUXI2A.js +82 -0
  18. package/dist/chunk-YL3MZH7N.js +66 -0
  19. package/dist/components/accordion.js +7 -3
  20. package/dist/components/api.d.ts +2 -5
  21. package/dist/components/api.js +2 -4
  22. package/dist/components/banner.js +5 -6
  23. package/dist/components/callout.js +2 -1
  24. package/dist/components/card.d.ts +6 -5
  25. package/dist/components/card.js +1 -1
  26. package/dist/components/codeblock.js +4 -3
  27. package/dist/components/dialog/search-algolia.d.ts +10 -4
  28. package/dist/components/dialog/search-algolia.js +25 -15
  29. package/dist/components/dialog/search-default.d.ts +10 -6
  30. package/dist/components/dialog/search-default.js +27 -5
  31. package/dist/components/dialog/search.d.ts +7 -7
  32. package/dist/components/dialog/search.js +4 -3
  33. package/dist/components/files.js +15 -11
  34. package/dist/components/heading.js +2 -1
  35. package/dist/components/image-zoom.js +8 -5
  36. package/dist/components/inline-toc.js +3 -1
  37. package/dist/components/layout/language-toggle.d.ts +4 -3
  38. package/dist/components/layout/language-toggle.js +8 -6
  39. package/dist/components/layout/root-toggle.d.ts +3 -3
  40. package/dist/components/layout/root-toggle.js +7 -73
  41. package/dist/components/tabs.js +30 -13
  42. package/dist/components/type-table.d.ts +7 -5
  43. package/dist/components/type-table.js +11 -11
  44. package/dist/dynamic-sidebar-QWGMOUMS.js +129 -0
  45. package/dist/{edit-on-github-YFVYCMB7.js → edit-on-github-PCTRDRD6.js} +10 -8
  46. package/dist/layouts/docs.client.d.ts +27 -0
  47. package/dist/layouts/docs.client.js +200 -0
  48. package/dist/layouts/docs.d.ts +30 -0
  49. package/dist/layouts/docs.js +207 -0
  50. package/dist/layouts/home.client.d.ts +11 -0
  51. package/dist/layouts/home.client.js +274 -0
  52. package/dist/layouts/home.d.ts +7 -0
  53. package/dist/layouts/home.js +61 -0
  54. package/dist/layouts/shared.d.ts +2 -0
  55. package/dist/layouts/shared.js +9 -0
  56. package/dist/mdx.client.js +4 -3
  57. package/dist/mdx.d.ts +1 -2
  58. package/dist/mdx.js +8 -10
  59. package/dist/og.d.ts +1 -7
  60. package/dist/og.js +5 -15
  61. package/dist/page.client.d.ts +2 -1
  62. package/dist/page.client.js +91 -63
  63. package/dist/page.d.ts +7 -6
  64. package/dist/page.js +78 -62
  65. package/dist/provider.d.ts +1 -2
  66. package/dist/provider.js +3 -4
  67. package/dist/shared-SScCiV7b.d.ts +152 -0
  68. package/dist/{sidebar-DwBSl7jC.d.ts → sidebar-CQ4HmzQl.d.ts} +8 -9
  69. package/dist/style.css +1 -1
  70. package/dist/tailwind-plugin.js +86 -39
  71. package/dist/{toc-clerk-CAID2WGC.js → toc-clerk-SKE4LBT7.js} +40 -50
  72. package/dist/{tree-CrKzI9Nz.d.ts → tree-06ley65N.d.ts} +9 -3
  73. package/package.json +32 -68
  74. package/dist/chunk-KCZRDPB4.js +0 -308
  75. package/dist/chunk-LSTPTAZ5.js +0 -58
  76. package/dist/chunk-P4HLRHHV.js +0 -36
  77. package/dist/chunk-UOD2T27N.js +0 -27
  78. package/dist/chunk-WLTWFYQA.js +0 -44
  79. package/dist/docs-layout.client.d.ts +0 -18
  80. package/dist/docs-layout.client.js +0 -406
  81. package/dist/home-layout.client.d.ts +0 -9
  82. package/dist/home-layout.client.js +0 -88
  83. package/dist/home-layout.d.ts +0 -7
  84. package/dist/home-layout.js +0 -30
  85. package/dist/layout.d.ts +0 -19
  86. package/dist/layout.js +0 -127
  87. package/dist/layout.shared-DEQFTB9M.d.ts +0 -117
  88. package/dist/twoslash/popup.d.ts +0 -11
  89. package/dist/twoslash/popup.js +0 -97
  90. package/dist/twoslash.css +0 -1
  91. /package/dist/{image-zoom.css → components/image-zoom.css} +0 -0
@@ -0,0 +1,212 @@
1
+ import {
2
+ LargeSearchToggle
3
+ } from "./chunk-V6RONFCQ.js";
4
+ import {
5
+ isActive
6
+ } from "./chunk-CDPVENXR.js";
7
+ import {
8
+ Collapsible,
9
+ CollapsibleContent,
10
+ CollapsibleTrigger
11
+ } from "./chunk-TQJ6YPJ3.js";
12
+ import {
13
+ ScrollArea,
14
+ ScrollViewport
15
+ } from "./chunk-2FLZOPQN.js";
16
+ import {
17
+ ChevronDown,
18
+ ExternalLink
19
+ } from "./chunk-5QPVK7QM.js";
20
+ import {
21
+ twMerge
22
+ } from "./chunk-TK3TM3MR.js";
23
+ import {
24
+ useSearchContext
25
+ } from "./chunk-ET4TW6M5.js";
26
+ import {
27
+ useTreeContext
28
+ } from "./chunk-YL3MZH7N.js";
29
+
30
+ // src/components/layout/sidebar.tsx
31
+ import * as Base from "fumadocs-core/sidebar";
32
+ import { usePathname } from "next/navigation";
33
+ import {
34
+ createContext,
35
+ memo,
36
+ useContext,
37
+ useMemo,
38
+ useState
39
+ } from "react";
40
+ import Link from "fumadocs-core/link";
41
+ import { useOnChange } from "fumadocs-core/utils/use-on-change";
42
+
43
+ // src/components/layout/variants.ts
44
+ import { cva } from "class-variance-authority";
45
+ var itemVariants = cva([
46
+ "flex flex-row items-center gap-2 rounded-md px-2 py-1.5 text-fd-muted-foreground transition-colors duration-100 [overflow-wrap:anywhere] [&_svg]:size-4",
47
+ "data-[active=false]:hover:bg-fd-accent/50 data-[active=false]:hover:text-fd-accent-foreground/80 data-[active=false]:hover:transition-none",
48
+ "data-[active=true]:bg-fd-primary/10 data-[active=true]:font-medium data-[active=true]:text-fd-primary"
49
+ ]);
50
+
51
+ // src/components/layout/sidebar.tsx
52
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
53
+ var Context = createContext(void 0);
54
+ var Sidebar = memo(
55
+ ({
56
+ components,
57
+ defaultOpenLevel = 0,
58
+ prefetch = true,
59
+ ...props
60
+ }) => {
61
+ const search = useSearchContext();
62
+ const hasSearch = search.enabled && !props.hideSearch;
63
+ const context = useMemo(
64
+ () => ({
65
+ defaultOpenLevel,
66
+ components: {
67
+ Folder: FolderNode,
68
+ Separator: SeparatorNode,
69
+ Item: PageNode,
70
+ ...components
71
+ },
72
+ prefetch
73
+ }),
74
+ [components, defaultOpenLevel, prefetch]
75
+ );
76
+ return /* @__PURE__ */ jsx(
77
+ Base.SidebarList,
78
+ {
79
+ id: "nd-sidebar",
80
+ blockScrollingWidth: 768,
81
+ ...props.aside,
82
+ className: twMerge(
83
+ "fixed top-fd-layout-top z-30 bg-fd-card pt-2 text-sm md:sticky md:h-[var(--fd-sidebar-height)] md:flex-1 md:pt-4",
84
+ "max-md:inset-x-0 max-md:bottom-0 max-md:bg-fd-background/80 max-md:text-[15px] max-md:backdrop-blur-lg max-md:data-[open=false]:invisible",
85
+ props.aside?.className
86
+ ),
87
+ style: {
88
+ ...props.aside?.style,
89
+ "--fd-sidebar-height": "calc(100dvh - var(--fd-banner-height) - var(--fd-nav-height))"
90
+ },
91
+ children: /* @__PURE__ */ jsxs("div", { className: "flex size-full flex-col md:ms-auto md:w-[var(--fd-sidebar-width)] md:border-e", children: [
92
+ props.banner,
93
+ hasSearch ? /* @__PURE__ */ jsx(LargeSearchToggle, { className: "mx-4 rounded-lg max-md:hidden md:mx-3" }) : null,
94
+ /* @__PURE__ */ jsx(ScrollArea, { className: "h-full", children: /* @__PURE__ */ jsxs(
95
+ ScrollViewport,
96
+ {
97
+ style: {
98
+ maskImage: "linear-gradient(to bottom, transparent 2px, white 16px)"
99
+ },
100
+ children: [
101
+ props.children,
102
+ /* @__PURE__ */ jsx(Context.Provider, { value: context, children: /* @__PURE__ */ jsx(RootNodeList, {}) })
103
+ ]
104
+ }
105
+ ) }),
106
+ props.footer
107
+ ] })
108
+ }
109
+ );
110
+ }
111
+ );
112
+ Sidebar.displayName = "Sidebar";
113
+ var SeparatorNode = memo(({ item }) => {
114
+ return /* @__PURE__ */ jsx("p", { className: "mb-2 mt-8 px-2 text-sm font-medium first:mt-0", children: item.name });
115
+ });
116
+ SeparatorNode.displayName = "SeparatorNode";
117
+ function RootNodeList() {
118
+ const { root } = useTreeContext();
119
+ const { components } = useInternalContext();
120
+ return /* @__PURE__ */ jsx("div", { className: "px-2 py-4 md:px-3", children: renderList(root.children, 0, components) });
121
+ }
122
+ function renderList(items, level, { Separator, Item, Folder }) {
123
+ return items.map((item, i) => {
124
+ const id = `${item.type}_${i.toString()}`;
125
+ switch (item.type) {
126
+ case "separator":
127
+ return /* @__PURE__ */ jsx(Separator, { item }, id);
128
+ case "folder":
129
+ return /* @__PURE__ */ jsx(Folder, { item, level: level + 1 }, id);
130
+ default:
131
+ return /* @__PURE__ */ jsx(Item, { item }, item.url);
132
+ }
133
+ });
134
+ }
135
+ var PageNode = memo(({ item }) => {
136
+ const pathname = usePathname();
137
+ const active = isActive(item.url, pathname, false);
138
+ const { prefetch } = useInternalContext();
139
+ return /* @__PURE__ */ jsxs(
140
+ Link,
141
+ {
142
+ href: item.url,
143
+ external: item.external,
144
+ "data-active": active,
145
+ className: twMerge(itemVariants()),
146
+ prefetch,
147
+ children: [
148
+ item.icon ?? (item.external ? /* @__PURE__ */ jsx(ExternalLink, {}) : null),
149
+ item.name
150
+ ]
151
+ }
152
+ );
153
+ });
154
+ PageNode.displayName = "PageNode";
155
+ var FolderNode = memo(
156
+ ({ item, level }) => {
157
+ const { defaultOpenLevel, prefetch, components } = useInternalContext();
158
+ const { path } = useTreeContext();
159
+ const pathname = usePathname();
160
+ const active = item.index !== void 0 && isActive(item.index.url, pathname, false);
161
+ const className = twMerge(itemVariants(), "w-full md:pe-1.5");
162
+ const shouldExtend = active || path.includes(item) || (item.defaultOpen ?? defaultOpenLevel >= level);
163
+ const [open, setOpen] = useState(shouldExtend);
164
+ useOnChange(shouldExtend, (v) => {
165
+ if (v) setOpen(v);
166
+ });
167
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
168
+ item.icon,
169
+ item.name,
170
+ /* @__PURE__ */ jsx(
171
+ ChevronDown,
172
+ {
173
+ "data-icon": true,
174
+ className: twMerge("ms-auto transition-transform", !open && "-rotate-90")
175
+ }
176
+ )
177
+ ] });
178
+ return /* @__PURE__ */ jsxs(Collapsible, { open, onOpenChange: setOpen, children: [
179
+ item.index ? /* @__PURE__ */ jsx(
180
+ Link,
181
+ {
182
+ "data-active": active,
183
+ className,
184
+ href: item.index.url,
185
+ onClick: (e) => {
186
+ if (
187
+ // clicking on icon
188
+ e.target.hasAttribute("data-icon") || active
189
+ ) {
190
+ setOpen((prev) => !prev);
191
+ e.preventDefault();
192
+ }
193
+ },
194
+ prefetch,
195
+ children: content
196
+ }
197
+ ) : /* @__PURE__ */ jsx(CollapsibleTrigger, { "data-active": active, className, children: content }),
198
+ /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx("div", { className: "ms-2 border-s py-1.5 ps-1", children: renderList(item.children, level, components) }) })
199
+ ] });
200
+ }
201
+ );
202
+ FolderNode.displayName = "FolderNode";
203
+ function useInternalContext() {
204
+ const ctx = useContext(Context);
205
+ if (!ctx) throw new Error("<Sidebar /> component required.");
206
+ return ctx;
207
+ }
208
+
209
+ export {
210
+ itemVariants,
211
+ Sidebar
212
+ };
@@ -0,0 +1,8 @@
1
+ // src/utils/shared.ts
2
+ function isActive(url, pathname, nested = true) {
3
+ return url === pathname || nested && pathname.startsWith(`${url}/`);
4
+ }
5
+
6
+ export {
7
+ isActive
8
+ };
@@ -1,9 +1,13 @@
1
+ import {
2
+ CircleX,
3
+ Info,
4
+ TriangleAlert
5
+ } from "./chunk-5QPVK7QM.js";
1
6
  import {
2
7
  twMerge
3
8
  } from "./chunk-TK3TM3MR.js";
4
9
 
5
10
  // src/components/callout.tsx
6
- import { AlertTriangle, Info, OctagonAlert } from "lucide-react";
7
11
  import { forwardRef } from "react";
8
12
  import { jsx, jsxs } from "react/jsx-runtime";
9
13
  var Callout = forwardRef(
@@ -20,8 +24,8 @@ var Callout = forwardRef(
20
24
  children: [
21
25
  icon ?? {
22
26
  info: /* @__PURE__ */ jsx(Info, { className: "size-5 fill-blue-500 text-fd-card" }),
23
- warn: /* @__PURE__ */ jsx(AlertTriangle, { className: "size-5 fill-orange-500 text-fd-card" }),
24
- error: /* @__PURE__ */ jsx(OctagonAlert, { className: "size-5 fill-red-500 text-fd-card" })
27
+ warn: /* @__PURE__ */ jsx(TriangleAlert, { className: "size-5 fill-orange-500 text-fd-card" }),
28
+ error: /* @__PURE__ */ jsx(CircleX, { className: "size-5 fill-red-500 text-fd-card" })
25
29
  }[type],
26
30
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
27
31
  title ? /* @__PURE__ */ jsx("p", { className: "not-prose mb-2 font-medium", children: title }) : null,
@@ -0,0 +1,61 @@
1
+ // src/components/layout/toc-thumb.tsx
2
+ import {
3
+ useEffect,
4
+ useRef
5
+ } from "react";
6
+ import * as Primitive from "fumadocs-core/toc";
7
+ import { useOnChange } from "fumadocs-core/utils/use-on-change";
8
+ import { jsx } from "react/jsx-runtime";
9
+ function calc(container, active) {
10
+ if (active.length === 0 || container.clientHeight === 0) {
11
+ return [0, 0];
12
+ }
13
+ let upper = Number.MAX_VALUE, lower = 0;
14
+ for (const item of active) {
15
+ const element = container.querySelector(`a[href="#${item}"]`);
16
+ if (!element) continue;
17
+ const styles = getComputedStyle(element);
18
+ upper = Math.min(upper, element.offsetTop + parseFloat(styles.paddingTop));
19
+ lower = Math.max(
20
+ lower,
21
+ element.offsetTop + element.clientHeight - parseFloat(styles.paddingBottom)
22
+ );
23
+ }
24
+ return [upper, lower - upper];
25
+ }
26
+ function update(element, info) {
27
+ element.style.setProperty("--fd-top", `${info[0]}px`);
28
+ element.style.setProperty("--fd-height", `${info[1]}px`);
29
+ }
30
+ function TocThumb({
31
+ containerRef,
32
+ ...props
33
+ }) {
34
+ const active = Primitive.useActiveAnchors();
35
+ const thumbRef = useRef(null);
36
+ const activeRef = useRef(active);
37
+ activeRef.current = active;
38
+ useEffect(() => {
39
+ if (!containerRef.current) return;
40
+ const container = containerRef.current;
41
+ const onResize = () => {
42
+ if (!thumbRef.current) return;
43
+ update(thumbRef.current, calc(container, activeRef.current));
44
+ };
45
+ onResize();
46
+ const observer = new ResizeObserver(onResize);
47
+ observer.observe(container);
48
+ return () => {
49
+ observer.disconnect();
50
+ };
51
+ }, [containerRef]);
52
+ useOnChange(active, () => {
53
+ if (!containerRef.current || !thumbRef.current) return;
54
+ update(thumbRef.current, calc(containerRef.current, active));
55
+ });
56
+ return /* @__PURE__ */ jsx("div", { ref: thumbRef, role: "none", ...props });
57
+ }
58
+
59
+ export {
60
+ TocThumb
61
+ };
@@ -1,4 +1,5 @@
1
- // src/layout.shared.tsx
1
+ // src/layouts/shared.tsx
2
+ import { Slot } from "@radix-ui/react-slot";
2
3
  import { jsx } from "react/jsx-runtime";
3
4
  function getLinks(links, githubUrl) {
4
5
  let result = links ?? [];
@@ -15,7 +16,14 @@ function getLinks(links, githubUrl) {
15
16
  ];
16
17
  return result;
17
18
  }
19
+ function replaceOrDefault(obj, def, customComponentProps, disabled) {
20
+ if (obj?.enabled === false) return disabled;
21
+ if (obj?.component !== void 0)
22
+ return /* @__PURE__ */ jsx(Slot, { ...customComponentProps, children: obj.component });
23
+ return def;
24
+ }
18
25
 
19
26
  export {
20
- getLinks
27
+ getLinks,
28
+ replaceOrDefault
21
29
  };
@@ -0,0 +1,48 @@
1
+ import {
2
+ twMerge
3
+ } from "./chunk-TK3TM3MR.js";
4
+
5
+ // src/components/card.tsx
6
+ import Link from "fumadocs-core/link";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ function Cards(props) {
9
+ return /* @__PURE__ */ jsx(
10
+ "div",
11
+ {
12
+ ...props,
13
+ className: twMerge("grid grid-cols-1 gap-4 sm:grid-cols-2", props.className),
14
+ children: props.children
15
+ }
16
+ );
17
+ }
18
+ function Card({
19
+ icon,
20
+ title,
21
+ description,
22
+ ...props
23
+ }) {
24
+ const E = props.href ? Link : "div";
25
+ return /* @__PURE__ */ jsxs(
26
+ E,
27
+ {
28
+ ...props,
29
+ "data-card": true,
30
+ className: twMerge(
31
+ "block rounded-lg border bg-fd-card p-4 text-fd-card-foreground shadow-md transition-colors",
32
+ props.href && "hover:bg-fd-accent/80",
33
+ props.className
34
+ ),
35
+ children: [
36
+ icon ? /* @__PURE__ */ jsx("div", { className: "not-prose mb-2 w-fit rounded-md border bg-fd-muted p-1.5 text-fd-muted-foreground [&_svg]:size-4", children: icon }) : null,
37
+ /* @__PURE__ */ jsx("h3", { className: "not-prose mb-1 text-sm font-medium", children: title }),
38
+ description ? /* @__PURE__ */ jsx("p", { className: "my-0 text-sm text-fd-muted-foreground", children: description }) : null,
39
+ props.children ? /* @__PURE__ */ jsx("div", { className: "text-sm text-fd-muted-foreground prose-no-margin", children: props.children }) : null
40
+ ]
41
+ }
42
+ );
43
+ }
44
+
45
+ export {
46
+ Cards,
47
+ Card
48
+ };
@@ -1,9 +1,11 @@
1
+ import {
2
+ Link
3
+ } from "./chunk-5QPVK7QM.js";
1
4
  import {
2
5
  twMerge
3
6
  } from "./chunk-TK3TM3MR.js";
4
7
 
5
8
  // src/components/heading.tsx
6
- import { Link } from "lucide-react";
7
9
  import { jsx, jsxs } from "react/jsx-runtime";
8
10
  function Heading({
9
11
  as,
@@ -18,7 +20,7 @@ function Heading({
18
20
  className: twMerge("flex scroll-m-28 flex-row items-center gap-2", className),
19
21
  ...props,
20
22
  children: [
21
- /* @__PURE__ */ jsx("a", { href: `#${props.id}`, className: "peer", children: props.children }),
23
+ /* @__PURE__ */ jsx("a", { "data-card": "", href: `#${props.id}`, className: "peer", children: props.children }),
22
24
  /* @__PURE__ */ jsx(
23
25
  Link,
24
26
  {
@@ -16,7 +16,7 @@ var PopoverContent = React.forwardRef(({ className, align = "center", sideOffset
16
16
  sideOffset,
17
17
  side: "bottom",
18
18
  className: twMerge(
19
- "z-50 min-w-[220px] max-w-[98vw] rounded-lg border bg-fd-popover p-2 text-sm text-fd-popover-foreground shadow-md data-[state=closed]:animate-fd-popover-out data-[state=open]:animate-fd-popover-in",
19
+ "z-50 min-w-[220px] max-w-[98vw] rounded-lg border bg-fd-popover p-2 text-sm text-fd-popover-foreground shadow-md focus-visible:outline-none data-[state=closed]:animate-fd-popover-out data-[state=open]:animate-fd-popover-in",
20
20
  className
21
21
  ),
22
22
  ...props
@@ -1,43 +1,47 @@
1
+ import {
2
+ buttonVariants
3
+ } from "./chunk-QKOA6KEZ.js";
1
4
  import {
2
5
  Popover,
3
6
  PopoverContent,
4
7
  PopoverTrigger
5
- } from "./chunk-CP67AHDD.js";
6
- import {
7
- useI18n
8
- } from "./chunk-EFMHXXHW.js";
9
- import {
10
- buttonVariants
11
- } from "./chunk-EDNTYBXS.js";
8
+ } from "./chunk-IVBHRX3O.js";
12
9
  import {
13
10
  twMerge
14
11
  } from "./chunk-TK3TM3MR.js";
12
+ import {
13
+ useI18n
14
+ } from "./chunk-EFMHXXHW.js";
15
15
 
16
16
  // src/components/layout/language-toggle.tsx
17
- import { useState } from "react";
18
- import { LanguagesIcon } from "lucide-react";
19
17
  import { jsx, jsxs } from "react/jsx-runtime";
20
18
  function LanguageToggle(props) {
21
19
  const context = useI18n();
22
- const [open, setOpen] = useState(false);
23
20
  if (!context.locales) throw new Error("Missing `<I18nProvider />`");
24
- return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, ...props, children: [
21
+ return /* @__PURE__ */ jsxs(Popover, { children: [
25
22
  /* @__PURE__ */ jsx(
26
23
  PopoverTrigger,
27
24
  {
28
25
  "aria-label": context.text.chooseLanguage,
29
- className: twMerge(buttonVariants({ size: "icon", color: "ghost" })),
30
- children: /* @__PURE__ */ jsx(LanguagesIcon, {})
26
+ ...props,
27
+ className: twMerge(
28
+ buttonVariants({
29
+ color: "ghost",
30
+ className: "gap-1.5 p-1.5"
31
+ }),
32
+ props.className
33
+ ),
34
+ children: props.children
31
35
  }
32
36
  ),
33
- /* @__PURE__ */ jsxs(PopoverContent, { className: "flex flex-col p-1", children: [
37
+ /* @__PURE__ */ jsxs(PopoverContent, { className: "flex flex-col overflow-hidden p-0", children: [
34
38
  /* @__PURE__ */ jsx("p", { className: "mb-1 p-2 text-xs font-medium text-fd-muted-foreground", children: context.text.chooseLanguage }),
35
39
  context.locales.map((item) => /* @__PURE__ */ jsx(
36
40
  "button",
37
41
  {
38
42
  type: "button",
39
43
  className: twMerge(
40
- "rounded-md p-2 text-left text-sm transition-colors duration-100",
44
+ "p-2 text-start text-sm",
41
45
  item.locale === context.locale ? "bg-fd-primary/10 font-medium text-fd-primary" : "hover:bg-fd-accent hover:text-fd-accent-foreground"
42
46
  ),
43
47
  onClick: () => {
@@ -50,7 +54,15 @@ function LanguageToggle(props) {
50
54
  ] })
51
55
  ] });
52
56
  }
57
+ function LanguageToggleText(props) {
58
+ const context = useI18n();
59
+ const text = context.locales?.find(
60
+ (item) => item.locale === context.locale
61
+ )?.name;
62
+ return /* @__PURE__ */ jsx("span", { ...props, children: text });
63
+ }
53
64
 
54
65
  export {
55
- LanguageToggle
66
+ LanguageToggle,
67
+ LanguageToggleText
56
68
  };
@@ -0,0 +1,57 @@
1
+ import {
2
+ twMerge
3
+ } from "./chunk-TK3TM3MR.js";
4
+ import {
5
+ useI18n
6
+ } from "./chunk-EFMHXXHW.js";
7
+
8
+ // src/components/layout/nav.tsx
9
+ import Link from "fumadocs-core/link";
10
+ import { createContext, useEffect, useState } from "react";
11
+ import { jsx } from "react/jsx-runtime";
12
+ var NavContext = createContext({
13
+ isTransparent: false
14
+ });
15
+ function NavProvider({
16
+ transparentMode = "none",
17
+ children
18
+ }) {
19
+ const [transparent, setTransparent] = useState(transparentMode !== "none");
20
+ useEffect(() => {
21
+ if (transparentMode !== "top") return;
22
+ const listener = () => {
23
+ setTransparent(window.scrollY < 10);
24
+ };
25
+ listener();
26
+ window.addEventListener("scroll", listener);
27
+ return () => {
28
+ window.removeEventListener("scroll", listener);
29
+ };
30
+ }, [transparentMode]);
31
+ return /* @__PURE__ */ jsx(NavContext.Provider, { value: { isTransparent: transparent }, children });
32
+ }
33
+ function Title({
34
+ title,
35
+ url,
36
+ ...props
37
+ }) {
38
+ const { locale } = useI18n();
39
+ return /* @__PURE__ */ jsx(
40
+ Link,
41
+ {
42
+ href: url ?? (locale ? `/${locale}` : "/"),
43
+ ...props,
44
+ className: twMerge(
45
+ "inline-flex items-center gap-2.5 font-semibold",
46
+ props.className
47
+ ),
48
+ children: title
49
+ }
50
+ );
51
+ }
52
+
53
+ export {
54
+ NavContext,
55
+ NavProvider,
56
+ Title
57
+ };
@@ -0,0 +1,125 @@
1
+ import {
2
+ isActive
3
+ } from "./chunk-CDPVENXR.js";
4
+ import {
5
+ buttonVariants
6
+ } from "./chunk-QKOA6KEZ.js";
7
+ import {
8
+ Moon,
9
+ Sun
10
+ } from "./chunk-5QPVK7QM.js";
11
+ import {
12
+ twMerge
13
+ } from "./chunk-TK3TM3MR.js";
14
+
15
+ // src/layouts/links.tsx
16
+ import Link from "fumadocs-core/link";
17
+ import { usePathname } from "next/navigation";
18
+ import { forwardRef } from "react";
19
+ import { jsx, jsxs } from "react/jsx-runtime";
20
+ var BaseLinkItem = forwardRef(({ item, ...props }, ref) => {
21
+ const pathname = usePathname();
22
+ const activeType = item.active ?? "url";
23
+ const active = activeType !== "none" && isActive(item.url, pathname, activeType === "nested-url");
24
+ return /* @__PURE__ */ jsx(
25
+ Link,
26
+ {
27
+ ref,
28
+ href: item.url,
29
+ external: item.external,
30
+ ...props,
31
+ "data-active": active,
32
+ children: props.children
33
+ }
34
+ );
35
+ });
36
+ BaseLinkItem.displayName = "BaseLinkItem";
37
+ var ButtonItem = forwardRef(({ item, ...props }, ref) => {
38
+ return /* @__PURE__ */ jsxs(
39
+ Link,
40
+ {
41
+ ref,
42
+ href: item.url,
43
+ external: item.external,
44
+ ...props,
45
+ className: twMerge(
46
+ buttonVariants({ color: "secondary" }),
47
+ "gap-1.5 [&_svg]:size-4",
48
+ props.className
49
+ ),
50
+ children: [
51
+ item.icon,
52
+ item.text
53
+ ]
54
+ }
55
+ );
56
+ });
57
+ ButtonItem.displayName = "ButtonItem";
58
+ var IconItem = forwardRef(({ item, ...props }, ref) => {
59
+ return /* @__PURE__ */ jsx(
60
+ Link,
61
+ {
62
+ ref,
63
+ "aria-label": item.label,
64
+ href: item.url,
65
+ external: item.external,
66
+ ...props,
67
+ className: twMerge(
68
+ buttonVariants({
69
+ size: "icon",
70
+ color: "ghost"
71
+ }),
72
+ props.className
73
+ ),
74
+ children: item.icon
75
+ }
76
+ );
77
+ });
78
+ IconItem.displayName = "IconItem";
79
+
80
+ // src/components/layout/theme-toggle.tsx
81
+ import { cva } from "class-variance-authority";
82
+ import { useTheme } from "next-themes";
83
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
84
+ var buttonVariants2 = cva("size-6 rounded-full p-1 text-fd-muted-foreground", {
85
+ variants: {
86
+ dark: {
87
+ true: "dark:bg-fd-accent dark:text-fd-accent-foreground",
88
+ false: "bg-fd-accent text-fd-accent-foreground dark:bg-transparent dark:text-fd-muted-foreground"
89
+ }
90
+ }
91
+ });
92
+ function ThemeToggle({
93
+ className,
94
+ ...props
95
+ }) {
96
+ const { setTheme, resolvedTheme } = useTheme();
97
+ const onToggle = () => {
98
+ setTheme(resolvedTheme === "dark" ? "light" : "dark");
99
+ };
100
+ return /* @__PURE__ */ jsxs2(
101
+ "button",
102
+ {
103
+ type: "button",
104
+ className: twMerge(
105
+ "inline-flex items-center rounded-full border p-0.5",
106
+ className
107
+ ),
108
+ "data-theme-toggle": "",
109
+ "aria-label": "Toggle Theme",
110
+ onClick: onToggle,
111
+ ...props,
112
+ children: [
113
+ /* @__PURE__ */ jsx2(Sun, { className: twMerge(buttonVariants2({ dark: false })) }),
114
+ /* @__PURE__ */ jsx2(Moon, { className: twMerge(buttonVariants2({ dark: true })) })
115
+ ]
116
+ }
117
+ );
118
+ }
119
+
120
+ export {
121
+ BaseLinkItem,
122
+ ButtonItem,
123
+ IconItem,
124
+ ThemeToggle
125
+ };