@clarify-labs/renderer 0.4.0 → 0.6.0

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.
Files changed (98) hide show
  1. package/README.md +9 -0
  2. package/output/AppShell-D3FsVHQK.js +390 -0
  3. package/output/AppShell-D3FsVHQK.js.map +1 -0
  4. package/output/AppShell-DeaJ-rgo.cjs +409 -0
  5. package/output/AppShell-DeaJ-rgo.cjs.map +1 -0
  6. package/output/OpenApiOperation-DYXG-6Rw.js +1772 -0
  7. package/output/OpenApiOperation-DYXG-6Rw.js.map +1 -0
  8. package/output/OpenApiOperation-mhoi-s4N.cjs +1840 -0
  9. package/output/OpenApiOperation-mhoi-s4N.cjs.map +1 -0
  10. package/output/app/PageNavigation.d.ts +7 -0
  11. package/output/app/PageSkeleton.d.ts +1 -0
  12. package/output/{components → app}/SectionProvider.d.ts +3 -2
  13. package/output/chunk-DakpK96I.cjs +43 -0
  14. package/output/client.cjs +1 -1
  15. package/output/client.js +1 -1
  16. package/output/components/Button.d.ts +18 -0
  17. package/output/components/Code.d.ts +11 -7
  18. package/output/components/Collapse.d.ts +9 -0
  19. package/output/components/Heading.d.ts +10 -0
  20. package/output/components/Logo.d.ts +2 -0
  21. package/output/components/Prose.d.ts +7 -0
  22. package/output/components/Tag.d.ts +34 -0
  23. package/output/components/index.d.ts +9 -80
  24. package/output/components/patterns.d.ts +4 -2
  25. package/output/context.d.ts +1 -8
  26. package/output/core/context.d.ts +8 -0
  27. package/output/core/i18n.d.ts +5 -0
  28. package/output/core/index.d.ts +3 -0
  29. package/output/core/types.d.ts +174 -0
  30. package/output/i18n.d.ts +1 -5
  31. package/output/index.cjs +105 -1741
  32. package/output/index.cjs.map +1 -1
  33. package/output/index.d.ts +15 -4
  34. package/output/index.js +71 -1719
  35. package/output/index.js.map +1 -1
  36. package/output/markdown.cjs +3 -0
  37. package/output/markdown.d.ts +1 -0
  38. package/output/markdown.js +2 -0
  39. package/output/mdx/DocShell.d.ts +7 -0
  40. package/output/mdx/Markdown.d.ts +7 -0
  41. package/output/mdx/components.d.ts +7 -7
  42. package/output/mdx/primitives.d.ts +18 -12
  43. package/output/mdx/remark.d.ts +2 -0
  44. package/output/openapi/{example-panels.d.ts → components/ExamplePanels.d.ts} +14 -9
  45. package/output/openapi/components/OpenApiOperation.d.ts +33 -0
  46. package/output/openapi/components/SchemaProperties.d.ts +20 -0
  47. package/output/openapi/entry.d.ts +13 -0
  48. package/output/openapi/index.d.ts +3 -3
  49. package/output/openapi/{helpers.d.ts → lib/helpers.d.ts} +7 -6
  50. package/output/openapi/{request-code.d.ts → lib/request-code.d.ts} +7 -5
  51. package/output/openapi/types.d.ts +5 -1
  52. package/output/preview/openapi.d.ts +28 -0
  53. package/output/preview.cjs +734 -0
  54. package/output/preview.cjs.map +1 -0
  55. package/output/preview.d.ts +19 -0
  56. package/output/preview.js +731 -0
  57. package/output/preview.js.map +1 -0
  58. package/output/remark-DNOdJz5i.cjs +14 -0
  59. package/output/remark-DNOdJz5i.cjs.map +1 -0
  60. package/output/remark-o5sg9Ilv.js +7 -0
  61. package/output/remark-o5sg9Ilv.js.map +1 -0
  62. package/output/{render-BCiQn6Q1.js → render-BpavVnAe.js} +3 -2
  63. package/output/render-BpavVnAe.js.map +1 -0
  64. package/output/{render-CZsdzmme.cjs → render-CjZt3edL.cjs} +6 -5
  65. package/output/render-CjZt3edL.cjs.map +1 -0
  66. package/output/renderer.css +403 -63
  67. package/output/server.cjs +7 -5
  68. package/output/server.cjs.map +1 -1
  69. package/output/server.js +4 -2
  70. package/output/server.js.map +1 -1
  71. package/output/shell/Navigation.d.ts +3 -2
  72. package/output/shell/Search.d.ts +6 -4
  73. package/output/{components → shell}/SiteLogo.d.ts +1 -1
  74. package/output/shell/icons.d.ts +3 -2
  75. package/output/shell/mobile.d.ts +3 -2
  76. package/output/{AppShell-nQnuKyn2.js → shell-BlMMdTpZ.js} +1118 -1320
  77. package/output/shell-BlMMdTpZ.js.map +1 -0
  78. package/output/{AppShell-CZw1MrPG.cjs → shell-_MyLsMUI.cjs} +1192 -1394
  79. package/output/shell-_MyLsMUI.cjs.map +1 -0
  80. package/output/{components → theme}/ThemeProvider.d.ts +3 -2
  81. package/output/types.d.ts +1 -174
  82. package/output/utils/clipboard.d.ts +1 -0
  83. package/output/utils/hash.d.ts +1 -0
  84. package/output/utils/href.d.ts +5 -0
  85. package/output/utils/lucide.d.ts +17 -0
  86. package/package.json +15 -2
  87. package/output/AppShell-CZw1MrPG.cjs.map +0 -1
  88. package/output/AppShell-nQnuKyn2.js.map +0 -1
  89. package/output/components/PageNavigation.d.ts +0 -5
  90. package/output/openapi/openapi-page.d.ts +0 -19
  91. package/output/openapi/schema-properties.d.ts +0 -15
  92. package/output/render-BCiQn6Q1.js.map +0 -1
  93. package/output/render-CZsdzmme.cjs.map +0 -1
  94. /package/output/{components → app}/BuiltWithClarify.d.ts +0 -0
  95. /package/output/{components → app}/PageFooter.d.ts +0 -0
  96. /package/output/openapi/{spec-path.d.ts → lib/spec-path.d.ts} +0 -0
  97. /package/output/openapi/{utils.d.ts → lib/utils.d.ts} +0 -0
  98. /package/output/{components → theme}/ThemeToggle.d.ts +0 -0
@@ -1,87 +1,13 @@
1
1
  import clsx from "clsx";
