fumadocs-ui 14.5.5 → 14.6.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/dist/components/codeblock.js +1 -1
- package/dist/components/dialog/search.js +5 -6
- package/dist/components/dynamic-codeblock.d.ts +7 -0
- package/dist/components/dynamic-codeblock.d.ts.map +1 -0
- package/dist/components/dynamic-codeblock.js +24 -0
- package/dist/components/layout/root-toggle.d.ts +4 -4
- package/dist/components/layout/root-toggle.d.ts.map +1 -1
- package/dist/components/layout/root-toggle.js +6 -7
- package/dist/components/layout/toc-thumb.d.ts +1 -1
- package/dist/components/layout/toc-thumb.d.ts.map +1 -1
- package/dist/components/tabs.d.ts +7 -1
- package/dist/components/tabs.d.ts.map +1 -1
- package/dist/components/tabs.js +80 -34
- package/dist/layouts/docs/shared.d.ts +1 -1
- package/dist/layouts/docs/shared.d.ts.map +1 -1
- package/dist/style.css +4 -1
- package/dist/utils/get-sidebar-tabs.d.ts.map +1 -1
- package/dist/utils/get-sidebar-tabs.js +23 -9
- package/package.json +12 -12
|
@@ -27,7 +27,7 @@ export const CodeBlock = forwardRef(({ title, allowCopy = true, keepBackground =
|
|
|
27
27
|
? {
|
|
28
28
|
__html: icon,
|
|
29
29
|
}
|
|
30
|
-
: undefined, children: typeof icon !== 'string' ? icon : null })) : null, _jsx("figcaption", { className: "flex-1 truncate text-fd-muted-foreground", children: title }), allowCopy ? (_jsx(CopyButton, { className: "-me-2", onCopy: onCopy })) : null] })) : (allowCopy && (_jsx(CopyButton, { className: "absolute right-2 top-2 z-[2] backdrop-blur-md", onCopy: onCopy }))), _jsxs(ScrollArea, { ref: areaRef, dir: "ltr", children: [_jsx(ScrollViewport, { ...viewportProps, className: cn('max-h-[
|
|
30
|
+
: undefined, children: typeof icon !== 'string' ? icon : null })) : null, _jsx("figcaption", { className: "flex-1 truncate text-fd-muted-foreground", children: title }), allowCopy ? (_jsx(CopyButton, { className: "-me-2", onCopy: onCopy })) : null] })) : (allowCopy && (_jsx(CopyButton, { className: "absolute right-2 top-2 z-[2] backdrop-blur-md", onCopy: onCopy }))), _jsxs(ScrollArea, { ref: areaRef, dir: "ltr", children: [_jsx(ScrollViewport, { ...viewportProps, className: cn('max-h-[600px]', viewportProps?.className), children: props.children }), _jsx(ScrollBar, { orientation: "horizontal" })] })] }));
|
|
31
31
|
});
|
|
32
32
|
CodeBlock.displayName = 'CodeBlock';
|
|
33
33
|
function CopyButton({ className, onCopy, ...props }) {
|
|
@@ -46,8 +46,7 @@ function SearchList({ items, hideResults = false }) {
|
|
|
46
46
|
(!active || items.every((item) => item.id !== active))) {
|
|
47
47
|
setActive(items[0].id);
|
|
48
48
|
}
|
|
49
|
-
|
|
50
|
-
listenerRef.current = (e) => {
|
|
49
|
+
function onKey(e) {
|
|
51
50
|
if (e.key === 'ArrowDown' || e.key == 'ArrowUp') {
|
|
52
51
|
setActive((cur) => {
|
|
53
52
|
const idx = items.findIndex((item) => item.id === cur);
|
|
@@ -63,11 +62,11 @@ function SearchList({ items, hideResults = false }) {
|
|
|
63
62
|
onOpen(selected.url);
|
|
64
63
|
e.preventDefault();
|
|
65
64
|
}
|
|
66
|
-
}
|
|
65
|
+
}
|
|
66
|
+
const listenerRef = useRef(onKey);
|
|
67
|
+
listenerRef.current = onKey;
|
|
67
68
|
useEffect(() => {
|
|
68
|
-
const listener = (e) =>
|
|
69
|
-
listenerRef.current?.(e);
|
|
70
|
-
};
|
|
69
|
+
const listener = (e) => listenerRef.current?.(e);
|
|
71
70
|
window.addEventListener('keydown', listener);
|
|
72
71
|
return () => {
|
|
73
72
|
window.removeEventListener('keydown', listener);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { HighlightOptions } from 'fumadocs-core/server';
|
|
2
|
+
export declare function DynamicCodeBlock({ lang, code, options, }: {
|
|
3
|
+
lang: string;
|
|
4
|
+
code: string;
|
|
5
|
+
options?: Omit<HighlightOptions, 'lang'>;
|
|
6
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=dynamic-codeblock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamic-codeblock.d.ts","sourceRoot":"","sources":["../../src/components/dynamic-codeblock.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAc7D,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,gBAAgB,EAAE,MAAM,CAAC,CAAC;CAC1C,2CAuBA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { CodeBlock, Pre } from '../components/codeblock';
|
|
4
|
+
import { PrerenderScript, useShiki } from 'fumadocs-core/utils/use-shiki';
|
|
5
|
+
import { useId } from 'react';
|
|
6
|
+
const components = {
|
|
7
|
+
pre(props) {
|
|
8
|
+
return (_jsx(CodeBlock, { ...props, children: _jsx(Pre, { children: props.children }) }));
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
export function DynamicCodeBlock({ lang, code, options, }) {
|
|
12
|
+
const scriptKey = useId();
|
|
13
|
+
const shikiOptions = {
|
|
14
|
+
lang,
|
|
15
|
+
scriptKey,
|
|
16
|
+
...options,
|
|
17
|
+
components: {
|
|
18
|
+
...components,
|
|
19
|
+
...options?.components,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
const children = useShiki(code, shikiOptions);
|
|
23
|
+
return (_jsxs(_Fragment, { children: [_jsx(PrerenderScript, { scriptKey: scriptKey, code: code, options: shikiOptions }), children] }));
|
|
24
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { type HTMLAttributes, type ReactNode } from 'react';
|
|
2
|
-
import type { PageTree } from 'fumadocs-core/server';
|
|
3
2
|
export interface Option {
|
|
4
3
|
/**
|
|
5
4
|
* Redirect URL of the folder, usually the index page
|
|
@@ -9,12 +8,13 @@ export interface Option {
|
|
|
9
8
|
title: ReactNode;
|
|
10
9
|
description?: ReactNode;
|
|
11
10
|
/**
|
|
12
|
-
* Detect from
|
|
11
|
+
* Detect from a list of urls
|
|
13
12
|
*/
|
|
14
|
-
|
|
13
|
+
urls?: string[];
|
|
15
14
|
props?: HTMLAttributes<HTMLElement>;
|
|
16
15
|
}
|
|
17
|
-
export declare function RootToggle({ options, ...props }: {
|
|
16
|
+
export declare function RootToggle({ options, placeholder, ...props }: {
|
|
17
|
+
placeholder?: ReactNode;
|
|
18
18
|
options: Option[];
|
|
19
19
|
} & HTMLAttributes<HTMLButtonElement>): import("react/jsx-runtime").JSX.Element;
|
|
20
20
|
//# sourceMappingURL=root-toggle.d.ts.map
|
|
@@ -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;
|
|
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,MAAM,EAAE,CAAC;IAEhB,KAAK,CAAC,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC;CACrC;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,iBAAiB,CAAC,2CAuDpC"}
|
|
@@ -8,22 +8,21 @@ import { cn } from '../../utils/cn';
|
|
|
8
8
|
import { isActive } from '../../utils/is-active';
|
|
9
9
|
import { useSidebar } from '../../contexts/sidebar';
|
|
10
10
|
import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
|
|
11
|
-
|
|
12
|
-
export function RootToggle({ options, ...props }) {
|
|
11
|
+
export function RootToggle({ options, placeholder, ...props }) {
|
|
13
12
|
const [open, setOpen] = useState(false);
|
|
14
13
|
const { closeOnRedirect } = useSidebar();
|
|
15
14
|
const pathname = usePathname();
|
|
16
|
-
const path = useTreePath();
|
|
17
15
|
const selected = useMemo(() => {
|
|
18
|
-
return options.findLast((item) => item.
|
|
19
|
-
?
|
|
16
|
+
return options.findLast((item) => item.urls
|
|
17
|
+
? item.urls.includes(pathname)
|
|
20
18
|
: isActive(item.url, pathname, true));
|
|
21
|
-
}, [
|
|
19
|
+
}, [options, pathname]);
|
|
22
20
|
const onClick = () => {
|
|
23
21
|
closeOnRedirect.current = false;
|
|
24
22
|
setOpen(false);
|
|
25
23
|
};
|
|
26
|
-
|
|
24
|
+
const item = selected ? _jsx(Item, { ...selected }) : placeholder;
|
|
25
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [item ? (_jsxs(PopoverTrigger, { ...props, className: cn('flex flex-row items-center gap-2 rounded-lg px-2 py-1.5 hover:bg-fd-accent/50 hover:text-fd-accent-foreground', props.className), children: [item, _jsx(ChevronDown, { className: "me-1.5 size-4 text-fd-muted-foreground" })] })) : null, _jsx(PopoverContent, { className: "w-[var(--radix-popover-trigger-width)] overflow-hidden p-0", children: options.map((item) => (_jsx(Link, { href: item.url, onClick: onClick, ...item.props, className: cn('flex w-full flex-row items-center gap-2 px-2 py-1.5', selected === item
|
|
27
26
|
? 'bg-fd-accent text-fd-accent-foreground'
|
|
28
27
|
: 'hover:bg-fd-accent/50', item.props?.className), children: _jsx(Item, { ...item }) }, item.url))) })] }));
|
|
29
28
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type HTMLAttributes, type ReactNode, type RefObject } from 'react';
|
|
2
2
|
export type TOCThumb = [top: number, height: number];
|
|
3
3
|
export declare function TocThumb({ containerRef, ...props }: HTMLAttributes<HTMLDivElement> & {
|
|
4
|
-
containerRef: RefObject<HTMLElement>;
|
|
4
|
+
containerRef: RefObject<HTMLElement | null>;
|
|
5
5
|
}): ReactNode;
|
|
6
6
|
//# sourceMappingURL=toc-thumb.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toc-thumb.d.ts","sourceRoot":"","sources":["../../../src/components/layout/toc-thumb.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,SAAS,EAGf,MAAM,OAAO,CAAC;AAIf,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAgCrD,wBAAgB,QAAQ,CAAC,EACvB,YAAY,EACZ,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG;IAClC,YAAY,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"toc-thumb.d.ts","sourceRoot":"","sources":["../../../src/components/layout/toc-thumb.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,SAAS,EAGf,MAAM,OAAO,CAAC;AAIf,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAgCrD,wBAAgB,QAAQ,CAAC,EACvB,YAAY,EACZ,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG;IAClC,YAAY,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CAC7C,GAAG,SAAS,CAgCZ"}
|
|
@@ -21,5 +21,11 @@ export interface TabsProps extends BaseProps {
|
|
|
21
21
|
updateAnchor?: boolean;
|
|
22
22
|
}
|
|
23
23
|
export declare function Tabs({ groupId, items, persist, defaultIndex, updateAnchor, ...props }: TabsProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
-
export
|
|
24
|
+
export type TabProps = Omit<TabsContentProps, 'value'> & {
|
|
25
|
+
/**
|
|
26
|
+
* Value of tab, detect from index if unspecified.
|
|
27
|
+
*/
|
|
28
|
+
value?: TabsContentProps['value'];
|
|
29
|
+
};
|
|
30
|
+
export declare function Tab({ value, className, ...props }: TabProps): import("react/jsx-runtime").JSX.Element;
|
|
25
31
|
//# sourceMappingURL=tabs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/components/tabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,SAAS,IAAI,SAAS,EACvB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/components/tabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,SAAS,IAAI,SAAS,EACvB,MAAM,sBAAsB,CAAC;AAY9B,OAAO,KAAK,SAAS,MAAM,WAAW,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,CAAC;AAmBrB,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAEjB;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAQD,wBAAgB,IAAI,CAAC,EACnB,OAAO,EACP,KAAU,EACV,OAAe,EACf,YAAgB,EAChB,YAAoB,EACpB,GAAG,KAAK,EACT,EAAE,SAAS,2CAqFX;AAMD,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GAAG;IACvD;;OAEG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;CACnC,CAAC;AAEF,wBAAgB,GAAG,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,QAAQ,2CA6B3D"}
|
package/dist/components/tabs.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useMemo, useState,
|
|
3
|
+
import { useMemo, useState, createContext, useContext, useRef, useLayoutEffect, useId, useEffect, } from 'react';
|
|
4
4
|
import { cn } from '../utils/cn';
|
|
5
5
|
import * as Primitive from './ui/tabs';
|
|
6
6
|
export { Primitive };
|
|
@@ -14,20 +14,23 @@ function removeChangeListener(id, listener) {
|
|
|
14
14
|
const list = listeners.get(id) ?? [];
|
|
15
15
|
listeners.set(id, list.filter((item) => item !== listener));
|
|
16
16
|
}
|
|
17
|
-
const
|
|
17
|
+
const TabsContext = createContext(null);
|
|
18
18
|
export function Tabs({ groupId, items = [], persist = false, defaultIndex = 0, updateAnchor = false, ...props }) {
|
|
19
19
|
const values = useMemo(() => items.map((item) => toValue(item)), [items]);
|
|
20
20
|
const [value, setValue] = useState(values[defaultIndex]);
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
const valueToIdMap = useMemo(() => new Map(), []);
|
|
22
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- re-reconstruct the collection if items changed
|
|
23
|
+
const collection = useMemo(() => createCollection(), [items]);
|
|
24
|
+
const onChange = (v) => {
|
|
24
25
|
if (values.includes(v))
|
|
25
26
|
setValue(v);
|
|
26
27
|
};
|
|
28
|
+
const onChangeRef = useRef(onChange);
|
|
29
|
+
onChangeRef.current = onChange;
|
|
27
30
|
useLayoutEffect(() => {
|
|
28
31
|
if (!groupId)
|
|
29
32
|
return;
|
|
30
|
-
const onUpdate = (v) => onChangeRef.current
|
|
33
|
+
const onUpdate = (v) => onChangeRef.current(v);
|
|
31
34
|
const previous = persist
|
|
32
35
|
? localStorage.getItem(groupId)
|
|
33
36
|
: sessionStorage.getItem(groupId);
|
|
@@ -42,40 +45,83 @@ export function Tabs({ groupId, items = [], persist = false, defaultIndex = 0, u
|
|
|
42
45
|
const hash = window.location.hash.slice(1);
|
|
43
46
|
if (!hash)
|
|
44
47
|
return;
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const onValueChange = useCallback((v) => {
|
|
50
|
-
if (updateAnchor) {
|
|
51
|
-
const id = valueToIdMapRef.current.get(v);
|
|
52
|
-
if (id) {
|
|
53
|
-
window.history.replaceState(null, '', `#${id}`);
|
|
48
|
+
for (const [value, id] of valueToIdMap.entries()) {
|
|
49
|
+
if (id === hash) {
|
|
50
|
+
setValue(value);
|
|
51
|
+
break;
|
|
54
52
|
}
|
|
55
53
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
54
|
+
}, [valueToIdMap]);
|
|
55
|
+
return (_jsxs(Primitive.Tabs, { value: value, onValueChange: (v) => {
|
|
56
|
+
if (updateAnchor) {
|
|
57
|
+
const id = valueToIdMap.get(v);
|
|
58
|
+
if (id) {
|
|
59
|
+
window.history.replaceState(null, '', `#${id}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (groupId) {
|
|
63
|
+
listeners.get(groupId)?.forEach((item) => {
|
|
64
|
+
item(v);
|
|
65
|
+
});
|
|
66
|
+
if (persist)
|
|
67
|
+
localStorage.setItem(groupId, v);
|
|
68
|
+
else
|
|
69
|
+
sessionStorage.setItem(groupId, v);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
setValue(v);
|
|
73
|
+
}
|
|
74
|
+
}, ...props, className: cn('my-4', props.className), children: [_jsx(Primitive.TabsList, { children: values.map((v, i) => (_jsx(Primitive.TabsTrigger, { value: v, children: items[i] }, v))) }), _jsx(TabsContext.Provider, { value: useMemo(() => ({ items, valueToIdMap, collection }), [valueToIdMap, collection, items]), children: props.children })] }));
|
|
70
75
|
}
|
|
71
76
|
function toValue(v) {
|
|
72
77
|
return v.toLowerCase().replace(/\s/, '-');
|
|
73
78
|
}
|
|
74
79
|
export function Tab({ value, className, ...props }) {
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
const ctx = useContext(TabsContext);
|
|
81
|
+
const resolvedValue = value ??
|
|
82
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks -- `value` is not supposed to change
|
|
83
|
+
ctx?.items.at(useCollectionIndex());
|
|
84
|
+
if (!resolvedValue)
|
|
85
|
+
throw new Error('Failed to resolve tab `value`, please pass a `value` prop to the Tab component.');
|
|
86
|
+
const v = toValue(resolvedValue);
|
|
87
|
+
if (props.id && ctx) {
|
|
88
|
+
ctx.valueToIdMap.set(v, props.id);
|
|
89
|
+
}
|
|
90
|
+
return (_jsx(Primitive.TabsContent, { value: v, className: cn('prose-no-margin [&>figure:only-child]:-m-4 [&>figure:only-child]:rounded-none [&>figure:only-child]:border-none', className), ...props, children: props.children }));
|
|
91
|
+
}
|
|
92
|
+
function createCollection() {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Inspired by Headless UI.
|
|
97
|
+
*
|
|
98
|
+
* Return the index of children, this is made possible by registering the order of render from children using React context.
|
|
99
|
+
* This is supposed by work with pre-rendering & pure client-side rendering.
|
|
100
|
+
*/
|
|
101
|
+
function useCollectionIndex() {
|
|
102
|
+
const key = useId();
|
|
103
|
+
const ctx = useContext(TabsContext);
|
|
104
|
+
if (!ctx)
|
|
105
|
+
throw new Error('You must wrap your component in <Tabs>');
|
|
106
|
+
const list = ctx.collection;
|
|
107
|
+
function register() {
|
|
108
|
+
if (!list.includes(key))
|
|
109
|
+
list.push(key);
|
|
110
|
+
}
|
|
111
|
+
function unregister() {
|
|
112
|
+
const idx = list.indexOf(key);
|
|
113
|
+
if (idx !== -1)
|
|
114
|
+
list.splice(idx, 1);
|
|
79
115
|
}
|
|
80
|
-
|
|
116
|
+
useMemo(() => {
|
|
117
|
+
// re-order the item to the bottom if registered
|
|
118
|
+
unregister();
|
|
119
|
+
register();
|
|
120
|
+
// eslint-disable-next-line -- register
|
|
121
|
+
}, [list]);
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
return unregister;
|
|
124
|
+
// eslint-disable-next-line -- clean up only
|
|
125
|
+
}, []);
|
|
126
|
+
return list.indexOf(key);
|
|
81
127
|
}
|
|
@@ -36,6 +36,6 @@ export interface SidebarComponents {
|
|
|
36
36
|
}
|
|
37
37
|
export declare function SidebarLinkItem({ item }: {
|
|
38
38
|
item: LinkItemType;
|
|
39
|
-
}): string | number | bigint | boolean | Iterable<ReactNode> | Promise<import("react").
|
|
39
|
+
}): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
40
40
|
export declare function getSidebarTabsFromOptions(options: SidebarOptions['tabs'], tree: PageTree.Root): Option[] | undefined;
|
|
41
41
|
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/layouts/docs/shared.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAML,KAAK,YAAY,EAClB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAC;AAE9D,MAAM,WAAW,cAAe,SAAQ,YAAY;IAClD,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IAErB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAExC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,UAAU,GAAG,KAAK,CAAC;IAErC,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,EAAE,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAA;KAAE,CAAC,CAAC;IAClC,MAAM,EAAE,EAAE,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,SAAS,EAAE,EAAE,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAA;KAAE,CAAC,CAAC;CAC7C;AAED,wBAAgB,eAAe,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/layouts/docs/shared.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAML,KAAK,YAAY,EAClB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAC;AAE9D,MAAM,WAAW,cAAe,SAAQ,YAAY;IAClD,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IAErB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAExC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,UAAU,GAAG,KAAK,CAAC;IAErC,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,EAAE,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAA;KAAE,CAAC,CAAC;IAClC,MAAM,EAAE,EAAE,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,SAAS,EAAE,EAAE,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAA;KAAE,CAAC,CAAC;CAC7C;AAED,wBAAgB,eAAe,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,2UA+C/D;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,EAC/B,IAAI,EAAE,QAAQ,CAAC,IAAI,wBASpB"}
|
package/dist/style.css
CHANGED
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
--tw-contain-paint: ;
|
|
106
106
|
--tw-contain-style: ;
|
|
107
107
|
}/*
|
|
108
|
-
! tailwindcss v3.4.
|
|
108
|
+
! tailwindcss v3.4.16 | MIT License | https://tailwindcss.com
|
|
109
109
|
*//*
|
|
110
110
|
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
|
|
111
111
|
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
|
|
@@ -1250,6 +1250,9 @@ body {
|
|
|
1250
1250
|
.max-h-\[460px\] {
|
|
1251
1251
|
max-height: 460px;
|
|
1252
1252
|
}
|
|
1253
|
+
.max-h-\[600px\] {
|
|
1254
|
+
max-height: 600px;
|
|
1255
|
+
}
|
|
1253
1256
|
.max-h-\[var\(--radix-popover-content-available-height\)\] {
|
|
1254
1257
|
max-height: var(--radix-popover-content-available-height);
|
|
1255
1258
|
}
|
|
@@ -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,UAAU;IACzB,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,SAAS,EAAE,GAAE,UAAe,GAC7B,MAAM,EAAE,
|
|
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,UAAU;IACzB,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,SAAS,EAAE,GAAE,UAAe,GAC7B,MAAM,EAAE,CA8BV"}
|
|
@@ -1,24 +1,38 @@
|
|
|
1
1
|
export function getSidebarTabs(pageTree, { transform } = {}) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
if (node.
|
|
2
|
+
function findOptions(node) {
|
|
3
|
+
const results = [];
|
|
4
|
+
if (node.root) {
|
|
5
5
|
const index = node.index ?? node.children.at(0);
|
|
6
6
|
if (index?.type === 'page') {
|
|
7
7
|
const option = {
|
|
8
8
|
url: index.url,
|
|
9
9
|
title: node.name,
|
|
10
10
|
icon: node.icon,
|
|
11
|
-
folder: node,
|
|
12
11
|
description: node.description,
|
|
12
|
+
urls: getFolderUrls(node),
|
|
13
13
|
};
|
|
14
14
|
const mapped = transform ? transform(option, node) : option;
|
|
15
15
|
if (mapped)
|
|
16
|
-
|
|
16
|
+
results.push(mapped);
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
for (const child of node.children) {
|
|
20
|
+
if (child.type === 'folder')
|
|
21
|
+
results.push(...findOptions(child));
|
|
22
|
+
}
|
|
23
|
+
return results;
|
|
24
|
+
}
|
|
25
|
+
return findOptions(pageTree);
|
|
26
|
+
}
|
|
27
|
+
function getFolderUrls(folder) {
|
|
28
|
+
const results = [];
|
|
29
|
+
if (folder.index)
|
|
30
|
+
results.push(folder.index.url);
|
|
31
|
+
for (const child of folder.children) {
|
|
32
|
+
if (child.type === 'page')
|
|
33
|
+
results.push(child.url);
|
|
34
|
+
if (child.type === 'folder')
|
|
35
|
+
results.push(...getFolderUrls(child));
|
|
21
36
|
}
|
|
22
|
-
|
|
23
|
-
return options;
|
|
37
|
+
return results;
|
|
24
38
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fumadocs-ui",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.6.0",
|
|
4
4
|
"description": "The framework for building a documentation website in Next.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"NextJs",
|
|
@@ -63,23 +63,23 @@
|
|
|
63
63
|
"@radix-ui/react-tabs": "^1.1.1",
|
|
64
64
|
"class-variance-authority": "^0.7.1",
|
|
65
65
|
"lodash.merge": "^4.6.2",
|
|
66
|
-
"lucide-react": "^0.
|
|
67
|
-
"next-themes": "^0.4.
|
|
66
|
+
"lucide-react": "^0.468.0",
|
|
67
|
+
"next-themes": "^0.4.4",
|
|
68
68
|
"postcss-selector-parser": "^7.0.0",
|
|
69
|
-
"react-medium-image-zoom": "^5.2.
|
|
69
|
+
"react-medium-image-zoom": "^5.2.12",
|
|
70
70
|
"tailwind-merge": "^2.5.5",
|
|
71
|
-
"fumadocs-core": "14.
|
|
71
|
+
"fumadocs-core": "14.6.0"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
|
-
"@next/eslint-plugin-next": "^15.0.
|
|
74
|
+
"@next/eslint-plugin-next": "^15.0.4",
|
|
75
75
|
"@types/lodash.merge": "^4.6.9",
|
|
76
|
-
"@types/react": "^
|
|
77
|
-
"@types/react-dom": "^
|
|
76
|
+
"@types/react": "^19.0.1",
|
|
77
|
+
"@types/react-dom": "^19.0.2",
|
|
78
78
|
"autoprefixer": "^10.4.20",
|
|
79
|
-
"next": "15.0.
|
|
79
|
+
"next": "15.0.4",
|
|
80
80
|
"postcss": "^8.4.49",
|
|
81
81
|
"postcss-cli": "^11.0.0",
|
|
82
|
-
"tailwindcss": "^3.4.
|
|
82
|
+
"tailwindcss": "^3.4.16",
|
|
83
83
|
"tsc-alias": "^1.8.10",
|
|
84
84
|
"@fumadocs/cli": "0.0.4",
|
|
85
85
|
"eslint-config-custom": "0.0.0",
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
},
|
|
88
88
|
"peerDependencies": {
|
|
89
89
|
"next": "14.x.x || 15.x.x",
|
|
90
|
-
"react": "
|
|
91
|
-
"react-dom": "
|
|
90
|
+
"react": "18.x.x || 19.x.x",
|
|
91
|
+
"react-dom": "18.x.x || 19.x.x",
|
|
92
92
|
"tailwindcss": "^3.4.14"
|
|
93
93
|
},
|
|
94
94
|
"peerDependenciesMeta": {
|