fumadocs-ui 13.2.2 → 13.3.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.
@@ -1,4 +1,7 @@
1
1
  "use client";
2
+ import {
3
+ useTocThumb
4
+ } from "./chunk-P4HLRHHV.js";
2
5
  import {
3
6
  useTreeContext
4
7
  } from "./chunk-LSTPTAZ5.js";
@@ -21,7 +24,7 @@ import {
21
24
  import "./chunk-MLKGABMK.js";
22
25
 
23
26
  // src/page.client.tsx
24
- import { useEffect, useMemo as useMemo2, useState as useState2 } from "react";
27
+ import { useEffect, useMemo as useMemo2, useState } from "react";
25
28
  import { ChevronLeft, ChevronRight as ChevronRight3 } from "lucide-react";
26
29
  import Link2 from "next/link";
27
30
  import { usePathname as usePathname2 } from "next/navigation";
@@ -30,15 +33,9 @@ import { cva } from "class-variance-authority";
30
33
  // src/components/layout/toc.tsx
31
34
  import { ChevronRight, Text } from "lucide-react";
32
35
  import * as Primitive from "fumadocs-core/toc";
33
- import {
34
- useLayoutEffect,
35
- useMemo,
36
- useRef,
37
- useState
38
- } from "react";
36
+ import { useMemo, useRef } from "react";
39
37
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
40
- var TocProvider = Primitive.AnchorProvider;
41
- function Toc({ items, header, footer }) {
38
+ function Toc({ header, footer, children }) {
42
39
  const { text } = useI18n();
43
40
  return /* @__PURE__ */ jsxs(
44
41
  "div",
@@ -51,18 +48,22 @@ function Toc({ items, header, footer }) {
51
48
  /* @__PURE__ */ jsx(Text, { className: "size-4" }),
52
49
  text.toc
53
50
  ] }),
54
- /* @__PURE__ */ jsx(TOCItems, { items }),
51
+ children,
55
52
  footer
56
53
  ]
57
54
  }
58
55
  );
59
56
  }
