fumadocs-ui 15.5.4 → 15.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/css/neutral.css +2 -2
- package/css/preset.css +9 -2
- package/css/shiki.css +7 -1
- package/dist/components/banner.d.ts +8 -2
- package/dist/components/banner.d.ts.map +1 -1
- package/dist/components/banner.js +24 -29
- package/dist/components/callout.d.ts.map +1 -1
- package/dist/components/callout.js +12 -22
- package/dist/components/card.d.ts.map +1 -1
- package/dist/components/card.js +2 -2
- package/dist/components/codeblock.d.ts +14 -33
- package/dist/components/codeblock.d.ts.map +1 -1
- package/dist/components/codeblock.js +50 -25
- package/dist/components/layout/sidebar.js +1 -1
- package/dist/components/tabs.d.ts +8 -19
- package/dist/components/tabs.d.ts.map +1 -1
- package/dist/components/tabs.js +17 -74
- package/dist/components/tabs.unstyled.d.ts +24 -0
- package/dist/components/tabs.unstyled.d.ts.map +1 -0
- package/dist/components/tabs.unstyled.js +89 -0
- package/dist/layouts/docs/page-client.js +1 -1
- package/dist/layouts/docs/page.js +1 -1
- package/dist/layouts/docs.js +3 -3
- package/dist/layouts/home/navbar.d.ts.map +1 -1
- package/dist/layouts/home/navbar.js +3 -1
- package/dist/layouts/notebook-client.d.ts +3 -2
- package/dist/layouts/notebook-client.d.ts.map +1 -1
- package/dist/layouts/notebook-client.js +15 -11
- package/dist/layouts/notebook.d.ts.map +1 -1
- package/dist/layouts/notebook.js +6 -6
- package/dist/mdx.d.ts +5 -0
- package/dist/mdx.d.ts.map +1 -1
- package/dist/mdx.js +5 -1
- package/dist/style.css +114 -110
- package/package.json +6 -6
- package/dist/components/ui/tabs.d.ts +0 -8
- package/dist/components/ui/tabs.d.ts.map +0 -1
- package/dist/components/ui/tabs.js +0 -16
package/css/neutral.css
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
--color-fd-background: hsl(0, 0%, 7.04%);
|
|
22
22
|
--color-fd-foreground: hsl(0, 0%, 92%);
|
|
23
23
|
--color-fd-muted: hsl(0, 0%, 12.9%);
|
|
24
|
-
--color-fd-muted-foreground:
|
|
24
|
+
--color-fd-muted-foreground: hsla(0, 0%, 70%, 0.8);
|
|
25
25
|
--color-fd-popover: hsl(0, 0%, 10.6%);
|
|
26
26
|
--color-fd-popover-foreground: hsl(0, 0%, 86.9%);
|
|
27
27
|
--color-fd-card: hsl(0, 0%, 9.8%);
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
--color-fd-primary: hsl(0, 0%, 98%);
|
|
31
31
|
--color-fd-primary-foreground: hsl(0, 0%, 9%);
|
|
32
32
|
--color-fd-secondary: hsl(0, 0%, 12.9%);
|
|
33
|
-
--color-fd-secondary-foreground: hsl(0, 0%,
|
|
33
|
+
--color-fd-secondary-foreground: hsl(0, 0%, 92%);
|
|
34
34
|
--color-fd-accent: hsla(0, 0%, 40.9%, 30%);
|
|
35
35
|
--color-fd-accent-foreground: hsl(0, 0%, 90%);
|
|
36
36
|
--color-fd-ring: hsl(0, 0%, 54.9%);
|
package/css/preset.css
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
@source '../dist/**/*.js';
|
|
4
4
|
@plugin '../dist/theme/typography/index.js';
|
|
5
5
|
|
|
6
|
+
@theme static {
|
|
7
|
+
--color-fd-info: oklch(62.3% 0.214 259.815);
|
|
8
|
+
--color-fd-warning: oklch(76.9% 0.188 70.08);
|
|
9
|
+
--color-fd-error: oklch(63.7% 0.237 25.331);
|
|
10
|
+
--color-fd-success: oklch(72.3% 0.219 149.579);
|
|
11
|
+
}
|
|
12
|
+
|
|
6
13
|
@theme {
|
|
7
14
|
--spacing-fd-container: 1400px;
|
|
8
15
|
--fd-page-width: 1200px;
|
|
@@ -110,14 +117,14 @@
|
|
|
110
117
|
@keyframes fd-popover-in {
|
|
111
118
|
from {
|
|
112
119
|
opacity: 0;
|
|
113
|
-
transform:
|
|
120
|
+
transform: scale(0.7);
|
|
114
121
|
}
|
|
115
122
|
}
|
|
116
123
|
|
|
117
124
|
@keyframes fd-popover-out {
|
|
118
125
|
to {
|
|
119
126
|
opacity: 0;
|
|
120
|
-
transform:
|
|
127
|
+
transform: scale(0.7);
|
|
121
128
|
}
|
|
122
129
|
}
|
|
123
130
|
|
package/css/shiki.css
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
.shiki:not(.not-fumadocs-codeblock *) {
|
|
2
|
+
--padding-left: calc(var(--spacing) * 3);
|
|
3
|
+
--padding-right: calc(var(--spacing) * 3);
|
|
4
|
+
|
|
2
5
|
code span {
|
|
3
6
|
color: var(--shiki-light);
|
|
4
7
|
}
|
|
5
8
|
|
|
6
9
|
code .line {
|
|
10
|
+
position: relative;
|
|
7
11
|
min-height: 1lh;
|
|
8
|
-
|
|
12
|
+
padding-left: var(--padding-left);
|
|
13
|
+
padding-right: var(--padding-right);
|
|
9
14
|
}
|
|
10
15
|
|
|
11
16
|
&.has-focused code .line:not(.focused) {
|
|
@@ -24,6 +29,7 @@
|
|
|
24
29
|
&[data-line-numbers] code .line {
|
|
25
30
|
width: calc(100% - 7 * var(--spacing));
|
|
26
31
|
counter-increment: line;
|
|
32
|
+
padding-left: calc(var(--padding-left) - var(--spacing));
|
|
27
33
|
@apply ml-7;
|
|
28
34
|
|
|
29
35
|
&::after {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type HTMLAttributes } from 'react';
|
|
2
|
-
|
|
2
|
+
type BannerVariant = 'rainbow' | 'normal';
|
|
3
|
+
export declare function Banner({ id, variant, changeLayout, height, rainbowColors, ...props }: HTMLAttributes<HTMLDivElement> & {
|
|
3
4
|
/**
|
|
4
5
|
* @defaultValue 3rem
|
|
5
6
|
*/
|
|
@@ -7,7 +8,11 @@ export declare function Banner({ id, variant, changeLayout, height, ...props }:
|
|
|
7
8
|
/**
|
|
8
9
|
* @defaultValue 'normal'
|
|
9
10
|
*/
|
|
10
|
-
variant?:
|
|
11
|
+
variant?: BannerVariant;
|
|
12
|
+
/**
|
|
13
|
+
* For rainbow variant only, customise the colors
|
|
14
|
+
*/
|
|
15
|
+
rainbowColors?: string[];
|
|
11
16
|
/**
|
|
12
17
|
* Change Fumadocs layout styles
|
|
13
18
|
*
|
|
@@ -15,4 +20,5 @@ export declare function Banner({ id, variant, changeLayout, height, ...props }:
|
|
|
15
20
|
*/
|
|
16
21
|
changeLayout?: boolean;
|
|
17
22
|
}): import("react/jsx-runtime").JSX.Element | null;
|
|
23
|
+
export {};
|
|
18
24
|
//# sourceMappingURL=banner.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"banner.d.ts","sourceRoot":"","sources":["../../src/components/banner.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAuB,MAAM,OAAO,CAAC;AAKjE,wBAAgB,MAAM,CAAC,EACrB,EAAE,EACF,OAAkB,EAClB,YAAmB,EACnB,MAAe,EACf,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG;IAClC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,OAAO,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"banner.d.ts","sourceRoot":"","sources":["../../src/components/banner.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAuB,MAAM,OAAO,CAAC;AAKjE,KAAK,aAAa,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE1C,wBAAgB,MAAM,CAAC,EACrB,EAAE,EACF,OAAkB,EAClB,YAAmB,EACnB,MAAe,EACf,aAKC,EACD,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG;IAClC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,kDAuEA"}
|
|
@@ -4,7 +4,12 @@ import { useEffect, useState } from 'react';
|
|
|
4
4
|
import { X } from '../icons.js';
|
|
5
5
|
import { cn } from '../utils/cn.js';
|
|
6
6
|
import { buttonVariants } from '../components/ui/button.js';
|
|
7
|
-
export function Banner({ id, variant = 'normal', changeLayout = true, height = '3rem',
|
|
7
|
+
export function Banner({ id, variant = 'normal', changeLayout = true, height = '3rem', rainbowColors = [
|
|
8
|
+
'rgba(0,149,255,0.56)',
|
|
9
|
+
'rgba(231,77,255,0.77)',
|
|
10
|
+
'rgba(255,0,0,0.73)',
|
|
11
|
+
'rgba(131,255,166,0.66)',
|
|
12
|
+
], ...props }) {
|
|
8
13
|
const [open, setOpen] = useState(true);
|
|
9
14
|
const globalKey = id ? `nd-banner-${id}` : null;
|
|
10
15
|
useEffect(() => {
|
|
@@ -13,47 +18,37 @@ export function Banner({ id, variant = 'normal', changeLayout = true, height = '
|
|
|
13
18
|
}, [globalKey]);
|
|
14
19
|
if (!open)
|
|
15
20
|
return null;
|
|
16
|
-
return (_jsxs("div", { id: id, ...props, className: cn('sticky top-0 z-40 flex flex-row items-center justify-center
|
|
21
|
+
return (_jsxs("div", { id: id, ...props, className: cn('sticky top-0 z-40 flex flex-row items-center justify-center px-4 text-center text-sm font-medium', variant === 'normal' && 'bg-fd-secondary', variant === 'rainbow' && 'bg-fd-background', !open && 'hidden', props.className), style: {
|
|
17
22
|
height,
|
|
18
23
|
}, children: [changeLayout && open ? (_jsx("style", { children: globalKey
|
|
19
24
|
? `:root:not(.${globalKey}) { --fd-banner-height: ${height}; }`
|
|
20
25
|
: `:root { --fd-banner-height: ${height}; }` })) : null, globalKey ? (_jsx("style", { children: `.${globalKey} #${id} { display: none; }` })) : null, globalKey ? (_jsx("script", { dangerouslySetInnerHTML: {
|
|
21
26
|
__html: `if (localStorage.getItem('${globalKey}') === 'true') document.documentElement.classList.add('${globalKey}');`,
|
|
22
|
-
} })) : null, variant === 'rainbow'
|
|
27
|
+
} })) : null, variant === 'rainbow'
|
|
28
|
+
? flow({
|
|
29
|
+
colors: rainbowColors,
|
|
30
|
+
})
|
|
31
|
+
: null, props.children, id ? (_jsx("button", { type: "button", "aria-label": "Close Banner", onClick: () => {
|
|
23
32
|
setOpen(false);
|
|
24
33
|
if (globalKey)
|
|
25
34
|
localStorage.setItem(globalKey, 'true');
|
|
26
35
|
}, className: cn(buttonVariants({
|
|
27
36
|
color: 'ghost',
|
|
28
|
-
className: 'absolute end-2 top-1/2 -translate-y-1/2 text-fd-muted-foreground',
|
|
29
|
-
size: 'icon',
|
|
37
|
+
className: 'absolute end-2 top-1/2 -translate-y-1/2 text-fd-muted-foreground/50',
|
|
38
|
+
size: 'icon-sm',
|
|
30
39
|
})), children: _jsx(X, {}) })) : null] }));
|
|
31
40
|
}
|
|
32
41
|
const maskImage = 'linear-gradient(to bottom,white,transparent), radial-gradient(circle at top center, white, transparent)';
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
backgroundImage: 'repeating-linear-gradient(60deg, var(--end), var(--start) 2%, var(--start) 5%, transparent 8%, transparent 14%, var(--via) 18%, var(--via) 22%, var(--mid) 28%, var(--mid) 30%, var(--via) 34%, var(--via) 36%, transparent, var(--end) calc(50% - 12px))',
|
|
43
|
-
backgroundSize: '200% 100%',
|
|
44
|
-
mixBlendMode: 'difference',
|
|
45
|
-
} }), _jsx("div", { className: "absolute inset-0 z-[-1]", style: {
|
|
46
|
-
maskImage,
|
|
47
|
-
maskComposite: 'intersect',
|
|
48
|
-
animation: 'fd-moving-banner 20s linear infinite',
|
|
49
|
-
'--start': 'rgba(255,120,120,0.5)',
|
|
50
|
-
'--mid': 'rgba(36,188,255,0.4)',
|
|
51
|
-
'--end': 'rgba(64,0,255,0.51)',
|
|
52
|
-
'--via': 'rgba(255,89,0,0.56)',
|
|
53
|
-
backgroundImage: 'repeating-linear-gradient(45deg, var(--end), var(--start) 4%, var(--start) 8%, transparent 9%, transparent 14%, var(--mid) 16%, var(--mid) 20%, transparent, var(--via) 36%, var(--via) 40%, transparent 42%, var(--end) 46%, var(--end) calc(50% - 16.8px))',
|
|
54
|
-
backgroundSize: '200% 100%',
|
|
55
|
-
mixBlendMode: 'color-dodge',
|
|
56
|
-
} }), _jsx("style", { children: `@keyframes fd-moving-banner {
|
|
42
|
+
function flow({ colors }) {
|
|
43
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute inset-0 z-[-1]", style: {
|
|
44
|
+
maskImage,
|
|
45
|
+
maskComposite: 'intersect',
|
|
46
|
+
animation: 'fd-moving-banner 20s linear infinite',
|
|
47
|
+
backgroundImage: `repeating-linear-gradient(70deg, ${[...colors, colors[0]].map((color, i) => `${color} ${(i * 50) / colors.length}%`).join(', ')})`,
|
|
48
|
+
backgroundSize: '200% 100%',
|
|
49
|
+
filter: 'saturate(2)',
|
|
50
|
+
} }), _jsx("style", { children: `@keyframes fd-moving-banner {
|
|
57
51
|
from { background-position: 0% 0; }
|
|
58
52
|
to { background-position: 100% 0; }
|
|
59
53
|
}` })] }));
|
|
54
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"callout.d.ts","sourceRoot":"","sources":["../../src/components/callout.tsx"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"callout.d.ts","sourceRoot":"","sources":["../../src/components/callout.tsx"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAmBxE,eAAO,MAAM,OAAO;YAZV,SAAS;IACjB;;OAEG;WACI,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS;IAExD;;OAEG;WACI,SAAS;kDAyCjB,CAAC"}
|
|
@@ -2,28 +2,18 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { CircleCheck, CircleX, Info, TriangleAlert } from '../icons.js';
|
|
3
3
|
import { forwardRef } from 'react';
|
|
4
4
|
import { cn } from '../utils/cn.js';
|
|
5
|
-
import { cva } from 'class-variance-authority';
|
|
6
|
-
const calloutVariants = cva('my-4 flex gap-2 rounded-lg border border-s-2 bg-fd-card p-3 text-sm text-fd-card-foreground shadow-md', {
|
|
7
|
-
variants: {
|
|
8
|
-
type: {
|
|
9
|
-
info: 'border-s-blue-500/50',
|
|
10
|
-
warn: 'border-s-amber-500/50',
|
|
11
|
-
error: 'border-s-red-500/50',
|
|
12
|
-
success: 'border-s-green-500/50',
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
5
|
export const Callout = forwardRef(({ className, children, title, type = 'info', icon, ...props }, ref) => {
|
|
17
|
-
if (type === '
|
|
18
|
-
type = '
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
6
|
+
if (type === 'warn')
|
|
7
|
+
type = 'warning';
|
|
8
|
+
const DefaultIcon = {
|
|
9
|
+
info: Info,
|
|
10
|
+
warning: TriangleAlert,
|
|
11
|
+
error: CircleX,
|
|
12
|
+
success: CircleCheck,
|
|
13
|
+
}[type];
|
|
14
|
+
return (_jsxs("div", { ref: ref, className: cn('flex gap-2 my-4 rounded-xl border bg-fd-card p-3 ps-1 text-sm text-fd-card-foreground shadow-md', className), ...props, style: {
|
|
15
|
+
'--callout-color': `var(--color-fd-${type})`,
|
|
16
|
+
...props.style,
|
|
17
|
+
}, children: [_jsx("div", { role: "none", className: "w-1 bg-(--callout-color)/50 rounded-sm" }), icon ?? (_jsx(DefaultIcon, { className: "size-5 -me-0.5 fill-(--callout-color) text-fd-card" })), _jsxs("div", { className: "flex flex-col gap-2 min-w-0 flex-1", children: [title ? _jsx("p", { className: "font-medium !my-0", children: title }) : null, _jsx("div", { className: "text-fd-muted-foreground prose-no-margin empty:hidden", children: children })] })] }));
|
|
28
18
|
});
|
|
29
19
|
Callout.displayName = 'Callout';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../src/components/card.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvD,wBAAgB,KAAK,CAAC,KAAK,EAAE,cAAc,CAAC,cAAc,CAAC,2CAS1D;AAED,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,GAAG;IACnE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IAExB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,wBAAgB,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,KAAK,EAAE,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../src/components/card.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvD,wBAAgB,KAAK,CAAC,KAAK,EAAE,cAAc,CAAC,cAAc,CAAC,2CAS1D;AAED,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,GAAG;IACnE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;IAExB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,wBAAgB,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,KAAK,EAAE,EAAE,SAAS,2CA2BrE"}
|
package/dist/components/card.js
CHANGED
|
@@ -2,9 +2,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import Link from 'fumadocs-core/link';
|
|
3
3
|
import { cn } from '../utils/cn.js';
|
|
4
4
|
export function Cards(props) {
|
|
5
|
-
return (_jsx("div", { ...props, className: cn('grid grid-cols-2 gap-
|
|
5
|
+
return (_jsx("div", { ...props, className: cn('grid grid-cols-2 gap-3 @container', props.className), children: props.children }));
|
|
6
6
|
}
|
|
7
7
|
export function Card({ icon, title, description, ...props }) {
|
|
8
8
|
const E = props.href ? Link : 'div';
|
|
9
|
-
return (_jsxs(E, { ...props, "data-card": true, className: cn('block rounded-
|
|
9
|
+
return (_jsxs(E, { ...props, "data-card": true, className: cn('block rounded-xl border bg-fd-card p-4 text-fd-card-foreground transition-colors @max-lg:col-span-full', props.href && 'hover:bg-fd-accent/80', props.className), children: [icon ? (_jsx("div", { className: "not-prose mb-2 w-fit shadow-md rounded-lg border bg-fd-muted p-1.5 text-fd-muted-foreground [&_svg]:size-4", children: icon })) : null, _jsx("h3", { className: "not-prose mb-1 text-sm font-medium", children: title }), description ? (_jsx("p", { className: "!my-0 text-sm text-fd-muted-foreground", children: description })) : null, _jsx("div", { className: "text-sm text-fd-muted-foreground prose-no-margin empty:hidden", children: props.children })] }));
|
|
10
10
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type HTMLAttributes, type ReactNode } from 'react';
|
|
2
|
-
|
|
1
|
+
import { type ComponentProps, type HTMLAttributes, type ReactNode } from 'react';
|
|
2
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from '../components/tabs.unstyled.js';
|
|
3
|
+
export interface CodeBlockProps extends ComponentProps<'figure'> {
|
|
3
4
|
/**
|
|
4
5
|
* Icon of code block
|
|
5
6
|
*
|
|
@@ -27,35 +28,15 @@ export type CodeBlockProps = HTMLAttributes<HTMLElement> & {
|
|
|
27
28
|
* @defaultValue 1
|
|
28
29
|
*/
|
|
29
30
|
'data-line-numbers-start'?: number;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*
|
|
42
|
-
* @defaultValue true
|
|
43
|
-
*/
|
|
44
|
-
allowCopy?: boolean;
|
|
45
|
-
/**
|
|
46
|
-
* Keep original background color generated by Shiki or Rehype Code
|
|
47
|
-
*
|
|
48
|
-
* @defaultValue false
|
|
49
|
-
*/
|
|
50
|
-
keepBackground?: boolean;
|
|
51
|
-
viewportProps?: HTMLAttributes<HTMLElement>;
|
|
52
|
-
/**
|
|
53
|
-
* show line numbers
|
|
54
|
-
*/
|
|
55
|
-
'data-line-numbers'?: boolean;
|
|
56
|
-
/**
|
|
57
|
-
* @defaultValue 1
|
|
58
|
-
*/
|
|
59
|
-
'data-line-numbers-start'?: number;
|
|
60
|
-
} & import("react").RefAttributes<HTMLElement>>;
|
|
31
|
+
Actions?: (props: {
|
|
32
|
+
className?: string;
|
|
33
|
+
children?: ReactNode;
|
|
34
|
+
}) => ReactNode;
|
|
35
|
+
}
|
|
36
|
+
export declare function Pre(props: ComponentProps<'pre'>): import("react/jsx-runtime").JSX.Element;
|
|
37
|
+
export declare function CodeBlock({ ref, title, allowCopy, keepBackground, icon, viewportProps, children, Actions, ...props }: CodeBlockProps): import("react/jsx-runtime").JSX.Element;
|
|
38
|
+
export declare function CodeBlockTabs({ ref, ...props }: ComponentProps<typeof Tabs>): import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
export declare function CodeBlockTabsList(props: ComponentProps<typeof TabsList>): import("react/jsx-runtime").JSX.Element;
|
|
40
|
+
export declare function CodeBlockTabsTrigger({ children, ...props }: ComponentProps<typeof TabsTrigger>): import("react/jsx-runtime").JSX.Element;
|
|
41
|
+
export declare const CodeBlockTab: (props: ComponentProps<typeof TabsContent>) => import("react/jsx-runtime").JSX.Element;
|
|
61
42
|
//# sourceMappingURL=codeblock.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codeblock.d.ts","sourceRoot":"","sources":["../../src/components/codeblock.tsx"],"names":[],"mappings":"AAEA,OAAO,
|
|
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;AAED,eAAO,MAAM,YAAY,GAAI,OAAO,cAAc,CAAC,OAAO,WAAW,CAAC,4CAErE,CAAC"}
|
|
@@ -1,18 +1,40 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Check, Copy } from '../icons.js';
|
|
4
|
-
import {
|
|
4
|
+
import { createContext, useContext, useMemo, useRef, } from 'react';
|
|
5
5
|
import { cn } from '../utils/cn.js';
|
|
6
6
|
import { useCopyButton } from '../utils/use-copy-button.js';
|
|
7
7
|
import { buttonVariants } from '../components/ui/button.js';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger, } from '../components/tabs.unstyled.js';
|
|
9
|
+
import { mergeRefs } from '../utils/merge-refs.js';
|
|
10
|
+
const TabsContext = createContext(null);
|
|
11
|
+
export function Pre(props) {
|
|
12
|
+
return (_jsx("pre", { ...props, className: cn('min-w-full w-max *:flex *:flex-col', props.className), children: props.children }));
|
|
13
|
+
}
|
|
14
|
+
export function CodeBlock({ ref, title, allowCopy, keepBackground = false, icon, viewportProps = {}, children, Actions = (props) => (_jsx("div", { ...props, className: cn('empty:hidden', props.className) })), ...props }) {
|
|
15
|
+
const isTab = useContext(TabsContext) !== null;
|
|
13
16
|
const areaRef = useRef(null);
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
allowCopy ?? (allowCopy = !isTab);
|
|
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: {
|
|
20
|
+
__html: icon,
|
|
21
|
+
} })) : (icon), _jsx("figcaption", { className: "flex-1 truncate", children: title }), Actions({
|
|
22
|
+
children: allowCopy && _jsx(CopyButton, { containerRef: areaRef }),
|
|
23
|
+
})] })) : (Actions({
|
|
24
|
+
className: 'absolute top-1 right-1 z-2 bg-fd-card rounded-bl-lg border-l border-b text-fd-muted-foreground',
|
|
25
|
+
children: allowCopy && _jsx(CopyButton, { containerRef: areaRef }),
|
|
26
|
+
})), _jsx("div", { ref: areaRef, ...viewportProps, className: cn(!isTab && [bg, 'rounded-lg border'], 'text-[13px] py-3.5 overflow-auto max-h-[600px] fd-scroll-container', viewportProps.className), style: {
|
|
27
|
+
// space for toolbar
|
|
28
|
+
'--padding-right': !title ? 'calc(var(--spacing) * 8)' : undefined,
|
|
29
|
+
counterSet: props['data-line-numbers']
|
|
30
|
+
? `line ${Number(props['data-line-numbers-start'] ?? 1) - 1}`
|
|
31
|
+
: undefined,
|
|
32
|
+
...viewportProps.style,
|
|
33
|
+
}, children: children })] }));
|
|
34
|
+
}
|
|
35
|
+
function CopyButton({ className, containerRef, ...props }) {
|
|
36
|
+
const [checked, onClick] = useCopyButton(() => {
|
|
37
|
+
const pre = containerRef.current?.getElementsByTagName('pre').item(0);
|
|
16
38
|
if (!pre)
|
|
17
39
|
return;
|
|
18
40
|
const clone = pre.cloneNode(true);
|
|
@@ -20,22 +42,25 @@ export const CodeBlock = forwardRef(({ title, allowCopy = true, keepBackground =
|
|
|
20
42
|
node.replaceWith('\n');
|
|
21
43
|
});
|
|
22
44
|
void navigator.clipboard.writeText(clone.textContent ?? '');
|
|
23
|
-
};
|
|
24
|
-
return (
|
|
25
|
-
? {
|
|
26
|
-
__html: icon,
|
|
27
|
-
}
|
|
28
|
-
: 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 })] })) : (allowCopy && (_jsx(CopyButton, { className: "absolute right-2 top-2 z-[2] backdrop-blur-md", onCopy: onCopy }))), _jsx("div", { ref: areaRef, ...viewportProps, className: cn('text-[13px] py-3.5 overflow-auto [&_.line]:px-4 max-h-[600px] fd-scroll-container', props['data-line-numbers'] && '[&_.line]:pl-3', viewportProps?.className), style: {
|
|
29
|
-
counterSet: props['data-line-numbers']
|
|
30
|
-
? `line ${Number(props['data-line-numbers-start'] ?? 1) - 1}`
|
|
31
|
-
: undefined,
|
|
32
|
-
...viewportProps?.style,
|
|
33
|
-
}, children: children })] }));
|
|
34
|
-
});
|
|
35
|
-
CodeBlock.displayName = 'CodeBlock';
|
|
36
|
-
function CopyButton({ className, onCopy, ...props }) {
|
|
37
|
-
const [checked, onClick] = useCopyButton(onCopy);
|
|
38
|
-
return (_jsxs("button", { type: "button", className: cn(buttonVariants({
|
|
45
|
+
});
|
|
46
|
+
return (_jsx("button", { type: "button", className: cn(buttonVariants({
|
|
39
47
|
color: 'ghost',
|
|
40
|
-
|
|
48
|
+
className: '[&_svg]:size-3.5',
|
|
49
|
+
}), className), "aria-label": checked ? 'Copied Text' : 'Copy Text', onClick: onClick, ...props, children: checked ? _jsx(Check, {}) : _jsx(Copy, {}) }));
|
|
50
|
+
}
|
|
51
|
+
export function CodeBlockTabs({ ref, ...props }) {
|
|
52
|
+
const containerRef = useRef(null);
|
|
53
|
+
const nested = useContext(TabsContext) !== null;
|
|
54
|
+
return (_jsx(Tabs, { ref: mergeRefs(containerRef, ref), ...props, className: cn('bg-fd-card p-1 rounded-xl border overflow-hidden', !nested && 'my-4', props.className), children: _jsx(TabsContext.Provider, { value: useMemo(() => ({
|
|
55
|
+
containerRef,
|
|
56
|
+
nested,
|
|
57
|
+
}), [nested]), children: props.children }) }));
|
|
58
|
+
}
|
|
59
|
+
export function CodeBlockTabsList(props) {
|
|
60
|
+
const { containerRef, nested } = useContext(TabsContext);
|
|
61
|
+
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
|
+
}
|
|
63
|
+
export function CodeBlockTabsTrigger({ children, ...props }) {
|
|
64
|
+
return (_jsxs(TabsTrigger, { ...props, className: cn('relative group inline-flex text-sm font-medium 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] }));
|
|
41
65
|
}
|
|
66
|
+
export const CodeBlockTab = (props) => (_jsx(TabsContent, { ...props, asChild: true }));
|
|
@@ -208,5 +208,5 @@ function getOffset(level) {
|
|
|
208
208
|
function Border({ level, active }) {
|
|
209
209
|
if (level <= 1)
|
|
210
210
|
return null;
|
|
211
|
-
return (_jsx("div", { className: cn('absolute w-px inset-y-3 z-
|
|
211
|
+
return (_jsx("div", { className: cn('absolute w-px inset-y-3 z-2 start-2.5 md:inset-y-2', active && 'bg-fd-primary') }));
|
|
212
212
|
}
|
|
@@ -1,18 +1,7 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
1
2
|
import { type ComponentProps, type ReactNode } from 'react';
|
|
2
|
-
import * as
|
|
3
|
-
export interface TabsProps extends ComponentProps<typeof
|
|
4
|
-
/**
|
|
5
|
-
* Identifier for Sharing value of tabs
|
|
6
|
-
*/
|
|
7
|
-
groupId?: string;
|
|
8
|
-
/**
|
|
9
|
-
* Enable persistent
|
|
10
|
-
*/
|
|
11
|
-
persist?: boolean;
|
|
12
|
-
/**
|
|
13
|
-
* If true, updates the URL hash based on the tab's id
|
|
14
|
-
*/
|
|
15
|
-
updateAnchor?: boolean;
|
|
3
|
+
import * as Unstyled from './tabs.unstyled.js';
|
|
4
|
+
export interface TabsProps extends Omit<ComponentProps<typeof Unstyled.Tabs>, 'value' | 'onValueChange'> {
|
|
16
5
|
/**
|
|
17
6
|
* Use simple mode instead of advanced usage as documented in https://radix-ui.com/primitives/docs/components/tabs.
|
|
18
7
|
*/
|
|
@@ -28,15 +17,15 @@ export interface TabsProps extends ComponentProps<typeof Primitive.Tabs> {
|
|
|
28
17
|
*/
|
|
29
18
|
label?: ReactNode;
|
|
30
19
|
}
|
|
31
|
-
export declare const TabsList:
|
|
32
|
-
export declare const TabsTrigger:
|
|
33
|
-
export declare function Tabs({ ref, className,
|
|
34
|
-
export interface TabProps extends Omit<ComponentProps<typeof
|
|
20
|
+
export declare const TabsList: React.ForwardRefExoticComponent<Omit<import("@radix-ui/react-tabs").TabsListProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
21
|
+
export declare const TabsTrigger: React.ForwardRefExoticComponent<Omit<import("@radix-ui/react-tabs").TabsTriggerProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
22
|
+
export declare function Tabs({ ref, className, items, label, defaultIndex, defaultValue, ...props }: TabsProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export interface TabProps extends Omit<ComponentProps<typeof Unstyled.TabsContent>, 'value'> {
|
|
35
24
|
/**
|
|
36
25
|
* Value of tab, detect from index if unspecified.
|
|
37
26
|
*/
|
|
38
27
|
value?: string;
|
|
39
28
|
}
|
|
40
29
|
export declare function Tab({ value, ...props }: TabProps): import("react/jsx-runtime").JSX.Element;
|
|
41
|
-
export declare function TabsContent({ value, className, ...props }: ComponentProps<typeof
|
|
30
|
+
export declare function TabsContent({ value, className, ...props }: ComponentProps<typeof Unstyled.TabsContent>): import("react/jsx-runtime").JSX.Element;
|
|
42
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,EACL,KAAK,cAAc,EAEnB,KAAK,SAAS,
|
|
1
|
+
{"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/components/tabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,SAAS,EAMf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAI5C,MAAM,WAAW,SACf,SAAQ,IAAI,CACV,cAAc,CAAC,OAAO,QAAQ,CAAC,IAAI,CAAC,EACpC,OAAO,GAAG,eAAe,CAC1B;IACD;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAEjB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAaD,eAAO,MAAM,QAAQ,wKAYnB,CAAC;AAGH,eAAO,MAAM,WAAW,iLAYtB,CAAC;AAGH,wBAAgB,IAAI,CAAC,EACnB,GAAG,EACH,SAAS,EACT,KAAK,EACL,KAAK,EACL,YAAgB,EAChB,YAAmE,EACnE,GAAG,KAAK,EACT,EAAE,SAAS,2CAqCX;AAED,MAAM,WAAW,QACf,SAAQ,IAAI,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAClE;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,EAAE,QAAQ,2CAgBhD;AAED,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,OAAO,QAAQ,CAAC,WAAW,CAAC,2CAc7C"}
|
package/dist/components/tabs.js
CHANGED
|
@@ -1,20 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { createContext, useContext, useEffect, useId, useMemo, useState, } from 'react';
|
|
4
5
|
import { cn } from '../utils/cn.js';
|
|
5
|
-
import * as
|
|
6
|
-
import { useEffectEvent } from 'fumadocs-core/utils/use-effect-event';
|
|
7
|
-
import { mergeRefs } from '../utils/merge-refs.js';
|
|
8
|
-
const listeners = new Map();
|
|
9
|
-
function addChangeListener(id, listener) {
|
|
10
|
-
const list = listeners.get(id) ?? [];
|
|
11
|
-
list.push(listener);
|
|
12
|
-
listeners.set(id, list);
|
|
13
|
-
}
|
|
14
|
-
function removeChangeListener(id, listener) {
|
|
15
|
-
const list = listeners.get(id) ?? [];
|
|
16
|
-
listeners.set(id, list.filter((item) => item !== listener));
|
|
17
|
-
}
|
|
6
|
+
import * as Unstyled from './tabs.unstyled.js';
|
|
18
7
|
const TabsContext = createContext(null);
|
|
19
8
|
function useTabContext() {
|
|
20
9
|
const ctx = useContext(TabsContext);
|
|
@@ -22,63 +11,18 @@ function useTabContext() {
|
|
|
22
11
|
throw new Error('You must wrap your component in <Tabs>');
|
|
23
12
|
return ctx;
|
|
24
13
|
}
|
|
25
|
-
export const TabsList =
|
|
26
|
-
|
|
27
|
-
export
|
|
28
|
-
|
|
14
|
+
export const TabsList = React.forwardRef((props, ref) => (_jsx(Unstyled.TabsList, { ref: ref, ...props, className: cn('flex gap-3.5 text-fd-secondary-foreground overflow-x-auto px-4 not-prose', props.className) })));
|
|
15
|
+
TabsList.displayName = 'TabsList';
|
|
16
|
+
export const TabsTrigger = React.forwardRef((props, ref) => (_jsx(Unstyled.TabsTrigger, { ref: ref, ...props, className: cn('inline-flex items-center gap-2 whitespace-nowrap text-fd-muted-foreground border-b border-transparent py-2 text-sm font-medium transition-colors [&_svg]:size-4 hover:text-fd-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=active]:border-fd-primary data-[state=active]:text-fd-primary', props.className) })));
|
|
17
|
+
TabsTrigger.displayName = 'TabsTrigger';
|
|
18
|
+
export function Tabs({ ref, className, items, label, defaultIndex = 0, defaultValue = items ? escapeValue(items[defaultIndex]) : undefined, ...props }) {
|
|
29
19
|
const [value, setValue] = useState(defaultValue);
|
|
30
|
-
const valueToIdMap = useMemo(() => new Map(), []);
|
|
31
20
|
const collection = useMemo(() => [], []);
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
useLayoutEffect(() => {
|
|
38
|
-
if (!groupId)
|
|
39
|
-
return;
|
|
40
|
-
const previous = persist
|
|
41
|
-
? localStorage.getItem(groupId)
|
|
42
|
-
: sessionStorage.getItem(groupId);
|
|
43
|
-
if (previous)
|
|
44
|
-
onUpdate(previous);
|
|
45
|
-
addChangeListener(groupId, onUpdate);
|
|
46
|
-
return () => {
|
|
47
|
-
removeChangeListener(groupId, onUpdate);
|
|
48
|
-
};
|
|
49
|
-
}, [groupId, onUpdate, persist]);
|
|
50
|
-
useLayoutEffect(() => {
|
|
51
|
-
const hash = window.location.hash.slice(1);
|
|
52
|
-
if (!hash)
|
|
53
|
-
return;
|
|
54
|
-
for (const [value, id] of valueToIdMap.entries()) {
|
|
55
|
-
if (id === hash) {
|
|
56
|
-
setValue(value);
|
|
57
|
-
tabsRef.current?.scrollIntoView();
|
|
58
|
-
break;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}, [valueToIdMap]);
|
|
62
|
-
return (_jsxs(Primitive.Tabs, { ref: mergeRefs(ref, tabsRef), value: value, onValueChange: (v) => {
|
|
63
|
-
if (updateAnchor) {
|
|
64
|
-
const id = valueToIdMap.get(v);
|
|
65
|
-
if (id) {
|
|
66
|
-
window.history.replaceState(null, '', `#${id}`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
if (groupId) {
|
|
70
|
-
listeners.get(groupId)?.forEach((item) => {
|
|
71
|
-
item(v);
|
|
72
|
-
});
|
|
73
|
-
if (persist)
|
|
74
|
-
localStorage.setItem(groupId, v);
|
|
75
|
-
else
|
|
76
|
-
sessionStorage.setItem(groupId, v);
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
setValue(v);
|
|
80
|
-
}
|
|
81
|
-
}, className: cn('my-4', className), ...props, children: [items && (_jsxs(TabsList, { children: [label && (_jsx("span", { className: "text-sm font-medium my-auto me-auto", children: label })), items.map((item) => (_jsx(TabsTrigger, { value: escapeValue(item), children: item }, item)))] })), _jsx(TabsContext.Provider, { value: useMemo(() => ({ items, valueToIdMap, collection }), [valueToIdMap, collection, items]), children: props.children })] }));
|
|
21
|
+
return (_jsxs(Unstyled.Tabs, { ref: ref, className: cn('flex flex-col overflow-hidden rounded-xl border bg-fd-secondary my-4', className), value: value, onValueChange: (v) => {
|
|
22
|
+
if (items && !items.some((item) => escapeValue(item) === v))
|
|
23
|
+
return;
|
|
24
|
+
setValue(v);
|
|
25
|
+
}, ...props, children: [items && (_jsxs(TabsList, { children: [label && (_jsx("span", { className: "text-sm font-medium my-auto me-auto", children: label })), items.map((item) => (_jsx(TabsTrigger, { value: escapeValue(item), children: item }, item)))] })), _jsx(TabsContext.Provider, { value: useMemo(() => ({ items, collection }), [collection, items]), children: props.children })] }));
|
|
82
26
|
}
|
|
83
27
|
export function Tab({ value, ...props }) {
|
|
84
28
|
const { items } = useTabContext();
|
|
@@ -90,11 +34,7 @@ export function Tab({ value, ...props }) {
|
|
|
90
34
|
return (_jsx(TabsContent, { value: escapeValue(resolved), ...props, children: props.children }));
|
|
91
35
|
}
|
|
92
36
|
export function TabsContent({ value, className, ...props }) {
|
|
93
|
-
|
|
94
|
-
if (props.id) {
|
|
95
|
-
valueToIdMap.set(value, props.id);
|
|
96
|
-
}
|
|
97
|
-
return (_jsx(Primitive.TabsContent, { value: value, forceMount: true, className: cn('prose-no-margin data-[state=inactive]:hidden [&>figure:only-child]:-m-4 [&>figure:only-child]:border-none', className), ...props, children: props.children }));
|
|
37
|
+
return (_jsx(Unstyled.TabsContent, { value: value, forceMount: true, className: cn('p-4 text-[15px] bg-fd-background rounded-xl outline-none prose-no-margin data-[state=inactive]:hidden [&>figure:only-child]:-m-4 [&>figure:only-child]:border-none', className), ...props, children: props.children }));
|
|
98
38
|
}
|
|
99
39
|
/**
|
|
100
40
|
* Inspired by Headless UI.
|
|
@@ -116,6 +56,9 @@ function useCollectionIndex() {
|
|
|
116
56
|
collection.push(key);
|
|
117
57
|
return collection.indexOf(key);
|
|
118
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* only escape whitespaces in values in simple mode
|
|
61
|
+
*/
|
|
119
62
|
function escapeValue(v) {
|
|
120
63
|
return v.toLowerCase().replace(/\s/, '-');
|
|
121
64
|
}
|