2
+ import { Children, Fragment, Suspense, createContext, forwardRef, isValidElement, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
3
+ import { Link, useLocation, useNavigate } from "react-router-dom";
4
+ import { CloseButton, Dialog, DialogBackdrop, DialogPanel, Menu, MenuButton, MenuItem, MenuItems, Tab, TabGroup, TabList, TabPanel, TabPanels, Transition, TransitionChild } from "@headlessui/react";
5
+ import * as LucideIcons from "lucide-react";
6
+ import { AlertTriangle, Check, CheckCircle2, ChevronDown, Copy, ExternalLink, FileText, Info, Lightbulb, Link2, MoreHorizontal, XCircle } from "lucide-react";
7
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
2
8
  import { AnimatePresence, motion, useInView, useIsPresent, useScroll, useTransform } from "framer-motion";
3
- import { Children, Fragment, Suspense, createContext, forwardRef, isValidElement, lazy, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
4
- import { Link, Route, Routes, useLocation, useNavigate } from "react-router-dom";
5
9
  import { create, createStore, useStore } from "zustand";
6
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
- import * as LucideIcons from "lucide-react";
8
- import { AlertTriangle, Check, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, Copy, ExternalLink, FileText, Info, Lightbulb, Link2, MoreHorizontal, XCircle } from "lucide-react";
9
- import { CloseButton, Dialog, DialogBackdrop, DialogPanel, Menu, MenuButton, MenuItem, MenuItems, Tab, TabGroup, TabList, TabPanel, TabPanels, Transition, TransitionChild } from "@headlessui/react";
10
- //#region source/utils/remToPx.ts
11
- function remToPx(remValue) {
12
- return remValue * (typeof window === "undefined" ? 16 : Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize));
13
- }
14
- //#endregion
15
- //#region source/components/SectionProvider.tsx
16
- function createSectionStore(sections) {
17
- return createStore()((set) => ({
18
- sections,
19
- visibleSections: [],
20
- setVisibleSections: (visibleSections) => set((state) => state.visibleSections.join() === visibleSections.join() ? {} : { visibleSections }),
21
- registerHeading: ({ id, ref, offsetRem }) => set((state) => ({ sections: state.sections.map((section) => section.id === id ? {
22
- ...section,
23
- headingRef: ref,
24
- offsetRem
25
- } : section) }))
26
- }));
27
- }
28
- function useVisibleSections(sectionStore) {
29
- const setVisibleSections = useStore(sectionStore, (state) => state.setVisibleSections);
30
- const sections = useStore(sectionStore, (state) => state.sections);
31
- useEffect(() => {
32
- function checkVisibleSections() {
33
- const { innerHeight, scrollY } = window;
34
- const newVisibleSections = [];
35
- for (let sectionIndex = 0; sectionIndex < sections.length; sectionIndex += 1) {
36
- const { id, headingRef, offsetRem = 0 } = sections[sectionIndex];
37
- if (!headingRef?.current) continue;
38
- const offset = remToPx(offsetRem);
39
- const top = headingRef.current.getBoundingClientRect().top + scrollY;
40
- if (sectionIndex === 0 && top - offset > scrollY) newVisibleSections.push("_top");
41
- const nextSection = sections[sectionIndex + 1];
42
- const bottom = (nextSection?.headingRef?.current?.getBoundingClientRect().top ?? Infinity) + scrollY - remToPx(nextSection?.offsetRem ?? 0);
43
- if (top > scrollY && top < scrollY + innerHeight || bottom > scrollY && bottom < scrollY + innerHeight || top <= scrollY && bottom >= scrollY + innerHeight) newVisibleSections.push(id);
44
- }
45
- setVisibleSections(newVisibleSections);
46
- }
47
- const raf = window.requestAnimationFrame(() => checkVisibleSections());
48
- window.addEventListener("scroll", checkVisibleSections, { passive: true });
49
- window.addEventListener("resize", checkVisibleSections);
50
- return () => {
51
- window.cancelAnimationFrame(raf);
52
- window.removeEventListener("scroll", checkVisibleSections);
53
- window.removeEventListener("resize", checkVisibleSections);
54
- };
55
- }, [setVisibleSections, sections]);
56
- }
57
- var SectionStoreContext = createContext(null);
58
- var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
59
- function SectionProvider(arg0) {
60
- const { sections, children } = arg0;
61
- const [sectionStore] = useState(() => createSectionStore(sections));
62
- useVisibleSections(sectionStore);
63
- useIsomorphicLayoutEffect(() => {
64
- sectionStore.setState((state) => ({ sections: sections.map((section) => {
65
- const registeredSection = state.sections.find((item) => item.id === section.id);
66
- return {
67
- ...section,
68
- headingRef: registeredSection?.headingRef,
69
- offsetRem: registeredSection?.offsetRem ?? section.offsetRem
70
- };
71
- }) }));
72
- }, [sectionStore, sections]);
73
- return /* @__PURE__ */ jsx(SectionStoreContext.Provider, {
74
- value: sectionStore,
75
- children
76
- });
77
- }
78
- function useSectionStore(selector) {
79
- const store = useContext(SectionStoreContext);
80
- if (!store) throw new Error("[clarify] useSectionStore must be used within SectionProvider");
81
- return useStore(store, selector);
82
- }
83
- //#endregion
84
- //#region source/context.tsx
10
+ //#region source/core/context.tsx
85
11
  var ClarifyConfigContext = createContext(null);
86
12
  var ClarifyLocaleContext = createContext(void 0);
87
13
  var OpenApisContext = createContext({});
@@ -94,7 +20,7 @@ function useOpenApis() {
94
20
  return useContext(OpenApisContext);
95
21
  }
96
22
  //#endregion
97
- //#region source/i18n.ts
23
+ //#region source/core/i18n.ts
98
24
  var builtInText = {
99
25
  en: {
100
26
  "actions.code": "Code",
@@ -112,6 +38,9 @@ var builtInText = {
112
38
  "contentActions.copyContentDescription": "Copy this page as {contentType} for LLMs",
113
39
  "contentActions.copyLink": "Copy {contentType} link",
114
40
  "contentActions.copyLinkDescription": "Copy the raw {contentType} content link for this page",
41
+ "contentActions.copyLlms": "Copy llms.txt",
42
+ "contentActions.copyLlmsDescription": "Copy the llms.txt link for this site",
43
+ "contentActions.copiedLlms": "Copied llms.txt",
115
44
  "contentActions.copyOptions": "Choose copy option",
116
45
  "contentActions.copiedContent": "Copied page",
117
46
  "contentActions.copiedLink": "Copied link",
@@ -184,6 +113,9 @@ var builtInText = {
184
113
  "contentActions.copyContentDescription": "将页面以 {contentType} 格式复制给 LLMs",
185
114
  "contentActions.copyLink": "复制 {contentType} 链接",
186
115
  "contentActions.copyLinkDescription": "复制当前页面的 {contentType} 原始内容链接",
116
+ "contentActions.copyLlms": "复制 llms.txt",
117
+ "contentActions.copyLlmsDescription": "复制此站点的 llms.txt 链接",
118
+ "contentActions.copiedLlms": "已复制 llms.txt",
187
119
  "contentActions.copyOptions": "选择复制选项",
188
120
  "contentActions.copiedContent": "已复制页面",
189
121
  "contentActions.copiedLink": "已复制链接",
@@ -256,894 +188,1027 @@ function useBuiltInText(locale) {
256
188
  return (key, replacements) => translateBuiltInText(resolvedLocale, key, replacements);
257
189
  }
258
190
  //#endregion
259
- //#region source/components/BuiltWithClarify.tsx
260
- function ClarifyMark(props) {
261
- return /* @__PURE__ */ jsxs("svg", {
262
- viewBox: "0 0 279 200",
263
- "aria-hidden": "true",
264
- ...props,
265
- children: [
266
- /* @__PURE__ */ jsx("path", {
267
- d: "M44.867217 0.00543761C130.715579 1.00591567 200 70.9091172 200 156.994562L199.986321 155.127494C199.384888 180.009127 179.026368 199.994562 154 199.994562H46C20.5949015 199.994562 0 179.399661 0 153.994562V45.9945624C0 21.0975659 19.7793434 0.820282524 44.4815926 0.0191499894Z",
268
- fill: "#00D492"
269
- }),
270
- /* @__PURE__ */ jsx("path", {
271
- d: "M123.867217 0.00543761C209.715579 1.00591567 279 70.9091172 279 156.994562L278.986321 155.127494C278.384888 180.009127 258.026368 199.994562 233 199.994562H125C99.5949015 199.994562 79 179.399661 79 153.994562V45.9945624C79 21.0975659 98.7793434 0.820282524 123.481593 0.0191499894Z",
272
- fill: "#00F6C9",
273
- fillOpacity: "0.6",
274
- transform: "rotate(-90 179 100)"
275
- }),
276
- /* @__PURE__ */ jsx("path", {
277
- d: "M199.979267 154.416906L199.984438 155.157125L199.962366 155.872459C198.977251 180.406837 178.776104 199.994562 154 199.994562L124.372438 199.994125L124.249053 199.994081C99.6939678 199.603921 79.8122712 179.973634 79.01915 155.518407L79.0054376 155.132783C79.5830823 105.566626 103.129768 61.5221348 139.498462 33.1463428C175.69419 61.3871018 199.186123 105.143863 199.979267 154.416906Z",
278
- fill: "#00F692"
279
- })
280
- ]
281
- });
282
- }
283
- function BuiltWithClarify() {
284
- const t = useBuiltInText();
285
- return /* @__PURE__ */ jsxs("a", {
286
- href: "https://clarify.pub",
287
- target: "_blank",
288
- rel: "noreferrer",
289
- "aria-label": t("builtWith.label"),
290
- className: "clarify-built-with inline-flex items-center gap-1.5 rounded-full px-2 py-1 font-medium no-underline transition",
291
- children: [
292
- /* @__PURE__ */ jsx("span", { children: t("builtWith.prefix") }),
293
- /* @__PURE__ */ jsx(ClarifyMark, { className: "clarify-built-with-logo h-3.5 w-5 flex-none" }),
294
- /* @__PURE__ */ jsx("span", {
295
- className: "clarify-built-with-brand font-semibold",
296
- children: "Clarify"
297
- })
298
- ]
299
- });
300
- }
301
- //#endregion
302
- //#region source/components/Callout.tsx
303
- var calloutStyles = {
304
- info: {
305
- container: "border-sky-500/20 bg-sky-50/50 text-sky-950 dark:border-sky-400/30 dark:bg-sky-400/5 dark:text-sky-100",
306
- icon: "text-sky-600 dark:text-sky-400",
307
- title: "text-sky-900 dark:text-sky-100",
308
- Icon: Info
309
- },
310
- note: {
311
- container: "border-zinc-500/20 bg-zinc-50 text-zinc-900 dark:border-white/10 dark:bg-white/5 dark:text-zinc-200",
312
- icon: "text-zinc-500 dark:text-zinc-400",
313
- title: "text-zinc-900 dark:text-white",
314
- Icon: Info
315
- },
316
- tip: {
317
- container: "border-emerald-500/20 bg-emerald-50/50 text-emerald-950 dark:border-emerald-400/30 dark:bg-emerald-400/5 dark:text-emerald-100",
318
- icon: "text-emerald-600 dark:text-emerald-400",
319
- title: "text-emerald-900 dark:text-emerald-100",
320
- Icon: Lightbulb
321
- },
322
- warning: {
323
- container: "border-amber-500/20 bg-amber-50/70 text-amber-950 dark:border-amber-400/30 dark:bg-amber-400/5 dark:text-amber-100",
324
- icon: "text-amber-600 dark:text-amber-400",
325
- title: "text-amber-900 dark:text-amber-100",
326
- Icon: AlertTriangle
327
- },
328
- danger: {
329
- container: "border-rose-500/20 bg-rose-50/70 text-rose-950 dark:border-rose-400/30 dark:bg-rose-400/5 dark:text-rose-100",
330
- icon: "text-rose-600 dark:text-rose-400",
331
- title: "text-rose-900 dark:text-rose-100",
332
- Icon: XCircle
333
- },
334
- success: {
335
- container: "border-emerald-500/20 bg-emerald-50/50 text-emerald-950 dark:border-emerald-400/30 dark:bg-emerald-400/5 dark:text-emerald-100",
336
- icon: "text-emerald-600 dark:text-emerald-400",
337
- title: "text-emerald-900 dark:text-emerald-100",
338
- Icon: CheckCircle2
191
+ //#region source/utils/clipboard.ts
192
+ async function copyTextToClipboard(text) {
193
+ if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) try {
194
+ await navigator.clipboard.writeText(text);
195
+ return true;
196
+ } catch {}
197
+ if (typeof document === "undefined") return false;
198
+ const textarea = document.createElement("textarea");
199
+ textarea.value = text;
200
+ textarea.setAttribute("readonly", "");
201
+ textarea.style.position = "fixed";
202
+ textarea.style.top = "-9999px";
203
+ textarea.style.opacity = "0";
204
+ document.body.appendChild(textarea);
205
+ try {
206
+ textarea.select();
207
+ return document.execCommand("copy");
208
+ } catch {
209
+ return false;
210
+ } finally {
211
+ textarea.remove();
339
212
  }
340
- };
341
- var defaultTitleKeys = {
342
- info: "callout.info",
343
- note: "callout.note",
344
- tip: "callout.tip",
345
- warning: "callout.warning",
346
- danger: "callout.danger",
347
- success: "callout.success"
348
- };
349
- function Callout(arg0) {
350
- const { children, type = "info", title, icon = true, className, ...props } = arg0;
351
- const t = useBuiltInText();
352
- const style = calloutStyles[type];
353
- const Icon = style.Icon;
354
- const resolvedTitle = title === void 0 ? t(defaultTitleKeys[type]) : title;
355
- return /* @__PURE__ */ jsxs("div", {
356
- className: clsx("clarify-callout my-6 flex gap-3 rounded-(--clarify-theme-tokens-radius-xl) border p-4 text-sm/6", style.container, className),
357
- ...props,
358
- children: [icon ? /* @__PURE__ */ jsx(Icon, {
359
- className: clsx("mt-1 size-4 flex-none", style.icon),
360
- "aria-hidden": "true"
361
- }) : null, /* @__PURE__ */ jsxs("div", {
362
- className: "min-w-0 flex-1 *:first:mt-0 *:last:mb-0",
363
- children: [resolvedTitle ? /* @__PURE__ */ jsx("p", {
364
- className: clsx("mb-1 font-semibold", style.title),
365
- children: resolvedTitle
366
- }) : null, /* @__PURE__ */ jsx("div", {
367
- className: "*:first:mt-0 *:last:mb-0",
368
- children
369
- })]
370
- })]
371
- });
372
213
  }
373
214
  //#endregion
374
- //#region source/components/Card.tsx
375
- function toPascalCase(value) {
376
- return value.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join("");
215
+ //#region source/utils/href.ts
216
+ function isExternalHref(href) {
217
+ return /^[a-z][a-z\d+.-]*:/i.test(href) || href.startsWith("//");
377
218
  }
378
- function CardIcon(arg0) {
379
- const { name } = arg0;
380
- if (!name) return null;
381
- const Icon = LucideIcons[toPascalCase(name)];
382
- if (!Icon) return null;
383
- return /* @__PURE__ */ jsx("span", {
384
- className: "flex size-9 flex-none items-center justify-center rounded-[var(--clarify-theme-tokens-radius-lg)] bg-(--clarify-ui-accent-background) text-(--clarify-ui-accent-text) ring-1 ring-(--clarify-ui-accent-border)",
385
- children: /* @__PURE__ */ jsx(Icon, {
386
- className: "size-5",
387
- "aria-hidden": "true"
388
- })
389
- });
219
+ function hasLocalePrefix(href, config) {
220
+ const firstSegment = href.replace(/^\/+/, "").split("/")[0];
221
+ return Boolean(firstSegment && config.i18n?.locales.some((locale) => locale.code === firstSegment));
390
222
  }
391
- var cardGroupColumnStyles = {
392
- 1: "grid-cols-1",
393
- 2: "grid-cols-1 sm:grid-cols-2",
394
- 3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
395
- 4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4"
396
- };
397
- function CardGroup(arg0) {
398
- const { children, cols = 2, className } = arg0;
399
- return /* @__PURE__ */ jsx("div", {
400
- className: clsx("not-prose my-10 grid gap-4", cardGroupColumnStyles[cols], className),
401
- children
402
- });
223
+ function localizeHref(href, config, locale) {
224
+ if (!locale || !config.i18n || isExternalHref(href) || href.startsWith("#")) return href;
225
+ if (locale === config.i18n.defaultLocale || hasLocalePrefix(href, config)) return href;
226
+ const cleanHref = href === "/" ? "" : href.replace(/^\/+/, "");
227
+ return `/${locale}${cleanHref ? `/${cleanHref}` : ""}`;
403
228
  }
404
- function Card(arg0) {
405
- const { title, icon, href, children, className, ...props } = arg0;
406
- const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
407
- className: "flex items-start gap-4",
408
- children: [/* @__PURE__ */ jsx(CardIcon, { name: icon }), /* @__PURE__ */ jsxs("div", {
409
- className: "min-w-0 flex-1",
410
- children: [/* @__PURE__ */ jsx("h3", {
411
- className: "m-0 text-base font-semibold text-[var(--clarify-theme-tokens-colors-foreground)] dark:text-white",
412
- children: title
413
- }), children ? /* @__PURE__ */ jsx("div", {
414
- className: "mt-2 text-sm/6 text-[var(--clarify-theme-tokens-colors-muted)] dark:text-zinc-400 *:m-0",
415
- children
416
- }) : null]
417
- })]
418
- }), href ? /* @__PURE__ */ jsx("span", {
419
- className: "absolute inset-0 rounded-[var(--clarify-theme-tokens-radius-xl)]",
420
- "aria-hidden": "true"
421
- }) : null] });
422
- const classes = clsx("group relative block rounded-[var(--clarify-theme-tokens-radius-xl)] border border-[color:var(--clarify-theme-tokens-colors-border)] bg-[var(--clarify-theme-tokens-colors-surface)] p-5 shadow-sm shadow-(--clarify-ui-accent-glow) transition hover:border-(--clarify-ui-accent-border) hover:shadow-md dark:bg-zinc-900/50", className);
423
- if (!href) return /* @__PURE__ */ jsx("div", {
424
- className: classes,
425
- children: content
426
- });
427
- if (href.startsWith("/") && !href.startsWith("//")) return /* @__PURE__ */ jsx(Link, {
428
- to: href,
429
- className: classes,
430
- ...props,
431
- children: content
432
- });
433
- return /* @__PURE__ */ jsx("a", {
434
- href,
435
- className: classes,
436
- ...props,
437
- children: content
438
- });
229
+ function prefixHref(href, routePrefix = "/") {
230
+ if (isExternalHref(href) || href.startsWith("#")) return href;
231
+ if (!routePrefix || routePrefix === "/") return href.startsWith("/") ? href : `/${href}`;
232
+ const prefix = routePrefix.replace(/^\/+|\/+$/g, "");
233
+ const path = href.replace(/^\/+/, "");
234
+ if (!path) return `/${prefix}`;
235
+ if (path === prefix || path.startsWith(`${prefix}/`)) return `/${path}`;
236
+ return `/${prefix}/${path}`;
439
237
  }
440
238
  //#endregion
441
- //#region source/components/Code.tsx
442
- var languageNames = {
443
- js: "JavaScript",
444
- ts: "TypeScript",
445
- jsx: "React JSX",
446
- tsx: "React TSX",
447
- javascript: "JavaScript",
448
- typescript: "TypeScript",
449
- php: "PHP",
450
- python: "Python",
451
- ruby: "Ruby",
452
- go: "Go",
453
- bash: "Shell",
454
- sh: "Shell",
455
- shell: "Shell",
456
- json: "JSON"
457
- };
458
- function getPanelTitle(arg0) {
459
- const { title, language, fallbackTitle = "Code" } = arg0;
460
- if (title) return title;
461
- if (language && language in languageNames) return languageNames[language];
462
- return fallbackTitle;
239
+ //#region source/shell/ContentActions.tsx
240
+ function resolveContentArtifactUrl(contentArtifactUrl, routePrefix = "/") {
241
+ return prefixHref(contentArtifactUrl, routePrefix);
463
242
  }
464
- function getNodeText(node) {
465
- if (typeof node === "string" || typeof node === "number") return String(node);
466
- if (Array.isArray(node)) return node.map(getNodeText).join("");
467
- if (isValidElement(node)) return getNodeText(node.props.children);
468
- return "";
243
+ function getAbsoluteUrl(path) {
244
+ if (typeof window === "undefined") return path;
245
+ return new URL(path, window.location.href).href;
469
246
  }
470
- function ClipboardIcon$1(props) {
471
- return /* @__PURE__ */ jsxs("svg", {
472
- viewBox: "0 0 20 20",
473
- "aria-hidden": "true",
474
- ...props,
475
- children: [/* @__PURE__ */ jsx("path", {
476
- strokeWidth: "0",
477
- d: "M5.5 13.5v-5a2 2 0 0 1 2-2l.447-.894A2 2 0 0 1 9.737 4.5h.527a2 2 0 0 1 1.789 1.106l.447.894a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2Z"
478
- }), /* @__PURE__ */ jsx("path", {
479
- fill: "none",
480
- strokeLinejoin: "round",
481
- d: "M12.5 6.5a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2m5 0-.447-.894a2 2 0 0 0-1.79-1.106h-.527a2 2 0 0 0-1.789 1.106L7.5 6.5m5 0-1 1h-3l-1-1"
482
- })]
247
+ function ContentActions(arg0) {
248
+ const { hasTabs = false, route, routePrefix } = arg0;
249
+ const t = useBuiltInText();
250
+ const [copied, setCopied] = useState("idle");
251
+ if (!route?.contentArtifactUrl) return null;
252
+ const contentArtifactUrl = resolveContentArtifactUrl(route.contentArtifactUrl, routePrefix);
253
+ const isOpenApi = route.kind === "openapi";
254
+ const replacements = { contentType: isOpenApi ? "OpenAPI" : "Markdown" };
255
+ const viewLabel = isOpenApi ? t("contentActions.viewOpenApi") : t("contentActions.viewMarkdown");
256
+ const viewDescription = isOpenApi ? t("contentActions.viewOpenApiDescription") : t("contentActions.viewMarkdownDescription");
257
+ function markCopied(state) {
258
+ setCopied(state);
259
+ window.setTimeout(() => setCopied("idle"), 1600);
260
+ }
261
+ async function handleCopyContent() {
262
+ if (await copyTextToClipboard(await (await fetch(contentArtifactUrl)).text())) markCopied("content");
263
+ }
264
+ const llmsArtifactUrl = resolveContentArtifactUrl("/llms.txt", routePrefix);
265
+ async function handleCopyLink() {
266
+ if (await copyTextToClipboard(getAbsoluteUrl(contentArtifactUrl))) markCopied("link");
267
+ }
268
+ async function handleCopyLlms() {
269
+ if (await copyTextToClipboard(getAbsoluteUrl(llmsArtifactUrl))) markCopied("llms");
270
+ }
271
+ const actions = [{
272
+ key: "content",
273
+ label: t("contentActions.copyContent"),
274
+ description: t("contentActions.copyContentDescription", replacements),
275
+ icon: Copy,
276
+ run: handleCopyContent,
277
+ copiedLabel: t("contentActions.copiedContent")
278
+ }, {
279
+ key: "link",
280
+ label: t("contentActions.copyLink", replacements),
281
+ description: t("contentActions.copyLinkDescription", replacements),
282
+ icon: Link2,
283
+ run: handleCopyLink,
284
+ copiedLabel: t("contentActions.copiedLink")
285
+ }];
286
+ const llmsAction = {
287
+ key: "llms",
288
+ label: t("contentActions.copyLlms"),
289
+ description: t("contentActions.copyLlmsDescription"),
290
+ icon: FileText,
291
+ run: handleCopyLlms,
292
+ copiedLabel: t("contentActions.copiedLlms")
293
+ };
294
+ const primaryAction = actions[0];
295
+ const PrimaryIcon = copied === primaryAction.key ? Check : primaryAction.icon;
296
+ return /* @__PURE__ */ jsx("div", {
297
+ className: `clarify-content-actions sticky z-20 flex justify-end py-4 ${hasTabs ? "top-16 lg:top-30" : "top-16"}`,
298
+ children: /* @__PURE__ */ jsxs(Menu, {
299
+ as: "div",
300
+ className: "clarify-content-actions-menu relative inline-flex text-sm font-medium",
301
+ children: [/* @__PURE__ */ jsxs("div", {
302
+ className: "clarify-content-actions-group inline-flex overflow-hidden rounded-full border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface)/90 shadow-sm shadow-zinc-900/5 backdrop-blur dark:border-white/10 dark:bg-zinc-900/80 dark:shadow-none",
303
+ children: [/* @__PURE__ */ jsxs("button", {
304
+ type: "button",
305
+ onClick: primaryAction.run,
306
+ className: "clarify-content-actions-primary clarify-ui-control inline-flex h-8 items-center gap-1.5 px-3 transition",
307
+ children: [/* @__PURE__ */ jsx(PrimaryIcon, { className: "h-3.5 w-3.5" }), copied === primaryAction.key ? t("actions.copied") : primaryAction.label]
308
+ }), /* @__PURE__ */ jsx(MenuButton, {
309
+ className: "clarify-content-actions-trigger clarify-ui-control inline-flex h-8 w-8 items-center justify-center border-l border-(--clarify-theme-tokens-colors-border) transition dark:border-white/10",
310
+ "aria-label": t("contentActions.copyOptions"),
311
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5" })
312
+ })]
313
+ }), /* @__PURE__ */ jsxs(MenuItems, {
314
+ anchor: "bottom end",
315
+ className: "clarify-content-actions-list clarify-ui-menu z-30 mt-2 w-(--clarify-ui-action-menu-width) origin-top-right rounded-(--clarify-theme-tokens-radius-xl) border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface) p-1.5 shadow-xl shadow-zinc-900/5 transition [--anchor-gap:--spacing(2)] focus:outline-none data-closed:scale-95 data-closed:opacity-0 dark:border-white/10 dark:bg-zinc-900 dark:shadow-none",
316
+ children: [
317
+ actions.slice(0, 1).map((action) => {
318
+ const Icon = action.icon;
319
+ const isCopied = copied === action.key;
320
+ return /* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsxs("button", {
321
+ type: "button",
322
+ onClick: action.run,
323
+ className: "clarify-content-actions-item clarify-ui-menu-item group flex w-full items-center gap-2 rounded-(--clarify-theme-tokens-radius-lg) px-1.5 py-1.5 text-left transition",
324
+ children: [
325
+ /* @__PURE__ */ jsx("span", {
326
+ className: "clarify-ui-menu-icon flex shrink-0 rounded-(--clarify-theme-tokens-radius-md) border border-(--clarify-theme-tokens-colors-border) p-1.5 dark:border-white/10",
327
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" })
328
+ }),
329
+ /* @__PURE__ */ jsxs("span", {
330
+ className: "flex min-w-0 flex-1 flex-col px-1",
331
+ children: [/* @__PURE__ */ jsx("span", {
332
+ className: "clarify-ui-menu-title",
333
+ children: isCopied ? t("contentActions.copiedContent") : action.label
334
+ }), /* @__PURE__ */ jsx("span", {
335
+ className: "clarify-ui-menu-description truncate",
336
+ children: action.description
337
+ })]
338
+ }),
339
+ /* @__PURE__ */ jsx(Check, { className: `h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) transition ${isCopied ? "opacity-100" : "opacity-0"}` })
340
+ ]
341
+ }) }, action.key);
342
+ }),
343
+ /* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsxs("a", {
344
+ href: contentArtifactUrl,
345
+ target: "_blank",
346
+ rel: "noreferrer",
347
+ className: "clarify-content-actions-item clarify-ui-menu-item group flex w-full items-center gap-2 rounded-(--clarify-theme-tokens-radius-lg) px-1.5 py-1.5 text-left no-underline transition",
348
+ children: [
349
+ /* @__PURE__ */ jsx("span", {
350
+ className: "clarify-ui-menu-icon flex shrink-0 rounded-(--clarify-theme-tokens-radius-md) border border-(--clarify-theme-tokens-colors-border) p-1.5 dark:border-white/10",
351
+ children: /* @__PURE__ */ jsx(FileText, { className: "h-4 w-4" })
352
+ }),
353
+ /* @__PURE__ */ jsxs("span", {
354
+ className: "flex min-w-0 flex-1 flex-col px-1",
355
+ children: [/* @__PURE__ */ jsxs("span", {
356
+ className: "clarify-ui-menu-title flex items-center gap-1",
357
+ children: [viewLabel, /* @__PURE__ */ jsx(ExternalLink, { className: "clarify-ui-menu-icon h-3 w-3" })]
358
+ }), /* @__PURE__ */ jsx("span", {
359
+ className: "clarify-ui-menu-description truncate",
360
+ children: viewDescription
361
+ })]
362
+ }),
363
+ /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) opacity-0" })
364
+ ]
365
+ }) }),
366
+ actions.slice(1).map((action) => {
367
+ const Icon = action.icon;
368
+ const isCopied = copied === action.key;
369
+ return /* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsxs("button", {
370
+ type: "button",
371
+ onClick: action.run,
372
+ className: "clarify-content-actions-item clarify-ui-menu-item group flex w-full items-center gap-2 rounded-(--clarify-theme-tokens-radius-lg) px-1.5 py-1.5 text-left transition",
373
+ children: [
374
+ /* @__PURE__ */ jsx("span", {
375
+ className: "clarify-ui-menu-icon flex shrink-0 rounded-(--clarify-theme-tokens-radius-md) border border-(--clarify-theme-tokens-colors-border) p-1.5 dark:border-white/10",
376
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" })
377
+ }),
378
+ /* @__PURE__ */ jsxs("span", {
379
+ className: "flex min-w-0 flex-1 flex-col px-1",
380
+ children: [/* @__PURE__ */ jsx("span", {
381
+ className: "clarify-ui-menu-title",
382
+ children: isCopied ? action.copiedLabel ?? action.label : action.label
383
+ }), /* @__PURE__ */ jsx("span", {
384
+ className: "clarify-ui-menu-description truncate",
385
+ children: action.description
386
+ })]
387
+ }),
388
+ /* @__PURE__ */ jsx(Check, { className: `h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) transition ${isCopied ? "opacity-100" : "opacity-0"}` })
389
+ ]
390
+ }) }, action.key);
391
+ }),
392
+ /* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsxs("button", {
393
+ type: "button",
394
+ onClick: llmsAction.run,
395
+ className: "clarify-content-actions-item clarify-ui-menu-item group flex w-full items-center gap-2 rounded-(--clarify-theme-tokens-radius-lg) px-1.5 py-1.5 text-left transition",
396
+ children: [
397
+ /* @__PURE__ */ jsx("span", {
398
+ className: "clarify-ui-menu-icon flex shrink-0 rounded-(--clarify-theme-tokens-radius-md) border border-(--clarify-theme-tokens-colors-border) p-1.5 dark:border-white/10",
399
+ children: /* @__PURE__ */ jsx(FileText, { className: "h-4 w-4" })
400
+ }),
401
+ /* @__PURE__ */ jsxs("span", {
402
+ className: "flex min-w-0 flex-1 flex-col px-1",
403
+ children: [/* @__PURE__ */ jsx("span", {
404
+ className: "clarify-ui-menu-title",
405
+ children: copied === llmsAction.key ? llmsAction.copiedLabel ?? llmsAction.label : llmsAction.label
406
+ }), /* @__PURE__ */ jsx("span", {
407
+ className: "clarify-ui-menu-description truncate",
408
+ children: llmsAction.description
409
+ })]
410
+ }),
411
+ /* @__PURE__ */ jsx(Check, { className: `h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) transition ${copied === llmsAction.key ? "opacity-100" : "opacity-0"}` })
412
+ ]
413
+ }) }, llmsAction.key)
414
+ ]
415
+ })]
416
+ })
483
417
  });
484
418
  }
485
- function CopyButton(arg0) {
486
- const { code } = arg0;
487
- const t = useBuiltInText();
488
- const [copyCount, setCopyCount] = useState(0);
489
- const copied = copyCount > 0;
419
+ //#endregion
420
+ //#region source/theme/ThemeProvider.tsx
421
+ var ThemeContext = createContext(null);
422
+ var storageKey = "clarify:theme";
423
+ function getSystemTheme() {
424
+ if (typeof window === "undefined") return "light";
425
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
426
+ }
427
+ function getStoredTheme() {
428
+ if (typeof window === "undefined") return "system";
429
+ try {
430
+ const storedTheme = window.localStorage.getItem(storageKey);
431
+ return storedTheme === "light" || storedTheme === "dark" || storedTheme === "system" ? storedTheme : "system";
432
+ } catch {
433
+ return "system";
434
+ }
435
+ }
436
+ function storeTheme(theme) {
437
+ if (typeof window === "undefined") return;
438
+ try {
439
+ window.localStorage.setItem(storageKey, theme);
440
+ } catch {}
441
+ }
442
+ function applyTheme(resolvedTheme) {
443
+ if (typeof document === "undefined") return;
444
+ document.documentElement.classList.toggle("dark", resolvedTheme === "dark");
445
+ document.documentElement.style.colorScheme = resolvedTheme;
446
+ }
447
+ function ThemeProvider(arg0) {
448
+ const { children } = arg0;
449
+ const [theme, setThemeState] = useState(() => getStoredTheme());
450
+ const [systemTheme, setSystemTheme] = useState(() => getSystemTheme());
451
+ const resolvedTheme = theme === "system" ? systemTheme : theme;
490
452
  useEffect(() => {
491
- if (copyCount === 0) return void 0;
492
- const timeout = window.setTimeout(() => setCopyCount(0), 1e3);
493
- return () => window.clearTimeout(timeout);
494
- }, [copyCount]);
495
- if (!code) return null;
496
- return /* @__PURE__ */ jsxs("button", {
497
- type: "button",
498
- className: clsx("clarify-code-copy group/button absolute top-3.5 right-4 overflow-hidden rounded-full py-1 pr-3 pl-2 text-2xs font-medium opacity-0 backdrop-blur-sm transition group-hover:opacity-100 focus:opacity-100", copied ? "bg-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-primary)_12%,transparent)] ring-1 ring-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-primary)_24%,transparent)] ring-inset" : "bg-white/5 hover:bg-white/7.5 dark:bg-white/2.5 dark:hover:bg-white/5"),
499
- onClick: () => {
500
- window.navigator.clipboard.writeText(code).then(() => {
501
- setCopyCount((count) => count + 1);
502
- });
503
- },
504
- children: [/* @__PURE__ */ jsxs("span", {
505
- "aria-hidden": copied,
506
- className: clsx("pointer-events-none flex items-center gap-0.5 text-zinc-400 transition duration-300", copied && "-translate-y-1.5 opacity-0"),
507
- children: [/* @__PURE__ */ jsx(ClipboardIcon$1, { className: "h-5 w-5 fill-zinc-500/20 stroke-zinc-500 transition-colors group-hover/button:stroke-zinc-400" }), t("actions.copy")]
508
- }), /* @__PURE__ */ jsx("span", {
509
- "aria-hidden": !copied,
510
- className: clsx("pointer-events-none absolute inset-0 flex items-center justify-center text-[var(--clarify-theme-tokens-colors-primary)] transition duration-300", !copied && "translate-y-1.5 opacity-0"),
511
- children: t("actions.copied")
512
- })]
453
+ applyTheme(resolvedTheme);
454
+ }, [resolvedTheme]);
455
+ useEffect(() => {
456
+ if (typeof window === "undefined") return;
457
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
458
+ function updateSystemTheme() {
459
+ setSystemTheme(mediaQuery.matches ? "dark" : "light");
460
+ }
461
+ updateSystemTheme();
462
+ mediaQuery.addEventListener("change", updateSystemTheme);
463
+ return () => mediaQuery.removeEventListener("change", updateSystemTheme);
464
+ }, []);
465
+ const value = useMemo(() => ({
466
+ theme,
467
+ resolvedTheme,
468
+ setTheme(nextTheme) {
469
+ setThemeState(nextTheme);
470
+ storeTheme(nextTheme);
471
+ }
472
+ }), [resolvedTheme, theme]);
473
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, {
474
+ value,
475
+ children
513
476
  });
514
477
  }
