@farming-labs/theme 0.0.62 → 0.0.64

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.
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
 
3
3
  import { useCallback, useEffect, useRef, useState } from "react";
4
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
4
  import { createPortal } from "react-dom";
5
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
6
  import { highlight } from "sugar-high";
7
7
 
8
8
  //#region src/ai-search-dialog.tsx
@@ -3,8 +3,8 @@
3
3
  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
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
6
  import { createPortal } from "react-dom";
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
8
 
9
9
  //#region src/docs-command-search.tsx
10
10
  function cn(...classes) {
@@ -6,8 +6,9 @@ import { DocsFeedback } from "./docs-feedback.mjs";
6
6
  import { resolveClientLocale, withLangInUrl } from "./i18n.mjs";
7
7
  import { Children, cloneElement, isValidElement, useEffect, useState } from "react";
8
8
  import { DocsBody, DocsPage, EditOnGitHub } from "fumadocs-ui/layouts/docs/page";
9
+ import { createPortal } from "react-dom";
9
10
  import { usePathname, useRouter } from "fumadocs-core/framework";
10
- import { jsx, jsxs } from "react/jsx-runtime";
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
12
 
12
13
  //#region src/docs-page-client.tsx
13
14
  /**
@@ -89,10 +90,16 @@ function localizeInternalLinks(root, locale) {
89
90
  }
90
91
  }
91
92
  function injectTitleDecorations(node, { description, belowTitle }) {
92
- if (!description && !belowTitle) return node;
93
+ if (!description && !belowTitle) return {
94
+ node,
95
+ inserted: false
96
+ };
93
97
  let inserted = false;
94
98
  const extras = [description, belowTitle].filter(Boolean);
95
- if (extras.length === 0) return node;
99
+ if (extras.length === 0) return {
100
+ node,
101
+ inserted: false
102
+ };
96
103
  function visit(current) {
97
104
  if (current == null || typeof current === "boolean") return current;
98
105
  if (inserted) return current;
@@ -114,15 +121,26 @@ function injectTitleDecorations(node, { description, belowTitle }) {
114
121
  if (!inserted) return current;
115
122
  return cloneElement(current, void 0, nextChildren);
116
123
  }
117
- if (Array.isArray(node)) return node.flatMap((child) => {
118
- const next = visit(child);
119
- return Array.isArray(next) ? next : [next];
120
- });
121
- return visit(node);
124
+ if (Array.isArray(node)) return {
125
+ node: node.flatMap((child) => {
126
+ const next = visit(child);
127
+ return Array.isArray(next) ? next : [next];
128
+ }),
129
+ inserted
130
+ };
131
+ return {
132
+ node: visit(node),
133
+ inserted
134
+ };
135
+ }
136
+ function TitleDecorations({ description, belowTitle }) {
137
+ if (!description && !belowTitle) return null;
138
+ return /* @__PURE__ */ jsxs(Fragment, { children: [description, belowTitle] });
122
139
  }