60
- function TocPopover({ items, header, footer }) {
57
+ function TocPopover({
58
+ header,
59
+ footer,
60
+ items,
61
+ children
62
+ }) {
61
63
  const { text } = useI18n();
62
64
  const active = Primitive.useActiveAnchor();
63
65
  const current = useMemo(() => {
64
- if (!active) return;
65
- return items.find((item) => item.url === `#${active}`)?.title;
66
+ return items.find((item) => active === item.url.slice(1))?.title;
66
67
  }, [items, active]);
67
68
  return /* @__PURE__ */ jsxs(Popover, { children: [
68
69
  /* @__PURE__ */ jsxs(PopoverTrigger, { className: "inline-flex size-full items-center gap-2 text-nowrap px-4 py-2 text-left md:px-3", children: [
@@ -84,7 +85,7 @@ function TocPopover({ items, header, footer }) {
84
85
  "data-toc-popover": "",
85
86
  children: [
86
87
  header,
87
- /* @__PURE__ */ jsx(TOCItems, { items, isMenu: true }),
88
+ children,
88
89
  footer
89
90
  ]
90
91
  }
@@ -97,17 +98,7 @@ function TOCItems({
97
98
  }) {
98
99
  const { text } = useI18n();
99
100
  const containerRef = useRef(null);
100
- const [pos, setPos] = useState();
101
- const active = Primitive.useActiveAnchor();
102
- useLayoutEffect(() => {
103
- const container = containerRef.current;
104
- if (!active || !container) return;
105
- const element = container.querySelector(
106
- `a[href="#${active}"]`
107
- );
108
- if (!element) return;
109
- setPos([element.offsetTop, element.clientHeight]);
110
- }, [active]);
101
+ const pos = useTocThumb(containerRef);
111
102
  if (items.length === 0)
112
103
  return /* @__PURE__ */ jsx("div", { className: "rounded-lg border bg-fd-card p-3 text-xs text-fd-muted-foreground", children: text.tocNoHeadings });
113
104
  return /* @__PURE__ */ jsx(ScrollArea, { className: twMerge("flex flex-col", isMenu && "-ms-3"), children: /* @__PURE__ */ jsxs(ScrollViewport, { className: "relative min-h-0 text-sm", ref: containerRef, children: [
@@ -115,11 +106,10 @@ function TOCItems({
115
106
  "div",
116
107
  {
117
108
  role: "none",
118
- className: "absolute start-0 w-0.5 bg-fd-primary transition-all",
109
+ className: "absolute start-0 w-px bg-fd-primary transition-all",
119
110
  style: {
120
- top: pos ? `${pos[0].toString()}px` : void 0,
121
- height: pos ? `${pos[1].toString()}px` : void 0,
122
- display: pos ? "block" : "hidden"
111
+ top: pos[0],
112
+ height: pos[1]
123
113
  }
124
114
  }
125
115
  ),
@@ -127,8 +117,8 @@ function TOCItems({
127
117
  "div",
128
118
  {
129
119
  className: twMerge(
130
- "flex flex-col gap-1 text-fd-muted-foreground",
131
- !isMenu && "border-s-2 border-fd-foreground/10"
120
+ "flex flex-col text-fd-muted-foreground",
121
+ !isMenu && "border-s border-fd-foreground/10"
132
122
  ),
133
123
  children: items.map((item) => /* @__PURE__ */ jsx(TOCItem2, { item }, item.url))
134
124
  }
@@ -141,10 +131,10 @@ function TOCItem2({ item }) {
141
131
  {
142
132
  href: item.url,
143
133
  className: twMerge(
144
- "py-1 transition-colors [overflow-wrap:anywhere] data-[active=true]:font-medium data-[active=true]:text-fd-primary",
145
- item.depth <= 2 && "ps-4",
146
- item.depth === 3 && "ps-7",
147
- item.depth >= 4 && "ps-10"
134
+ "py-1.5 transition-colors [overflow-wrap:anywhere] first:pt-0 last:pb-0 data-[active=true]:text-fd-primary",
135
+ item.depth <= 2 && "ps-3.5",
136
+ item.depth === 3 && "ps-6",
137
+ item.depth >= 4 && "ps-8"
148
138
  ),
149
139
  children: item.title
150
140
  }
@@ -153,7 +143,9 @@ function TOCItem2({ item }) {
153
143
 
154
144
  // src/components/layout/breadcrumb.tsx
155
145
  import { ChevronRight as ChevronRight2 } from "lucide-react";
156
- import { useBreadcrumb } from "fumadocs-core/breadcrumb";
146
+ import {
147
+ useBreadcrumb
148
+ } from "fumadocs-core/breadcrumb";
157
149
  import Link from "next/link";
158
150
  import { usePathname } from "next/navigation";
159
151
  import { Fragment as Fragment2 } from "react";
@@ -168,33 +160,25 @@ function Breadcrumb({
168
160
  includePage: full,
169
161
  ...options
170
162
  });
171
- return /* @__PURE__ */ jsx2(
172
- "div",
173
- {
174
- className: twMerge(
175
- "-mb-3 flex flex-row items-center gap-1 text-sm font-medium text-fd-muted-foreground",
176
- items.length === 0 && "hidden"
177
- ),
178
- children: items.map((item, i) => /* @__PURE__ */ jsxs2(Fragment2, { children: [
179
- i !== 0 && /* @__PURE__ */ jsx2(ChevronRight2, { className: "size-4 shrink-0 rtl:rotate-180" }),
180
- item.url ? /* @__PURE__ */ jsx2(
181
- Link,
182
- {
183
- href: item.url,
184
- className: "truncate hover:text-fd-accent-foreground",
185
- children: item.name
186
- }
187
- ) : /* @__PURE__ */ jsx2("span", { className: "truncate", children: item.name })
188
- ] }, i))
189
- }
190
- );
163
+ if (items.length === 0) return null;
164
+ return /* @__PURE__ */ jsx2("div", { className: "-mb-3 flex flex-row items-center gap-1 text-sm font-medium text-fd-muted-foreground", children: items.map((item, i) => /* @__PURE__ */ jsxs2(Fragment2, { children: [
165
+ i !== 0 && /* @__PURE__ */ jsx2(ChevronRight2, { className: "size-4 shrink-0 rtl:rotate-180" }),
166
+ item.url ? /* @__PURE__ */ jsx2(
167
+ Link,
168
+ {
169
+ href: item.url,
170
+ className: "truncate hover:text-fd-accent-foreground",
171
+ children: item.name
172
+ }
173
+ ) : /* @__PURE__ */ jsx2("span", { className: "truncate", children: item.name })
174
+ ] }, i)) });
191
175
  }
192
176
 
193
177
  // src/page.client.tsx
194
178
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
195
179
  function LastUpdate(props) {
196
180
  const { text } = useI18n();
197
- const [date, setDate] = useState2("");
181
+ const [date, setDate] = useState("");
198
182
  useEffect(() => {
199
183
  setDate(props.date.toLocaleDateString());
200
184
  }, [props.date]);
@@ -249,7 +233,7 @@ export {
249
233
  Breadcrumb,
250
234
  Footer,
251
235
  LastUpdate,
236
+ TOCItems,
252
237
  Toc,
253
- TocPopover,
254
- TocProvider
238
+ TocPopover
255
239
  };
package/dist/page.d.ts CHANGED
@@ -1,14 +1,20 @@
1
- import * as React$1 from 'react';
1
+ import * as react from 'react';
2
2
  import { ReactNode, HTMLAttributes } from 'react';
3
3
  import { TableOfContents } from 'fumadocs-core/server';
4
+ import { Page } from 'fumadocs-core/source';
5
+ import { AnchorProviderProps } from 'fumadocs-core/toc';
4
6
  import { TOCProps, BreadcrumbProps, FooterProps } from './page.client.js';
5
- import 'fumadocs-core/toc';
6
7
  import 'fumadocs-core/breadcrumb';
7
8
 
8
- type TableOfContentOptions = Omit<TOCProps, 'items'> & {
9
+ type TableOfContentOptions = Omit<TOCProps, 'items' | 'children'> & Pick<AnchorProviderProps, 'single'> & {
9
10
  enabled: boolean;
10
11
  component: ReactNode;
12
+ /**
13
+ * @defaultValue 'normal'
14
+ */
15
+ style?: 'normal' | 'clerk';
11
16
  };
17
+ type TableOfContentPopoverOptions = Omit<TableOfContentOptions, 'single'>;
12
18
  interface BreadcrumbOptions extends BreadcrumbProps {
13
19
  enabled: boolean;
14
20
  component: ReactNode;
@@ -26,7 +32,7 @@ interface DocsPageProps {
26
32
  */
27
33
  full?: boolean;
28
34
  tableOfContent?: Partial<TableOfContentOptions>;
29
- tableOfContentPopover?: Partial<TableOfContentOptions>;
35
+ tableOfContentPopover?: Partial<TableOfContentPopoverOptions>;
30
36
  /**
31
37
  * Replace or disable breadcrumb
32
38
  */
@@ -42,7 +48,13 @@ declare function DocsPage({ toc, tableOfContent, breadcrumb, tableOfContentPopov
42
48
  /**
43
49
  * Add typography styles
44
50
  */
45
- declare const DocsBody: React$1.ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
51
+ declare const DocsBody: react.ForwardRefExoticComponent<HTMLAttributes<HTMLDivElement> & react.RefAttributes<HTMLDivElement>>;
52
+ declare const DocsDescription: react.ForwardRefExoticComponent<HTMLAttributes<HTMLParagraphElement> & react.RefAttributes<HTMLParagraphElement>>;
53
+ declare const DocsTitle: react.ForwardRefExoticComponent<HTMLAttributes<HTMLHeadingElement> & react.RefAttributes<HTMLHeadingElement>>;
54
+ declare function DocsCategory({ page, pages, ...props }: HTMLAttributes<HTMLDivElement> & {
55
+ page: Page;
56
+ pages: Page[];
57
+ }): React.ReactElement;
46
58
  /**
47
59
  * For separate MDX page
48
60
  */
@@ -50,4 +62,4 @@ declare function withArticle({ children, }: {
50
62
  children: React.ReactNode;
51
63
  }): React.ReactElement;
52
64
 
53
- export { DocsBody, DocsPage, type DocsPageProps, withArticle };
65
+ export { DocsBody, DocsCategory, DocsDescription, DocsPage, type DocsPageProps, DocsTitle, withArticle };
package/dist/page.js CHANGED
@@ -3,12 +3,16 @@ import {
3
3
  TocPopover,
4
4
  Breadcrumb,
5
5
  Footer,
6
- TocProvider,
6
+ TOCItems,
7
7
  LastUpdate,
8
8
  } from "./page.client"
9
9
  import {
10
10
  replaceOrDefault
11
11
  } from "./chunk-UOD2T27N.js";
12
+ import {
13
+ Card,
14
+ Cards
15
+ } from "./chunk-WLTWFYQA.js";
12
16
  import {
13
17
  twMerge
14
18
  } from "./chunk-TK3TM3MR.js";
@@ -16,7 +20,10 @@ import "./chunk-MLKGABMK.js";
16
20
 
17
21
  // src/page.tsx
18
22
  import { forwardRef } from "react";
23
+ import dynamic from "next/dynamic";
24
+ import { AnchorProvider } from "fumadocs-core/toc";
19
25
  import { jsx, jsxs } from "react/jsx-runtime";
26
+ var ClerkTOCItems = dynamic(() => import("./toc-clerk-RXJ32UXT.js"));
20
27
  function DocsPage({
21
28
  toc = [],
22
29
  tableOfContent = {},
@@ -32,7 +39,7 @@ function DocsPage({
32
39
  enabled: tableOfContent.enabled ?? !full,
33
40
  ...tableOfContent
34
41
  };
35
- return /* @__PURE__ */ jsxs(TocProvider, { toc, children: [
42
+ return /* @__PURE__ */ jsxs(AnchorProvider, { toc, single: tableOfContent.single, children: [
36
43
  /* @__PURE__ */ jsxs(
37
44
  "div",
38
45
  {
@@ -56,7 +63,8 @@ function DocsPage({
56
63
  {
57
64
  items: toc,
58
65
  header: tocPopoverOptions.header,
59
- footer: tocPopoverOptions.footer
66
+ footer: tocPopoverOptions.footer,
67
+ children: tocPopoverOptions.style === "clerk" ? /* @__PURE__ */ jsx(ClerkTOCItems, { items: toc, isMenu: true }) : /* @__PURE__ */ jsx(TOCItems, { items: toc, isMenu: true })
60
68
  }
61
69
  )
62
70
  }
@@ -74,19 +82,56 @@ function DocsPage({
74
82
  ),
75
83
  replaceOrDefault(
76
84
  tocOptions,
77
- /* @__PURE__ */ jsx(
78
- Toc,
79
- {
80
- items: toc,
81
- header: tocOptions.header,
82
- footer: tocOptions.footer
83
- }
84
- )
85
+ /* @__PURE__ */ jsx(Toc, { header: tocOptions.header, footer: tocOptions.footer, children: tocOptions.style === "clerk" ? /* @__PURE__ */ jsx(ClerkTOCItems, { items: toc }) : /* @__PURE__ */ jsx(TOCItems, { items: toc }) })
85
86
  )
86
87
  ] });
87
88
  }
88
89
  var DocsBody = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: twMerge("prose", className), ...props }));
89
90
  DocsBody.displayName = "DocsBody";
91
+ var DocsDescription = forwardRef((props, ref) => {
92
+ if (props.children === void 0) return null;
93
+ return /* @__PURE__ */ jsx(
94
+ "p",
95
+ {
96
+ ref,
97
+ ...props,
98
+ className: twMerge("mb-8 text-lg text-fd-muted-foreground", props.className),
99
+ children: props.children
100
+ }
101
+ );
102
+ });
103
+ DocsDescription.displayName = "DocsDescription";
104
+ var DocsTitle = forwardRef((props, ref) => {
105
+ return /* @__PURE__ */ jsx(
106
+ "h1",
107
+ {
108
+ ref,
109
+ ...props,
110
+ className: twMerge("text-3xl font-bold", props.className),
111
+ children: props.children
112
+ }
113
+ );
114
+ });
115
+ DocsTitle.displayName = "DocsTitle";
116
+ function DocsCategory({
117
+ page,
118
+ pages,
119
+ ...props
120
+ }) {
121
+ const filtered = pages.filter(
122
+ (item) => item.file.dirname === page.file.dirname && item.file.name !== page.file.name
123
+ );
124
+ return /* @__PURE__ */ jsx(Cards, { ...props, children: filtered.map((item) => /* @__PURE__ */ jsx(
125
+ Card,
126
+ {
127
+ title: item.data.title,
128
+ description: item.data.description ?? "No Description",
129
+ href: item.url
130
+ },
131
+ item.url
132
+ )) });
133
+ }
134
+ DocsBody.displayName = "DocsBody";
90
135
  function withArticle({
91
136
  children
92
137
  }) {
@@ -94,6 +139,9 @@ function withArticle({
94
139
  }
95
140
  export {
96
141
  DocsBody,
142
+ DocsCategory,
143
+ DocsDescription,
97
144
  DocsPage,
145
+ DocsTitle,
98
146
  withArticle
99
147
  };
@@ -1,4 +1,4 @@
1
- import * as React$1 from 'react';
1
+ import * as react from 'react';
2
2
  import { MutableRefObject, ReactNode } from 'react';
3
3
  import { ThemeProviderProps } from 'next-themes/dist/types';
4
4
  import { DefaultSearchDialogProps } from './components/dialog/search-default.js';
@@ -61,7 +61,7 @@ interface SidebarContext {
61
61
  */
62
62
  closeOnRedirect: MutableRefObject<boolean>;
63
63
  }
64
- declare const SidebarContext: React$1.Context<SidebarContext | undefined>;
64
+ declare const SidebarContext: react.Context<SidebarContext | undefined>;
65
65
  declare function useSidebar(): SidebarContext;
66
66
 
67
67
  interface SearchOptions extends Omit<SearchProviderProps, 'options' | 'children'> {