@farming-labs/next 0.2.103 → 0.2.104

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/api.d.mts DELETED
@@ -1,30 +0,0 @@
1
- import { createDocsAPI as createDocsAPI$1, createDocsMCPAPI as createDocsMCPAPI$1 } from "@farming-labs/theme/api";
2
- import { DocsCloudRouteHandlerOptions, DocsCloudRouteHandlerOptions as DocsCloudRouteHandlerOptions$1, DocsCloudRouteHandlers, DocsCloudServer, DocsCloudServer as DocsCloudServer$1, createDocsCloudRouteHandler } from "@farming-labs/docs/cloud/server";
3
-
4
- //#region src/api.d.ts
5
- type DocsAPIOptions = NonNullable<Parameters<typeof createDocsAPI$1>[0]>;
6
- type DocsMCPAPIOptions = NonNullable<Parameters<typeof createDocsMCPAPI$1>[0]>;
7
- interface DocsAPICloudOptions extends DocsCloudRouteHandlerOptions$1 {
8
- docsCloud?: DocsCloudServer$1;
9
- }
10
- type DocsAPICloudIntegration = DocsCloudServer$1 | DocsAPICloudOptions;
11
- /**
12
- * Resolve the app project root for a Next route module.
13
- *
14
- * This handles source routes (`app/...` or `src/app/...`) and built production
15
- * output (`.next/server/app/...` or custom-dist-dir `/server/app/...`).
16
- */
17
- declare function resolveNextProjectRoot(metaUrl: string): string;
18
- declare function createDocsAPI(options?: DocsAPIOptions, cloudIntegration?: DocsAPICloudIntegration): {
19
- HEAD(request: Request): Promise<Response>;
20
- GET(request: Request): Promise<Response>;
21
- POST(request: Request): Promise<Response>;
22
- };
23
- declare function createDocsMCPAPI(options?: DocsMCPAPIOptions): {
24
- GET(request: Request): Promise<Response>;
25
- POST(request: Request): Promise<Response>;
26
- DELETE(request: Request): Promise<Response>;
27
- OPTIONS(request: Request): Promise<Response>;
28
- };
29
- //#endregion
30
- export { DocsAPICloudIntegration, DocsAPICloudOptions, type DocsCloudRouteHandlerOptions, type DocsCloudRouteHandlers, type DocsCloudServer, createDocsAPI, createDocsCloudRouteHandler, createDocsMCPAPI, resolveNextProjectRoot };
package/dist/api.mjs DELETED
@@ -1,154 +0,0 @@
1
- import path from "node:path";
2
- import { fileURLToPath, pathToFileURL } from "node:url";
3
- import { createDocsAPI as createDocsAPI$1, createDocsMCPAPI as createDocsMCPAPI$1 } from "@farming-labs/theme/api";
4
- import { bundledAgentSkills } from "@farming-labs/docs/agent-skills-bundle";
5
- import { createDocsCloudRouteHandler } from "@farming-labs/docs/cloud/server";
6
-
7
- //#region src/api.ts
8
- /**
9
- * Resolve the app project root for a Next route module.
10
- *
11
- * This handles source routes (`app/...` or `src/app/...`) and built production
12
- * output (`.next/server/app/...` or custom-dist-dir `/server/app/...`).
13
- */
14
- function resolveNextProjectRoot(metaUrl) {
15
- const filePath = fileURLToPath(metaUrl);
16
- let current = path.dirname(filePath);
17
- while (true) {
18
- const parent = path.dirname(current);
19
- if (path.basename(current) === "app") {
20
- if (path.basename(parent) === "src") return path.dirname(parent);
21
- if (path.basename(parent) === "server") {
22
- const serverParent = path.dirname(parent);
23
- if (path.basename(serverParent) === "dev") return path.dirname(path.dirname(serverParent));
24
- return path.dirname(serverParent);
25
- }
26
- return parent;
27
- }
28
- if (parent === current) return process.cwd();
29
- current = parent;
30
- }
31
- }
32
- function isNextRouteFile(filePath) {
33
- const normalized = filePath.replaceAll("\\", "/");
34
- return /\/(?:src\/)?app\/api\/.+\/route\.[cm]?[jt]sx?$/.test(normalized);
35
- }
36
- function inferNextProjectRootFromCaller() {
37
- const previousPrepareStackTrace = Error.prepareStackTrace;
38
- try {
39
- Error.prepareStackTrace = (_error, stack) => stack;
40
- const error = /* @__PURE__ */ new Error();
41
- Error.captureStackTrace?.(error, inferNextProjectRootFromCaller);
42
- const stack = error.stack;
43
- for (const frame of stack ?? []) {
44
- const fileName = frame.getFileName?.();
45
- if (!fileName || !isNextRouteFile(fileName)) continue;
46
- return resolveNextProjectRoot(pathToFileURL(fileName).href);
47
- }
48
- } catch {} finally {
49
- Error.prepareStackTrace = previousPrepareStackTrace;
50
- }
51
- }
52
- function isRecord(value) {
53
- return typeof value === "object" && value !== null && !Array.isArray(value);
54
- }
55
- function normalizeAction(value) {
56
- return value?.trim().toLowerCase().replace(/_/g, "-") || void 0;
57
- }
58
- function isDocsCloudServer(value) {
59
- return isRecord(value) && typeof value.handleRequest === "function";
60
- }
61
- function resolveDocsCloudIntegration(integration) {
62
- if (!integration) return void 0;
63
- if (isDocsCloudServer(integration)) return {
64
- docsCloud: integration,
65
- routeOptions: {}
66
- };
67
- if (!integration.docsCloud) return void 0;
68
- return {
69
- docsCloud: integration.docsCloud,
70
- routeOptions: {
71
- locale: integration.locale,
72
- publicBaseUrl: integration.publicBaseUrl
73
- }
74
- };
75
- }
76
- function isDocsCloudGetRequest(request) {
77
- const url = new URL(request.url);
78
- const cloud = normalizeAction(url.searchParams.get("cloud"));
79
- const action = normalizeAction(url.searchParams.get("action"));
80
- const format = normalizeAction(url.searchParams.get("format"));
81
- return cloud === "config" || cloud === "public-config" || action === "cloud-config" || action === "docs-cloud-config" || format === "cloud-config" || format === "docs-cloud-config";
82
- }
83
- function isDocsCloudAction(action) {
84
- return Boolean(action && [
85
- "analytics",
86
- "track",
87
- "track-event",
88
- "event",
89
- "ask-ai",
90
- "ai",
91
- "chat",
92
- "docs-cloud"
93
- ].includes(action));
94
- }
95
- async function readJson(request) {
96
- try {
97
- return await request.clone().json();
98
- } catch {
99
- return;
100
- }
101
- }
102
- async function isDocsCloudPostRequest(request) {
103
- const url = new URL(request.url);
104
- const cloud = normalizeAction(url.searchParams.get("cloud"));
105
- const action = normalizeAction(url.searchParams.get("action"));
106
- if (isDocsCloudAction(cloud) || isDocsCloudAction(action)) return true;
107
- const body = await readJson(request);
108
- if (!isRecord(body)) return false;
109
- if (isDocsCloudAction(normalizeAction(typeof body.action === "string" ? body.action : void 0))) return true;
110
- if (typeof body.type === "string") return true;
111
- if (isRecord(body.event) && typeof body.event.type === "string") return true;
112
- if (isRecord(body.payload) && typeof body.payload.type === "string") return true;
113
- return false;
114
- }
115
- function createDocsAPI(options = {}, cloudIntegration) {
116
- const rootDir = options.rootDir ?? inferNextProjectRootFromCaller();
117
- const handlers = createDocsAPI$1({
118
- ...options,
119
- ...rootDir ? { rootDir } : {},
120
- _preloadedAgentSkills: options._preloadedAgentSkills ?? bundledAgentSkills
121
- });
122
- const integration = resolveDocsCloudIntegration(cloudIntegration);
123
- if (!integration) return handlers;
124
- return {
125
- GET(request) {
126
- if (isDocsCloudGetRequest(request)) return integration.docsCloud.handleRequest(request, integration.routeOptions);
127
- return handlers.GET(request);
128
- },
129
- async HEAD(request) {
130
- if (!isDocsCloudGetRequest(request)) return handlers.HEAD(request);
131
- const response = await integration.docsCloud.handleRequest(request, integration.routeOptions);
132
- return new Response(null, {
133
- status: response.status,
134
- statusText: response.statusText,
135
- headers: response.headers
136
- });
137
- },
138
- async POST(request) {
139
- if (await isDocsCloudPostRequest(request)) return integration.docsCloud.handleRequest(request, integration.routeOptions);
140
- return handlers.POST(request);
141
- }
142
- };
143
- }
144
- function createDocsMCPAPI(options = {}) {
145
- const rootDir = options.rootDir ?? inferNextProjectRootFromCaller();
146
- return createDocsMCPAPI$1({
147
- ...options,
148
- ...rootDir ? { rootDir } : {},
149
- _preloadedAgentSkills: options._preloadedAgentSkills ?? bundledAgentSkills
150
- });
151
- }
152
-
153
- //#endregion
154
- export { createDocsAPI, createDocsCloudRouteHandler, createDocsMCPAPI, resolveNextProjectRoot };
@@ -1,46 +0,0 @@
1
- import { ReactNode } from "react";
2
- import * as react_jsx_runtime0 from "react/jsx-runtime";
3
-
4
- //#region src/changelog-rail-search.d.ts
5
- interface ChangelogDirectoryEntry {
6
- slug: string;
7
- title: string;
8
- description?: string;
9
- date: string;
10
- url: string;
11
- version?: string;
12
- tags: string[];
13
- authors: string[];
14
- image?: string;
15
- content?: ReactNode;
16
- }
17
- interface ChangelogDirectoryProps {
18
- title: string;
19
- description?: string;
20
- entries: ChangelogDirectoryEntry[];
21
- searchEnabled: boolean;
22
- actions?: ReactNode;
23
- }
24
- interface ChangelogTOCItem {
25
- href: string;
26
- title: string;
27
- meta?: string;
28
- }
29
- declare function ChangelogTOC({
30
- title,
31
- items,
32
- variant
33
- }: {
34
- title: string;
35
- items: ChangelogTOCItem[];
36
- variant?: "releases" | "content";
37
- }): react_jsx_runtime0.JSX.Element | null;
38
- declare function ChangelogDirectory({
39
- title,
40
- description,
41
- entries,
42
- searchEnabled,
43
- actions
44
- }: ChangelogDirectoryProps): react_jsx_runtime0.JSX.Element;
45
- //#endregion
46
- export { ChangelogDirectory, ChangelogDirectoryEntry, ChangelogTOC };
@@ -1,443 +0,0 @@
1
- "use client";
2
-
3
- import Link from "next/link";
4
- import { useEffect, useMemo, useRef, useState } from "react";
5
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
-
7
- //#region src/changelog-rail-search.tsx
8
- const MAGIC_PROSE = "fd-changelog-prose prose dark:prose-invert max-w-none min-w-0 prose-headings:scroll-mt-8 prose-headings:font-semibold prose-a:no-underline prose-headings:tracking-tight prose-headings:text-balance prose-p:tracking-tight prose-p:text-balance";
9
- function formatTagLabel(tag) {
10
- return tag.split(/[-_\s]+/).filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ");
11
- }
12
- function SearchIcon() {
13
- return /* @__PURE__ */ jsxs("svg", {
14
- "aria-hidden": "true",
15
- viewBox: "0 0 24 24",
16
- className: "size-4",
17
- fill: "none",
18
- stroke: "currentColor",
19
- strokeWidth: "1.8",
20
- strokeLinecap: "round",
21
- strokeLinejoin: "round",
22
- children: [/* @__PURE__ */ jsx("circle", {
23
- cx: "11",
24
- cy: "11",
25
- r: "7"
26
- }), /* @__PURE__ */ jsx("path", { d: "m20 20-3.5-3.5" })]
27
- });
28
- }
29
- function formatTimelineDate(value) {
30
- const parsed = /* @__PURE__ */ new Date(`${value}T00:00:00Z`);
31
- if (Number.isNaN(parsed.valueOf())) return value;
32
- return new Intl.DateTimeFormat("en-US", {
33
- year: "numeric",
34
- month: "long",
35
- day: "numeric",
36
- timeZone: "UTC"
37
- }).format(parsed).toUpperCase();
38
- }
39
- function buildSearchHaystack(entry) {
40
- return [
41
- entry.title,
42
- entry.description,
43
- entry.date,
44
- entry.version,
45
- entry.tags.join(" "),
46
- entry.authors.join(" ")
47
- ].filter(Boolean).join(" ").toLowerCase();
48
- }
49
- function EmptyResults({ query }) {
50
- return /* @__PURE__ */ jsxs("div", {
51
- className: "rounded-lg border border-fd-border/70 bg-fd-muted/30 px-6 py-12 sm:px-8",
52
- style: {
53
- width: "min(100%, 48rem)",
54
- maxWidth: "48rem",
55
- minHeight: "10rem",
56
- display: "flex",
57
- flexDirection: "column",
58
- alignItems: "flex-start",
59
- justifyContent: "center",
60
- textAlign: "left",
61
- alignSelf: "flex-start",
62
- marginLeft: 0,
63
- marginRight: "auto"
64
- },
65
- children: [
66
- /* @__PURE__ */ jsx("p", {
67
- className: "text-xs font-medium uppercase tracking-[0.12em] text-fd-muted-foreground",
68
- children: "No matches"
69
- }),
70
- /* @__PURE__ */ jsxs("h2", {
71
- className: "mt-3 max-w-2xl text-2xl font-semibold tracking-tight text-fd-foreground sm:text-3xl",
72
- children: [
73
- "Nothing matched “",
74
- query,
75
- "”"
76
- ]
77
- }),
78
- /* @__PURE__ */ jsx("p", {
79
- className: "mt-3 max-w-xl text-sm leading-relaxed text-fd-muted-foreground",
80
- children: "Try a release title, version, tag, or author name."
81
- })
82
- ]
83
- });
84
- }
85
- function decodeHashValue(value) {
86
- try {
87
- return decodeURIComponent(value);
88
- } catch {
89
- return value;
90
- }
91
- }
92
- function getHashTargetElement(href) {
93
- if (!href.startsWith("#")) return null;
94
- const targetId = decodeHashValue(href.slice(1));
95
- if (!targetId) return null;
96
- const candidates = Array.from(document.querySelectorAll("[id]")).filter((candidate) => candidate.id === targetId);
97
- const element = candidates.find((candidate) => {
98
- const rect = candidate.getBoundingClientRect();
99
- return rect.width > 0 || rect.height > 0;
100
- }) ?? candidates[0];
101
- if (!element) return null;
102
- const rect = element.getBoundingClientRect();
103
- if (rect.width > 0 || rect.height > 0) return element;
104
- return element.closest("h1, h2, h3, h4, h5, h6, section, article") ?? element.parentElement;
105
- }
106
- function ChangelogTOC({ title, items, variant = "releases" }) {
107
- const tocId = `fd-changelog-toc-${variant}-${title.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
108
- const [activeHref, setActiveHref] = useState(items[0]?.href ?? "");
109
- const activeSourceRef = useRef("hash");
110
- useEffect(() => {
111
- let frameId = 0;
112
- const updateActiveHrefFromScroll = () => {
113
- const threshold = Math.max(140, window.innerHeight * .18);
114
- let nextActiveHref = items[0]?.href ?? "";
115
- for (const item of items) {
116
- const element = getHashTargetElement(item.href);
117
- if (!element) continue;
118
- const { top } = element.getBoundingClientRect();
119
- if (top <= threshold) nextActiveHref = item.href;
120
- else break;
121
- }
122
- const scrollingElement = document.scrollingElement ?? document.documentElement;
123
- if (scrollingElement.scrollTop > 0 && scrollingElement.scrollHeight - scrollingElement.scrollTop - scrollingElement.clientHeight <= 2) for (let index = items.length - 1; index >= 0; index -= 1) {
124
- const item = items[index];
125
- if (item && getHashTargetElement(item.href)) {
126
- nextActiveHref = item.href;
127
- break;
128
- }
129
- }
130
- setActiveHref(nextActiveHref);
131
- };
132
- const updateActiveHrefFromHash = () => {
133
- if (!window.location.hash) return false;
134
- const hashHref = `#${decodeHashValue(window.location.hash.slice(1))}`;
135
- if (items.some((item) => item.href === hashHref)) {
136
- setActiveHref(hashHref);
137
- return true;
138
- }
139
- return false;
140
- };
141
- const syncActiveHref = () => {
142
- if (activeSourceRef.current === "hash" && updateActiveHrefFromHash()) return;
143
- activeSourceRef.current = "scroll";
144
- updateActiveHrefFromScroll();
145
- };
146
- const scheduleActiveHrefUpdate = () => {
147
- if (frameId !== 0) return;
148
- frameId = window.requestAnimationFrame(() => {
149
- frameId = 0;
150
- syncActiveHref();
151
- });
152
- };
153
- const handleScroll = () => {
154
- activeSourceRef.current = "scroll";
155
- scheduleActiveHrefUpdate();
156
- };
157
- const handleHashChange = () => {
158
- activeSourceRef.current = "hash";
159
- if (updateActiveHrefFromHash()) return;
160
- activeSourceRef.current = "scroll";
161
- scheduleActiveHrefUpdate();
162
- };
163
- syncActiveHref();
164
- const initialUpdateId = window.setTimeout(syncActiveHref, 0);
165
- const settledUpdateId = window.setTimeout(syncActiveHref, 250);
166
- window.addEventListener("scroll", handleScroll, { passive: true });
167
- window.addEventListener("resize", scheduleActiveHrefUpdate);
168
- window.addEventListener("hashchange", handleHashChange);
169
- return () => {
170
- window.clearTimeout(initialUpdateId);
171
- window.clearTimeout(settledUpdateId);
172
- if (frameId !== 0) window.cancelAnimationFrame(frameId);
173
- window.removeEventListener("scroll", handleScroll);
174
- window.removeEventListener("resize", scheduleActiveHrefUpdate);
175
- window.removeEventListener("hashchange", handleHashChange);
176
- };
177
- }, [items]);
178
- if (items.length === 0) return null;
179
- return /* @__PURE__ */ jsx("aside", {
180
- id: tocId,
181
- className: "fd-changelog-toc",
182
- "aria-label": title,
183
- "data-fd-changelog-toc": "true",
184
- "data-variant": variant,
185
- children: /* @__PURE__ */ jsxs("div", {
186
- className: "fd-changelog-toc-card",
187
- children: [/* @__PURE__ */ jsx("p", {
188
- className: "fd-changelog-toc-heading",
189
- children: title
190
- }), /* @__PURE__ */ jsx("nav", {
191
- className: "fd-changelog-toc-list",
192
- children: items.map((item) => {
193
- const isActive = item.href === activeHref;
194
- return /* @__PURE__ */ jsxs("a", {
195
- href: item.href,
196
- className: "fd-changelog-toc-link",
197
- "data-fd-changelog-toc-link": "true",
198
- "data-active": isActive ? "true" : "false",
199
- "aria-current": isActive ? "location" : void 0,
200
- onClick: () => setActiveHref(item.href),
201
- children: [item.meta ? /* @__PURE__ */ jsx("span", {
202
- className: "fd-changelog-toc-meta",
203
- children: item.meta
204
- }) : null, /* @__PURE__ */ jsx("span", {
205
- className: "fd-changelog-toc-title",
206
- children: item.title
207
- })]
208
- }, item.href);
209
- })
210
- })]
211
- })
212
- });
213
- }
214
- function ChangelogTimelineItem({ entry, isLast }) {
215
- return /* @__PURE__ */ jsxs("div", {
216
- id: entry.slug,
217
- className: "fd-changelog-entry relative scroll-mt-24 not-prose isolate",
218
- children: [
219
- /* @__PURE__ */ jsxs("div", {
220
- className: "fd-changelog-mobile-summary",
221
- children: [entry.version ? /* @__PURE__ */ jsx("div", {
222
- className: "fd-changelog-version-box",
223
- children: entry.version
224
- }) : /* @__PURE__ */ jsx("div", {}), /* @__PURE__ */ jsx("time", {
225
- className: "fd-changelog-date",
226
- style: { marginBottom: "10px" },
227
- dateTime: entry.date,
228
- children: formatTimelineDate(entry.date)
229
- })]
230
- }),
231
- /* @__PURE__ */ jsxs("div", {
232
- className: "fd-changelog-mobile-content",
233
- style: isLast ? void 0 : { paddingBottom: "5rem" },
234
- children: [/* @__PURE__ */ jsxs("div", {
235
- className: "flex flex-col gap-2",
236
- children: [
237
- /* @__PURE__ */ jsx("h2", {
238
- className: "m-0 text-balance text-lg font-semibold leading-snug tracking-tight text-fd-foreground md:text-xl",
239
- children: /* @__PURE__ */ jsx(Link, {
240
- href: entry.url,
241
- className: "text-inherit no-underline hover:underline",
242
- children: entry.title
243
- })
244
- }),
245
- entry.tags.length > 0 ? /* @__PURE__ */ jsx("div", {
246
- className: "flex flex-wrap gap-2",
247
- children: entry.tags.map((tag) => /* @__PURE__ */ jsx("span", {
248
- className: "fd-changelog-tag",
249
- "data-testid": "changelog-tag",
250
- children: formatTagLabel(tag)
251
- }, `${entry.slug}-${tag}`))
252
- }) : null,
253
- entry.description ? /* @__PURE__ */ jsx("p", {
254
- className: "m-0 max-w-2xl text-sm leading-relaxed text-fd-muted-foreground",
255
- children: entry.description
256
- }) : null
257
- ]
258
- }), entry.content || entry.image ? /* @__PURE__ */ jsxs("div", {
259
- className: MAGIC_PROSE,
260
- children: [entry.image ? /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("img", {
261
- src: entry.image,
262
- alt: `${entry.title} preview`,
263
- loading: "lazy",
264
- decoding: "async"
265
- }) }) : null, entry.content]
266
- }) : null]
267
- }),
268
- /* @__PURE__ */ jsxs("div", {
269
- className: "fd-changelog-desktop-grid",
270
- style: isLast ? void 0 : { paddingBottom: "5rem" },
271
- children: [
272
- /* @__PURE__ */ jsx("div", {
273
- className: "flex items-start justify-end pt-0.5",
274
- children: entry.version ? /* @__PURE__ */ jsx("div", {
275
- className: "fd-changelog-version-box",
276
- children: entry.version
277
- }) : /* @__PURE__ */ jsx("div", {
278
- className: "h-9",
279
- "aria-hidden": "true"
280
- })
281
- }),
282
- /* @__PURE__ */ jsxs("div", {
283
- className: "fd-changelog-rail",
284
- "data-testid": "changelog-rail",
285
- children: [/* @__PURE__ */ jsx("div", {
286
- className: "fd-changelog-timeline-dot mt-1",
287
- "data-testid": "changelog-timeline-dot",
288
- "aria-hidden": true
289
- }), isLast ? /* @__PURE__ */ jsx("div", {
290
- className: "fd-changelog-rail-end-mask",
291
- "aria-hidden": true
292
- }) : null]
293
- }),
294
- /* @__PURE__ */ jsxs("div", {
295
- className: "min-w-0 space-y-5",
296
- children: [/* @__PURE__ */ jsx("time", {
297
- className: "fd-changelog-date block pt-0.5",
298
- dateTime: entry.date,
299
- children: formatTimelineDate(entry.date)
300
- }), /* @__PURE__ */ jsxs("div", {
301
- className: "space-y-6",
302
- children: [/* @__PURE__ */ jsxs("div", {
303
- className: "flex flex-col gap-2",
304
- children: [
305
- /* @__PURE__ */ jsx("h2", {
306
- className: "m-0 text-balance text-lg font-semibold leading-snug tracking-tight text-fd-foreground md:text-xl",
307
- children: /* @__PURE__ */ jsx(Link, {
308
- href: entry.url,
309
- className: "text-inherit no-underline hover:underline",
310
- children: entry.title
311
- })
312
- }),
313
- entry.tags.length > 0 ? /* @__PURE__ */ jsx("div", {
314
- className: "flex flex-wrap gap-2",
315
- children: entry.tags.map((tag) => /* @__PURE__ */ jsx("span", {
316
- className: "fd-changelog-tag",
317
- "data-testid": "changelog-tag",
318
- children: formatTagLabel(tag)
319
- }, `${entry.slug}-${tag}`))
320
- }) : null,
321
- entry.description ? /* @__PURE__ */ jsx("p", {
322
- className: "m-0 max-w-2xl text-sm leading-relaxed text-fd-muted-foreground",
323
- children: entry.description
324
- }) : null
325
- ]
326
- }), entry.content || entry.image ? /* @__PURE__ */ jsxs("div", {
327
- className: MAGIC_PROSE,
328
- children: [entry.image ? /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx("img", {
329
- src: entry.image,
330
- alt: `${entry.title} preview`,
331
- loading: "lazy",
332
- decoding: "async"
333
- }) }) : null, entry.content]
334
- }) : null]
335
- })]
336
- })
337
- ]
338
- })
339
- ]
340
- });
341
- }
342
- function ChangelogDirectory({ title, description, entries, searchEnabled, actions }) {
343
- const [query, setQuery] = useState("");
344
- const normalizedQuery = query.trim().toLowerCase();
345
- const filteredEntries = useMemo(() => {
346
- if (!normalizedQuery) return entries;
347
- return entries.filter((entry) => buildSearchHaystack(entry).includes(normalizedQuery));
348
- }, [entries, normalizedQuery]);
349
- const releaseCount = entries.length;
350
- const hasResults = filteredEntries.length > 0;
351
- const tocItems = filteredEntries.map((entry) => ({
352
- href: `#${entry.slug}`,
353
- title: entry.title,
354
- meta: entry.version ?? formatTimelineDate(entry.date)
355
- }));
356
- const searchControl = searchEnabled ? /* @__PURE__ */ jsx("div", {
357
- className: "fd-changelog-search-row",
358
- children: /* @__PURE__ */ jsxs("label", {
359
- className: "fd-changelog-search",
360
- "aria-label": "Search changelog entries",
361
- children: [/* @__PURE__ */ jsx("span", {
362
- className: "fd-changelog-search-icon",
363
- "aria-hidden": "true",
364
- children: /* @__PURE__ */ jsx(SearchIcon, {})
365
- }), /* @__PURE__ */ jsx("input", {
366
- type: "text",
367
- inputMode: "search",
368
- autoComplete: "off",
369
- value: query,
370
- onChange: (event) => setQuery(event.target.value),
371
- placeholder: "Search changelog entries",
372
- className: "fd-changelog-search-input"
373
- })]
374
- })
375
- }) : null;
376
- return /* @__PURE__ */ jsxs("div", {
377
- className: "fd-changelog-frame not-prose relative w-full pb-16",
378
- children: [
379
- /* @__PURE__ */ jsx("div", {
380
- className: "fd-changelog-header-strip border-b-0 border-fd-border/50",
381
- children: /* @__PURE__ */ jsxs("div", {
382
- className: "flex flex-wrap items-center justify-between gap-4",
383
- style: {
384
- paddingTop: "1.25rem",
385
- paddingBottom: "1.25rem"
386
- },
387
- children: [/* @__PURE__ */ jsxs("div", {
388
- className: "min-w-0",
389
- children: [/* @__PURE__ */ jsx("h1", {
390
- className: "text-2xl font-semibold tracking-tight text-fd-foreground md:text-3xl",
391
- children: title
392
- }), /* @__PURE__ */ jsxs("p", {
393
- className: "mt-0.5 text-sm text-fd-muted-foreground",
394
- children: [
395
- releaseCount,
396
- " ",
397
- releaseCount === 1 ? "release" : "releases"
398
- ]
399
- })]
400
- }), actions ? /* @__PURE__ */ jsx("div", {
401
- className: "flex flex-wrap items-center gap-2",
402
- children: actions
403
- }) : null]
404
- })
405
- }),
406
- description || searchControl ? /* @__PURE__ */ jsxs(Fragment, { children: [
407
- description ? /* @__PURE__ */ jsx("p", {
408
- className: "max-w-2xl text-base leading-relaxed text-fd-muted-foreground",
409
- style: { marginTop: "1rem" },
410
- children: description
411
- }) : null,
412
- searchControl ? /* @__PURE__ */ jsx("div", {
413
- style: { marginTop: description ? "1rem" : "1.25rem" },
414
- children: searchControl
415
- }) : null,
416
- /* @__PURE__ */ jsx("hr", {
417
- className: "border-0 border-t border-fd-border/40",
418
- style: { marginTop: "1rem" }
419
- })
420
- ] }) : null,
421
- /* @__PURE__ */ jsxs("div", {
422
- className: hasResults ? "fd-changelog-shell fd-changelog-shell-shifted" : "fd-changelog-shell",
423
- style: { paddingTop: "4rem" },
424
- children: [/* @__PURE__ */ jsx("div", {
425
- className: "fd-changelog-main fd-changelog-directory-feed relative",
426
- children: hasResults ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
427
- className: "fd-changelog-directory-line",
428
- "aria-hidden": true
429
- }), filteredEntries.map((entry, index) => /* @__PURE__ */ jsx(ChangelogTimelineItem, {
430
- entry,
431
- isLast: index === filteredEntries.length - 1
432
- }, entry.slug))] }) : /* @__PURE__ */ jsx(EmptyResults, { query })
433
- }), /* @__PURE__ */ jsx(ChangelogTOC, {
434
- title: "Releases",
435
- items: tocItems
436
- })]
437
- })
438
- ]
439
- });
440
- }
441
-
442
- //#endregion
443
- export { ChangelogDirectory, ChangelogTOC };