fumadocs-ui 8.0.0
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.
- package/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/chunk-24NYFO7H.js +31 -0
- package/dist/chunk-2ZR5Z6B2.js +105 -0
- package/dist/chunk-36MVEJ25.js +39 -0
- package/dist/chunk-5EZE3X7G.js +31 -0
- package/dist/chunk-5KW7ATCP.js +23 -0
- package/dist/chunk-6C3VEZWH.js +9 -0
- package/dist/chunk-CBOHU2VN.js +28 -0
- package/dist/chunk-EDUYFB4P.js +43 -0
- package/dist/chunk-F62NYOL5.js +44 -0
- package/dist/chunk-GZQICERS.js +31 -0
- package/dist/chunk-IXYX64FW.js +243 -0
- package/dist/chunk-KCGRUOMD.js +13 -0
- package/dist/chunk-OG3QOLYP.js +43 -0
- package/dist/chunk-PLXR6QNH.js +21 -0
- package/dist/chunk-UIZNMCLD.js +49 -0
- package/dist/chunk-YAHHY62W.js +20 -0
- package/dist/components/accordion.d.mts +11 -0
- package/dist/components/accordion.js +128 -0
- package/dist/components/api.d.mts +20 -0
- package/dist/components/api.js +136 -0
- package/dist/components/callout.d.mts +13 -0
- package/dist/components/callout.js +39 -0
- package/dist/components/card.d.mts +12 -0
- package/dist/components/card.js +10 -0
- package/dist/components/codeblock.d.mts +12 -0
- package/dist/components/codeblock.js +14 -0
- package/dist/components/dialog/search-algolia.d.mts +15 -0
- package/dist/components/dialog/search-algolia.js +39 -0
- package/dist/components/dialog/search-default.d.mts +15 -0
- package/dist/components/dialog/search-default.js +39 -0
- package/dist/components/dialog/search.d.mts +25 -0
- package/dist/components/dialog/search.js +13 -0
- package/dist/components/files.d.mts +20 -0
- package/dist/components/files.js +56 -0
- package/dist/components/heading.d.mts +9 -0
- package/dist/components/heading.js +8 -0
- package/dist/components/image-zoom.d.mts +12 -0
- package/dist/components/image-zoom.js +39 -0
- package/dist/components/inline-toc.d.mts +11 -0
- package/dist/components/inline-toc.js +53 -0
- package/dist/components/roll-button.d.mts +14 -0
- package/dist/components/roll-button.js +54 -0
- package/dist/components/steps.d.mts +10 -0
- package/dist/components/steps.js +14 -0
- package/dist/components/tabs.d.mts +37 -0
- package/dist/components/tabs.js +141 -0
- package/dist/components/type-table.d.mts +23 -0
- package/dist/components/type-table.js +52 -0
- package/dist/i18n-dw7ODAws.d.mts +22 -0
- package/dist/i18n.d.mts +21 -0
- package/dist/i18n.js +146 -0
- package/dist/layout-YB7EFpgW.d.mts +79 -0
- package/dist/layout.client.d.mts +4 -0
- package/dist/layout.client.js +458 -0
- package/dist/layout.d.mts +3 -0
- package/dist/layout.js +97 -0
- package/dist/mdx.client.d.mts +7 -0
- package/dist/mdx.client.js +23 -0
- package/dist/mdx.d.mts +36 -0
- package/dist/mdx.js +51 -0
- package/dist/page.client.d.mts +29 -0
- package/dist/page.client.js +168 -0
- package/dist/page.d.mts +49 -0
- package/dist/page.js +56 -0
- package/dist/provider.d.mts +50 -0
- package/dist/provider.js +51 -0
- package/dist/style.css +1 -0
- package/dist/tailwind-plugin.d.ts +36 -0
- package/dist/tailwind-plugin.js +481 -0
- package/dist/tree-Zwtp9xPv.d.mts +15 -0
- package/package.json +97 -0
package/dist/i18n.js
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
I18nContext,
|
|
4
|
+
useI18n
|
|
5
|
+
} from "./chunk-YAHHY62W.js";
|
|
6
|
+
import {
|
|
7
|
+
cn
|
|
8
|
+
} from "./chunk-KCGRUOMD.js";
|
|
9
|
+
import "./chunk-6C3VEZWH.js";
|
|
10
|
+
|
|
11
|
+
// src/i18n.tsx
|
|
12
|
+
import { useCallback } from "react";
|
|
13
|
+
import { useRouter, usePathname } from "next/navigation";
|
|
14
|
+
|
|
15
|
+
// src/components/ui/select.tsx
|
|
16
|
+
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
17
|
+
import { Check, ChevronDown } from "lucide-react";
|
|
18
|
+
import * as React from "react";
|
|
19
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
20
|
+
var Select = SelectPrimitive.Root;
|
|
21
|
+
var SelectValue = SelectPrimitive.Value;
|
|
22
|
+
var SelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
23
|
+
SelectPrimitive.Trigger,
|
|
24
|
+
{
|
|
25
|
+
ref,
|
|
26
|
+
className: cn(
|
|
27
|
+
"flex h-10 w-full items-center justify-between rounded-md border border-input px-3 py-2 text-sm ring-offset-background focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[placeholder]:text-muted-foreground",
|
|
28
|
+
className
|
|
29
|
+
),
|
|
30
|
+
...props,
|
|
31
|
+
children: [
|
|
32
|
+
children,
|
|
33
|
+
/* @__PURE__ */ jsx(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 opacity-50" }) })
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
));
|
|
37
|
+
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
38
|
+
var SelectContent = React.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
39
|
+
SelectPrimitive.Content,
|
|
40
|
+
{
|
|
41
|
+
ref,
|
|
42
|
+
className: cn(
|
|
43
|
+
"relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=closed]:animate-popover-out data-[state=open]:animate-popover-in",
|
|
44
|
+
position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
45
|
+
className
|
|
46
|
+
),
|
|
47
|
+
position,
|
|
48
|
+
...props,
|
|
49
|
+
children: /* @__PURE__ */ jsx(
|
|
50
|
+
SelectPrimitive.Viewport,
|
|
51
|
+
{
|
|
52
|
+
className: cn(
|
|
53
|
+
"p-1",
|
|
54
|
+
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
|
|
55
|
+
),
|
|
56
|
+
children
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
) }));
|
|
61
|
+
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
62
|
+
var SelectLabel = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
63
|
+
SelectPrimitive.Label,
|
|
64
|
+
{
|
|
65
|
+
ref,
|
|
66
|
+
className: cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className),
|
|
67
|
+
...props
|
|
68
|
+
}
|
|
69
|
+
));
|
|
70
|
+
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
71
|
+
var SelectItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
72
|
+
SelectPrimitive.Item,
|
|
73
|
+
{
|
|
74
|
+
ref,
|
|
75
|
+
className: cn(
|
|
76
|
+
"relative flex w-full select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
77
|
+
className
|
|
78
|
+
),
|
|
79
|
+
...props,
|
|
80
|
+
children: [
|
|
81
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "size-4" }) }) }),
|
|
82
|
+
/* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children })
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
));
|
|
86
|
+
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
87
|
+
var SelectSeparator = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
88
|
+
SelectPrimitive.Separator,
|
|
89
|
+
{
|
|
90
|
+
ref,
|
|
91
|
+
className: cn("-mx-1 my-1 h-px bg-muted", className),
|
|
92
|
+
...props
|
|
93
|
+
}
|
|
94
|
+
));
|
|
95
|
+
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
96
|
+
|
|
97
|
+
// src/i18n.tsx
|
|
98
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
99
|
+
function LanguageSelect({ ...props }) {
|
|
100
|
+
const context = useI18n();
|
|
101
|
+
if (!context.translations)
|
|
102
|
+
throw new Error("Missing prop `translations`");
|
|
103
|
+
const languages = Object.entries(context.translations);
|
|
104
|
+
return /* @__PURE__ */ jsxs2(Select, { value: context.locale, onValueChange: context.onChange, ...props, children: [
|
|
105
|
+
/* @__PURE__ */ jsx2(SelectTrigger, { children: /* @__PURE__ */ jsx2(SelectValue, { placeholder: context.text.chooseLanguage }) }),
|
|
106
|
+
/* @__PURE__ */ jsx2(SelectContent, { children: languages.map(([lang, { name }]) => /* @__PURE__ */ jsx2(SelectItem, { value: lang, children: name }, lang)) })
|
|
107
|
+
] });
|
|
108
|
+
}
|
|
109
|
+
function I18nProvider({
|
|
110
|
+
translations = {},
|
|
111
|
+
locale: forceLocale,
|
|
112
|
+
children
|
|
113
|
+
}) {
|
|
114
|
+
const localeIndex = 1;
|
|
115
|
+
const router = useRouter();
|
|
116
|
+
const pathname = usePathname();
|
|
117
|
+
const context = useI18n();
|
|
118
|
+
const segments = pathname.split("/");
|
|
119
|
+
const locale = forceLocale ?? segments[localeIndex];
|
|
120
|
+
const onChange = useCallback(
|
|
121
|
+
(v) => {
|
|
122
|
+
segments[localeIndex] = v;
|
|
123
|
+
router.push(segments.join("/"));
|
|
124
|
+
},
|
|
125
|
+
[segments, router]
|
|
126
|
+
);
|
|
127
|
+
return /* @__PURE__ */ jsx2(
|
|
128
|
+
I18nContext.Provider,
|
|
129
|
+
{
|
|
130
|
+
value: {
|
|
131
|
+
locale,
|
|
132
|
+
translations,
|
|
133
|
+
text: {
|
|
134
|
+
...context.text,
|
|
135
|
+
...translations[locale]
|
|
136
|
+
},
|
|
137
|
+
onChange
|
|
138
|
+
},
|
|
139
|
+
children
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
export {
|
|
144
|
+
I18nProvider,
|
|
145
|
+
LanguageSelect
|
|
146
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { PageTree } from 'fumadocs-core/server';
|
|
2
|
+
import { ReactNode, HTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
interface NavLinkProps {
|
|
5
|
+
icon: ReactNode;
|
|
6
|
+
href: string;
|
|
7
|
+
label: string;
|
|
8
|
+
external?: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface NavProps {
|
|
11
|
+
title: ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* Redirect url of title
|
|
14
|
+
* @defaultValue '/'
|
|
15
|
+
*/
|
|
16
|
+
url?: string;
|
|
17
|
+
items: LinkItem[];
|
|
18
|
+
links: NavLinkProps[];
|
|
19
|
+
enableSidebar: boolean;
|
|
20
|
+
collapsibleSidebar: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* When to use transparent navbar
|
|
23
|
+
* @defaultValue none
|
|
24
|
+
*/
|
|
25
|
+
transparentMode?: 'always' | 'top' | 'none';
|
|
26
|
+
children?: ReactNode;
|
|
27
|
+
}
|
|
28
|
+
declare function Nav({ title, url, links, items, transparentMode, enableSidebar, collapsibleSidebar, children, }: NavProps): JSX.Element;
|
|
29
|
+
|
|
30
|
+
interface SidebarProps {
|
|
31
|
+
items: LinkItem[];
|
|
32
|
+
/**
|
|
33
|
+
* Open folders by default if their level is lower or equal to a specific level
|
|
34
|
+
* (Starting from 1)
|
|
35
|
+
*
|
|
36
|
+
* @defaultValue 1
|
|
37
|
+
*/
|
|
38
|
+
defaultOpenLevel?: number;
|
|
39
|
+
banner?: ReactNode;
|
|
40
|
+
footer?: ReactNode;
|
|
41
|
+
}
|
|
42
|
+
declare function Sidebar({ banner, footer, items, defaultOpenLevel, }: SidebarProps): JSX.Element;
|
|
43
|
+
|
|
44
|
+
interface LinkItem {
|
|
45
|
+
url: string;
|
|
46
|
+
icon?: ReactNode;
|
|
47
|
+
text: string;
|
|
48
|
+
external?: boolean;
|
|
49
|
+
}
|
|
50
|
+
interface NavOptions extends Omit<NavProps, 'enableSidebar' | 'collapsibleSidebar' | 'items'> {
|
|
51
|
+
enabled: boolean;
|
|
52
|
+
component: ReactNode;
|
|
53
|
+
/**
|
|
54
|
+
* Github url displayed on the navbar
|
|
55
|
+
*/
|
|
56
|
+
githubUrl: string;
|
|
57
|
+
}
|
|
58
|
+
interface SidebarOptions extends Omit<SidebarProps, 'items'> {
|
|
59
|
+
enabled: boolean;
|
|
60
|
+
component: ReactNode;
|
|
61
|
+
collapsible: boolean;
|
|
62
|
+
}
|
|
63
|
+
interface BaseLayoutProps {
|
|
64
|
+
links?: LinkItem[];
|
|
65
|
+
/**
|
|
66
|
+
* Replace or disable navbar
|
|
67
|
+
*/
|
|
68
|
+
nav?: Partial<NavOptions>;
|
|
69
|
+
children: ReactNode;
|
|
70
|
+
}
|
|
71
|
+
interface DocsLayoutProps extends BaseLayoutProps {
|
|
72
|
+
tree: PageTree.Root;
|
|
73
|
+
sidebar?: Partial<SidebarOptions>;
|
|
74
|
+
containerProps?: HTMLAttributes<HTMLDivElement>;
|
|
75
|
+
}
|
|
76
|
+
declare function Layout({ nav, links, children, }: BaseLayoutProps): JSX.Element;
|
|
77
|
+
declare function DocsLayout({ nav, sidebar, links, containerProps, tree, children, }: DocsLayoutProps): JSX.Element;
|
|
78
|
+
|
|
79
|
+
export { type BaseLayoutProps as B, type DocsLayoutProps as D, type LinkItem as L, Nav as N, Sidebar as S, Layout as a, DocsLayout as b };
|
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
useSidebarCollapse
|
|
4
|
+
} from "./chunk-PLXR6QNH.js";
|
|
5
|
+
import {
|
|
6
|
+
TreeContextProvider,
|
|
7
|
+
useTreeContext
|
|
8
|
+
} from "./chunk-UIZNMCLD.js";
|
|
9
|
+
import {
|
|
10
|
+
ScrollArea
|
|
11
|
+
} from "./chunk-OG3QOLYP.js";
|
|
12
|
+
import {
|
|
13
|
+
Popover,
|
|
14
|
+
PopoverContent,
|
|
15
|
+
PopoverTrigger
|
|
16
|
+
} from "./chunk-GZQICERS.js";
|
|
17
|
+
import {
|
|
18
|
+
hasActive,
|
|
19
|
+
isActive
|
|
20
|
+
} from "./chunk-EDUYFB4P.js";
|
|
21
|
+
import {
|
|
22
|
+
useSearchContext
|
|
23
|
+
} from "./chunk-36MVEJ25.js";
|
|
24
|
+
import {
|
|
25
|
+
useI18n
|
|
26
|
+
} from "./chunk-YAHHY62W.js";
|
|
27
|
+
import {
|
|
28
|
+
Collapsible,
|
|
29
|
+
CollapsibleContent,
|
|
30
|
+
CollapsibleTrigger
|
|
31
|
+
} from "./chunk-5EZE3X7G.js";
|
|
32
|
+
import {
|
|
33
|
+
buttonVariants
|
|
34
|
+
} from "./chunk-5KW7ATCP.js";
|
|
35
|
+
import {
|
|
36
|
+
cn
|
|
37
|
+
} from "./chunk-KCGRUOMD.js";
|
|
38
|
+
import "./chunk-6C3VEZWH.js";
|
|
39
|
+
|
|
40
|
+
// src/components/nav.tsx
|
|
41
|
+
import { cva as cva2 } from "class-variance-authority";
|
|
42
|
+
import {
|
|
43
|
+
MenuIcon,
|
|
44
|
+
MoreVerticalIcon,
|
|
45
|
+
SearchIcon,
|
|
46
|
+
SidebarCloseIcon,
|
|
47
|
+
SidebarOpenIcon
|
|
48
|
+
} from "lucide-react";
|
|
49
|
+
import Link from "fumadocs-core/link";
|
|
50
|
+
import { SidebarTrigger } from "fumadocs-core/sidebar";
|
|
51
|
+
import { usePathname } from "next/navigation";
|
|
52
|
+
import {
|
|
53
|
+
forwardRef,
|
|
54
|
+
useEffect,
|
|
55
|
+
useState,
|
|
56
|
+
useCallback as useCallback2
|
|
57
|
+
} from "react";
|
|
58
|
+
import { PopoverClose } from "@radix-ui/react-popover";
|
|
59
|
+
|
|
60
|
+
// src/components/theme-toggle.tsx
|
|
61
|
+
import { cva } from "class-variance-authority";
|
|
62
|
+
import { MoonIcon, SunIcon } from "lucide-react";
|
|
63
|
+
import { useTheme } from "next-themes";
|
|
64
|
+
import { useCallback } from "react";
|
|
65
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
66
|
+
var buttonVariants2 = cva("size-7 rounded-full p-1.5 text-muted-foreground", {
|
|
67
|
+
variants: {
|
|
68
|
+
dark: {
|
|
69
|
+
true: "dark:bg-accent dark:text-accent-foreground",
|
|
70
|
+
false: "bg-accent text-accent-foreground dark:bg-transparent dark:text-muted-foreground"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
function ThemeToggle({
|
|
75
|
+
className,
|
|
76
|
+
...props
|
|
77
|
+
}) {
|
|
78
|
+
const { setTheme, resolvedTheme } = useTheme();
|
|
79
|
+
const onToggle = useCallback(() => {
|
|
80
|
+
setTheme(resolvedTheme === "dark" ? "light" : "dark");
|
|
81
|
+
}, [setTheme, resolvedTheme]);
|
|
82
|
+
return /* @__PURE__ */ jsxs(
|
|
83
|
+
"button",
|
|
84
|
+
{
|
|
85
|
+
type: "button",
|
|
86
|
+
className: cn(
|
|
87
|
+
"inline-flex items-center rounded-full border p-0.5",
|
|
88
|
+
className
|
|
89
|
+
),
|
|
90
|
+
"aria-label": "Toggle Theme",
|
|
91
|
+
onClick: onToggle,
|
|
92
|
+
...props,
|
|
93
|
+
children: [
|
|
94
|
+
/* @__PURE__ */ jsx(SunIcon, { className: cn(buttonVariants2({ dark: false })) }),
|
|
95
|
+
/* @__PURE__ */ jsx(MoonIcon, { className: cn(buttonVariants2({ dark: true })) })
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/components/nav.tsx
|
|
102
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
103
|
+
function Nav({
|
|
104
|
+
title,
|
|
105
|
+
url = "/",
|
|
106
|
+
links,
|
|
107
|
+
items,
|
|
108
|
+
transparentMode = "none",
|
|
109
|
+
enableSidebar,
|
|
110
|
+
collapsibleSidebar,
|
|
111
|
+
children
|
|
112
|
+
}) {
|
|
113
|
+
const [transparent, setTransparent] = useState(transparentMode !== "none");
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
if (transparentMode !== "top")
|
|
116
|
+
return;
|
|
117
|
+
const listener = () => {
|
|
118
|
+
setTransparent(window.scrollY < 10);
|
|
119
|
+
};
|
|
120
|
+
listener();
|
|
121
|
+
window.addEventListener("scroll", listener);
|
|
122
|
+
return () => {
|
|
123
|
+
window.removeEventListener("scroll", listener);
|
|
124
|
+
};
|
|
125
|
+
}, [transparentMode]);
|
|
126
|
+
return /* @__PURE__ */ jsx2(
|
|
127
|
+
"header",
|
|
128
|
+
{
|
|
129
|
+
className: cn(
|
|
130
|
+
"sticky top-0 z-50 h-16 border-b backdrop-blur-md transition-colors",
|
|
131
|
+
transparent ? "border-transparent" : "border-foreground/10 bg-background/50"
|
|
132
|
+
),
|
|
133
|
+
children: /* @__PURE__ */ jsxs2("nav", { className: "container flex h-full flex-row items-center gap-4", children: [
|
|
134
|
+
/* @__PURE__ */ jsx2(Link, { href: url, className: "inline-flex items-center font-bold", children: title }),
|
|
135
|
+
children,
|
|
136
|
+
items.map((item) => /* @__PURE__ */ jsx2(NavItem, { item, className: "max-lg:hidden" }, item.url)),
|
|
137
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex flex-1 flex-row items-center justify-end md:gap-2", children: [
|
|
138
|
+
/* @__PURE__ */ jsx2(SearchToggle, {}),
|
|
139
|
+
enableSidebar ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
140
|
+
/* @__PURE__ */ jsx2(ThemeToggle, { className: "max-md:hidden" }),
|
|
141
|
+
/* @__PURE__ */ jsx2(SidebarToggle, { collapsible: collapsibleSidebar })
|
|
142
|
+
] }) : /* @__PURE__ */ jsxs2(Popover, { children: [
|
|
143
|
+
/* @__PURE__ */ jsx2(ThemeToggle, { className: "max-lg:hidden" }),
|
|
144
|
+
/* @__PURE__ */ jsx2(
|
|
145
|
+
PopoverTrigger,
|
|
146
|
+
{
|
|
147
|
+
className: cn(
|
|
148
|
+
buttonVariants({
|
|
149
|
+
size: "icon",
|
|
150
|
+
color: "ghost",
|
|
151
|
+
className: "lg:hidden"
|
|
152
|
+
})
|
|
153
|
+
),
|
|
154
|
+
children: /* @__PURE__ */ jsx2(MoreVerticalIcon, {})
|
|
155
|
+
}
|
|
156
|
+
),
|
|
157
|
+
/* @__PURE__ */ jsxs2(PopoverContent, { className: "flex min-w-[260px] flex-col px-3 py-1", children: [
|
|
158
|
+
items.map((item) => /* @__PURE__ */ jsx2(PopoverClose, { asChild: true, children: /* @__PURE__ */ jsx2(
|
|
159
|
+
NavItem,
|
|
160
|
+
{
|
|
161
|
+
item,
|
|
162
|
+
className: "py-2 text-medium font-medium"
|
|
163
|
+
}
|
|
164
|
+
) }, item.url)),
|
|
165
|
+
/* @__PURE__ */ jsx2(ThemeToggle, { className: "w-fit" })
|
|
166
|
+
] })
|
|
167
|
+
] }),
|
|
168
|
+
/* @__PURE__ */ jsx2(
|
|
169
|
+
"div",
|
|
170
|
+
{
|
|
171
|
+
className: cn(
|
|
172
|
+
"flex flex-row items-center border-l pl-2 max-md:hidden",
|
|
173
|
+
links.length === 0 && "hidden"
|
|
174
|
+
),
|
|
175
|
+
children: links.map((item) => /* @__PURE__ */ jsx2(
|
|
176
|
+
Link,
|
|
177
|
+
{
|
|
178
|
+
"aria-label": item.label,
|
|
179
|
+
href: item.href,
|
|
180
|
+
external: item.external,
|
|
181
|
+
className: cn(buttonVariants({ size: "icon", color: "ghost" })),
|
|
182
|
+
children: item.icon
|
|
183
|
+
},
|
|
184
|
+
item.href
|
|
185
|
+
))
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
] })
|
|
189
|
+
] })
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
var shortcut = cva2("rounded-md border bg-background px-1.5");
|
|
194
|
+
function SearchToggle() {
|
|
195
|
+
const { setOpenSearch } = useSearchContext();
|
|
196
|
+
const { text } = useI18n();
|
|
197
|
+
const onClick = useCallback2(() => {
|
|
198
|
+
setOpenSearch(true);
|
|
199
|
+
}, [setOpenSearch]);
|
|
200
|
+
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
201
|
+
/* @__PURE__ */ jsx2(
|
|
202
|
+
"button",
|
|
203
|
+
{
|
|
204
|
+
type: "button",
|
|
205
|
+
className: cn(
|
|
206
|
+
buttonVariants({
|
|
207
|
+
size: "icon",
|
|
208
|
+
color: "ghost",
|
|
209
|
+
className: "md:hidden"
|
|
210
|
+
})
|
|
211
|
+
),
|
|
212
|
+
"aria-label": "Open Search",
|
|
213
|
+
onClick,
|
|
214
|
+
children: /* @__PURE__ */ jsx2(SearchIcon, {})
|
|
215
|
+
}
|
|
216
|
+
),
|
|
217
|
+
/* @__PURE__ */ jsxs2(
|
|
218
|
+
"button",
|
|
219
|
+
{
|
|
220
|
+
type: "button",
|
|
221
|
+
className: "inline-flex w-full max-w-[240px] 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 max-md:hidden",
|
|
222
|
+
onClick,
|
|
223
|
+
children: [
|
|
224
|
+
/* @__PURE__ */ jsx2(SearchIcon, { "aria-label": "Open Search", className: "ml-1 size-4" }),
|
|
225
|
+
text.search,
|
|
226
|
+
/* @__PURE__ */ jsxs2("div", { className: "ml-auto inline-flex gap-0.5 text-xs", children: [
|
|
227
|
+
/* @__PURE__ */ jsx2("kbd", { className: shortcut(), children: "\u2318" }),
|
|
228
|
+
/* @__PURE__ */ jsx2("kbd", { className: shortcut(), children: "K" })
|
|
229
|
+
] })
|
|
230
|
+
]
|
|
231
|
+
}
|
|
232
|
+
)
|
|
233
|
+
] });
|
|
234
|
+
}
|
|
235
|
+
function SidebarToggle({ collapsible }) {
|
|
236
|
+
const [open, setOpen] = useSidebarCollapse();
|
|
237
|
+
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
238
|
+
/* @__PURE__ */ jsx2(
|
|
239
|
+
SidebarTrigger,
|
|
240
|
+
{
|
|
241
|
+
"aria-label": "Toggle Sidebar",
|
|
242
|
+
className: cn(
|
|
243
|
+
buttonVariants({
|
|
244
|
+
size: "icon",
|
|
245
|
+
color: "ghost",
|
|
246
|
+
className: "md:hidden"
|
|
247
|
+
})
|
|
248
|
+
),
|
|
249
|
+
children: /* @__PURE__ */ jsx2(MenuIcon, {})
|
|
250
|
+
}
|
|
251
|
+
),
|
|
252
|
+
collapsible ? /* @__PURE__ */ jsx2(
|
|
253
|
+
"button",
|
|
254
|
+
{
|
|
255
|
+
type: "button",
|
|
256
|
+
"aria-label": "Toggle Sidebar",
|
|
257
|
+
onClick: () => {
|
|
258
|
+
setOpen(!open);
|
|
259
|
+
},
|
|
260
|
+
className: cn(
|
|
261
|
+
buttonVariants({
|
|
262
|
+
color: "outline",
|
|
263
|
+
size: "icon",
|
|
264
|
+
className: "rounded-full max-md:hidden"
|
|
265
|
+
})
|
|
266
|
+
),
|
|
267
|
+
children: open ? /* @__PURE__ */ jsx2(SidebarCloseIcon, {}) : /* @__PURE__ */ jsx2(SidebarOpenIcon, {})
|
|
268
|
+
}
|
|
269
|
+
) : null
|
|
270
|
+
] });
|
|
271
|
+
}
|
|
272
|
+
var NavItem = forwardRef(({ item, className, ...props }, ref) => {
|
|
273
|
+
const { text, url, external } = item;
|
|
274
|
+
const pathname = usePathname();
|
|
275
|
+
return /* @__PURE__ */ jsx2(
|
|
276
|
+
Link,
|
|
277
|
+
{
|
|
278
|
+
ref,
|
|
279
|
+
href: url,
|
|
280
|
+
external,
|
|
281
|
+
className: cn(
|
|
282
|
+
"text-sm text-muted-foreground",
|
|
283
|
+
isActive(url, pathname) ? "font-medium text-accent-foreground" : "transition-colors hover:text-accent-foreground",
|
|
284
|
+
className
|
|
285
|
+
),
|
|
286
|
+
...props,
|
|
287
|
+
children: text
|
|
288
|
+
}
|
|
289
|
+
);
|
|
290
|
+
});
|
|
291
|
+
NavItem.displayName = "NavItem";
|
|
292
|
+
|
|
293
|
+
// src/components/sidebar.tsx
|
|
294
|
+
import { cva as cva3 } from "class-variance-authority";
|
|
295
|
+
import { ChevronDown } from "lucide-react";
|
|
296
|
+
import * as Base from "fumadocs-core/sidebar";
|
|
297
|
+
import { usePathname as usePathname2 } from "next/navigation";
|
|
298
|
+
import { createContext, useContext, useEffect as useEffect2, useMemo, useState as useState2 } from "react";
|
|
299
|
+
import Link2 from "fumadocs-core/link";
|
|
300
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
301
|
+
var itemVariants = cva3(
|
|
302
|
+
"flex flex-row items-center gap-2 rounded-md px-2 py-1.5 text-muted-foreground [&_svg]:size-4",
|
|
303
|
+
{
|
|
304
|
+
variants: {
|
|
305
|
+
active: {
|
|
306
|
+
true: "bg-primary/10 font-medium text-primary",
|
|
307
|
+
false: "hover:bg-accent/50 hover:text-accent-foreground/80"
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
);
|
|
312
|
+
var SidebarContext = createContext({
|
|
313
|
+
defaultOpenLevel: 1
|
|
314
|
+
});
|
|
315
|
+
function Sidebar({
|
|
316
|
+
banner,
|
|
317
|
+
footer,
|
|
318
|
+
items = [],
|
|
319
|
+
defaultOpenLevel = 1
|
|
320
|
+
}) {
|
|
321
|
+
const [open] = useSidebarCollapse();
|
|
322
|
+
const { root } = useTreeContext();
|
|
323
|
+
return /* @__PURE__ */ jsx3(
|
|
324
|
+
Base.SidebarList,
|
|
325
|
+
{
|
|
326
|
+
minWidth: 768,
|
|
327
|
+
className: cn(
|
|
328
|
+
"flex w-full flex-col text-medium",
|
|
329
|
+
!open ? "md:hidden" : "md:sticky md:top-16 md:h-body md:w-[240px] md:text-sm xl:w-[260px]",
|
|
330
|
+
"max-md:fixed max-md:inset-0 max-md:z-40 max-md:bg-background/80 max-md:pt-16 max-md:backdrop-blur-md max-md:data-[open=false]:hidden"
|
|
331
|
+
),
|
|
332
|
+
children: /* @__PURE__ */ jsxs3(SidebarContext.Provider, { value: { defaultOpenLevel }, children: [
|
|
333
|
+
/* @__PURE__ */ jsx3(ScrollArea, { className: "flex-1", children: /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-8 pb-10 pt-4 max-md:px-4 md:pr-3 md:pt-10", children: [
|
|
334
|
+
banner,
|
|
335
|
+
/* @__PURE__ */ jsx3("div", { className: "lg:hidden", children: items.map((item) => /* @__PURE__ */ jsx3(BaseItem, { item, nested: true }, item.url)) }),
|
|
336
|
+
/* @__PURE__ */ jsx3(NodeList, { items: root.children })
|
|
337
|
+
] }) }),
|
|
338
|
+
/* @__PURE__ */ jsxs3(
|
|
339
|
+
"div",
|
|
340
|
+
{
|
|
341
|
+
className: cn(
|
|
342
|
+
"flex flex-row items-center gap-2 border-t py-2 max-md:px-4",
|
|
343
|
+
!footer && "md:hidden"
|
|
344
|
+
),
|
|
345
|
+
children: [
|
|
346
|
+
footer,
|
|
347
|
+
/* @__PURE__ */ jsx3(ThemeToggle, { className: "md:hidden" })
|
|
348
|
+
]
|
|
349
|
+
}
|
|
350
|
+
)
|
|
351
|
+
] })
|
|
352
|
+
}
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
function NodeList({ items, level = 0, ...props }) {
|
|
356
|
+
return /* @__PURE__ */ jsx3("div", { ...props, children: items.map((item) => {
|
|
357
|
+
const id = `${item.type}_${item.name}`;
|
|
358
|
+
switch (item.type) {
|
|
359
|
+
case "separator":
|
|
360
|
+
return /* @__PURE__ */ jsx3(SeparatorNode, { item }, id);
|
|
361
|
+
case "folder":
|
|
362
|
+
return /* @__PURE__ */ jsx3(Folder, { item, level: level + 1 }, id);
|
|
363
|
+
default:
|
|
364
|
+
return /* @__PURE__ */ jsx3(
|
|
365
|
+
BaseItem,
|
|
366
|
+
{
|
|
367
|
+
item: { text: item.name, url: item.url, icon: item.icon }
|
|
368
|
+
},
|
|
369
|
+
item.url
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
}) });
|
|
373
|
+
}
|
|
374
|
+
function BaseItem({
|
|
375
|
+
item,
|
|
376
|
+
nested = false
|
|
377
|
+
}) {
|
|
378
|
+
const pathname = usePathname2();
|
|
379
|
+
const active = isActive(item.url, pathname, nested);
|
|
380
|
+
return /* @__PURE__ */ jsxs3(
|
|
381
|
+
Link2,
|
|
382
|
+
{
|
|
383
|
+
href: item.url,
|
|
384
|
+
external: item.external,
|
|
385
|
+
className: cn(itemVariants({ active })),
|
|
386
|
+
children: [
|
|
387
|
+
item.icon,
|
|
388
|
+
item.text
|
|
389
|
+
]
|
|
390
|
+
}
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
function Folder({
|
|
394
|
+
item: { name, children, index, icon },
|
|
395
|
+
level
|
|
396
|
+
}) {
|
|
397
|
+
const { defaultOpenLevel } = useContext(SidebarContext);
|
|
398
|
+
const pathname = usePathname2();
|
|
399
|
+
const active = index && isActive(index.url, pathname, false);
|
|
400
|
+
const childActive = useMemo(
|
|
401
|
+
() => hasActive(children, pathname),
|
|
402
|
+
[children, pathname]
|
|
403
|
+
);
|
|
404
|
+
const [extend, setExtend] = useState2(
|
|
405
|
+
active || childActive || defaultOpenLevel >= level
|
|
406
|
+
);
|
|
407
|
+
useEffect2(() => {
|
|
408
|
+
if (active || childActive)
|
|
409
|
+
setExtend(true);
|
|
410
|
+
}, [active, childActive]);
|
|
411
|
+
const content = /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
412
|
+
icon,
|
|
413
|
+
name,
|
|
414
|
+
/* @__PURE__ */ jsx3(
|
|
415
|
+
ChevronDown,
|
|
416
|
+
{
|
|
417
|
+
onClick: (e) => {
|
|
418
|
+
setExtend((prev) => !prev);
|
|
419
|
+
e.preventDefault();
|
|
420
|
+
},
|
|
421
|
+
className: cn("ml-auto transition-transform", !extend && "-rotate-90")
|
|
422
|
+
}
|
|
423
|
+
)
|
|
424
|
+
] });
|
|
425
|
+
return /* @__PURE__ */ jsxs3(
|
|
426
|
+
Collapsible,
|
|
427
|
+
{
|
|
428
|
+
open: extend,
|
|
429
|
+
onOpenChange: !index || active ? setExtend : void 0,
|
|
430
|
+
children: [
|
|
431
|
+
/* @__PURE__ */ jsx3(
|
|
432
|
+
CollapsibleTrigger,
|
|
433
|
+
{
|
|
434
|
+
className: cn(itemVariants({ active, className: "w-full" })),
|
|
435
|
+
asChild: true,
|
|
436
|
+
children: index ? /* @__PURE__ */ jsx3(Link2, { href: index.url, children: content }) : /* @__PURE__ */ jsx3("button", { type: "button", children: content })
|
|
437
|
+
}
|
|
438
|
+
),
|
|
439
|
+
/* @__PURE__ */ jsx3(CollapsibleContent, { children: /* @__PURE__ */ jsx3(
|
|
440
|
+
NodeList,
|
|
441
|
+
{
|
|
442
|
+
className: "ml-4 flex flex-col border-l py-2 pl-2",
|
|
443
|
+
items: children,
|
|
444
|
+
level
|
|
445
|
+
}
|
|
446
|
+
) })
|
|
447
|
+
]
|
|
448
|
+
}
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
function SeparatorNode({ item }) {
|
|
452
|
+
return /* @__PURE__ */ jsx3("p", { className: "mb-2 mt-8 px-2 font-medium first:mt-0", children: item.name });
|
|
453
|
+
}
|
|
454
|
+
export {
|
|
455
|
+
Nav,
|
|
456
|
+
Sidebar,
|
|
457
|
+
TreeContextProvider
|
|
458
|
+
};
|