@farming-labs/theme 0.0.2-beta.10
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/_virtual/_rolldown/runtime.mjs +7 -0
- package/dist/ai-search-dialog.d.mts +37 -0
- package/dist/ai-search-dialog.mjs +937 -0
- package/dist/darksharp/index.d.mts +97 -0
- package/dist/darksharp/index.mjs +111 -0
- package/dist/default/index.d.mts +97 -0
- package/dist/default/index.mjs +110 -0
- package/dist/docs-ai-features.d.mts +23 -0
- package/dist/docs-ai-features.mjs +81 -0
- package/dist/docs-api.d.mts +68 -0
- package/dist/docs-api.mjs +204 -0
- package/dist/docs-layout.d.mts +33 -0
- package/dist/docs-layout.mjs +331 -0
- package/dist/docs-page-client.d.mts +46 -0
- package/dist/docs-page-client.mjs +128 -0
- package/dist/index.d.mts +11 -0
- package/dist/index.mjs +12 -0
- package/dist/mdx.d.mts +38 -0
- package/dist/mdx.mjs +27 -0
- package/dist/page-actions.d.mts +21 -0
- package/dist/page-actions.mjs +155 -0
- package/dist/pixel-border/index.d.mts +87 -0
- package/dist/pixel-border/index.mjs +95 -0
- package/dist/provider.d.mts +14 -0
- package/dist/provider.mjs +29 -0
- package/dist/search.d.mts +34 -0
- package/dist/search.mjs +36 -0
- package/dist/serialize-icon.d.mts +4 -0
- package/dist/serialize-icon.mjs +16 -0
- package/dist/theme.d.mts +2 -0
- package/dist/theme.mjs +3 -0
- package/package.json +90 -0
- package/styles/ai.css +894 -0
- package/styles/base.css +298 -0
- package/styles/darksharp.css +433 -0
- package/styles/default.css +88 -0
- package/styles/fumadocs.css +2 -0
- package/styles/pixel-border.css +671 -0
- package/styles/presets/base.css +14 -0
- package/styles/presets/black.css +14 -0
- package/styles/presets/neutral.css +14 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { PageActions } from "./page-actions.mjs";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { DocsBody, DocsPage, EditOnGitHub } from "fumadocs-ui/layouts/docs/page";
|
|
7
|
+
import { usePathname, useRouter } from "next/navigation";
|
|
8
|
+
|
|
9
|
+
//#region src/docs-page-client.tsx
|
|
10
|
+
/**
|
|
11
|
+
* Path-based breadcrumb that shows only parent / current folder.
|
|
12
|
+
* Skips the entry segment (e.g. "docs"). Parent is clickable.
|
|
13
|
+
*/
|
|
14
|
+
function PathBreadcrumb({ pathname, entry }) {
|
|
15
|
+
const router = useRouter();
|
|
16
|
+
const allSegments = pathname.split("/").filter(Boolean);
|
|
17
|
+
const segments = allSegments.filter((s) => s.toLowerCase() !== entry.toLowerCase());
|
|
18
|
+
if (segments.length < 2) return null;
|
|
19
|
+
const parentSegment = segments[segments.length - 2];
|
|
20
|
+
const currentSegment = segments[segments.length - 1];
|
|
21
|
+
const parentLabel = parentSegment.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
22
|
+
const currentLabel = currentSegment.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
23
|
+
const parentIndex = allSegments.indexOf(parentSegment);
|
|
24
|
+
const parentUrl = "/" + allSegments.slice(0, parentIndex + 1).join("/");
|
|
25
|
+
return /* @__PURE__ */ jsxs("nav", {
|
|
26
|
+
className: "fd-breadcrumb",
|
|
27
|
+
"aria-label": "Breadcrumb",
|
|
28
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
29
|
+
className: "fd-breadcrumb-item",
|
|
30
|
+
children: /* @__PURE__ */ jsx("a", {
|
|
31
|
+
href: parentUrl,
|
|
32
|
+
className: "fd-breadcrumb-parent fd-breadcrumb-link",
|
|
33
|
+
onClick: (e) => {
|
|
34
|
+
e.preventDefault();
|
|
35
|
+
router.push(parentUrl);
|
|
36
|
+
},
|
|
37
|
+
children: parentLabel
|
|
38
|
+
})
|
|
39
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
40
|
+
className: "fd-breadcrumb-item",
|
|
41
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
42
|
+
className: "fd-breadcrumb-sep",
|
|
43
|
+
children: "/"
|
|
44
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
45
|
+
className: "fd-breadcrumb-current",
|
|
46
|
+
children: currentLabel
|
|
47
|
+
})]
|
|
48
|
+
})]
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Client wrapper for DocsPage that auto-detects headings from the DOM,
|
|
53
|
+
* populates the Table of Contents, and renders page action buttons
|
|
54
|
+
* (Copy Markdown, Open in LLM). Re-scans when the route changes.
|
|
55
|
+
*/
|
|
56
|
+
/**
|
|
57
|
+
* Build the GitHub URL for the current page's source file.
|
|
58
|
+
*
|
|
59
|
+
* Examples:
|
|
60
|
+
* No directory: https://github.com/user/repo/tree/main/app/docs/cli/page.mdx
|
|
61
|
+
* With directory: https://github.com/farming-labs/docs/tree/main/website/app/docs/cli/page.mdx
|
|
62
|
+
*/
|
|
63
|
+
function buildGithubFileUrl(githubUrl, branch, pathname, directory) {
|
|
64
|
+
const segments = pathname.replace(/^\//, "").replace(/\/$/, "");
|
|
65
|
+
return `${githubUrl}/tree/${branch}/${directory ? `${directory}/` : ""}app/${segments}/page.mdx`;
|
|
66
|
+
}
|
|
67
|
+
function DocsPageClient({ tocEnabled, breadcrumbEnabled = true, entry = "docs", copyMarkdown = false, openDocs = false, openDocsProviders, pageActionsPosition = "below-title", githubUrl, githubBranch = "main", githubDirectory, lastModifiedMap, children }) {
|
|
68
|
+
const [toc, setToc] = useState([]);
|
|
69
|
+
const pathname = usePathname();
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
if (!tocEnabled) return;
|
|
72
|
+
const timer = requestAnimationFrame(() => {
|
|
73
|
+
const container = document.getElementById("nd-page");
|
|
74
|
+
if (!container) return;
|
|
75
|
+
const headings = container.querySelectorAll("h2[id], h3[id], h4[id]");
|
|
76
|
+
setToc(Array.from(headings).map((el) => ({
|
|
77
|
+
title: el.textContent?.replace(/^#\s*/, "") || "",
|
|
78
|
+
url: `#${el.id}`,
|
|
79
|
+
depth: parseInt(el.tagName[1], 10)
|
|
80
|
+
})));
|
|
81
|
+
});
|
|
82
|
+
return () => cancelAnimationFrame(timer);
|
|
83
|
+
}, [tocEnabled, pathname]);
|
|
84
|
+
const showActions = copyMarkdown || openDocs;
|
|
85
|
+
const githubFileUrl = githubUrl ? buildGithubFileUrl(githubUrl, githubBranch, pathname, githubDirectory) : void 0;
|
|
86
|
+
const normalizedPath = pathname.replace(/\/$/, "") || "/";
|
|
87
|
+
const lastModified = lastModifiedMap?.[normalizedPath];
|
|
88
|
+
const showFooter = githubFileUrl || lastModified;
|
|
89
|
+
return /* @__PURE__ */ jsxs(DocsPage, {
|
|
90
|
+
toc,
|
|
91
|
+
tableOfContent: { enabled: tocEnabled },
|
|
92
|
+
tableOfContentPopover: { enabled: tocEnabled },
|
|
93
|
+
breadcrumb: { enabled: false },
|
|
94
|
+
children: [
|
|
95
|
+
breadcrumbEnabled && /* @__PURE__ */ jsx(PathBreadcrumb, {
|
|
96
|
+
pathname,
|
|
97
|
+
entry
|
|
98
|
+
}),
|
|
99
|
+
showActions && /* @__PURE__ */ jsx("div", {
|
|
100
|
+
"data-actions-position": pageActionsPosition,
|
|
101
|
+
children: /* @__PURE__ */ jsx(PageActions, {
|
|
102
|
+
copyMarkdown,
|
|
103
|
+
openDocs,
|
|
104
|
+
providers: openDocsProviders
|
|
105
|
+
})
|
|
106
|
+
}),
|
|
107
|
+
/* @__PURE__ */ jsxs(DocsBody, {
|
|
108
|
+
style: {
|
|
109
|
+
display: "flex",
|
|
110
|
+
flexDirection: "column"
|
|
111
|
+
},
|
|
112
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
113
|
+
style: { flex: 1 },
|
|
114
|
+
children
|
|
115
|
+
}), showFooter && /* @__PURE__ */ jsxs("div", {
|
|
116
|
+
className: "not-prose fd-page-footer",
|
|
117
|
+
children: [githubFileUrl && /* @__PURE__ */ jsx(EditOnGitHub, { href: githubFileUrl }), lastModified && /* @__PURE__ */ jsxs("span", {
|
|
118
|
+
className: "fd-last-updated",
|
|
119
|
+
children: ["Last updated: ", lastModified]
|
|
120
|
+
})]
|
|
121
|
+
})]
|
|
122
|
+
})
|
|
123
|
+
]
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
//#endregion
|
|
128
|
+
export { DocsPageClient };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { DefaultUIDefaults, fumadocs } from "./default/index.mjs";
|
|
2
|
+
import { createDocsLayout, createDocsMetadata } from "./docs-layout.mjs";
|
|
3
|
+
import { DocsPageClient } from "./docs-page-client.mjs";
|
|
4
|
+
import { RootProvider } from "./provider.mjs";
|
|
5
|
+
import { PageActions } from "./page-actions.mjs";
|
|
6
|
+
import { DocsLayout } from "fumadocs-ui/layouts/docs";
|
|
7
|
+
import { DocsBody, DocsPage } from "fumadocs-ui/layouts/docs/page";
|
|
8
|
+
import { AIConfig, BreadcrumbConfig, CopyMarkdownConfig, DocsConfig, DocsMetadata, DocsNav, DocsTheme, FontStyle, OGConfig, OpenDocsConfig, OpenDocsProvider, PageActionsConfig, PageFrontmatter, SidebarConfig, ThemeToggleConfig, TypographyConfig, UIConfig, createTheme, deepMerge, defineDocs, extendTheme } from "@farming-labs/docs";
|
|
9
|
+
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
|
|
10
|
+
import { CodeBlock, CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger, Pre } from "fumadocs-ui/components/codeblock";
|
|
11
|
+
export { type AIConfig, type BreadcrumbConfig, CodeBlock, CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger, type CopyMarkdownConfig, DocsBody, type DocsConfig, DocsLayout, type DocsMetadata, type DocsNav, DocsPage, DocsPageClient, type DocsTheme, type FontStyle, DefaultUIDefaults as FumadocsUIDefaults, type OGConfig, type OpenDocsConfig, type OpenDocsProvider, PageActions, type PageActionsConfig, type PageFrontmatter, Pre, RootProvider, type SidebarConfig, Tab, Tabs, type ThemeToggleConfig, type TypographyConfig, type UIConfig, createDocsLayout, createDocsMetadata, createTheme, deepMerge, defineDocs, extendTheme, fumadocs };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PageActions } from "./page-actions.mjs";
|
|
2
|
+
import { DocsPageClient } from "./docs-page-client.mjs";
|
|
3
|
+
import { createDocsLayout, createDocsMetadata } from "./docs-layout.mjs";
|
|
4
|
+
import { RootProvider } from "./provider.mjs";
|
|
5
|
+
import { DefaultUIDefaults, fumadocs } from "./default/index.mjs";
|
|
6
|
+
import { DocsLayout } from "fumadocs-ui/layouts/docs";
|
|
7
|
+
import { DocsBody, DocsPage } from "fumadocs-ui/layouts/docs/page";
|
|
8
|
+
import { createTheme, deepMerge, defineDocs, extendTheme } from "@farming-labs/docs";
|
|
9
|
+
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
|
|
10
|
+
import { CodeBlock, CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger, Pre } from "fumadocs-ui/components/codeblock";
|
|
11
|
+
|
|
12
|
+
export { CodeBlock, CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger, DocsBody, DocsLayout, DocsPage, DocsPageClient, DefaultUIDefaults as FumadocsUIDefaults, PageActions, Pre, RootProvider, Tab, Tabs, createDocsLayout, createDocsMetadata, createTheme, deepMerge, defineDocs, extendTheme, fumadocs };
|
package/dist/mdx.d.mts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as react from "react";
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
|
+
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
|
|
4
|
+
import * as fumadocs_ui_components_codeblock0 from "fumadocs-ui/components/codeblock";
|
|
5
|
+
import defaultMdxComponents from "fumadocs-ui/mdx";
|
|
6
|
+
import * as fumadocs_ui_components_card0 from "fumadocs-ui/components/card";
|
|
7
|
+
import * as fumadocs_ui_components_callout0 from "fumadocs-ui/components/callout";
|
|
8
|
+
|
|
9
|
+
//#region src/mdx.d.ts
|
|
10
|
+
declare const extendedMdxComponents: {
|
|
11
|
+
Tab: typeof Tab;
|
|
12
|
+
Tabs: typeof Tabs;
|
|
13
|
+
CodeBlockTab: typeof fumadocs_ui_components_codeblock0.CodeBlockTab;
|
|
14
|
+
CodeBlockTabs: typeof fumadocs_ui_components_codeblock0.CodeBlockTabs;
|
|
15
|
+
CodeBlockTabsList: typeof fumadocs_ui_components_codeblock0.CodeBlockTabsList;
|
|
16
|
+
CodeBlockTabsTrigger: typeof fumadocs_ui_components_codeblock0.CodeBlockTabsTrigger;
|
|
17
|
+
pre: (props: react.HTMLAttributes<HTMLPreElement>) => react_jsx_runtime0.JSX.Element;
|
|
18
|
+
Card: typeof fumadocs_ui_components_card0.Card;
|
|
19
|
+
Cards: typeof fumadocs_ui_components_card0.Cards;
|
|
20
|
+
a: react.FC<react.AnchorHTMLAttributes<HTMLAnchorElement>>;
|
|
21
|
+
img: (props: react.ImgHTMLAttributes<HTMLImageElement> & {
|
|
22
|
+
sizes?: string;
|
|
23
|
+
}) => react_jsx_runtime0.JSX.Element;
|
|
24
|
+
h1: (props: react.HTMLAttributes<HTMLHeadingElement>) => react_jsx_runtime0.JSX.Element;
|
|
25
|
+
h2: (props: react.HTMLAttributes<HTMLHeadingElement>) => react_jsx_runtime0.JSX.Element;
|
|
26
|
+
h3: (props: react.HTMLAttributes<HTMLHeadingElement>) => react_jsx_runtime0.JSX.Element;
|
|
27
|
+
h4: (props: react.HTMLAttributes<HTMLHeadingElement>) => react_jsx_runtime0.JSX.Element;
|
|
28
|
+
h5: (props: react.HTMLAttributes<HTMLHeadingElement>) => react_jsx_runtime0.JSX.Element;
|
|
29
|
+
h6: (props: react.HTMLAttributes<HTMLHeadingElement>) => react_jsx_runtime0.JSX.Element;
|
|
30
|
+
table: (props: react.TableHTMLAttributes<HTMLTableElement>) => react_jsx_runtime0.JSX.Element;
|
|
31
|
+
Callout: typeof fumadocs_ui_components_callout0.Callout;
|
|
32
|
+
CalloutContainer: typeof fumadocs_ui_components_callout0.CalloutContainer;
|
|
33
|
+
CalloutTitle: typeof fumadocs_ui_components_callout0.CalloutTitle;
|
|
34
|
+
CalloutDescription: typeof fumadocs_ui_components_callout0.CalloutDescription;
|
|
35
|
+
};
|
|
36
|
+
declare function getMDXComponents<T extends Record<string, unknown> = Record<string, unknown>>(overrides?: T): typeof extendedMdxComponents & T;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { Tab, Tabs, defaultMdxComponents, extendedMdxComponents, getMDXComponents };
|
package/dist/mdx.mjs
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
|
|
2
|
+
import defaultMdxComponents from "fumadocs-ui/mdx";
|
|
3
|
+
|
|
4
|
+
//#region src/mdx.ts
|
|
5
|
+
/**
|
|
6
|
+
* Re-export fumadocs-ui MDX components.
|
|
7
|
+
*
|
|
8
|
+
* Includes all default MDX components (headings, code blocks, callouts, cards)
|
|
9
|
+
* plus Tabs/Tab for tabbed content and InstallTabs for package manager tabs.
|
|
10
|
+
*
|
|
11
|
+
* Usage in mdx-components.tsx:
|
|
12
|
+
* import { getMDXComponents } from "@farming-labs/theme/mdx";
|
|
13
|
+
*/
|
|
14
|
+
const extendedMdxComponents = {
|
|
15
|
+
...defaultMdxComponents,
|
|
16
|
+
Tab,
|
|
17
|
+
Tabs
|
|
18
|
+
};
|
|
19
|
+
function getMDXComponents(overrides) {
|
|
20
|
+
return {
|
|
21
|
+
...extendedMdxComponents,
|
|
22
|
+
...overrides
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
export { Tab, Tabs, defaultMdxComponents, extendedMdxComponents, getMDXComponents };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
|
+
|
|
3
|
+
//#region src/page-actions.d.ts
|
|
4
|
+
/** Serializable provider — icon is an HTML string, not JSX. */
|
|
5
|
+
interface SerializedProvider {
|
|
6
|
+
name: string;
|
|
7
|
+
iconHtml?: string;
|
|
8
|
+
urlTemplate: string;
|
|
9
|
+
}
|
|
10
|
+
interface PageActionsProps {
|
|
11
|
+
copyMarkdown?: boolean;
|
|
12
|
+
openDocs?: boolean;
|
|
13
|
+
providers?: SerializedProvider[];
|
|
14
|
+
}
|
|
15
|
+
declare function PageActions({
|
|
16
|
+
copyMarkdown,
|
|
17
|
+
openDocs,
|
|
18
|
+
providers
|
|
19
|
+
}: PageActionsProps): react_jsx_runtime0.JSX.Element | null;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { PageActions };
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { usePathname } from "next/navigation";
|
|
6
|
+
|
|
7
|
+
//#region src/page-actions.tsx
|
|
8
|
+
const CopyIcon = () => /* @__PURE__ */ jsxs("svg", {
|
|
9
|
+
width: "14",
|
|
10
|
+
height: "14",
|
|
11
|
+
viewBox: "0 0 24 24",
|
|
12
|
+
fill: "none",
|
|
13
|
+
stroke: "currentColor",
|
|
14
|
+
strokeWidth: "2",
|
|
15
|
+
strokeLinecap: "round",
|
|
16
|
+
strokeLinejoin: "round",
|
|
17
|
+
children: [/* @__PURE__ */ jsx("rect", {
|
|
18
|
+
x: "9",
|
|
19
|
+
y: "9",
|
|
20
|
+
width: "13",
|
|
21
|
+
height: "13",
|
|
22
|
+
rx: "2",
|
|
23
|
+
ry: "2"
|
|
24
|
+
}), /* @__PURE__ */ jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })]
|
|
25
|
+
});
|
|
26
|
+
const CheckIcon = () => /* @__PURE__ */ jsx("svg", {
|
|
27
|
+
width: "14",
|
|
28
|
+
height: "14",
|
|
29
|
+
viewBox: "0 0 24 24",
|
|
30
|
+
fill: "none",
|
|
31
|
+
stroke: "currentColor",
|
|
32
|
+
strokeWidth: "2",
|
|
33
|
+
strokeLinecap: "round",
|
|
34
|
+
strokeLinejoin: "round",
|
|
35
|
+
children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
|
|
36
|
+
});
|
|
37
|
+
const ChevronDownIcon = () => /* @__PURE__ */ jsx("svg", {
|
|
38
|
+
width: "12",
|
|
39
|
+
height: "12",
|
|
40
|
+
viewBox: "0 0 24 24",
|
|
41
|
+
fill: "none",
|
|
42
|
+
stroke: "currentColor",
|
|
43
|
+
strokeWidth: "2",
|
|
44
|
+
strokeLinecap: "round",
|
|
45
|
+
strokeLinejoin: "round",
|
|
46
|
+
children: /* @__PURE__ */ jsx("polyline", { points: "6 9 12 15 18 9" })
|
|
47
|
+
});
|
|
48
|
+
const ExternalLinkIcon = () => /* @__PURE__ */ jsxs("svg", {
|
|
49
|
+
width: "12",
|
|
50
|
+
height: "12",
|
|
51
|
+
viewBox: "0 0 24 24",
|
|
52
|
+
fill: "none",
|
|
53
|
+
stroke: "currentColor",
|
|
54
|
+
strokeWidth: "2",
|
|
55
|
+
strokeLinecap: "round",
|
|
56
|
+
strokeLinejoin: "round",
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
|
|
59
|
+
/* @__PURE__ */ jsx("polyline", { points: "15 3 21 3 21 9" }),
|
|
60
|
+
/* @__PURE__ */ jsx("line", {
|
|
61
|
+
x1: "10",
|
|
62
|
+
y1: "14",
|
|
63
|
+
x2: "21",
|
|
64
|
+
y2: "3"
|
|
65
|
+
})
|
|
66
|
+
]
|
|
67
|
+
});
|
|
68
|
+
const DEFAULT_PROVIDERS = [{
|
|
69
|
+
name: "ChatGPT",
|
|
70
|
+
urlTemplate: "https://chatgpt.com/?hints=search&q=Read+{mdxUrl},+I+want+to+ask+questions+about+it."
|
|
71
|
+
}, {
|
|
72
|
+
name: "Claude",
|
|
73
|
+
urlTemplate: "https://claude.ai/new?q=Read+{mdxUrl},+I+want+to+ask+questions+about+it."
|
|
74
|
+
}];
|
|
75
|
+
function PageActions({ copyMarkdown, openDocs, providers }) {
|
|
76
|
+
const [copied, setCopied] = useState(false);
|
|
77
|
+
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
78
|
+
const dropdownRef = useRef(null);
|
|
79
|
+
const pathname = usePathname();
|
|
80
|
+
const resolvedProviders = providers ?? DEFAULT_PROVIDERS;
|
|
81
|
+
const handleCopyMarkdown = useCallback(async () => {
|
|
82
|
+
try {
|
|
83
|
+
const article = document.querySelector("article");
|
|
84
|
+
if (article) {
|
|
85
|
+
await navigator.clipboard.writeText(article.innerText || "");
|
|
86
|
+
setCopied(true);
|
|
87
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
88
|
+
}
|
|
89
|
+
} catch {}
|
|
90
|
+
}, []);
|
|
91
|
+
const handleOpen = useCallback((template) => {
|
|
92
|
+
const pageUrl = window.location.href;
|
|
93
|
+
const mdxUrl = `${window.location.origin}${pathname}.mdx`;
|
|
94
|
+
const url = template.replace(/\{url\}/g, encodeURIComponent(pageUrl)).replace(/\{mdxUrl\}/g, encodeURIComponent(mdxUrl));
|
|
95
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
96
|
+
setDropdownOpen(false);
|
|
97
|
+
}, [pathname]);
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
if (!dropdownOpen) return;
|
|
100
|
+
function handleClick(e) {
|
|
101
|
+
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) setDropdownOpen(false);
|
|
102
|
+
}
|
|
103
|
+
document.addEventListener("mousedown", handleClick);
|
|
104
|
+
return () => document.removeEventListener("mousedown", handleClick);
|
|
105
|
+
}, [dropdownOpen]);
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
setDropdownOpen(false);
|
|
108
|
+
setCopied(false);
|
|
109
|
+
}, [pathname]);
|
|
110
|
+
if (!copyMarkdown && !openDocs) return null;
|
|
111
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
112
|
+
className: "fd-page-actions",
|
|
113
|
+
"data-page-actions": true,
|
|
114
|
+
children: [copyMarkdown && /* @__PURE__ */ jsxs("button", {
|
|
115
|
+
type: "button",
|
|
116
|
+
onClick: handleCopyMarkdown,
|
|
117
|
+
className: "fd-page-action-btn",
|
|
118
|
+
"data-copied": copied,
|
|
119
|
+
children: [copied ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {}), /* @__PURE__ */ jsx("span", { children: copied ? "Copied!" : "Copy Markdown" })]
|
|
120
|
+
}), openDocs && resolvedProviders.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
121
|
+
ref: dropdownRef,
|
|
122
|
+
className: "fd-page-action-dropdown",
|
|
123
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
124
|
+
type: "button",
|
|
125
|
+
onClick: () => setDropdownOpen(!dropdownOpen),
|
|
126
|
+
className: "fd-page-action-btn",
|
|
127
|
+
"aria-expanded": dropdownOpen,
|
|
128
|
+
children: [/* @__PURE__ */ jsx("span", { children: "Open in" }), /* @__PURE__ */ jsx(ChevronDownIcon, {})]
|
|
129
|
+
}), dropdownOpen && /* @__PURE__ */ jsx("div", {
|
|
130
|
+
className: "fd-page-action-menu",
|
|
131
|
+
role: "menu",
|
|
132
|
+
children: resolvedProviders.map((provider) => /* @__PURE__ */ jsxs("button", {
|
|
133
|
+
type: "button",
|
|
134
|
+
role: "menuitem",
|
|
135
|
+
className: "fd-page-action-menu-item",
|
|
136
|
+
onClick: () => handleOpen(provider.urlTemplate),
|
|
137
|
+
children: [
|
|
138
|
+
provider.iconHtml && /* @__PURE__ */ jsx("span", {
|
|
139
|
+
className: "fd-page-action-menu-icon",
|
|
140
|
+
dangerouslySetInnerHTML: { __html: provider.iconHtml }
|
|
141
|
+
}),
|
|
142
|
+
/* @__PURE__ */ jsxs("span", {
|
|
143
|
+
className: "fd-page-action-menu-label",
|
|
144
|
+
children: ["Open in ", provider.name]
|
|
145
|
+
}),
|
|
146
|
+
/* @__PURE__ */ jsx(ExternalLinkIcon, {})
|
|
147
|
+
]
|
|
148
|
+
}, provider.name))
|
|
149
|
+
})]
|
|
150
|
+
})]
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
//#endregion
|
|
155
|
+
export { PageActions };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { DocsTheme } from "@farming-labs/docs";
|
|
2
|
+
|
|
3
|
+
//#region src/pixel-border/index.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Pixel-border UI defaults — better-auth inspired, clean dark UI.
|
|
6
|
+
*
|
|
7
|
+
* Theme authors can import and extend:
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { PixelBorderUIDefaults } from "@farming-labs/theme/pixel-border";
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
declare const PixelBorderUIDefaults: {
|
|
13
|
+
colors: {
|
|
14
|
+
primary: string;
|
|
15
|
+
background: string;
|
|
16
|
+
muted: string;
|
|
17
|
+
border: string;
|
|
18
|
+
};
|
|
19
|
+
typography: {
|
|
20
|
+
font: {
|
|
21
|
+
style: {
|
|
22
|
+
sans: string;
|
|
23
|
+
mono: string;
|
|
24
|
+
};
|
|
25
|
+
h1: {
|
|
26
|
+
size: string;
|
|
27
|
+
weight: number;
|
|
28
|
+
lineHeight: string;
|
|
29
|
+
letterSpacing: string;
|
|
30
|
+
};
|
|
31
|
+
h2: {
|
|
32
|
+
size: string;
|
|
33
|
+
weight: number;
|
|
34
|
+
lineHeight: string;
|
|
35
|
+
letterSpacing: string;
|
|
36
|
+
};
|
|
37
|
+
h3: {
|
|
38
|
+
size: string;
|
|
39
|
+
weight: number;
|
|
40
|
+
lineHeight: string;
|
|
41
|
+
};
|
|
42
|
+
h4: {
|
|
43
|
+
size: string;
|
|
44
|
+
weight: number;
|
|
45
|
+
lineHeight: string;
|
|
46
|
+
};
|
|
47
|
+
body: {
|
|
48
|
+
size: string;
|
|
49
|
+
weight: number;
|
|
50
|
+
lineHeight: string;
|
|
51
|
+
};
|
|
52
|
+
small: {
|
|
53
|
+
size: string;
|
|
54
|
+
weight: number;
|
|
55
|
+
lineHeight: string;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
layout: {
|
|
60
|
+
contentWidth: number;
|
|
61
|
+
sidebarWidth: number;
|
|
62
|
+
toc: {
|
|
63
|
+
enabled: boolean;
|
|
64
|
+
depth: number;
|
|
65
|
+
};
|
|
66
|
+
header: {
|
|
67
|
+
height: number;
|
|
68
|
+
sticky: boolean;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
components: {};
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Pixel-border theme preset factory.
|
|
75
|
+
*
|
|
76
|
+
* Built with `createTheme` — the same helper theme authors use.
|
|
77
|
+
* Inspired by better-auth.com — clean dark UI with visible borders.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* import { pixelBorder } from "@farming-labs/theme/pixel-border";
|
|
82
|
+
* export default defineDocs({ theme: pixelBorder() });
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
declare const pixelBorder: (overrides?: Partial<DocsTheme>) => DocsTheme;
|
|
86
|
+
//#endregion
|
|
87
|
+
export { PixelBorderUIDefaults, pixelBorder };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { createTheme } from "@farming-labs/docs";
|
|
2
|
+
|
|
3
|
+
//#region src/pixel-border/index.ts
|
|
4
|
+
/**
|
|
5
|
+
* @farming-labs/theme/pixel-border
|
|
6
|
+
*
|
|
7
|
+
* Inspired by better-auth.com — clean dark UI with visible rounded borders,
|
|
8
|
+
* pixel-perfect spacing, and a refined sidebar.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Pixel-border UI defaults — better-auth inspired, clean dark UI.
|
|
12
|
+
*
|
|
13
|
+
* Theme authors can import and extend:
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { PixelBorderUIDefaults } from "@farming-labs/theme/pixel-border";
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
const PixelBorderUIDefaults = {
|
|
19
|
+
colors: {
|
|
20
|
+
primary: "oklch(0.985 0.001 106.423)",
|
|
21
|
+
background: "hsl(0 0% 2%)",
|
|
22
|
+
muted: "hsl(0 0% 55%)",
|
|
23
|
+
border: "hsl(0 0% 15%)"
|
|
24
|
+
},
|
|
25
|
+
typography: { font: {
|
|
26
|
+
style: {
|
|
27
|
+
sans: "var(--font-geist-sans, system-ui, -apple-system, sans-serif)",
|
|
28
|
+
mono: "var(--font-geist-mono, ui-monospace, monospace)"
|
|
29
|
+
},
|
|
30
|
+
h1: {
|
|
31
|
+
size: "2.25rem",
|
|
32
|
+
weight: 700,
|
|
33
|
+
lineHeight: "1.2",
|
|
34
|
+
letterSpacing: "-0.02em"
|
|
35
|
+
},
|
|
36
|
+
h2: {
|
|
37
|
+
size: "1.5rem",
|
|
38
|
+
weight: 600,
|
|
39
|
+
lineHeight: "1.3",
|
|
40
|
+
letterSpacing: "-0.01em"
|
|
41
|
+
},
|
|
42
|
+
h3: {
|
|
43
|
+
size: "1.25rem",
|
|
44
|
+
weight: 600,
|
|
45
|
+
lineHeight: "1.4"
|
|
46
|
+
},
|
|
47
|
+
h4: {
|
|
48
|
+
size: "1.125rem",
|
|
49
|
+
weight: 600,
|
|
50
|
+
lineHeight: "1.4"
|
|
51
|
+
},
|
|
52
|
+
body: {
|
|
53
|
+
size: "1rem",
|
|
54
|
+
weight: 400,
|
|
55
|
+
lineHeight: "1.75"
|
|
56
|
+
},
|
|
57
|
+
small: {
|
|
58
|
+
size: "0.875rem",
|
|
59
|
+
weight: 400,
|
|
60
|
+
lineHeight: "1.5"
|
|
61
|
+
}
|
|
62
|
+
} },
|
|
63
|
+
layout: {
|
|
64
|
+
contentWidth: 860,
|
|
65
|
+
sidebarWidth: 286,
|
|
66
|
+
toc: {
|
|
67
|
+
enabled: true,
|
|
68
|
+
depth: 3
|
|
69
|
+
},
|
|
70
|
+
header: {
|
|
71
|
+
height: 56,
|
|
72
|
+
sticky: true
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
components: {}
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Pixel-border theme preset factory.
|
|
79
|
+
*
|
|
80
|
+
* Built with `createTheme` — the same helper theme authors use.
|
|
81
|
+
* Inspired by better-auth.com — clean dark UI with visible borders.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```ts
|
|
85
|
+
* import { pixelBorder } from "@farming-labs/theme/pixel-border";
|
|
86
|
+
* export default defineDocs({ theme: pixelBorder() });
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
const pixelBorder = createTheme({
|
|
90
|
+
name: "fumadocs-pixel-border",
|
|
91
|
+
ui: PixelBorderUIDefaults
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
//#endregion
|
|
95
|
+
export { PixelBorderUIDefaults, pixelBorder };
|
|
@@ -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/next";
|
|
4
|
+
|
|
5
|
+
//#region src/provider.d.ts
|
|
6
|
+
type FumadocsProviderProps = ComponentPropsWithoutRef<typeof RootProvider$1>;
|
|
7
|
+
interface DocsRootProviderProps extends FumadocsProviderProps {}
|
|
8
|
+
declare function RootProvider({
|
|
9
|
+
children,
|
|
10
|
+
search,
|
|
11
|
+
...props
|
|
12
|
+
}: DocsRootProviderProps): react_jsx_runtime0.JSX.Element;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { DocsRootProviderProps, RootProvider };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import { RootProvider as RootProvider$1 } from "fumadocs-ui/provider/next";
|
|
5
|
+
|
|
6
|
+
//#region src/provider.tsx
|
|
7
|
+
/**
|
|
8
|
+
* RootProvider wrapper — thin layer over fumadocs-ui's RootProvider.
|
|
9
|
+
*
|
|
10
|
+
* Defaults the search API to `/api/docs` (unified handler).
|
|
11
|
+
* AI features are handled automatically by `createDocsLayout`
|
|
12
|
+
* based on the `ai` config in `docs.config.tsx` — no props needed here.
|
|
13
|
+
*/
|
|
14
|
+
function RootProvider({ children, search, ...props }) {
|
|
15
|
+
return /* @__PURE__ */ jsx(RootProvider$1, {
|
|
16
|
+
search: {
|
|
17
|
+
...search,
|
|
18
|
+
options: {
|
|
19
|
+
api: "/api/docs",
|
|
20
|
+
...search?.options
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
...props,
|
|
24
|
+
children
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
//#endregion
|
|
29
|
+
export { RootProvider };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//#region src/search.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Search API — backward-compatible re-export.
|
|
4
|
+
*
|
|
5
|
+
* New projects should use `createDocsAPI` from `@farming-labs/theme/api`
|
|
6
|
+
* which provides a unified handler for both search (GET) and AI chat (POST).
|
|
7
|
+
*
|
|
8
|
+
* This module is kept for backward compatibility with existing projects
|
|
9
|
+
* that import `createDocsSearchAPI` from `@farming-labs/theme/search`.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* // Recommended (new): app/api/docs/route.ts
|
|
14
|
+
* import { createDocsAPI } from "@farming-labs/theme/api";
|
|
15
|
+
* export const { GET, POST } = createDocsAPI();
|
|
16
|
+
*
|
|
17
|
+
* // Legacy: app/api/search/route.ts
|
|
18
|
+
* import { createDocsSearchAPI } from "@farming-labs/theme/search";
|
|
19
|
+
* export const { GET } = createDocsSearchAPI();
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* @deprecated Use `createDocsAPI` from `@farming-labs/theme/api` instead.
|
|
24
|
+
* This function is kept for backward compatibility.
|
|
25
|
+
*/
|
|
26
|
+
declare function createDocsSearchAPI(options?: {
|
|
27
|
+
entry?: string;
|
|
28
|
+
language?: string;
|
|
29
|
+
}): {
|
|
30
|
+
GET: (request: Request) => Promise<Response>;
|
|
31
|
+
POST(request: Request): Promise<Response>;
|
|
32
|
+
};
|
|
33
|
+
//#endregion
|
|
34
|
+
export { createDocsSearchAPI };
|