515
- function CodePanelHeader(arg0) {
516
- const { tag, label } = arg0;
517
- if (!tag && !label) return null;
518
- return /* @__PURE__ */ jsxs("div", {
519
- className: "clarify-code-panel-header flex h-9 items-center gap-2 border-y border-t-transparent border-b-white/7.5 bg-zinc-900 px-4 dark:border-b-white/5 dark:bg-white/1",
520
- children: [
521
- tag ? /* @__PURE__ */ jsx("span", {
522
- className: "font-mono text-[0.625rem]/6 font-semibold text-[var(--clarify-theme-tokens-colors-primary)]",
523
- children: tag
524
- }) : null,
525
- tag && label ? /* @__PURE__ */ jsx("span", { className: "h-0.5 w-0.5 rounded-full bg-zinc-500" }) : null,
526
- label ? /* @__PURE__ */ jsx("span", {
527
- className: "font-mono text-xs text-zinc-400",
528
- children: label
529
- }) : null
530
- ]
531
- });
478
+ function useTheme() {
479
+ const context = useContext(ThemeContext);
480
+ if (!context) throw new Error("[clarify] useTheme must be used within ThemeProvider");
481
+ return context;
532
482
  }
533
- function CodePanel(arg0) {
534
- const { children } = arg0;
535
- let { tag, label, code } = arg0;
536
- const child = Children.only(children);
537
- if (isValidElement(child)) {
538
- const props = child.props;
539
- tag = props.tag ?? tag;
540
- label = props.label ?? label;
541
- code = props.code ?? code ?? getNodeText(props.children);
542
- }
543
- const copyText = code ?? getNodeText(children);
544
- return /* @__PURE__ */ jsxs("div", {
545
- className: "clarify-code-panel group dark:bg-white/2.5",
546
- children: [/* @__PURE__ */ jsx(CodePanelHeader, {
547
- tag,
548
- label
549
- }), /* @__PURE__ */ jsxs("div", {
550
- className: "relative",
551
- children: [/* @__PURE__ */ jsx("pre", {
552
- className: "clarify-code-pre overflow-x-auto p-4 text-xs text-white",
553
- children
554
- }), /* @__PURE__ */ jsx(CopyButton, { code: copyText })]
483
+ //#endregion
484
+ //#region source/theme/ThemeToggle.tsx
485
+ function SunIcon(props) {
486
+ return /* @__PURE__ */ jsxs("svg", {
487
+ viewBox: "0 0 20 20",
488
+ fill: "none",
489
+ "aria-hidden": "true",
490
+ ...props,
491
+ children: [/* @__PURE__ */ jsx("path", { d: "M12.5 10a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Z" }), /* @__PURE__ */ jsx("path", {
492
+ strokeLinecap: "round",
493
+ d: "M10 5.5v-1M13.182 6.818l.707-.707M14.5 10h1M13.182 13.182l.707.707M10 15.5v-1M6.11 13.889l.708-.707M4.5 10h1M6.11 6.111l.708.707"
555
494
  })]
556
495
  });
557
496
  }
558
- function CodeGroupHeader(arg0) {
559
- const { title, children, selectedIndex } = arg0;
497
+ function MoonIcon(props) {
498
+ return /* @__PURE__ */ jsx("svg", {
499
+ viewBox: "0 0 20 20",
500
+ fill: "none",
501
+ "aria-hidden": "true",
502
+ ...props,
503
+ children: /* @__PURE__ */ jsx("path", { d: "M15.224 11.724a5.5 5.5 0 0 1-6.949-6.949 5.5 5.5 0 1 0 6.949 6.949Z" })
504
+ });
505
+ }
506
+ function ThemeToggle() {
507
+ const { resolvedTheme, setTheme } = useTheme();
560
508
  const t = useBuiltInText();
561
- const hasTabs = Children.count(children) > 1;
562
- if (!title && !hasTabs) return null;
563
- return /* @__PURE__ */ jsxs("div", {
564
- className: "clarify-code-group-header flex min-h-[calc(--spacing(12)+1px)] flex-wrap items-start gap-x-4 border-b border-zinc-700 bg-zinc-800 px-4 dark:border-zinc-800 dark:bg-transparent",
565
- children: [title ? /* @__PURE__ */ jsx("h3", {
566
- className: "mr-auto pt-3 text-xs font-semibold text-white",
567
- children: title
568
- }) : null, hasTabs ? /* @__PURE__ */ jsx(TabList, {
569
- className: "clarify-code-tabs -mb-px flex gap-4 text-xs font-medium",
570
- children: Children.map(children, (child, childIndex) => /* @__PURE__ */ jsx(Tab, {
571
- className: clsx("clarify-code-tab border-b py-3 transition data-selected:not-data-focus:outline-hidden", childIndex === selectedIndex ? "border-[var(--clarify-theme-tokens-colors-primary)] text-[var(--clarify-theme-tokens-colors-primary)]" : "border-transparent text-zinc-400 hover:text-zinc-300"),
572
- children: getPanelTitle({
573
- ...isValidElement(child) ? child.props : {},
574
- fallbackTitle: t("actions.code")
575
- })
576
- }))
577
- }) : null]
509
+ const otherTheme = resolvedTheme === "dark" ? "light" : "dark";
510
+ return /* @__PURE__ */ jsxs("button", {
511
+ type: "button",
512
+ className: "clarify-theme-toggle relative flex size-8 items-center justify-center rounded-(--clarify-theme-tokens-radius-md) transition hover:bg-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-foreground)_5%,transparent)] dark:hover:bg-white/5",
513
+ "aria-label": otherTheme === "dark" ? t("theme.switchToDark") : t("theme.switchToLight"),
514
+ onClick: () => setTheme(otherTheme),
515
+ children: [
516
+ /* @__PURE__ */ jsx("span", { className: "absolute size-12 pointer-fine:hidden" }),
517
+ /* @__PURE__ */ jsx(SunIcon, { className: "h-5 w-5 stroke-(--clarify-theme-tokens-colors-foreground) dark:hidden" }),
518
+ /* @__PURE__ */ jsx(MoonIcon, { className: "hidden h-5 w-5 stroke-white dark:block" })
519
+ ]
578
520
  });
579
521
  }
580
- function CodeGroupPanels(arg0) {
581
- const { children, ...props } = arg0;
582
- if (Children.count(children) > 1) return /* @__PURE__ */ jsx(TabPanels, { children: Children.map(children, (child) => /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(CodePanel, {
583
- ...props,
584
- children: child
585
- }) })) });
586
- return /* @__PURE__ */ jsx(CodePanel, {
587
- ...props,
588
- children
522
+ //#endregion
523
+ //#region source/utils/path.ts
524
+ function normalizeRoutePath(path) {
525
+ const [pathname, suffix = ""] = path.split(/([?#].*)/, 2);
526
+ return `${pathname.replace(/^\/+/, "/").replace(/\/+$/, "") || "/"}${suffix}`;
527
+ }
528
+ function isSameRoutePath(a, b) {
529
+ if (!a || !b) return false;
530
+ return normalizeRoutePath(a) === normalizeRoutePath(b);
531
+ }
532
+ //#endregion
533
+ //#region source/utils/lucide.ts
534
+ /**
535
+ * Registry of all Lucide icon components keyed by their PascalCase export name.
536
+ *
537
+ * Access icons via index lookup (e.g. `lucideIconRegistry[name]`) so React
538
+ * tooling does not mistake the access for a component created during render.
539
+ */
540
+ var lucideIconRegistry = LucideIcons;
541
+ function toPascalCase(value) {
542
+ return value.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join("");
543
+ }
544
+ /**
545
+ * Resolve an icon name into the matching Lucide registry key.
546
+ *
547
+ * Accepts both the exact PascalCase export name (e.g. `ArrowRight`) and
548
+ * kebab/space/snake variants (e.g. `arrow-right`), returning `undefined`
549
+ * when no matching icon exists.
550
+ */
551
+ function resolveLucideIconName(name) {
552
+ if (!name) return void 0;
553
+ if (lucideIconRegistry[name]) return name;
554
+ const pascalName = toPascalCase(name);
555
+ return lucideIconRegistry[pascalName] ? pascalName : void 0;
556
+ }
557
+ //#endregion
558
+ //#region source/shell/icons.tsx
559
+ function NavigationIcon(arg0) {
560
+ const { name, className } = arg0;
561
+ if (!name) return null;
562
+ const iconName = resolveLucideIconName(name);
563
+ if (!iconName) return null;
564
+ const Icon = lucideIconRegistry[iconName];
565
+ if (!Icon) return null;
566
+ return /* @__PURE__ */ jsx(Icon, {
567
+ className: clsx("shrink-0 stroke-current", className),
568
+ "aria-hidden": "true"
589
569
  });
590
570
  }
591
- function usePreventLayoutShift() {
592
- const positionRef = useRef(null);
593
- const rafRef = useRef(void 0);
571
+ //#endregion
572
+ //#region source/utils/remToPx.ts
573
+ function remToPx(remValue) {
574
+ return remValue * (typeof window === "undefined" ? 16 : Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize));
575
+ }
576
+ //#endregion
577
+ //#region source/app/SectionProvider.tsx
578
+ function createSectionStore(sections) {
579
+ return createStore()((set) => ({
580
+ sections,
581
+ visibleSections: [],
582
+ setVisibleSections: (visibleSections) => set((state) => state.visibleSections.join() === visibleSections.join() ? {} : { visibleSections }),
583
+ registerHeading: ({ id, ref, offsetRem }) => set((state) => ({ sections: state.sections.map((section) => section.id === id ? {
584
+ ...section,
585
+ headingRef: ref,
586
+ offsetRem
587
+ } : section) }))
588
+ }));
589
+ }
590
+ function useVisibleSections(sectionStore) {
591
+ const setVisibleSections = useStore(sectionStore, (state) => state.setVisibleSections);
592
+ const sections = useStore(sectionStore, (state) => state.sections);
594
593
  useEffect(() => {
594
+ function checkVisibleSections() {
595
+ const { innerHeight, scrollY } = window;
596
+ const viewportTop = scrollY;
597
+ const viewportBottom = scrollY + innerHeight;
598
+ const newVisibleSections = [];
599
+ for (let sectionIndex = 0; sectionIndex < sections.length; sectionIndex += 1) {
600
+ const { id, headingRef, offsetRem = 0 } = sections[sectionIndex];
601
+ if (!headingRef?.current) continue;
602
+ const offset = remToPx(offsetRem);
603
+ const top = headingRef.current.getBoundingClientRect().top + scrollY;
604
+ if (sectionIndex === 0 && top - offset > viewportTop) newVisibleSections.push("_top");
605
+ if ((sections[sectionIndex + 1]?.headingRef?.current?.getBoundingClientRect().top ?? Infinity) + scrollY > viewportTop && top < viewportBottom) newVisibleSections.push(id);
606
+ }
607
+ setVisibleSections(newVisibleSections);
608
+ }
609
+ const raf = window.requestAnimationFrame(() => checkVisibleSections());
610
+ window.addEventListener("scroll", checkVisibleSections, { passive: true });
611
+ window.addEventListener("resize", checkVisibleSections);
595
612
  return () => {
596
- if (typeof rafRef.current !== "undefined") window.cancelAnimationFrame(rafRef.current);
613
+ window.cancelAnimationFrame(raf);
614
+ window.removeEventListener("scroll", checkVisibleSections);
615
+ window.removeEventListener("resize", checkVisibleSections);
597
616
  };
598
- }, []);
599
- return {
600
- positionRef,
601
- preventLayoutShift(callback) {
602
- if (!positionRef.current) return;
603
- const initialTop = positionRef.current.getBoundingClientRect().top;
604
- callback();
605
- rafRef.current = window.requestAnimationFrame(() => {
606
- const newTop = positionRef.current?.getBoundingClientRect().top ?? initialTop;
607
- window.scrollBy(0, newTop - initialTop);
608
- });
609
- }
610
- };
611
- }
612
- var usePreferredLanguageStore = create()((set) => ({
613
- preferredLanguages: [],
614
- addPreferredLanguage: (language) => set((state) => ({ preferredLanguages: [...state.preferredLanguages.filter((preferredLanguage) => preferredLanguage !== language), language] }))
615
- }));
616
- function useTabGroupProps(availableLanguages) {
617
- const { preferredLanguages, addPreferredLanguage } = usePreferredLanguageStore();
618
- const [selectedIndex, setSelectedIndex] = useState(0);
619
- const activeLanguage = [...availableLanguages].sort((a, z) => preferredLanguages.indexOf(z) - preferredLanguages.indexOf(a))[0];
620
- const languageIndex = availableLanguages.indexOf(activeLanguage);
621
- const newSelectedIndex = languageIndex === -1 ? selectedIndex : languageIndex;
622
- if (newSelectedIndex !== selectedIndex) setSelectedIndex(newSelectedIndex);
623
- const { positionRef, preventLayoutShift } = usePreventLayoutShift();
624
- return {
625
- as: "div",
626
- ref: positionRef,
627
- selectedIndex,
628
- onChange: (nextSelectedIndex) => {
629
- preventLayoutShift(() => addPreferredLanguage(availableLanguages[nextSelectedIndex]));
630
- }
631
- };
617
+ }, [setVisibleSections, sections]);
632
618
  }
633
- var CodeGroupContext = createContext(false);
634
- function CodeGroup(arg0) {
635
- const { children, title, ...props } = arg0;
636
- const t = useBuiltInText();
637
- const tabGroupProps = useTabGroupProps(Children.map(children, (child) => getPanelTitle({
638
- ...isValidElement(child) ? child.props : {},
639
- fallbackTitle: t("actions.code")
640
- })) ?? []);
641
- const hasTabs = Children.count(children) > 1;
642
- const containerClassName = "clarify-code-group my-6 overflow-hidden rounded-2xl bg-zinc-900 shadow-md dark:ring-1 dark:ring-white/10";
643
- const header = /* @__PURE__ */ jsx(CodeGroupHeader, {
644
- title,
645
- selectedIndex: tabGroupProps.selectedIndex,
619
+ var SectionStoreContext = createContext(null);
620
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
621
+ function SectionProvider(arg0) {
622
+ const { sections, children } = arg0;
623
+ const [sectionStore] = useState(() => createSectionStore(sections));
624
+ useVisibleSections(sectionStore);
625
+ useIsomorphicLayoutEffect(() => {
626
+ sectionStore.setState((state) => ({
627
+ sections: sections.map((section) => {
628
+ const registeredSection = state.sections.find((item) => item.id === section.id);
629
+ return {
630
+ ...section,
631
+ headingRef: registeredSection?.headingRef,
632
+ offsetRem: registeredSection?.offsetRem ?? section.offsetRem
633
+ };
634
+ }),
635
+ visibleSections: []
636
+ }));
637
+ }, [sectionStore, sections]);
638
+ return /* @__PURE__ */ jsx(SectionStoreContext.Provider, {
639
+ value: sectionStore,
646
640
  children
647
641
  });
648
- const panels = /* @__PURE__ */ jsx(CodeGroupPanels, {
642
+ }
643
+ function useSectionStore(selector) {
644
+ const store = useContext(SectionStoreContext);
645
+ if (!store) throw new Error("[clarify] useSectionStore must be used within SectionProvider");
646
+ return useStore(store, selector);
647
+ }
648
+ //#endregion
649
+ //#region source/components/Button.tsx
650
+ function ArrowIcon(props) {
651
+ return /* @__PURE__ */ jsx("svg", {
652
+ viewBox: "0 0 20 20",
653
+ fill: "none",
654
+ "aria-hidden": "true",
649
655
  ...props,
650
- children
651
- });
652
- return /* @__PURE__ */ jsx(CodeGroupContext.Provider, {
653
- value: true,
654
- children: hasTabs ? /* @__PURE__ */ jsx(TabGroup, {
655
- ...tabGroupProps,
656
- className: containerClassName,
657
- children: /* @__PURE__ */ jsxs("div", {
658
- className: "not-prose",
659
- children: [header, panels]
660
- })
661
- }) : /* @__PURE__ */ jsx("div", {
662
- className: containerClassName,
663
- children: /* @__PURE__ */ jsxs("div", {
664
- className: "not-prose",
665
- children: [header, panels]
666
- })
656
+ children: /* @__PURE__ */ jsx("path", {
657
+ stroke: "currentColor",
658
+ strokeLinecap: "round",
659
+ strokeLinejoin: "round",
660
+ d: "m11.5 6.5 3 3.5m0 0-3 3.5m3-3.5h-9"
667
661
  })
668
662
  });
669
663
  }
670
- function Code(arg0) {
671
- const { children, ...props } = arg0;
672
- if (useContext(CodeGroupContext) && typeof children === "string") return /* @__PURE__ */ jsx("code", {
664
+ var buttonVariantStyles = {
665
+ primary: "rounded-full bg-(--clarify-theme-tokens-colors-foreground) px-3 py-1 text-white hover:opacity-80 dark:bg-(--clarify-theme-tokens-colors-primary)/10 dark:text-(--clarify-theme-tokens-colors-primary) dark:ring-1 dark:ring-inset dark:ring-(--clarify-theme-tokens-colors-primary)/20 dark:hover:opacity-80",
666
+ secondary: "rounded-full bg-(--clarify-theme-tokens-colors-code-background) px-3 py-1 text-(--clarify-theme-tokens-colors-foreground) hover:opacity-80 dark:bg-zinc-800/40 dark:text-zinc-400 dark:ring-1 dark:ring-inset dark:ring-zinc-800 dark:hover:bg-zinc-800 dark:hover:text-zinc-300",
667
+ filled: "rounded-full bg-(--clarify-theme-tokens-colors-foreground) px-3 py-1 text-white hover:opacity-80 dark:bg-(--clarify-theme-tokens-colors-primary) dark:hover:opacity-80",
668
+ outline: "rounded-full px-3 py-1 text-(--clarify-theme-tokens-colors-muted) ring-1 ring-inset ring-(--clarify-theme-tokens-colors-border) hover:bg-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-foreground)_2.5%,transparent)] hover:text-(--clarify-theme-tokens-colors-foreground) dark:text-zinc-400 dark:ring-white/10 dark:hover:bg-white/5 dark:hover:text-white",
669
+ text: "text-(--clarify-theme-tokens-colors-primary) hover:opacity-80 dark:text-(--clarify-theme-tokens-colors-primary) dark:hover:opacity-80"
670
+ };
671
+ function Button(arg0) {
672
+ const { variant = "primary", className, children, arrow, ...props } = arg0;
673
+ const classes = clsx("clarify-button inline-flex justify-center gap-0.5 overflow-hidden text-sm font-medium transition", buttonVariantStyles[variant], className);
674
+ const arrowIcon = /* @__PURE__ */ jsx(ArrowIcon, { className: clsx("mt-0.5 h-5 w-5", variant === "text" && "relative top-px", arrow === "left" && "-ml-1 rotate-180", arrow === "right" && "-mr-1") });
675
+ const inner = /* @__PURE__ */ jsxs(Fragment$1, { children: [
676
+ arrow === "left" ? arrowIcon : null,
677
+ children,
678
+ arrow === "right" ? arrowIcon : null
679
+ ] });
680
+ if (typeof props.href === "undefined") return /* @__PURE__ */ jsx("button", {
681
+ className: classes,
673
682
  ...props,
674
- dangerouslySetInnerHTML: { __html: children }
683
+ children: inner
675
684
  });
676
- return /* @__PURE__ */ jsx("code", {
685
+ return /* @__PURE__ */ jsx("a", {
686
+ className: classes,
677
687
  ...props,
678
- children
688
+ children: inner
679
689
  });
680
690
  }
681
- function Pre(arg0) {
682
- const { children, ...props } = arg0;
683
- if (useContext(CodeGroupContext)) return children;
684
- return /* @__PURE__ */ jsx(CodeGroup, {
691
+ //#endregion
692
+ //#region source/components/Callout.tsx
693
+ var calloutStyles = {
694
+ info: {
695
+ container: "border-sky-500/20 bg-sky-50/50 text-sky-950 dark:border-sky-400/30 dark:bg-sky-400/5 dark:text-sky-100",
696
+ icon: "text-sky-600 dark:text-sky-400",
697
+ title: "text-sky-900 dark:text-sky-100",
698
+ Icon: Info
699
+ },
700
+ note: {
701
+ container: "border-zinc-500/20 bg-zinc-50 text-zinc-900 dark:border-white/10 dark:bg-white/5 dark:text-zinc-200",
702
+ icon: "text-zinc-500 dark:text-zinc-400",
703
+ title: "text-zinc-900 dark:text-white",
704
+ Icon: Info
705
+ },
706
+ tip: {
707
+ container: "border-emerald-500/20 bg-emerald-50/50 text-emerald-950 dark:border-emerald-400/30 dark:bg-emerald-400/5 dark:text-emerald-100",
708
+ icon: "text-emerald-600 dark:text-emerald-400",
709
+ title: "text-emerald-900 dark:text-emerald-100",
710
+ Icon: Lightbulb
711
+ },
712
+ warning: {
713
+ container: "border-amber-500/20 bg-amber-50/70 text-amber-950 dark:border-amber-400/30 dark:bg-amber-400/5 dark:text-amber-100",
714
+ icon: "text-amber-600 dark:text-amber-400",
715
+ title: "text-amber-900 dark:text-amber-100",
716
+ Icon: AlertTriangle
717
+ },
718
+ danger: {
719
+ container: "border-rose-500/20 bg-rose-50/70 text-rose-950 dark:border-rose-400/30 dark:bg-rose-400/5 dark:text-rose-100",
720
+ icon: "text-rose-600 dark:text-rose-400",
721
+ title: "text-rose-900 dark:text-rose-100",
722
+ Icon: XCircle
723
+ },
724
+ success: {
725
+ container: "border-emerald-500/20 bg-emerald-50/50 text-emerald-950 dark:border-emerald-400/30 dark:bg-emerald-400/5 dark:text-emerald-100",
726
+ icon: "text-emerald-600 dark:text-emerald-400",
727
+ title: "text-emerald-900 dark:text-emerald-100",
728
+ Icon: CheckCircle2
729
+ }
730
+ };
731
+ var defaultTitleKeys = {
732
+ info: "callout.info",
733
+ note: "callout.note",
734
+ tip: "callout.tip",
735
+ warning: "callout.warning",
736
+ danger: "callout.danger",
737
+ success: "callout.success"
738
+ };
739
+ function Callout(arg0) {
740
+ const { children, type = "info", title, icon = true, className, ...props } = arg0;
741
+ const t = useBuiltInText();
742
+ const style = calloutStyles[type];
743
+ const Icon = style.Icon;
744
+ const resolvedTitle = title === void 0 ? t(defaultTitleKeys[type]) : title;
745
+ return /* @__PURE__ */ jsxs("div", {
746
+ className: clsx("clarify-callout my-6 flex gap-3 rounded-(--clarify-theme-tokens-radius-xl) border p-4 text-sm/6", style.container, className),
685
747
  ...props,
686
- children
748
+ children: [icon ? /* @__PURE__ */ jsx(Icon, {
749
+ className: clsx("mt-1 size-4 flex-none", style.icon),
750
+ "aria-hidden": "true"
751
+ }) : null, /* @__PURE__ */ jsxs("div", {
752
+ className: "min-w-0 flex-1 *:first:mt-0 *:last:mb-0",
753
+ children: [resolvedTitle ? /* @__PURE__ */ jsx("p", {
754
+ className: clsx("mb-1 font-semibold", style.title),
755
+ children: resolvedTitle
756
+ }) : null, /* @__PURE__ */ jsx("div", {
757
+ className: "*:first:mt-0 *:last:mb-0",
758
+ children
759
+ })]
760
+ })]
687
761
  });
688
762
  }
689
763
  //#endregion
690
- //#region source/components/Feedback.tsx
691
- function CheckIcon$1(props) {
692
- return /* @__PURE__ */ jsxs("svg", {
693
- viewBox: "0 0 20 20",
694
- "aria-hidden": "true",
695
- ...props,
696
- children: [/* @__PURE__ */ jsx("circle", {
697
- cx: "10",
698
- cy: "10",
699
- r: "10",
700
- strokeWidth: "0"
701
- }), /* @__PURE__ */ jsx("path", {
702
- fill: "none",
703
- strokeLinecap: "round",
704
- strokeLinejoin: "round",
705
- strokeWidth: "1.5",
706
- d: "m6.75 10.813 2.438 2.437c1.218-4.469 4.062-6.5 4.062-6.5"
707
- })]
764
+ //#region source/components/Card.tsx
765
+ function CardIcon(arg0) {
766
+ const { name } = arg0;
767
+ if (!name) return null;
768
+ const iconName = resolveLucideIconName(name);
769
+ if (!iconName) return null;
770
+ const Icon = lucideIconRegistry[iconName];
771
+ if (!Icon) return null;
772
+ return /* @__PURE__ */ jsx("span", {
773
+ className: "flex size-9 flex-none items-center justify-center rounded-(--clarify-theme-tokens-radius-lg) bg-(--clarify-ui-accent-background) text-(--clarify-ui-accent-text) ring-1 ring-(--clarify-ui-accent-border)",
774
+ children: /* @__PURE__ */ jsx(Icon, {
775
+ className: "size-5",
776
+ "aria-hidden": "true"
777
+ })
708
778
  });
709
779
  }
710
- function FeedbackButton(props) {
711
- return /* @__PURE__ */ jsx("button", {
712
- type: "submit",
713
- className: "clarify-feedback-button px-3 text-sm font-medium text-zinc-600 transition hover:bg-zinc-900/2.5 hover:text-zinc-900 dark:text-zinc-400 dark:hover:bg-white/5 dark:hover:text-white",
714
- ...props
780
+ var cardGroupColumnStyles = {
781
+ 1: "grid-cols-1",
782
+ 2: "grid-cols-1 sm:grid-cols-2",
783
+ 3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
784
+ 4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4"
785
+ };
786
+ function CardGroup(arg0) {
787
+ const { children, cols = 2, className } = arg0;
788
+ return /* @__PURE__ */ jsx("div", {
789
+ className: clsx("not-prose my-10 grid gap-4", cardGroupColumnStyles[cols], className),
790
+ children
715
791
  });
716
792
  }
717
- var FeedbackForm = forwardRef(function FeedbackForm(arg0, ref) {
718
- const { onSubmit, className, ...props } = arg0;
719
- const t = useBuiltInText();
720
- return /* @__PURE__ */ jsxs("form", {
721
- ...props,
722
- ref,
723
- onSubmit,
724
- className: clsx(className, "clarify-feedback-form absolute inset-0 flex items-center justify-center gap-6 md:justify-start"),
725
- children: [/* @__PURE__ */ jsx("p", {
726
- className: "text-sm text-zinc-600 dark:text-zinc-400",
727
- children: t("feedback.prompt")
728
- }), /* @__PURE__ */ jsxs("div", {
729
- className: "clarify-feedback-actions group grid h-8 grid-cols-[1fr_1px_1fr] overflow-hidden rounded-full border border-zinc-900/10 dark:border-white/10",
730
- children: [
731
- /* @__PURE__ */ jsx(FeedbackButton, {
732
- "data-response": "yes",
733
- children: t("feedback.yes")
734
- }),
735
- /* @__PURE__ */ jsx("div", { className: "bg-zinc-900/10 dark:bg-white/10" }),
736
- /* @__PURE__ */ jsx(FeedbackButton, {
737
- "data-response": "no",
738
- children: t("feedback.no")
739
- })
740
- ]
793
+ function Card(arg0) {
794
+ const { title, icon, href, children, className, ...props } = arg0;
795
+ const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
796
+ className: "flex items-start gap-4",
797
+ children: [/* @__PURE__ */ jsx(CardIcon, { name: icon }), /* @__PURE__ */ jsxs("div", {
798
+ className: "min-w-0 flex-1",
799
+ children: [/* @__PURE__ */ jsx("h3", {
800
+ className: "m-0 text-base font-semibold text-(--clarify-theme-tokens-colors-foreground) dark:text-white",
801
+ children: title
802
+ }), children ? /* @__PURE__ */ jsx("div", {
803
+ className: "mt-2 text-sm/6 text-(--clarify-theme-tokens-colors-muted) dark:text-zinc-400 *:m-0",
804
+ children
805
+ }) : null]
741
806
  })]
807
+ }), href ? /* @__PURE__ */ jsx("span", {
808
+ className: "absolute inset-0 rounded-(--clarify-theme-tokens-radius-xl)",
809
+ "aria-hidden": "true"
810
+ }) : null] });
811
+ const classes = clsx("group relative block rounded-(--clarify-theme-tokens-radius-xl) border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface) p-5 shadow-(--clarify-ui-accent-glow) transition hover:border-(--clarify-ui-accent-border) hover:shadow-md dark:bg-zinc-900/50", className);
812
+ if (!href) return /* @__PURE__ */ jsx("div", {
813
+ className: classes,
814
+ children: content
742
815
  });
743
- });
744
- var FeedbackThanks = forwardRef(function FeedbackThanks(arg0, ref) {
745
- const { className, ...props } = arg0;
746
- const t = useBuiltInText();
747
- return /* @__PURE__ */ jsx("div", {
816
+ if (href.startsWith("/") && !href.startsWith("//")) return /* @__PURE__ */ jsx(Link, {
817
+ to: href,
818
+ className: classes,
748
819
  ...props,
749
- ref,
750
- className: clsx(className, "clarify-feedback-thanks absolute inset-0 flex justify-center md:justify-start"),
751
- children: /* @__PURE__ */ jsxs("div", {
752
- className: "flex items-center gap-3 rounded-full bg-(--clarify-ui-accent-background) py-1 pr-3 pl-1.5 text-sm text-(--clarify-ui-accent-text) ring-1 ring-(--clarify-ui-accent-border) ring-inset",
753
- children: [/* @__PURE__ */ jsx(CheckIcon$1, { className: "h-5 w-5 flex-none fill-(--clarify-ui-accent-text) stroke-white dark:fill-(--clarify-ui-accent-background) dark:stroke-(--clarify-ui-accent-text)" }), t("feedback.thanks")]
754
- })
755
- });
756
- });
757
- function Feedback() {
758
- const [submitted, setSubmitted] = useState(false);
759
- function onSubmit(event) {
760
- event.preventDefault();
761
- setSubmitted(true);
762
- }
763
- return /* @__PURE__ */ jsxs("div", {
764
- className: "clarify-feedback relative h-8",
765
- children: [/* @__PURE__ */ jsx(Transition, {
766
- show: !submitted,
767
- children: /* @__PURE__ */ jsx(FeedbackForm, {
768
- className: "duration-300 data-closed:opacity-0 data-leave:pointer-events-none",
769
- onSubmit
770
- })
771
- }), /* @__PURE__ */ jsx(Transition, {
772
- show: submitted,
773
- children: /* @__PURE__ */ jsx(FeedbackThanks, { className: "delay-150 duration-300 data-closed:opacity-0" })
774
- })]
820
+ children: content
775
821
  });
776
- }
777
- //#endregion
778
- //#region source/components/patterns.tsx
779
- function GridPattern(arg0) {
780
- const { width, height, x, y, squares, ...props } = arg0;
781
- const patternId = useId();
782
- return /* @__PURE__ */ jsxs("svg", {
783
- "aria-hidden": "true",
822
+ return /* @__PURE__ */ jsx("a", {
823
+ href,
824
+ className: classes,
784
825
  ...props,
785
- children: [
786
- /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("pattern", {
787
- id: patternId,
788
- width,
789
- height,
790
- patternUnits: "userSpaceOnUse",
791
- x,
792
- y,
793
- children: /* @__PURE__ */ jsx("path", {
794
- d: `M.5 ${height}V.5H${width}`,
795
- fill: "none"
796
- })
797
- }) }),
798
- /* @__PURE__ */ jsx("rect", {
799
- width: "100%",
800
- height: "100%",
801
- strokeWidth: 0,
802
- fill: `url(#${patternId})`
803
- }),
804
- squares ? /* @__PURE__ */ jsx("svg", {
805
- x,
806
- y,
807
- className: "overflow-visible",
808
- children: squares.map(([squareX, squareY]) => /* @__PURE__ */ jsx("rect", {
809
- width: width + 1,
810
- height: height + 1,
811
- x: squareX * width,
812
- y: squareY * height,
813
- strokeWidth: "0"
814
- }, `${squareX}-${squareY}`))
815
- }) : null
816
- ]
817
- });
818
- }
819
- function HeroPattern() {
820
- return /* @__PURE__ */ jsx("div", {
821
- className: "absolute inset-0 -z-10 mx-0 max-w-none overflow-hidden",
822
- children: /* @__PURE__ */ jsxs("div", {
823
- className: "absolute top-0 left-1/2 -ml-152 h-100 w-325 dark:mask-[linear-gradient(white,transparent)]",
824
- children: [/* @__PURE__ */ jsx("div", {
825
- className: "absolute inset-0 bg-[linear-gradient(to_right,var(--clarify-theme-tokens-colors-primary),var(--clarify-theme-tokens-colors-accent))] opacity-35 mask-[radial-gradient(farthest-side_at_top,white,transparent)] dark:opacity-55",
826
- children: /* @__PURE__ */ jsx(GridPattern, {
827
- width: 72,
828
- height: 56,
829
- x: -12,
830
- y: 4,
831
- squares: [
832
- [4, 3],
833
- [2, 1],
834
- [7, 3],
835
- [10, 6]
836
- ],
837
- className: "absolute inset-x-0 inset-y-[-50%] h-[200%] w-full -skew-y-18 fill-black/40 stroke-black/50 mix-blend-overlay dark:fill-white/2.5 dark:stroke-white/5"
838
- })
839
- }), /* @__PURE__ */ jsx("svg", {
840
- viewBox: "0 0 1113 440",
841
- "aria-hidden": "true",
842
- className: "absolute top-0 left-1/2 -ml-76 w-278.25 fill-white blur-[26px] dark:hidden",
843
- children: /* @__PURE__ */ jsx("path", { d: "M.016 439.5s-9.5-300 434-300S882.516 20 882.516 20V0h230.004v439.5H.016Z" })
844
- })]
845
- })
826
+ children: content
846
827
  });
847
828
  }
848
829
  //#endregion
849
- //#region source/components/PageFooter.tsx
850
- function resolveLocalizedText$1(text, locale, fallbackLocale) {
851
- if (typeof text === "string") return text;
852
- return (locale ? text[locale] : void 0) ?? (fallbackLocale ? text[fallbackLocale] : void 0) ?? Object.values(text)[0] ?? "";
853
- }
854
- function isExternalHref$1(href) {
855
- return /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith("//");
856
- }
857
- function localeForPath$1(config, pathname) {
858
- const i18n = config.i18n;
859
- if (!i18n) return void 0;
860
- const firstSegment = pathname.split("/").filter(Boolean)[0];
861
- return i18n.locales.find((locale) => locale.code === firstSegment)?.code ?? i18n.defaultLocale;
862
- }
863
- function localizeHref$1(href, config, locale) {
864
- if (!locale || !config.i18n || isExternalHref$1(href) || href.startsWith("#")) return href;
865
- if (locale === config.i18n.defaultLocale) return href;
866
- const cleanHref = href === "/" ? "" : href.replace(/^\/+/, "");
867
- return `/${locale}${cleanHref ? `/${cleanHref}` : ""}`;
830
+ //#region source/components/Code.tsx
831
+ var languageNames = {
832
+ js: "JavaScript",
833
+ ts: "TypeScript",
834
+ jsx: "React JSX",
835
+ tsx: "React TSX",
836
+ javascript: "JavaScript",
837
+ typescript: "TypeScript",
838
+ php: "PHP",
839
+ python: "Python",
840
+ ruby: "Ruby",
841
+ go: "Go",
842
+ bash: "Shell",
843
+ sh: "Shell",
844
+ shell: "Shell",
845
+ json: "JSON"
846
+ };
847
+ function getPanelTitle(arg0) {
848
+ const { title, language, fallbackTitle = "Code" } = arg0;
849
+ if (title) return title;
850
+ if (language && language in languageNames) return languageNames[language];
851
+ return fallbackTitle;
868
852
  }
869
- function FooterLink(arg0) {
870
- const { link, locale, config } = arg0;
871
- const external = link.external ?? isExternalHref$1(link.href);
872
- return /* @__PURE__ */ jsx("a", {
873
- href: external ? link.href : localizeHref$1(link.href, config, locale),
874
- target: external ? "_blank" : void 0,
875
- rel: external ? "noreferrer" : void 0,
876
- className: "clarify-footer-link no-underline transition",
877
- children: resolveLocalizedText$1(link.label, locale, config.i18n?.defaultLocale)
878
- });
853
+ function getNodeText(node) {
854
+ if (typeof node === "string" || typeof node === "number") return String(node);
855
+ if (Array.isArray(node)) return node.map(getNodeText).join("");
856
+ if (isValidElement(node)) return getNodeText(node.props.children);
857
+ return "";
879
858
  }
880
- function SocialLink(arg0) {
881
- const { name, href } = arg0;
882
- return /* @__PURE__ */ jsx("a", {
883
- href,
884
- target: "_blank",
885
- rel: "noreferrer",
886
- className: "clarify-footer-social capitalize no-underline transition",
887
- children: name
888
- });
889
- }
890
- function PageFooter() {
891
- const config = useClarifyConfig();
892
- const locale = localeForPath$1(config, useLocation().pathname);
893
- const footer = config.footer;
894
- const links = footer?.links ?? [];
895
- const socials = Object.entries(footer?.socials ?? {});
896
- const copyright = footer?.copyright ? resolveLocalizedText$1(footer.copyright, locale, config.i18n?.defaultLocale) : void 0;
897
- const hasCustomFooter = Boolean(copyright || links.length > 0 || socials.length > 0);
898
- return /* @__PURE__ */ jsxs("footer", {
899
- className: clsx("clarify-page-footer mx-auto mt-16 flex w-full max-w-(--clarify-theme-layout-max-width) flex-col items-end gap-4 border-t border-(--clarify-theme-tokens-colors-border) px-4 py-8 sm:px-6 lg:mt-24 lg:px-5 dark:border-white/10", hasCustomFooter && "sm:flex-row sm:items-center sm:justify-between"),
900
- children: [hasCustomFooter ? /* @__PURE__ */ jsxs("div", {
901
- className: "clarify-footer-content flex flex-col gap-3 text-right sm:text-left",
902
- children: [copyright ? /* @__PURE__ */ jsx("p", {
903
- className: "clarify-footer-copyright m-0",
904
- children: copyright
905
- }) : null, links.length > 0 || socials.length > 0 ? /* @__PURE__ */ jsxs("div", {
906
- className: "clarify-footer-links flex flex-wrap justify-end gap-x-4 gap-y-2 sm:justify-start",
907
- children: [links.map((link) => /* @__PURE__ */ jsx(FooterLink, {
908
- link,
909
- locale,
910
- config
911
- }, `${link.href}-${resolveLocalizedText$1(link.label, locale, config.i18n?.defaultLocale)}`)), socials.map(([name, href]) => /* @__PURE__ */ jsx(SocialLink, {
912
- name,
913
- href
914
- }, name))]
915
- }) : null]
916
- }) : null, /* @__PURE__ */ jsx("div", {
917
- className: "clarify-footer-brand flex justify-end",
918
- children: /* @__PURE__ */ jsx(BuiltWithClarify, {})
859
+ function ClipboardIcon$1(props) {
860
+ return /* @__PURE__ */ jsxs("svg", {
861
+ viewBox: "0 0 20 20",
862
+ "aria-hidden": "true",
863
+ ...props,
864
+ children: [/* @__PURE__ */ jsx("path", {
865
+ strokeWidth: "0",
866
+ d: "M5.5 13.5v-5a2 2 0 0 1 2-2l.447-.894A2 2 0 0 1 9.737 4.5h.527a2 2 0 0 1 1.789 1.106l.447.894a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2Z"
867
+ }), /* @__PURE__ */ jsx("path", {
868
+ fill: "none",
869
+ strokeLinejoin: "round",
870
+ d: "M12.5 6.5a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2m5 0-.447-.894a2 2 0 0 0-1.79-1.106h-.527a2 2 0 0 0-1.789 1.106L7.5 6.5m5 0-1 1h-3l-1-1"
919
871
  })]
920
872
  });
921
873
  }
922
- //#endregion
923
- //#region source/utils/path.ts
924
- function normalizeRoutePath(path) {
925
- const [pathname, suffix = ""] = path.split(/([?#].*)/, 2);
926
- return `${pathname.replace(/^\/+/, "/").replace(/\/+$/, "") || "/"}${suffix}`;
927
- }
928
- function isSameRoutePath(a, b) {
929
- if (!a || !b) return false;
930
- return normalizeRoutePath(a) === normalizeRoutePath(b);
931
- }
932
- //#endregion
933
- //#region source/components/PageNavigation.tsx
934
- function flattenNavigation(nodes) {
935
- return nodes.flatMap((node) => node.children?.length ? flattenNavigation(node.children) : [node]);
936
- }
937
- function PageNavigation(arg0) {
938
- const { navigation, currentRoute } = arg0;
874
+ function CopyButton(arg0) {
875
+ const { code } = arg0;
939
876
  const t = useBuiltInText();
940
- if (!currentRoute) return null;
941
- const pageRoutes = flattenNavigation(navigation);
942
- const currentIndex = pageRoutes.findIndex((route) => isSameRoutePath(route.path, currentRoute.path));
943
- if (currentIndex === -1) return null;
944
- const previous = pageRoutes[currentIndex - 1];
945
- const next = pageRoutes[currentIndex + 1];
946
- if (!previous && !next) return null;
947
- return /* @__PURE__ */ jsxs("nav", {
948
- className: "clarify-page-navigation mt-6 grid gap-3 @3xl:grid-cols-2",
949
- "aria-label": t("navigation.previousNext"),
950
- children: [/* @__PURE__ */ jsx(PageNavigationLink, {
951
- direction: "previous",
952
- route: previous
953
- }), /* @__PURE__ */ jsx(PageNavigationLink, {
954
- direction: "next",
955
- route: next
877
+ const [copyCount, setCopyCount] = useState(0);
878
+ const copied = copyCount > 0;
879
+ useEffect(() => {
880
+ if (copyCount === 0) return void 0;
881
+ const timeout = window.setTimeout(() => setCopyCount(0), 1e3);
882
+ return () => window.clearTimeout(timeout);
883
+ }, [copyCount]);
884
+ if (!code) return null;
885
+ return /* @__PURE__ */ jsxs("button", {
886
+ type: "button",
887
+ className: clsx("clarify-code-copy group/button absolute top-3.5 right-4 overflow-hidden rounded-full py-1 pr-3 pl-2 text-2xs font-medium opacity-0 backdrop-blur-sm transition group-hover:opacity-100 focus:opacity-100", copied ? "bg-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-primary)_12%,transparent)] ring-1 ring-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-primary)_24%,transparent)] ring-inset" : "bg-white/5 hover:bg-white/7.5 dark:bg-white/2.5 dark:hover:bg-white/5"),
888
+ onClick: () => {
889
+ copyTextToClipboard(code).then((ok) => {
890
+ if (ok) setCopyCount((count) => count + 1);
891
+ });
892
+ },
893
+ children: [/* @__PURE__ */ jsxs("span", {
894
+ "aria-hidden": copied,
895
+ className: clsx("pointer-events-none flex items-center gap-0.5 text-zinc-400 transition duration-300", copied && "-translate-y-1.5 opacity-0"),
896
+ children: [/* @__PURE__ */ jsx(ClipboardIcon$1, { className: "h-5 w-5 fill-zinc-500/20 stroke-zinc-500 transition-colors group-hover/button:stroke-zinc-400" }), t("actions.copy")]
897
+ }), /* @__PURE__ */ jsx("span", {
898
+ "aria-hidden": !copied,
899
+ className: clsx("pointer-events-none absolute inset-0 flex items-center justify-center text-(--clarify-theme-tokens-colors-primary) transition duration-300", !copied && "translate-y-1.5 opacity-0"),
900
+ children: t("actions.copied")
956
901
  })]
957
902
  });
958
903
  }
959
- function PageNavigationLink(arg0) {
960
- const { direction, route } = arg0;
961
- const t = useBuiltInText();
962
- if (!route) return /* @__PURE__ */ jsx("div", { className: "hidden @3xl:block" });
963
- const isNext = direction === "next";
964
- return /* @__PURE__ */ jsxs(Link, {
965
- to: normalizeRoutePath(route.path),
966
- className: clsx("group flex min-w-0 items-center gap-3 rounded-lg border border-(--clarify-theme-tokens-colors-border) px-4 py-3 no-underline transition hover:border-(--clarify-theme-tokens-colors-primary) hover:bg-(--clarify-theme-tokens-colors-surface) dark:border-white/10 dark:hover:border-(--clarify-theme-tokens-colors-primary) dark:hover:bg-white/2.5", isNext && "@3xl:justify-end @3xl:text-right"),
904
+ function CodePanelHeader(arg0) {
905
+ const { tag, label } = arg0;
906
+ if (!tag && !label) return null;
907
+ return /* @__PURE__ */ jsxs("div", {
908
+ className: "clarify-code-panel-header flex h-9 items-center gap-2 border-y border-t-transparent border-b-white/7.5 bg-zinc-900 px-4 dark:border-b-white/5 dark:bg-white/1",
967
909
  children: [
968
- !isNext ? /* @__PURE__ */ jsx(ChevronLeft, { className: "h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-muted) transition group-hover:text-(--clarify-theme-tokens-colors-primary)" }) : null,
969
- /* @__PURE__ */ jsxs("span", {
970
- className: "min-w-0 flex-1",
971
- children: [/* @__PURE__ */ jsx("span", {
972
- className: "block text-[0.6875rem] font-medium uppercase tracking-wide text-(--clarify-theme-tokens-colors-muted)",
973
- children: isNext ? t("navigation.next") : t("navigation.previous")
974
- }), /* @__PURE__ */ jsx("span", {
975
- className: "mt-0.5 block truncate text-[0.8125rem] font-semibold text-(--clarify-theme-tokens-colors-foreground) dark:text-white",
976
- children: route.title
977
- })]
978
- }),
979
- isNext ? /* @__PURE__ */ jsx(ChevronRight, { className: "h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-muted) transition group-hover:text-(--clarify-theme-tokens-colors-primary)" }) : null
910
+ tag ? /* @__PURE__ */ jsx("span", {
911
+ className: "clarify-code-panel-tag font-semibold text-(--clarify-theme-tokens-colors-primary)",
912
+ children: tag
913
+ }) : null,
914
+ tag && label ? /* @__PURE__ */ jsx("span", { className: "h-0.5 w-0.5 rounded-full bg-zinc-500" }) : null,
915
+ label ? /* @__PURE__ */ jsx("span", {
916
+ className: "text-xs text-zinc-400",
917
+ children: label
918
+ }) : null
980
919
  ]
981
920
  });
982
921
  }
983
- //#endregion
984
- //#region source/components/SiteLogo.tsx
985
- function SiteLogo(arg0) {
986
- const { logo, className } = arg0;
987
- if (!logo) return null;
988
- if (typeof logo === "string") return /* @__PURE__ */ jsx("img", {
989
- src: logo,
990
- alt: "",
991
- className: clsx("clarify-logo", className)
992
- });
993
- const lightLogo = logo.light ?? logo.dark;
994
- const darkLogo = logo.dark ?? logo.light;
995
- if (!lightLogo || !darkLogo) return null;
996
- if (lightLogo === darkLogo) return /* @__PURE__ */ jsx("img", {
997
- src: lightLogo,
998
- alt: "",
999
- className: clsx("clarify-logo", className)
922
+ function CodePanel(arg0) {
923
+ const { children } = arg0;
924
+ let { tag, label, code } = arg0;
925
+ const child = Children.only(children);
926
+ if (isValidElement(child)) {
927
+ const props = child.props;
928
+ tag = props.tag ?? tag;
929
+ label = props.label ?? label;
930
+ code = props.code ?? code ?? getNodeText(props.children);
931
+ }
932
+ const copyText = code ?? getNodeText(children);
933
+ return /* @__PURE__ */ jsxs("div", {
934
+ className: "clarify-code-panel group dark:bg-white/2.5",
935
+ children: [/* @__PURE__ */ jsx(CodePanelHeader, {
936
+ tag,
937
+ label
938
+ }), /* @__PURE__ */ jsxs("div", {
939
+ className: "relative",
940
+ children: [/* @__PURE__ */ jsx("pre", {
941
+ className: "clarify-code-pre overflow-x-auto p-4 text-xs text-white",
942
+ children
943
+ }), /* @__PURE__ */ jsx(CopyButton, { code: copyText })]
944
+ })]
1000
945
  });
1001
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("img", {
1002
- src: lightLogo,
1003
- alt: "",
1004
- className: clsx("clarify-logo clarify-logo-light", className, "dark:hidden")
1005
- }), /* @__PURE__ */ jsx("img", {
1006
- src: darkLogo,
1007
- alt: "",
1008
- className: clsx("clarify-logo clarify-logo-dark", className, "hidden dark:block")
1009
- })] });
1010
- }
1011
- //#endregion
1012
- //#region source/components/ThemeProvider.tsx
1013
- var ThemeContext = createContext(null);
1014
- var storageKey = "clarify:theme";
1015
- function getSystemTheme() {
1016
- if (typeof window === "undefined") return "light";
1017
- return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
1018
946
  }
1019
- function getStoredTheme() {
1020
- if (typeof window === "undefined") return "system";
1021
- const storedTheme = window.localStorage.getItem(storageKey);
1022
- return storedTheme === "light" || storedTheme === "dark" || storedTheme === "system" ? storedTheme : "system";
947
+ function CodeGroupHeader(arg0) {
948
+ const { title, children, selectedIndex } = arg0;
949
+ const t = useBuiltInText();
950
+ const hasTabs = Children.count(children) > 1;
951
+ if (!title && !hasTabs) return null;
952
+ return /* @__PURE__ */ jsxs("div", {
953
+ className: "clarify-code-group-header flex min-h-[calc(--spacing(12)+1px)] flex-wrap items-start gap-x-4 border-b border-zinc-700 bg-zinc-800 px-4 dark:border-zinc-800 dark:bg-transparent",
954
+ children: [title ? /* @__PURE__ */ jsx("h3", {
955
+ className: "mr-auto pt-3 text-xs font-semibold text-white",
956
+ children: title
957
+ }) : null, hasTabs ? /* @__PURE__ */ jsx(TabList, {
958
+ className: "clarify-code-tabs -mb-px flex gap-4 text-xs font-medium",
959
+ children: Children.map(children, (child, childIndex) => /* @__PURE__ */ jsx(Tab, {
960
+ className: clsx("clarify-code-tab border-b py-3 transition data-selected:not-data-focus:outline-hidden", childIndex === selectedIndex ? "border-(--clarify-theme-tokens-colors-primary) text-(--clarify-theme-tokens-colors-primary)" : "border-transparent text-zinc-400 hover:text-zinc-300"),
961
+ children: getPanelTitle({
962
+ ...isValidElement(child) ? child.props : {},
963
+ fallbackTitle: t("actions.code")
964
+ })
965
+ }))
966
+ }) : null]
967
+ });
1023
968
  }
1024
- function applyTheme(resolvedTheme) {
1025
- if (typeof document === "undefined") return;
1026
- document.documentElement.classList.toggle("dark", resolvedTheme === "dark");
1027
- document.documentElement.style.colorScheme = resolvedTheme;
969
+ function CodeGroupPanels(arg0) {
970
+ const { children, ...props } = arg0;
971
+ if (Children.count(children) > 1) return /* @__PURE__ */ jsx(TabPanels, { children: Children.map(children, (child) => /* @__PURE__ */ jsx(TabPanel, { children: /* @__PURE__ */ jsx(CodePanel, {
972
+ ...props,
973
+ children: child
974
+ }) })) });
975
+ return /* @__PURE__ */ jsx(CodePanel, {
976
+ ...props,
977
+ children
978
+ });
1028
979
  }
1029
- function ThemeProvider(arg0) {
1030
- const { children } = arg0;
1031
- const [theme, setThemeState] = useState(() => getStoredTheme());
1032
- const [systemTheme, setSystemTheme] = useState(() => getSystemTheme());
1033
- const resolvedTheme = theme === "system" ? systemTheme : theme;
1034
- useEffect(() => {
1035
- applyTheme(resolvedTheme);
1036
- }, [resolvedTheme]);
980
+ function usePreventLayoutShift() {
981
+ const positionRef = useRef(null);
982
+ const rafRef = useRef(void 0);
1037
983
  useEffect(() => {
1038
- if (typeof window === "undefined") return;
1039
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
1040
- function updateSystemTheme() {
1041
- setSystemTheme(mediaQuery.matches ? "dark" : "light");
1042
- }
1043
- updateSystemTheme();
1044
- mediaQuery.addEventListener("change", updateSystemTheme);
1045
- return () => mediaQuery.removeEventListener("change", updateSystemTheme);
984
+ return () => {
985
+ if (typeof rafRef.current !== "undefined") window.cancelAnimationFrame(rafRef.current);
986
+ };
1046
987
  }, []);
1047
- const value = useMemo(() => ({
1048
- theme,
1049
- resolvedTheme,
1050
- setTheme(nextTheme) {
1051
- setThemeState(nextTheme);
1052
- if (typeof window !== "undefined") window.localStorage.setItem(storageKey, nextTheme);
988
+ return {
989
+ positionRef,
990
+ preventLayoutShift(callback) {
991
+ if (!positionRef.current) return;
992
+ const initialTop = positionRef.current.getBoundingClientRect().top;
993
+ callback();
994
+ rafRef.current = window.requestAnimationFrame(() => {
995
+ const newTop = positionRef.current?.getBoundingClientRect().top ?? initialTop;
996
+ window.scrollBy(0, newTop - initialTop);
997
+ });
1053
998
  }
1054
- }), [resolvedTheme, theme]);
1055
- return /* @__PURE__ */ jsx(ThemeContext.Provider, {
1056
- value,
999
+ };
1000
+ }
1001
+ var usePreferredLanguageStore = create()((set) => ({
1002
+ preferredLanguages: [],
1003
+ addPreferredLanguage: (language) => set((state) => ({ preferredLanguages: [...state.preferredLanguages.filter((preferredLanguage) => preferredLanguage !== language), language] }))
1004
+ }));
1005
+ function useTabGroupProps(availableLanguages) {
1006
+ const { preferredLanguages, addPreferredLanguage } = usePreferredLanguageStore();
1007
+ const [selectedIndex, setSelectedIndex] = useState(0);
1008
+ if (new Set(availableLanguages).size === availableLanguages.length) {
1009
+ const activeLanguage = [...availableLanguages].sort((a, z) => preferredLanguages.indexOf(z) - preferredLanguages.indexOf(a))[0];
1010
+ const languageIndex = availableLanguages.indexOf(activeLanguage);
1011
+ const newSelectedIndex = languageIndex === -1 ? selectedIndex : languageIndex;
1012
+ if (newSelectedIndex !== selectedIndex) setSelectedIndex(newSelectedIndex);
1013
+ }
1014
+ const { positionRef, preventLayoutShift } = usePreventLayoutShift();
1015
+ return {
1016
+ as: "div",
1017
+ ref: positionRef,
1018
+ selectedIndex,
1019
+ onChange: (nextSelectedIndex) => {
1020
+ setSelectedIndex(nextSelectedIndex);
1021
+ preventLayoutShift(() => addPreferredLanguage(availableLanguages[nextSelectedIndex]));
1022
+ }
1023
+ };
1024
+ }
1025
+ var CodeGroupContext = createContext(false);
1026
+ function CodeGroup(arg0) {
1027
+ const { children, title, ...props } = arg0;
1028
+ const t = useBuiltInText();
1029
+ const tabGroupProps = useTabGroupProps(Children.map(children, (child) => getPanelTitle({
1030
+ ...isValidElement(child) ? child.props : {},
1031
+ fallbackTitle: t("actions.code")
1032
+ })) ?? []);
1033
+ const hasTabs = Children.count(children) > 1;
1034
+ const containerClassName = "clarify-code-group my-6 overflow-hidden rounded-2xl bg-zinc-900 shadow-md dark:ring-1 dark:ring-white/10";
1035
+ const header = /* @__PURE__ */ jsx(CodeGroupHeader, {
1036
+ title,
1037
+ selectedIndex: tabGroupProps.selectedIndex,
1038
+ children
1039
+ });
1040
+ const panels = /* @__PURE__ */ jsx(CodeGroupPanels, {
1041
+ ...props,
1042
+ children
1043
+ });
1044
+ return /* @__PURE__ */ jsx(CodeGroupContext.Provider, {
1045
+ value: true,
1046
+ children: hasTabs ? /* @__PURE__ */ jsx(TabGroup, {
1047
+ ...tabGroupProps,
1048
+ className: containerClassName,
1049
+ children: /* @__PURE__ */ jsxs("div", {
1050
+ className: "not-prose",
1051
+ children: [header, panels]
1052
+ })
1053
+ }) : /* @__PURE__ */ jsx("div", {
1054
+ className: containerClassName,
1055
+ children: /* @__PURE__ */ jsxs("div", {
1056
+ className: "not-prose",
1057
+ children: [header, panels]
1058
+ })
1059
+ })
1060
+ });
1061
+ }
1062
+ function Code(arg0) {
1063
+ const { children, ...props } = arg0;
1064
+ if (useContext(CodeGroupContext) && typeof children === "string") return /* @__PURE__ */ jsx("code", {
1065
+ ...props,
1066
+ dangerouslySetInnerHTML: { __html: children }
1067
+ });
1068
+ return /* @__PURE__ */ jsx("code", {
1069
+ ...props,
1070
+ children
1071
+ });
1072
+ }
1073
+ function Pre(arg0) {
1074
+ const { children, ...props } = arg0;
1075
+ if (useContext(CodeGroupContext)) return children;
1076
+ return /* @__PURE__ */ jsx(CodeGroup, {
1077
+ ...props,
1057
1078
  children
1058
1079
  });
1059
1080
  }
1060
- function useTheme() {
1061
- const context = useContext(ThemeContext);
1062
- if (!context) throw new Error("[clarify] useTheme must be used within ThemeProvider");
1063
- return context;
1081
+ //#endregion
1082
+ //#region source/components/Collapse.tsx
1083
+ function Collapse(arg0) {
1084
+ const { children, title, summary, defaultOpen = false, className, ...props } = arg0;
1085
+ const [open, setOpen] = useState(defaultOpen);
1086
+ const contentRef = useRef(null);
1087
+ const [maxHeight, setMaxHeight] = useState("0px");
1088
+ const summaryLabel = title ?? summary ?? "Details";
1089
+ const contentId = useId();
1090
+ useLayoutEffect(() => {
1091
+ if (!contentRef.current) return;
1092
+ setMaxHeight(open ? `${contentRef.current.scrollHeight}px` : "0px");
1093
+ }, [open, children]);
1094
+ return /* @__PURE__ */ jsxs("div", {
1095
+ className: clsx("clarify-collapse my-6 overflow-hidden rounded-(--clarify-theme-tokens-radius-xl) border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface) shadow-sm dark:border-white/10 dark:bg-zinc-950", className),
1096
+ ...props,
1097
+ children: [/* @__PURE__ */ jsxs("button", {
1098
+ type: "button",
1099
+ className: "flex w-full cursor-pointer items-center justify-between gap-3 px-4 py-3 text-left text-sm font-semibold text-(--clarify-theme-tokens-colors-foreground) transition hover:bg-(--clarify-ui-hover-background) dark:text-white dark:hover:bg-white/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-(--clarify-theme-tokens-colors-primary) focus-visible:ring-offset-2 focus-visible:ring-offset-(--clarify-theme-tokens-colors-background) dark:focus-visible:ring-offset-zinc-950",
1100
+ "aria-expanded": open,
1101
+ "aria-controls": contentId,
1102
+ onClick: () => setOpen((value) => !value),
1103
+ children: [/* @__PURE__ */ jsx("span", { children: summaryLabel }), /* @__PURE__ */ jsx(ChevronDown, {
1104
+ className: clsx("h-4 w-4 text-(--clarify-theme-tokens-colors-muted) transition-transform duration-200", open && "rotate-180"),
1105
+ "aria-hidden": "true"
1106
+ })]
1107
+ }), /* @__PURE__ */ jsx("div", {
1108
+ id: contentId,
1109
+ className: "overflow-hidden border-t border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-background) transition-[max-height,opacity,transform] duration-200 ease-out dark:border-white/10 dark:bg-zinc-950/95",
1110
+ style: {
1111
+ maxHeight,
1112
+ willChange: "max-height, opacity, transform"
1113
+ },
1114
+ children: /* @__PURE__ */ jsx("div", {
1115
+ ref: contentRef,
1116
+ className: clsx("px-4 py-4 text-sm/6 text-(--clarify-theme-tokens-colors-foreground) transition-opacity duration-200 ease-out", open ? "opacity-100 translate-y-0" : "opacity-0 -translate-y-1"),
1117
+ children
1118
+ })
1119
+ })]
1120
+ });
1064
1121
  }
1065
1122
  //#endregion
1066
- //#region source/components/ThemeToggle.tsx
1067
- function SunIcon(props) {
1123
+ //#region source/components/Feedback.tsx
1124
+ function CheckIcon$1(props) {
1068
1125
  return /* @__PURE__ */ jsxs("svg", {
1069
1126
  viewBox: "0 0 20 20",
1070
- fill: "none",
1071
1127
  "aria-hidden": "true",
1072
1128
  ...props,
1073
- children: [/* @__PURE__ */ jsx("path", { d: "M12.5 10a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Z" }), /* @__PURE__ */ jsx("path", {
1129
+ children: [/* @__PURE__ */ jsx("circle", {
1130
+ cx: "10",
1131
+ cy: "10",
1132
+ r: "10",
1133
+ strokeWidth: "0"
1134
+ }), /* @__PURE__ */ jsx("path", {
1135
+ fill: "none",
1074
1136
  strokeLinecap: "round",
1075
- d: "M10 5.5v-1M13.182 6.818l.707-.707M14.5 10h1M13.182 13.182l.707.707M10 15.5v-1M6.11 13.889l.708-.707M4.5 10h1M6.11 6.111l.708.707"
1137
+ strokeLinejoin: "round",
1138
+ strokeWidth: "1.5",
1139
+ d: "m6.75 10.813 2.438 2.437c1.218-4.469 4.062-6.5 4.062-6.5"
1076
1140
  })]
1077
1141
  });
1078
1142
  }
1079
- function MoonIcon(props) {
1080
- return /* @__PURE__ */ jsx("svg", {
1081
- viewBox: "0 0 20 20",
1082
- fill: "none",
1083
- "aria-hidden": "true",
1084
- ...props,
1085
- children: /* @__PURE__ */ jsx("path", { d: "M15.224 11.724a5.5 5.5 0 0 1-6.949-6.949 5.5 5.5 0 1 0 6.949 6.949Z" })
1143
+ function FeedbackButton(props) {
1144
+ return /* @__PURE__ */ jsx("button", {
1145
+ type: "submit",
1146
+ className: "clarify-feedback-button px-3 text-sm font-medium text-zinc-600 transition hover:bg-zinc-900/2.5 hover:text-zinc-900 dark:text-zinc-400 dark:hover:bg-white/5 dark:hover:text-white",
1147
+ ...props
1086
1148
  });
1087
1149
  }
1088
- function ThemeToggle() {
1089
- const { resolvedTheme, setTheme } = useTheme();
1150
+ var FeedbackForm = forwardRef(function FeedbackForm(arg0, ref) {
1151
+ const { onSubmit, className, ...props } = arg0;
1090
1152
  const t = useBuiltInText();
1091
- const otherTheme = resolvedTheme === "dark" ? "light" : "dark";
1092
- return /* @__PURE__ */ jsxs("button", {
1093
- type: "button",
1094
- className: "clarify-theme-toggle relative flex size-8 items-center justify-center rounded-(--clarify-theme-tokens-radius-md) transition hover:bg-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-foreground)_5%,transparent)] dark:hover:bg-white/5",
1095
- "aria-label": otherTheme === "dark" ? t("theme.switchToDark") : t("theme.switchToLight"),
1096
- onClick: () => setTheme(otherTheme),
1097
- children: [
1098
- /* @__PURE__ */ jsx("span", { className: "absolute size-12 pointer-fine:hidden" }),
1099
- /* @__PURE__ */ jsx(SunIcon, { className: "h-5 w-5 stroke-(--clarify-theme-tokens-colors-foreground) dark:hidden" }),
1100
- /* @__PURE__ */ jsx(MoonIcon, { className: "hidden h-5 w-5 stroke-white dark:block" })
1101
- ]
1102
- });
1103
- }
1104
- //#endregion
1105
- //#region source/components/index.tsx
1106
- function ArrowIcon(props) {
1107
- return /* @__PURE__ */ jsx("svg", {
1108
- viewBox: "0 0 20 20",
1109
- fill: "none",
1110
- "aria-hidden": "true",
1153
+ return /* @__PURE__ */ jsxs("form", {
1111
1154
  ...props,
1112
- children: /* @__PURE__ */ jsx("path", {
1113
- stroke: "currentColor",
1114
- strokeLinecap: "round",
1115
- strokeLinejoin: "round",
1116
- d: "m11.5 6.5 3 3.5m0 0-3 3.5m3-3.5h-9"
1117
- })
1155
+ ref,
1156
+ onSubmit,
1157
+ className: clsx(className, "clarify-feedback-form absolute inset-0 flex items-center justify-center gap-6 md:justify-start"),
1158
+ children: [/* @__PURE__ */ jsx("p", {
1159
+ className: "text-sm text-zinc-600 dark:text-zinc-400",
1160
+ children: t("feedback.prompt")
1161
+ }), /* @__PURE__ */ jsxs("div", {
1162
+ className: "clarify-feedback-actions group grid h-8 grid-cols-[1fr_1px_1fr] overflow-hidden rounded-full border border-zinc-900/10 dark:border-white/10",
1163
+ children: [
1164
+ /* @__PURE__ */ jsx(FeedbackButton, {
1165
+ "data-response": "yes",
1166
+ children: t("feedback.yes")
1167
+ }),
1168
+ /* @__PURE__ */ jsx("div", { className: "bg-zinc-900/10 dark:bg-white/10" }),
1169
+ /* @__PURE__ */ jsx(FeedbackButton, {
1170
+ "data-response": "no",
1171
+ children: t("feedback.no")
1172
+ })
1173
+ ]
1174
+ })]
1118
1175
  });
1119
- }
1120
- var buttonVariantStyles = {
1121
- primary: "rounded-full bg-(--clarify-theme-tokens-colors-foreground) px-3 py-1 text-white hover:opacity-80 dark:bg-(--clarify-theme-tokens-colors-primary)/10 dark:text-(--clarify-theme-tokens-colors-primary) dark:ring-1 dark:ring-inset dark:ring-(--clarify-theme-tokens-colors-primary)/20 dark:hover:opacity-80",
1122
- secondary: "rounded-full bg-(--clarify-theme-tokens-colors-code-background) px-3 py-1 text-(--clarify-theme-tokens-colors-foreground) hover:opacity-80 dark:bg-zinc-800/40 dark:text-zinc-400 dark:ring-1 dark:ring-inset dark:ring-zinc-800 dark:hover:bg-zinc-800 dark:hover:text-zinc-300",
1123
- filled: "rounded-full bg-(--clarify-theme-tokens-colors-foreground) px-3 py-1 text-white hover:opacity-80 dark:bg-(--clarify-theme-tokens-colors-primary) dark:hover:opacity-80",
1124
- outline: "rounded-full px-3 py-1 text-(--clarify-theme-tokens-colors-muted) ring-1 ring-inset ring-(--clarify-theme-tokens-colors-border) hover:bg-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-foreground)_2.5%,transparent)] hover:text-(--clarify-theme-tokens-colors-foreground) dark:text-zinc-400 dark:ring-white/10 dark:hover:bg-white/5 dark:hover:text-white",
1125
- text: "text-(--clarify-theme-tokens-colors-primary) hover:opacity-80 dark:text-(--clarify-theme-tokens-colors-primary) dark:hover:opacity-80"
1126
- };
1127
- function Button(arg0) {
1128
- const { variant = "primary", className, children, arrow, ...props } = arg0;
1129
- const classes = clsx("clarify-button inline-flex justify-center gap-0.5 overflow-hidden text-sm font-medium transition", buttonVariantStyles[variant], className);
1130
- const arrowIcon = /* @__PURE__ */ jsx(ArrowIcon, { className: clsx("mt-0.5 h-5 w-5", variant === "text" && "relative top-px", arrow === "left" && "-ml-1 rotate-180", arrow === "right" && "-mr-1") });
1131
- const inner = /* @__PURE__ */ jsxs(Fragment$1, { children: [
1132
- arrow === "left" ? arrowIcon : null,
1133
- children,
1134
- arrow === "right" ? arrowIcon : null
1135
- ] });
1136
- if (typeof props.href === "undefined") return /* @__PURE__ */ jsx("button", {
1137
- className: classes,
1176
+ });
1177
+ var FeedbackThanks = forwardRef(function FeedbackThanks(arg0, ref) {
1178
+ const { className, ...props } = arg0;
1179
+ const t = useBuiltInText();
1180
+ return /* @__PURE__ */ jsx("div", {
1138
1181
  ...props,
1139
- children: inner
1182
+ ref,
1183
+ className: clsx(className, "clarify-feedback-thanks absolute inset-0 flex justify-center md:justify-start"),
1184
+ children: /* @__PURE__ */ jsxs("div", {
1185
+ className: "flex items-center gap-3 rounded-full bg-(--clarify-ui-accent-background) py-1 pr-3 pl-1.5 text-sm text-(--clarify-ui-accent-text) ring-1 ring-(--clarify-ui-accent-border) ring-inset",
1186
+ children: [/* @__PURE__ */ jsx(CheckIcon$1, { className: "h-5 w-5 flex-none fill-(--clarify-ui-accent-text) stroke-white dark:fill-(--clarify-ui-accent-background) dark:stroke-(--clarify-ui-accent-text)" }), t("feedback.thanks")]
1187
+ })
1140
1188
  });
1141
- return /* @__PURE__ */ jsx("a", {
1142
- className: classes,
1143
- ...props,
1144
- children: inner
1189
+ });
1190
+ function Feedback() {
1191
+ const [submitted, setSubmitted] = useState(false);
1192
+ function onSubmit(event) {
1193
+ event.preventDefault();
1194
+ setSubmitted(true);
1195
+ }
1196
+ return /* @__PURE__ */ jsxs("div", {
1197
+ className: "clarify-feedback relative h-8",
1198
+ children: [/* @__PURE__ */ jsx(Transition, {
1199
+ show: !submitted,
1200
+ children: /* @__PURE__ */ jsx(FeedbackForm, {
1201
+ className: "duration-300 data-closed:opacity-0 data-leave:pointer-events-none",
1202
+ onSubmit
1203
+ })
1204
+ }), /* @__PURE__ */ jsx(Transition, {
1205
+ show: submitted,
1206
+ children: /* @__PURE__ */ jsx(FeedbackThanks, { className: "delay-150 duration-300 data-closed:opacity-0" })
1207
+ })]
1145
1208
  });
1146
1209
  }
1210
+ //#endregion
1211
+ //#region source/components/Tag.tsx
1147
1212
  var tagVariantStyles = {
1148
1213
  small: "",
1149
1214
  medium: "rounded-lg px-1.5 ring-1 ring-inset"
@@ -1182,32 +1247,12 @@ function Tag(arg0) {
1182
1247
  const value = typeof children === "string" ? children.toUpperCase() : "";
1183
1248
  const resolvedColor = color ?? tagValueColorMap[value] ?? "emerald";
1184
1249
  return /* @__PURE__ */ jsx("span", {
1185
- className: clsx("clarify-tag font-mono text-[0.625rem]/6 font-bold", tagVariantStyles[variant], tagColorStyles[resolvedColor][variant]),
1250
+ className: clsx("clarify-tag font-bold", tagVariantStyles[variant], tagColorStyles[resolvedColor][variant]),
1186
1251
  children
1187
1252
  });
1188
1253
  }
1189
- function Logo(props) {
1190
- return /* @__PURE__ */ jsxs("svg", {
1191
- viewBox: "0 0 99 24",
1192
- "aria-hidden": "true",
1193
- ...props,
1194
- className: clsx("clarify-logo", props.className),
1195
- children: [/* @__PURE__ */ jsx("path", {
1196
- className: "fill-(--clarify-theme-tokens-colors-primary)",
1197
- d: "M16 8a5 5 0 0 0-5-5H5a5 5 0 0 0-5 5v13.927a1 1 0 0 0 1.623.782l3.684-2.93a4 4 0 0 1 2.49-.87H11a5 5 0 0 0 5-5V8Z"
1198
- }), /* @__PURE__ */ jsx("path", {
1199
- className: "fill-(--clarify-theme-tokens-colors-foreground) dark:fill-white",
1200
- d: "M26.538 18h2.654v-3.999h2.576c2.672 0 4.456-1.723 4.456-4.333V9.65c0-2.61-1.784-4.333-4.456-4.333h-5.23V18Zm4.58-10.582c1.52 0 2.416.8 2.416 2.241v.018c0 1.441-.896 2.25-2.417 2.25h-1.925V7.418h1.925ZM38.051 18h2.566v-5.414c0-1.371.923-2.206 2.382-2.206.396 0 .791.061 1.178.15V8.287a3.843 3.843 0 0 0-.958-.123c-1.257 0-2.136.615-2.443 1.661h-.159V8.323h-2.566V18Zm11.55.202c2.979 0 4.772-1.88 4.772-5.036v-.018c0-3.128-1.82-5.036-4.773-5.036-2.953 0-4.772 1.916-4.772 5.036v.018c0 3.146 1.793 5.036 4.772 5.036Zm0-2.013c-1.372 0-2.145-1.116-2.145-3.023v-.018c0-1.89.782-3.023 2.144-3.023 1.354 0 2.145 1.134 2.145 3.023v.018c0 1.907-.782 3.023-2.145 3.023Zm10.52 1.846c.492 0 .967-.053 1.283-.114v-1.907a6.057 6.057 0 0 1-.755.044c-.87 0-1.24-.387-1.24-1.257v-4.544h1.995V8.323H59.41V6.012h-2.592v2.311h-1.495v1.934h1.495v5.133c0 1.88.949 2.645 3.304 2.645Zm7.287.167c2.98 0 4.772-1.88 4.772-5.036v-.018c0-3.128-1.82-5.036-4.772-5.036-2.954 0-4.773 1.916-4.773 5.036v.018c0 3.146 1.793 5.036 4.773 5.036Zm0-2.013c-1.372 0-2.145-1.116-2.145-3.023v-.018c0-1.89.782-3.023 2.145-3.023 1.353 0 2.144 1.134 2.144 3.023v.018c0 1.907-.782 3.023-2.144 3.023Zm10.767 2.013c2.522 0 4.034-1.353 4.297-3.463l.01-.053h-2.374l-.017.036c-.229.966-.853 1.467-1.908 1.467-1.37 0-2.135-1.08-2.135-3.04v-.018c0-1.934.755-3.006 2.135-3.006 1.099 0 1.74.615 1.908 1.556l.008.017h2.391v-.026c-.228-2.162-1.749-3.56-4.315-3.56-3.033 0-4.738 1.837-4.738 5.019v.017c0 3.217 1.714 5.054 4.738 5.054Zm10.257 0c2.98 0 4.772-1.88 4.772-5.036v-.018c0-3.128-1.82-5.036-4.772-5.036-2.953 0-4.773 1.916-4.773 5.036v.018c0 3.146 1.793 5.036 4.773 5.036Zm0-2.013c-1.371 0-2.145-1.116-2.145-3.023v-.018c0-1.89.782-3.023 2.145-3.023 1.353 0 2.144 1.134 2.144 3.023v.018c0 1.907-.782 3.023-2.144 3.023ZM95.025 18h2.566V4.623h-2.566V18Z"
1201
- })]
1202
- });
1203
- }
1204
- function Prose(arg0) {
1205
- const { as, className, ...props } = arg0;
1206
- return /* @__PURE__ */ jsx(as ?? "div", {
1207
- className: clsx(className, "clarify-prose prose max-w-none dark:prose-invert", "[html_:where(&>*)]:w-full [html_:where(&>*)]:min-w-0 [html_:where(&>*)]:max-w-full"),
1208
- ...props
1209
- });
1210
- }
1254
+ //#endregion
1255
+ //#region source/components/Heading.tsx
1211
1256
  function AnchorIcon(props) {
1212
1257
  return /* @__PURE__ */ jsx("svg", {
1213
1258
  viewBox: "0 0 20 20",
@@ -1227,7 +1272,7 @@ function Eyebrow(arg0) {
1227
1272
  tag ? /* @__PURE__ */ jsx(Tag, { children: tag }) : null,
1228
1273
  tag && label ? /* @__PURE__ */ jsx("span", { className: "h-0.5 w-0.5 rounded-full bg-zinc-300 dark:bg-zinc-600" }) : null,
1229
1274
  label ? /* @__PURE__ */ jsx("span", {
1230
- className: "font-mono text-xs text-zinc-400",
1275
+ className: "text-xs text-zinc-400",
1231
1276
  children: label
1232
1277
  }) : null
1233
1278
  ]
@@ -1284,206 +1329,113 @@ function Heading(arg0) {
1284
1329
  }) : children
1285
1330
  })] });
1286
1331
  }
1287
- function DocShell(arg0) {
1288
- const { title, subtitle, children } = arg0;
1289
- return /* @__PURE__ */ jsx("main", {
1290
- className: "clarify-doc-shell min-h-screen bg-white px-6 py-10 text-zinc-900 dark:bg-zinc-950 dark:text-white md:px-10",
1291
- children: /* @__PURE__ */ jsxs("div", {
1292
- className: "mx-auto max-w-6xl",
1293
- children: [/* @__PURE__ */ jsxs("header", {
1294
- className: "mb-10",
1295
- children: [/* @__PURE__ */ jsx("h1", {
1296
- className: "text-3xl font-bold tracking-tight md:text-5xl",
1297
- children: title
1298
- }), subtitle ? /* @__PURE__ */ jsx("p", {
1299
- className: "mt-3 max-w-2xl text-zinc-600 dark:text-zinc-400",
1300
- children: subtitle
1301
- }) : null]
1302
- }), /* @__PURE__ */ jsx(Prose, { children })]
1303
- })
1304
- });
1305
- }
1306
- function ApiEndpointCard(arg0) {
1307
- const { method, path, description, id } = arg0;
1308
- return /* @__PURE__ */ jsxs("article", {
1309
- id,
1310
- className: "clarify-api-endpoint-card scroll-mt-20 rounded-2xl border border-zinc-900/10 bg-white p-5 shadow-sm dark:border-white/10 dark:bg-zinc-900",
1311
- children: [/* @__PURE__ */ jsxs("div", {
1312
- className: "flex items-center gap-3",
1313
- children: [/* @__PURE__ */ jsx(Tag, { children: method }), /* @__PURE__ */ jsx("code", {
1314
- className: "text-sm font-medium text-zinc-800 dark:text-zinc-200",
1315
- children: path
1316
- })]
1317
- }), description ? /* @__PURE__ */ jsx("p", {
1318
- className: "mt-3 text-sm text-zinc-600 dark:text-zinc-400",
1319
- children: description
1320
- }) : null]
1332
+ //#endregion
1333
+ //#region source/components/Logo.tsx
1334
+ function Logo(props) {
1335
+ return /* @__PURE__ */ jsxs("svg", {
1336
+ viewBox: "0 0 99 24",
1337
+ "aria-hidden": "true",
1338
+ ...props,
1339
+ className: clsx("clarify-logo", props.className),
1340
+ children: [/* @__PURE__ */ jsx("path", {
1341
+ className: "fill-(--clarify-theme-tokens-colors-primary)",
1342
+ d: "M16 8a5 5 0 0 0-5-5H5a5 5 0 0 0-5 5v13.927a1 1 0 0 0 1.623.782l3.684-2.93a4 4 0 0 1 2.49-.87H11a5 5 0 0 0 5-5V8Z"
1343
+ }), /* @__PURE__ */ jsx("path", {
1344
+ className: "fill-(--clarify-theme-tokens-colors-foreground) dark:fill-white",
1345
+ d: "M26.538 18h2.654v-3.999h2.576c2.672 0 4.456-1.723 4.456-4.333V9.65c0-2.61-1.784-4.333-4.456-4.333h-5.23V18Zm4.58-10.582c1.52 0 2.416.8 2.416 2.241v.018c0 1.441-.896 2.25-2.417 2.25h-1.925V7.418h1.925ZM38.051 18h2.566v-5.414c0-1.371.923-2.206 2.382-2.206.396 0 .791.061 1.178.15V8.287a3.843 3.843 0 0 0-.958-.123c-1.257 0-2.136.615-2.443 1.661h-.159V8.323h-2.566V18Zm11.55.202c2.979 0 4.772-1.88 4.772-5.036v-.018c0-3.128-1.82-5.036-4.773-5.036-2.953 0-4.772 1.916-4.772 5.036v.018c0 3.146 1.793 5.036 4.772 5.036Zm0-2.013c-1.372 0-2.145-1.116-2.145-3.023v-.018c0-1.89.782-3.023 2.144-3.023 1.354 0 2.145 1.134 2.145 3.023v.018c0 1.907-.782 3.023-2.145 3.023Zm10.52 1.846c.492 0 .967-.053 1.283-.114v-1.907a6.057 6.057 0 0 1-.755.044c-.87 0-1.24-.387-1.24-1.257v-4.544h1.995V8.323H59.41V6.012h-2.592v2.311h-1.495v1.934h1.495v5.133c0 1.88.949 2.645 3.304 2.645Zm7.287.167c2.98 0 4.772-1.88 4.772-5.036v-.018c0-3.128-1.82-5.036-4.772-5.036-2.954 0-4.773 1.916-4.773 5.036v.018c0 3.146 1.793 5.036 4.773 5.036Zm0-2.013c-1.372 0-2.145-1.116-2.145-3.023v-.018c0-1.89.782-3.023 2.145-3.023 1.353 0 2.144 1.134 2.144 3.023v.018c0 1.907-.782 3.023-2.144 3.023Zm10.767 2.013c2.522 0 4.034-1.353 4.297-3.463l.01-.053h-2.374l-.017.036c-.229.966-.853 1.467-1.908 1.467-1.37 0-2.135-1.08-2.135-3.04v-.018c0-1.934.755-3.006 2.135-3.006 1.099 0 1.74.615 1.908 1.556l.008.017h2.391v-.026c-.228-2.162-1.749-3.56-4.315-3.56-3.033 0-4.738 1.837-4.738 5.019v.017c0 3.217 1.714 5.054 4.738 5.054Zm10.257 0c2.98 0 4.772-1.88 4.772-5.036v-.018c0-3.128-1.82-5.036-4.772-5.036-2.953 0-4.773 1.916-4.773 5.036v.018c0 3.146 1.793 5.036 4.773 5.036Zm0-2.013c-1.371 0-2.145-1.116-2.145-3.023v-.018c0-1.89.782-3.023 2.145-3.023 1.353 0 2.144 1.134 2.144 3.023v.018c0 1.907-.782 3.023-2.144 3.023ZM95.025 18h2.566V4.623h-2.566V18Z"
1346
+ })]
1321
1347
  });
1322
1348
  }
1323
1349
  //#endregion
1324
- //#region source/shell/ContentActions.tsx
1325
- function resolveContentArtifactUrl(contentArtifactUrl, routePrefix = "/") {
1326
- if (!routePrefix || routePrefix === "/") return contentArtifactUrl;
1327
- return `/${routePrefix.replace(/^\/+|\/+$/g, "")}${contentArtifactUrl}`;
1328
- }
1329
- function getAbsoluteUrl(path) {
1330
- if (typeof window === "undefined") return path;
1331
- return new URL(path, window.location.href).href;
1332
- }
1333
- async function copyText(text) {
1334
- await navigator.clipboard.writeText(text);
1335
- }
1336
- function ContentActions(arg0) {
1337
- const { hasTabs = false, route, routePrefix } = arg0;
1338
- const t = useBuiltInText();
1339
- const [copied, setCopied] = useState("idle");
1340
- if (!route?.contentArtifactUrl) return null;
1341
- const contentArtifactUrl = resolveContentArtifactUrl(route.contentArtifactUrl, routePrefix);
1342
- const isOpenApi = route.kind === "openapi";
1343
- const replacements = { contentType: isOpenApi ? "OpenAPI" : "Markdown" };
1344
- const viewLabel = isOpenApi ? t("contentActions.viewOpenApi") : t("contentActions.viewMarkdown");
1345
- const viewDescription = isOpenApi ? t("contentActions.viewOpenApiDescription") : t("contentActions.viewMarkdownDescription");
1346
- function markCopied(state) {
1347
- setCopied(state);
1348
- window.setTimeout(() => setCopied("idle"), 1600);
1349
- }
1350
- async function handleCopyContent() {
1351
- await copyText(await (await fetch(contentArtifactUrl)).text());
1352
- markCopied("content");
1353
- }
1354
- async function handleCopyLink() {
1355
- await copyText(getAbsoluteUrl(contentArtifactUrl));
1356
- markCopied("link");
1357
- }
1358
- const actions = [{
1359
- key: "content",
1360
- label: t("contentActions.copyContent"),
1361
- description: t("contentActions.copyContentDescription", replacements),
1362
- icon: Copy,
1363
- run: handleCopyContent
1364
- }, {
1365
- key: "link",
1366
- label: t("contentActions.copyLink", replacements),
1367
- description: t("contentActions.copyLinkDescription", replacements),
1368
- icon: Link2,
1369
- run: handleCopyLink
1370
- }];
1371
- const primaryAction = actions[0];
1372
- const PrimaryIcon = copied === primaryAction.key ? Check : primaryAction.icon;
1350
+ //#region source/components/patterns.tsx
1351
+ function GridPattern(arg0) {
1352
+ const { width, height, x, y, squares, ...props } = arg0;
1353
+ const patternId = useId();
1354
+ return /* @__PURE__ */ jsxs("svg", {
1355
+ "aria-hidden": "true",
1356
+ ...props,
1357
+ children: [
1358
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("pattern", {
1359
+ id: patternId,
1360
+ width,
1361
+ height,
1362
+ patternUnits: "userSpaceOnUse",
1363
+ x,
1364
+ y,
1365
+ children: /* @__PURE__ */ jsx("path", {
1366
+ d: `M.5 ${height}V.5H${width}`,
1367
+ fill: "none"
1368
+ })
1369
+ }) }),
1370
+ /* @__PURE__ */ jsx("rect", {
1371
+ width: "100%",
1372
+ height: "100%",
1373
+ strokeWidth: 0,
1374
+ fill: `url(#${patternId})`
1375
+ }),
1376
+ squares ? /* @__PURE__ */ jsx("svg", {
1377
+ x,
1378
+ y,
1379
+ className: "overflow-visible",
1380
+ children: squares.map(([squareX, squareY]) => /* @__PURE__ */ jsx("rect", {
1381
+ width: width + 1,
1382
+ height: height + 1,
1383
+ x: squareX * width,
1384
+ y: squareY * height,
1385
+ strokeWidth: "0"
1386
+ }, `${squareX}-${squareY}`))
1387
+ }) : null
1388
+ ]
1389
+ });
1390
+ }
1391
+ function HeroPattern() {
1373
1392
  return /* @__PURE__ */ jsx("div", {
1374
- className: `clarify-content-actions sticky z-20 flex justify-end py-4 ${hasTabs ? "top-16 lg:top-30" : "top-16"}`,
1375
- children: /* @__PURE__ */ jsxs(Menu, {
1376
- as: "div",
1377
- className: "clarify-content-actions-menu relative inline-flex text-sm font-medium",
1378
- children: [/* @__PURE__ */ jsxs("div", {
1379
- className: "clarify-content-actions-group inline-flex overflow-hidden rounded-full border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface)/90 shadow-sm shadow-zinc-900/5 backdrop-blur dark:border-white/10 dark:bg-zinc-900/80 dark:shadow-none",
1380
- children: [/* @__PURE__ */ jsxs("button", {
1381
- type: "button",
1382
- onClick: primaryAction.run,
1383
- className: "clarify-content-actions-primary clarify-ui-control inline-flex h-8 items-center gap-1.5 px-3 transition",
1384
- children: [/* @__PURE__ */ jsx(PrimaryIcon, { className: "h-3.5 w-3.5" }), copied === primaryAction.key ? t("actions.copied") : primaryAction.label]
1385
- }), /* @__PURE__ */ jsx(MenuButton, {
1386
- className: "clarify-content-actions-trigger clarify-ui-control inline-flex h-8 w-8 items-center justify-center border-l border-(--clarify-theme-tokens-colors-border) transition dark:border-white/10",
1387
- "aria-label": t("contentActions.copyOptions"),
1388
- children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5" })
1389
- })]
1390
- }), /* @__PURE__ */ jsxs(MenuItems, {
1391
- anchor: "bottom end",
1392
- className: "clarify-content-actions-list clarify-ui-menu z-30 mt-2 w-(--clarify-ui-action-menu-width) origin-top-right rounded-(--clarify-theme-tokens-radius-xl) border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface) p-1.5 shadow-xl shadow-zinc-900/5 transition [--anchor-gap:--spacing(2)] focus:outline-none data-closed:scale-95 data-closed:opacity-0 dark:border-white/10 dark:bg-zinc-900 dark:shadow-none",
1393
- children: [
1394
- actions.slice(0, 1).map((action) => {
1395
- const Icon = action.icon;
1396
- const isCopied = copied === action.key;
1397
- return /* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsxs("button", {
1398
- type: "button",
1399
- onClick: action.run,
1400
- className: "clarify-content-actions-item clarify-ui-menu-item group flex w-full items-center gap-2 rounded-(--clarify-theme-tokens-radius-lg) px-1.5 py-1.5 text-left transition",
1401
- children: [
1402
- /* @__PURE__ */ jsx("span", {
1403
- className: "clarify-ui-menu-icon flex shrink-0 rounded-(--clarify-theme-tokens-radius-md) border border-(--clarify-theme-tokens-colors-border) p-1.5 dark:border-white/10",
1404
- children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" })
1405
- }),
1406
- /* @__PURE__ */ jsxs("span", {
1407
- className: "flex min-w-0 flex-1 flex-col px-1",
1408
- children: [/* @__PURE__ */ jsx("span", {
1409
- className: "clarify-ui-menu-title",
1410
- children: isCopied ? t("contentActions.copiedContent") : action.label
1411
- }), /* @__PURE__ */ jsx("span", {
1412
- className: "clarify-ui-menu-description truncate",
1413
- children: action.description
1414
- })]
1415
- }),
1416
- /* @__PURE__ */ jsx(Check, { className: `h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) transition ${isCopied ? "opacity-100" : "opacity-0"}` })
1417
- ]
1418
- }) }, action.key);
1419
- }),
1420
- /* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsxs("a", {
1421
- href: contentArtifactUrl,
1422
- target: "_blank",
1423
- rel: "noreferrer",
1424
- className: "clarify-content-actions-item clarify-ui-menu-item group flex w-full items-center gap-2 rounded-(--clarify-theme-tokens-radius-lg) px-1.5 py-1.5 text-left no-underline transition",
1425
- children: [
1426
- /* @__PURE__ */ jsx("span", {
1427
- className: "clarify-ui-menu-icon flex shrink-0 rounded-(--clarify-theme-tokens-radius-md) border border-(--clarify-theme-tokens-colors-border) p-1.5 dark:border-white/10",
1428
- children: /* @__PURE__ */ jsx(FileText, { className: "h-4 w-4" })
1429
- }),
1430
- /* @__PURE__ */ jsxs("span", {
1431
- className: "flex min-w-0 flex-1 flex-col px-1",
1432
- children: [/* @__PURE__ */ jsxs("span", {
1433
- className: "clarify-ui-menu-title flex items-center gap-1",
1434
- children: [viewLabel, /* @__PURE__ */ jsx(ExternalLink, { className: "clarify-ui-menu-icon h-3 w-3" })]
1435
- }), /* @__PURE__ */ jsx("span", {
1436
- className: "clarify-ui-menu-description truncate",
1437
- children: viewDescription
1438
- })]
1439
- }),
1440
- /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) opacity-0" })
1441
- ]
1442
- }) }),
1443
- actions.slice(1).map((action) => {
1444
- const Icon = action.icon;
1445
- const isCopied = copied === action.key;
1446
- return /* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsxs("button", {
1447
- type: "button",
1448
- onClick: action.run,
1449
- className: "clarify-content-actions-item clarify-ui-menu-item group flex w-full items-center gap-2 rounded-(--clarify-theme-tokens-radius-lg) px-1.5 py-1.5 text-left transition",
1450
- children: [
1451
- /* @__PURE__ */ jsx("span", {
1452
- className: "clarify-ui-menu-icon flex shrink-0 rounded-(--clarify-theme-tokens-radius-md) border border-(--clarify-theme-tokens-colors-border) p-1.5 dark:border-white/10",
1453
- children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" })
1454
- }),
1455
- /* @__PURE__ */ jsxs("span", {
1456
- className: "flex min-w-0 flex-1 flex-col px-1",
1457
- children: [/* @__PURE__ */ jsx("span", {
1458
- className: "clarify-ui-menu-title",
1459
- children: isCopied ? t("contentActions.copiedLink") : action.label
1460
- }), /* @__PURE__ */ jsx("span", {
1461
- className: "clarify-ui-menu-description truncate",
1462
- children: action.description
1463
- })]
1464
- }),
1465
- /* @__PURE__ */ jsx(Check, { className: `h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) transition ${isCopied ? "opacity-100" : "opacity-0"}` })
1466
- ]
1467
- }) }, action.key);
1468
- })
1469
- ]
1393
+ className: "absolute inset-0 -z-10 mx-0 max-w-none overflow-hidden",
1394
+ children: /* @__PURE__ */ jsxs("div", {
1395
+ className: "absolute top-0 left-1/2 -ml-152 h-100 w-325 dark:mask-[linear-gradient(white,transparent)]",
1396
+ children: [/* @__PURE__ */ jsx("div", {
1397
+ className: "absolute inset-0 bg-[linear-gradient(to_right,var(--clarify-theme-tokens-colors-primary),var(--clarify-theme-tokens-colors-accent))] opacity-35 mask-[radial-gradient(farthest-side_at_top,white,transparent)] dark:opacity-55",
1398
+ children: /* @__PURE__ */ jsx(GridPattern, {
1399
+ width: 72,
1400
+ height: 56,
1401
+ x: -12,
1402
+ y: 4,
1403
+ squares: [
1404
+ [4, 3],
1405
+ [2, 1],
1406
+ [7, 3],
1407
+ [10, 6]
1408
+ ],
1409
+ className: "absolute inset-x-0 inset-y-[-50%] h-[200%] w-full -skew-y-18 fill-black/40 stroke-black/50 mix-blend-overlay dark:fill-white/2.5 dark:stroke-white/5"
1410
+ })
1411
+ }), /* @__PURE__ */ jsx("svg", {
1412
+ viewBox: "0 0 1113 440",
1413
+ "aria-hidden": "true",
1414
+ className: "absolute top-0 left-1/2 -ml-76 w-278.25 fill-white blur-[26px] dark:hidden",
1415
+ children: /* @__PURE__ */ jsx("path", { d: "M.016 439.5s-9.5-300 434-300S882.516 20 882.516 20V0h230.004v439.5H.016Z" })
1470
1416
  })]
1471
1417
  })
1472
1418
  });
1473
1419
  }
1474
1420
  //#endregion
1475
- //#region source/shell/icons.tsx
1476
- function NavigationIcon(arg0) {
1477
- const { name, className } = arg0;
1478
- if (!name) return null;
1479
- const Icon = LucideIcons[name];
1480
- if (!Icon) return null;
1481
- return /* @__PURE__ */ jsx(Icon, {
1482
- className: clsx("shrink-0 stroke-current", className),
1483
- "aria-hidden": "true"
1421
+ //#region source/components/Prose.tsx
1422
+ function Prose(arg0) {
1423
+ const { as, className, ...props } = arg0;
1424
+ return /* @__PURE__ */ jsx(as ?? "div", {
1425
+ className: clsx(className, "clarify-prose prose max-w-none dark:prose-invert", "[html_:where(&>*)]:w-full [html_:where(&>*)]:min-w-0 [html_:where(&>*)]:max-w-full"),
1426
+ ...props
1484
1427
  });
1485
1428
  }
1486
1429
  //#endregion
1430
+ //#region source/utils/hash.ts
1431
+ function safeDecodeURIComponent(value) {
1432
+ try {
1433
+ return decodeURIComponent(value);
1434
+ } catch {
1435
+ return value;
1436
+ }
1437
+ }
1438
+ //#endregion
1487
1439
  //#region source/shell/Navigation.tsx
1488
1440
  function useInitialValue(value, condition = true) {
1489
1441
  const [initialValue] = useState(value);
@@ -1519,7 +1471,7 @@ var sectionBadgeColorStyles = {
1519
1471
  function SectionBadge(arg0) {
1520
1472
  const { children } = arg0;
1521
1473
  return /* @__PURE__ */ jsx("span", {
1522
- className: clsx("clarify-navigation-section-badge inline-flex shrink-0 justify-end font-mono font-semibold uppercase tracking-wide", sectionBadgeColorStyles[children.toUpperCase()] ?? "clarify-ui-menu-description"),
1474
+ className: clsx("clarify-navigation-section-badge inline-flex shrink-0 justify-end font-semibold uppercase tracking-wide", sectionBadgeColorStyles[children.toUpperCase()] ?? "clarify-ui-menu-description"),
1523
1475
  children
1524
1476
  });
1525
1477
  }
@@ -1529,7 +1481,7 @@ function NavLink(arg0) {
1529
1481
  if (!isAnchorLink) return;
1530
1482
  const hashIndex = href.indexOf("#");
1531
1483
  if (hashIndex === -1) return;
1532
- const targetId = decodeURIComponent(href.slice(hashIndex + 1));
1484
+ const targetId = safeDecodeURIComponent(href.slice(hashIndex + 1));
1533
1485
  window.requestAnimationFrame(() => {
1534
1486
  document.getElementById(targetId)?.scrollIntoView();
1535
1487
  window.requestAnimationFrame(() => {
@@ -1552,7 +1504,7 @@ function NavLink(arg0) {
1552
1504
  }) : null,
1553
1505
  badge ? /* @__PURE__ */ jsx(SectionBadge, { children: badge }) : null,
1554
1506
  /* @__PURE__ */ jsx("span", {
1555
- className: "min-w-0 truncate",
1507
+ className: "min-w-0 truncate whitespace-nowrap",
1556
1508
  children
1557
1509
  })
1558
1510
  ]
@@ -1575,13 +1527,27 @@ function VisibleSectionHighlight(arg0) {
1575
1527
  const height = isPresent ? Math.max(1, visibleSections.length) * itemHeight : itemHeight;
1576
1528
  const top = group.links.findIndex((link) => isSameRoutePath(link.href, pathname)) * itemHeight + firstVisibleSectionIndex * itemHeight;
1577
1529
  return /* @__PURE__ */ jsx(motion.div, {
1578
- layout: true,
1579
- initial: { opacity: 0 },
1530
+ initial: {
1531
+ opacity: 0,
1532
+ height: 0
1533
+ },
1580
1534
  animate: {
1581
1535
  opacity: 1,
1582
- transition: { delay: .2 }
1536
+ top,
1537
+ height,
1538
+ transition: {
1539
+ duration: .2,
1540
+ ease: "easeOut"
1541
+ }
1542
+ },
1543
+ exit: {
1544
+ opacity: 0,
1545
+ height: 0,
1546
+ transition: {
1547
+ duration: .15,
1548
+ ease: "easeIn"
1549
+ }
1583
1550
  },
1584
- exit: { opacity: 0 },
1585
1551
  className: "clarify-navigation-section-highlight absolute inset-x-0 top-0 will-change-transform",
1586
1552
  style: {
1587
1553
  borderRadius: "var(--clarify-theme-tokens-radius-sm)",
@@ -1595,14 +1561,26 @@ function ActivePageMarker(arg0) {
1595
1561
  const itemHeight = remToPx(2);
1596
1562
  const top = remToPx(.25) + group.links.findIndex((link) => isSameRoutePath(link.href, pathname)) * itemHeight;
1597
1563
  return /* @__PURE__ */ jsx(motion.div, {
1598
- layout: true,
1599
1564
  className: "absolute left-2 h-6 w-px bg-(--clarify-theme-tokens-colors-primary)",
1600
- initial: { opacity: 0 },
1565
+ initial: {
1566
+ opacity: 0,
1567
+ top
1568
+ },
1601
1569
  animate: {
1602
1570
  opacity: 1,
1603
- transition: { delay: .2 }
1571
+ top,
1572
+ transition: {
1573
+ duration: .2,
1574
+ ease: "easeOut"
1575
+ }
1576
+ },
1577
+ exit: {
1578
+ opacity: 0,
1579
+ transition: {
1580
+ duration: .15,
1581
+ ease: "easeIn"
1582
+ }
1604
1583
  },
1605
- exit: { opacity: 0 },
1606
1584
  style: { top }
1607
1585
  });
1608
1586
  }
@@ -1613,8 +1591,7 @@ function NavigationGroup(arg0) {
1613
1591
  const isActiveGroup = group.links.findIndex((link) => isSameRoutePath(link.href, pathname)) !== -1;
1614
1592
  return /* @__PURE__ */ jsxs("li", {
1615
1593
  className: clsx("clarify-navigation-group relative mt-6", className),
1616
- children: [/* @__PURE__ */ jsxs(motion.h2, {
1617
- layout: "position",
1594
+ children: [/* @__PURE__ */ jsxs("h2", {
1618
1595
  className: "clarify-navigation-group-title flex items-center gap-2",
1619
1596
  children: [/* @__PURE__ */ jsx(NavigationIcon, {
1620
1597
  name: group.icon,
@@ -1630,10 +1607,7 @@ function NavigationGroup(arg0) {
1630
1607
  pathname
1631
1608
  }) : null
1632
1609
  }),
1633
- /* @__PURE__ */ jsx(motion.div, {
1634
- layout: true,
1635
- className: "absolute inset-y-0 left-2 w-px bg-(--clarify-theme-tokens-colors-border) dark:bg-white/5"
1636
- }),
1610
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 left-2 w-px bg-(--clarify-theme-tokens-colors-border) dark:bg-white/5" }),
1637
1611
  /* @__PURE__ */ jsx(AnimatePresence, {
1638
1612
  initial: false,
1639
1613
  children: isActiveGroup ? /* @__PURE__ */ jsx(ActivePageMarker, {
@@ -1646,8 +1620,7 @@ function NavigationGroup(arg0) {
1646
1620
  className: "border-l border-transparent",
1647
1621
  children: group.links.map((link) => {
1648
1622
  const active = isSameRoutePath(link.href, pathname);
1649
- return /* @__PURE__ */ jsxs(motion.li, {
1650
- layout: "position",
1623
+ return /* @__PURE__ */ jsxs("li", {
1651
1624
  className: "relative",
1652
1625
  children: [/* @__PURE__ */ jsx(NavLink, {
1653
1626
  href: link.href,
@@ -1655,7 +1628,6 @@ function NavigationGroup(arg0) {
1655
1628
  active,
1656
1629
  children: link.title
1657
1630
  }), /* @__PURE__ */ jsx(AnimatePresence, {
1658
- mode: "popLayout",
1659
1631
  initial: false,
1660
1632
  children: active && sections.length > 0 ? /* @__PURE__ */ jsx(motion.ul, {
1661
1633
  role: "list",
@@ -1722,11 +1694,11 @@ function XIcon(props) {
1722
1694
  });
1723
1695
  }
1724
1696
  var IsInsideMobileNavigationContext = createContext(false);
1725
- function hasPath$2(nodes, pathname) {
1726
- return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath$2(node.children ?? [], pathname));
1697
+ function hasPath$1(nodes, pathname) {
1698
+ return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath$1(node.children ?? [], pathname));
1727
1699
  }
1728
1700
  function isActiveTab$1(tab, pathname) {
1729
- return isSameRoutePath(tab.path, pathname) || hasPath$2(tab.children, pathname);
1701
+ return isSameRoutePath(tab.path, pathname) || hasPath$1(tab.children, pathname);
1730
1702
  }
1731
1703
  function MobileTabsSelect(arg0) {
1732
1704
  const { tabs } = arg0;
@@ -1745,7 +1717,7 @@ function MobileTabsSelect(arg0) {
1745
1717
  name: activeTab.icon,
1746
1718
  className: "h-4 w-4 shrink-0 text-(--clarify-theme-tokens-colors-primary)"
1747
1719
  }), /* @__PURE__ */ jsx("span", {
1748
- className: "truncate tracking-[-0.01em]",
1720
+ className: "truncate",
1749
1721
  children: activeTab.title
1750
1722
  })]
1751
1723
  }), /* @__PURE__ */ jsx("svg", {
@@ -2173,20 +2145,39 @@ function MobileSearch(arg0) {
2173
2145
  });
2174
2146
  }
2175
2147
  //#endregion
2148
+ //#region source/shell/SiteLogo.tsx
2149
+ function SiteLogo(arg0) {
2150
+ const { logo, className } = arg0;
2151
+ if (!logo) return null;
2152
+ if (typeof logo === "string") return /* @__PURE__ */ jsx("img", {
2153
+ src: logo,
2154
+ alt: "",
2155
+ className: clsx("clarify-logo", className)
2156
+ });
2157
+ const lightLogo = logo.light ?? logo.dark;
2158
+ const darkLogo = logo.dark ?? logo.light;
2159
+ if (!lightLogo || !darkLogo) return null;
2160
+ if (lightLogo === darkLogo) return /* @__PURE__ */ jsx("img", {
2161
+ src: lightLogo,
2162
+ alt: "",
2163
+ className: clsx("clarify-logo", className)
2164
+ });
2165
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("img", {
2166
+ src: lightLogo,
2167
+ alt: "",
2168
+ className: clsx("clarify-logo clarify-logo-light", className, "dark:hidden")
2169
+ }), /* @__PURE__ */ jsx("img", {
2170
+ src: darkLogo,
2171
+ alt: "",
2172
+ className: clsx("clarify-logo clarify-logo-dark", className, "hidden dark:block")
2173
+ })] });
2174
+ }
2175
+ //#endregion
2176
2176
  //#region source/shell/Header.tsx
2177
2177
  function resolveLocalizedText(text, locale, fallbackLocale) {
2178
2178
  if (typeof text === "string") return text;
2179
2179
  return (locale ? text[locale] : void 0) ?? (fallbackLocale ? text[fallbackLocale] : void 0) ?? Object.values(text)[0] ?? "";
2180
2180
  }
2181
- function isExternalHref(href) {
2182
- return /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith("//");
2183
- }
2184
- function localizeHref(href, config, locale) {
2185
- if (!locale || !config.i18n || isExternalHref(href) || href.startsWith("#")) return href;
2186
- if (locale === config.i18n.defaultLocale) return href;
2187
- const cleanHref = href === "/" ? "" : href.replace(/^\/+/, "");
2188
- return `/${locale}${cleanHref ? `/${cleanHref}` : ""}`;
2189
- }
2190
2181
  function localizedRoutePath(config, locale, route) {
2191
2182
  const alternatePath = route?.alternates?.[locale];
2192
2183
  if (alternatePath) return alternatePath;
@@ -2299,11 +2290,11 @@ function MobileNavbarMenu(arg0) {
2299
2290
  })]
2300
2291
  });
2301
2292
  }
2302
- function hasPath$1(nodes, pathname) {
2303
- return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath$1(node.children ?? [], pathname));
2293
+ function hasPath(nodes, pathname) {
2294
+ return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath(node.children ?? [], pathname));
2304
2295
  }
2305
2296
  function isActiveTab(tab, pathname) {
2306
- return isSameRoutePath(tab.path, pathname) || hasPath$1(tab.children, pathname);
2297
+ return isSameRoutePath(tab.path, pathname) || hasPath(tab.children, pathname);
2307
2298
  }
2308
2299
  function ProductTabs(arg0) {
2309
2300
  const { tabs } = arg0;
@@ -2320,7 +2311,7 @@ function ProductTabs(arg0) {
2320
2311
  return /* @__PURE__ */ jsxs(Link, {
2321
2312
  to: tab.path,
2322
2313
  "aria-current": active ? "page" : void 0,
2323
- className: clsx("clarify-product-tab clarify-ui-tab relative inline-flex shrink-0 items-center gap-2 px-0 transition", active && "clarify-ui-tab-active"),
2314
+ className: clsx("clarify-product-tab clarify-ui-tab relative inline-flex h-full shrink-0 items-center gap-2 px-0 transition", active && "clarify-ui-tab-active"),
2324
2315
  children: [
2325
2316
  /* @__PURE__ */ jsx(NavigationIcon, {
2326
2317
  name: tab.icon,
@@ -2331,9 +2322,9 @@ function ProductTabs(arg0) {
2331
2322
  layoutId: "clarify-product-tab-indicator",
2332
2323
  className: "absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-(--clarify-theme-tokens-colors-foreground) dark:bg-white",
2333
2324
  transition: {
2334
- type: "spring",
2335
- stiffness: 420,
2336
- damping: 36
2325
+ type: "tween",
2326
+ duration: .16,
2327
+ ease: "easeOut"
2337
2328
  }
2338
2329
  }) : null
2339
2330
  ]
@@ -2431,199 +2422,6 @@ var Header = forwardRef(function Header(arg0, ref) {
2431
2422
  });
2432
2423
  });
2433
2424
  //#endregion
2434
- //#region source/app/AppShell.tsx
2435
- function routeForPath(routes, pathname) {
2436
- return routes.find((route) => isSameRoutePath(route.path, pathname));
2437
- }
2438
- function sectionsForRoute(route) {
2439
- return route?.sections?.map((section) => ({
2440
- id: section.id,
2441
- title: section.title,
2442
- badge: section.badge,
2443
- tags: section.tags
2444
- })) ?? [];
2445
- }
2446
- function resolveRouteComponent(route) {
2447
- if (route.lazy) return lazy(route.component);
2448
- return route.component;
2449
- }
2450
- function scrollToHash(hash) {
2451
- if (!hash) return;
2452
- const targetId = decodeURIComponent(hash.slice(1));
2453
- window.requestAnimationFrame(() => {
2454
- document.getElementById(targetId)?.scrollIntoView();
2455
- window.requestAnimationFrame(() => {
2456
- window.dispatchEvent(new Event("scroll"));
2457
- });
2458
- });
2459
- }
2460
- function localeForPath(config, pathname, route) {
2461
- if (route?.locale) return route.locale;
2462
- const i18n = config.i18n;
2463
- if (!i18n) return void 0;
2464
- const firstSegment = pathname.split("/").filter(Boolean)[0];
2465
- return i18n.locales.find((locale) => locale.code === firstSegment)?.code ?? i18n.defaultLocale;
2466
- }
2467
- function isTabbedNavigation(navigation) {
2468
- return !Array.isArray(navigation) && "tabs" in navigation;
2469
- }
2470
- function hasPath(nodes, pathname) {
2471
- return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath(node.children ?? [], pathname));
2472
- }
2473
- function navigationFromTabs(navigation, pathname) {
2474
- return {
2475
- items: navigation.tabs.find((tab) => isSameRoutePath(tab.path, pathname) || hasPath(tab.children, pathname))?.children ?? navigation.tabs[0]?.children ?? [],
2476
- tabs: navigation.tabs
2477
- };
2478
- }
2479
- function navigationForLocale(navigation, locale, pathname) {
2480
- if (Array.isArray(navigation)) return { items: navigation };
2481
- if (isTabbedNavigation(navigation)) return navigationFromTabs(navigation, pathname);
2482
- if (!locale) return { items: [] };
2483
- const localizedNavigation = navigation[locale];
2484
- if (!localizedNavigation) return { items: [] };
2485
- return Array.isArray(localizedNavigation) ? { items: localizedNavigation } : navigationFromTabs(localizedNavigation, pathname);
2486
- }
2487
- function themeStyle(config) {
2488
- const { colors, radius } = config.theme.tokens;
2489
- const { layout } = config.theme;
2490
- return {
2491
- "--clarify-theme-tokens-colors-primary": colors.primary,
2492
- "--clarify-theme-tokens-colors-accent": colors.accent,
2493
- "--clarify-theme-tokens-colors-background": colors.background,
2494
- "--clarify-theme-tokens-colors-foreground": colors.foreground,
2495
- "--clarify-theme-tokens-colors-surface": colors.surface,
2496
- "--clarify-theme-tokens-colors-muted": colors.muted,
2497
- "--clarify-theme-tokens-colors-border": colors.border,
2498
- "--clarify-theme-tokens-colors-code-background": colors.codeBackground,
2499
- "--clarify-theme-tokens-radius-sm": radius.sm,
2500
- "--clarify-theme-tokens-radius-md": radius.md,
2501
- "--clarify-theme-tokens-radius-lg": radius.lg,
2502
- "--clarify-theme-tokens-radius-xl": radius.xl,
2503
- "--clarify-theme-layout-max-width": layout.maxWidth
2504
- };
2505
- }
2506
- function pageTitle(config, route) {
2507
- const routeTitle = route?.title?.trim();
2508
- if (!routeTitle || routeTitle === config.title) return config.title;
2509
- return `${routeTitle} - ${config.title}`;
2510
- }
2511
- function setNamedMeta(name, content) {
2512
- const existing = document.head.querySelector(`meta[name="${name}"]`);
2513
- if (!content) {
2514
- existing?.remove();
2515
- return;
2516
- }
2517
- const meta = existing ?? document.createElement("meta");
2518
- meta.name = name;
2519
- meta.content = content;
2520
- if (!existing) document.head.appendChild(meta);
2521
- }
2522
- function applyDocumentMetadata(config, route) {
2523
- document.title = pageTitle(config, route);
2524
- setNamedMeta("description", route?.description ?? config.description);
2525
- setNamedMeta("keywords", route?.keywords?.join(", "));
2526
- }
2527
- function applyRootThemeVariables(themeVariables) {
2528
- const rootStyle = document.documentElement.style;
2529
- for (const [property, value] of Object.entries(themeVariables)) rootStyle.setProperty(property, value);
2530
- return () => {
2531
- for (const property of Object.keys(themeVariables)) rootStyle.removeProperty(property);
2532
- };
2533
- }
2534
- function AppShell(arg0) {
2535
- const { config, routes, navigation } = arg0;
2536
- const location = useLocation();
2537
- const pathname = normalizeRoutePath(location.pathname);
2538
- const currentRoute = routeForPath(routes, pathname);
2539
- const currentLocale = localeForPath(config, pathname, currentRoute);
2540
- const currentLocaleConfig = config.i18n?.locales.find((locale) => locale.code === currentLocale);
2541
- const currentNavigation = navigationForLocale(navigation, currentLocale, pathname);
2542
- const sections = sectionsForRoute(currentRoute);
2543
- const hasTabs = Boolean(currentNavigation.tabs?.length);
2544
- const themeVariables = themeStyle(config);
2545
- const renderRoutes = useMemo(() => routes.map((route) => ({
2546
- ...route,
2547
- component: resolveRouteComponent(route)
2548
- })), [routes]);
2549
- useEffect(() => applyRootThemeVariables(themeVariables), [themeVariables]);
2550
- useEffect(() => {
2551
- if (location.hash) {
2552
- scrollToHash(location.hash);
2553
- return;
2554
- }
2555
- window.scrollTo({
2556
- top: 0,
2557
- left: 0
2558
- });
2559
- window.requestAnimationFrame(() => {
2560
- window.dispatchEvent(new Event("scroll"));
2561
- });
2562
- }, [location.hash, location.pathname]);
2563
- useEffect(() => {
2564
- if (!currentLocale) return;
2565
- document.documentElement.lang = currentLocale;
2566
- if (currentLocaleConfig?.dir) document.documentElement.dir = currentLocaleConfig.dir;
2567
- else document.documentElement.removeAttribute("dir");
2568
- }, [currentLocale, currentLocaleConfig?.dir]);
2569
- useEffect(() => {
2570
- applyDocumentMetadata(config, currentRoute);
2571
- }, [config, currentRoute]);
2572
- return /* @__PURE__ */ jsx(ClarifyLocaleContext.Provider, {
2573
- value: currentLocale,
2574
- children: /* @__PURE__ */ jsx(SectionProvider, {
2575
- sections,
2576
- children: /* @__PURE__ */ jsxs("div", {
2577
- className: "clarify-app h-full min-h-screen bg-(--clarify-theme-tokens-colors-background) text-(--clarify-theme-tokens-colors-foreground) dark:bg-zinc-950 dark:text-white",
2578
- "data-theme-preset": config.theme.preset,
2579
- style: themeVariables,
2580
- children: [
2581
- /* @__PURE__ */ jsx(Header, {
2582
- config,
2583
- navigation: currentNavigation.items,
2584
- tabs: currentNavigation.tabs,
2585
- routes,
2586
- currentLocale,
2587
- currentRoute
2588
- }),
2589
- /* @__PURE__ */ jsxs("div", {
2590
- className: "clarify-layout mx-auto grid w-full max-w-(--clarify-theme-layout-max-width) grid-cols-1 lg:grid-cols-[18rem_minmax(0,1fr)] xl:grid-cols-[20rem_minmax(0,1fr)]",
2591
- children: [/* @__PURE__ */ jsx(motion.aside, {
2592
- layoutScroll: true,
2593
- className: clsx("clarify-sidebar hidden lg:sticky lg:z-30 lg:block lg:h-[calc(100vh-3.5rem)] lg:self-start lg:overflow-y-auto lg:bg-(--clarify-theme-tokens-colors-background) lg:px-5 lg:pb-8 xl:px-6 lg:dark:bg-zinc-950", hasTabs ? "lg:top-28 lg:h-[calc(100vh-7rem)] lg:pt-6" : "lg:top-14 lg:pt-6"),
2594
- children: /* @__PURE__ */ jsx(Navigation, { navigation: currentNavigation.items })
2595
- }), /* @__PURE__ */ jsxs("div", {
2596
- className: clsx("clarify-content @container relative flex min-h-screen min-w-0 flex-col px-4 sm:px-6 lg:px-8 xl:px-10", hasTabs ? "pt-14 lg:pt-28" : "pt-14"),
2597
- children: [
2598
- /* @__PURE__ */ jsx(ContentActions, {
2599
- hasTabs,
2600
- route: currentRoute,
2601
- routePrefix: config.routePrefix
2602
- }),
2603
- /* @__PURE__ */ jsx("main", {
2604
- className: "clarify-main min-w-0 flex-auto",
2605
- children: /* @__PURE__ */ jsx(Suspense, {
2606
- fallback: null,
2607
- children: /* @__PURE__ */ jsx(Routes, { children: renderRoutes.map((route) => /* @__PURE__ */ jsx(Route, {
2608
- path: route.path,
2609
- element: /* @__PURE__ */ jsx(route.component, {})
2610
- }, route.path)) })
2611
- })
2612
- }),
2613
- /* @__PURE__ */ jsx(PageNavigation, {
2614
- navigation: currentNavigation.items,
2615
- currentRoute
2616
- })
2617
- ]
2618
- })]
2619
- }),
2620
- /* @__PURE__ */ jsx(PageFooter, {})
2621
- ]
2622
- })
2623
- })
2624
- });
2625
- }
2626
- //#endregion
2627
- export { remToPx as A, useBuiltInText as C, useOpenApis as D, useClarifyConfig as E, SectionProvider as O, BuiltWithClarify as S, OpenApisContext as T, CodeGroup as _, Heading as a, CardGroup as b, Tag as c, useTheme as d, PageFooter as f, Code as g, Feedback as h, DocShell as i, useSectionStore as k, ThemeToggle as l, HeroPattern as m, ApiEndpointCard as n, Logo as o, GridPattern as p, Button as r, Prose as s, AppShell as t, ThemeProvider as u, Pre as v, ClarifyConfigContext as w, Callout as x, Card as y };
2425
+ export { prefixHref as A, normalizeRoutePath as C, ContentActions as D, useTheme as E, OpenApisContext as F, useClarifyConfig as I, useOpenApis as L, useBuiltInText as M, ClarifyConfigContext as N, isExternalHref as O, ClarifyLocaleContext as P, isSameRoutePath as S, ThemeProvider as T, Callout as _, GridPattern as a, useSectionStore as b, Heading as c, Collapse as d, Code as f, CardGroup as g, Card as h, Prose as i, copyTextToClipboard as j, localizeHref as k, Tag as l, Pre as m, Navigation as n, HeroPattern as o, CodeGroup as p, safeDecodeURIComponent as r, Logo as s, Header as t, Feedback as u, Button as v, ThemeToggle as w, remToPx as x, SectionProvider as y };
2628
2426
 
2629
- //# sourceMappingURL=AppShell-nQnuKyn2.js.map
2427
+ //# sourceMappingURL=shell-BlMMdTpZ.js.map