fumadocs-ui 15.6.11 → 15.7.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/css/shadcn.css CHANGED
@@ -16,3 +16,14 @@
16
16
  --color-fd-accent-foreground: var(--accent-foreground);
17
17
  --color-fd-ring: var(--ring);
18
18
  }
19
+
20
+ #nd-sidebar {
21
+ background-color: var(--sidebar);
22
+ color: var(--sidebar-foreground);
23
+ border-color: var(--sidebar-border);
24
+
25
+ --color-fd-accent: var(--sidebar-accent);
26
+ --color-fd-accent-foreground: var(--sidebar-accent-foreground);
27
+ --color-fd-ring: var(--sidebar-ring);
28
+ --color-fd-primary-foreground: var(--sidebar-primary-foreground);
29
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"codeblock.d.ts","sourceRoot":"","sources":["../../src/components/codeblock.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,cAAc,EACnB,KAAK,SAAS,EAKf,MAAM,OAAO,CAAC;AAIf,OAAO,EACL,IAAI,EACJ,WAAW,EACX,QAAQ,EACR,WAAW,EACZ,MAAM,4BAA4B,CAAC;AAGpC,MAAM,WAAW,cAAe,SAAQ,cAAc,CAAC,QAAQ,CAAC;IAC9D;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IAEjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB,aAAa,CAAC,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC;IAE5C;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;OAEG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAC;IAEnC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;KAAE,KAAK,SAAS,CAAC;CAC9E;AAOD,wBAAgB,GAAG,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,2CAS/C;AAED,wBAAgB,SAAS,CAAC,EACxB,GAAG,EACH,KAAK,EACL,SAAS,EACT,cAAsB,EACtB,IAAI,EACJ,aAAkB,EAClB,QAAQ,EACR,OAEC,EACD,GAAG,KAAK,EACT,EAAE,cAAc,2CAwEhB;AAwCD,wBAAgB,aAAa,CAAC,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,OAAO,IAAI,CAAC,2CA2B3E;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,2CAoBvE;AAED,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,OAAO,WAAW,CAAC,2CAapC;AAGD,eAAO,MAAM,YAAY,oBAAc,CAAC"}
1
+ {"version":3,"file":"codeblock.d.ts","sourceRoot":"","sources":["../../src/components/codeblock.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,cAAc,EACnB,KAAK,SAAS,EAKf,MAAM,OAAO,CAAC;AAIf,OAAO,EACL,IAAI,EACJ,WAAW,EACX,QAAQ,EACR,WAAW,EACZ,MAAM,4BAA4B,CAAC;AAGpC,MAAM,WAAW,cAAe,SAAQ,cAAc,CAAC,QAAQ,CAAC;IAC9D;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IAEjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB,aAAa,CAAC,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC;IAE5C;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;OAEG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAC;IAEnC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;KAAE,KAAK,SAAS,CAAC;CAC9E;AAOD,wBAAgB,GAAG,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,2CAS/C;AAED,wBAAgB,SAAS,CAAC,EACxB,GAAG,EACH,KAAK,EACL,SAAS,EACT,cAAsB,EACtB,IAAI,EACJ,aAAkB,EAClB,QAAQ,EACR,OAEC,EACD,GAAG,KAAK,EACT,EAAE,cAAc,2CAwEhB;AAuCD,wBAAgB,aAAa,CAAC,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,CAAC,OAAO,IAAI,CAAC,2CA2B3E;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,2CAoBvE;AAED,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,OAAO,WAAW,CAAC,2CAapC;AAGD,eAAO,MAAM,YAAY,oBAAc,CAAC"}
@@ -16,7 +16,7 @@ export function CodeBlock({ ref, title, allowCopy, keepBackground = false, icon,
16
16
  const areaRef = useRef(null);
17
17
  allowCopy ?? (allowCopy = !isTab);
18
18
  const bg = cn('bg-fd-secondary', keepBackground && 'bg-(--shiki-light-bg) dark:bg-(--shiki-dark-bg)');
19
- return (_jsxs("figure", { ref: ref, dir: "ltr", ...props, className: cn(isTab ? [bg, 'rounded-lg shadow-sm'] : 'my-4 rounded-xl bg-fd-card p-1', 'shiki relative border outline-none not-prose overflow-hidden text-sm', props.className), children: [title ? (_jsxs("div", { className: cn('flex text-fd-muted-foreground items-center gap-2 ps-3 h-9.5', isTab && 'border-b'), children: [typeof icon === 'string' ? (_jsx("div", { className: "[&_svg]:size-3.5", dangerouslySetInnerHTML: {
19
+ return (_jsxs("figure", { ref: ref, dir: "ltr", ...props, className: cn(isTab ? [bg, 'rounded-lg'] : 'my-4 rounded-xl bg-fd-card p-1', 'shiki relative border shadow-sm outline-none not-prose overflow-hidden text-sm', props.className), children: [title ? (_jsxs("div", { className: cn('flex text-fd-muted-foreground items-center gap-2 ps-3 h-9.5', isTab && 'border-b'), children: [typeof icon === 'string' ? (_jsx("div", { className: "[&_svg]:size-3.5", dangerouslySetInnerHTML: {
20
20
  __html: icon,
21
21
  } })) : (icon), _jsx("figcaption", { className: "flex-1 truncate", children: title }), Actions({
22
22
  children: allowCopy && _jsx(CopyButton, { containerRef: areaRef }),
@@ -44,8 +44,7 @@ function CopyButton({ className, containerRef, ...props }) {
44
44
  void navigator.clipboard.writeText(clone.textContent ?? '');
45
45
  });
46
46
  return (_jsx("button", { type: "button", className: cn(buttonVariants({
47
- color: 'ghost',
48
- className: '[&_svg]:size-3.5',
47
+ className: '[&_svg]:size-3.5 hover:text-fd-accent-foreground',
49
48
  }), className), "aria-label": checked ? 'Copied Text' : 'Copy Text', onClick: onClick, ...props, children: checked ? _jsx(Check, {}) : _jsx(Copy, {}) }));
50
49
  }
51
50
  export function CodeBlockTabs({ ref, ...props }) {
@@ -61,7 +60,7 @@ export function CodeBlockTabsList(props) {
61
60
  return (_jsxs(TabsList, { ...props, className: cn('flex flex-row overflow-x-auto px-1 -mx-1 text-fd-muted-foreground', props.className), children: [props.children, !nested && (_jsx(CopyButton, { className: "sticky ms-auto right-0 bg-fd-card backdrop-blur-sm", containerRef: containerRef }))] }));
62
61
  }
63
62
  export function CodeBlockTabsTrigger({ children, ...props }) {
64
- return (_jsxs(TabsTrigger, { ...props, className: cn('relative group inline-flex text-sm font-medium text-nowrap items-center gap-2 px-2 first:ms-1 py-1.5 hover:text-fd-accent-foreground data-[state=active]:text-fd-primary [&_svg]:size-3.5', props.className), children: [_jsx("div", { className: "absolute inset-x-2 bottom-0 h-px group-data-[state=active]:bg-fd-primary" }), children] }));
63
+ return (_jsxs(TabsTrigger, { ...props, className: cn('relative group inline-flex text-sm font-medium text-nowrap items-center transition-colors gap-2 px-2 first:ms-1 py-1.5 hover:text-fd-accent-foreground data-[state=active]:text-fd-primary [&_svg]:size-3.5', props.className), children: [_jsx("div", { className: "absolute inset-x-2 bottom-0 h-px group-data-[state=active]:bg-fd-primary" }), children] }));
65
64
  }
66
65
  // TODO: currently Vite RSC plugin has problem with adding `asChild` here, maybe revisit this in future
67
66
  export const CodeBlockTab = TabsContent;
@@ -1,7 +1,21 @@
1
+ import { type CodeBlockProps } from '../components/codeblock.js';
1
2
  import type { HighlightOptionsCommon, HighlightOptionsThemes } from 'fumadocs-core/highlight';
2
- export declare function DynamicCodeBlock({ lang, code, options, }: {
3
+ export interface DynamicCodeblockProps {
3
4
  lang: string;
4
5
  code: string;
6
+ /**
7
+ * Extra props for the underlying `<CodeBlock />` component.
8
+ *
9
+ * Ignored if you defined your own `pre` component in `options.components`.
10
+ */
11
+ codeblock?: CodeBlockProps;
12
+ /**
13
+ * Wrap in React `<Suspense />` and provide a fallback.
14
+ *
15
+ * @defaultValue true
16
+ */
17
+ wrapInSuspense?: boolean;
5
18
  options?: Omit<HighlightOptionsCommon, 'lang'> & HighlightOptionsThemes;
6
- }): import("react").ReactNode;
19
+ }
20
+ export declare function DynamicCodeBlock({ lang, code, codeblock, options, wrapInSuspense, }: DynamicCodeblockProps): import("react/jsx-runtime").JSX.Element;
7
21
  //# sourceMappingURL=dynamic-codeblock.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-codeblock.d.ts","sourceRoot":"","sources":["../../src/components/dynamic-codeblock.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AAajC,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,IAAI,EACJ,OAAO,GACR,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,MAAM,CAAC,GAAG,sBAAsB,CAAC;CACzE,6BA8BA"}
1
+ {"version":3,"file":"dynamic-codeblock.d.ts","sourceRoot":"","sources":["../../src/components/dynamic-codeblock.tsx"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,cAAc,EAAO,MAAM,wBAAwB,CAAC;AAC7E,OAAO,KAAK,EAEV,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AAWjC,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,MAAM,CAAC,GAAG,sBAAsB,CAAC;CACzE;AAkBD,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,OAAO,EACP,cAAqB,GACtB,EAAE,qBAAqB,2CAuBvB"}
@@ -3,26 +3,30 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { CodeBlock, Pre } from '../components/codeblock.js';
4
4
  import { useShiki } from 'fumadocs-core/highlight/client';
5
5
  import { cn } from '../utils/cn.js';
6
- import { useMemo } from 'react';
7
- function pre(props) {
8
- return (_jsx(CodeBlock, { ...props, className: cn('my-0', props.className), children: _jsx(Pre, { children: props.children }) }));
6
+ import { createContext, Suspense, use, } from 'react';
7
+ const PropsContext = createContext(undefined);
8
+ function DefaultPre(props) {
9
+ const extraProps = use(PropsContext);
10
+ return (_jsx(CodeBlock, { ...props, ...extraProps, className: cn('my-0', props.className, extraProps?.className), children: _jsx(Pre, { children: props.children }) }));
9
11
  }
10
- export function DynamicCodeBlock({ lang, code, options, }) {
11
- const components = {
12
- pre,
13
- ...options?.components,
14
- };
15
- const loading = useMemo(() => {
16
- const Pre = (components.pre ?? 'pre');
17
- const Code = (components.code ?? 'code');
18
- return (_jsx(Pre, { children: _jsx(Code, { children: code.split('\n').map((line, i) => (_jsx("span", { className: "line", children: line }, i))) }) }));
19
- // eslint-disable-next-line -- initial value only
20
- }, []);
21
- return useShiki(code, {
12
+ export function DynamicCodeBlock({ lang, code, codeblock, options, wrapInSuspense = true, }) {
13
+ const shikiOptions = {
22
14
  lang,
23
- loading,
24
- withPrerenderScript: true,
25
15
  ...options,
26
- components,
27
- });
16
+ components: {
17
+ pre: DefaultPre,
18
+ ...options?.components,
19
+ },
20
+ };
21
+ let children = _jsx(Internal, { code: code, options: shikiOptions });
22
+ if (wrapInSuspense)
23
+ children = (_jsx(Suspense, { fallback: _jsx(Placeholder, { code: code, components: shikiOptions.components }), children: children }));
24
+ return _jsx(PropsContext, { value: codeblock, children: children });
25
+ }
26
+ function Placeholder({ code, components = {}, }) {
27
+ const { pre: Pre = 'pre', code: Code = 'code' } = components;
28
+ return (_jsx(Pre, { children: _jsx(Code, { children: code.split('\n').map((line, i) => (_jsx("span", { className: "line", children: line }, i))) }) }));
29
+ }
30
+ function Internal({ code, options, }) {
31
+ return useShiki(code, options);
28
32
  }
@@ -7,6 +7,7 @@ export interface Option {
7
7
  icon?: ReactNode;
8
8
  title: ReactNode;
9
9
  description?: ReactNode;
10
+ unlisted?: boolean;
10
11
  /**
11
12
  * Detect from a list of urls
12
13
  */
@@ -1 +1 @@
1
- {"version":3,"file":"root-toggle.d.ts","sourceRoot":"","sources":["../../../src/components/layout/root-toggle.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAC;AAQ/E,MAAM,WAAW,MAAM;IACrB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IAExB;;OAEG;IACH,IAAI,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAEnB,KAAK,CAAC,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC;CAC7B;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,WAAW,EACX,GAAG,KAAK,EACT,EAAE;IACD,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,GAAG,cAAc,CAAC,QAAQ,CAAC,2CAqF3B"}
1
+ {"version":3,"file":"root-toggle.d.ts","sourceRoot":"","sources":["../../../src/components/layout/root-toggle.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAC;AAQ/E,MAAM,WAAW,MAAM;IACrB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,IAAI,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAEnB,KAAK,CAAC,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC;CAC7B;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,WAAW,EACX,GAAG,KAAK,EACT,EAAE;IACD,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,GAAG,cAAc,CAAC,QAAQ,CAAC,2CAsF3B"}
@@ -26,7 +26,9 @@ export function RootToggle({ options, placeholder, ...props }) {
26
26
  };
27
27
  const item = selected ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "size-9 shrink-0 md:size-5", children: selected.icon }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium", children: selected.title }), _jsx("p", { className: "text-[13px] text-fd-muted-foreground empty:hidden md:hidden", children: selected.description })] })] })) : (placeholder);
28
28
  return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [item && (_jsxs(PopoverTrigger, { ...props, className: cn('flex items-center gap-2 rounded-lg p-2 border bg-fd-secondary/50 text-start text-fd-secondary-foreground transition-colors hover:bg-fd-accent data-[state=open]:bg-fd-accent data-[state=open]:text-fd-accent-foreground', props.className), children: [item, _jsx(ChevronsUpDown, { className: "shrink-0 ms-auto size-4 text-fd-muted-foreground" })] })), _jsx(PopoverContent, { className: "flex flex-col gap-1 w-(--radix-popover-trigger-width) overflow-hidden p-1", children: options.map((item) => {
29
- const isActive = item === selected;
29
+ const isActive = selected && item.url === selected.url;
30
+ if (!isActive && item.unlisted)
31
+ return;
30
32
  return (_jsxs(Link, { href: item.url, onClick: onClick, ...item.props, className: cn('flex items-center gap-2 rounded-lg p-1.5 hover:bg-fd-accent hover:text-fd-accent-foreground', item.props?.className), children: [_jsx("div", { className: "shrink-0 size-9 md:mt-1 md:mb-auto md:size-5", children: item.icon }), _jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium", children: item.title }), _jsx("p", { className: "text-[13px] text-fd-muted-foreground empty:hidden", children: item.description })] }), _jsx(Check, { className: cn('shrink-0 ms-auto size-3.5 text-fd-primary', !isActive && 'invisible') })] }, item.url));
31
33
  }) })] }));
32
34
  }
@@ -1,5 +1,6 @@
1
1
  import { type VariantProps } from 'class-variance-authority';
2
2
  export declare const buttonVariants: (props?: ({
3
+ variant?: "primary" | "outline" | "ghost" | "secondary" | null | undefined;
3
4
  color?: "primary" | "outline" | "ghost" | "secondary" | null | undefined;
4
5
  size?: "sm" | "icon" | "icon-sm" | "icon-xs" | null | undefined;
5
6
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/components/ui/button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAElE,eAAO,MAAM,cAAc;;;8EAoB1B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC"}
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/components/ui/button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAUlE,eAAO,MAAM,cAAc;;;;8EAe1B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC"}
@@ -1,12 +1,15 @@
1
1
  import { cva } from 'class-variance-authority';
2
+ const variants = {
3
+ primary: 'bg-fd-primary text-fd-primary-foreground hover:bg-fd-primary/80',
4
+ outline: 'border hover:bg-fd-accent hover:text-fd-accent-foreground',
5
+ ghost: 'hover:bg-fd-accent hover:text-fd-accent-foreground',
6
+ secondary: 'border bg-fd-secondary text-fd-secondary-foreground hover:bg-fd-accent hover:text-fd-accent-foreground',
7
+ };
2
8
  export const buttonVariants = cva('inline-flex items-center justify-center rounded-md p-2 text-sm font-medium transition-colors duration-100 disabled:pointer-events-none disabled:opacity-50 focus-visible:outline-none', {
3
9
  variants: {
4
- color: {
5
- primary: 'bg-fd-primary text-fd-primary-foreground hover:bg-fd-primary/80',
6
- outline: 'border hover:bg-fd-accent hover:text-fd-accent-foreground',
7
- ghost: 'hover:bg-fd-accent hover:text-fd-accent-foreground',
8
- secondary: 'border bg-fd-secondary text-fd-secondary-foreground hover:bg-fd-accent hover:text-fd-accent-foreground',
9
- },
10
+ variant: variants,
11
+ // fumadocs use `color` instead of `variant`
12
+ color: variants,
10
13
  size: {
11
14
  sm: 'gap-1 px-2 py-1.5 text-xs',
12
15
  icon: 'p-1.5 [&_svg]:size-5',
@@ -0,0 +1,11 @@
1
+ import type { I18nProviderProps } from '../provider/base.js';
2
+ /**
3
+ * @deprecated legacy I18n Provider, use `<RootProvider i18n={...} />` instead
4
+ */
5
+ export declare function I18nProvider({ locales, locale, onChange: _onChange, onLocaleChange, ...props }: I18nProviderProps & {
6
+ /**
7
+ * @deprecated use `onLocaleChange` instead
8
+ */
9
+ onChange?: I18nProviderProps['onLocaleChange'];
10
+ }): import("react/jsx-runtime").JSX.Element;
11
+ //# sourceMappingURL=legacy-i18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacy-i18n.d.ts","sourceRoot":"","sources":["../../src/contexts/legacy-i18n.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAMzD;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAC3B,OAAY,EACZ,MAAM,EACN,QAAQ,EAAE,SAAS,EACnB,cAA0B,EAC1B,GAAG,KAAK,EACT,EAAE,iBAAiB,GAAG;IACrB;;OAEG;IACH,QAAQ,CAAC,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;CAChD,2CAsCA"}
@@ -0,0 +1,37 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { usePathname, useRouter } from 'fumadocs-core/framework';
4
+ import { useEffectEvent } from 'fumadocs-core/utils/use-effect-event';
5
+ import { useMemo } from 'react';
6
+ import { defaultTranslations, I18nContext } from '../contexts/i18n.js';
7
+ /**
8
+ * @deprecated legacy I18n Provider, use `<RootProvider i18n={...} />` instead
9
+ */
10
+ export function I18nProvider({ locales = [], locale, onChange: _onChange, onLocaleChange = _onChange, ...props }) {
11
+ const router = useRouter();
12
+ const pathname = usePathname();
13
+ const onChange = useEffectEvent((value) => {
14
+ if (onLocaleChange) {
15
+ return onLocaleChange(value);
16
+ }
17
+ const segments = pathname.split('/').filter((v) => v.length > 0);
18
+ // If locale prefix hidden
19
+ if (segments[0] !== locale) {
20
+ segments.unshift(value);
21
+ }
22
+ else {
23
+ segments[0] = value;
24
+ }
25
+ router.push(`/${segments.join('/')}`);
26
+ router.refresh();
27
+ });
28
+ return (_jsx(I18nContext.Provider, { value: useMemo(() => ({
29
+ locale,
30
+ locales,
31
+ text: {
32
+ ...defaultTranslations,
33
+ ...props.translations,
34
+ },
35
+ onChange,
36
+ }), [locale, locales, onChange, props.translations]), children: props.children }));
37
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../src/contexts/tree.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,KAAK,SAAS,EAAmB,MAAM,OAAO,CAAC;AAGxD,KAAK,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAE5E,UAAU,eAAe;IACvB,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC5D;AAKD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAwBA;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAAC,IAAI,EAAE,CAE7C;AAED,wBAAgB,cAAc,IAAI,eAAe,CAEhD"}
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../src/contexts/tree.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,KAAK,SAAS,EAAmB,MAAM,OAAO,CAAC;AAGxD,KAAK,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAE5E,UAAU,eAAe;IACvB,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC5D;AAKD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CA2BA;AAED,wBAAgB,WAAW,IAAI,QAAQ,CAAC,IAAI,EAAE,CAE7C;AAED,wBAAgB,cAAc,IAAI,eAAe,CAEhD"}
@@ -12,7 +12,14 @@ export function TreeContextProvider(props) {
12
12
  // using the id here to make sure this never happens
13
13
  // eslint-disable-next-line react-hooks/exhaustive-deps
14
14
  const tree = useMemo(() => props.tree, [props.tree.$id ?? props.tree]);
15
- const path = useMemo(() => searchPath(tree.children, pathname) ?? [], [tree, pathname]);
15
+ const path = useMemo(() => {
16
+ let result = searchPath(tree.children, pathname);
17
+ if (result)
18
+ return result;
19
+ if (tree.fallback)
20
+ result = searchPath(tree.fallback.children, pathname);
21
+ return result ?? [];
22
+ }, [tree, pathname]);
16
23
  const root = path.findLast((item) => item.type === 'folder' && item.root) ?? tree;
17
24
  root.$id ?? (root.$id = String(nextIdRef.current++));
18
25
  return (_jsx(TreeContext.Provider, { value: useMemo(() => ({ root }), [root]), children: _jsx(PathContext.Provider, { value: path, children: props.children }) }));
package/dist/i18n.d.ts CHANGED
@@ -1,13 +1,16 @@
1
+ import type { Translations } from './contexts/i18n.js';
1
2
  import type { I18nProviderProps } from './provider/base.js';
2
- export type { I18nProviderProps };
3
- export { defaultTranslations, type Translations } from './contexts/i18n.js';
4
- /**
5
- * @deprecated legacy I18n Provider, use `<RootProvider i18n={...} />` instead
6
- */
7
- export declare function I18nProvider({ locales, locale, onChange: _onChange, onLocaleChange, ...props }: I18nProviderProps & {
8
- /**
9
- * @deprecated use `onLocaleChange` instead
10
- */
11
- onChange?: I18nProviderProps['onLocaleChange'];
12
- }): import("react/jsx-runtime").JSX.Element;
3
+ import type { I18nConfig } from 'fumadocs-core/i18n';
4
+ export type { I18nProviderProps, Translations };
5
+ export { defaultTranslations } from './contexts/i18n.js';
6
+ export { I18nProvider } from './contexts/legacy-i18n.js';
7
+ export declare function defineI18nUI<Languages extends string>(config: I18nConfig<Languages>, options: {
8
+ translations: {
9
+ [K in Languages]?: Partial<Translations> & {
10
+ displayName?: string;
11
+ };
12
+ };
13
+ }): {
14
+ provider(locale?: string): I18nProviderProps;
15
+ };
13
16
  //# sourceMappingURL=i18n.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGzE;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAC3B,OAAY,EACZ,MAAM,EACN,QAAQ,EAAE,SAAS,EACnB,cAA0B,EAC1B,GAAG,KAAK,EACT,EAAE,iBAAiB,GAAG;IACrB;;OAEG;IACH,QAAQ,CAAC,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;CAChD,2CAsCA"}
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,wBAAgB,YAAY,CAAC,SAAS,SAAS,MAAM,EACnD,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC,EAC7B,OAAO,EAAE;IACP,YAAY,EAAE;SACX,CAAC,IAAI,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG;YAAE,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE;KACpE,CAAC;CACH;sBAKkB,MAAM,GAA4B,iBAAiB;EAWvE"}
package/dist/i18n.js CHANGED
@@ -1,39 +1,17 @@
1
- 'use client';
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- import { usePathname, useRouter } from 'next/navigation';
4
- import { useEffectEvent } from 'fumadocs-core/utils/use-effect-event';
5
- import { useMemo } from 'react';
6
- import { defaultTranslations, I18nContext } from './contexts/i18n.js';
7
1
  export { defaultTranslations } from './contexts/i18n.js';
8
- // TODO: remove next major
9
- /**
10
- * @deprecated legacy I18n Provider, use `<RootProvider i18n={...} />` instead
11
- */
12
- export function I18nProvider({ locales = [], locale, onChange: _onChange, onLocaleChange = _onChange, ...props }) {
13
- const router = useRouter();
14
- const pathname = usePathname();
15
- const onChange = useEffectEvent((value) => {
16
- if (onLocaleChange) {
17
- return onLocaleChange(value);
18
- }
19
- const segments = pathname.split('/').filter((v) => v.length > 0);
20
- // If locale prefix hidden
21
- if (segments[0] !== locale) {
22
- segments.unshift(value);
23
- }
24
- else {
25
- segments[0] = value;
26
- }
27
- router.push(`/${segments.join('/')}`);
28
- router.refresh();
29
- });
30
- return (_jsx(I18nContext.Provider, { value: useMemo(() => ({
31
- locale,
32
- locales,
33
- text: {
34
- ...defaultTranslations,
35
- ...props.translations,
36
- },
37
- onChange,
38
- }), [locale, locales, onChange, props.translations]), children: props.children }));
2
+ export { I18nProvider } from './contexts/legacy-i18n.js';
3
+ export function defineI18nUI(config, options) {
4
+ const { translations } = options;
5
+ return {
6
+ provider(locale = config.defaultLanguage) {
7
+ return {
8
+ locale,
9
+ translations: translations[locale],
10
+ locales: config.languages.map((locale) => ({
11
+ locale,
12
+ name: translations[locale]?.displayName ?? locale,
13
+ })),
14
+ };
15
+ },
16
+ };
39
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/layouts/docs/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAIf,OAAO,EAQL,cAAc,EAEf,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,KAAK,eAAe,EAAY,MAAM,kBAAkB,CAAC;AAKlE,OAAO,EAAE,kBAAkB,EAAc,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAG/E,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAS/B,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;IAEpB,OAAO,CAAC,EAAE,cAAc,GACtB,cAAc,CAAC,OAAO,CAAC,GAAG;QACxB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,SAAS,CAAC,EAAE,SAAS,CAAC;KACvB,CAAC;IAEJ;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;CACjD;AAED,wBAAgB,UAAU,CAAC,EACzB,GAAG,EAAE,EAAE,eAAe,EAAE,GAAG,GAAG,EAAO,EACrC,OAAO,EAAE,EACP,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,cAAqB,EAC9B,GAAG,YAAY,EACX,EACN,YAAiB,EACjB,kBAA0B,EAC1B,WAA8C,EAC9C,IAAY,EACZ,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,eAAe,2CA8NjB;AAED,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/layouts/docs/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAIf,OAAO,EAQL,cAAc,EAEf,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,KAAK,eAAe,EAAY,MAAM,kBAAkB,CAAC;AAKlE,OAAO,EAAE,kBAAkB,EAAc,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAG/E,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAS/B,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;IAEpB,OAAO,CAAC,EAAE,cAAc,GACtB,cAAc,CAAC,OAAO,CAAC,GAAG;QACxB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,SAAS,CAAC,EAAE,SAAS,CAAC;KACvB,CAAC;IAEJ;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;CACjD;AAED,wBAAgB,UAAU,CAAC,EACzB,GAAG,EAAE,EAAE,eAAe,EAAE,GAAG,GAAG,EAAO,EACrC,OAAO,EAAE,EACP,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,cAAqB,EAC9B,GAAG,YAAY,EACX,EACN,YAAiB,EACjB,kBAA0B,EAC1B,WAA8C,EAC9C,IAAY,EACZ,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,eAAe,2CA6NjB;AAED,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,CAAC"}
@@ -43,8 +43,8 @@ export function DocsLayout({ nav: { transparentMode, ...nav } = {}, sidebar: { t
43
43
  size: 'icon-sm',
44
44
  className: 'mb-auto text-fd-muted-foreground',
45
45
  })), children: _jsx(SidebarIcon, {}) }))] }), searchToggle.enabled !== false &&
46
- (searchToggle.components?.lg ?? (_jsx(LargeSearchToggle, { hideIfDisabled: true }))), tabs.length > 0 && _jsx(RootToggle, { options: tabs }), banner] }), viewport, _jsxs(HideIfEmpty, { as: SidebarFooter, children: [_jsxs("div", { className: "flex text-fd-muted-foreground items-center justify-end empty:hidden", children: [iconLinks.map((item, i) => (_jsx(BaseLinkItem, { item: item, className: cn(buttonVariants({ size: 'icon-sm', color: 'ghost' }), i === iconLinks.length - 1 && 'me-auto'), "aria-label": item.label, children: item.icon }, i))), i18n ? (_jsx(LanguageToggle, { children: _jsx(Languages, { className: "size-4.5" }) })) : null, themeSwitch.enabled !== false &&
47
- (themeSwitch.component ?? (_jsx(ThemeToggle, { className: "p-0", mode: themeSwitch.mode })))] }), footer] })] }));
46
+ (searchToggle.components?.lg ?? (_jsx(LargeSearchToggle, { hideIfDisabled: true }))), tabs.length > 0 && _jsx(RootToggle, { options: tabs }), banner] }), viewport, _jsxs(HideIfEmpty, { as: SidebarFooter, children: [_jsxs("div", { className: "flex text-fd-muted-foreground items-center empty:hidden", children: [i18n ? (_jsx(LanguageToggle, { children: _jsx(Languages, { className: "size-4.5" }) })) : null, iconLinks.map((item, i) => (_jsx(BaseLinkItem, { item: item, className: cn(buttonVariants({ size: 'icon-sm', color: 'ghost' })), "aria-label": item.label, children: item.icon }, i))), themeSwitch.enabled !== false &&
47
+ (themeSwitch.component ?? (_jsx(ThemeToggle, { className: "ms-auto p-0", mode: themeSwitch.mode })))] }), footer] })] }));
48
48
  return (_jsx(Sidebar, { defaultOpenLevel: defaultOpenLevel, prefetch: prefetch, Mobile: mobile, Content: _jsxs(_Fragment, { children: [collapsible && _jsx(CollapsibleControl, {}), content] }) }));
49
49
  }
50
50
  return (_jsx(TreeContextProvider, { tree: props.tree, children: _jsxs(NavProvider, { transparentMode: transparentMode, children: [nav.enabled !== false &&
@@ -21,7 +21,7 @@ export function PageTOCPopoverItems({ variant = 'normal', ...props }) {
21
21
  return (_jsx(TOCScrollArea, { ...props, children: variant === 'clerk' ? _jsx(ClerkTOCItems, {}) : _jsx(TOCItems, {}) }));
22
22
  }
23
23
  export function PageArticle(props) {
24
- return (_jsx("article", { ...props, className: cn('flex min-w-0 w-full flex-col gap-4 px-4 pt-8 md:px-6 md:mx-auto xl:pt-12 xl:px-12', props.className), children: props.children }));
24
+ return (_jsx("article", { ...props, className: cn('flex min-w-0 w-full flex-col gap-4 px-4 pt-8 md:px-6 md:mx-auto 2xl:pt-12 2xl:px-12', props.className), children: props.children }));
25
25
  }
26
26
  export function PageRoot({ toc, children, ...props }) {
27
27
  return (_jsx(TOCProvider, { ...toc, children: _jsx("div", { id: "nd-page", ...props, className: cn('flex flex-1 w-full mx-auto max-w-(--fd-page-width) pt-(--fd-tocnav-height)', props.className), children: children }) }));
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/layouts/home/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,cAAc,EAAW,MAAM,OAAO,CAAC;AAE/D,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAC;AA8B1B,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,GAAG,CAAC,EAAE,OAAO,CACX,UAAU,GAAG;QACX;;WAEG;QACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;KAC7B,CACF,CAAC;CACH;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,eAAe,GAAG,cAAc,CAAC,WAAW,CAAC,2CAmCrD;AAED,wBAAgB,MAAM,CAAC,EACrB,GAAQ,EACR,IAAY,EACZ,KAAK,EACL,SAAS,EACT,WAAgB,EAChB,YAAiB,GAClB,EAAE,eAAe,2CAmGjB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/layouts/home/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,cAAc,EAAW,MAAM,OAAO,CAAC;AAE/D,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAC;AA8B1B,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,GAAG,CAAC,EAAE,OAAO,CACX,UAAU,GAAG;QACX;;WAEG;QACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;KAC7B,CACF,CAAC;CACH;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,eAAe,GAAG,cAAc,CAAC,WAAW,CAAC,2CAmCrD;AAED,wBAAgB,MAAM,CAAC,EACrB,GAAQ,EACR,IAAY,EACZ,KAAK,EACL,SAAS,EACT,WAAgB,EAChB,YAAiB,GAClB,EAAE,eAAe,2CAiGjB"}
@@ -22,11 +22,13 @@ export function Header({ nav = {}, i18n = false, links, githubUrl, themeSwitch =
22
22
  const menuItems = finalLinks.filter((item) => ['menu', 'all'].includes(item.on ?? 'all'));
23
23
  return (_jsxs(Navbar, { children: [_jsx(Link, { href: nav.url ?? '/', className: "inline-flex items-center gap-2.5 font-semibold", children: nav.title }), nav.children, _jsx("ul", { className: "flex flex-row items-center gap-2 px-6 max-sm:hidden", children: navItems
24
24
  .filter((item) => !isSecondary(item))
25
- .map((item, i) => (_jsx(NavbarLinkItem, { item: item, className: "text-sm" }, i))) }), _jsxs("div", { className: "flex flex-row items-center justify-end gap-1.5 flex-1", children: [searchToggle.enabled !== false && (_jsxs(_Fragment, { children: [searchToggle.components?.sm ?? (_jsx(SearchToggle, { className: "p-2 lg:hidden", hideIfDisabled: true })), searchToggle.components?.lg ?? (_jsx(LargeSearchToggle, { className: "w-full rounded-full ps-2.5 max-w-[240px] max-lg:hidden", hideIfDisabled: true }))] })), themeSwitch.enabled !== false &&
26
- (themeSwitch.component ?? (_jsx(ThemeToggle, { className: "max-lg:hidden", mode: themeSwitch?.mode }))), i18n ? (_jsx(LanguageToggle, { className: "max-lg:hidden", children: _jsx(Languages, { className: "size-5" }) })) : null] }), _jsxs("ul", { className: "flex flex-row items-center", children: [navItems.filter(isSecondary).map((item, i) => (_jsx(NavbarLinkItem, { item: item, className: "max-lg:hidden" }, i))), _jsxs(Menu, { className: "lg:hidden", children: [_jsx(MenuTrigger, { "aria-label": "Toggle Menu", className: cn(buttonVariants({
25
+ .map((item, i) => (_jsx(NavbarLinkItem, { item: item, className: "text-sm" }, i))) }), _jsxs("div", { className: "flex flex-row items-center justify-end gap-1.5 flex-1 max-lg:hidden", children: [searchToggle.enabled !== false &&
26
+ (searchToggle.components?.lg ?? (_jsx(LargeSearchToggle, { className: "w-full rounded-full ps-2.5 max-w-[240px]", hideIfDisabled: true }))), themeSwitch.enabled !== false &&
27
+ (themeSwitch.component ?? _jsx(ThemeToggle, { mode: themeSwitch?.mode })), i18n ? (_jsx(LanguageToggle, { children: _jsx(Languages, { className: "size-5" }) })) : null, _jsx("div", { className: "flex flex-row items-center empty:hidden", children: navItems.filter(isSecondary).map((item, i) => (_jsx(NavbarLinkItem, { item: item }, i))) })] }), _jsxs("ul", { className: "flex flex-row items-center ms-auto -me-1.5 lg:hidden", children: [searchToggle.enabled !== false &&
28
+ (searchToggle.components?.sm ?? (_jsx(SearchToggle, { className: "p-2", hideIfDisabled: true }))), _jsxs(Menu, { children: [_jsx(MenuTrigger, { "aria-label": "Toggle Menu", className: cn(buttonVariants({
27
29
  size: 'icon',
28
30
  color: 'ghost',
29
- className: 'group -me-1.5',
31
+ className: 'group',
30
32
  })), enableHover: nav.enableHoverToOpen, children: _jsx(ChevronDown, { className: "!size-5.5 transition-transform duration-300 group-data-[state=open]:rotate-180" }) }), _jsxs(MenuContent, { className: "sm:flex-row sm:items-center sm:justify-end", children: [menuItems
31
33
  .filter((item) => !isSecondary(item))
32
34
  .map((item, i) => (_jsx(MenuLinkItem, { item: item, className: "sm:hidden" }, i))), _jsxs("div", { className: "-ms-1.5 flex flex-row items-center gap-1.5 max-sm:mt-2", children: [menuItems.filter(isSecondary).map((item, i) => (_jsx(MenuLinkItem, { item: item, className: "-me-1.5" }, i))), _jsx("div", { role: "separator", className: "flex-1" }), i18n ? (_jsxs(LanguageToggle, { children: [_jsx(Languages, { className: "size-5" }), _jsx(LanguageToggleText, {}), _jsx(ChevronDown, { className: "size-3 text-fd-muted-foreground" })] })) : null, themeSwitch.enabled !== false &&
@@ -45,8 +45,8 @@ export function LayoutTabs({ options, ...props }) {
45
45
  return isActive(option.url, pathname, true);
46
46
  });
47
47
  }, [options, pathname]);
48
- return (_jsx("div", { ...props, className: cn('flex flex-row items-center gap-2 overflow-auto', props.className), children: options.map((option) => (_jsx(LayoutTab, { selected: selected === option, option: option }, option.url))) }));
48
+ return (_jsx("div", { ...props, className: cn('flex flex-row items-center gap-4 overflow-auto', props.className), children: options.map((option) => (_jsx(LayoutTab, { selected: selected === option, option: option }, option.url))) }));
49
49
  }
50
50
  function LayoutTab({ option, selected = false, }) {
51
- return (_jsx(Link, { className: cn('inline-flex rounded-full items-center px-2 py-1.5 font-medium gap-2 text-fd-muted-foreground text-sm text-nowrap', selected && 'bg-fd-primary/10 text-fd-primary'), href: option.url, children: option.title }));
51
+ return (_jsx(Link, { className: cn('inline-flex border-b border-transparent transition-colors items-center py-1.5 font-medium gap-2 text-fd-muted-foreground text-sm text-nowrap', selected && 'border-fd-primary text-fd-primary'), href: option.url, children: option.title }));
52
52
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/layouts/notebook/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,cAAc,EAEpB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,KAAK,eAAe,EAAY,MAAM,kBAAkB,CAAC;AA6BlE,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAGL,MAAM,EACN,oBAAoB,EACrB,MAAM,2BAA2B,CAAC;AAUnC,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAE/B,GAAG,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG;QAC7B,IAAI,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;KACvB,CAAC;IAEF,OAAO,CAAC,EAAE,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAEnD,cAAc,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;CACjD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,2CAgNhD;AA6LD,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/layouts/notebook/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,cAAc,EAEpB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,KAAK,eAAe,EAAY,MAAM,kBAAkB,CAAC;AA6BlE,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAGL,MAAM,EACN,oBAAoB,EACrB,MAAM,2BAA2B,CAAC;AAUnC,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAE/B,GAAG,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG;QAC7B,IAAI,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;KACvB,CAAC;IAEF,OAAO,CAAC,EAAE,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAEnD,cAAc,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;CACjD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,2CAgNhD;AAsMD,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC"}
@@ -58,10 +58,13 @@ export function DocsLayout(props) {
58
58
  function DocsNavbar({ links, tabs, searchToggle = {}, themeSwitch = {}, nav = {}, ...props }) {
59
59
  const navMode = nav.mode ?? 'auto';
60
60
  const sidebarCollapsible = props.sidebar?.collapsible ?? true;
61
- return (_jsxs(Navbar, { mode: navMode, children: [_jsxs("div", { className: cn('flex border-b px-2.5 gap-2 flex-1 md:px-4', navMode === 'auto' && 'md:px-6'), children: [_jsxs("div", { className: cn('flex items-center', navMode === 'top' && 'flex-1'), children: [sidebarCollapsible && navMode === 'auto' && (_jsx(SidebarCollapseTrigger, { className: cn(buttonVariants({
61
+ return (_jsxs(Navbar, { mode: navMode, children: [_jsxs("div", { className: cn('flex border-b px-4 gap-2 flex-1', navMode === 'auto' && 'md:px-6'), children: [_jsxs("div", { className: cn('items-center', navMode === 'top' && 'flex flex-1', navMode === 'auto' && [
62
+ 'hidden max-md:flex',
63
+ sidebarCollapsible && 'has-data-[collapsed=true]:md:flex',
64
+ ]), children: [sidebarCollapsible && navMode === 'auto' && (_jsx(SidebarCollapseTrigger, { className: cn(buttonVariants({
62
65
  color: 'ghost',
63
66
  size: 'icon-sm',
64
- }), 'text-fd-muted-foreground data-[collapsed=false]:hidden max-md:hidden'), children: _jsx(SidebarIcon, {}) })), _jsx(Link, { href: nav.url ?? '/', className: cn('inline-flex items-center gap-2.5 font-semibold empty:hidden', navMode === 'auto' && 'md:hidden'), children: nav.title })] }), searchToggle.enabled !== false &&
67
+ }), 'text-fd-muted-foreground data-[collapsed=false]:hidden max-md:hidden'), children: _jsx(SidebarIcon, {}) })), _jsx(Link, { href: nav.url ?? '/', className: cn('inline-flex items-center gap-2.5 font-semibold', navMode === 'auto' && 'md:hidden'), children: nav.title })] }), searchToggle.enabled !== false &&
65
68
  (searchToggle.components?.lg ? (_jsx("div", { className: cn('w-full my-auto max-md:hidden', navMode === 'top' ? 'rounded-xl max-w-sm' : 'max-w-[240px]'), children: searchToggle.components.lg })) : (_jsx(LargeSearchToggle, { hideIfDisabled: true, className: cn('w-full my-auto max-md:hidden', navMode === 'top'
66
69
  ? 'rounded-xl max-w-sm ps-2.5'
67
70
  : 'max-w-[240px]') }))), _jsxs("div", { className: "flex flex-1 items-center justify-end md:gap-2", children: [_jsx("div", { className: "flex items-center gap-6 empty:hidden max-lg:hidden", children: links
@@ -69,7 +72,7 @@ function DocsNavbar({ links, tabs, searchToggle = {}, themeSwitch = {}, nav = {}
69
72
  .map((item, i) => (_jsx(NavbarLinkItem, { item: item, className: "text-sm text-fd-muted-foreground transition-colors hover:text-fd-accent-foreground data-[active=true]:text-fd-primary" }, i))) }), nav.children, links
70
73
  .filter((item) => item.type === 'icon')
71
74
  .map((item, i) => (_jsx(BaseLinkItem, { item: item, className: cn(buttonVariants({ size: 'icon-sm', color: 'ghost' }), 'text-fd-muted-foreground max-lg:hidden'), "aria-label": item.label, children: item.icon }, i))), _jsxs("div", { className: "flex items-center md:hidden", children: [searchToggle.enabled !== false &&
72
- (searchToggle.components?.sm ?? (_jsx(SearchToggle, { hideIfDisabled: true, className: "p-2" }))), _jsx(NavbarSidebarTrigger, { className: "p-2" })] }), _jsxs("div", { className: "flex items-center gap-2 max-md:hidden", children: [props.i18n ? (_jsx(LanguageToggle, { children: _jsx(Languages, { className: "size-4.5 text-fd-muted-foreground" }) })) : null, themeSwitch.enabled !== false &&
75
+ (searchToggle.components?.sm ?? (_jsx(SearchToggle, { hideIfDisabled: true, className: "p-2" }))), _jsx(NavbarSidebarTrigger, { className: "p-2 -me-1.5" })] }), _jsxs("div", { className: "flex items-center gap-2 max-md:hidden", children: [props.i18n ? (_jsx(LanguageToggle, { children: _jsx(Languages, { className: "size-4.5 text-fd-muted-foreground" }) })) : null, themeSwitch.enabled !== false &&
73
76
  (themeSwitch.component ?? (_jsx(ThemeToggle, { mode: themeSwitch.mode ?? 'light-dark-system' }))), sidebarCollapsible && navMode === 'top' && (_jsx(SidebarCollapseTrigger, { className: cn(buttonVariants({
74
77
  color: 'secondary',
75
78
  size: 'icon-sm',
package/dist/style.css CHANGED
@@ -1,4 +1,4 @@
1
- /*! tailwindcss v4.1.11 | MIT License | https://tailwindcss.com */
1
+ /*! tailwindcss v4.1.12 | MIT License | https://tailwindcss.com */
2
2
  @layer properties;
3
3
  @layer theme, base, components, utilities;
4
4
  @layer theme {
@@ -222,6 +222,9 @@
222
222
  ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {
223
223
  padding-block: 0;
224
224
  }
225
+ ::-webkit-calendar-picker-indicator {
226
+ line-height: 1;
227
+ }
225
228
  :-moz-ui-invalid {
226
229
  box-shadow: none;
227
230
  }
@@ -1301,6 +1304,9 @@
1301
1304
  border-color: color-mix(in oklab, var(--color-fd-foreground) 10%, transparent);
1302
1305
  }
1303
1306
  }
1307
+ .border-fd-primary {
1308
+ border-color: var(--color-fd-primary);
1309
+ }
1304
1310
  .border-transparent {
1305
1311
  border-color: transparent;
1306
1312
  }
@@ -1424,9 +1430,6 @@
1424
1430
  .px-2 {
1425
1431
  padding-inline: calc(var(--spacing) * 2);
1426
1432
  }
1427
- .px-2\.5 {
1428
- padding-inline: calc(var(--spacing) * 2.5);
1429
- }
1430
1433
  .px-3 {
1431
1434
  padding-inline: calc(var(--spacing) * 3);
1432
1435
  }
@@ -2232,6 +2235,11 @@
2232
2235
  bottom: calc(var(--spacing) * 0);
2233
2236
  }
2234
2237
  }
2238
+ .max-md\:flex {
2239
+ @media (width < 48rem) {
2240
+ display: flex;
2241
+ }
2242
+ }
2235
2243
  .max-md\:hidden {
2236
2244
  @media (width < 48rem) {
2237
2245
  display: none;
@@ -2356,11 +2364,6 @@
2356
2364
  gap: calc(var(--spacing) * 2);
2357
2365
  }
2358
2366
  }
2359
- .md\:px-4 {
2360
- @media (width >= 48rem) {
2361
- padding-inline: calc(var(--spacing) * 4);
2362
- }
2363
- }
2364
2367
  .md\:px-6 {
2365
2368
  @media (width >= 48rem) {
2366
2369
  padding-inline: calc(var(--spacing) * 6);
@@ -2386,6 +2389,13 @@
2386
2389
  --fd-sidebar-width: 286px;
2387
2390
  }
2388
2391
  }
2392
+ .has-data-\[collapsed\=true\]\:md\:flex {
2393
+ &:has(*[data-collapsed="true"]) {
2394
+ @media (width >= 48rem) {
2395
+ display: flex;
2396
+ }
2397
+ }
2398
+ }
2389
2399
  .lg\:hidden {
2390
2400
  @media (width >= 64rem) {
2391
2401
  display: none;
@@ -2426,19 +2436,19 @@
2426
2436
  display: none;
2427
2437
  }
2428
2438
  }
2429
- .xl\:px-12 {
2439
+ .xl\:\[--fd-toc-width\:286px\] {
2430
2440
  @media (width >= 80rem) {
2431
- padding-inline: calc(var(--spacing) * 12);
2441
+ --fd-toc-width: 286px;
2432
2442
  }
2433
2443
  }
2434
- .xl\:pt-12 {
2435
- @media (width >= 80rem) {
2436
- padding-top: calc(var(--spacing) * 12);
2444
+ .\32 xl\:px-12 {
2445
+ @media (width >= 96rem) {
2446
+ padding-inline: calc(var(--spacing) * 12);
2437
2447
  }
2438
2448
  }
2439
- .xl\:\[--fd-toc-width\:286px\] {
2440
- @media (width >= 80rem) {
2441
- --fd-toc-width: 286px;
2449
+ .\32 xl\:pt-12 {
2450
+ @media (width >= 96rem) {
2451
+ padding-top: calc(var(--spacing) * 12);
2442
2452
  }
2443
2453
  }
2444
2454
  .\@max-lg\:col-span-full {
@@ -3,5 +3,5 @@ import type { Option } from '../components/layout/root-toggle.js';
3
3
  export interface GetSidebarTabsOptions {
4
4
  transform?: (option: Option, node: PageTree.Folder) => Option | null;
5
5
  }
6
- export declare function getSidebarTabs(pageTree: PageTree.Root, { transform }?: GetSidebarTabsOptions): Option[];
6
+ export declare function getSidebarTabs(tree: PageTree.Root, { transform }?: GetSidebarTabsOptions): Option[];
7
7
  //# sourceMappingURL=get-sidebar-tabs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-sidebar-tabs.d.ts","sourceRoot":"","sources":["../../src/utils/get-sidebar-tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAC;AAE9D,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACtE;AAeD,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,QAAQ,CAAC,IAAI,EACvB,EAAE,SAA4B,EAAE,GAAE,qBAA0B,GAC3D,MAAM,EAAE,CA6BV"}
1
+ {"version":3,"file":"get-sidebar-tabs.d.ts","sourceRoot":"","sources":["../../src/utils/get-sidebar-tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAC;AAE9D,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CACtE;AAeD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,QAAQ,CAAC,IAAI,EACnB,EAAE,SAA4B,EAAE,GAAE,qBAA0B,GAC3D,MAAM,EAAE,CAuCV"}
@@ -7,16 +7,17 @@ const defaultTransform = (option, node) => {
7
7
  icon: (_jsx("div", { className: "size-full [&_svg]:size-full max-md:p-1.5 max-md:rounded-md max-md:border max-md:bg-fd-secondary", children: node.icon })),
8
8
  };
9
9
  };
10
- export function getSidebarTabs(pageTree, { transform = defaultTransform } = {}) {
11
- function findOptions(node) {
10
+ export function getSidebarTabs(tree, { transform = defaultTransform } = {}) {
11
+ function findOptions(node, unlisted) {
12
12
  const results = [];
13
- if (node.root) {
13
+ if ('root' in node && node.root) {
14
14
  const urls = getFolderUrls(node);
15
15
  if (urls.size > 0) {
16
16
  const option = {
17
17
  url: urls.values().next().value ?? '',
18
18
  title: node.name,
19
19
  icon: node.icon,
20
+ unlisted,
20
21
  description: node.description,
21
22
  urls,
22
23
  };
@@ -27,11 +28,15 @@ export function getSidebarTabs(pageTree, { transform = defaultTransform } = {})
27
28
  }
28
29
  for (const child of node.children) {
29
30
  if (child.type === 'folder')
30
- results.push(...findOptions(child));
31
+ results.push(...findOptions(child, unlisted));
31
32
  }
32
33
  return results;
33
34
  }
34
- return findOptions(pageTree);
35
+ const options = findOptions(tree);
36
+ if (tree.fallback) {
37
+ options.push(...findOptions(tree.fallback, true));
38
+ }
39
+ return options;
35
40
  }
36
41
  function getFolderUrls(folder, output = new Set()) {
37
42
  if (folder.index)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-ui",
3
- "version": "15.6.11",
3
+ "version": "15.7.0",
4
4
  "description": "The framework for building a documentation website in Next.js",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -104,16 +104,16 @@
104
104
  "css/*"
105
105
  ],
106
106
  "dependencies": {
107
- "@radix-ui/react-accordion": "^1.2.11",
108
- "@radix-ui/react-collapsible": "^1.1.11",
109
- "@radix-ui/react-dialog": "^1.1.14",
107
+ "@radix-ui/react-accordion": "^1.2.12",
108
+ "@radix-ui/react-collapsible": "^1.1.12",
109
+ "@radix-ui/react-dialog": "^1.1.15",
110
110
  "@radix-ui/react-direction": "^1.1.1",
111
- "@radix-ui/react-navigation-menu": "^1.2.13",
112
- "@radix-ui/react-popover": "^1.1.14",
113
- "@radix-ui/react-presence": "^1.1.4",
114
- "@radix-ui/react-scroll-area": "^1.2.9",
111
+ "@radix-ui/react-navigation-menu": "^1.2.14",
112
+ "@radix-ui/react-popover": "^1.1.15",
113
+ "@radix-ui/react-presence": "^1.1.5",
114
+ "@radix-ui/react-scroll-area": "^1.2.10",
115
115
  "@radix-ui/react-slot": "^1.2.3",
116
- "@radix-ui/react-tabs": "^1.1.12",
116
+ "@radix-ui/react-tabs": "^1.1.13",
117
117
  "class-variance-authority": "^0.7.1",
118
118
  "lodash.merge": "^4.6.2",
119
119
  "next-themes": "^0.4.6",
@@ -121,20 +121,20 @@
121
121
  "react-medium-image-zoom": "^5.3.0",
122
122
  "scroll-into-view-if-needed": "^3.1.0",
123
123
  "tailwind-merge": "^3.3.1",
124
- "fumadocs-core": "15.6.11"
124
+ "fumadocs-core": "15.7.0"
125
125
  },
126
126
  "devDependencies": {
127
- "@next/eslint-plugin-next": "^15.4.6",
128
- "@tailwindcss/cli": "^4.1.11",
127
+ "@next/eslint-plugin-next": "^15.5.0",
128
+ "@tailwindcss/cli": "^4.1.12",
129
129
  "@types/lodash.merge": "^4.6.9",
130
130
  "@types/react": "^19.1.10",
131
131
  "@types/react-dom": "^19.1.7",
132
- "next": "15.4.6",
133
- "tailwindcss": "^4.1.11",
132
+ "next": "15.5.0",
133
+ "tailwindcss": "^4.1.12",
134
134
  "tsc-alias": "^1.8.16",
135
135
  "@fumadocs/cli": "1.0.0",
136
136
  "eslint-config-custom": "0.0.0",
137
- "fumadocs-core": "15.6.11",
137
+ "fumadocs-core": "15.7.0",
138
138
  "tsconfig": "0.0.0"
139
139
  },
140
140
  "peerDependencies": {