123
140
  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, feedbackEnabled = false, feedbackQuestion, feedbackPlaceholder, feedbackPositiveLabel, feedbackNegativeLabel, feedbackSubmitLabel, feedbackOnFeedback, children }) {
124
141
  const fdTocStyle = tocStyle === "directional" ? "clerk" : void 0;
125
142
  const [toc, setToc] = useState([]);
143
+ const [titlePortalHost, setTitlePortalHost] = useState(null);
126
144
  const pathname = usePathname();
127
145
  const activeLocale = resolveClientLocale(useWindowSearchParams(), locale);
128
146
  const llmsLangParam = activeLocale ? `&lang=${encodeURIComponent(activeLocale)}` : "";
@@ -163,32 +181,59 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
163
181
  const showLastUpdatedBelowTitle = !!lastModified && lastUpdatedPosition === "below-title";
164
182
  const showLastUpdatedInFooter = !!lastModified && lastUpdatedPosition === "footer";
165
183
  const showFooter = !!githubFileUrl || showLastUpdatedInFooter || llmsTxtEnabled;
166
- const decoratedChildren = injectTitleDecorations(children, {
167
- description: pageDescription ? /* @__PURE__ */ jsx("p", {
168
- className: "fd-page-description",
169
- children: pageDescription
170
- }) : void 0,
171
- belowTitle: showLastUpdatedBelowTitle || showActionsBelowTitle ? /* @__PURE__ */ jsxs("div", {
172
- className: "fd-below-title-block not-prose",
173
- children: [
174
- showLastUpdatedBelowTitle && /* @__PURE__ */ jsxs("p", {
175
- className: "fd-last-updated-inline",
176
- children: ["Last updated ", lastModified]
177
- }),
178
- /* @__PURE__ */ jsx("hr", { className: "fd-title-separator" }),
179
- showActionsBelowTitle && /* @__PURE__ */ jsx("div", {
180
- className: "fd-actions-portal",
181
- "data-actions-alignment": pageActionsAlignment,
182
- children: /* @__PURE__ */ jsx(PageActions, {
183
- copyMarkdown,
184
- openDocs,
185
- providers: openDocsProviders,
186
- githubFileUrl
187
- })
184
+ const titleDescription = pageDescription ? /* @__PURE__ */ jsx("p", {
185
+ className: "fd-page-description",
186
+ children: pageDescription
187
+ }) : void 0;
188
+ const belowTitleBlock = showLastUpdatedBelowTitle || showActionsBelowTitle ? /* @__PURE__ */ jsxs("div", {
189
+ className: "fd-below-title-block not-prose",
190
+ children: [
191
+ showLastUpdatedBelowTitle && /* @__PURE__ */ jsxs("p", {
192
+ className: "fd-last-updated-inline",
193
+ children: ["Last updated ", lastModified]
194
+ }),
195
+ /* @__PURE__ */ jsx("hr", { className: "fd-title-separator" }),
196
+ showActionsBelowTitle && /* @__PURE__ */ jsx("div", {
197
+ className: "fd-actions-portal",
198
+ "data-actions-alignment": pageActionsAlignment,
199
+ children: /* @__PURE__ */ jsx(PageActions, {
200
+ copyMarkdown,
201
+ openDocs,
202
+ providers: openDocsProviders,
203
+ alignment: pageActionsAlignment,
204
+ githubFileUrl
188
205
  })
189
- ]
190
- }) : void 0
206
+ })
207
+ ]
208
+ }) : void 0;
209
+ const { node: decoratedChildren, inserted: titleDecorationsInserted } = injectTitleDecorations(children, {
210
+ description: titleDescription,
211
+ belowTitle: belowTitleBlock
191
212
  });
213
+ const needsTitleDecorationsPortal = !titleDecorationsInserted && (!!titleDescription || !!belowTitleBlock);
214
+ useEffect(() => {
215
+ if (!needsTitleDecorationsPortal) {
216
+ setTitlePortalHost(null);
217
+ return;
218
+ }
219
+ const title = document.getElementById("nd-page")?.querySelector("h1");
220
+ if (!title) {
221
+ setTitlePortalHost(null);
222
+ return;
223
+ }
224
+ const host = document.createElement("div");
225
+ host.className = "fd-title-decorations-host";
226
+ title.insertAdjacentElement("afterend", host);
227
+ setTitlePortalHost(host);
228
+ return () => {
229
+ host.remove();
230
+ setTitlePortalHost(null);
231
+ };
232
+ }, [needsTitleDecorationsPortal, pathname]);
233
+ const titleDecorationsPortal = needsTitleDecorationsPortal && titlePortalHost ? createPortal(/* @__PURE__ */ jsx(TitleDecorations, {
234
+ description: titleDescription,
235
+ belowTitle: belowTitleBlock
236
+ }), titlePortalHost) : null;
192
237
  return /* @__PURE__ */ jsxs(DocsPage, {
193
238
  toc,
194
239
  tableOfContent: {
@@ -208,11 +253,16 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
208
253
  }),
209
254
  showActionsAboveTitle && /* @__PURE__ */ jsx("div", {
210
255
  className: "fd-below-title-block not-prose",
211
- children: /* @__PURE__ */ jsx(PageActions, {
212
- copyMarkdown,
213
- openDocs,
214
- providers: openDocsProviders,
215
- githubFileUrl
256
+ children: /* @__PURE__ */ jsx("div", {
257
+ className: "fd-actions-portal",
258
+ "data-actions-alignment": pageActionsAlignment,
259
+ children: /* @__PURE__ */ jsx(PageActions, {
260
+ copyMarkdown,
261
+ openDocs,
262
+ providers: openDocsProviders,
263
+ alignment: pageActionsAlignment,
264
+ githubFileUrl
265
+ })
216
266
  })
217
267
  }),
218
268
  /* @__PURE__ */ jsxs(DocsBody, {
@@ -225,6 +275,7 @@ function DocsPageClient({ tocEnabled, tocStyle = "default", breadcrumbEnabled =
225
275
  style: { flex: 1 },
226
276
  children: decoratedChildren
227
277
  }),
278
+ titleDecorationsPortal,
228
279
  feedbackEnabled && /* @__PURE__ */ jsx(DocsFeedback, {
229
280
  pathname: normalizedPath,
230
281
  entry,
@@ -11,6 +11,7 @@ interface PageActionsProps {
11
11
  copyMarkdown?: boolean;
12
12
  openDocs?: boolean;
13
13
  providers?: SerializedProvider[];
14
+ alignment?: "left" | "right";
14
15
  /** GitHub file URL (edit view) for the current page. Used when urlTemplate contains {githubUrl}. */
15
16
  githubFileUrl?: string | null;
16
17
  }
@@ -18,6 +19,7 @@ declare function PageActions({
18
19
  copyMarkdown,
19
20
  openDocs,
20
21
  providers,
22
+ alignment,
21
23
  githubFileUrl
22
24
  }: PageActionsProps): react_jsx_runtime0.JSX.Element | null;
23
25
  //#endregion
@@ -72,7 +72,7 @@ const DEFAULT_PROVIDERS = [{
72
72
  name: "Claude",
73
73
  urlTemplate: "https://claude.ai/new?q=Read+{mdxUrl},+I+want+to+ask+questions+about+it."
74
74
  }];
75
- function PageActions({ copyMarkdown, openDocs, providers, githubFileUrl }) {
75
+ function PageActions({ copyMarkdown, openDocs, providers, alignment = "left", githubFileUrl }) {
76
76
  const [copied, setCopied] = useState(false);
77
77
  const [dropdownOpen, setDropdownOpen] = useState(false);
78
78
  const dropdownRef = useRef(null);
@@ -115,6 +115,7 @@ function PageActions({ copyMarkdown, openDocs, providers, githubFileUrl }) {
115
115
  return /* @__PURE__ */ jsxs("div", {
116
116
  className: "fd-page-actions",
117
117
  "data-page-actions": true,
118
+ "data-actions-alignment": alignment,
118
119
  children: [copyMarkdown && /* @__PURE__ */ jsxs("button", {
119
120
  type: "button",
120
121
  onClick: handleCopyMarkdown,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/theme",
3
- "version": "0.0.62",
3
+ "version": "0.0.64",
4
4
  "description": "Theme package for @farming-labs/docs — layout, provider, MDX components, and styles",
5
5
  "keywords": [
6
6
  "docs",
@@ -115,7 +115,7 @@
115
115
  "tsdown": "^0.20.3",
116
116
  "typescript": "^5.9.3",
117
117
  "vitest": "^3.2.4",
118
- "@farming-labs/docs": "0.0.62"
118
+ "@farming-labs/docs": "0.0.64"
119
119
  },
120
120
  "peerDependencies": {
121
121
  "@farming-labs/docs": ">=0.0.1",
package/styles/base.css CHANGED
@@ -252,6 +252,7 @@ figure.shiki:has(figcaption) figcaption {
252
252
 
253
253
  /* ─── Page Actions (Copy Markdown / Open in …) ────────────────────── */
254
254
 
255
+ .fd-page-actions,
255
256
  [data-page-actions] {
256
257
  display: flex;
257
258
  flex-direction: row;
@@ -259,12 +260,17 @@ figure.shiki:has(figcaption) figcaption {
259
260
  gap: 0.5rem;
260
261
  margin-bottom: 0.75rem;
261
262
  margin-top: 0.25rem;
263
+ width: 100%;
262
264
  }
263
265
 
266
+ [data-page-actions][data-actions-alignment="right"],
267
+ .fd-page-actions[data-actions-alignment="right"],
264
268
  [data-actions-alignment="right"] > [data-page-actions] {
265
269
  justify-content: flex-end;
266
270
  }
267
271
 
272
+ [data-page-actions][data-actions-alignment="left"],
273
+ .fd-page-actions[data-actions-alignment="left"],
268
274
  [data-actions-alignment="left"] > [data-page-actions] {
269
275
  justify-content: flex-start;
270
276
  }