@farming-labs/theme 0.1.58 → 0.1.60
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.mjs +5 -5
- package/dist/docs-ai-features.mjs +2 -2
- package/dist/docs-command-search.mjs +4 -4
- package/dist/docs-layout.mjs +1 -1
- package/dist/docs-page-client.mjs +7 -5
- package/dist/index.d.mts +2 -1
- package/dist/index.mjs +2 -1
- package/dist/mdx.d.mts +7 -1
- package/dist/mdx.mjs +41 -10
- package/dist/prompt-text.mjs +23 -0
- package/dist/prompt.d.mts +53 -0
- package/dist/prompt.mjs +281 -0
- package/dist/tanstack-layout.mjs +1 -1
- package/package.json +2 -2
- package/styles/base.css +175 -5
- package/styles/pixel-border.css +62 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
4
|
import { createPortal } from "react-dom";
|
|
5
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { highlight } from "sugar-high";
|
|
7
7
|
|
|
8
8
|
//#region src/ai-search-dialog.tsx
|
|
@@ -635,7 +635,7 @@ function DocsSearchDialog({ open, onOpenChange, api = "/api/docs", suggestedQues
|
|
|
635
635
|
};
|
|
636
636
|
if (!open) return null;
|
|
637
637
|
const aiName = aiLabel || "AI";
|
|
638
|
-
return createPortal(/* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
638
|
+
return createPortal(/* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
639
639
|
onClick: () => onOpenChange(false),
|
|
640
640
|
className: "fd-ai-overlay"
|
|
641
641
|
}), /* @__PURE__ */ jsxs("div", {
|
|
@@ -863,7 +863,7 @@ function FloatingAIChat({ api = "/api/docs", position = "bottom-right", floating
|
|
|
863
863
|
const isModal = floatingStyle === "modal";
|
|
864
864
|
const containerStyles = getContainerStyles(floatingStyle, position);
|
|
865
865
|
const aiName = aiLabel || "AI";
|
|
866
|
-
return createPortal(/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
866
|
+
return createPortal(/* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
867
867
|
isOpen && isModal && /* @__PURE__ */ jsx("div", {
|
|
868
868
|
onClick: () => setIsOpen(false),
|
|
869
869
|
className: "fd-ai-overlay"
|
|
@@ -1030,7 +1030,7 @@ function FullModalAIChat({ api, isOpen, setIsOpen, messages, setMessages, aiInpu
|
|
|
1030
1030
|
if (canSend) submitQuestion(aiInput);
|
|
1031
1031
|
}
|
|
1032
1032
|
};
|
|
1033
|
-
return createPortal(/* @__PURE__ */ jsxs(Fragment, { children: [isOpen && /* @__PURE__ */ jsxs("div", {
|
|
1033
|
+
return createPortal(/* @__PURE__ */ jsxs(Fragment$1, { children: [isOpen && /* @__PURE__ */ jsxs("div", {
|
|
1034
1034
|
className: "fd-ai-fm-overlay",
|
|
1035
1035
|
onClick: (e) => {
|
|
1036
1036
|
if (e.target === e.currentTarget) setIsOpen(false);
|
|
@@ -1186,7 +1186,7 @@ function AIModalDialog({ open, onOpenChange, api = "/api/docs", suggestedQuestio
|
|
|
1186
1186
|
}, [open]);
|
|
1187
1187
|
if (!open) return null;
|
|
1188
1188
|
const aiName = aiLabel || "AI";
|
|
1189
|
-
return createPortal(/* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
1189
|
+
return createPortal(/* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
1190
1190
|
onClick: () => onOpenChange(false),
|
|
1191
1191
|
className: "fd-ai-overlay"
|
|
1192
1192
|
}), /* @__PURE__ */ jsxs("div", {
|
|
@@ -4,7 +4,7 @@ import { useWindowSearchParams } from "./client-location.mjs";
|
|
|
4
4
|
import { resolveClientLocale, withLangInUrl } from "./i18n.mjs";
|
|
5
5
|
import { AIModalDialog, DocsSearchDialog, FloatingAIChat } from "./ai-search-dialog.mjs";
|
|
6
6
|
import { useEffect, useState } from "react";
|
|
7
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
|
|
9
9
|
//#region src/docs-ai-features.tsx
|
|
10
10
|
/**
|
|
@@ -124,7 +124,7 @@ function SidebarIconModeAI({ api, suggestedQuestions, aiLabel, loaderVariant, lo
|
|
|
124
124
|
window.removeEventListener("fd-open-ai", onAI);
|
|
125
125
|
};
|
|
126
126
|
}, []);
|
|
127
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(DocsSearchDialog, {
|
|
127
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DocsSearchDialog, {
|
|
128
128
|
open: searchOpen,
|
|
129
129
|
onOpenChange: setSearchOpen,
|
|
130
130
|
api,
|
|
@@ -4,7 +4,7 @@ import { useWindowSearchParams } from "./client-location.mjs";
|
|
|
4
4
|
import { resolveClientLocale, withLangInUrl } from "./i18n.mjs";
|
|
5
5
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
6
6
|
import { createPortal } from "react-dom";
|
|
7
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
|
|
9
9
|
//#region src/docs-command-search.tsx
|
|
10
10
|
function cn(...classes) {
|
|
@@ -56,7 +56,7 @@ function fuzzyScore(query, text) {
|
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
function HighlightedLabel({ label, indices }) {
|
|
59
|
-
if (!indices.length) return /* @__PURE__ */ jsx(Fragment, { children: label });
|
|
59
|
+
if (!indices.length) return /* @__PURE__ */ jsx(Fragment$1, { children: label });
|
|
60
60
|
const out = [];
|
|
61
61
|
for (let pos = 0; pos < label.length; pos++) if (indices.includes(pos)) {
|
|
62
62
|
let run = label[pos];
|
|
@@ -71,7 +71,7 @@ function HighlightedLabel({ label, indices }) {
|
|
|
71
71
|
}, `m-${pos}`));
|
|
72
72
|
pos = p - 1;
|
|
73
73
|
} else out.push(/* @__PURE__ */ jsx("span", { children: label[pos] }, `t-${pos}`));
|
|
74
|
-
return /* @__PURE__ */ jsx(Fragment, { children: out });
|
|
74
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: out });
|
|
75
75
|
}
|
|
76
76
|
function SearchIcon() {
|
|
77
77
|
return /* @__PURE__ */ jsxs("svg", {
|
|
@@ -492,7 +492,7 @@ function DocsCommandSearch({ api = "/api/docs", locale }) {
|
|
|
492
492
|
}
|
|
493
493
|
if (!mounted || !open) return null;
|
|
494
494
|
const allItems = [...recentItems, ...displayItems];
|
|
495
|
-
return createPortal(/* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
495
|
+
return createPortal(/* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
496
496
|
className: "omni-overlay",
|
|
497
497
|
onClick: () => setOpen(false)
|
|
498
498
|
}), /* @__PURE__ */ jsxs("div", {
|
package/dist/docs-layout.mjs
CHANGED
|
@@ -587,7 +587,7 @@ function createDocsLayout(config, options) {
|
|
|
587
587
|
const readingTimeWordsPerMinute = readingTimeOptions.wordsPerMinute ?? 220;
|
|
588
588
|
const llmsTxtEnabled = resolveBool(config.llmsTxt);
|
|
589
589
|
const feedbackConfig = resolveFeedbackConfig(config.feedback);
|
|
590
|
-
const openDocsProviders = (typeof pageActions
|
|
590
|
+
const openDocsProviders = (pageActions?.openDocs && typeof pageActions.openDocs === "object" && pageActions.openDocs.providers ? pageActions.openDocs.providers : void 0)?.map((p) => ({
|
|
591
591
|
name: p.name,
|
|
592
592
|
urlTemplate: p.urlTemplate,
|
|
593
593
|
iconHtml: p.icon ? serializeIcon(p.icon) : void 0
|
|
@@ -4,11 +4,11 @@ import { PageActions } from "./page-actions.mjs";
|
|
|
4
4
|
import { useWindowSearchParams } from "./client-location.mjs";
|
|
5
5
|
import { DocsFeedback } from "./docs-feedback.mjs";
|
|
6
6
|
import { resolveClientLocale, withLangInUrl } from "./i18n.mjs";
|
|
7
|
-
import { Children, cloneElement, isValidElement, useEffect, useState } from "react";
|
|
7
|
+
import { Children, Fragment, cloneElement, isValidElement, useEffect, useState } from "react";
|
|
8
8
|
import { DocsBody, DocsPage, EditOnGitHub } from "fumadocs-ui/layouts/docs/page";
|
|
9
9
|
import { createPortal } from "react-dom";
|
|
10
10
|
import { usePathname, useRouter } from "fumadocs-core/framework";
|
|
11
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
12
12
|
|
|
13
13
|
//#region src/docs-page-client.tsx
|
|
14
14
|
/**
|
|
@@ -124,6 +124,7 @@ function injectTitleDecorations(node, { description, belowTitle }) {
|
|
|
124
124
|
node,
|
|
125
125
|
inserted: false
|
|
126
126
|
};
|
|
127
|
+
const insertedExtras = extras.map((extra, index) => /* @__PURE__ */ jsx(Fragment, { children: extra }, `fd-title-decoration-${index}`));
|
|
127
128
|
function visit(current) {
|
|
128
129
|
if (current == null || typeof current === "boolean") return current;
|
|
129
130
|
if (inserted) return current;
|
|
@@ -134,7 +135,7 @@ function injectTitleDecorations(node, { description, belowTitle }) {
|
|
|
134
135
|
if (!isValidElement(current)) return current;
|
|
135
136
|
if (typeof current.type === "string" && current.type === "h1") {
|
|
136
137
|
inserted = true;
|
|
137
|
-
return
|
|
138
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [current, insertedExtras] }, "fd-title-decoration-block");
|
|
138
139
|
}
|
|
139
140
|
const childProps = current.props ?? null;
|
|
140
141
|
if (childProps?.children === void 0) return current;
|
|
@@ -159,7 +160,7 @@ function injectTitleDecorations(node, { description, belowTitle }) {
|
|
|
159
160
|
}
|
|
160
161
|
function TitleDecorations({ description, belowTitle }) {
|
|
161
162
|
if (!description && !belowTitle) return null;
|
|
162
|
-
return /* @__PURE__ */ jsx(Fragment, { children: Children.toArray([description, belowTitle].filter(Boolean)) });
|
|
163
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: Children.toArray([description, belowTitle].filter(Boolean)) });
|
|
163
164
|
}
|
|
164
165
|
function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled = true, changelogBasePath, entry = "docs", locale, copyMarkdown = false, openDocs = false, openDocsProviders, pageActionsPosition = "below-title", pageActionsAlignment = "left", githubUrl, contentDir, githubBranch = "main", githubDirectory, editOnGithubUrl, lastModifiedMap, lastModified: lastModifiedProp, readingTimeMap, readingTime: readingTimeProp, readingTimeEnabled = false, lastUpdatedEnabled = true, lastUpdatedPosition = "footer", llmsTxtEnabled = false, descriptionMap, description, feedbackEnabled = false, feedbackQuestion, feedbackPlaceholder, feedbackPositiveLabel, feedbackNegativeLabel, feedbackSubmitLabel, feedbackOnFeedback, children }) {
|
|
165
166
|
const fdTocStyle = tocStyle === "directional" ? "clerk" : void 0;
|
|
@@ -318,6 +319,7 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
318
319
|
description: titleDescription,
|
|
319
320
|
belowTitle: belowTitleBlock
|
|
320
321
|
}), titlePortalHost) : null;
|
|
322
|
+
const renderedChildren = Children.toArray(decoratedChildren);
|
|
321
323
|
return /* @__PURE__ */ jsxs(DocsPage, {
|
|
322
324
|
full: false,
|
|
323
325
|
toc,
|
|
@@ -360,7 +362,7 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
|
|
|
360
362
|
children: [
|
|
361
363
|
/* @__PURE__ */ jsx("div", {
|
|
362
364
|
style: { flex: 1 },
|
|
363
|
-
children:
|
|
365
|
+
children: renderedChildren
|
|
364
366
|
}),
|
|
365
367
|
titleDecorationsPortal,
|
|
366
368
|
!isChangelogRoute && feedbackEnabled && /* @__PURE__ */ jsx(DocsFeedback, {
|
package/dist/index.d.mts
CHANGED
|
@@ -11,10 +11,11 @@ import { DocsFeedback, DocsFeedbackProps } from "./docs-feedback.mjs";
|
|
|
11
11
|
import { PageActions } from "./page-actions.mjs";
|
|
12
12
|
import { withLangInUrl } from "./i18n.mjs";
|
|
13
13
|
import { HoverLink, HoverLinkProps } from "./hover-link.mjs";
|
|
14
|
+
import { Prompt, PromptProps } from "./prompt.mjs";
|
|
14
15
|
import { Agent } from "./mdx.mjs";
|
|
15
16
|
import { DocsLayout } from "fumadocs-ui/layouts/docs";
|
|
16
17
|
import { AIConfig, BreadcrumbConfig, ChangelogConfig, ChangelogFrontmatter, CopyMarkdownConfig, DocsConfig, DocsFeedbackData, DocsFeedbackValue, DocsMetadata, DocsNav, DocsTheme, FeedbackConfig, FontStyle, OGConfig, OpenDocsConfig, OpenDocsProvider, PageActionsConfig, PageFrontmatter, SidebarConfig, ThemeToggleConfig, TypographyConfig, UIConfig, createTheme, deepMerge, defineDocs, extendTheme } from "@farming-labs/docs";
|
|
17
18
|
import { DocsBody, DocsPage } from "fumadocs-ui/layouts/docs/page";
|
|
18
19
|
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
|
|
19
20
|
import { CodeBlock, CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger, Pre } from "fumadocs-ui/components/codeblock";
|
|
20
|
-
export { type AIConfig, Agent, type BreadcrumbConfig, type ChangelogConfig, type ChangelogFrontmatter, CodeBlock, CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger, CommandGridUIDefaults, ConcreteUIDefaults, type CopyMarkdownConfig, DocsBody, DocsClientHooks, DocsCommandSearch, type DocsConfig, DocsFeedback, type DocsFeedbackData, type DocsFeedbackProps, type DocsFeedbackValue, DocsLayout, type DocsMetadata, type DocsNav, DocsPage, DocsPageClient, type DocsTheme, type FeedbackConfig, type FontStyle, DefaultUIDefaults as FumadocsUIDefaults, HardlineUIDefaults, HoverLink, type HoverLinkProps, type OGConfig, type OpenDocsConfig, type OpenDocsProvider, PageActions, type PageActionsConfig, type PageFrontmatter, Pre, RootProvider, type SidebarConfig, Tab, Tabs, type ThemeToggleConfig, type TypographyConfig, type UIConfig, commandGrid, concrete, createDocsLayout, createDocsMetadata, createPageMetadata, createTheme, deepMerge, defineDocs, extendTheme, fumadocs, hardline, withLangInUrl };
|
|
21
|
+
export { type AIConfig, Agent, type BreadcrumbConfig, type ChangelogConfig, type ChangelogFrontmatter, CodeBlock, CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger, CommandGridUIDefaults, ConcreteUIDefaults, type CopyMarkdownConfig, DocsBody, DocsClientHooks, DocsCommandSearch, type DocsConfig, DocsFeedback, type DocsFeedbackData, type DocsFeedbackProps, type DocsFeedbackValue, DocsLayout, type DocsMetadata, type DocsNav, DocsPage, DocsPageClient, type DocsTheme, type FeedbackConfig, type FontStyle, DefaultUIDefaults as FumadocsUIDefaults, HardlineUIDefaults, HoverLink, type HoverLinkProps, type OGConfig, type OpenDocsConfig, type OpenDocsProvider, PageActions, type PageActionsConfig, type PageFrontmatter, Pre, Prompt, type PromptProps, RootProvider, type SidebarConfig, Tab, Tabs, type ThemeToggleConfig, type TypographyConfig, type UIConfig, commandGrid, concrete, createDocsLayout, createDocsMetadata, createPageMetadata, createTheme, deepMerge, defineDocs, extendTheme, fumadocs, hardline, withLangInUrl };
|
package/dist/index.mjs
CHANGED
|
@@ -11,6 +11,7 @@ import { ConcreteUIDefaults, concrete } from "./concrete/index.mjs";
|
|
|
11
11
|
import { HardlineUIDefaults, hardline } from "./hardline/index.mjs";
|
|
12
12
|
import { DocsClientHooks } from "./docs-client-hooks.mjs";
|
|
13
13
|
import { HoverLink } from "./hover-link.mjs";
|
|
14
|
+
import { Prompt } from "./prompt.mjs";
|
|
14
15
|
import { Agent } from "./mdx.mjs";
|
|
15
16
|
import { DocsLayout } from "fumadocs-ui/layouts/docs";
|
|
16
17
|
import { createTheme, deepMerge, defineDocs, extendTheme } from "@farming-labs/docs";
|
|
@@ -18,4 +19,4 @@ import { DocsBody, DocsPage } from "fumadocs-ui/layouts/docs/page";
|
|
|
18
19
|
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
|
|
19
20
|
import { CodeBlock, CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger, Pre } from "fumadocs-ui/components/codeblock";
|
|
20
21
|
|
|
21
|
-
export { Agent, CodeBlock, CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger, CommandGridUIDefaults, ConcreteUIDefaults, DocsBody, DocsClientHooks, DocsCommandSearch, DocsFeedback, DocsLayout, DocsPage, DocsPageClient, DefaultUIDefaults as FumadocsUIDefaults, HardlineUIDefaults, HoverLink, PageActions, Pre, RootProvider, Tab, Tabs, commandGrid, concrete, createDocsLayout, createDocsMetadata, createPageMetadata, createTheme, deepMerge, defineDocs, extendTheme, fumadocs, hardline, withLangInUrl };
|
|
22
|
+
export { Agent, CodeBlock, CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger, CommandGridUIDefaults, ConcreteUIDefaults, DocsBody, DocsClientHooks, DocsCommandSearch, DocsFeedback, DocsLayout, DocsPage, DocsPageClient, DefaultUIDefaults as FumadocsUIDefaults, HardlineUIDefaults, HoverLink, PageActions, Pre, Prompt, RootProvider, Tab, Tabs, commandGrid, concrete, createDocsLayout, createDocsMetadata, createPageMetadata, createTheme, deepMerge, defineDocs, extendTheme, fumadocs, hardline, withLangInUrl };
|
package/dist/mdx.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MDXImg } from "./mdx-img.mjs";
|
|
2
2
|
import { HoverLink } from "./hover-link.mjs";
|
|
3
|
+
import { Prompt, PromptIconValue, PromptOpenDocsProvider } from "./prompt.mjs";
|
|
3
4
|
import React from "react";
|
|
4
5
|
import { CodeBlockCopyData, DocsTheme } from "@farming-labs/docs";
|
|
5
6
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
@@ -21,6 +22,7 @@ declare const extendedMdxComponents: {
|
|
|
21
22
|
table: typeof Table;
|
|
22
23
|
Agent: typeof Agent;
|
|
23
24
|
HoverLink: typeof HoverLink;
|
|
25
|
+
Prompt: typeof Prompt;
|
|
24
26
|
Tab: typeof Tab;
|
|
25
27
|
Tabs: typeof Tabs;
|
|
26
28
|
CodeBlockTab: typeof fumadocs_ui_components_codeblock0.CodeBlockTab;
|
|
@@ -47,7 +49,11 @@ interface GetMDXComponentsOptions {
|
|
|
47
49
|
onCopyClick?: (data: CodeBlockCopyData) => void;
|
|
48
50
|
/** Theme config used to apply built-in MDX component defaults from `theme.ui.components`. */
|
|
49
51
|
theme?: DocsTheme;
|
|
52
|
+
/** Shared icon registry from `docs.config.ts[x]`. */
|
|
53
|
+
icons?: Record<string, PromptIconValue>;
|
|
54
|
+
/** Optional site-wide "Open in …" providers used by built-in components such as `Prompt`. */
|
|
55
|
+
openDocsProviders?: PromptOpenDocsProvider[];
|
|
50
56
|
}
|
|
51
57
|
declare function getMDXComponents<T extends Record<string, unknown> = Record<string, unknown>>(overrides?: T, options?: GetMDXComponentsOptions): typeof extendedMdxComponents & T;
|
|
52
58
|
//#endregion
|
|
53
|
-
export { Agent, GetMDXComponentsOptions, HoverLink, Tab, Tabs, defaultMdxComponents, extendedMdxComponents, getMDXComponents };
|
|
59
|
+
export { Agent, GetMDXComponentsOptions, HoverLink, Prompt, Tab, Tabs, defaultMdxComponents, extendedMdxComponents, getMDXComponents };
|
package/dist/mdx.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { MDXImg } from "./mdx-img.mjs";
|
|
2
2
|
import { createPreWithCopyCallback } from "./code-block-copy-wrapper.mjs";
|
|
3
3
|
import { HoverLink } from "./hover-link.mjs";
|
|
4
|
+
import { extractPromptText } from "./prompt-text.mjs";
|
|
5
|
+
import { Prompt } from "./prompt.mjs";
|
|
4
6
|
import React from "react";
|
|
5
7
|
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
|
|
6
8
|
import defaultMdxComponents from "fumadocs-ui/mdx";
|
|
@@ -36,17 +38,32 @@ const extendedMdxComponents = {
|
|
|
36
38
|
table: Table,
|
|
37
39
|
Agent,
|
|
38
40
|
HoverLink,
|
|
41
|
+
Prompt,
|
|
39
42
|
Tab,
|
|
40
43
|
Tabs
|
|
41
44
|
};
|
|
42
|
-
const mdxComponentDefaults = {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
const mdxComponentDefaults = {
|
|
46
|
+
HoverLink: {
|
|
47
|
+
linkLabel: "Open page",
|
|
48
|
+
showIndicator: false,
|
|
49
|
+
align: "center",
|
|
50
|
+
side: "bottom",
|
|
51
|
+
sideOffset: 12,
|
|
52
|
+
closeDelay: 90
|
|
53
|
+
},
|
|
54
|
+
Prompt: {
|
|
55
|
+
showTitle: true,
|
|
56
|
+
showDescription: true,
|
|
57
|
+
showPrompt: false,
|
|
58
|
+
actions: ["copy"],
|
|
59
|
+
copyLabel: "Copy prompt",
|
|
60
|
+
copiedLabel: "Copied",
|
|
61
|
+
openLabel: "Open in",
|
|
62
|
+
copyIcon: "copy",
|
|
63
|
+
copiedIcon: "check",
|
|
64
|
+
openIcon: "arrowUpRight"
|
|
65
|
+
}
|
|
66
|
+
};
|
|
50
67
|
function applyBuiltInComponentDefaults(options) {
|
|
51
68
|
const themeComponents = options?.theme?.ui?.components;
|
|
52
69
|
if (!themeComponents) return extendedMdxComponents;
|
|
@@ -57,9 +74,10 @@ function applyBuiltInComponentDefaults(options) {
|
|
|
57
74
|
const Component = components[name];
|
|
58
75
|
if (!Component) continue;
|
|
59
76
|
const builtInDefaults = mdxComponentDefaults[name] ?? {};
|
|
77
|
+
const configuredDefaults = value && typeof value === "object" ? value : {};
|
|
60
78
|
const componentDefaults = typeof value === "function" ? value(builtInDefaults) : {
|
|
61
79
|
...builtInDefaults,
|
|
62
|
-
...
|
|
80
|
+
...configuredDefaults
|
|
63
81
|
};
|
|
64
82
|
if (!componentDefaults || typeof componentDefaults !== "object") continue;
|
|
65
83
|
components[name] = function ThemedComponent(props) {
|
|
@@ -76,6 +94,19 @@ function getMDXComponents(overrides, options) {
|
|
|
76
94
|
...applyBuiltInComponentDefaults(options),
|
|
77
95
|
...overrides
|
|
78
96
|
};
|
|
97
|
+
if (base.Prompt) {
|
|
98
|
+
const DefaultPrompt = base.Prompt;
|
|
99
|
+
base.Prompt = function PromptWithDocsContext(props) {
|
|
100
|
+
const { children, ...rest } = props;
|
|
101
|
+
return React.createElement(DefaultPrompt, {
|
|
102
|
+
iconRegistry: options?.icons,
|
|
103
|
+
openDocsProviders: options?.openDocsProviders,
|
|
104
|
+
prompt: extractPromptText(children),
|
|
105
|
+
...rest,
|
|
106
|
+
children
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
}
|
|
79
110
|
if (options?.onCopyClick) {
|
|
80
111
|
const DefaultPre = base.pre;
|
|
81
112
|
if (DefaultPre) base.pre = createPreWithCopyCallback(DefaultPre, options.onCopyClick);
|
|
@@ -84,4 +115,4 @@ function getMDXComponents(overrides, options) {
|
|
|
84
115
|
}
|
|
85
116
|
|
|
86
117
|
//#endregion
|
|
87
|
-
export { Agent, HoverLink, Tab, Tabs, defaultMdxComponents, extendedMdxComponents, getMDXComponents };
|
|
118
|
+
export { Agent, HoverLink, Prompt, Tab, Tabs, defaultMdxComponents, extendedMdxComponents, getMDXComponents };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/prompt-text.ts
|
|
4
|
+
function extractPromptText(children) {
|
|
5
|
+
function inner(node) {
|
|
6
|
+
if (node == null || typeof node === "boolean") return "";
|
|
7
|
+
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
8
|
+
if (Array.isArray(node)) return node.map((child) => inner(child)).join("");
|
|
9
|
+
if (React.isValidElement(node)) {
|
|
10
|
+
const childText = inner(node.props.children);
|
|
11
|
+
if (node.type === "br") return "\n";
|
|
12
|
+
if (node.type === "li") return `- ${childText.trim()}\n`;
|
|
13
|
+
if (node.type === "p") return `${childText.trim()}\n\n`;
|
|
14
|
+
if (node.type === "ul" || node.type === "ol") return `${childText.trim()}\n`;
|
|
15
|
+
return childText;
|
|
16
|
+
}
|
|
17
|
+
return "";
|
|
18
|
+
}
|
|
19
|
+
return inner(children).replace(/\r\n/g, "\n").replace(/\n{3,}/g, "\n\n").replace(/[ \t]+\n/g, "\n").trim();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
export { extractPromptText };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
//#region src/prompt.d.ts
|
|
5
|
+
type PromptAction = "copy" | "open";
|
|
6
|
+
type PromptIconValue = React.ReactNode | string;
|
|
7
|
+
interface PromptOpenDocsProvider {
|
|
8
|
+
name: string;
|
|
9
|
+
icon?: PromptIconValue;
|
|
10
|
+
urlTemplate: string;
|
|
11
|
+
promptUrlTemplate?: string;
|
|
12
|
+
}
|
|
13
|
+
interface PromptProps {
|
|
14
|
+
title?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
prompt?: string;
|
|
17
|
+
icon?: string;
|
|
18
|
+
showTitle?: boolean;
|
|
19
|
+
showDescription?: boolean;
|
|
20
|
+
showPrompt?: boolean;
|
|
21
|
+
actions?: PromptAction[] | string[];
|
|
22
|
+
providers?: string[] | string;
|
|
23
|
+
copyLabel?: string;
|
|
24
|
+
copiedLabel?: string;
|
|
25
|
+
openLabel?: string;
|
|
26
|
+
copyIcon?: string | false;
|
|
27
|
+
copiedIcon?: string | false;
|
|
28
|
+
openIcon?: string | false;
|
|
29
|
+
iconRegistry?: Record<string, PromptIconValue>;
|
|
30
|
+
openDocsProviders?: PromptOpenDocsProvider[];
|
|
31
|
+
}
|
|
32
|
+
declare function Prompt({
|
|
33
|
+
title,
|
|
34
|
+
description,
|
|
35
|
+
prompt,
|
|
36
|
+
icon,
|
|
37
|
+
showTitle,
|
|
38
|
+
showDescription,
|
|
39
|
+
showPrompt,
|
|
40
|
+
actions,
|
|
41
|
+
providers,
|
|
42
|
+
copyLabel,
|
|
43
|
+
copiedLabel,
|
|
44
|
+
openLabel,
|
|
45
|
+
copyIcon,
|
|
46
|
+
copiedIcon,
|
|
47
|
+
openIcon,
|
|
48
|
+
iconRegistry,
|
|
49
|
+
openDocsProviders,
|
|
50
|
+
children
|
|
51
|
+
}: React.PropsWithChildren<PromptProps>): react_jsx_runtime0.JSX.Element;
|
|
52
|
+
//#endregion
|
|
53
|
+
export { Prompt, PromptIconValue, PromptOpenDocsProvider, PromptProps };
|
package/dist/prompt.mjs
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { extractPromptText } from "./prompt-text.mjs";
|
|
4
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
|
|
7
|
+
//#region src/prompt.tsx
|
|
8
|
+
const builtInIcons = {
|
|
9
|
+
copy: /* @__PURE__ */ jsxs("svg", {
|
|
10
|
+
width: "14",
|
|
11
|
+
height: "14",
|
|
12
|
+
viewBox: "0 0 24 24",
|
|
13
|
+
fill: "none",
|
|
14
|
+
stroke: "currentColor",
|
|
15
|
+
strokeWidth: "2",
|
|
16
|
+
strokeLinecap: "round",
|
|
17
|
+
strokeLinejoin: "round",
|
|
18
|
+
children: [/* @__PURE__ */ jsx("rect", {
|
|
19
|
+
x: "9",
|
|
20
|
+
y: "9",
|
|
21
|
+
width: "13",
|
|
22
|
+
height: "13",
|
|
23
|
+
rx: "2",
|
|
24
|
+
ry: "2"
|
|
25
|
+
}), /* @__PURE__ */ jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })]
|
|
26
|
+
}),
|
|
27
|
+
check: /* @__PURE__ */ jsx("svg", {
|
|
28
|
+
width: "14",
|
|
29
|
+
height: "14",
|
|
30
|
+
viewBox: "0 0 24 24",
|
|
31
|
+
fill: "none",
|
|
32
|
+
stroke: "currentColor",
|
|
33
|
+
strokeWidth: "2",
|
|
34
|
+
strokeLinecap: "round",
|
|
35
|
+
strokeLinejoin: "round",
|
|
36
|
+
children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
|
|
37
|
+
}),
|
|
38
|
+
arrowUpRight: /* @__PURE__ */ jsxs("svg", {
|
|
39
|
+
width: "14",
|
|
40
|
+
height: "14",
|
|
41
|
+
viewBox: "0 0 24 24",
|
|
42
|
+
fill: "none",
|
|
43
|
+
stroke: "currentColor",
|
|
44
|
+
strokeWidth: "2",
|
|
45
|
+
strokeLinecap: "round",
|
|
46
|
+
strokeLinejoin: "round",
|
|
47
|
+
children: [
|
|
48
|
+
/* @__PURE__ */ jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
|
|
49
|
+
/* @__PURE__ */ jsx("polyline", { points: "15 3 21 3 21 9" }),
|
|
50
|
+
/* @__PURE__ */ jsx("line", {
|
|
51
|
+
x1: "10",
|
|
52
|
+
y1: "14",
|
|
53
|
+
x2: "21",
|
|
54
|
+
y2: "3"
|
|
55
|
+
})
|
|
56
|
+
]
|
|
57
|
+
}),
|
|
58
|
+
chevronDown: /* @__PURE__ */ jsx("svg", {
|
|
59
|
+
width: "12",
|
|
60
|
+
height: "12",
|
|
61
|
+
viewBox: "0 0 24 24",
|
|
62
|
+
fill: "none",
|
|
63
|
+
stroke: "currentColor",
|
|
64
|
+
strokeWidth: "2",
|
|
65
|
+
strokeLinecap: "round",
|
|
66
|
+
strokeLinejoin: "round",
|
|
67
|
+
children: /* @__PURE__ */ jsx("polyline", { points: "6 9 12 15 18 9" })
|
|
68
|
+
})
|
|
69
|
+
};
|
|
70
|
+
const defaultPromptProviderTemplates = {
|
|
71
|
+
chatgpt: "https://chatgpt.com/?q={prompt}",
|
|
72
|
+
claude: "https://claude.ai/new?q={prompt}",
|
|
73
|
+
cursor: "https://cursor.com/link/prompt?text={prompt}",
|
|
74
|
+
gemini: "https://gemini.google.com/app?q={prompt}",
|
|
75
|
+
copilot: "https://github.com/copilot?prompt={prompt}"
|
|
76
|
+
};
|
|
77
|
+
function normalizeProviderName(name) {
|
|
78
|
+
return name.trim().toLowerCase();
|
|
79
|
+
}
|
|
80
|
+
function parseStringArray(value) {
|
|
81
|
+
if (Array.isArray(value)) {
|
|
82
|
+
const normalized = value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter(Boolean);
|
|
83
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
84
|
+
}
|
|
85
|
+
if (typeof value !== "string") return void 0;
|
|
86
|
+
const trimmed = value.trim();
|
|
87
|
+
if (!trimmed) return void 0;
|
|
88
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
89
|
+
const normalized = trimmed.slice(1, -1).split(",").map((entry) => entry.trim().replace(/^['"]|['"]$/g, "")).filter(Boolean);
|
|
90
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
91
|
+
}
|
|
92
|
+
const normalized = trimmed.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
93
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
94
|
+
}
|
|
95
|
+
function resolveProviderChoices(availableProviders, preferredNames) {
|
|
96
|
+
const configuredByName = new Map((availableProviders ?? []).map((provider) => [normalizeProviderName(provider.name), provider]));
|
|
97
|
+
const names = preferredNames && preferredNames.length > 0 ? preferredNames : (availableProviders ?? []).map((provider) => provider.name);
|
|
98
|
+
const seen = /* @__PURE__ */ new Set();
|
|
99
|
+
const resolved = [];
|
|
100
|
+
for (const rawName of names) {
|
|
101
|
+
const name = rawName.trim();
|
|
102
|
+
if (!name) continue;
|
|
103
|
+
const normalized = normalizeProviderName(name);
|
|
104
|
+
if (seen.has(normalized)) continue;
|
|
105
|
+
seen.add(normalized);
|
|
106
|
+
const configured = configuredByName.get(normalized);
|
|
107
|
+
const template = configured?.promptUrlTemplate ?? configured?.urlTemplate ?? defaultPromptProviderTemplates[normalized];
|
|
108
|
+
if (!template) continue;
|
|
109
|
+
resolved.push({
|
|
110
|
+
name: configured?.name ?? name,
|
|
111
|
+
icon: configured?.icon,
|
|
112
|
+
urlTemplate: template
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
return resolved;
|
|
116
|
+
}
|
|
117
|
+
function resolveActionIcon(name, iconRegistry) {
|
|
118
|
+
if (name === false) return null;
|
|
119
|
+
if (!name) return null;
|
|
120
|
+
const registryMatch = iconRegistry?.[name];
|
|
121
|
+
if (registryMatch) {
|
|
122
|
+
if (typeof registryMatch !== "string") return registryMatch;
|
|
123
|
+
}
|
|
124
|
+
if (name in builtInIcons) return builtInIcons[name];
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
async function fallbackCopyText(text) {
|
|
128
|
+
if (typeof document === "undefined") return false;
|
|
129
|
+
const textarea = document.createElement("textarea");
|
|
130
|
+
textarea.value = text;
|
|
131
|
+
textarea.setAttribute("readonly", "");
|
|
132
|
+
textarea.style.position = "fixed";
|
|
133
|
+
textarea.style.top = "0";
|
|
134
|
+
textarea.style.left = "0";
|
|
135
|
+
textarea.style.opacity = "0";
|
|
136
|
+
textarea.style.pointerEvents = "none";
|
|
137
|
+
document.body.appendChild(textarea);
|
|
138
|
+
textarea.focus();
|
|
139
|
+
textarea.select();
|
|
140
|
+
let copied = false;
|
|
141
|
+
try {
|
|
142
|
+
copied = document.execCommand("copy");
|
|
143
|
+
} catch {
|
|
144
|
+
copied = false;
|
|
145
|
+
} finally {
|
|
146
|
+
document.body.removeChild(textarea);
|
|
147
|
+
}
|
|
148
|
+
return copied;
|
|
149
|
+
}
|
|
150
|
+
function Prompt({ title, description, prompt, icon, showTitle = true, showDescription = true, showPrompt = false, actions, providers, copyLabel = "Copy prompt", copiedLabel = "Copied", openLabel = "Open in", copyIcon = "copy", copiedIcon = "check", openIcon = "arrowUpRight", iconRegistry, openDocsProviders, children }) {
|
|
151
|
+
const [copied, setCopied] = useState(false);
|
|
152
|
+
const [menuOpen, setMenuOpen] = useState(false);
|
|
153
|
+
const dropdownRef = useRef(null);
|
|
154
|
+
const promptText = useMemo(() => typeof prompt === "string" && prompt.trim() ? prompt.trim() : extractPromptText(children), [prompt, children]);
|
|
155
|
+
const promptIconValue = icon && iconRegistry?.[icon] ? iconRegistry[icon] : void 0;
|
|
156
|
+
const promptIcon = promptIconValue && typeof promptIconValue !== "string" ? promptIconValue : null;
|
|
157
|
+
const resolvedActions = useMemo(() => parseStringArray(actions) ?? ["copy"], [actions]);
|
|
158
|
+
const resolvedProviders = useMemo(() => resolveProviderChoices(openDocsProviders, parseStringArray(providers)), [openDocsProviders, providers]);
|
|
159
|
+
const handleCopy = useCallback(async () => {
|
|
160
|
+
if (!promptText) return;
|
|
161
|
+
try {
|
|
162
|
+
if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) await navigator.clipboard.writeText(promptText);
|
|
163
|
+
else if (!await fallbackCopyText(promptText)) return;
|
|
164
|
+
setCopied(true);
|
|
165
|
+
window.setTimeout(() => setCopied(false), 2e3);
|
|
166
|
+
} catch {
|
|
167
|
+
if (!await fallbackCopyText(promptText)) return;
|
|
168
|
+
setCopied(true);
|
|
169
|
+
window.setTimeout(() => setCopied(false), 2e3);
|
|
170
|
+
}
|
|
171
|
+
}, [promptText]);
|
|
172
|
+
const handleOpen = useCallback((provider) => {
|
|
173
|
+
if (!promptText) return;
|
|
174
|
+
const targetUrl = provider.urlTemplate.replace(/\{prompt\}/g, encodeURIComponent(promptText));
|
|
175
|
+
window.open(targetUrl, "_blank", "noopener,noreferrer");
|
|
176
|
+
setMenuOpen(false);
|
|
177
|
+
}, [promptText]);
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
if (!menuOpen) return;
|
|
180
|
+
function handleOutsideClick(event) {
|
|
181
|
+
if (!dropdownRef.current) return;
|
|
182
|
+
if (!dropdownRef.current.contains(event.target)) setMenuOpen(false);
|
|
183
|
+
}
|
|
184
|
+
document.addEventListener("mousedown", handleOutsideClick);
|
|
185
|
+
return () => document.removeEventListener("mousedown", handleOutsideClick);
|
|
186
|
+
}, [menuOpen]);
|
|
187
|
+
const showCopy = resolvedActions.includes("copy");
|
|
188
|
+
const showOpen = resolvedActions.includes("open") && resolvedProviders.length > 0;
|
|
189
|
+
const singleProvider = showOpen && resolvedProviders.length === 1 ? resolvedProviders[0] : null;
|
|
190
|
+
const visibleTitle = showTitle ? title : void 0;
|
|
191
|
+
const visibleDescription = showDescription ? description : void 0;
|
|
192
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
193
|
+
className: "fd-prompt",
|
|
194
|
+
"data-prompt-card": true,
|
|
195
|
+
children: [
|
|
196
|
+
(promptIcon || visibleTitle || visibleDescription) && /* @__PURE__ */ jsxs("div", {
|
|
197
|
+
className: "fd-prompt-header",
|
|
198
|
+
children: [promptIcon ? /* @__PURE__ */ jsx("span", {
|
|
199
|
+
className: "fd-prompt-icon",
|
|
200
|
+
children: promptIcon
|
|
201
|
+
}) : null, /* @__PURE__ */ jsxs("div", {
|
|
202
|
+
className: "fd-prompt-copy",
|
|
203
|
+
children: [visibleTitle && /* @__PURE__ */ jsx("p", {
|
|
204
|
+
className: "fd-prompt-title",
|
|
205
|
+
children: visibleTitle
|
|
206
|
+
}), visibleDescription && /* @__PURE__ */ jsx("p", {
|
|
207
|
+
className: "fd-prompt-description",
|
|
208
|
+
children: visibleDescription
|
|
209
|
+
})]
|
|
210
|
+
})]
|
|
211
|
+
}),
|
|
212
|
+
showPrompt && promptText && /* @__PURE__ */ jsx("div", {
|
|
213
|
+
className: "fd-prompt-body",
|
|
214
|
+
children: /* @__PURE__ */ jsx("pre", {
|
|
215
|
+
className: "fd-prompt-code",
|
|
216
|
+
children: promptText
|
|
217
|
+
})
|
|
218
|
+
}),
|
|
219
|
+
(showCopy || showOpen) && /* @__PURE__ */ jsxs("div", {
|
|
220
|
+
className: "fd-prompt-actions",
|
|
221
|
+
children: [
|
|
222
|
+
showCopy && /* @__PURE__ */ jsxs("button", {
|
|
223
|
+
type: "button",
|
|
224
|
+
className: "fd-prompt-action-btn",
|
|
225
|
+
"data-copied": copied,
|
|
226
|
+
onClick: handleCopy,
|
|
227
|
+
children: [copied ? resolveActionIcon(copiedIcon, iconRegistry) : resolveActionIcon(copyIcon, iconRegistry), /* @__PURE__ */ jsx("span", { children: copied ? copiedLabel : copyLabel })]
|
|
228
|
+
}),
|
|
229
|
+
singleProvider ? /* @__PURE__ */ jsxs("button", {
|
|
230
|
+
type: "button",
|
|
231
|
+
className: "fd-prompt-action-btn",
|
|
232
|
+
onClick: () => handleOpen(singleProvider),
|
|
233
|
+
children: [resolveActionIcon(openIcon, iconRegistry), /* @__PURE__ */ jsxs("span", { children: [
|
|
234
|
+
openLabel,
|
|
235
|
+
" ",
|
|
236
|
+
singleProvider.name
|
|
237
|
+
] })]
|
|
238
|
+
}) : null,
|
|
239
|
+
!singleProvider && showOpen ? /* @__PURE__ */ jsxs("div", {
|
|
240
|
+
ref: dropdownRef,
|
|
241
|
+
className: "fd-prompt-dropdown",
|
|
242
|
+
children: [/* @__PURE__ */ jsxs("button", {
|
|
243
|
+
type: "button",
|
|
244
|
+
className: "fd-prompt-action-btn",
|
|
245
|
+
"aria-expanded": menuOpen,
|
|
246
|
+
onClick: () => setMenuOpen((current) => !current),
|
|
247
|
+
children: [
|
|
248
|
+
resolveActionIcon(openIcon, iconRegistry),
|
|
249
|
+
/* @__PURE__ */ jsx("span", { children: openLabel }),
|
|
250
|
+
builtInIcons.chevronDown
|
|
251
|
+
]
|
|
252
|
+
}), menuOpen && /* @__PURE__ */ jsx("div", {
|
|
253
|
+
className: "fd-prompt-menu",
|
|
254
|
+
role: "menu",
|
|
255
|
+
children: resolvedProviders.map((provider) => /* @__PURE__ */ jsxs("button", {
|
|
256
|
+
type: "button",
|
|
257
|
+
role: "menuitem",
|
|
258
|
+
className: "fd-prompt-menu-item",
|
|
259
|
+
onClick: () => handleOpen(provider),
|
|
260
|
+
children: [provider.icon && typeof provider.icon !== "string" ? /* @__PURE__ */ jsx("span", {
|
|
261
|
+
className: "fd-prompt-menu-icon",
|
|
262
|
+
children: provider.icon
|
|
263
|
+
}) : null, /* @__PURE__ */ jsxs("span", {
|
|
264
|
+
className: "fd-prompt-menu-label",
|
|
265
|
+
children: [
|
|
266
|
+
openLabel,
|
|
267
|
+
" ",
|
|
268
|
+
provider.name
|
|
269
|
+
]
|
|
270
|
+
})]
|
|
271
|
+
}, provider.name))
|
|
272
|
+
})]
|
|
273
|
+
}) : null
|
|
274
|
+
]
|
|
275
|
+
})
|
|
276
|
+
]
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
//#endregion
|
|
281
|
+
export { Prompt };
|
package/dist/tanstack-layout.mjs
CHANGED
|
@@ -238,7 +238,7 @@ function TanstackDocsLayout({ config, tree, locale, description, readingTime, la
|
|
|
238
238
|
const llmsTxtEnabled = resolveBool(config.llmsTxt);
|
|
239
239
|
const feedbackConfig = resolveFeedbackConfig(config.feedback);
|
|
240
240
|
const staticExport = !!config.staticExport;
|
|
241
|
-
const openDocsProviders = (typeof pageActions
|
|
241
|
+
const openDocsProviders = (pageActions?.openDocs && typeof pageActions.openDocs === "object" && pageActions.openDocs.providers ? pageActions.openDocs.providers : void 0)?.map((provider) => ({
|
|
242
242
|
name: provider.name,
|
|
243
243
|
urlTemplate: provider.urlTemplate
|
|
244
244
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/theme",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.60",
|
|
4
4
|
"description": "Theme package for @farming-labs/docs — layout, provider, MDX components, and styles",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
"tsdown": "^0.20.3",
|
|
134
134
|
"typescript": "^5.9.3",
|
|
135
135
|
"vitest": "^3.2.4",
|
|
136
|
-
"@farming-labs/docs": "0.1.
|
|
136
|
+
"@farming-labs/docs": "0.1.60"
|
|
137
137
|
},
|
|
138
138
|
"peerDependencies": {
|
|
139
139
|
"@farming-labs/docs": ">=0.0.1",
|
package/styles/base.css
CHANGED
|
@@ -422,12 +422,12 @@ figure.shiki:has(figcaption) figcaption {
|
|
|
422
422
|
}
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
-
.fd-page-action-menu-item
|
|
425
|
+
.fd-page-action-menu-item,
|
|
426
|
+
.fd-prompt-menu-item {
|
|
426
427
|
display: flex;
|
|
427
428
|
align-items: center;
|
|
428
429
|
gap: 0.5rem;
|
|
429
430
|
width: 100%;
|
|
430
|
-
padding: 0.2rem 0.625rem;
|
|
431
431
|
font-size: 0.8125rem;
|
|
432
432
|
font-weight: 400;
|
|
433
433
|
color: var(--color-fd-popover-foreground);
|
|
@@ -441,9 +441,8 @@ figure.shiki:has(figcaption) figcaption {
|
|
|
441
441
|
color 0.1s;
|
|
442
442
|
}
|
|
443
443
|
|
|
444
|
-
.fd-page-action-menu-item
|
|
445
|
-
|
|
446
|
-
color: var(--color-fd-accent-foreground);
|
|
444
|
+
.fd-page-action-menu-item {
|
|
445
|
+
padding: 0.2rem 0.625rem;
|
|
447
446
|
}
|
|
448
447
|
|
|
449
448
|
.fd-page-action-menu-icon {
|
|
@@ -464,6 +463,177 @@ figure.shiki:has(figcaption) figcaption {
|
|
|
464
463
|
flex: 1;
|
|
465
464
|
}
|
|
466
465
|
|
|
466
|
+
/* ─── Prompt Cards ─────────────────────────────────────────────────── */
|
|
467
|
+
|
|
468
|
+
.fd-prompt {
|
|
469
|
+
display: flex;
|
|
470
|
+
flex-direction: column;
|
|
471
|
+
gap: 0.875rem;
|
|
472
|
+
margin: 1.25rem 0;
|
|
473
|
+
padding: 1rem;
|
|
474
|
+
border: 1px solid var(--color-fd-border);
|
|
475
|
+
border-radius: 0.75rem;
|
|
476
|
+
background: color-mix(in srgb, var(--color-fd-card) 78%, transparent);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
.fd-prompt-header {
|
|
480
|
+
display: flex;
|
|
481
|
+
align-items: flex-start;
|
|
482
|
+
gap: 0.75rem;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.fd-prompt-icon,
|
|
486
|
+
.fd-prompt-action-icon,
|
|
487
|
+
.fd-prompt-menu-icon {
|
|
488
|
+
display: inline-flex;
|
|
489
|
+
align-items: center;
|
|
490
|
+
justify-content: center;
|
|
491
|
+
flex-shrink: 0;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
.fd-prompt-icon {
|
|
495
|
+
width: 1.75rem;
|
|
496
|
+
height: 1.75rem;
|
|
497
|
+
border-radius: 0.5rem;
|
|
498
|
+
border: 1px solid color-mix(in srgb, var(--color-fd-border) 80%, transparent);
|
|
499
|
+
background: color-mix(in srgb, var(--color-fd-background) 55%, transparent);
|
|
500
|
+
color: var(--color-fd-foreground);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
.fd-prompt-icon svg,
|
|
504
|
+
.fd-prompt-action-icon svg,
|
|
505
|
+
.fd-prompt-menu-icon svg {
|
|
506
|
+
width: 1rem;
|
|
507
|
+
height: 1rem;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
.fd-prompt-copy {
|
|
511
|
+
min-width: 0;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
.fd-prompt-title {
|
|
515
|
+
margin: 0;
|
|
516
|
+
color: var(--color-fd-foreground);
|
|
517
|
+
font-size: 0.9375rem;
|
|
518
|
+
font-weight: 600;
|
|
519
|
+
line-height: 1.35;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
.fd-prompt-description {
|
|
523
|
+
margin: 0.25rem 0 0;
|
|
524
|
+
color: var(--color-fd-muted-foreground);
|
|
525
|
+
font-size: 0.875rem;
|
|
526
|
+
line-height: 1.55;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.fd-prompt-body {
|
|
530
|
+
margin: 0;
|
|
531
|
+
padding: 0.875rem 1rem;
|
|
532
|
+
border-radius: 0.625rem;
|
|
533
|
+
border: 1px solid color-mix(in srgb, var(--color-fd-border) 82%, transparent);
|
|
534
|
+
background: color-mix(in srgb, var(--color-fd-background) 45%, transparent);
|
|
535
|
+
overflow-x: auto;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
.fd-prompt-body > pre.fd-prompt-code {
|
|
539
|
+
margin: 0;
|
|
540
|
+
padding: 0 !important;
|
|
541
|
+
border: 0 !important;
|
|
542
|
+
border-radius: 0 !important;
|
|
543
|
+
background: transparent !important;
|
|
544
|
+
box-shadow: none !important;
|
|
545
|
+
color: var(--color-fd-foreground);
|
|
546
|
+
font-size: 0.875rem;
|
|
547
|
+
line-height: 1.65;
|
|
548
|
+
white-space: pre-wrap;
|
|
549
|
+
word-break: break-word;
|
|
550
|
+
font-family: var(
|
|
551
|
+
--fd-font-mono,
|
|
552
|
+
ui-monospace,
|
|
553
|
+
"SF Mono",
|
|
554
|
+
SFMono-Regular,
|
|
555
|
+
Menlo,
|
|
556
|
+
Consolas,
|
|
557
|
+
monospace
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.fd-prompt-actions {
|
|
562
|
+
display: flex;
|
|
563
|
+
flex-wrap: wrap;
|
|
564
|
+
gap: 0.5rem;
|
|
565
|
+
align-items: center;
|
|
566
|
+
justify-content: flex-end;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
.fd-prompt-action-btn {
|
|
570
|
+
display: inline-flex;
|
|
571
|
+
align-items: center;
|
|
572
|
+
gap: 0.4375rem;
|
|
573
|
+
min-height: 2rem;
|
|
574
|
+
padding: 0.375rem 0.75rem;
|
|
575
|
+
border: 1px solid var(--color-fd-border);
|
|
576
|
+
border-radius: 0.375rem;
|
|
577
|
+
background: var(--color-fd-secondary);
|
|
578
|
+
color: var(--color-fd-muted-foreground);
|
|
579
|
+
font-size: 0.8125rem;
|
|
580
|
+
font-weight: 500;
|
|
581
|
+
line-height: 1;
|
|
582
|
+
cursor: pointer;
|
|
583
|
+
transition:
|
|
584
|
+
color 0.15s,
|
|
585
|
+
background 0.15s,
|
|
586
|
+
border-color 0.15s;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.fd-prompt-action-btn:hover {
|
|
590
|
+
color: var(--color-fd-accent-foreground);
|
|
591
|
+
background: var(--color-fd-accent);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
.fd-prompt-action-btn[data-copied="true"] {
|
|
595
|
+
color: var(--color-fd-foreground);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
.fd-prompt-action-icon-copied[hidden] {
|
|
599
|
+
display: none;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
.fd-prompt-dropdown {
|
|
603
|
+
position: relative;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
.fd-prompt-menu {
|
|
607
|
+
position: absolute;
|
|
608
|
+
top: calc(100% + 0.375rem);
|
|
609
|
+
right: 0;
|
|
610
|
+
z-index: 50;
|
|
611
|
+
min-width: 220px;
|
|
612
|
+
padding: 0.375rem;
|
|
613
|
+
background: var(--color-fd-popover);
|
|
614
|
+
border: 1px solid var(--color-fd-border);
|
|
615
|
+
border-radius: 0.5rem;
|
|
616
|
+
box-shadow: 0 4px 24px hsl(0 0% 0% / 0.15);
|
|
617
|
+
display: flex;
|
|
618
|
+
flex-direction: column;
|
|
619
|
+
gap: 0.125rem;
|
|
620
|
+
animation: fd-page-actions-fade-in 0.12s ease-out;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
.fd-prompt-menu-item {
|
|
624
|
+
padding: 0.25rem 0.625rem;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
.fd-page-action-menu-item:hover,
|
|
628
|
+
.fd-prompt-menu-item:hover {
|
|
629
|
+
background: var(--color-fd-accent);
|
|
630
|
+
color: var(--color-fd-accent-foreground);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
.fd-prompt-menu-label {
|
|
634
|
+
flex: 1;
|
|
635
|
+
}
|
|
636
|
+
|
|
467
637
|
/* ─── Docs Feedback ────────────────────────────────────────────────── */
|
|
468
638
|
|
|
469
639
|
.fd-feedback {
|
package/styles/pixel-border.css
CHANGED
|
@@ -529,6 +529,68 @@ hr {
|
|
|
529
529
|
font-family: var(--fd-font-mono, var(--font-geist-mono, ui-monospace, monospace)) !important;
|
|
530
530
|
}
|
|
531
531
|
|
|
532
|
+
/* ─── Prompt (pixel-border overrides) ────────────────────────────── */
|
|
533
|
+
|
|
534
|
+
.fd-prompt {
|
|
535
|
+
border-radius: 0 !important;
|
|
536
|
+
border: 1px solid var(--color-fd-border, #262626) !important;
|
|
537
|
+
background: var(--color-fd-card, var(--color-fd-background)) !important;
|
|
538
|
+
box-shadow: 4px 4px 0 0 var(--color-fd-border, #262626) !important;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
.fd-prompt-body {
|
|
542
|
+
border-radius: 0 !important;
|
|
543
|
+
border-top: 1px solid var(--color-fd-border, #262626) !important;
|
|
544
|
+
background: var(--color-fd-background, #0c0c0c) !important;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
.fd-prompt-action-btn {
|
|
548
|
+
border-radius: 0 !important;
|
|
549
|
+
font-size: 0.75rem !important;
|
|
550
|
+
letter-spacing: 0.03em !important;
|
|
551
|
+
text-transform: uppercase !important;
|
|
552
|
+
box-shadow: 2px 2px 0 0 var(--color-fd-border, #262626) !important;
|
|
553
|
+
font-family: var(--fd-font-mono, var(--font-geist-mono, ui-monospace, monospace)) !important;
|
|
554
|
+
background: var(--color-fd-background, #0c0c0c) !important;
|
|
555
|
+
color: var(--color-fd-foreground, inherit) !important;
|
|
556
|
+
border: 1px solid var(--color-fd-border, #262626) !important;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.fd-prompt-action-btn:hover {
|
|
560
|
+
background: var(--color-fd-muted, var(--color-fd-accent)) !important;
|
|
561
|
+
color: var(--color-fd-foreground, inherit) !important;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
.fd-prompt-menu {
|
|
565
|
+
border-radius: 0 !important;
|
|
566
|
+
box-shadow:
|
|
567
|
+
4px 4px 0 0 var(--color-fd-border, #262626),
|
|
568
|
+
0 4px 24px hsl(0 0% 0% / 0.5) !important;
|
|
569
|
+
background: var(--color-fd-popover, var(--color-fd-background)) !important;
|
|
570
|
+
border: 2px solid var(--color-fd-border, #262626) !important;
|
|
571
|
+
padding: 0.375rem !important;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
.fd-prompt-menu-item {
|
|
575
|
+
border-radius: 0 !important;
|
|
576
|
+
font-size: 0.8rem !important;
|
|
577
|
+
letter-spacing: 0.03em !important;
|
|
578
|
+
text-transform: uppercase !important;
|
|
579
|
+
color: var(--color-fd-popover-foreground, var(--color-fd-foreground)) !important;
|
|
580
|
+
font-family: var(--fd-font-mono, var(--font-geist-mono, ui-monospace, monospace)) !important;
|
|
581
|
+
background: transparent !important;
|
|
582
|
+
border-top: 1px solid var(--color-fd-border, #262626) !important;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
.fd-prompt-menu-item:first-child {
|
|
586
|
+
border-top: none !important;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.fd-prompt-menu-item:hover {
|
|
590
|
+
background: var(--color-fd-muted, var(--color-fd-accent)) !important;
|
|
591
|
+
color: var(--color-fd-foreground, inherit) !important;
|
|
592
|
+
}
|
|
593
|
+
|
|
532
594
|
/* model selector */
|
|
533
595
|
.fd-ai-model-select-row {
|
|
534
596
|
display: flex;
|