fumadocs-ui 9.0.0 → 10.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.
@@ -20,24 +20,10 @@ function hasActive(items, url) {
20
20
  return false;
21
21
  });
22
22
  }
23
- function flattenTree(tree) {
24
- return tree.flatMap((node) => {
25
- if (node.type === "separator")
26
- return [];
27
- if (node.type === "folder") {
28
- const children = flattenTree(node.children);
29
- if (!node.root && node.index)
30
- return [node.index, ...children];
31
- return children;
32
- }
33
- return [node];
34
- });
35
- }
36
23
 
37
24
  export {
38
25
  defaultImageSizes,
39
26
  isActive,
40
27
  replaceOrDefault,
41
- hasActive,
42
- flattenTree
28
+ hasActive
43
29
  };
@@ -1,7 +1,6 @@
1
1
  import {
2
- flattenTree,
3
2
  hasActive
4
- } from "./chunk-EDUYFB4P.js";
3
+ } from "./chunk-7F2LGCS6.js";
5
4
 
6
5
  // src/contexts/tree.tsx
7
6
  import { usePathname } from "next/navigation";
@@ -20,6 +19,19 @@ function findRoot(items, pathname) {
20
19
  }
21
20
  }
22
21
  }
22
+ function getNavigationList(tree) {
23
+ return tree.flatMap((node) => {
24
+ if (node.type === "separator")
25
+ return [];
26
+ if (node.type === "folder") {
27
+ const children = getNavigationList(node.children);
28
+ if (!node.root && node.index)
29
+ children.unshift(node.index);
30
+ return children;
31
+ }
32
+ return !node.external ? [node] : [];
33
+ });
34
+ }
23
35
  function TreeContextProvider({
24
36
  children,
25
37
  tree
@@ -27,10 +39,9 @@ function TreeContextProvider({
27
39
  const pathname = usePathname();
28
40
  const value = useMemo(() => {
29
41
  const root = findRoot(tree.children, pathname) ?? tree;
30
- const list = flattenTree(root.children);
31
42
  return {
32
43
  root,
33
- list,
44
+ navigation: getNavigationList(root.children),
34
45
  tree
35
46
  };
36
47
  }, [pathname, tree]);
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  defaultImageSizes
4
- } from "../chunk-EDUYFB4P.js";
4
+ } from "../chunk-7F2LGCS6.js";
5
5
  import "../chunk-6C3VEZWH.js";
6
6
 
7
7
  // src/components/image-zoom.tsx
@@ -7,7 +7,7 @@ interface ObjectType {
7
7
  /**
8
8
  * Additional description of the field
9
9
  */
10
- description?: string;
10
+ description?: ReactNode;
11
11
  type: string;
12
12
  typeDescription?: string;
13
13
  /**
@@ -12,37 +12,42 @@ import "../chunk-6C3VEZWH.js";
12
12
  // src/components/type-table.tsx
13
13
  import { InfoIcon } from "lucide-react";
14
14
  import Link from "next/link";
15
+ import { cva } from "class-variance-authority";
15
16
  import { jsx, jsxs } from "react/jsx-runtime";
16
17
  function Info({ children }) {
17
18
  return /* @__PURE__ */ jsxs(Popover, { children: [
18
19
  /* @__PURE__ */ jsx(PopoverTrigger, { children: /* @__PURE__ */ jsx(InfoIcon, { className: "size-4" }) }),
19
- /* @__PURE__ */ jsx(PopoverContent, { className: "text-sm", children })
20
+ /* @__PURE__ */ jsx(PopoverContent, { className: "prose text-sm", children })
20
21
  ] });
21
22
  }
23
+ var th = cva("p-2 font-medium first:pl-0 last:pr-0");
24
+ var td = cva("p-2 first:pl-0 last:pr-0");
25
+ var field = cva("inline-flex flex-row items-center gap-1");
26
+ var code = cva("rounded-md bg-secondary p-1 text-secondary-foreground", {
27
+ variants: {
28
+ color: { primary: "bg-primary/10 text-primary" }
29
+ }
30
+ });
22
31
  function TypeTable({
23
32
  type
24
33
  }) {
25
- const th = twMerge("p-2 font-medium first:pl-0 last:pr-0");
26
- const td = twMerge("p-2 first:pl-0 last:pr-0");
27
- const field = twMerge("inline-flex flex-row items-center gap-1");
28
- const code = twMerge("rounded-md bg-secondary p-1 text-secondary-foreground");
29
34
  return /* @__PURE__ */ jsx("div", { className: "not-prose overflow-auto whitespace-nowrap", children: /* @__PURE__ */ jsxs("table", { className: "my-4 w-full text-left text-sm text-muted-foreground", children: [
30
35
  /* @__PURE__ */ jsx("thead", { className: "border-b", children: /* @__PURE__ */ jsxs("tr", { children: [
31
- /* @__PURE__ */ jsx("th", { className: twMerge(th, "w-[45%]"), children: "Prop" }),
32
- /* @__PURE__ */ jsx("th", { className: twMerge(th, "w-[30%]"), children: "Type" }),
33
- /* @__PURE__ */ jsx("th", { className: twMerge(th, "w-[25%]"), children: "Default" })
36
+ /* @__PURE__ */ jsx("th", { className: twMerge(th(), "w-[45%]"), children: "Prop" }),
37
+ /* @__PURE__ */ jsx("th", { className: twMerge(th(), "w-[30%]"), children: "Type" }),
38
+ /* @__PURE__ */ jsx("th", { className: twMerge(th(), "w-[25%]"), children: "Default" })
34
39
  ] }) }),
35
40
  /* @__PURE__ */ jsx("tbody", { className: "border-collapse divide-y divide-border", children: Object.entries(type).map(([key, value]) => /* @__PURE__ */ jsxs("tr", { children: [
36
- /* @__PURE__ */ jsx("td", { className: td, children: /* @__PURE__ */ jsxs("div", { className: field, children: [
37
- /* @__PURE__ */ jsx("code", { className: twMerge(code, "bg-primary/10 text-primary"), children: key }),
41
+ /* @__PURE__ */ jsx("td", { className: td(), children: /* @__PURE__ */ jsxs("div", { className: field(), children: [
42
+ /* @__PURE__ */ jsx("code", { className: twMerge(code({ color: "primary" })), children: key }),
38
43
  value.description ? /* @__PURE__ */ jsx(Info, { children: value.description }) : null
39
44
  ] }) }),
40
- /* @__PURE__ */ jsx("td", { className: td, children: /* @__PURE__ */ jsxs("div", { className: field, children: [
41
- /* @__PURE__ */ jsx("code", { className: code, children: value.type }),
45
+ /* @__PURE__ */ jsx("td", { className: td(), children: /* @__PURE__ */ jsxs("div", { className: field(), children: [
46
+ /* @__PURE__ */ jsx("code", { className: code(), children: value.type }),
42
47
  value.typeDescription ? /* @__PURE__ */ jsx(Info, { children: /* @__PURE__ */ jsx("pre", { className: "overflow-auto bg-secondary text-secondary-foreground", children: value.typeDescription }) }) : null,
43
48
  value.typeDescriptionLink ? /* @__PURE__ */ jsx(Link, { href: value.typeDescriptionLink, children: /* @__PURE__ */ jsx(InfoIcon, { className: "size-4" }) }) : null
44
49
  ] }) }),
45
- /* @__PURE__ */ jsx("td", { className: td, children: value.default ? /* @__PURE__ */ jsx("code", { className: code, children: value.default }) : /* @__PURE__ */ jsx("span", { children: "-" }) })
50
+ /* @__PURE__ */ jsx("td", { className: td(), children: value.default ? /* @__PURE__ */ jsx("code", { className: code(), children: value.default }) : /* @__PURE__ */ jsx("span", { children: "-" }) })
46
51
  ] }, key)) })
47
52
  ] }) });
48
53
  }
@@ -1,5 +1,5 @@
1
1
  import { PageTree } from 'fumadocs-core/server';
2
- import { ReactNode, HTMLAttributes } from 'react';
2
+ import { ReactNode, FC, HTMLAttributes } from 'react';
3
3
 
4
4
  interface NavLinkProps {
5
5
  icon: ReactNode;
@@ -36,10 +36,23 @@ interface SidebarProps {
36
36
  * @defaultValue 1
37
37
  */
38
38
  defaultOpenLevel?: number;
39
+ components?: Partial<Components>;
39
40
  banner?: ReactNode;
40
41
  footer?: ReactNode;
41
42
  }
42
- declare function Sidebar({ banner, footer, items, defaultOpenLevel, }: SidebarProps): JSX.Element;
43
+ interface Components {
44
+ Item: FC<{
45
+ item: PageTree.Item;
46
+ }>;
47
+ Folder: FC<{
48
+ item: PageTree.Folder;
49
+ level: number;
50
+ }>;
51
+ Separator: FC<{
52
+ item: PageTree.Separator;
53
+ }>;
54
+ }
55
+ declare function Sidebar({ banner, footer, components, items, defaultOpenLevel, }: SidebarProps): JSX.Element;
43
56
 
44
57
  interface LinkItem {
45
58
  url: string;
@@ -1,4 +1,4 @@
1
- export { T as TreeContextProvider } from './tree-Zwtp9xPv.mjs';
2
- export { N as Nav, S as Sidebar } from './layout-YB7EFpgW.mjs';
1
+ export { T as TreeContextProvider } from './tree-ersey5_u.mjs';
2
+ export { N as Nav, S as Sidebar } from './layout-W7dJ6OHQ.mjs';
3
3
  import 'fumadocs-core/server';
4
4
  import 'react';
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  TreeContextProvider,
7
7
  useTreeContext
8
- } from "./chunk-UIZNMCLD.js";
8
+ } from "./chunk-C4PI62MH.js";
9
9
  import {
10
10
  ScrollArea
11
11
  } from "./chunk-ZOR33LFA.js";
@@ -17,7 +17,7 @@ import {
17
17
  import {
18
18
  hasActive,
19
19
  isActive
20
- } from "./chunk-EDUYFB4P.js";
20
+ } from "./chunk-7F2LGCS6.js";
21
21
  import {
22
22
  useSearchContext
23
23
  } from "./chunk-36MVEJ25.js";
@@ -286,7 +286,7 @@ NavItem.displayName = "NavItem";
286
286
 
287
287
  // src/components/sidebar.tsx
288
288
  import { cva as cva3 } from "class-variance-authority";
289
- import { ChevronDown } from "lucide-react";
289
+ import { ChevronDown, ExternalLinkIcon } from "lucide-react";
290
290
  import * as Base from "fumadocs-core/sidebar";
291
291
  import { usePathname as usePathname2 } from "next/navigation";
292
292
  import { createContext, useContext, useEffect as useEffect2, useMemo, useState as useState2 } from "react";
@@ -303,17 +303,31 @@ var itemVariants = cva3(
303
303
  }
304
304
  }
305
305
  );
306
+ var defaultComponents = {
307
+ Folder: FolderNode,
308
+ Separator: SeparatorNode,
309
+ Item: ({ item: { name, ...rest } }) => /* @__PURE__ */ jsx3(BaseItem, { item: { text: name, ...rest } })
310
+ };
306
311
  var SidebarContext = createContext({
307
- defaultOpenLevel: 1
312
+ defaultOpenLevel: 1,
313
+ components: defaultComponents
308
314
  });
309
315
  function Sidebar({
310
316
  banner,
311
317
  footer,
318
+ components,
312
319
  items = [],
313
320
  defaultOpenLevel = 1
314
321
  }) {
315
322
  const [open] = useSidebarCollapse();
316
323
  const { root } = useTreeContext();
324
+ const context = useMemo(
325
+ () => ({
326
+ defaultOpenLevel,
327
+ components: { ...defaultComponents, ...components }
328
+ }),
329
+ [components, defaultOpenLevel]
330
+ );
317
331
  return /* @__PURE__ */ jsx3(
318
332
  Base.SidebarList,
319
333
  {
@@ -323,10 +337,10 @@ function Sidebar({
323
337
  !open ? "md:hidden" : "md:sticky md:top-16 md:h-body md:w-[240px] md:text-sm xl:w-[260px]",
324
338
  "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"
325
339
  ),
326
- children: /* @__PURE__ */ jsxs3(SidebarContext.Provider, { value: { defaultOpenLevel }, children: [
340
+ children: /* @__PURE__ */ jsxs3(SidebarContext.Provider, { value: context, children: [
327
341
  /* @__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: [
328
342
  banner,
329
- /* @__PURE__ */ jsx3("div", { className: "lg:hidden", children: items.map((item) => /* @__PURE__ */ jsx3(BaseItem, { item, nested: true }, item.url)) }),
343
+ items.length > 0 && /* @__PURE__ */ jsx3("div", { className: "lg:hidden", children: items.map((item) => /* @__PURE__ */ jsx3(BaseItem, { item, nested: true }, item.url)) }),
330
344
  /* @__PURE__ */ jsx3(NodeList, { items: root.children })
331
345
  ] }) }),
332
346
  /* @__PURE__ */ jsxs3(
@@ -347,21 +361,16 @@ function Sidebar({
347
361
  );
348
362
  }
349
363
  function NodeList({ items, level = 0, ...props }) {
364
+ const { components } = useContext(SidebarContext);
350
365
  return /* @__PURE__ */ jsx3("div", { ...props, children: items.map((item) => {
351
366
  const id = `${item.type}_${item.name}`;
352
367
  switch (item.type) {
353
368
  case "separator":
354
- return /* @__PURE__ */ jsx3(SeparatorNode, { item }, id);
369
+ return /* @__PURE__ */ jsx3(components.Separator, { item }, id);
355
370
  case "folder":
356
- return /* @__PURE__ */ jsx3(Folder, { item, level: level + 1 }, id);
371
+ return /* @__PURE__ */ jsx3(components.Folder, { item, level: level + 1 }, id);
357
372
  default:
358
- return /* @__PURE__ */ jsx3(
359
- BaseItem,
360
- {
361
- item: { text: item.name, url: item.url, icon: item.icon }
362
- },
363
- item.url
364
- );
373
+ return /* @__PURE__ */ jsx3(components.Item, { item }, item.url);
365
374
  }
366
375
  }) });
367
376
  }
@@ -371,6 +380,7 @@ function BaseItem({
371
380
  }) {
372
381
  const pathname = usePathname2();
373
382
  const active = isActive(item.url, pathname, nested);
383
+ const defaultIcon = item.external ? /* @__PURE__ */ jsx3(ExternalLinkIcon, {}) : null;
374
384
  return /* @__PURE__ */ jsxs3(
375
385
  Link2,
376
386
  {
@@ -378,14 +388,14 @@ function BaseItem({
378
388
  external: item.external,
379
389
  className: twMerge(itemVariants({ active })),
380
390
  children: [
381
- item.icon,
391
+ item.icon ?? defaultIcon,
382
392
  item.text
383
393
  ]
384
394
  }
385
395
  );
386
396
  }
387
- function Folder({
388
- item: { name, children, index, icon },
397
+ function FolderNode({
398
+ item: { name, children, index, icon, defaultOpen = false },
389
399
  level
390
400
  }) {
391
401
  const { defaultOpenLevel } = useContext(SidebarContext);
@@ -396,7 +406,7 @@ function Folder({
396
406
  [children, pathname]
397
407
  );
398
408
  const [extend, setExtend] = useState2(
399
- active || childActive || defaultOpenLevel >= level
409
+ active || childActive || defaultOpenLevel >= level || defaultOpen
400
410
  );
401
411
  useEffect2(() => {
402
412
  if (active || childActive)
package/dist/layout.d.mts CHANGED
@@ -1,3 +1,3 @@
1
1
  import 'fumadocs-core/server';
2
2
  import 'react';
3
- export { B as BaseLayoutProps, b as DocsLayout, D as DocsLayoutProps, a as Layout, L as LinkItem } from './layout-YB7EFpgW.mjs';
3
+ export { B as BaseLayoutProps, b as DocsLayout, D as DocsLayoutProps, a as Layout, L as LinkItem } from './layout-W7dJ6OHQ.mjs';
package/dist/layout.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  } from "./layout.client.js"
6
6
  import {
7
7
  replaceOrDefault
8
- } from "./chunk-EDUYFB4P.js";
8
+ } from "./chunk-7F2LGCS6.js";
9
9
  import {
10
10
  twMerge
11
11
  } from "./chunk-TK3TM3MR.js";
package/dist/mdx.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Pre } from "./mdx.client.js"
2
2
  import {
3
3
  defaultImageSizes
4
- } from "./chunk-EDUYFB4P.js";
4
+ } from "./chunk-7F2LGCS6.js";
5
5
  import {
6
6
  Card,
7
7
  Cards
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import {
3
3
  useTreeContext
4
- } from "./chunk-UIZNMCLD.js";
5
- import "./chunk-EDUYFB4P.js";
4
+ } from "./chunk-C4PI62MH.js";
5
+ import "./chunk-7F2LGCS6.js";
6
6
  import {
7
7
  useI18n
8
8
  } from "./chunk-YAHHY62W.js";
@@ -143,12 +143,14 @@ function Footer({ items }) {
143
143
  const { previous, next } = useMemo(() => {
144
144
  if (items)
145
145
  return items;
146
- const currentIndex = tree.list.findIndex((item) => item.url === pathname);
146
+ const currentIndex = tree.navigation.findIndex(
147
+ (item) => item.url === pathname
148
+ );
147
149
  return {
148
- previous: tree.list[currentIndex - 1],
149
- next: tree.list[currentIndex + 1]
150
+ previous: tree.navigation[currentIndex - 1],
151
+ next: tree.navigation[currentIndex + 1]
150
152
  };
151
- }, [items, pathname, tree.list]);
153
+ }, [items, pathname, tree.navigation]);
152
154
  return /* @__PURE__ */ jsxs3("div", { className: "mt-4 flex flex-row flex-wrap gap-4 border-t py-12", children: [
153
155
  previous ? /* @__PURE__ */ jsxs3(Link2, { href: previous.url, className: footerItem(), children: [
154
156
  /* @__PURE__ */ jsx3(ChevronLeftIcon, { className: "size-5 shrink-0" }),
package/dist/page.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  } from "./page.client.js"
7
7
  import {
8
8
  replaceOrDefault
9
- } from "./chunk-EDUYFB4P.js";
9
+ } from "./chunk-7F2LGCS6.js";
10
10
  import {
11
11
  twMerge
12
12
  } from "./chunk-TK3TM3MR.js";
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import { ComponentType, ReactNode } from 'react';
3
3
  import { SharedProps } from './components/dialog/search.mjs';
4
4
  export { u as useI18n } from './i18n-dw7ODAws.mjs';
5
- export { u as useTreeContext } from './tree-Zwtp9xPv.mjs';
5
+ export { u as useTreeContext } from './tree-ersey5_u.mjs';
6
6
  import 'fumadocs-core/search/shared';
7
7
  import 'fumadocs-core/server';
8
8
 
package/dist/provider.js CHANGED
@@ -5,8 +5,8 @@ import {
5
5
  } from "./chunk-PLXR6QNH.js";
6
6
  import {
7
7
  useTreeContext
8
- } from "./chunk-UIZNMCLD.js";
9
- import "./chunk-EDUYFB4P.js";
8
+ } from "./chunk-C4PI62MH.js";
9
+ import "./chunk-7F2LGCS6.js";
10
10
  import {
11
11
  SearchProvider,
12
12
  useSearchContext
@@ -3,7 +3,7 @@ import { ReactNode } from 'react';
3
3
 
4
4
  interface TreeContextType {
5
5
  tree: PageTree.Root;
6
- list: PageTree.Item[];
6
+ navigation: PageTree.Item[];
7
7
  root: PageTree.Root | PageTree.Folder;
8
8
  }
9
9
  declare function TreeContextProvider({ children, tree, }: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-ui",
3
- "version": "9.0.0",
3
+ "version": "10.0.0",
4
4
  "description": "The framework for building a documentation website in Next.js",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -97,7 +97,7 @@
97
97
  "react-medium-image-zoom": "^5.1.8",
98
98
  "tailwind-merge": "^2.0.0",
99
99
  "tailwindcss": "^3.4.1",
100
- "fumadocs-core": "9.0.0"
100
+ "fumadocs-core": "10.0.0"
101
101
  },
102
102
  "devDependencies": {
103
103
  "@algolia/client-search": "^4.20.0",
@@ -105,7 +105,7 @@
105
105
  "@types/react": "18.2.0",
106
106
  "@types/react-dom": "18.2.1",
107
107
  "algoliasearch": "^4.20.0",
108
- "next": "14.1.0",
108
+ "next": "14.1.1",
109
109
  "postcss": "8.4.35",
110
110
  "postcss-cli": "^11.0.0",
111
111
  "postcss-lightningcss": "^1.0.0",
@@ -1,14 +0,0 @@
1
- import { Options } from 'fumadocs-core/typescript';
2
-
3
- /**
4
- * **Server Component Only**
5
- *
6
- * Display properties in an exported interface via Type Table
7
- */
8
- declare function AutoTypeTable({ path, name, options, }: {
9
- path: string;
10
- name: string;
11
- options?: Options['options'];
12
- }): JSX.Element;
13
-
14
- export { AutoTypeTable };
@@ -1,32 +0,0 @@
1
- import { TypeTable } from "./type-table.js"
2
- import "../chunk-6C3VEZWH.js";
3
-
4
- // src/components/auto-type-table.tsx
5
- import { generateDocumentation } from "fumadocs-core/typescript";
6
- import "server-only";
7
- import { jsx } from "react/jsx-runtime";
8
- function AutoTypeTable({
9
- path,
10
- name,
11
- options
12
- }) {
13
- const output = generateDocumentation({ file: path, name, options });
14
- return /* @__PURE__ */ jsx(
15
- TypeTable,
16
- {
17
- type: Object.fromEntries(
18
- output.map((entry) => [
19
- entry.name,
20
- {
21
- type: entry.type,
22
- description: entry.description,
23
- default: entry.default
24
- }
25
- ])
26
- )
27
- }
28
- );
29
- }
30
- export {
31
- AutoTypeTable
32
- };