@farming-labs/theme 0.0.33 → 0.0.36
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-search-dialog.d.mts +6 -3
- package/dist/ai-search-dialog.mjs +1 -1
- package/dist/client-location.mjs +43 -0
- package/dist/code-block-copy-wrapper.mjs +9 -3
- package/dist/docs-ai-features.mjs +2 -2
- package/dist/docs-api.mjs +1 -1
- package/dist/docs-command-search.d.mts +3 -1
- package/dist/docs-command-search.mjs +3 -3
- package/dist/docs-layout.mjs +13 -3
- package/dist/docs-page-client.d.mts +9 -0
- package/dist/docs-page-client.mjs +81 -84
- package/dist/locale-theme-control.mjs +3 -2
- package/dist/mdx-img.d.mts +1 -1
- package/dist/mdx-img.mjs +3 -5
- package/dist/page-actions.mjs +1 -1
- package/dist/provider-tanstack.d.mts +14 -0
- package/dist/provider-tanstack.mjs +22 -0
- package/dist/tanstack-layout.d.mts +45 -0
- package/dist/tanstack-layout.mjs +328 -0
- package/dist/tanstack.d.mts +3 -0
- package/dist/tanstack.mjs +4 -0
- package/package.json +8 -2
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import * as react from "react";
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
|
+
|
|
1
4
|
//#region src/ai-search-dialog.d.ts
|
|
2
5
|
type AIModelOption = {
|
|
3
6
|
id: string;
|
|
@@ -24,7 +27,7 @@ declare function DocsSearchDialog({
|
|
|
24
27
|
loadingComponentHtml?: string;
|
|
25
28
|
models?: AIModelOption[];
|
|
26
29
|
defaultModelId?: string;
|
|
27
|
-
}):
|
|
30
|
+
}): react.ReactPortal | null;
|
|
28
31
|
type FloatingPosition = "bottom-right" | "bottom-left" | "bottom-center";
|
|
29
32
|
type FloatingStyle = "panel" | "modal" | "popover" | "full-modal";
|
|
30
33
|
declare function FloatingAIChat({
|
|
@@ -49,7 +52,7 @@ declare function FloatingAIChat({
|
|
|
49
52
|
loadingComponentHtml?: string;
|
|
50
53
|
models?: AIModelOption[];
|
|
51
54
|
defaultModelId?: string;
|
|
52
|
-
}):
|
|
55
|
+
}): react_jsx_runtime0.JSX.Element | null;
|
|
53
56
|
declare function AIModalDialog({
|
|
54
57
|
open,
|
|
55
58
|
onOpenChange,
|
|
@@ -70,6 +73,6 @@ declare function AIModalDialog({
|
|
|
70
73
|
loadingComponentHtml?: string;
|
|
71
74
|
models?: AIModelOption[];
|
|
72
75
|
defaultModelId?: string;
|
|
73
|
-
}):
|
|
76
|
+
}): react.ReactPortal | null;
|
|
74
77
|
//#endregion
|
|
75
78
|
export { AIModalDialog, DocsSearchDialog, FloatingAIChat };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
-
import { createPortal } from "react-dom";
|
|
5
4
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { createPortal } from "react-dom";
|
|
6
6
|
import { highlight } from "sugar-high";
|
|
7
7
|
|
|
8
8
|
//#region src/ai-search-dialog.tsx
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useSyncExternalStore } from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/client-location.ts
|
|
6
|
+
function patchHistoryEvents() {
|
|
7
|
+
if (typeof window === "undefined" || window.__fdHistoryPatched) return;
|
|
8
|
+
const wrap = (method) => {
|
|
9
|
+
const original = window.history[method];
|
|
10
|
+
window.history[method] = function patchedHistoryMethod(...args) {
|
|
11
|
+
const result = original.apply(this, args);
|
|
12
|
+
window.dispatchEvent(new Event("fd-location-change"));
|
|
13
|
+
return result;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
wrap("pushState");
|
|
17
|
+
wrap("replaceState");
|
|
18
|
+
window.__fdHistoryPatched = true;
|
|
19
|
+
}
|
|
20
|
+
function subscribe(onStoreChange) {
|
|
21
|
+
if (typeof window === "undefined") return () => {};
|
|
22
|
+
patchHistoryEvents();
|
|
23
|
+
const notify = () => onStoreChange();
|
|
24
|
+
window.addEventListener("popstate", notify);
|
|
25
|
+
window.addEventListener("hashchange", notify);
|
|
26
|
+
window.addEventListener("fd-location-change", notify);
|
|
27
|
+
return () => {
|
|
28
|
+
window.removeEventListener("popstate", notify);
|
|
29
|
+
window.removeEventListener("hashchange", notify);
|
|
30
|
+
window.removeEventListener("fd-location-change", notify);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function getSnapshot() {
|
|
34
|
+
if (typeof window === "undefined") return "";
|
|
35
|
+
return window.location.search;
|
|
36
|
+
}
|
|
37
|
+
function useWindowSearchParams() {
|
|
38
|
+
const search = useSyncExternalStore(subscribe, getSnapshot, () => "");
|
|
39
|
+
return new URLSearchParams(search);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { useWindowSearchParams };
|
|
@@ -10,7 +10,12 @@ import { jsx } from "react/jsx-runtime";
|
|
|
10
10
|
* The actual copy-to-clipboard is still done by the default component.
|
|
11
11
|
*/
|
|
12
12
|
function createPreWithCopyCallback(DefaultPre, onCopyClick) {
|
|
13
|
-
if (!onCopyClick)
|
|
13
|
+
if (!onCopyClick) {
|
|
14
|
+
if (typeof DefaultPre !== "string") return DefaultPre;
|
|
15
|
+
return function NativePre(props) {
|
|
16
|
+
return /* @__PURE__ */ jsx("pre", { ...props });
|
|
17
|
+
};
|
|
18
|
+
}
|
|
14
19
|
function PreWithCopyCallback(props) {
|
|
15
20
|
const ref = React$1.useRef(null);
|
|
16
21
|
React$1.useEffect(() => {
|
|
@@ -25,8 +30,9 @@ function createPreWithCopyCallback(DefaultPre, onCopyClick) {
|
|
|
25
30
|
const content = code.textContent ?? "";
|
|
26
31
|
const url = typeof window !== "undefined" ? window.location.href : "";
|
|
27
32
|
const language = code.getAttribute("data-language") ?? figure.getAttribute("data-language") ?? void 0;
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
const title = figure.querySelector("[data-title]")?.textContent?.trim() ?? figure.querySelector(".fd-codeblock-title-text")?.textContent?.trim() ?? void 0;
|
|
34
|
+
onCopyClick?.({
|
|
35
|
+
title,
|
|
30
36
|
content,
|
|
31
37
|
url,
|
|
32
38
|
language
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import { useWindowSearchParams } from "./client-location.mjs";
|
|
3
4
|
import { resolveClientLocale, withLangInUrl } from "./i18n.mjs";
|
|
4
5
|
import { AIModalDialog, DocsSearchDialog, FloatingAIChat } from "./ai-search-dialog.mjs";
|
|
5
6
|
import { useEffect, useState } from "react";
|
|
6
|
-
import { useSearchParams } from "next/navigation";
|
|
7
7
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
|
|
9
9
|
//#region src/docs-ai-features.tsx
|
|
@@ -22,7 +22,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
22
22
|
* never needs to be modified — AI features work purely from `docs.config.ts`.
|
|
23
23
|
*/
|
|
24
24
|
function DocsAIFeatures({ mode, api = "/api/docs", locale, position = "bottom-right", floatingStyle = "panel", triggerComponentHtml, suggestedQuestions, aiLabel, loaderVariant, loadingComponentHtml, models, defaultModelId }) {
|
|
25
|
-
const localizedApi = withLangInUrl(api, resolveClientLocale(
|
|
25
|
+
const localizedApi = withLangInUrl(api, resolveClientLocale(useWindowSearchParams(), locale));
|
|
26
26
|
if (mode === "search") return /* @__PURE__ */ jsx(SearchModeAI, {
|
|
27
27
|
api: localizedApi,
|
|
28
28
|
suggestedQuestions,
|
package/dist/docs-api.mjs
CHANGED
|
@@ -51,7 +51,7 @@ function readI18nConfig(root) {
|
|
|
51
51
|
if (!content.includes("i18n")) continue;
|
|
52
52
|
const localesMatch = content.match(/i18n\s*:\s*\{[\s\S]*?locales\s*:\s*\[([^\]]+)\]/);
|
|
53
53
|
if (!localesMatch) continue;
|
|
54
|
-
const locales = localesMatch[1].split(",").map((l) => l.trim().replace(/^['
|
|
54
|
+
const locales = localesMatch[1].split(",").map((l) => l.trim().replace(/^['"`]|['"`]$/g, "")).filter(Boolean);
|
|
55
55
|
if (locales.length === 0) continue;
|
|
56
56
|
return {
|
|
57
57
|
locales,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as React$1 from "react";
|
|
2
|
+
|
|
1
3
|
//#region src/docs-command-search.d.ts
|
|
2
4
|
/**
|
|
3
5
|
* Built-in docs search command palette.
|
|
@@ -11,6 +13,6 @@ declare function DocsCommandSearch({
|
|
|
11
13
|
}: {
|
|
12
14
|
api?: string;
|
|
13
15
|
locale?: string;
|
|
14
|
-
}):
|
|
16
|
+
}): React$1.ReactPortal | null;
|
|
15
17
|
//#endregion
|
|
16
18
|
export { DocsCommandSearch };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import { useWindowSearchParams } from "./client-location.mjs";
|
|
3
4
|
import { resolveClientLocale, withLangInUrl } from "./i18n.mjs";
|
|
4
5
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
-
import { createPortal } from "react-dom";
|
|
6
|
-
import { useSearchParams } from "next/navigation";
|
|
7
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { createPortal } from "react-dom";
|
|
8
8
|
|
|
9
9
|
//#region src/docs-command-search.tsx
|
|
10
10
|
function cn(...classes) {
|
|
@@ -308,7 +308,7 @@ function DocsCommandSearch({ api = "/api/docs", locale }) {
|
|
|
308
308
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
309
309
|
const [recents, setRecents] = useState([]);
|
|
310
310
|
const [mounted, setMounted] = useState(false);
|
|
311
|
-
const activeLocale = resolveClientLocale(
|
|
311
|
+
const activeLocale = resolveClientLocale(useWindowSearchParams(), locale);
|
|
312
312
|
const searchApi = useMemo(() => withLangInUrl(api, activeLocale), [activeLocale, api]);
|
|
313
313
|
const inputRef = useRef(null);
|
|
314
314
|
const listRef = useRef(null);
|
package/dist/docs-layout.mjs
CHANGED
|
@@ -52,17 +52,25 @@ function resolveDocsI18nConfig(i18n) {
|
|
|
52
52
|
}
|
|
53
53
|
function resolveDocsLocaleContext(config, locale) {
|
|
54
54
|
const entryBase = config.entry ?? "docs";
|
|
55
|
-
const appDir = getNextAppDir(process.cwd());
|
|
56
55
|
const i18n = resolveDocsI18nConfig(getDocsI18n(config));
|
|
56
|
+
const contentDir = config.contentDir;
|
|
57
|
+
function resolveContentDir(localeValue) {
|
|
58
|
+
if (!contentDir) {
|
|
59
|
+
const appDir = getNextAppDir(process.cwd());
|
|
60
|
+
return path.join(process.cwd(), appDir, entryBase, ...localeValue ? [localeValue] : []);
|
|
61
|
+
}
|
|
62
|
+
const base = path.isAbsolute(contentDir) ? contentDir : path.join(process.cwd(), contentDir);
|
|
63
|
+
return localeValue ? path.join(base, localeValue) : base;
|
|
64
|
+
}
|
|
57
65
|
if (!i18n) return {
|
|
58
66
|
entryPath: entryBase,
|
|
59
|
-
docsDir:
|
|
67
|
+
docsDir: resolveContentDir()
|
|
60
68
|
};
|
|
61
69
|
const resolvedLocale = locale && i18n.locales.includes(locale) ? locale : i18n.defaultLocale;
|
|
62
70
|
return {
|
|
63
71
|
entryPath: entryBase,
|
|
64
72
|
locale: resolvedLocale,
|
|
65
|
-
docsDir:
|
|
73
|
+
docsDir: resolveContentDir(resolvedLocale)
|
|
66
74
|
};
|
|
67
75
|
}
|
|
68
76
|
function buildTree(config, ctx, flat = false) {
|
|
@@ -467,6 +475,7 @@ function createDocsLayout(config, options) {
|
|
|
467
475
|
const githubUrl = typeof githubRaw === "string" ? githubRaw.replace(/\/$/, "") : githubRaw?.url.replace(/\/$/, "");
|
|
468
476
|
const githubBranch = typeof githubRaw === "object" ? githubRaw.branch ?? "main" : "main";
|
|
469
477
|
const githubDirectory = typeof githubRaw === "object" ? githubRaw.directory?.replace(/^\/|\/$/g, "") : void 0;
|
|
478
|
+
const contentDir = config.contentDir;
|
|
470
479
|
const staticExport = !!config.staticExport;
|
|
471
480
|
const aiConfig = config.ai;
|
|
472
481
|
const aiEnabled = !staticExport && !!aiConfig?.enabled;
|
|
@@ -572,6 +581,7 @@ function createDocsLayout(config, options) {
|
|
|
572
581
|
pageActionsPosition,
|
|
573
582
|
pageActionsAlignment,
|
|
574
583
|
githubUrl,
|
|
584
|
+
contentDir,
|
|
575
585
|
githubBranch,
|
|
576
586
|
githubDirectory,
|
|
577
587
|
lastModifiedMap,
|
|
@@ -25,12 +25,18 @@ interface DocsPageClientProps {
|
|
|
25
25
|
pageActionsAlignment?: "left" | "right";
|
|
26
26
|
/** GitHub repository URL (e.g. "https://github.com/user/repo") */
|
|
27
27
|
githubUrl?: string;
|
|
28
|
+
/** Path to docs content relative to the repo root (used for Edit on GitHub outside Next.js app/docs) */
|
|
29
|
+
contentDir?: string;
|
|
28
30
|
/** GitHub branch name @default "main" */
|
|
29
31
|
githubBranch?: string;
|
|
30
32
|
/** Subdirectory in the repo where the docs site lives (for monorepos) */
|
|
31
33
|
githubDirectory?: string;
|
|
34
|
+
/** Direct GitHub URL override for the current page. */
|
|
35
|
+
editOnGithubUrl?: string;
|
|
32
36
|
/** Map of pathname → formatted last-modified date string */
|
|
33
37
|
lastModifiedMap?: Record<string, string>;
|
|
38
|
+
/** Direct last-modified value override for the current page. */
|
|
39
|
+
lastModified?: string;
|
|
34
40
|
/** Whether to show "Last updated" at all */
|
|
35
41
|
lastUpdatedEnabled?: boolean;
|
|
36
42
|
/** Where to show the "Last updated" date: "footer" (next to Edit on GitHub) or "below-title" */
|
|
@@ -55,9 +61,12 @@ declare function DocsPageClient({
|
|
|
55
61
|
pageActionsPosition,
|
|
56
62
|
pageActionsAlignment,
|
|
57
63
|
githubUrl,
|
|
64
|
+
contentDir,
|
|
58
65
|
githubBranch,
|
|
59
66
|
githubDirectory,
|
|
67
|
+
editOnGithubUrl,
|
|
60
68
|
lastModifiedMap,
|
|
69
|
+
lastModified: lastModifiedProp,
|
|
61
70
|
lastUpdatedEnabled,
|
|
62
71
|
lastUpdatedPosition,
|
|
63
72
|
llmsTxtEnabled,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { PageActions } from "./page-actions.mjs";
|
|
4
|
+
import { useWindowSearchParams } from "./client-location.mjs";
|
|
4
5
|
import { resolveClientLocale, withLangInUrl } from "./i18n.mjs";
|
|
5
|
-
import { useEffect, useState } from "react";
|
|
6
|
+
import { Children, cloneElement, isValidElement, useEffect, useState } from "react";
|
|
6
7
|
import { DocsBody, DocsPage, EditOnGitHub } from "fumadocs-ui/layouts/docs/page";
|
|
7
|
-
import {
|
|
8
|
-
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
|
8
|
+
import { usePathname, useRouter } from "fumadocs-core/framework";
|
|
9
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
10
|
|
|
11
11
|
//#region src/docs-page-client.tsx
|
|
@@ -62,13 +62,14 @@ function PathBreadcrumb({ pathname, entry, locale }) {
|
|
|
62
62
|
* No directory: https://github.com/user/repo/edit/main/app/docs/cli/page.mdx
|
|
63
63
|
* With directory: https://github.com/farming-labs/docs/edit/main/website/app/docs/cli/page.mdx
|
|
64
64
|
*/
|
|
65
|
-
function buildGithubFileUrl(githubUrl, branch, pathname, entry, locale, directory) {
|
|
65
|
+
function buildGithubFileUrl(githubUrl, branch, pathname, entry, locale, directory, contentDir) {
|
|
66
66
|
const normalizedEntry = entry.replace(/^\/+|\/+$/g, "") || "docs";
|
|
67
|
+
const normalizedContentDir = contentDir?.replace(/^\/+|\/+$/g, "");
|
|
67
68
|
const entryParts = normalizedEntry.split("/").filter(Boolean);
|
|
68
69
|
const pathnameParts = pathname.replace(/^\/+|\/+$/g, "").split("/").filter(Boolean);
|
|
69
70
|
const slugParts = pathnameParts.slice(0, entryParts.length).join("/") === entryParts.join("/") ? pathnameParts.slice(entryParts.length) : pathnameParts;
|
|
70
71
|
const dirPrefix = directory ? `${directory}/` : "";
|
|
71
|
-
const basePath = `app/${normalizedEntry}`;
|
|
72
|
+
const basePath = normalizedContentDir || `app/${normalizedEntry}`;
|
|
72
73
|
const relativePath = [locale, slugParts.join("/")].filter(Boolean).join("/");
|
|
73
74
|
return `${githubUrl}/edit/${branch}/${`${dirPrefix}${basePath}${relativePath ? `/${relativePath}` : ""}/page.mdx`}`;
|
|
74
75
|
}
|
|
@@ -86,13 +87,44 @@ function localizeInternalLinks(root, locale) {
|
|
|
86
87
|
} catch {}
|
|
87
88
|
}
|
|
88
89
|
}
|
|
89
|
-
function
|
|
90
|
+
function injectTitleDecorations(node, { description, belowTitle }) {
|
|
91
|
+
if (!description && !belowTitle) return node;
|
|
92
|
+
let inserted = false;
|
|
93
|
+
const extras = [description, belowTitle].filter(Boolean);
|
|
94
|
+
if (extras.length === 0) return node;
|
|
95
|
+
function visit(current) {
|
|
96
|
+
if (current == null || typeof current === "boolean") return current;
|
|
97
|
+
if (inserted) return current;
|
|
98
|
+
if (Array.isArray(current)) return current.flatMap((child) => {
|
|
99
|
+
const next = visit(child);
|
|
100
|
+
return Array.isArray(next) ? next : [next];
|
|
101
|
+
});
|
|
102
|
+
if (!isValidElement(current)) return current;
|
|
103
|
+
if (typeof current.type === "string" && current.type === "h1") {
|
|
104
|
+
inserted = true;
|
|
105
|
+
return [current, ...extras];
|
|
106
|
+
}
|
|
107
|
+
const childProps = current.props ?? null;
|
|
108
|
+
if (childProps?.children === void 0) return current;
|
|
109
|
+
const nextChildren = Children.toArray(childProps.children).flatMap((child) => {
|
|
110
|
+
const next = visit(child);
|
|
111
|
+
return Array.isArray(next) ? next : [next];
|
|
112
|
+
});
|
|
113
|
+
if (!inserted) return current;
|
|
114
|
+
return cloneElement(current, void 0, nextChildren);
|
|
115
|
+
}
|
|
116
|
+
if (Array.isArray(node)) return node.flatMap((child) => {
|
|
117
|
+
const next = visit(child);
|
|
118
|
+
return Array.isArray(next) ? next : [next];
|
|
119
|
+
});
|
|
120
|
+
return visit(node);
|
|
121
|
+
}
|
|
122
|
+
function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled = true, entry = "docs", locale, copyMarkdown = false, openDocs = false, openDocsProviders, pageActionsPosition = "below-title", pageActionsAlignment = "left", githubUrl, contentDir, githubBranch = "main", githubDirectory, editOnGithubUrl, lastModifiedMap, lastModified: lastModifiedProp, lastUpdatedEnabled = true, lastUpdatedPosition = "footer", llmsTxtEnabled = false, descriptionMap, description, children }) {
|
|
90
123
|
const fdTocStyle = tocStyle === "directional" ? "clerk" : void 0;
|
|
91
124
|
const [toc, setToc] = useState([]);
|
|
92
125
|
const pathname = usePathname();
|
|
93
|
-
const activeLocale = resolveClientLocale(
|
|
126
|
+
const activeLocale = resolveClientLocale(useWindowSearchParams(), locale);
|
|
94
127
|
const llmsLangParam = activeLocale ? `&lang=${encodeURIComponent(activeLocale)}` : "";
|
|
95
|
-
const [actionsPortalTarget, setActionsPortalTarget] = useState(null);
|
|
96
128
|
const pageDescription = description ?? descriptionMap?.[pathname.replace(/\/$/, "") || "/"];
|
|
97
129
|
useEffect(() => {
|
|
98
130
|
if (!tocEnabled) return;
|
|
@@ -109,26 +141,7 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
109
141
|
return () => cancelAnimationFrame(timer);
|
|
110
142
|
}, [tocEnabled, pathname]);
|
|
111
143
|
useEffect(() => {
|
|
112
|
-
if (!
|
|
113
|
-
const timer = requestAnimationFrame(() => {
|
|
114
|
-
const container = document.getElementById("nd-page");
|
|
115
|
-
if (!container) return;
|
|
116
|
-
const existingDesc = container.querySelector(".fd-page-description");
|
|
117
|
-
if (existingDesc) existingDesc.remove();
|
|
118
|
-
const h1 = container.querySelector("h1");
|
|
119
|
-
if (!h1) return;
|
|
120
|
-
const descEl = document.createElement("p");
|
|
121
|
-
descEl.className = "fd-page-description";
|
|
122
|
-
descEl.textContent = pageDescription;
|
|
123
|
-
h1.insertAdjacentElement("afterend", descEl);
|
|
124
|
-
});
|
|
125
|
-
return () => {
|
|
126
|
-
cancelAnimationFrame(timer);
|
|
127
|
-
const desc = document.querySelector("#nd-page .fd-page-description");
|
|
128
|
-
if (desc) desc.remove();
|
|
129
|
-
};
|
|
130
|
-
}, [pageDescription, pathname]);
|
|
131
|
-
useEffect(() => {
|
|
144
|
+
if (!activeLocale) return;
|
|
132
145
|
const timer = requestAnimationFrame(() => {
|
|
133
146
|
const container = document.getElementById("nd-page");
|
|
134
147
|
if (!container) return;
|
|
@@ -141,59 +154,40 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
141
154
|
pathname
|
|
142
155
|
]);
|
|
143
156
|
const showActions = copyMarkdown || openDocs;
|
|
144
|
-
const
|
|
157
|
+
const showActionsBelowTitle = showActions && pageActionsPosition === "below-title";
|
|
158
|
+
const showActionsAboveTitle = showActions && pageActionsPosition === "above-title";
|
|
159
|
+
const githubFileUrl = editOnGithubUrl ?? (githubUrl ? buildGithubFileUrl(githubUrl, githubBranch, pathname, entry, activeLocale, githubDirectory, contentDir) : void 0);
|
|
145
160
|
const normalizedPath = pathname.replace(/\/$/, "") || "/";
|
|
146
|
-
const lastModified = lastUpdatedEnabled ? lastModifiedMap?.[normalizedPath] : void 0;
|
|
161
|
+
const lastModified = lastUpdatedEnabled ? lastModifiedProp ?? lastModifiedMap?.[normalizedPath] : void 0;
|
|
147
162
|
const showLastUpdatedBelowTitle = !!lastModified && lastUpdatedPosition === "below-title";
|
|
148
163
|
const showLastUpdatedInFooter = !!lastModified && lastUpdatedPosition === "footer";
|
|
149
164
|
const showFooter = !!githubFileUrl || showLastUpdatedInFooter || llmsTxtEnabled;
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const portalEl = document.createElement("div");
|
|
177
|
-
portalEl.className = "fd-actions-portal";
|
|
178
|
-
portalEl.setAttribute("data-actions-alignment", pageActionsAlignment);
|
|
179
|
-
wrapper.appendChild(portalEl);
|
|
180
|
-
setActionsPortalTarget(portalEl);
|
|
181
|
-
}
|
|
182
|
-
insertAfter.insertAdjacentElement("afterend", wrapper);
|
|
183
|
-
});
|
|
184
|
-
return () => {
|
|
185
|
-
cancelAnimationFrame(timer);
|
|
186
|
-
setActionsPortalTarget(null);
|
|
187
|
-
document.querySelectorAll("#nd-page .fd-below-title-block").forEach((el) => el.remove());
|
|
188
|
-
};
|
|
189
|
-
}, [
|
|
190
|
-
lastModified,
|
|
191
|
-
needsBelowTitleBlock,
|
|
192
|
-
showLastUpdatedBelowTitle,
|
|
193
|
-
showActions,
|
|
194
|
-
pageActionsAlignment,
|
|
195
|
-
pathname
|
|
196
|
-
]);
|
|
165
|
+
const decoratedChildren = injectTitleDecorations(children, {
|
|
166
|
+
description: pageDescription ? /* @__PURE__ */ jsx("p", {
|
|
167
|
+
className: "fd-page-description",
|
|
168
|
+
children: pageDescription
|
|
169
|
+
}) : void 0,
|
|
170
|
+
belowTitle: showLastUpdatedBelowTitle || showActionsBelowTitle ? /* @__PURE__ */ jsxs("div", {
|
|
171
|
+
className: "fd-below-title-block not-prose",
|
|
172
|
+
children: [
|
|
173
|
+
showLastUpdatedBelowTitle && /* @__PURE__ */ jsxs("p", {
|
|
174
|
+
className: "fd-last-updated-inline",
|
|
175
|
+
children: ["Last updated ", lastModified]
|
|
176
|
+
}),
|
|
177
|
+
/* @__PURE__ */ jsx("hr", { className: "fd-title-separator" }),
|
|
178
|
+
showActionsBelowTitle && /* @__PURE__ */ jsx("div", {
|
|
179
|
+
className: "fd-actions-portal",
|
|
180
|
+
"data-actions-alignment": pageActionsAlignment,
|
|
181
|
+
children: /* @__PURE__ */ jsx(PageActions, {
|
|
182
|
+
copyMarkdown,
|
|
183
|
+
openDocs,
|
|
184
|
+
providers: openDocsProviders,
|
|
185
|
+
githubFileUrl
|
|
186
|
+
})
|
|
187
|
+
})
|
|
188
|
+
]
|
|
189
|
+
}) : void 0
|
|
190
|
+
});
|
|
197
191
|
return /* @__PURE__ */ jsxs(DocsPage, {
|
|
198
192
|
toc,
|
|
199
193
|
tableOfContent: {
|
|
@@ -211,12 +205,15 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
211
205
|
entry,
|
|
212
206
|
locale: activeLocale
|
|
213
207
|
}),
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
208
|
+
showActionsAboveTitle && /* @__PURE__ */ jsx("div", {
|
|
209
|
+
className: "fd-below-title-block not-prose",
|
|
210
|
+
children: /* @__PURE__ */ jsx(PageActions, {
|
|
211
|
+
copyMarkdown,
|
|
212
|
+
openDocs,
|
|
213
|
+
providers: openDocsProviders,
|
|
214
|
+
githubFileUrl
|
|
215
|
+
})
|
|
216
|
+
}),
|
|
220
217
|
/* @__PURE__ */ jsxs(DocsBody, {
|
|
221
218
|
style: {
|
|
222
219
|
display: "flex",
|
|
@@ -224,7 +221,7 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
224
221
|
},
|
|
225
222
|
children: [/* @__PURE__ */ jsx("div", {
|
|
226
223
|
style: { flex: 1 },
|
|
227
|
-
children
|
|
224
|
+
children: decoratedChildren
|
|
228
225
|
}), showFooter && /* @__PURE__ */ jsxs("div", {
|
|
229
226
|
className: "not-prose fd-page-footer",
|
|
230
227
|
children: [
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import { useWindowSearchParams } from "./client-location.mjs";
|
|
3
4
|
import { resolveClientLocale, withLangInUrl } from "./i18n.mjs";
|
|
4
5
|
import { useEffect, useMemo, useState } from "react";
|
|
5
|
-
import { usePathname, useRouter
|
|
6
|
+
import { usePathname, useRouter } from "fumadocs-core/framework";
|
|
6
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
8
|
|
|
8
9
|
//#region src/locale-theme-control.tsx
|
|
@@ -102,7 +103,7 @@ function ChevronDownIcon() {
|
|
|
102
103
|
function LocaleThemeControl({ locales, defaultLocale, locale, showThemeToggle = true, themeMode = "light-dark" }) {
|
|
103
104
|
const router = useRouter();
|
|
104
105
|
const pathname = usePathname();
|
|
105
|
-
const searchParams =
|
|
106
|
+
const searchParams = useWindowSearchParams();
|
|
106
107
|
const [mounted, setMounted] = useState(false);
|
|
107
108
|
const [themeValue, setThemeValue] = useState("system");
|
|
108
109
|
const [resolvedTheme, setResolvedTheme] = useState("light");
|
package/dist/mdx-img.d.mts
CHANGED
package/dist/mdx-img.mjs
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import { Image } from "fumadocs-core/framework";
|
|
3
4
|
import { jsx } from "react/jsx-runtime";
|
|
4
|
-
import Image from "next/image";
|
|
5
5
|
|
|
6
6
|
//#region src/mdx-img.tsx
|
|
7
7
|
/**
|
|
8
8
|
* MDX image component that works with  when width/height are not provided.
|
|
9
|
-
* Fumadocs-ui's
|
|
10
|
-
*
|
|
11
|
-
* with default dimensions when missing, so external (e.g. GitHub) images work.
|
|
9
|
+
* Fumadocs-ui's framework-aware image component keeps Next.js optimization when available
|
|
10
|
+
* and falls back to a plain <img> in other runtimes.
|
|
12
11
|
*/
|
|
13
12
|
const DEFAULT_WIDTH = 800;
|
|
14
13
|
const DEFAULT_HEIGHT = 600;
|
|
@@ -19,7 +18,6 @@ function MDXImg(props) {
|
|
|
19
18
|
alt,
|
|
20
19
|
width: width != null ? Number(width) : DEFAULT_WIDTH,
|
|
21
20
|
height: height != null ? Number(height) : DEFAULT_HEIGHT,
|
|
22
|
-
unoptimized: !(width != null && height != null),
|
|
23
21
|
style: {
|
|
24
22
|
maxWidth: "100%",
|
|
25
23
|
height: "auto",
|
package/dist/page-actions.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
-
import { usePathname } from "
|
|
4
|
+
import { usePathname } from "fumadocs-core/framework";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
|
|
7
7
|
//#region src/page-actions.tsx
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ComponentPropsWithoutRef } from "react";
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
|
+
import { RootProvider as RootProvider$1 } from "fumadocs-ui/provider/tanstack";
|
|
4
|
+
|
|
5
|
+
//#region src/provider-tanstack.d.ts
|
|
6
|
+
type FumadocsProviderProps = ComponentPropsWithoutRef<typeof RootProvider$1>;
|
|
7
|
+
interface DocsTanstackRootProviderProps extends FumadocsProviderProps {}
|
|
8
|
+
declare function RootProvider({
|
|
9
|
+
children,
|
|
10
|
+
search,
|
|
11
|
+
...props
|
|
12
|
+
}: DocsTanstackRootProviderProps): react_jsx_runtime0.JSX.Element;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { DocsTanstackRootProviderProps, RootProvider };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { RootProvider as RootProvider$1 } from "fumadocs-ui/provider/tanstack";
|
|
5
|
+
|
|
6
|
+
//#region src/provider-tanstack.tsx
|
|
7
|
+
function RootProvider({ children, search, ...props }) {
|
|
8
|
+
return /* @__PURE__ */ jsx(RootProvider$1, {
|
|
9
|
+
search: {
|
|
10
|
+
...search,
|
|
11
|
+
options: {
|
|
12
|
+
api: "/api/docs",
|
|
13
|
+
...search?.options
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
...props,
|
|
17
|
+
children
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { RootProvider };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { DocsConfig } from "@farming-labs/docs";
|
|
3
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/tanstack-layout.d.ts
|
|
6
|
+
interface PageNode {
|
|
7
|
+
type: "page";
|
|
8
|
+
name: string;
|
|
9
|
+
url: string;
|
|
10
|
+
icon?: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
interface FolderNode {
|
|
13
|
+
type: "folder";
|
|
14
|
+
name: string;
|
|
15
|
+
icon?: ReactNode;
|
|
16
|
+
index?: PageNode;
|
|
17
|
+
children: (PageNode | FolderNode)[];
|
|
18
|
+
collapsible?: boolean;
|
|
19
|
+
defaultOpen?: boolean;
|
|
20
|
+
}
|
|
21
|
+
type TreeNode = PageNode | FolderNode;
|
|
22
|
+
interface TreeRoot {
|
|
23
|
+
name: string;
|
|
24
|
+
children: TreeNode[];
|
|
25
|
+
}
|
|
26
|
+
interface TanstackDocsLayoutProps {
|
|
27
|
+
config: DocsConfig;
|
|
28
|
+
tree: TreeRoot;
|
|
29
|
+
locale?: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
lastModified?: string;
|
|
32
|
+
editOnGithubUrl?: string;
|
|
33
|
+
children: ReactNode;
|
|
34
|
+
}
|
|
35
|
+
declare function TanstackDocsLayout({
|
|
36
|
+
config,
|
|
37
|
+
tree,
|
|
38
|
+
locale,
|
|
39
|
+
description,
|
|
40
|
+
lastModified,
|
|
41
|
+
editOnGithubUrl,
|
|
42
|
+
children
|
|
43
|
+
}: TanstackDocsLayoutProps): react_jsx_runtime0.JSX.Element;
|
|
44
|
+
//#endregion
|
|
45
|
+
export { TanstackDocsLayout, TanstackDocsLayoutProps };
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { withLangInUrl } from "./i18n.mjs";
|
|
2
|
+
import { DocsPageClient } from "./docs-page-client.mjs";
|
|
3
|
+
import { DocsAIFeatures } from "./docs-ai-features.mjs";
|
|
4
|
+
import { DocsCommandSearch } from "./docs-command-search.mjs";
|
|
5
|
+
import { SidebarSearchWithAI } from "./sidebar-search-ai.mjs";
|
|
6
|
+
import { LocaleThemeControl } from "./locale-theme-control.mjs";
|
|
7
|
+
import { DocsLayout } from "fumadocs-ui/layouts/docs";
|
|
8
|
+
import { Suspense } from "react";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
|
|
11
|
+
//#region src/tanstack-layout.tsx
|
|
12
|
+
function resolveTreeIcon(icon, registry) {
|
|
13
|
+
if (!icon) return void 0;
|
|
14
|
+
if (typeof icon !== "string") return icon;
|
|
15
|
+
const fromRegistry = registry?.[icon];
|
|
16
|
+
if (fromRegistry) return fromRegistry;
|
|
17
|
+
}
|
|
18
|
+
function resolveTreeIcons(tree, registry) {
|
|
19
|
+
function mapNode(node) {
|
|
20
|
+
if (node.type === "page") return {
|
|
21
|
+
...node,
|
|
22
|
+
icon: resolveTreeIcon(node.icon, registry)
|
|
23
|
+
};
|
|
24
|
+
return {
|
|
25
|
+
...node,
|
|
26
|
+
icon: resolveTreeIcon(node.icon, registry),
|
|
27
|
+
index: node.index ? {
|
|
28
|
+
...node.index,
|
|
29
|
+
icon: resolveTreeIcon(node.index.icon, registry)
|
|
30
|
+
} : void 0,
|
|
31
|
+
children: node.children.map(mapNode)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
...tree,
|
|
36
|
+
children: tree.children.map(mapNode)
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function localizeTreeUrls(tree, locale) {
|
|
40
|
+
function mapNode(node) {
|
|
41
|
+
if (node.type === "page") return {
|
|
42
|
+
...node,
|
|
43
|
+
url: withLangInUrl(node.url, locale)
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
...node,
|
|
47
|
+
index: node.index ? {
|
|
48
|
+
...node.index,
|
|
49
|
+
url: withLangInUrl(node.index.url, locale)
|
|
50
|
+
} : void 0,
|
|
51
|
+
children: node.children.map(mapNode)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
...tree,
|
|
56
|
+
children: tree.children.map(mapNode)
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function resolveThemeSwitch(toggle) {
|
|
60
|
+
if (toggle === void 0 || toggle === true) return { enabled: true };
|
|
61
|
+
if (toggle === false) return { enabled: false };
|
|
62
|
+
return {
|
|
63
|
+
enabled: toggle.enabled !== false,
|
|
64
|
+
mode: toggle.mode
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function resolveSidebar(sidebar) {
|
|
68
|
+
if (sidebar === void 0 || sidebar === true) return {};
|
|
69
|
+
if (sidebar === false) return { enabled: false };
|
|
70
|
+
return {
|
|
71
|
+
enabled: sidebar.enabled !== false,
|
|
72
|
+
componentFn: typeof sidebar.component === "function" ? sidebar.component : void 0,
|
|
73
|
+
footer: sidebar.footer,
|
|
74
|
+
banner: sidebar.banner,
|
|
75
|
+
collapsible: sidebar.collapsible,
|
|
76
|
+
flat: sidebar.flat
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const COLOR_MAP = {
|
|
80
|
+
primary: "--color-fd-primary",
|
|
81
|
+
primaryForeground: "--color-fd-primary-foreground",
|
|
82
|
+
background: "--color-fd-background",
|
|
83
|
+
foreground: "--color-fd-foreground",
|
|
84
|
+
muted: "--color-fd-muted",
|
|
85
|
+
mutedForeground: "--color-fd-muted-foreground",
|
|
86
|
+
border: "--color-fd-border",
|
|
87
|
+
card: "--color-fd-card",
|
|
88
|
+
cardForeground: "--color-fd-card-foreground",
|
|
89
|
+
accent: "--color-fd-accent",
|
|
90
|
+
accentForeground: "--color-fd-accent-foreground",
|
|
91
|
+
popover: "--color-fd-popover",
|
|
92
|
+
popoverForeground: "--color-fd-popover-foreground",
|
|
93
|
+
secondary: "--color-fd-secondary",
|
|
94
|
+
secondaryForeground: "--color-fd-secondary-foreground",
|
|
95
|
+
ring: "--color-fd-ring"
|
|
96
|
+
};
|
|
97
|
+
function buildColorsCSS(colors) {
|
|
98
|
+
if (!colors) return "";
|
|
99
|
+
const vars = [];
|
|
100
|
+
for (const [key, value] of Object.entries(colors)) {
|
|
101
|
+
if (!value || !COLOR_MAP[key]) continue;
|
|
102
|
+
vars.push(`${COLOR_MAP[key]}: ${value};`);
|
|
103
|
+
}
|
|
104
|
+
if (vars.length === 0) return "";
|
|
105
|
+
const block = vars.join("\n ");
|
|
106
|
+
return `:root {\n ${block}\n}\n.dark {\n ${block}\n}`;
|
|
107
|
+
}
|
|
108
|
+
function ColorStyle({ colors }) {
|
|
109
|
+
const css = buildColorsCSS(colors);
|
|
110
|
+
if (!css) return null;
|
|
111
|
+
return /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: css } });
|
|
112
|
+
}
|
|
113
|
+
function buildFontStyleVars(prefix, style) {
|
|
114
|
+
if (!style) return "";
|
|
115
|
+
const parts = [];
|
|
116
|
+
if (style.size) parts.push(`${prefix}-size: ${style.size};`);
|
|
117
|
+
if (style.weight != null) parts.push(`${prefix}-weight: ${style.weight};`);
|
|
118
|
+
if (style.lineHeight) parts.push(`${prefix}-line-height: ${style.lineHeight};`);
|
|
119
|
+
if (style.letterSpacing) parts.push(`${prefix}-letter-spacing: ${style.letterSpacing};`);
|
|
120
|
+
return parts.join("\n ");
|
|
121
|
+
}
|
|
122
|
+
function buildTypographyCSS(typo) {
|
|
123
|
+
if (!typo?.font) return "";
|
|
124
|
+
const vars = [];
|
|
125
|
+
const fontStyle = typo.font.style;
|
|
126
|
+
if (fontStyle?.sans) vars.push(`--fd-font-sans: ${fontStyle.sans};`);
|
|
127
|
+
if (fontStyle?.mono) vars.push(`--fd-font-mono: ${fontStyle.mono};`);
|
|
128
|
+
for (const element of [
|
|
129
|
+
"h1",
|
|
130
|
+
"h2",
|
|
131
|
+
"h3",
|
|
132
|
+
"h4",
|
|
133
|
+
"body",
|
|
134
|
+
"small"
|
|
135
|
+
]) {
|
|
136
|
+
const style = typo.font[element];
|
|
137
|
+
if (style) {
|
|
138
|
+
const cssVars = buildFontStyleVars(`--fd-${element}`, style);
|
|
139
|
+
if (cssVars) vars.push(cssVars);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (vars.length === 0) return "";
|
|
143
|
+
return `:root {\n ${vars.join("\n ")}\n}`;
|
|
144
|
+
}
|
|
145
|
+
function TypographyStyle({ typography }) {
|
|
146
|
+
const css = buildTypographyCSS(typography);
|
|
147
|
+
if (!css) return null;
|
|
148
|
+
return /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: css } });
|
|
149
|
+
}
|
|
150
|
+
function LayoutStyle({ layout }) {
|
|
151
|
+
if (!layout) return null;
|
|
152
|
+
const rootVars = [];
|
|
153
|
+
const desktopRootVars = [];
|
|
154
|
+
const desktopGridVars = [];
|
|
155
|
+
if (layout.sidebarWidth) {
|
|
156
|
+
const value = `--fd-sidebar-width: ${layout.sidebarWidth}px`;
|
|
157
|
+
desktopRootVars.push(`${value};`);
|
|
158
|
+
desktopGridVars.push(`${value} !important;`);
|
|
159
|
+
}
|
|
160
|
+
if (layout.contentWidth) rootVars.push(`--fd-content-width: ${layout.contentWidth}px;`);
|
|
161
|
+
if (layout.tocWidth) {
|
|
162
|
+
const value = `--fd-toc-width: ${layout.tocWidth}px`;
|
|
163
|
+
desktopRootVars.push(`${value};`);
|
|
164
|
+
desktopGridVars.push(`${value} !important;`);
|
|
165
|
+
}
|
|
166
|
+
if (rootVars.length === 0 && desktopRootVars.length === 0) return null;
|
|
167
|
+
const parts = [];
|
|
168
|
+
if (rootVars.length > 0) parts.push(`:root {\n ${rootVars.join("\n ")}\n}`);
|
|
169
|
+
if (desktopRootVars.length > 0) {
|
|
170
|
+
const inner = [`:root {\n ${desktopRootVars.join("\n ")}\n }`];
|
|
171
|
+
if (desktopGridVars.length > 0) inner.push(`[style*="fd-sidebar-col"] {\n ${desktopGridVars.join("\n ")}\n }`);
|
|
172
|
+
parts.push(`@media (min-width: 1024px) {\n ${inner.join("\n ")}\n}`);
|
|
173
|
+
}
|
|
174
|
+
return /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: parts.join("\n") } });
|
|
175
|
+
}
|
|
176
|
+
function resolveBool(value) {
|
|
177
|
+
if (value === void 0) return false;
|
|
178
|
+
if (typeof value === "boolean") return value;
|
|
179
|
+
return value.enabled !== false;
|
|
180
|
+
}
|
|
181
|
+
function ForcedThemeScript({ theme }) {
|
|
182
|
+
return /* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: `document.documentElement.classList.remove('light','dark');document.documentElement.classList.add('${theme === "light" || theme === "dark" ? theme : "light"}');` } });
|
|
183
|
+
}
|
|
184
|
+
function TanstackDocsLayout({ config, tree, locale, description, lastModified, editOnGithubUrl, children }) {
|
|
185
|
+
const tocConfig = config.theme?.ui?.layout?.toc;
|
|
186
|
+
const tocEnabled = tocConfig?.enabled !== false;
|
|
187
|
+
const tocStyle = tocConfig?.style;
|
|
188
|
+
const docsApiUrl = withLangInUrl("/api/docs", locale);
|
|
189
|
+
const navTitle = config.nav?.title ?? "Docs";
|
|
190
|
+
const navUrl = withLangInUrl(config.nav?.url ?? `/${config.entry ?? "docs"}`, locale);
|
|
191
|
+
const themeSwitch = resolveThemeSwitch(config.themeToggle);
|
|
192
|
+
const toggleConfig = typeof config.themeToggle === "object" ? config.themeToggle : void 0;
|
|
193
|
+
const forcedTheme = themeSwitch.enabled === false && toggleConfig?.default && toggleConfig.default !== "system" ? toggleConfig.default : void 0;
|
|
194
|
+
const resolvedSidebar = resolveSidebar(config.sidebar);
|
|
195
|
+
const sidebarFlat = resolvedSidebar.flat;
|
|
196
|
+
const sidebarComponentFn = resolvedSidebar.componentFn;
|
|
197
|
+
const { flat: _sidebarFlat, componentFn: _componentFn, ...sidebarProps } = resolvedSidebar;
|
|
198
|
+
const breadcrumbConfig = config.breadcrumb;
|
|
199
|
+
const breadcrumbEnabled = breadcrumbConfig === void 0 || breadcrumbConfig === true || typeof breadcrumbConfig === "object" && breadcrumbConfig.enabled !== false;
|
|
200
|
+
const colors = config.theme?._userColorOverrides;
|
|
201
|
+
const typography = config.theme?.ui?.typography;
|
|
202
|
+
const layoutDimensions = config.theme?.ui?.layout;
|
|
203
|
+
const pageActions = config.pageActions;
|
|
204
|
+
const copyMarkdownEnabled = resolveBool(pageActions?.copyMarkdown);
|
|
205
|
+
const openDocsEnabled = resolveBool(pageActions?.openDocs);
|
|
206
|
+
const pageActionsPosition = pageActions?.position ?? "below-title";
|
|
207
|
+
const pageActionsAlignment = pageActions?.alignment ?? "left";
|
|
208
|
+
const lastUpdatedRaw = config.lastUpdated;
|
|
209
|
+
const lastUpdatedEnabled = lastUpdatedRaw !== false && (typeof lastUpdatedRaw !== "object" || lastUpdatedRaw.enabled !== false);
|
|
210
|
+
const lastUpdatedPosition = typeof lastUpdatedRaw === "object" ? lastUpdatedRaw.position ?? "footer" : "footer";
|
|
211
|
+
const llmsTxtEnabled = resolveBool(config.llmsTxt);
|
|
212
|
+
const staticExport = !!config.staticExport;
|
|
213
|
+
const openDocsProviders = (typeof pageActions?.openDocs === "object" && pageActions.openDocs.providers ? pageActions.openDocs.providers : void 0)?.map((provider) => ({
|
|
214
|
+
name: provider.name,
|
|
215
|
+
urlTemplate: provider.urlTemplate
|
|
216
|
+
}));
|
|
217
|
+
const aiConfig = config.ai;
|
|
218
|
+
const aiEnabled = !staticExport && !!aiConfig?.enabled;
|
|
219
|
+
const aiMode = aiConfig?.mode ?? "search";
|
|
220
|
+
const aiPosition = aiConfig?.position ?? "bottom-right";
|
|
221
|
+
const aiFloatingStyle = aiConfig?.floatingStyle ?? "panel";
|
|
222
|
+
const aiSuggestedQuestions = aiConfig?.suggestedQuestions;
|
|
223
|
+
const aiLabel = aiConfig?.aiLabel;
|
|
224
|
+
const aiLoaderVariant = aiConfig?.loader;
|
|
225
|
+
const rawModelConfig = aiConfig?.model;
|
|
226
|
+
let aiModels = aiConfig?.models;
|
|
227
|
+
let aiDefaultModelId = aiConfig?.defaultModel ?? (typeof aiConfig?.model === "string" ? aiConfig.model : void 0);
|
|
228
|
+
if (rawModelConfig && typeof rawModelConfig === "object") {
|
|
229
|
+
aiModels = rawModelConfig.models ?? aiModels;
|
|
230
|
+
aiDefaultModelId = rawModelConfig.defaultModel ?? rawModelConfig.models?.[0]?.id ?? aiDefaultModelId;
|
|
231
|
+
}
|
|
232
|
+
const i18n = config.i18n;
|
|
233
|
+
const resolvedTree = resolveTreeIcons(locale ? localizeTreeUrls(tree, locale) : tree, config.icons);
|
|
234
|
+
const finalSidebarProps = { ...sidebarProps };
|
|
235
|
+
const sidebarFooter = sidebarProps.footer;
|
|
236
|
+
if (locale && i18n?.locales && i18n.defaultLocale) finalSidebarProps.footer = /* @__PURE__ */ jsxs("div", {
|
|
237
|
+
style: {
|
|
238
|
+
display: "flex",
|
|
239
|
+
flexDirection: "column",
|
|
240
|
+
gap: 12
|
|
241
|
+
},
|
|
242
|
+
children: [sidebarFooter, /* @__PURE__ */ jsx(Suspense, {
|
|
243
|
+
fallback: null,
|
|
244
|
+
children: /* @__PURE__ */ jsx(LocaleThemeControl, {
|
|
245
|
+
locales: i18n.locales,
|
|
246
|
+
defaultLocale: i18n.defaultLocale,
|
|
247
|
+
locale,
|
|
248
|
+
showThemeToggle: themeSwitch.enabled !== false,
|
|
249
|
+
themeMode: themeSwitch.mode
|
|
250
|
+
})
|
|
251
|
+
})]
|
|
252
|
+
});
|
|
253
|
+
if (sidebarComponentFn) finalSidebarProps.component = sidebarComponentFn({
|
|
254
|
+
tree: resolvedTree,
|
|
255
|
+
collapsible: sidebarProps.collapsible !== false,
|
|
256
|
+
flat: !!sidebarFlat
|
|
257
|
+
});
|
|
258
|
+
return /* @__PURE__ */ jsx("div", {
|
|
259
|
+
id: "nd-docs-layout",
|
|
260
|
+
style: { display: "contents" },
|
|
261
|
+
children: /* @__PURE__ */ jsxs(DocsLayout, {
|
|
262
|
+
tree: resolvedTree,
|
|
263
|
+
nav: {
|
|
264
|
+
title: navTitle,
|
|
265
|
+
url: navUrl
|
|
266
|
+
},
|
|
267
|
+
themeSwitch: locale && i18n?.locales ? {
|
|
268
|
+
...themeSwitch,
|
|
269
|
+
enabled: false
|
|
270
|
+
} : themeSwitch,
|
|
271
|
+
sidebar: finalSidebarProps,
|
|
272
|
+
...aiMode === "sidebar-icon" && aiEnabled ? { searchToggle: { components: { lg: /* @__PURE__ */ jsx(SidebarSearchWithAI, {}) } } } : {},
|
|
273
|
+
children: [
|
|
274
|
+
/* @__PURE__ */ jsx(ColorStyle, { colors }),
|
|
275
|
+
/* @__PURE__ */ jsx(TypographyStyle, { typography }),
|
|
276
|
+
/* @__PURE__ */ jsx(LayoutStyle, { layout: layoutDimensions }),
|
|
277
|
+
forcedTheme && /* @__PURE__ */ jsx(ForcedThemeScript, { theme: forcedTheme }),
|
|
278
|
+
!staticExport && /* @__PURE__ */ jsx(Suspense, {
|
|
279
|
+
fallback: null,
|
|
280
|
+
children: /* @__PURE__ */ jsx(DocsCommandSearch, {
|
|
281
|
+
api: docsApiUrl,
|
|
282
|
+
locale
|
|
283
|
+
})
|
|
284
|
+
}),
|
|
285
|
+
aiEnabled && /* @__PURE__ */ jsx(Suspense, {
|
|
286
|
+
fallback: null,
|
|
287
|
+
children: /* @__PURE__ */ jsx(DocsAIFeatures, {
|
|
288
|
+
mode: aiMode,
|
|
289
|
+
api: docsApiUrl,
|
|
290
|
+
locale,
|
|
291
|
+
position: aiPosition,
|
|
292
|
+
floatingStyle: aiFloatingStyle,
|
|
293
|
+
suggestedQuestions: aiSuggestedQuestions,
|
|
294
|
+
aiLabel,
|
|
295
|
+
loaderVariant: aiLoaderVariant,
|
|
296
|
+
models: aiModels,
|
|
297
|
+
defaultModelId: aiDefaultModelId
|
|
298
|
+
})
|
|
299
|
+
}),
|
|
300
|
+
/* @__PURE__ */ jsx(Suspense, {
|
|
301
|
+
fallback: children,
|
|
302
|
+
children: /* @__PURE__ */ jsx(DocsPageClient, {
|
|
303
|
+
tocEnabled,
|
|
304
|
+
tocStyle,
|
|
305
|
+
breadcrumbEnabled,
|
|
306
|
+
entry: config.entry ?? "docs",
|
|
307
|
+
locale,
|
|
308
|
+
copyMarkdown: copyMarkdownEnabled,
|
|
309
|
+
openDocs: openDocsEnabled,
|
|
310
|
+
openDocsProviders,
|
|
311
|
+
pageActionsPosition,
|
|
312
|
+
pageActionsAlignment,
|
|
313
|
+
editOnGithubUrl,
|
|
314
|
+
lastUpdatedEnabled,
|
|
315
|
+
lastUpdatedPosition,
|
|
316
|
+
lastModified,
|
|
317
|
+
llmsTxtEnabled,
|
|
318
|
+
description,
|
|
319
|
+
children
|
|
320
|
+
})
|
|
321
|
+
})
|
|
322
|
+
]
|
|
323
|
+
})
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
//#endregion
|
|
328
|
+
export { TanstackDocsLayout };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/theme",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.36",
|
|
4
4
|
"description": "Theme package for @farming-labs/docs — layout, provider, MDX components, and styles",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -73,6 +73,11 @@
|
|
|
73
73
|
"import": "./dist/docs-api.mjs",
|
|
74
74
|
"default": "./dist/docs-api.mjs"
|
|
75
75
|
},
|
|
76
|
+
"./tanstack": {
|
|
77
|
+
"types": "./dist/tanstack.d.mts",
|
|
78
|
+
"import": "./dist/tanstack.mjs",
|
|
79
|
+
"default": "./dist/tanstack.mjs"
|
|
80
|
+
},
|
|
76
81
|
"./ai": {
|
|
77
82
|
"types": "./dist/ai-search-dialog.d.mts",
|
|
78
83
|
"import": "./dist/ai-search-dialog.mjs",
|
|
@@ -100,11 +105,12 @@
|
|
|
100
105
|
"devDependencies": {
|
|
101
106
|
"@types/node": "^22.10.0",
|
|
102
107
|
"@types/react": "^19.0.0",
|
|
108
|
+
"@types/react-dom": "^19.0.0",
|
|
103
109
|
"next": ">=14.0.0",
|
|
104
110
|
"tsdown": "^0.20.3",
|
|
105
111
|
"typescript": "^5.9.3",
|
|
106
112
|
"vitest": "^3.2.4",
|
|
107
|
-
"@farming-labs/docs": "0.0.
|
|
113
|
+
"@farming-labs/docs": "0.0.36"
|
|
108
114
|
},
|
|
109
115
|
"peerDependencies": {
|
|
110
116
|
"@farming-labs/docs": ">=0.0.1",
|