@windrun-huaiin/third-ui 25.0.0 → 27.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/ai-prompt-textarea.d.ts +72 -0
- package/dist/ai/ai-prompt-textarea.js +114 -0
- package/dist/ai/ai-prompt-textarea.mjs +112 -0
- package/dist/ai/index.d.ts +1 -0
- package/dist/ai/index.js +2 -0
- package/dist/ai/index.mjs +1 -0
- package/dist/clerk/clerk-provider-client.js +0 -1
- package/dist/clerk/clerk-provider-client.mjs +0 -1
- package/dist/clerk/fingerprint/fingerprint-client.js +0 -4
- package/dist/clerk/fingerprint/fingerprint-client.mjs +0 -4
- package/dist/clerk/fingerprint/use-fingerprint.js +0 -6
- package/dist/clerk/fingerprint/use-fingerprint.mjs +0 -6
- package/dist/clerk/signin-with-fingerprint-client.js +0 -9
- package/dist/clerk/signin-with-fingerprint-client.mjs +0 -9
- package/dist/clerk/signup-button-with-fingerprint-client.js +0 -16
- package/dist/clerk/signup-button-with-fingerprint-client.mjs +0 -16
- package/dist/clerk/signup-with-fingerprint-client.js +0 -9
- package/dist/clerk/signup-with-fingerprint-client.mjs +0 -9
- package/dist/fuma/base/custom-header.js +10 -8
- package/dist/fuma/base/custom-header.mjs +10 -8
- package/dist/fuma/base/custom-home-layout.d.ts +1 -0
- package/dist/fuma/base/index.d.ts +1 -0
- package/dist/fuma/base/index.js +4 -0
- package/dist/fuma/base/index.mjs +1 -0
- package/dist/fuma/base/nav-config.d.ts +10 -0
- package/dist/fuma/base/nav-config.js +32 -0
- package/dist/fuma/base/nav-config.mjs +28 -0
- package/dist/fuma/base/site-layout.d.ts +4 -0
- package/dist/fuma/base/site-layout.js +2 -2
- package/dist/fuma/base/site-layout.mjs +2 -2
- package/dist/fuma/fuma-page-genarator.d.ts +1 -1
- package/dist/fuma/fuma-page-genarator.js +60 -5
- package/dist/fuma/fuma-page-genarator.mjs +60 -5
- package/dist/fuma/llm-copy-handler.js +0 -9
- package/dist/fuma/llm-copy-handler.mjs +0 -9
- package/dist/fuma/mdx/index.d.ts +0 -1
- package/dist/fuma/mdx/index.js +0 -2
- package/dist/fuma/mdx/index.mjs +0 -1
- package/dist/fuma/mdx/suno-embed.js +3 -1
- package/dist/fuma/mdx/suno-embed.mjs +3 -1
- package/dist/fuma/mdx/toc-base.js +0 -1
- package/dist/fuma/mdx/toc-base.mjs +0 -1
- package/dist/fuma/server/features/widgets.js +5 -1
- package/dist/fuma/server/features/widgets.mjs +5 -1
- package/dist/lib/site-docs-helper.d.ts +51 -0
- package/dist/lib/site-docs-helper.js +68 -0
- package/dist/lib/site-docs-helper.mjs +66 -0
- package/dist/main/alert-dialog/index.js +14 -0
- package/dist/main/alert-dialog/index.mjs +5 -0
- package/dist/main/buttons/gradient-button.d.ts +20 -0
- package/dist/main/buttons/gradient-button.js +88 -0
- package/dist/main/buttons/gradient-button.mjs +86 -0
- package/dist/main/buttons/index.d.ts +3 -0
- package/dist/main/buttons/index.js +12 -0
- package/dist/main/buttons/index.mjs +4 -0
- package/dist/main/buttons/x-button.d.ts +39 -0
- package/dist/main/buttons/x-button.js +92 -0
- package/dist/main/buttons/x-button.mjs +90 -0
- package/dist/main/buttons/x-toggle-button.d.ts +32 -0
- package/dist/main/buttons/x-toggle-button.js +95 -0
- package/dist/main/buttons/x-toggle-button.mjs +74 -0
- package/dist/main/credit/credit-overview-client.js +3 -2
- package/dist/main/credit/credit-overview-client.mjs +3 -2
- package/dist/main/credit/index.d.ts +4 -0
- package/dist/main/credit/index.js +10 -0
- package/dist/main/credit/index.mjs +3 -0
- package/dist/main/credit/server.d.ts +2 -0
- package/dist/main/credit/server.js +7 -0
- package/dist/main/credit/server.mjs +1 -0
- package/dist/main/cta.js +4 -2
- package/dist/main/cta.mjs +4 -2
- package/dist/main/hero/index.d.ts +2 -0
- package/dist/main/hero/index.js +10 -0
- package/dist/main/hero/index.mjs +3 -0
- package/dist/main/home/server.d.ts +7 -0
- package/dist/main/home/server.js +19 -0
- package/dist/main/home/server.mjs +7 -0
- package/dist/main/index.d.ts +0 -15
- package/dist/main/index.js +0 -43
- package/dist/main/index.mjs +0 -21
- package/dist/main/loading/index.d.ts +1 -0
- package/dist/main/loading/index.js +9 -0
- package/dist/main/loading/index.mjs +2 -0
- package/dist/main/loading-frame/index.d.ts +1 -0
- package/dist/main/loading-frame/index.js +9 -0
- package/dist/main/loading-frame/index.mjs +2 -0
- package/dist/main/money-price/index.d.ts +4 -0
- package/dist/main/money-price/index.js +15 -0
- package/dist/main/money-price/index.mjs +4 -0
- package/dist/main/money-price/money-price-button.d.ts +1 -1
- package/dist/main/money-price/money-price-button.js +10 -7
- package/dist/main/money-price/money-price-button.mjs +10 -7
- package/dist/main/money-price/money-price-interactive.js +9 -8
- package/dist/main/money-price/money-price-interactive.mjs +9 -8
- package/dist/main/money-price/money-price-types.d.ts +1 -0
- package/dist/main/money-price/server.d.ts +5 -0
- package/dist/main/money-price/server.js +18 -0
- package/dist/main/money-price/server.mjs +4 -0
- package/package.json +54 -4
- package/src/ai/index.ts +1 -0
- package/src/clerk/clerk-provider-client.tsx +1 -3
- package/src/clerk/fingerprint/fingerprint-client.ts +0 -4
- package/src/clerk/fingerprint/use-fingerprint.ts +0 -6
- package/src/clerk/signin-with-fingerprint-client.tsx +0 -10
- package/src/clerk/signup-button-with-fingerprint-client.tsx +0 -17
- package/src/clerk/signup-with-fingerprint-client.tsx +0 -10
- package/src/fuma/base/custom-header.tsx +12 -8
- package/src/fuma/base/custom-home-layout.tsx +7 -4
- package/src/fuma/base/index.ts +1 -0
- package/src/fuma/base/nav-config.ts +81 -0
- package/src/fuma/base/site-layout.tsx +6 -0
- package/src/fuma/fuma-banner-suit.tsx +1 -1
- package/src/fuma/fuma-page-genarator.tsx +60 -7
- package/src/fuma/llm-copy-handler.ts +0 -11
- package/src/fuma/mdx/index.ts +0 -1
- package/src/fuma/mdx/suno-embed.tsx +1 -1
- package/src/fuma/mdx/toc-base.tsx +0 -1
- package/src/fuma/mdx/toc-footer-wrapper.tsx +2 -2
- package/src/fuma/server/features/widgets.tsx +1 -1
- package/src/lib/server.ts +1 -1
- package/src/{fuma/mdx → main/buttons}/gradient-button.tsx +10 -21
- package/src/main/buttons/index.ts +5 -0
- package/src/main/{x-button.tsx → buttons/x-button.tsx} +28 -42
- package/src/main/credit/credit-overview-client.tsx +1 -1
- package/src/main/credit/index.ts +11 -0
- package/src/main/credit/server.ts +7 -0
- package/src/main/cta.tsx +1 -1
- package/src/main/hero/index.ts +4 -0
- package/src/main/home/server.ts +7 -0
- package/src/main/index.ts +1 -20
- package/src/main/language-detector.tsx +0 -1
- package/src/main/loading/index.ts +3 -0
- package/src/main/loading-frame/index.ts +3 -0
- package/src/main/money-price/index.ts +18 -0
- package/src/main/money-price/money-price-button.tsx +12 -6
- package/src/main/money-price/money-price-interactive.tsx +17 -10
- package/src/main/money-price/money-price-types.ts +1 -0
- package/src/main/money-price/server.ts +22 -0
- package/dist/fuma/mdx/features.d.ts +0 -8
- package/dist/fuma/mdx/features.js +0 -92
- package/dist/fuma/mdx/features.mjs +0 -85
- package/dist/fuma/mdx/image-grid.d.ts +0 -6
- package/dist/fuma/mdx/image-grid.js +0 -17
- package/dist/fuma/mdx/image-grid.mjs +0 -15
- package/dist/fuma/mdx/image-zoom.d.ts +0 -22
- package/dist/fuma/mdx/image-zoom.js +0 -39
- package/dist/fuma/mdx/image-zoom.mjs +0 -37
- package/dist/fuma/mdx/markdown-component-map.d.ts +0 -3
- package/dist/fuma/mdx/markdown-component-map.js +0 -79
- package/dist/fuma/mdx/markdown-component-map.mjs +0 -77
- package/dist/fuma/mdx/math.d.ts +0 -17
- package/dist/fuma/mdx/math.js +0 -60
- package/dist/fuma/mdx/math.mjs +0 -57
- package/dist/fuma/mdx/mermaid.d.ts +0 -13
- package/dist/fuma/mdx/mermaid.js +0 -360
- package/dist/fuma/mdx/mermaid.mjs +0 -358
- package/dist/fuma/mdx/site-mdx-components.d.ts +0 -13
- package/dist/fuma/mdx/site-mdx-components.js +0 -19
- package/dist/fuma/mdx/site-mdx-components.mjs +0 -17
- package/dist/fuma/mdx/site-mdx-presets.d.ts +0 -13
- package/dist/fuma/mdx/site-mdx-presets.js +0 -49
- package/dist/fuma/mdx/site-mdx-presets.mjs +0 -45
- package/dist/fuma/server/optional-features.d.ts +0 -6
- package/dist/fuma/server/optional-features.js +0 -17
- package/dist/fuma/server/optional-features.mjs +0 -6
- package/dist/fuma/server/site-mdx-components.d.ts +0 -13
- package/dist/fuma/server/site-mdx-components.js +0 -18
- package/dist/fuma/server/site-mdx-components.mjs +0 -16
- package/dist/fuma/server/site-mdx-presets.d.ts +0 -195
- package/dist/fuma/server/site-mdx-presets.js +0 -55
- package/dist/fuma/server/site-mdx-presets.mjs +0 -52
- /package/src/{main → ai}/ai-prompt-textarea.tsx +0 -0
- /package/src/main/{x-toggle-button.tsx → buttons/x-toggle-button.tsx} +0 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CreateSiteNavGroupOptions,
|
|
3
|
+
CreateSiteNavItemContext,
|
|
4
|
+
SiteMenuGroupConfig,
|
|
5
|
+
SiteMenuLeafConfig,
|
|
6
|
+
SiteNavItemConfig,
|
|
7
|
+
SiteNavLinkItemConfig,
|
|
8
|
+
} from './site-layout';
|
|
9
|
+
|
|
10
|
+
export interface LocalizedNavContextOptions {
|
|
11
|
+
locale: string;
|
|
12
|
+
localePrefixAsNeeded?: boolean;
|
|
13
|
+
defaultLocale?: string;
|
|
14
|
+
localizeHref: (locale: string, path: string, localePrefixAsNeeded: boolean, defaultLocale: string) => string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function createLocalizedNavContext(
|
|
18
|
+
options: LocalizedNavContextOptions,
|
|
19
|
+
): CreateSiteNavItemContext {
|
|
20
|
+
const {
|
|
21
|
+
locale,
|
|
22
|
+
localePrefixAsNeeded = true,
|
|
23
|
+
defaultLocale = 'en',
|
|
24
|
+
localizeHref,
|
|
25
|
+
} = options;
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
resolveUrl(path: string) {
|
|
29
|
+
return localizeHref(locale, path, localePrefixAsNeeded, defaultLocale);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function createLocalizedNavLink(
|
|
35
|
+
item: SiteMenuLeafConfig,
|
|
36
|
+
context: CreateSiteNavItemContext,
|
|
37
|
+
): SiteNavItemConfig {
|
|
38
|
+
return {
|
|
39
|
+
type: 'main',
|
|
40
|
+
text: item.text,
|
|
41
|
+
...(item.description ? { description: item.description } : {}),
|
|
42
|
+
url: context.resolveUrl(item.path),
|
|
43
|
+
...(item.external ? { external: item.external } : {}),
|
|
44
|
+
...(item.prefetch !== undefined ? { prefetch: item.prefetch } : {}),
|
|
45
|
+
...(item.icon || item.className
|
|
46
|
+
? {
|
|
47
|
+
menu: {
|
|
48
|
+
...(item.icon ? { banner: item.icon } : {}),
|
|
49
|
+
...(item.className ? { className: item.className } : {}),
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
: {}),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function createLocalizedNavGroup(
|
|
57
|
+
item: SiteMenuGroupConfig,
|
|
58
|
+
context: CreateSiteNavItemContext,
|
|
59
|
+
options?: CreateSiteNavGroupOptions,
|
|
60
|
+
): SiteNavItemConfig {
|
|
61
|
+
return {
|
|
62
|
+
type: 'menu',
|
|
63
|
+
text: item.text,
|
|
64
|
+
...(item.path ? { url: context.resolveUrl(item.path) } : {}),
|
|
65
|
+
...(item.prefetch !== undefined ? { prefetch: item.prefetch } : {}),
|
|
66
|
+
items: [
|
|
67
|
+
...(item.landing
|
|
68
|
+
? [
|
|
69
|
+
{
|
|
70
|
+
...createLocalizedNavLink(item.landing, context),
|
|
71
|
+
menu: {
|
|
72
|
+
...(options?.featuredBanner ? { banner: options.featuredBanner } : {}),
|
|
73
|
+
className: options?.featuredClassName ?? 'md:row-span-2',
|
|
74
|
+
},
|
|
75
|
+
} as SiteNavLinkItemConfig,
|
|
76
|
+
]
|
|
77
|
+
: []),
|
|
78
|
+
...item.items.map((child) => createLocalizedNavLink(child, context)),
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -25,6 +25,7 @@ export interface SiteNavLinkItemConfig extends SiteNavSharedFields {
|
|
|
25
25
|
text: ReactNode;
|
|
26
26
|
url: string;
|
|
27
27
|
external?: boolean;
|
|
28
|
+
prefetch?: boolean;
|
|
28
29
|
icon?: ReactNode;
|
|
29
30
|
description?: ReactNode;
|
|
30
31
|
menu?: SiteMenuConfig;
|
|
@@ -37,6 +38,7 @@ export interface SiteNavMenuItemConfig extends SiteNavSharedFields {
|
|
|
37
38
|
text: ReactNode;
|
|
38
39
|
url?: string;
|
|
39
40
|
external?: boolean;
|
|
41
|
+
prefetch?: boolean;
|
|
40
42
|
icon?: ReactNode;
|
|
41
43
|
description?: ReactNode;
|
|
42
44
|
items: SiteNavItemConfig[];
|
|
@@ -92,11 +94,13 @@ export interface SiteMenuLeafConfig {
|
|
|
92
94
|
icon?: ReactNode;
|
|
93
95
|
className?: string;
|
|
94
96
|
external?: boolean;
|
|
97
|
+
prefetch?: boolean;
|
|
95
98
|
}
|
|
96
99
|
|
|
97
100
|
export interface SiteMenuGroupConfig {
|
|
98
101
|
text: ReactNode;
|
|
99
102
|
path?: string;
|
|
103
|
+
prefetch?: boolean;
|
|
100
104
|
landing?: SiteMenuLeafConfig;
|
|
101
105
|
items: SiteMenuLeafConfig[];
|
|
102
106
|
}
|
|
@@ -147,6 +151,7 @@ export function createSiteNavLink(
|
|
|
147
151
|
...(item.description ? { description: item.description } : {}),
|
|
148
152
|
url: context.resolveUrl(item.path),
|
|
149
153
|
...(item.external ? { external: item.external } : {}),
|
|
154
|
+
...(item.prefetch !== undefined ? { prefetch: item.prefetch } : {}),
|
|
150
155
|
...(item.icon || item.className
|
|
151
156
|
? {
|
|
152
157
|
menu: {
|
|
@@ -167,6 +172,7 @@ export function createSiteNavGroup(
|
|
|
167
172
|
type: 'menu',
|
|
168
173
|
text: item.text,
|
|
169
174
|
...(item.path ? { url: context.resolveUrl(item.path) } : {}),
|
|
175
|
+
...(item.prefetch !== undefined ? { prefetch: item.prefetch } : {}),
|
|
170
176
|
items: [
|
|
171
177
|
...(item.landing
|
|
172
178
|
? [
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/page';
|
|
2
2
|
import { ReactNode, ReactElement, cloneElement, type CSSProperties } from 'react';
|
|
3
|
-
import { TocFooterWrapper } from '
|
|
4
|
-
import type { LLMCopyButtonProps, LLMCopyButton } from '
|
|
3
|
+
import { TocFooterWrapper } from './mdx/toc-footer-wrapper';
|
|
4
|
+
import type { LLMCopyButtonProps, LLMCopyButton } from './mdx/toc-base';
|
|
5
5
|
import { getAsNeededLocalizedUrl } from '@windrun-huaiin/lib';
|
|
6
|
-
import { PortableClerkTOC, PortableClerkTOCTitle } from '
|
|
6
|
+
import { PortableClerkTOC, PortableClerkTOCTitle } from './mdx/toc-clerk-portable';
|
|
7
7
|
import { themeSvgIconColor } from '@windrun-huaiin/base-ui/lib';
|
|
8
8
|
|
|
9
9
|
export type FumaPageTocRenderMode =
|
|
@@ -99,6 +99,14 @@ export function createFumaPage({
|
|
|
99
99
|
localePrefixAsNeeded = true,
|
|
100
100
|
defaultLocale = 'en',
|
|
101
101
|
}: FumaPageParams) {
|
|
102
|
+
const isLocalMdDebugEnabled = process.env.LOCAL_MD_DEBUG?.toLowerCase() === 'true';
|
|
103
|
+
const now = () => (typeof performance !== 'undefined' ? performance.now() : Date.now());
|
|
104
|
+
const durationMs = (startedAt: number) => Number((now() - startedAt).toFixed(1));
|
|
105
|
+
const logFumaPageDebug = (message: string, details?: Record<string, unknown>) => {
|
|
106
|
+
if (!isLocalMdDebugEnabled) return;
|
|
107
|
+
console.log(`[fuma-page] ${message}`, details ?? {});
|
|
108
|
+
};
|
|
109
|
+
|
|
102
110
|
const getSource = async () => {
|
|
103
111
|
if (typeof mdxContentSource === 'function') {
|
|
104
112
|
return await mdxContentSource();
|
|
@@ -108,11 +116,28 @@ export function createFumaPage({
|
|
|
108
116
|
};
|
|
109
117
|
|
|
110
118
|
const Page = async function Page({ params }: { params: Promise<{ locale: string; slug?: string[] }> }) {
|
|
119
|
+
const pageStartedAt = now();
|
|
111
120
|
const { slug, locale } = await params;
|
|
121
|
+
const sourceStartedAt = now();
|
|
112
122
|
const source = await getSource();
|
|
123
|
+
logFumaPageDebug('page:source-ready', {
|
|
124
|
+
sourceKey,
|
|
125
|
+
locale,
|
|
126
|
+
slug,
|
|
127
|
+
durationMs: durationMs(sourceStartedAt),
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const getPageStartedAt = now();
|
|
113
131
|
const page = source.getPage(slug, locale);
|
|
132
|
+
logFumaPageDebug('page:get-page', {
|
|
133
|
+
sourceKey,
|
|
134
|
+
locale,
|
|
135
|
+
slug,
|
|
136
|
+
found: Boolean(page),
|
|
137
|
+
durationMs: durationMs(getPageStartedAt),
|
|
138
|
+
totalElapsedMs: durationMs(pageStartedAt),
|
|
139
|
+
});
|
|
114
140
|
if (!page) {
|
|
115
|
-
console.log('[FumaPage] missing page', { slug, locale, available: source.pageTree?.[locale]?.children?.map((c: any) => c.url) });
|
|
116
141
|
return (
|
|
117
142
|
<DocsPage
|
|
118
143
|
full
|
|
@@ -143,7 +168,19 @@ export function createFumaPage({
|
|
|
143
168
|
|
|
144
169
|
const content =
|
|
145
170
|
typeof page.data.load === 'function'
|
|
146
|
-
? await
|
|
171
|
+
? await (async () => {
|
|
172
|
+
const loadStartedAt = now();
|
|
173
|
+
const result = await page.data.load(getMDXComponents());
|
|
174
|
+
logFumaPageDebug('page:load', {
|
|
175
|
+
sourceKey,
|
|
176
|
+
locale,
|
|
177
|
+
slug,
|
|
178
|
+
pagePath: page.path,
|
|
179
|
+
durationMs: durationMs(loadStartedAt),
|
|
180
|
+
totalElapsedMs: durationMs(pageStartedAt),
|
|
181
|
+
});
|
|
182
|
+
return result;
|
|
183
|
+
})()
|
|
147
184
|
: {
|
|
148
185
|
body: await page.data.body({ components: getMDXComponents() }),
|
|
149
186
|
toc: page.data.toc ?? [],
|
|
@@ -174,14 +211,30 @@ export function createFumaPage({
|
|
|
174
211
|
);
|
|
175
212
|
};
|
|
176
213
|
|
|
177
|
-
function generateStaticParams() {
|
|
178
|
-
|
|
214
|
+
async function generateStaticParams() {
|
|
215
|
+
const startedAt = now();
|
|
216
|
+
const source = await getSource();
|
|
217
|
+
const params = source.generateParams('slug', 'locale');
|
|
218
|
+
logFumaPageDebug('generateStaticParams', {
|
|
219
|
+
sourceKey,
|
|
220
|
+
count: Array.isArray(params) ? params.length : undefined,
|
|
221
|
+
durationMs: durationMs(startedAt),
|
|
222
|
+
});
|
|
223
|
+
return params;
|
|
179
224
|
}
|
|
180
225
|
|
|
181
226
|
async function generateMetadata(props: { params: Promise<{ slug?: string[]; locale?: string }> }) {
|
|
227
|
+
const startedAt = now();
|
|
182
228
|
const { slug, locale } = await props.params;
|
|
183
229
|
const source = await getSource();
|
|
184
230
|
const page = source.getPage(slug, locale);
|
|
231
|
+
logFumaPageDebug('generateMetadata:get-page', {
|
|
232
|
+
sourceKey,
|
|
233
|
+
locale,
|
|
234
|
+
slug,
|
|
235
|
+
found: Boolean(page),
|
|
236
|
+
durationMs: durationMs(startedAt),
|
|
237
|
+
});
|
|
185
238
|
if (!page) {
|
|
186
239
|
return {
|
|
187
240
|
title: '404 - Page Not Found',
|
|
@@ -21,17 +21,10 @@ export type LLMCopyHandlerOptions = {
|
|
|
21
21
|
*/
|
|
22
22
|
export async function LLMCopyHandler(options: LLMCopyHandlerOptions): Promise<{ text?: string; error?: string; status: number }> {
|
|
23
23
|
const { sourceDir, dataSource, requestedPath, locale } = options;
|
|
24
|
-
|
|
25
|
-
// log received parameters
|
|
26
|
-
console.log(`[LLMCopy] Received, locale=${locale}, path=${requestedPath}`);
|
|
27
|
-
|
|
28
24
|
const slug = requestedPath?.split('/') || [];
|
|
29
25
|
|
|
30
26
|
try {
|
|
31
|
-
console.log('[LLMCopy] Attempting to call getPage()');
|
|
32
27
|
const page = dataSource.getPage(slug, locale);
|
|
33
|
-
// console.log(page);
|
|
34
|
-
console.log('[LLMCopy] Call to getPage() completed.');
|
|
35
28
|
|
|
36
29
|
if (!page) {
|
|
37
30
|
console.error(`[LLMCopy] Page or page data not found for locale=${locale}, path=${requestedPath}`);
|
|
@@ -46,19 +39,15 @@ export async function LLMCopyHandler(options: LLMCopyHandlerOptions): Promise<{
|
|
|
46
39
|
const description = page.data?.description ?? page.description;
|
|
47
40
|
const relativeMdxFilePath = page.path;
|
|
48
41
|
const absoluteFilePath = nodePath.join(process.cwd(), sourceDir, relativeMdxFilePath);
|
|
49
|
-
console.log(`[LLMCopy] Attempting to read MDX content from: ${absoluteFilePath}`);
|
|
50
42
|
|
|
51
43
|
let mdxContent: string;
|
|
52
44
|
try {
|
|
53
45
|
mdxContent = fs.readFileSync(absoluteFilePath, 'utf-8');
|
|
54
|
-
console.log(`[LLMCopy] Successfully read MDX content from: ${absoluteFilePath}`);
|
|
55
46
|
} catch (readError: any) {
|
|
56
47
|
console.error(`[LLMCopy] Failed to read file at: ${absoluteFilePath}. Error: ${readError.message}`);
|
|
57
48
|
console.error('[LLMCopy] Read Error object details:', JSON.stringify(readError, Object.getOwnPropertyNames(readError), 2));
|
|
58
49
|
// directory traversal debug logs
|
|
59
50
|
try {
|
|
60
|
-
console.log(`[LLMCopy] Current CWD: ${process.cwd()}`);
|
|
61
|
-
console.log(`[LLMCopy] CWD contents: ${fs.readdirSync(process.cwd()).join(', ')}`);
|
|
62
51
|
const srcPath = nodePath.join(process.cwd(), 'src');
|
|
63
52
|
if (fs.existsSync(srcPath)) {
|
|
64
53
|
console.log(`[LLMCopy] src dir contents: ${fs.readdirSync(srcPath).join(', ')}`);
|
package/src/fuma/mdx/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { useEffect, useRef, useState } from 'react';
|
|
|
4
4
|
import { cn } from '@windrun-huaiin/lib/utils';
|
|
5
5
|
import { themeBgColor, themeSvgIconColor } from '@windrun-huaiin/base-ui/lib';
|
|
6
6
|
import { SnakeLoadingFrame } from '../../main/snake-loading-frame';
|
|
7
|
-
import { GradientButton } from '
|
|
7
|
+
import { GradientButton } from '../../main/buttons';
|
|
8
8
|
|
|
9
9
|
interface SunoEmbedProps {
|
|
10
10
|
src: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { EditOnGitHub, LastUpdatedDate } from '
|
|
3
|
+
import { EditOnGitHub, LastUpdatedDate } from './toc-base';
|
|
4
4
|
import React from 'react';
|
|
5
5
|
|
|
6
6
|
interface TocFooterProps {
|
|
@@ -19,4 +19,4 @@ export function TocFooterWrapper({ lastModified, editPath, githubBaseUrl, copyBu
|
|
|
19
19
|
{showEdit && <EditOnGitHub url={`${githubBaseUrl}${editPath}`} />}
|
|
20
20
|
</div>
|
|
21
21
|
);
|
|
22
|
-
}
|
|
22
|
+
}
|
|
@@ -2,7 +2,7 @@ import type { MDXComponents } from 'mdx/types';
|
|
|
2
2
|
import { lazy } from 'react';
|
|
3
3
|
import { TrophyCard } from '../../mdx/trophy-card';
|
|
4
4
|
import { ZiaCard } from '../../mdx/zia-card';
|
|
5
|
-
import { GradientButton } from '
|
|
5
|
+
import { GradientButton } from '../../../main/buttons';
|
|
6
6
|
import { ZiaFile, ZiaFolder } from '../../mdx/zia-file';
|
|
7
7
|
import { SunoEmbed } from '../../mdx/suno-embed';
|
|
8
8
|
|
package/src/lib/server.ts
CHANGED
|
@@ -23,12 +23,9 @@ export interface GradientButtonProps {
|
|
|
23
23
|
disabled?: boolean;
|
|
24
24
|
className?: string;
|
|
25
25
|
iconClassName?: string;
|
|
26
|
-
// for Link
|
|
27
26
|
href?: string;
|
|
28
27
|
openInNewTab?: boolean;
|
|
29
28
|
preserveReferrer?: boolean;
|
|
30
|
-
|
|
31
|
-
// for click
|
|
32
29
|
onClick?: () => void | Promise<void>;
|
|
33
30
|
loadingText?: React.ReactNode;
|
|
34
31
|
preventDoubleClick?: boolean;
|
|
@@ -52,7 +49,7 @@ export function GradientButton({
|
|
|
52
49
|
variant = 'default',
|
|
53
50
|
}: GradientButtonProps) {
|
|
54
51
|
const [isLoading, setIsLoading] = useState(false);
|
|
55
|
-
const actualLoadingText = loadingText || title?.toString().trim() || 'Loading...'
|
|
52
|
+
const actualLoadingText = loadingText || title?.toString().trim() || 'Loading...';
|
|
56
53
|
|
|
57
54
|
const defaultIconClass = "h-4 w-4";
|
|
58
55
|
const finalIconClass = cn(
|
|
@@ -60,14 +57,13 @@ export function GradientButton({
|
|
|
60
57
|
iconClassName || defaultIconClass
|
|
61
58
|
);
|
|
62
59
|
|
|
63
|
-
// set justify class according to alignment
|
|
64
60
|
const getAlignmentClass = () => {
|
|
65
61
|
switch (align) {
|
|
66
62
|
case 'center':
|
|
67
63
|
return 'justify-center';
|
|
68
64
|
case 'right':
|
|
69
65
|
return 'justify-end';
|
|
70
|
-
default:
|
|
66
|
+
default:
|
|
71
67
|
return 'justify-start';
|
|
72
68
|
}
|
|
73
69
|
};
|
|
@@ -80,11 +76,11 @@ export function GradientButton({
|
|
|
80
76
|
|
|
81
77
|
if (onClick) {
|
|
82
78
|
e.preventDefault();
|
|
83
|
-
|
|
79
|
+
|
|
84
80
|
if (preventDoubleClick) {
|
|
85
81
|
setIsLoading(true);
|
|
86
82
|
}
|
|
87
|
-
|
|
83
|
+
|
|
88
84
|
try {
|
|
89
85
|
await onClick();
|
|
90
86
|
} catch (error) {
|
|
@@ -98,10 +94,7 @@ export function GradientButton({
|
|
|
98
94
|
};
|
|
99
95
|
|
|
100
96
|
const isDisabled = disabled || isLoading;
|
|
101
|
-
|
|
102
97
|
const displayTitle = isLoading ? actualLoadingText : title;
|
|
103
|
-
|
|
104
|
-
// icon
|
|
105
98
|
const iconProvided = icon !== undefined;
|
|
106
99
|
|
|
107
100
|
const iconNode = (() => {
|
|
@@ -147,8 +140,6 @@ export function GradientButton({
|
|
|
147
140
|
? 'justify-center'
|
|
148
141
|
: 'justify-start';
|
|
149
142
|
|
|
150
|
-
// Base styles extracted from Button component + size="lg" (h-11 px-8)
|
|
151
|
-
// Removed [&_svg] constraints
|
|
152
143
|
const baseButtonStyles = "inline-flex items-center gap-2 whitespace-nowrap h-11 px-8 ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50";
|
|
153
144
|
const variantClassName = variant === 'soft'
|
|
154
145
|
? cn(
|
|
@@ -163,11 +154,11 @@ export function GradientButton({
|
|
|
163
154
|
themeIconColor,
|
|
164
155
|
'border border-neutral-200 shadow-sm hover:shadow-md hover:bg-neutral-50 dark:border-neutral-800 dark:hover:bg-neutral-800'
|
|
165
156
|
)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
157
|
+
: cn(
|
|
158
|
+
themeButtonGradientClass,
|
|
159
|
+
themeButtonGradientHoverClass,
|
|
160
|
+
'text-white shadow-lg hover:shadow-xl'
|
|
161
|
+
);
|
|
171
162
|
|
|
172
163
|
const buttonClassName = cn(
|
|
173
164
|
baseButtonStyles,
|
|
@@ -181,7 +172,6 @@ export function GradientButton({
|
|
|
181
172
|
return (
|
|
182
173
|
<div className={`flex flex-row gap-3 ${getAlignmentClass()}`}>
|
|
183
174
|
{onClick ? (
|
|
184
|
-
// for click
|
|
185
175
|
<button
|
|
186
176
|
type="button"
|
|
187
177
|
className={buttonClassName}
|
|
@@ -191,7 +181,6 @@ export function GradientButton({
|
|
|
191
181
|
{buttonContent}
|
|
192
182
|
</button>
|
|
193
183
|
) : (
|
|
194
|
-
// for Link
|
|
195
184
|
<Link
|
|
196
185
|
href={href || "#"}
|
|
197
186
|
className={cn(buttonClassName, "no-underline hover:no-underline")}
|
|
@@ -204,4 +193,4 @@ export function GradientButton({
|
|
|
204
193
|
)}
|
|
205
194
|
</div>
|
|
206
195
|
);
|
|
207
|
-
}
|
|
196
|
+
}
|
|
@@ -7,7 +7,6 @@ import { cn } from '@windrun-huaiin/lib/utils'
|
|
|
7
7
|
|
|
8
8
|
type XButtonVariant = 'default' | 'soft' | 'subtle'
|
|
9
9
|
|
|
10
|
-
// base button config
|
|
11
10
|
interface BaseButtonConfig {
|
|
12
11
|
icon: ReactNode
|
|
13
12
|
text: string
|
|
@@ -15,7 +14,6 @@ interface BaseButtonConfig {
|
|
|
15
14
|
disabled?: boolean
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
// menu item config
|
|
19
17
|
interface MenuItemConfig extends BaseButtonConfig {
|
|
20
18
|
tag?: {
|
|
21
19
|
text: string
|
|
@@ -24,7 +22,6 @@ interface MenuItemConfig extends BaseButtonConfig {
|
|
|
24
22
|
splitTopBorder?: boolean
|
|
25
23
|
}
|
|
26
24
|
|
|
27
|
-
// single button config
|
|
28
25
|
interface SingleButtonProps {
|
|
29
26
|
type: 'single'
|
|
30
27
|
button: BaseButtonConfig
|
|
@@ -35,7 +32,6 @@ interface SingleButtonProps {
|
|
|
35
32
|
variant?: XButtonVariant
|
|
36
33
|
}
|
|
37
34
|
|
|
38
|
-
// split button config
|
|
39
35
|
interface SplitButtonProps {
|
|
40
36
|
type: 'split'
|
|
41
37
|
mainButton: BaseButtonConfig
|
|
@@ -77,7 +73,6 @@ export function XButton(props: xButtonProps) {
|
|
|
77
73
|
return icon;
|
|
78
74
|
};
|
|
79
75
|
|
|
80
|
-
// click outside to close menu
|
|
81
76
|
useEffect(() => {
|
|
82
77
|
if (props.type === 'split') {
|
|
83
78
|
const handleClickOutside = (event: MouseEvent) => {
|
|
@@ -96,7 +91,6 @@ export function XButton(props: xButtonProps) {
|
|
|
96
91
|
}
|
|
97
92
|
}, [menuOpen, props.type])
|
|
98
93
|
|
|
99
|
-
// handle button click
|
|
100
94
|
const handleButtonClick = async (onClick: () => void | Promise<void>) => {
|
|
101
95
|
if (isLoading) return
|
|
102
96
|
|
|
@@ -110,7 +104,6 @@ export function XButton(props: xButtonProps) {
|
|
|
110
104
|
}
|
|
111
105
|
}
|
|
112
106
|
|
|
113
|
-
// base style class
|
|
114
107
|
const baseButtonClass = "flex items-center justify-center gap-2 px-4 py-2 text-sm font-semibold transition-colors"
|
|
115
108
|
const singleButtonVariantClass = variant === 'soft'
|
|
116
109
|
? cn(
|
|
@@ -125,7 +118,7 @@ export function XButton(props: xButtonProps) {
|
|
|
125
118
|
themeIconColor,
|
|
126
119
|
"border border-neutral-200 hover:bg-neutral-50 dark:border-neutral-800 dark:hover:bg-neutral-800"
|
|
127
120
|
)
|
|
128
|
-
|
|
121
|
+
: "bg-neutral-200 dark:bg-neutral-800 text-neutral-700 dark:text-white hover:bg-neutral-300 dark:hover:bg-neutral-700"
|
|
129
122
|
const splitMainButtonVariantClass = variant === 'soft'
|
|
130
123
|
? cn(
|
|
131
124
|
"bg-transparent hover:bg-black/5 dark:hover:bg-white/5",
|
|
@@ -136,7 +129,7 @@ export function XButton(props: xButtonProps) {
|
|
|
136
129
|
"bg-transparent hover:bg-neutral-50 dark:hover:bg-neutral-800",
|
|
137
130
|
themeIconColor
|
|
138
131
|
)
|
|
139
|
-
|
|
132
|
+
: "bg-neutral-200 dark:bg-neutral-800 text-neutral-700 dark:text-white hover:bg-neutral-300 dark:hover:bg-neutral-700"
|
|
140
133
|
const splitDropdownVariantClass = variant === 'soft'
|
|
141
134
|
? cn(
|
|
142
135
|
"bg-transparent hover:bg-black/5 dark:hover:bg-white/5 sm:border-l",
|
|
@@ -149,13 +142,12 @@ export function XButton(props: xButtonProps) {
|
|
|
149
142
|
themeIconColor,
|
|
150
143
|
"border-neutral-200 dark:border-neutral-800"
|
|
151
144
|
)
|
|
152
|
-
|
|
145
|
+
: "bg-neutral-200 dark:bg-neutral-800 text-neutral-700 dark:text-white hover:bg-neutral-300 dark:hover:bg-neutral-700 sm:border-l sm:border-neutral-300 sm:dark:border-neutral-700"
|
|
153
146
|
const disabledClass = "opacity-60 cursor-not-allowed"
|
|
154
147
|
|
|
155
148
|
if (props.type === 'single') {
|
|
156
149
|
const { button, loadingText, minWidth = 'min-w-[110px]', className = '' } = props
|
|
157
150
|
const isDisabled = button.disabled || isLoading
|
|
158
|
-
// loadingText: props.loadingText > button.text > 'Loading...'
|
|
159
151
|
const actualLoadingText = loadingText || button.text?.trim() || 'Loading...'
|
|
160
152
|
|
|
161
153
|
return (
|
|
@@ -188,36 +180,28 @@ export function XButton(props: xButtonProps) {
|
|
|
188
180
|
)
|
|
189
181
|
}
|
|
190
182
|
|
|
191
|
-
// Split button
|
|
192
183
|
const { mainButton, menuItems, loadingText, menuWidth = 'w-full sm:w-40', className = '', mainButtonClassName = '', dropdownButtonClassName = '' } = props
|
|
193
184
|
const isMainDisabled = mainButton.disabled || isLoading
|
|
194
|
-
// loadingText prioty:props.loadingText > mainButton.text > 'Loading...'
|
|
195
185
|
const actualLoadingText = loadingText || mainButton.text?.trim() || 'Loading...'
|
|
196
186
|
|
|
197
187
|
return (
|
|
198
188
|
<div className={cn(
|
|
199
189
|
"relative flex flex-row items-stretch w-full sm:w-auto rounded-full gap-0",
|
|
200
190
|
menuOpen && "z-90",
|
|
201
|
-
variant === 'soft'
|
|
202
|
-
? cn(themeBgColor, themeBorderColor, "border")
|
|
203
|
-
: variant === 'subtle'
|
|
204
|
-
? cn(themeMainBgColor, "border border-neutral-200 dark:border-neutral-800")
|
|
205
|
-
: "bg-neutral-200 dark:bg-neutral-800",
|
|
206
191
|
className
|
|
207
192
|
)}>
|
|
208
|
-
{/* left main button */}
|
|
209
193
|
<button
|
|
210
194
|
onClick={() => handleButtonClick(mainButton.onClick)}
|
|
211
195
|
disabled={isMainDisabled}
|
|
212
196
|
className={cn(
|
|
213
|
-
"min-w-0 flex-
|
|
197
|
+
"flex-1 min-w-0 sm:min-w-[100px] sm:flex-initial rounded-l-full",
|
|
214
198
|
baseButtonClass,
|
|
215
199
|
splitMainButtonVariantClass,
|
|
216
|
-
"rounded-l-full rounded-r-none",
|
|
217
200
|
isMainDisabled && disabledClass,
|
|
218
201
|
mainButtonClassName
|
|
219
202
|
)}
|
|
220
203
|
onMouseDown={e => { if (e.button === 2) e.preventDefault() }}
|
|
204
|
+
title={mainButton.text}
|
|
221
205
|
>
|
|
222
206
|
{isLoading ? (
|
|
223
207
|
<>
|
|
@@ -227,52 +211,54 @@ export function XButton(props: xButtonProps) {
|
|
|
227
211
|
) : (
|
|
228
212
|
<>
|
|
229
213
|
{renderIcon(mainButton.icon)}
|
|
230
|
-
<span
|
|
214
|
+
<span>{mainButton.text}</span>
|
|
231
215
|
</>
|
|
232
216
|
)}
|
|
233
217
|
</button>
|
|
234
218
|
|
|
235
|
-
{/* right dropdown button */}
|
|
236
219
|
<button
|
|
237
220
|
type="button"
|
|
221
|
+
onClick={() => setMenuOpen(!menuOpen)}
|
|
222
|
+
disabled={isLoading}
|
|
238
223
|
className={cn(
|
|
239
|
-
"
|
|
224
|
+
"w-12 rounded-r-full",
|
|
225
|
+
baseButtonClass,
|
|
240
226
|
splitDropdownVariantClass,
|
|
227
|
+
isLoading && disabledClass,
|
|
241
228
|
dropdownButtonClassName
|
|
242
229
|
)}
|
|
243
|
-
|
|
244
|
-
aria-label="More actions"
|
|
245
|
-
aria-expanded={menuOpen}
|
|
230
|
+
aria-label="Open menu"
|
|
246
231
|
>
|
|
247
|
-
<ChevronDownIcon className={chevronIconClass} />
|
|
232
|
+
<ChevronDownIcon className={cn(chevronIconClass, menuOpen && "rotate-180", "transition-transform")} />
|
|
248
233
|
</button>
|
|
249
234
|
|
|
250
|
-
{/* dropdown menu */}
|
|
251
235
|
{menuOpen && (
|
|
252
236
|
<div
|
|
253
237
|
ref={menuRef}
|
|
254
|
-
className={
|
|
238
|
+
className={cn(
|
|
239
|
+
"absolute top-full right-0 mt-2 bg-white dark:bg-neutral-800 border border-neutral-200 dark:border-neutral-700 rounded-lg shadow-lg z-50 overflow-hidden",
|
|
240
|
+
menuWidth
|
|
241
|
+
)}
|
|
255
242
|
>
|
|
256
243
|
{menuItems.map((item, index) => (
|
|
257
244
|
<button
|
|
258
245
|
key={index}
|
|
246
|
+
type="button"
|
|
259
247
|
onClick={() => {
|
|
260
|
-
handleButtonClick(item.onClick)
|
|
261
248
|
setMenuOpen(false)
|
|
249
|
+
handleButtonClick(item.onClick)
|
|
262
250
|
}}
|
|
263
|
-
disabled={item.disabled}
|
|
264
|
-
className={
|
|
265
|
-
|
|
251
|
+
disabled={item.disabled || isLoading}
|
|
252
|
+
className={cn(
|
|
253
|
+
"w-full flex items-center gap-2 px-3 py-2 text-sm text-left hover:bg-neutral-100 dark:hover:bg-neutral-700 transition-colors",
|
|
254
|
+
item.disabled && disabledClass,
|
|
255
|
+
item.splitTopBorder && "border-t border-neutral-200 dark:border-neutral-700"
|
|
256
|
+
)}
|
|
266
257
|
>
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
<span>{item.text}</span>
|
|
270
|
-
</span>
|
|
258
|
+
{renderIcon(item.icon)}
|
|
259
|
+
<span className="flex-1">{item.text}</span>
|
|
271
260
|
{item.tag && (
|
|
272
|
-
<span
|
|
273
|
-
className="absolute right-3 top-1 text-[10px] font-semibold"
|
|
274
|
-
style={{ color: item.tag.color || '#A855F7', pointerEvents: 'none' }}
|
|
275
|
-
>
|
|
261
|
+
<span className={cn("px-1.5 py-0.5 text-xs rounded", item.tag.color || "bg-blue-100 text-blue-800")}>
|
|
276
262
|
{item.tag.text}
|
|
277
263
|
</span>
|
|
278
264
|
)}
|