@windrun-huaiin/third-ui 23.0.0 → 23.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +152 -189
- package/dist/fuma/fuma-page-genarator.d.ts +3 -1
- package/dist/fuma/fuma-page-genarator.js +33 -6
- package/dist/fuma/fuma-page-genarator.mjs +34 -7
- package/dist/fuma/mdx/index.js +1 -0
- package/dist/fuma/mdx/index.mjs +1 -1
- package/dist/fuma/mdx/toc-clerk-portable.d.ts +1 -0
- package/dist/fuma/mdx/toc-clerk-portable.js +12 -9
- package/dist/fuma/mdx/toc-clerk-portable.mjs +11 -9
- package/dist/fuma/server/features/code.d.ts +1 -2
- package/dist/fuma/server/features/code.js +2 -3
- package/dist/fuma/server/features/code.mjs +2 -3
- package/dist/fuma/server/site-mdx-base.js +5 -1
- package/dist/fuma/server/site-mdx-base.mjs +5 -1
- package/dist/fuma/server/site-mdx-fallbacks.d.ts +7 -0
- package/dist/fuma/server/site-mdx-fallbacks.js +30 -0
- package/dist/fuma/server/site-mdx-fallbacks.mjs +29 -1
- package/package.json +4 -14
- package/src/fuma/fuma-page-genarator.tsx +80 -12
- package/src/fuma/mdx/toc-clerk-portable.tsx +65 -27
- package/src/fuma/server/features/code.tsx +5 -9
- package/src/fuma/server/site-mdx-base.tsx +6 -2
- package/src/fuma/server/site-mdx-fallbacks.tsx +50 -0
- package/src/fuma/server/optional-features.tsx +0 -6
- package/src/fuma/server/site-mdx-components.tsx +0 -46
- package/src/fuma/server/site-mdx-presets.ts +0 -131
|
@@ -51,11 +51,10 @@ function tryToMatchIcon(props, iconMap) {
|
|
|
51
51
|
}
|
|
52
52
|
return undefined;
|
|
53
53
|
}
|
|
54
|
-
function createCodeMdxComponents(
|
|
55
|
-
const mergedIconMap = Object.assign(Object.assign({}, defaultCodeLanguageIconMap), iconMap);
|
|
54
|
+
function createCodeMdxComponents() {
|
|
56
55
|
return {
|
|
57
56
|
pre: (props) => {
|
|
58
|
-
const customIcon = tryToMatchIcon(props,
|
|
57
|
+
const customIcon = tryToMatchIcon(props, defaultCodeLanguageIconMap);
|
|
59
58
|
return (jsxRuntime.jsx(CodeBlock, Object.assign({}, props, (customIcon && { icon: customIcon }), { children: jsxRuntime.jsx(Pre, { children: props.children }) })));
|
|
60
59
|
},
|
|
61
60
|
CodeBlock,
|
|
@@ -49,11 +49,10 @@ function tryToMatchIcon(props, iconMap) {
|
|
|
49
49
|
}
|
|
50
50
|
return undefined;
|
|
51
51
|
}
|
|
52
|
-
function createCodeMdxComponents(
|
|
53
|
-
const mergedIconMap = Object.assign(Object.assign({}, defaultCodeLanguageIconMap), iconMap);
|
|
52
|
+
function createCodeMdxComponents() {
|
|
54
53
|
return {
|
|
55
54
|
pre: (props) => {
|
|
56
|
-
const customIcon = tryToMatchIcon(props,
|
|
55
|
+
const customIcon = tryToMatchIcon(props, defaultCodeLanguageIconMap);
|
|
57
56
|
return (jsx(CodeBlock, Object.assign({}, props, (customIcon && { icon: customIcon }), { children: jsx(Pre, { children: props.children }) })));
|
|
58
57
|
},
|
|
59
58
|
CodeBlock,
|
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
var tabs = require('fumadocs-ui/components/tabs');
|
|
4
4
|
var callout = require('fumadocs-ui/components/callout');
|
|
5
|
+
var card = require('fumadocs-ui/components/card');
|
|
5
6
|
var files = require('fumadocs-ui/components/files');
|
|
6
7
|
var accordion = require('fumadocs-ui/components/accordion');
|
|
7
8
|
var siteX = require('../site-x.js');
|
|
8
9
|
var base = require('./features/base.js');
|
|
9
10
|
var widgets = require('./features/widgets.js');
|
|
11
|
+
var siteMdxFallbacks = require('./site-mdx-fallbacks.js');
|
|
10
12
|
|
|
11
13
|
const defaultFumaUiComponents = {
|
|
14
|
+
Card: card.Card,
|
|
15
|
+
Cards: card.Cards,
|
|
12
16
|
Callout: callout.Callout,
|
|
13
17
|
File: files.File,
|
|
14
18
|
Folder: files.Folder,
|
|
@@ -24,7 +28,7 @@ function createSiteMdxBaseComponents(options = {}) {
|
|
|
24
28
|
function createSiteMdxComponents(options = {}) {
|
|
25
29
|
const { additionalComponents, baseOptions, features = [], } = options;
|
|
26
30
|
return function getMDXComponents(components) {
|
|
27
|
-
return Object.assign(Object.assign(Object.assign(Object.assign({}, createSiteMdxBaseComponents(baseOptions)), features.reduce((acc, feature) => (Object.assign(Object.assign({}, acc), feature)), {})), additionalComponents), components);
|
|
31
|
+
return siteMdxFallbacks.withMissingMdxComponentFallback(Object.assign(Object.assign(Object.assign(Object.assign({}, createSiteMdxBaseComponents(baseOptions)), features.reduce((acc, feature) => (Object.assign(Object.assign({}, acc), feature)), {})), additionalComponents), components));
|
|
28
32
|
};
|
|
29
33
|
}
|
|
30
34
|
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { Tabs, Tab } from 'fumadocs-ui/components/tabs';
|
|
2
2
|
import { Callout } from 'fumadocs-ui/components/callout';
|
|
3
|
+
import { Cards, Card } from 'fumadocs-ui/components/card';
|
|
3
4
|
import { Files, Folder, File } from 'fumadocs-ui/components/files';
|
|
4
5
|
import { Accordions, Accordion } from 'fumadocs-ui/components/accordion';
|
|
5
6
|
import { SiteX } from '../site-x.mjs';
|
|
6
7
|
import { createBaseMdxComponents } from './features/base.mjs';
|
|
7
8
|
import { createWidgetMdxComponents } from './features/widgets.mjs';
|
|
9
|
+
import { withMissingMdxComponentFallback } from './site-mdx-fallbacks.mjs';
|
|
8
10
|
|
|
9
11
|
const defaultFumaUiComponents = {
|
|
12
|
+
Card,
|
|
13
|
+
Cards,
|
|
10
14
|
Callout,
|
|
11
15
|
File,
|
|
12
16
|
Folder,
|
|
@@ -22,7 +26,7 @@ function createSiteMdxBaseComponents(options = {}) {
|
|
|
22
26
|
function createSiteMdxComponents(options = {}) {
|
|
23
27
|
const { additionalComponents, baseOptions, features = [], } = options;
|
|
24
28
|
return function getMDXComponents(components) {
|
|
25
|
-
return Object.assign(Object.assign(Object.assign(Object.assign({}, createSiteMdxBaseComponents(baseOptions)), features.reduce((acc, feature) => (Object.assign(Object.assign({}, acc), feature)), {})), additionalComponents), components);
|
|
29
|
+
return withMissingMdxComponentFallback(Object.assign(Object.assign(Object.assign(Object.assign({}, createSiteMdxBaseComponents(baseOptions)), features.reduce((acc, feature) => (Object.assign(Object.assign({}, acc), feature)), {})), additionalComponents), components));
|
|
26
30
|
};
|
|
27
31
|
}
|
|
28
32
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef } from 'react';
|
|
2
|
+
import type { MDXComponents } from 'mdx/types';
|
|
2
3
|
type MissingFeatureBlockProps = ComponentPropsWithoutRef<'div'> & {
|
|
3
4
|
feature: string;
|
|
4
5
|
component: string;
|
|
@@ -14,5 +15,11 @@ export declare function createMissingMdxFeatureComponents(): {
|
|
|
14
15
|
InlineMath: (props: ComponentPropsWithoutRef<"span">) => import("react/jsx-runtime").JSX.Element;
|
|
15
16
|
Mermaid: (props: ComponentPropsWithoutRef<"div">) => import("react/jsx-runtime").JSX.Element;
|
|
16
17
|
TypeTable: (props: ComponentPropsWithoutRef<"div">) => import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
CodeBlockTab: (props: ComponentPropsWithoutRef<"div">) => import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
CodeBlockTabs: (props: ComponentPropsWithoutRef<"div">) => import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
CodeBlockTabsList: (props: ComponentPropsWithoutRef<"div">) => import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
CodeBlockTabsTrigger: (props: ComponentPropsWithoutRef<"div">) => import("react/jsx-runtime").JSX.Element;
|
|
17
22
|
};
|
|
23
|
+
export declare function createMissingMdxComponentFallback(component: string): (props: ComponentPropsWithoutRef<"div">) => import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
export declare function withMissingMdxComponentFallback(components: MDXComponents): MDXComponents;
|
|
18
25
|
export {};
|
|
@@ -41,9 +41,39 @@ function createMissingMdxFeatureComponents() {
|
|
|
41
41
|
InlineMath: (props) => (jsxRuntime.jsx(MissingMdxFeatureInline, Object.assign({}, props, { feature: "math", component: "InlineMath" }))),
|
|
42
42
|
Mermaid: (props) => (jsxRuntime.jsx(MissingMdxFeatureBlock, Object.assign({}, props, { feature: "diagram renderer", component: "Mermaid" }))),
|
|
43
43
|
TypeTable: (props) => (jsxRuntime.jsx(MissingMdxFeatureBlock, Object.assign({}, props, { feature: "API table renderer", component: "TypeTable" }))),
|
|
44
|
+
CodeBlockTab: (props) => (jsxRuntime.jsx(MissingMdxFeatureBlock, Object.assign({}, props, { feature: "code", component: "CodeBlockTab" }))),
|
|
45
|
+
CodeBlockTabs: (props) => (jsxRuntime.jsx(MissingMdxFeatureBlock, Object.assign({}, props, { feature: "code", component: "CodeBlockTabs" }))),
|
|
46
|
+
CodeBlockTabsList: (props) => (jsxRuntime.jsx(MissingMdxFeatureBlock, Object.assign({}, props, { feature: "code", component: "CodeBlockTabsList" }))),
|
|
47
|
+
CodeBlockTabsTrigger: (props) => (jsxRuntime.jsx(MissingMdxFeatureBlock, Object.assign({}, props, { feature: "code", component: "CodeBlockTabsTrigger" }))),
|
|
44
48
|
};
|
|
45
49
|
}
|
|
50
|
+
function createMissingMdxComponentFallback(component) {
|
|
51
|
+
return function MissingMdxComponent(props) {
|
|
52
|
+
return (jsxRuntime.jsx(MissingMdxFeatureBlock, Object.assign({}, props, { feature: "unknown MDX component", component: component })));
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function withMissingMdxComponentFallback(components) {
|
|
56
|
+
return new Proxy(components, {
|
|
57
|
+
has(target, prop) {
|
|
58
|
+
if (typeof prop === 'string' && /^[A-Z]/.test(prop)) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return prop in target;
|
|
62
|
+
},
|
|
63
|
+
get(target, prop, receiver) {
|
|
64
|
+
if (typeof prop !== 'string' || prop in target) {
|
|
65
|
+
return Reflect.get(target, prop, receiver);
|
|
66
|
+
}
|
|
67
|
+
if (/^[A-Z]/.test(prop)) {
|
|
68
|
+
return createMissingMdxComponentFallback(prop);
|
|
69
|
+
}
|
|
70
|
+
return Reflect.get(target, prop, receiver);
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
46
74
|
|
|
47
75
|
exports.MissingMdxFeatureBlock = MissingMdxFeatureBlock;
|
|
48
76
|
exports.MissingMdxFeatureInline = MissingMdxFeatureInline;
|
|
77
|
+
exports.createMissingMdxComponentFallback = createMissingMdxComponentFallback;
|
|
49
78
|
exports.createMissingMdxFeatureComponents = createMissingMdxFeatureComponents;
|
|
79
|
+
exports.withMissingMdxComponentFallback = withMissingMdxComponentFallback;
|
|
@@ -39,7 +39,35 @@ function createMissingMdxFeatureComponents() {
|
|
|
39
39
|
InlineMath: (props) => (jsx(MissingMdxFeatureInline, Object.assign({}, props, { feature: "math", component: "InlineMath" }))),
|
|
40
40
|
Mermaid: (props) => (jsx(MissingMdxFeatureBlock, Object.assign({}, props, { feature: "diagram renderer", component: "Mermaid" }))),
|
|
41
41
|
TypeTable: (props) => (jsx(MissingMdxFeatureBlock, Object.assign({}, props, { feature: "API table renderer", component: "TypeTable" }))),
|
|
42
|
+
CodeBlockTab: (props) => (jsx(MissingMdxFeatureBlock, Object.assign({}, props, { feature: "code", component: "CodeBlockTab" }))),
|
|
43
|
+
CodeBlockTabs: (props) => (jsx(MissingMdxFeatureBlock, Object.assign({}, props, { feature: "code", component: "CodeBlockTabs" }))),
|
|
44
|
+
CodeBlockTabsList: (props) => (jsx(MissingMdxFeatureBlock, Object.assign({}, props, { feature: "code", component: "CodeBlockTabsList" }))),
|
|
45
|
+
CodeBlockTabsTrigger: (props) => (jsx(MissingMdxFeatureBlock, Object.assign({}, props, { feature: "code", component: "CodeBlockTabsTrigger" }))),
|
|
42
46
|
};
|
|
43
47
|
}
|
|
48
|
+
function createMissingMdxComponentFallback(component) {
|
|
49
|
+
return function MissingMdxComponent(props) {
|
|
50
|
+
return (jsx(MissingMdxFeatureBlock, Object.assign({}, props, { feature: "unknown MDX component", component: component })));
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function withMissingMdxComponentFallback(components) {
|
|
54
|
+
return new Proxy(components, {
|
|
55
|
+
has(target, prop) {
|
|
56
|
+
if (typeof prop === 'string' && /^[A-Z]/.test(prop)) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
return prop in target;
|
|
60
|
+
},
|
|
61
|
+
get(target, prop, receiver) {
|
|
62
|
+
if (typeof prop !== 'string' || prop in target) {
|
|
63
|
+
return Reflect.get(target, prop, receiver);
|
|
64
|
+
}
|
|
65
|
+
if (/^[A-Z]/.test(prop)) {
|
|
66
|
+
return createMissingMdxComponentFallback(prop);
|
|
67
|
+
}
|
|
68
|
+
return Reflect.get(target, prop, receiver);
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
}
|
|
44
72
|
|
|
45
|
-
export { MissingMdxFeatureBlock, MissingMdxFeatureInline, createMissingMdxFeatureComponents };
|
|
73
|
+
export { MissingMdxFeatureBlock, MissingMdxFeatureInline, createMissingMdxComponentFallback, createMissingMdxFeatureComponents, withMissingMdxComponentFallback };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@windrun-huaiin/third-ui",
|
|
3
|
-
"version": "23.
|
|
3
|
+
"version": "23.1.1",
|
|
4
4
|
"description": "Third-party integrated UI components for windrun-huaiin projects",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./clerk": {
|
|
@@ -48,11 +48,6 @@
|
|
|
48
48
|
"import": "./dist/fuma/server.mjs",
|
|
49
49
|
"require": "./dist/fuma/server.js"
|
|
50
50
|
},
|
|
51
|
-
"./fuma/server/site-mdx-components": {
|
|
52
|
-
"types": "./dist/fuma/server/site-mdx-components.d.ts",
|
|
53
|
-
"import": "./dist/fuma/server/site-mdx-components.mjs",
|
|
54
|
-
"require": "./dist/fuma/server/site-mdx-components.js"
|
|
55
|
-
},
|
|
56
51
|
"./fuma/server/site-mdx/base": {
|
|
57
52
|
"types": "./dist/fuma/server/site-mdx-base.d.ts",
|
|
58
53
|
"import": "./dist/fuma/server/site-mdx-base.mjs",
|
|
@@ -93,11 +88,6 @@
|
|
|
93
88
|
"import": "./dist/fuma/mdx/index.mjs",
|
|
94
89
|
"require": "./dist/fuma/mdx/index.js"
|
|
95
90
|
},
|
|
96
|
-
"./fuma/server/optional-features": {
|
|
97
|
-
"types": "./dist/fuma/server/optional-features.d.ts",
|
|
98
|
-
"import": "./dist/fuma/server/optional-features.mjs",
|
|
99
|
-
"require": "./dist/fuma/server/optional-features.js"
|
|
100
|
-
},
|
|
101
91
|
"./fuma/base": {
|
|
102
92
|
"types": "./dist/fuma/base/index.d.ts",
|
|
103
93
|
"import": "./dist/fuma/base/index.mjs",
|
|
@@ -147,9 +137,9 @@
|
|
|
147
137
|
"tslib": "^2.8.1",
|
|
148
138
|
"unified": "^11.0.5",
|
|
149
139
|
"zod": "^4.3.6",
|
|
150
|
-
"@windrun-huaiin/base-ui": "^23.
|
|
151
|
-
"@windrun-huaiin/
|
|
152
|
-
"@windrun-huaiin/
|
|
140
|
+
"@windrun-huaiin/base-ui": "^23.1.0",
|
|
141
|
+
"@windrun-huaiin/contracts": "^23.1.0",
|
|
142
|
+
"@windrun-huaiin/lib": "^23.1.0"
|
|
153
143
|
},
|
|
154
144
|
"peerDependencies": {
|
|
155
145
|
"clsx": "^2.1.1",
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/page';
|
|
2
|
-
import { ReactNode, ReactElement, cloneElement } from 'react';
|
|
2
|
+
import { ReactNode, ReactElement, cloneElement, type CSSProperties } from 'react';
|
|
3
3
|
import { TocFooterWrapper } from '@third-ui/fuma/mdx/toc-footer-wrapper';
|
|
4
4
|
import type { LLMCopyButtonProps, LLMCopyButton } from '@third-ui/fuma/mdx/toc-base';
|
|
5
5
|
import { getAsNeededLocalizedUrl } from '@windrun-huaiin/lib';
|
|
6
|
-
import { PortableClerkTOC } from '@third-ui/fuma/mdx/toc-clerk-portable';
|
|
6
|
+
import { PortableClerkTOC, PortableClerkTOCTitle } from '@third-ui/fuma/mdx/toc-clerk-portable';
|
|
7
|
+
import { themeSvgIconColor } from '@windrun-huaiin/base-ui/lib';
|
|
8
|
+
|
|
9
|
+
export type FumaPageTocRenderMode =
|
|
10
|
+
| 'portable-clerk'
|
|
11
|
+
| 'fumadocs-clerk'
|
|
12
|
+
| 'fumadocs-normal';
|
|
7
13
|
|
|
8
14
|
interface FumaPageParams {
|
|
9
15
|
/*
|
|
@@ -49,6 +55,17 @@ interface FumaPageParams {
|
|
|
49
55
|
// default true
|
|
50
56
|
showTableOfContent?: boolean;
|
|
51
57
|
|
|
58
|
+
/*
|
|
59
|
+
* Controls which TOC renderer is used.
|
|
60
|
+
*
|
|
61
|
+
* - portable-clerk: use @third-ui's custom Clerk-like TOC renderer.
|
|
62
|
+
* - fumadocs-clerk: use fumadocs-ui's built-in clerk slot renderer.
|
|
63
|
+
* - fumadocs-normal: use fumadocs-ui's built-in normal slot renderer.
|
|
64
|
+
*
|
|
65
|
+
* @defaultValue 'portable-clerk'
|
|
66
|
+
*/
|
|
67
|
+
tocRenderMode?: FumaPageTocRenderMode;
|
|
68
|
+
|
|
52
69
|
/*
|
|
53
70
|
* @deprecated Mobile TOC popover is no longer used.
|
|
54
71
|
*/
|
|
@@ -77,6 +94,7 @@ export function createFumaPage({
|
|
|
77
94
|
supportedLocales = ['en'],
|
|
78
95
|
showBreadcrumb = true,
|
|
79
96
|
showTableOfContent = true,
|
|
97
|
+
tocRenderMode = 'portable-clerk',
|
|
80
98
|
showTableOfContentPopover = false,
|
|
81
99
|
localePrefixAsNeeded = true,
|
|
82
100
|
defaultLocale = 'en',
|
|
@@ -123,18 +141,15 @@ export function createFumaPage({
|
|
|
123
141
|
return (
|
|
124
142
|
<DocsPage
|
|
125
143
|
breadcrumb={{enabled: showBreadcrumb}}
|
|
126
|
-
tableOfContent={{
|
|
144
|
+
tableOfContent={resolveTableOfContentOptions({
|
|
127
145
|
enabled: showTableOfContent,
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
footer={tocFooterElement}
|
|
133
|
-
/>
|
|
134
|
-
),
|
|
135
|
-
}}
|
|
146
|
+
tocRenderMode,
|
|
147
|
+
toc: content.toc,
|
|
148
|
+
footer: tocFooterElement,
|
|
149
|
+
})}
|
|
136
150
|
tableOfContentPopover={{
|
|
137
|
-
enabled:
|
|
151
|
+
enabled: showTableOfContentPopover && tocRenderMode !== 'portable-clerk',
|
|
152
|
+
style: tocRenderMode === 'fumadocs-clerk' ? 'clerk' : 'normal',
|
|
138
153
|
}}
|
|
139
154
|
toc={content.toc}
|
|
140
155
|
className="max-sm:pb-16"
|
|
@@ -194,3 +209,56 @@ export function createFumaPage({
|
|
|
194
209
|
generateMetadata,
|
|
195
210
|
};
|
|
196
211
|
}
|
|
212
|
+
|
|
213
|
+
function resolveTableOfContentOptions({
|
|
214
|
+
enabled,
|
|
215
|
+
tocRenderMode,
|
|
216
|
+
toc,
|
|
217
|
+
footer,
|
|
218
|
+
}: {
|
|
219
|
+
enabled: boolean;
|
|
220
|
+
tocRenderMode: FumaPageTocRenderMode;
|
|
221
|
+
toc: any[];
|
|
222
|
+
footer: ReactNode;
|
|
223
|
+
}) {
|
|
224
|
+
if (tocRenderMode === 'portable-clerk') {
|
|
225
|
+
return {
|
|
226
|
+
enabled,
|
|
227
|
+
single: false,
|
|
228
|
+
component: (
|
|
229
|
+
<PortableClerkTOC
|
|
230
|
+
toc={toc}
|
|
231
|
+
footer={footer}
|
|
232
|
+
/>
|
|
233
|
+
),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const themedTocProps = {
|
|
238
|
+
container: {
|
|
239
|
+
className: '[--color-fd-primary:var(--third-ui-toc-primary)] [--color-fd-primary-foreground:var(--third-ui-toc-primary-foreground)] [&_#toc-title]:hidden',
|
|
240
|
+
style: {
|
|
241
|
+
'--third-ui-toc-primary': themeSvgIconColor,
|
|
242
|
+
'--third-ui-toc-primary-foreground': '#ffffff',
|
|
243
|
+
} as CSSProperties,
|
|
244
|
+
},
|
|
245
|
+
header: <PortableClerkTOCTitle />,
|
|
246
|
+
footer,
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
if (tocRenderMode === 'fumadocs-clerk') {
|
|
250
|
+
return {
|
|
251
|
+
enabled,
|
|
252
|
+
single: false,
|
|
253
|
+
style: 'clerk',
|
|
254
|
+
...themedTocProps,
|
|
255
|
+
} as const;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return {
|
|
259
|
+
enabled,
|
|
260
|
+
single: false,
|
|
261
|
+
style: 'normal',
|
|
262
|
+
...themedTocProps,
|
|
263
|
+
} as const;
|
|
264
|
+
}
|
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
* https://github.com/fuma-nama/fumadocs/blob/dev/packages/radix-ui/src/components/toc/clerk.tsx
|
|
6
6
|
*/
|
|
7
7
|
import * as Primitive from 'fumadocs-core/toc';
|
|
8
|
+
import { I18nLabel } from 'fumadocs-ui/contexts/i18n';
|
|
8
9
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from 'fumadocs-ui/layouts/docs/page/slots/toc';
|
|
10
|
+
Collapsible,
|
|
11
|
+
CollapsibleContent,
|
|
12
|
+
CollapsibleTrigger,
|
|
13
|
+
} from 'fumadocs-ui/components/ui/collapsible';
|
|
14
14
|
import {
|
|
15
15
|
type ComponentProps,
|
|
16
16
|
type ReactNode,
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
themeIconColor,
|
|
25
25
|
themeSvgIconColor,
|
|
26
26
|
} from '@windrun-huaiin/base-ui/lib';
|
|
27
|
+
import { ChevronDownIcon, NotepadTextIcon } from '@windrun-huaiin/base-ui/icons';
|
|
27
28
|
|
|
28
29
|
type TOCItemType = Primitive.TOCItemType;
|
|
29
30
|
|
|
@@ -84,20 +85,20 @@ export function PortableClerkTOC({
|
|
|
84
85
|
className,
|
|
85
86
|
}: PortableClerkTOCProps) {
|
|
86
87
|
return (
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
88
|
+
<div
|
|
89
|
+
id="nd-toc"
|
|
90
|
+
className={cn(
|
|
91
|
+
'sticky top-(--fd-docs-row-1) h-[calc(var(--fd-docs-height)-var(--fd-docs-row-1))] flex flex-col [grid-area:toc] w-(--fd-toc-width) pt-12 pe-4 pb-2 max-xl:hidden',
|
|
92
|
+
className,
|
|
93
|
+
)}
|
|
94
|
+
>
|
|
95
|
+
{header}
|
|
96
|
+
{title ?? <PortableClerkTOCTitle />}
|
|
97
|
+
<PortableClerkTOCScrollArea>
|
|
98
|
+
<PortableClerkTOCItems toc={toc} emptyLabel={emptyLabel} />
|
|
99
|
+
</PortableClerkTOCScrollArea>
|
|
100
|
+
{footer}
|
|
101
|
+
</div>
|
|
101
102
|
);
|
|
102
103
|
}
|
|
103
104
|
|
|
@@ -108,14 +109,51 @@ export function PortableClerkTOCPopover({
|
|
|
108
109
|
emptyLabel = 'No headings',
|
|
109
110
|
}: Omit<PortableClerkTOCProps, 'title' | 'className'>) {
|
|
110
111
|
return (
|
|
111
|
-
<
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
112
|
+
<Collapsible
|
|
113
|
+
data-toc-popover=""
|
|
114
|
+
className="sticky top-(--fd-docs-row-2) z-10 [grid-area:toc-popover] h-(--fd-toc-popover-height) xl:hidden max-xl:layout:[--fd-toc-popover-height:--spacing(10)]"
|
|
115
|
+
>
|
|
116
|
+
<header className="border-b bg-fd-background/80 backdrop-blur-sm transition-colors">
|
|
117
|
+
<CollapsibleTrigger
|
|
118
|
+
data-toc-popover-trigger=""
|
|
119
|
+
className="flex w-full h-10 items-center text-sm text-fd-muted-foreground gap-2.5 px-4 py-2.5 text-start focus-visible:outline-none [&_svg]:size-4 md:px-6"
|
|
120
|
+
>
|
|
121
|
+
<NotepadTextIcon className="shrink-0" />
|
|
122
|
+
<span className="flex-1 truncate">
|
|
123
|
+
<I18nLabel label="toc" />
|
|
124
|
+
</span>
|
|
125
|
+
<ChevronDownIcon className="shrink-0 transition-transform mx-0.5" />
|
|
126
|
+
</CollapsibleTrigger>
|
|
127
|
+
<CollapsibleContent data-toc-popover-content="">
|
|
128
|
+
<div className="flex max-h-[50vh] flex-col px-4 md:px-6">
|
|
129
|
+
{header}
|
|
130
|
+
<PortableClerkTOCScrollArea>
|
|
131
|
+
<PortableClerkTOCItems toc={toc} emptyLabel={emptyLabel} />
|
|
132
|
+
</PortableClerkTOCScrollArea>
|
|
133
|
+
{footer}
|
|
134
|
+
</div>
|
|
135
|
+
</CollapsibleContent>
|
|
136
|
+
</header>
|
|
137
|
+
</Collapsible>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function PortableClerkTOCTitle({
|
|
142
|
+
className,
|
|
143
|
+
...props
|
|
144
|
+
}: ComponentProps<'h3'>) {
|
|
145
|
+
return (
|
|
146
|
+
<h3
|
|
147
|
+
id="toc-title"
|
|
148
|
+
className={cn(
|
|
149
|
+
'inline-flex items-center gap-1.5 text-sm text-fd-muted-foreground',
|
|
150
|
+
className,
|
|
151
|
+
)}
|
|
152
|
+
{...props}
|
|
153
|
+
>
|
|
154
|
+
<NotepadTextIcon className={cn('size-4', themeIconColor)} />
|
|
155
|
+
<I18nLabel label="toc" />
|
|
156
|
+
</h3>
|
|
119
157
|
);
|
|
120
158
|
}
|
|
121
159
|
|
|
@@ -78,17 +78,13 @@ function tryToMatchIcon(
|
|
|
78
78
|
return undefined;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
export function createCodeMdxComponents(
|
|
82
|
-
iconMap: Record<string, ReactNode> = {},
|
|
83
|
-
): MDXComponents {
|
|
84
|
-
const mergedIconMap = {
|
|
85
|
-
...defaultCodeLanguageIconMap,
|
|
86
|
-
...iconMap,
|
|
87
|
-
};
|
|
88
|
-
|
|
81
|
+
export function createCodeMdxComponents(): MDXComponents {
|
|
89
82
|
return {
|
|
90
83
|
pre: (props) => {
|
|
91
|
-
const customIcon = tryToMatchIcon(
|
|
84
|
+
const customIcon = tryToMatchIcon(
|
|
85
|
+
props as MDXProps & { 'data-language'?: string; title?: string },
|
|
86
|
+
defaultCodeLanguageIconMap,
|
|
87
|
+
);
|
|
92
88
|
return (
|
|
93
89
|
<CodeBlock
|
|
94
90
|
{...props}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
|
2
2
|
import { Callout } from 'fumadocs-ui/components/callout';
|
|
3
|
+
import { Card, Cards } from 'fumadocs-ui/components/card';
|
|
3
4
|
import { File, Folder, Files } from 'fumadocs-ui/components/files';
|
|
4
5
|
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
|
|
5
6
|
import type { MDXComponents } from 'mdx/types';
|
|
6
7
|
import { SiteX } from '../site-x';
|
|
7
8
|
import { createBaseMdxComponents } from './features/base';
|
|
8
9
|
import { createWidgetMdxComponents } from './features/widgets';
|
|
10
|
+
import { withMissingMdxComponentFallback } from './site-mdx-fallbacks';
|
|
9
11
|
|
|
10
12
|
export type SiteMdxFeatureComponents = MDXComponents;
|
|
11
13
|
|
|
@@ -21,6 +23,8 @@ export interface CreateSiteMdxComponentsOptions {
|
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
const defaultFumaUiComponents: MDXComponents = {
|
|
26
|
+
Card,
|
|
27
|
+
Cards,
|
|
24
28
|
Callout,
|
|
25
29
|
File,
|
|
26
30
|
Folder,
|
|
@@ -52,11 +56,11 @@ export function createSiteMdxComponents(
|
|
|
52
56
|
} = options;
|
|
53
57
|
|
|
54
58
|
return function getMDXComponents(components?: MDXComponents): MDXComponents {
|
|
55
|
-
return {
|
|
59
|
+
return withMissingMdxComponentFallback({
|
|
56
60
|
...createSiteMdxBaseComponents(baseOptions),
|
|
57
61
|
...features.reduce<MDXComponents>((acc, feature) => ({ ...acc, ...feature }), {}),
|
|
58
62
|
...additionalComponents,
|
|
59
63
|
...components,
|
|
60
|
-
};
|
|
64
|
+
});
|
|
61
65
|
};
|
|
62
66
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef, ReactNode } from 'react';
|
|
2
|
+
import type { MDXComponents } from 'mdx/types';
|
|
2
3
|
|
|
3
4
|
type MissingFeatureBlockProps = ComponentPropsWithoutRef<'div'> & {
|
|
4
5
|
feature: string;
|
|
@@ -118,5 +119,54 @@ export function createMissingMdxFeatureComponents() {
|
|
|
118
119
|
TypeTable: (props: ComponentPropsWithoutRef<'div'>) => (
|
|
119
120
|
<MissingMdxFeatureBlock {...props} feature="API table renderer" component="TypeTable" />
|
|
120
121
|
),
|
|
122
|
+
CodeBlockTab: (props: ComponentPropsWithoutRef<'div'>) => (
|
|
123
|
+
<MissingMdxFeatureBlock {...props} feature="code" component="CodeBlockTab" />
|
|
124
|
+
),
|
|
125
|
+
CodeBlockTabs: (props: ComponentPropsWithoutRef<'div'>) => (
|
|
126
|
+
<MissingMdxFeatureBlock {...props} feature="code" component="CodeBlockTabs" />
|
|
127
|
+
),
|
|
128
|
+
CodeBlockTabsList: (props: ComponentPropsWithoutRef<'div'>) => (
|
|
129
|
+
<MissingMdxFeatureBlock {...props} feature="code" component="CodeBlockTabsList" />
|
|
130
|
+
),
|
|
131
|
+
CodeBlockTabsTrigger: (props: ComponentPropsWithoutRef<'div'>) => (
|
|
132
|
+
<MissingMdxFeatureBlock {...props} feature="code" component="CodeBlockTabsTrigger" />
|
|
133
|
+
),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function createMissingMdxComponentFallback(component: string) {
|
|
138
|
+
return function MissingMdxComponent(props: ComponentPropsWithoutRef<'div'>) {
|
|
139
|
+
return (
|
|
140
|
+
<MissingMdxFeatureBlock
|
|
141
|
+
{...props}
|
|
142
|
+
feature="unknown MDX component"
|
|
143
|
+
component={component}
|
|
144
|
+
/>
|
|
145
|
+
);
|
|
121
146
|
};
|
|
122
147
|
}
|
|
148
|
+
|
|
149
|
+
export function withMissingMdxComponentFallback(
|
|
150
|
+
components: MDXComponents,
|
|
151
|
+
): MDXComponents {
|
|
152
|
+
return new Proxy(components, {
|
|
153
|
+
has(target, prop) {
|
|
154
|
+
if (typeof prop === 'string' && /^[A-Z]/.test(prop)) {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return prop in target;
|
|
159
|
+
},
|
|
160
|
+
get(target, prop, receiver) {
|
|
161
|
+
if (typeof prop !== 'string' || prop in target) {
|
|
162
|
+
return Reflect.get(target, prop, receiver);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (/^[A-Z]/.test(prop)) {
|
|
166
|
+
return createMissingMdxComponentFallback(prop);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return Reflect.get(target, prop, receiver);
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export { createBaseMdxComponents } from './features/base';
|
|
2
|
-
export { createCodeMdxComponents } from './features/code';
|
|
3
|
-
export { createMathMdxComponents } from './features/math';
|
|
4
|
-
export { createMermaidMdxComponents } from './features/mermaid';
|
|
5
|
-
export { createTypeTableMdxComponents } from './features/type-table';
|
|
6
|
-
export { createWidgetMdxComponents } from './features/widgets';
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { MDXComponents } from 'mdx/types';
|
|
2
|
-
import type { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
createComposedSiteMdxComponents,
|
|
5
|
-
DEFAULT_SITE_MDX_FEATURES,
|
|
6
|
-
type SiteMdxFeature,
|
|
7
|
-
} from './site-mdx-presets';
|
|
8
|
-
|
|
9
|
-
export interface SiteMdxComponentsOptions {
|
|
10
|
-
imageFallbackSrc?: string;
|
|
11
|
-
cdnBaseUrl?: string;
|
|
12
|
-
watermarkEnabled?: boolean;
|
|
13
|
-
watermarkText?: string;
|
|
14
|
-
additionalComponents?: MDXComponents;
|
|
15
|
-
iconMap?: Record<string, ReactNode>;
|
|
16
|
-
features?: SiteMdxFeature[];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function createSiteMdxComponents(
|
|
20
|
-
options: SiteMdxComponentsOptions,
|
|
21
|
-
) {
|
|
22
|
-
const {
|
|
23
|
-
additionalComponents,
|
|
24
|
-
cdnBaseUrl,
|
|
25
|
-
features = DEFAULT_SITE_MDX_FEATURES,
|
|
26
|
-
iconMap = {},
|
|
27
|
-
imageFallbackSrc,
|
|
28
|
-
watermarkEnabled,
|
|
29
|
-
watermarkText,
|
|
30
|
-
} = options;
|
|
31
|
-
|
|
32
|
-
return function getMDXComponents(components?: MDXComponents): MDXComponents {
|
|
33
|
-
return createComposedSiteMdxComponents(
|
|
34
|
-
features,
|
|
35
|
-
{
|
|
36
|
-
cdnBaseUrl,
|
|
37
|
-
iconMap,
|
|
38
|
-
imageFallbackSrc,
|
|
39
|
-
watermarkEnabled,
|
|
40
|
-
watermarkText,
|
|
41
|
-
},
|
|
42
|
-
additionalComponents,
|
|
43
|
-
components,
|
|
44
|
-
);
|
|
45
|
-
};
|
|
46
|
-
}
|