@fumadocs/base-ui 16.11.5 → 16.12.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.
- package/css/generated/docs.css +1 -1
- package/css/generated/flux.css +1 -1
- package/css/generated/glass.css +1 -0
- package/css/generated/home.css +1 -1
- package/css/generated/notebook.css +1 -1
- package/css/generated/shared.css +1 -1
- package/css/lib/base.css +2 -1
- package/css/preset.css +0 -1
- package/dist/.translations/index.d.ts +6 -0
- package/dist/.translations/keys.js +6 -0
- package/dist/components/image-zoom.d.ts +2 -2
- package/dist/components/image-zoom.js +1 -1
- package/dist/components/sidebar/tabs/dropdown.d.ts +2 -3
- package/dist/components/sidebar/tabs/dropdown.js +9 -4
- package/dist/components/tabs.js +0 -1
- package/dist/components/toc/index.js +1 -1
- package/dist/components/ui/popover.js +1 -1
- package/dist/components/ui/tabs.d.ts +1 -1
- package/dist/components/ui/tabs.js +36 -11
- package/dist/layouts/docs/client.js +10 -5
- package/dist/layouts/docs/page/slots/toc.js +17 -11
- package/dist/layouts/docs/slots/sidebar.js +8 -2
- package/dist/layouts/flux/index.d.ts +1 -1
- package/dist/layouts/flux/index.js +34 -34
- package/dist/layouts/flux/page/slots/toc.js +7 -4
- package/dist/layouts/flux/slots/sidebar.js +4 -4
- package/dist/layouts/flux/slots/tab-dropdown.js +8 -2
- package/dist/layouts/glass/index.d.ts +41 -0
- package/dist/layouts/glass/index.js +70 -0
- package/dist/layouts/glass/layout-tabs.js +53 -0
- package/dist/layouts/glass/page/index.d.ts +31 -0
- package/dist/layouts/glass/page/index.js +92 -0
- package/dist/layouts/glass/page/slots/breadcrumb.d.ts +7 -0
- package/dist/layouts/glass/page/slots/breadcrumb.js +44 -0
- package/dist/layouts/glass/page/slots/footer.d.ts +16 -0
- package/dist/layouts/glass/page/slots/footer.js +56 -0
- package/dist/layouts/glass/page/slots/toc.d.ts +19 -0
- package/dist/layouts/glass/page/slots/toc.js +108 -0
- package/dist/layouts/glass/slots/header.d.ts +6 -0
- package/dist/layouts/glass/slots/header.js +73 -0
- package/dist/layouts/glass/slots/sidebar.d.ts +23 -0
- package/dist/layouts/glass/slots/sidebar.js +294 -0
- package/dist/layouts/home/index.js +2 -2
- package/dist/layouts/home/slots/header.d.ts +1 -1
- package/dist/layouts/home/slots/header.js +1 -0
- package/dist/layouts/notebook/client.js +2 -2
- package/dist/layouts/notebook/page/slots/toc.js +17 -11
- package/dist/layouts/notebook/slots/header.js +8 -2
- package/dist/layouts/notebook/slots/sidebar.js +8 -2
- package/dist/layouts/shared/client.d.ts +1 -1
- package/dist/layouts/shared/client.js +1 -1
- package/dist/layouts/shared/index.d.ts +7 -6
- package/dist/layouts/shared/index.js +5 -3
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/controlled.d.ts +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/controlled.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/uncontrolled.d.ts +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/uncontrolled.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/adjust-svg-ids.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/compute-positioned-style.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/element-tests.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/get-div-img-style.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/get-img-alt.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/get-img-object-fit-style.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/get-img-regular-style.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/get-img-src.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/get-modal-img-transform.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/get-scale.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/get-style-ghost.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/get-style-modal-img.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/get-target-dimension.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/parse-position.js +1 -1
- package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/utils/test-has-scalable-src.js +1 -1
- package/dist/style.css +985 -885
- package/package.json +16 -9
- /package/dist/node_modules/.pnpm/{react-medium-image-zoom@5.4.8_react-dom@19.2.7_react@19.2.7__react@19.2.7 → react-medium-image-zoom@5.4.8_react-dom@19.2.8_react@19.2.8__react@19.2.8}/node_modules/react-medium-image-zoom/dist/index.d.ts +0 -0
|
@@ -20,13 +20,13 @@ function useFluxLayout() {
|
|
|
20
20
|
if (!context) throw new Error("Please use Flux layout components under <DocsLayout /> (`fumadocs-ui/layouts/flux`).");
|
|
21
21
|
return context;
|
|
22
22
|
}
|
|
23
|
-
const {
|
|
23
|
+
const { useBaseSlots } = baseSlots({ useProps() {
|
|
24
24
|
return useFluxLayout().props;
|
|
25
25
|
} });
|
|
26
26
|
function DocsLayout(props) {
|
|
27
27
|
const { tree, nav = {}, sidebar: { enabled: sidebarEnabled = true, tabs: _tabs, defaultOpenLevel, prefetch, ...sidebarProps } = {}, tabs: defaultTabs = _tabs, children, containerProps, renderNavigationPanel = (props) => /* @__PURE__ */ jsx(NavigationPanel, { ...props }), slots: defaultSlots = {} } = props;
|
|
28
28
|
const linkItems = useLinkItems(props);
|
|
29
|
-
const { baseSlots, baseProps } =
|
|
29
|
+
const { baseSlots, baseProps } = useBaseSlots(props);
|
|
30
30
|
const tabs = useMemo(() => {
|
|
31
31
|
if (Array.isArray(defaultTabs)) return defaultTabs;
|
|
32
32
|
if (typeof defaultTabs === "object") return getLayoutTabs(tree, defaultTabs);
|
|
@@ -50,44 +50,44 @@ function DocsLayout(props) {
|
|
|
50
50
|
slots,
|
|
51
51
|
...linkItems
|
|
52
52
|
},
|
|
53
|
-
children: /* @__PURE__ */
|
|
53
|
+
children: /* @__PURE__ */ jsx(TreeContextProvider, {
|
|
54
54
|
tree,
|
|
55
|
-
children:
|
|
55
|
+
children: /* @__PURE__ */ jsxs(slots.sidebar.provider, {
|
|
56
56
|
defaultOpenLevel,
|
|
57
57
|
prefetch,
|
|
58
|
-
children: /* @__PURE__ */ jsxs(slots.container, {
|
|
58
|
+
children: [/* @__PURE__ */ jsxs(slots.container, {
|
|
59
59
|
...containerProps,
|
|
60
60
|
children: [sidebarEnabled && /* @__PURE__ */ jsx(slots.sidebar.root, { ...sidebarProps }), children]
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
tabs
|
|
67
|
-
}),
|
|
68
|
-
tool: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
69
|
-
slots.languageSelect && /* @__PURE__ */ jsx(slots.languageSelect.root, { children: /* @__PURE__ */ jsx(Languages, { className: "size-4.5" }) }),
|
|
70
|
-
slots.searchTrigger && /* @__PURE__ */ jsx(slots.searchTrigger.sm, {
|
|
71
|
-
hideIfDisabled: true,
|
|
72
|
-
className: "rounded-lg"
|
|
61
|
+
}), renderNavigationPanel({
|
|
62
|
+
head: /* @__PURE__ */ jsxs(Fragment, { children: [slots.navTitle && /* @__PURE__ */ jsx(slots.navTitle, { className: "inline-flex items-center gap-2.5 text-sm font-semibold" }), nav.children] }),
|
|
63
|
+
tabDropdown: slots.tabDropdown && tabs.length > 0 && /* @__PURE__ */ jsx(slots.tabDropdown, {
|
|
64
|
+
className: "flex-1",
|
|
65
|
+
tabs
|
|
73
66
|
}),
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
67
|
+
tool: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
68
|
+
slots.languageSelect && /* @__PURE__ */ jsx(slots.languageSelect.root, { children: /* @__PURE__ */ jsx(Languages, { className: "size-4.5" }) }),
|
|
69
|
+
slots.searchTrigger && /* @__PURE__ */ jsx(slots.searchTrigger.sm, {
|
|
70
|
+
hideIfDisabled: true,
|
|
71
|
+
className: "rounded-lg"
|
|
72
|
+
}),
|
|
73
|
+
slots.sidebar && /* @__PURE__ */ jsx(slots.sidebar.trigger, { className: cn(buttonVariants({
|
|
74
|
+
variant: "ghost",
|
|
75
|
+
size: "icon-sm",
|
|
76
|
+
className: "overflow-hidden"
|
|
77
|
+
})) }),
|
|
78
|
+
slots.themeSwitch && /* @__PURE__ */ jsx(slots.themeSwitch, { className: "p-1 h-full ms-1 rounded-xl bg-fd-muted *:rounded-lg" })
|
|
79
|
+
] }),
|
|
80
|
+
link: linkItems.menuItems.filter((item) => item.type === "icon").map((item, i) => /* @__PURE__ */ jsx(LinkItem, {
|
|
81
|
+
item,
|
|
82
|
+
className: cn(buttonVariants({
|
|
83
|
+
size: "icon-sm",
|
|
84
|
+
color: "ghost"
|
|
85
|
+
})),
|
|
86
|
+
"aria-label": item.label,
|
|
87
|
+
children: item.icon
|
|
88
|
+
}, i))
|
|
89
|
+
})]
|
|
90
|
+
})
|
|
91
91
|
})
|
|
92
92
|
});
|
|
93
93
|
}
|
|
@@ -24,10 +24,13 @@ function TOC({ container, trigger, content, header, footer, style = "normal", li
|
|
|
24
24
|
...content,
|
|
25
25
|
children: [
|
|
26
26
|
header,
|
|
27
|
-
/* @__PURE__ */ jsx(TOCScrollArea, {
|
|
28
|
-
|
|
29
|
-
children:
|
|
30
|
-
|
|
27
|
+
/* @__PURE__ */ jsx(TOCScrollArea, {
|
|
28
|
+
className: "ms-px",
|
|
29
|
+
children: /* @__PURE__ */ jsxs(TOCItems, {
|
|
30
|
+
...list,
|
|
31
|
+
children: [items.length === 0 && /* @__PURE__ */ jsx(TOCEmpty, {}), items.map((item) => /* @__PURE__ */ jsx(TOCItem, { item }, item.url))]
|
|
32
|
+
})
|
|
33
|
+
}),
|
|
31
34
|
footer
|
|
32
35
|
]
|
|
33
36
|
}), /* @__PURE__ */ jsx(PageTOCPopoverTrigger, { ...trigger })]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../../utils/cn.js";
|
|
3
3
|
import { mergeRefs } from "../../../utils/merge-refs.js";
|
|
4
|
-
import { SidebarFolder as SidebarFolder$1, SidebarFolderContent as SidebarFolderContent$1, SidebarFolderLink as SidebarFolderLink$1, SidebarFolderTrigger as SidebarFolderTrigger$1, SidebarItem as SidebarItem$1, SidebarProvider as SidebarProvider$1, SidebarSeparator as SidebarSeparator$1,
|
|
4
|
+
import { SidebarFolder as SidebarFolder$1, SidebarFolderContent as SidebarFolderContent$1, SidebarFolderLink as SidebarFolderLink$1, SidebarFolderTrigger as SidebarFolderTrigger$1, SidebarItem as SidebarItem$1, SidebarProvider as SidebarProvider$1, SidebarSeparator as SidebarSeparator$1, base_exports, useFolder, useFolderDepth } from "../../../components/sidebar/base.js";
|
|
5
5
|
import { createPageTreeRenderer } from "../../../components/sidebar/page-tree.js";
|
|
6
6
|
import { createLinkItemRenderer } from "../../../components/sidebar/link-item.js";
|
|
7
7
|
import { useFluxLayout } from "../index.js";
|
|
@@ -40,13 +40,13 @@ function Sidebar({ footer, banner, components, ...rest }) {
|
|
|
40
40
|
className: "flex flex-col gap-3 p-4 pb-2 empty:hidden",
|
|
41
41
|
children: banner
|
|
42
42
|
}),
|
|
43
|
-
/* @__PURE__ */
|
|
44
|
-
className: "flex flex-col",
|
|
43
|
+
/* @__PURE__ */ jsxs("div", {
|
|
44
|
+
className: "flex flex-col p-4",
|
|
45
45
|
children: [menuItems.filter((v) => v.type !== "icon").map((item, i, list) => /* @__PURE__ */ jsx(SidebarLinkItem, {
|
|
46
46
|
item,
|
|
47
47
|
className: cn(i === list.length - 1 && "mb-4")
|
|
48
48
|
}, i)), /* @__PURE__ */ jsx(SidebarPageTree, { ...components })]
|
|
49
|
-
})
|
|
49
|
+
}),
|
|
50
50
|
footer
|
|
51
51
|
]
|
|
52
52
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../../../utils/cn.js";
|
|
3
|
+
import { useTreePath } from "../../../contexts/tree.js";
|
|
3
4
|
import { Popover, PopoverContent, PopoverTrigger } from "../../../components/ui/popover.js";
|
|
4
5
|
import { isLayoutTabActive } from "../../shared/index.js";
|
|
5
6
|
import Link from "fumadocs-core/link";
|
|
@@ -12,9 +13,14 @@ import { AnimatePresence, motion } from "motion/react";
|
|
|
12
13
|
function TabDropdown({ tabs, placeholder, className, ...props }) {
|
|
13
14
|
const [open, setOpen] = useState(false);
|
|
14
15
|
const pathname = usePathname();
|
|
16
|
+
const path = useTreePath();
|
|
15
17
|
const selectedIdx = useMemo(() => {
|
|
16
|
-
return tabs.findLastIndex((item) => isLayoutTabActive(item, pathname));
|
|
17
|
-
}, [
|
|
18
|
+
return tabs.findLastIndex((item) => isLayoutTabActive(item, path, pathname));
|
|
19
|
+
}, [
|
|
20
|
+
tabs,
|
|
21
|
+
path,
|
|
22
|
+
pathname
|
|
23
|
+
]);
|
|
18
24
|
const selected = selectedIdx !== -1 ? tabs[selectedIdx] : void 0;
|
|
19
25
|
const onClick = () => {
|
|
20
26
|
setOpen(false);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { BaseSlots, BaseSlotsProps } from "../shared/client.js";
|
|
2
|
+
import { BaseLayoutProps, GetLayoutTabsOptions, LayoutTab, LinkItemType } from "../shared/index.js";
|
|
3
|
+
import { SidebarDrawerProps, SidebarProps, SidebarProviderProps, useSidebar } from "./slots/sidebar.js";
|
|
4
|
+
import { HeaderProps } from "./slots/header.js";
|
|
5
|
+
import { FC } from "react";
|
|
6
|
+
import * as PageTree from "fumadocs-core/page-tree";
|
|
7
|
+
import { Drawer } from "@base-ui/react";
|
|
8
|
+
//#region src/layouts/glass/index.d.ts
|
|
9
|
+
interface GlassSlots extends BaseSlots {
|
|
10
|
+
header: FC<HeaderProps>;
|
|
11
|
+
sidebar: {
|
|
12
|
+
main: FC<SidebarProps>;
|
|
13
|
+
provider: FC<SidebarProviderProps>;
|
|
14
|
+
use: typeof useSidebar;
|
|
15
|
+
drawer: FC<SidebarDrawerProps>;
|
|
16
|
+
drawerHandle: Drawer.Handle<unknown>;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
interface GlassLayoutProps extends BaseLayoutProps {
|
|
20
|
+
tree: PageTree.Root;
|
|
21
|
+
tabs?: LayoutTab[] | GetLayoutTabsOptions | false;
|
|
22
|
+
aiChat?: {
|
|
23
|
+
open: boolean;
|
|
24
|
+
onOpenChange: (v: boolean) => void;
|
|
25
|
+
};
|
|
26
|
+
slots?: Partial<GlassSlots>;
|
|
27
|
+
sidebar?: Omit<SidebarProviderProps, 'children'>;
|
|
28
|
+
}
|
|
29
|
+
interface SlotsProps extends BaseSlotsProps<GlassLayoutProps> {
|
|
30
|
+
tabs: LayoutTab[];
|
|
31
|
+
aiChat?: GlassLayoutProps['aiChat'];
|
|
32
|
+
}
|
|
33
|
+
declare function useGlassLayout(): {
|
|
34
|
+
props: SlotsProps;
|
|
35
|
+
navItems: LinkItemType[];
|
|
36
|
+
menuItems: LinkItemType[];
|
|
37
|
+
slots: GlassSlots;
|
|
38
|
+
};
|
|
39
|
+
declare function GlassLayout(props: GlassLayoutProps): import("react").JSX.Element;
|
|
40
|
+
//#endregion
|
|
41
|
+
export { GlassLayout, GlassLayoutProps, GlassSlots, useGlassLayout };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { TreeContextProvider } from "../../contexts/tree.js";
|
|
3
|
+
import { baseSlots } from "../shared/client.js";
|
|
4
|
+
import { getLayoutTabs, useLinkItems } from "../shared/index.js";
|
|
5
|
+
import { Sidebar, SidebarDrawer, SidebarProvider, drawerHandle, useSidebar } from "./slots/sidebar.js";
|
|
6
|
+
import { Header } from "./slots/header.js";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { createContext, use, useMemo } from "react";
|
|
9
|
+
//#region src/layouts/glass/index.tsx
|
|
10
|
+
const LayoutContext = createContext(null);
|
|
11
|
+
function useGlassLayout() {
|
|
12
|
+
const context = use(LayoutContext);
|
|
13
|
+
if (!context) throw new Error("Please use Glass layout components under <GlassLayout /> (`fumadocs-ui/layouts/glass`).");
|
|
14
|
+
return context;
|
|
15
|
+
}
|
|
16
|
+
const { useBaseSlots } = baseSlots({ useProps() {
|
|
17
|
+
return useGlassLayout().props;
|
|
18
|
+
} });
|
|
19
|
+
function GlassLayout(props) {
|
|
20
|
+
const { tree, tabs: defaultTabs, aiChat, children, slots: defaultSlots = {} } = props;
|
|
21
|
+
const linkItems = useLinkItems(props);
|
|
22
|
+
const { baseSlots, baseProps } = useBaseSlots(props);
|
|
23
|
+
const tabs = useMemo(() => {
|
|
24
|
+
if (Array.isArray(defaultTabs)) return defaultTabs;
|
|
25
|
+
if (typeof defaultTabs === "object") return getLayoutTabs(tree, defaultTabs);
|
|
26
|
+
if (defaultTabs !== false) return getLayoutTabs(tree);
|
|
27
|
+
return [];
|
|
28
|
+
}, [tree, defaultTabs]);
|
|
29
|
+
const slots = {
|
|
30
|
+
...baseSlots,
|
|
31
|
+
header: defaultSlots.header ?? Header,
|
|
32
|
+
sidebar: defaultSlots.sidebar ?? {
|
|
33
|
+
drawer: SidebarDrawer,
|
|
34
|
+
drawerHandle,
|
|
35
|
+
main: Sidebar,
|
|
36
|
+
provider: SidebarProvider,
|
|
37
|
+
use: useSidebar
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
return /* @__PURE__ */ jsx(LayoutContext, {
|
|
41
|
+
value: {
|
|
42
|
+
props: {
|
|
43
|
+
tabs,
|
|
44
|
+
aiChat,
|
|
45
|
+
...baseProps
|
|
46
|
+
},
|
|
47
|
+
slots,
|
|
48
|
+
...linkItems
|
|
49
|
+
},
|
|
50
|
+
children: /* @__PURE__ */ jsx(slots.sidebar.provider, {
|
|
51
|
+
...props.sidebar,
|
|
52
|
+
children: /* @__PURE__ */ jsx(TreeContextProvider, {
|
|
53
|
+
tree,
|
|
54
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
55
|
+
id: "fd-glass-layout",
|
|
56
|
+
className: "grid overflow-x-clip min-h-dvh [--fd-main-width:900px] [--fd-left-width:0px] [--fd-right-width:0px]",
|
|
57
|
+
style: { gridTemplate: `"left left-margin main right-margin right" 1fr / var(--fd-left-width) calc(50% - var(--fd-main-width)/2 - var(--fd-left-width)) 1fr calc(50% - var(--fd-main-width)/2 - var(--fd-right-width)) var(--fd-right-width)` },
|
|
58
|
+
children: [
|
|
59
|
+
/* @__PURE__ */ jsx(slots.sidebar.drawer, {}),
|
|
60
|
+
/* @__PURE__ */ jsx(slots.sidebar.main, {}),
|
|
61
|
+
/* @__PURE__ */ jsx(slots.header, {}),
|
|
62
|
+
children
|
|
63
|
+
]
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
export { GlassLayout, useGlassLayout };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { cn } from "../../utils/cn.js";
|
|
2
|
+
import { useTreePath } from "../../contexts/tree.js";
|
|
3
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../../components/ui/popover.js";
|
|
4
|
+
import { isLayoutTabActive } from "../shared/index.js";
|
|
5
|
+
import Link from "fumadocs-core/link";
|
|
6
|
+
import { usePathname } from "fumadocs-core/framework";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { ChevronsUpDown } from "lucide-react";
|
|
9
|
+
import { useState } from "react";
|
|
10
|
+
import { useTranslations } from "@fuma-translate/react";
|
|
11
|
+
//#region src/layouts/glass/layout-tabs.tsx
|
|
12
|
+
function LayoutTabsDropdown({ tabs, className, size = "default", ...props }) {
|
|
13
|
+
const path = useTreePath();
|
|
14
|
+
const pathname = usePathname();
|
|
15
|
+
const t = useTranslations();
|
|
16
|
+
const selected = tabs.findLast((t) => isLayoutTabActive(t, path, pathname));
|
|
17
|
+
const [open, setOpen] = useState(false);
|
|
18
|
+
return /* @__PURE__ */ jsxs(Popover, {
|
|
19
|
+
open,
|
|
20
|
+
onOpenChange: setOpen,
|
|
21
|
+
children: [/* @__PURE__ */ jsxs(PopoverTrigger, {
|
|
22
|
+
className: cn("inline-flex items-center gap-2 text-sm font-medium rounded-full transition-colors hover:bg-fd-accent data-popup-open:bg-fd-accent", size === "lg" && "text-[0.9375rem]", className),
|
|
23
|
+
...props,
|
|
24
|
+
children: [selected ? /* @__PURE__ */ jsxs(Fragment, { children: [selected.icon, /* @__PURE__ */ jsx("span", {
|
|
25
|
+
className: "truncate",
|
|
26
|
+
children: selected.title
|
|
27
|
+
})] }) : /* @__PURE__ */ jsx("span", {
|
|
28
|
+
className: "text-fd-muted-foreground truncate",
|
|
29
|
+
children: t("Layout Tab", { note: "layout tab trigger" })
|
|
30
|
+
}), /* @__PURE__ */ jsx(ChevronsUpDown, { className: cn("ms-auto shrink-0 text-fd-muted-foreground", size === "default" && "size-3.5!", size === "lg" && "size-4!") })]
|
|
31
|
+
}), /* @__PURE__ */ jsx(PopoverContent, {
|
|
32
|
+
className: "flex flex-col p-1 rounded-xl",
|
|
33
|
+
align: "start",
|
|
34
|
+
children: tabs.map((t, i) => {
|
|
35
|
+
if (t.unlisted && t !== selected) return;
|
|
36
|
+
return /* @__PURE__ */ jsxs(Link, {
|
|
37
|
+
href: t.url,
|
|
38
|
+
className: cn("text-sm px-2 py-1.5 rounded-lg", selected === t ? "bg-fd-primary/10 text-fd-primary" : "hover:bg-fd-accent hover:text-fd-accent-foreground"),
|
|
39
|
+
onClick: () => setOpen(false),
|
|
40
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
41
|
+
className: "font-medium inline-flex items-center gap-2 [&_svg]:size-4",
|
|
42
|
+
children: [t.icon, t.title]
|
|
43
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
44
|
+
className: cn("mt-1 text-xs text-fd-muted-foreground empty:hidden", selected === t && "text-fd-primary/80"),
|
|
45
|
+
children: t.description
|
|
46
|
+
})]
|
|
47
|
+
}, i);
|
|
48
|
+
})
|
|
49
|
+
})]
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { LayoutTabsDropdown };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { MarkdownCopyButton, ViewOptionsPopover } from "../../shared/page-actions.js";
|
|
2
|
+
import { TOCProps } from "./slots/toc.js";
|
|
3
|
+
import { ComponentProps } from "react";
|
|
4
|
+
import { TOCItemType } from "fumadocs-core/toc";
|
|
5
|
+
//#region src/layouts/glass/page/index.d.ts
|
|
6
|
+
interface DocsPageProps extends ComponentProps<'article'> {
|
|
7
|
+
toc?: TOCItemType[];
|
|
8
|
+
/**
|
|
9
|
+
* Extend the page to fill all available space
|
|
10
|
+
*
|
|
11
|
+
* @defaultValue false
|
|
12
|
+
*/
|
|
13
|
+
full?: boolean | undefined;
|
|
14
|
+
tableOfContent?: TOCProps;
|
|
15
|
+
}
|
|
16
|
+
declare function useDocsPage(): {
|
|
17
|
+
full: boolean;
|
|
18
|
+
};
|
|
19
|
+
declare function DocsPage({ full, toc, tableOfContent, children }: DocsPageProps): import("react").JSX.Element;
|
|
20
|
+
declare function EditOnGitHub(props: ComponentProps<'a'>): import("react").JSX.Element;
|
|
21
|
+
/**
|
|
22
|
+
* Add typography styles
|
|
23
|
+
*/
|
|
24
|
+
declare function DocsBody({ children, className, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
|
|
25
|
+
declare function DocsDescription({ children, className, ...props }: ComponentProps<'p'>): import("react").JSX.Element | null;
|
|
26
|
+
declare function DocsTitle({ children, className, ...props }: ComponentProps<'h1'>): import("react").JSX.Element;
|
|
27
|
+
declare function PageLastUpdate({ date: value, ...props }: Omit<ComponentProps<'p'>, 'children'> & {
|
|
28
|
+
date: Date;
|
|
29
|
+
}): import("react").JSX.Element;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { DocsBody, DocsDescription, DocsPage, DocsPageProps, DocsTitle, EditOnGitHub, MarkdownCopyButton, PageLastUpdate, ViewOptionsPopover, useDocsPage };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../../../utils/cn.js";
|
|
3
|
+
import { buttonVariants } from "../../../components/ui/button.js";
|
|
4
|
+
import { MarkdownCopyButton, ViewOptionsPopover } from "../../shared/page-actions.js";
|
|
5
|
+
import { Footer } from "./slots/footer.js";
|
|
6
|
+
import { Breadcrumb } from "./slots/breadcrumb.js";
|
|
7
|
+
import { TOC, TOCProvider } from "./slots/toc.js";
|
|
8
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { Edit } from "lucide-react";
|
|
10
|
+
import { createContext, use, useEffect, useState } from "react";
|
|
11
|
+
import { useTranslations } from "@fuma-translate/react";
|
|
12
|
+
//#region src/layouts/glass/page/index.tsx
|
|
13
|
+
const PageContext = createContext(null);
|
|
14
|
+
function useDocsPage() {
|
|
15
|
+
const context = use(PageContext);
|
|
16
|
+
if (!context) throw new Error("Please use page components under <DocsPage /> (`fumadocs-ui/layouts/glass/page`).");
|
|
17
|
+
return context;
|
|
18
|
+
}
|
|
19
|
+
const Empty = [];
|
|
20
|
+
function DocsPage({ full = false, toc = Empty, tableOfContent, children }) {
|
|
21
|
+
return /* @__PURE__ */ jsx(PageContext, {
|
|
22
|
+
value: { full },
|
|
23
|
+
children: /* @__PURE__ */ jsxs(TOCProvider, {
|
|
24
|
+
toc,
|
|
25
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
26
|
+
"data-fd-full": full,
|
|
27
|
+
className: cn("flex flex-col gap-2 p-6 pb-16 min-w-0 [grid-area:main] md:pt-16 md:pb-8", full && "layout:[--fd-main-width:1200px]"),
|
|
28
|
+
children: [
|
|
29
|
+
/* @__PURE__ */ jsx(Breadcrumb, {}),
|
|
30
|
+
children,
|
|
31
|
+
/* @__PURE__ */ jsx(Footer, {})
|
|
32
|
+
]
|
|
33
|
+
}), /* @__PURE__ */ jsx(TOC, { ...tableOfContent })]
|
|
34
|
+
})
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function EditOnGitHub(props) {
|
|
38
|
+
const t = useTranslations({ note: "edit page" });
|
|
39
|
+
return /* @__PURE__ */ jsx("a", {
|
|
40
|
+
target: "_blank",
|
|
41
|
+
rel: "noreferrer noopener",
|
|
42
|
+
...props,
|
|
43
|
+
className: cn(buttonVariants({
|
|
44
|
+
color: "secondary",
|
|
45
|
+
size: "sm"
|
|
46
|
+
}), "gap-1.5 not-prose", props.className),
|
|
47
|
+
children: props.children ?? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Edit, { className: "size-3.5" }), t("Edit on GitHub")] })
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Add typography styles
|
|
52
|
+
*/
|
|
53
|
+
function DocsBody({ children, className, ...props }) {
|
|
54
|
+
return /* @__PURE__ */ jsx("div", {
|
|
55
|
+
...props,
|
|
56
|
+
className: cn("prose flex-1", className),
|
|
57
|
+
children
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function DocsDescription({ children, className, ...props }) {
|
|
61
|
+
if (children === void 0) return null;
|
|
62
|
+
return /* @__PURE__ */ jsx("p", {
|
|
63
|
+
...props,
|
|
64
|
+
className: cn("mb-8 text-lg text-fd-muted-foreground", className),
|
|
65
|
+
children
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function DocsTitle({ children, className, ...props }) {
|
|
69
|
+
return /* @__PURE__ */ jsx("h1", {
|
|
70
|
+
...props,
|
|
71
|
+
className: cn("text-[1.75em] font-semibold", className),
|
|
72
|
+
children
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function PageLastUpdate({ date: value, ...props }) {
|
|
76
|
+
const t = useTranslations({ note: "page footer" });
|
|
77
|
+
const [date, setDate] = useState("");
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
setDate(value.toLocaleDateString());
|
|
80
|
+
}, [value]);
|
|
81
|
+
return /* @__PURE__ */ jsxs("p", {
|
|
82
|
+
...props,
|
|
83
|
+
className: cn("text-sm text-fd-muted-foreground", props.className),
|
|
84
|
+
children: [
|
|
85
|
+
t("Last updated on"),
|
|
86
|
+
" ",
|
|
87
|
+
date
|
|
88
|
+
]
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
export { DocsBody, DocsDescription, DocsPage, DocsTitle, EditOnGitHub, MarkdownCopyButton, PageLastUpdate, ViewOptionsPopover, useDocsPage };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ComponentProps } from "react";
|
|
2
|
+
import { BreadcrumbOptions } from "fumadocs-core/breadcrumb";
|
|
3
|
+
//#region src/layouts/glass/page/slots/breadcrumb.d.ts
|
|
4
|
+
type BreadcrumbProps = BreadcrumbOptions & ComponentProps<'div'>;
|
|
5
|
+
declare function Breadcrumb({ includeRoot, includeSeparator, includePage, ...props }: BreadcrumbProps): import("react").JSX.Element | null;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { Breadcrumb, BreadcrumbProps };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../../../../utils/cn.js";
|
|
3
|
+
import { useTreeContext, useTreePath } from "../../../../contexts/tree.js";
|
|
4
|
+
import Link from "fumadocs-core/link";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { ChevronRight } from "lucide-react";
|
|
7
|
+
import { Fragment as Fragment$1, useMemo } from "react";
|
|
8
|
+
import { getBreadcrumbItemsFromPath } from "fumadocs-core/breadcrumb";
|
|
9
|
+
//#region src/layouts/glass/page/slots/breadcrumb.tsx
|
|
10
|
+
function Breadcrumb({ includeRoot, includeSeparator, includePage, ...props }) {
|
|
11
|
+
const path = useTreePath();
|
|
12
|
+
const { root } = useTreeContext();
|
|
13
|
+
const items = useMemo(() => {
|
|
14
|
+
return getBreadcrumbItemsFromPath(root, path, {
|
|
15
|
+
includePage,
|
|
16
|
+
includeSeparator,
|
|
17
|
+
includeRoot
|
|
18
|
+
});
|
|
19
|
+
}, [
|
|
20
|
+
includePage,
|
|
21
|
+
includeRoot,
|
|
22
|
+
includeSeparator,
|
|
23
|
+
path,
|
|
24
|
+
root
|
|
25
|
+
]);
|
|
26
|
+
if (items.length === 0) return null;
|
|
27
|
+
return /* @__PURE__ */ jsx("div", {
|
|
28
|
+
...props,
|
|
29
|
+
className: cn("flex items-center gap-1.5 text-sm text-fd-muted-foreground", props.className),
|
|
30
|
+
children: items.map((item, i) => {
|
|
31
|
+
const className = cn("truncate", i === items.length - 1 && "text-fd-primary font-medium");
|
|
32
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [i !== 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5 shrink-0" }), item.url ? /* @__PURE__ */ jsx(Link, {
|
|
33
|
+
href: item.url,
|
|
34
|
+
className: cn(className, "transition-opacity hover:opacity-80"),
|
|
35
|
+
children: item.name
|
|
36
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
37
|
+
className,
|
|
38
|
+
children: item.name
|
|
39
|
+
})] }, i);
|
|
40
|
+
})
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { Breadcrumb };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ComponentProps } from "react";
|
|
2
|
+
import * as PageTree from "fumadocs-core/page-tree";
|
|
3
|
+
//#region src/layouts/glass/page/slots/footer.d.ts
|
|
4
|
+
type Item = Pick<PageTree.Item, 'name' | 'description' | 'url'>;
|
|
5
|
+
interface FooterProps extends ComponentProps<'div'> {
|
|
6
|
+
/**
|
|
7
|
+
* Items including information for the next and previous page
|
|
8
|
+
*/
|
|
9
|
+
items?: {
|
|
10
|
+
previous?: Item;
|
|
11
|
+
next?: Item;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
declare function Footer({ items, children, className, ...props }: FooterProps): import("react").JSX.Element;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { Footer, FooterProps };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../../../../utils/cn.js";
|
|
3
|
+
import { isActive } from "../../../../utils/urls.js";
|
|
4
|
+
import { useFooterItems } from "../../../../utils/use-footer-items.js";
|
|
5
|
+
import Link from "fumadocs-core/link";
|
|
6
|
+
import { usePathname } from "fumadocs-core/framework";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
9
|
+
import { useMemo } from "react";
|
|
10
|
+
import { useTranslations } from "@fuma-translate/react";
|
|
11
|
+
//#region src/layouts/glass/page/slots/footer.tsx
|
|
12
|
+
function Footer({ items, children, className, ...props }) {
|
|
13
|
+
const footerList = useFooterItems();
|
|
14
|
+
const pathname = usePathname();
|
|
15
|
+
const { previous, next } = useMemo(() => {
|
|
16
|
+
if (items) return items;
|
|
17
|
+
const idx = footerList.findIndex((item) => isActive(item.url, pathname));
|
|
18
|
+
if (idx === -1) return {};
|
|
19
|
+
return {
|
|
20
|
+
previous: footerList[idx - 1],
|
|
21
|
+
next: footerList[idx + 1]
|
|
22
|
+
};
|
|
23
|
+
}, [
|
|
24
|
+
footerList,
|
|
25
|
+
items,
|
|
26
|
+
pathname
|
|
27
|
+
]);
|
|
28
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
29
|
+
className: cn("@container grid gap-4", previous && next ? "grid-cols-2" : "grid-cols-1", className),
|
|
30
|
+
...props,
|
|
31
|
+
children: [previous && /* @__PURE__ */ jsx(FooterItem, {
|
|
32
|
+
item: previous,
|
|
33
|
+
index: 0
|
|
34
|
+
}), next && /* @__PURE__ */ jsx(FooterItem, {
|
|
35
|
+
item: next,
|
|
36
|
+
index: 1
|
|
37
|
+
})]
|
|
38
|
+
}), children] });
|
|
39
|
+
}
|
|
40
|
+
function FooterItem({ item, index }) {
|
|
41
|
+
const t = useTranslations({ note: "pagination" });
|
|
42
|
+
const Icon = index === 0 ? ChevronLeft : ChevronRight;
|
|
43
|
+
return /* @__PURE__ */ jsxs(Link, {
|
|
44
|
+
href: item.url,
|
|
45
|
+
className: cn("flex flex-col gap-2 rounded-lg border p-4 text-sm transition-colors hover:bg-fd-accent/80 hover:text-fd-accent-foreground @max-lg:col-span-full", index === 1 && "text-end"),
|
|
46
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
47
|
+
className: cn("inline-flex items-center gap-1.5 font-medium", index === 1 && "flex-row-reverse"),
|
|
48
|
+
children: [/* @__PURE__ */ jsx(Icon, { className: "-mx-1 size-4 shrink-0 rtl:rotate-180" }), /* @__PURE__ */ jsx("p", { children: item.name })]
|
|
49
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
50
|
+
className: "text-fd-muted-foreground truncate",
|
|
51
|
+
children: item.description ?? (index === 0 ? t("Previous Page") : t("Next Page"))
|
|
52
|
+
})]
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { Footer };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { TOCProviderProps as TOCProviderProps$1 } from "../../../../components/toc/index.js";
|
|
2
|
+
import { ComponentProps, ReactNode } from "react";
|
|
3
|
+
//#region src/layouts/glass/page/slots/toc.d.ts
|
|
4
|
+
type TOCProviderProps = TOCProviderProps$1;
|
|
5
|
+
declare function TOCProvider(props: TOCProviderProps): import("react").JSX.Element;
|
|
6
|
+
interface TOCProps {
|
|
7
|
+
container?: ComponentProps<'div'>;
|
|
8
|
+
/**
|
|
9
|
+
* Custom content in TOC container, before the main TOC
|
|
10
|
+
*/
|
|
11
|
+
header?: ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* Custom content in TOC container, after the main TOC
|
|
14
|
+
*/
|
|
15
|
+
footer?: ReactNode;
|
|
16
|
+
}
|
|
17
|
+
declare function TOC({ container, header, footer }: TOCProps): import("react").JSX.Element | undefined;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { TOC, TOCProps, TOCProvider, TOCProviderProps };
|