@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,119 +1,15 @@
1
- //#region \0rolldown/runtime.js
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __exportAll = (all, no_symbols) => {
9
- let target = {};
10
- for (var name in all) __defProp(target, name, {
11
- get: all[name],
12
- enumerable: true
13
- });
14
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
15
- return target;
16
- };
17
- var __copyProps = (to, from, except, desc) => {
18
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
19
- key = keys[i];
20
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
21
- get: ((k) => from[k]).bind(null, key),
22
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
23
- });
24
- }
25
- return to;
26
- };
27
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
28
- value: mod,
29
- enumerable: true
30
- }) : target, mod));
31
- //#endregion
1
+ const require_chunk = require("./chunk-DakpK96I.cjs");
32
2
  let clsx = require("clsx");
33
- clsx = __toESM(clsx, 1);
34
- let framer_motion = require("framer-motion");
3
+ clsx = require_chunk.__toESM(clsx, 1);
35
4
  let react = require("react");
36
5
  let react_router_dom = require("react-router-dom");
37
- let zustand = require("zustand");
38
- let react_jsx_runtime = require("react/jsx-runtime");
39
- let lucide_react = require("lucide-react");
40
- lucide_react = __toESM(lucide_react, 1);
41
6
  let _headlessui_react = require("@headlessui/react");
42
- //#region source/utils/remToPx.ts
43
- function remToPx(remValue) {
44
- return remValue * (typeof window === "undefined" ? 16 : Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize));
45
- }
46
- //#endregion
47
- //#region source/components/SectionProvider.tsx
48
- function createSectionStore(sections) {
49
- return (0, zustand.createStore)()((set) => ({
50
- sections,
51
- visibleSections: [],
52
- setVisibleSections: (visibleSections) => set((state) => state.visibleSections.join() === visibleSections.join() ? {} : { visibleSections }),
53
- registerHeading: ({ id, ref, offsetRem }) => set((state) => ({ sections: state.sections.map((section) => section.id === id ? {
54
- ...section,
55
- headingRef: ref,
56
- offsetRem
57
- } : section) }))
58
- }));
59
- }
60
- function useVisibleSections(sectionStore) {
61
- const setVisibleSections = (0, zustand.useStore)(sectionStore, (state) => state.setVisibleSections);
62
- const sections = (0, zustand.useStore)(sectionStore, (state) => state.sections);
63
- (0, react.useEffect)(() => {
64
- function checkVisibleSections() {
65
- const { innerHeight, scrollY } = window;
66
- const newVisibleSections = [];
67
- for (let sectionIndex = 0; sectionIndex < sections.length; sectionIndex += 1) {
68
- const { id, headingRef, offsetRem = 0 } = sections[sectionIndex];
69
- if (!headingRef?.current) continue;
70
- const offset = remToPx(offsetRem);
71
- const top = headingRef.current.getBoundingClientRect().top + scrollY;
72
- if (sectionIndex === 0 && top - offset > scrollY) newVisibleSections.push("_top");
73
- const nextSection = sections[sectionIndex + 1];
74
- const bottom = (nextSection?.headingRef?.current?.getBoundingClientRect().top ?? Infinity) + scrollY - remToPx(nextSection?.offsetRem ?? 0);
75
- if (top > scrollY && top < scrollY + innerHeight || bottom > scrollY && bottom < scrollY + innerHeight || top <= scrollY && bottom >= scrollY + innerHeight) newVisibleSections.push(id);
76
- }
77
- setVisibleSections(newVisibleSections);
78
- }
79
- const raf = window.requestAnimationFrame(() => checkVisibleSections());
80
- window.addEventListener("scroll", checkVisibleSections, { passive: true });
81
- window.addEventListener("resize", checkVisibleSections);
82
- return () => {
83
- window.cancelAnimationFrame(raf);
84
- window.removeEventListener("scroll", checkVisibleSections);
85
- window.removeEventListener("resize", checkVisibleSections);
86
- };
87
- }, [setVisibleSections, sections]);
88
- }
89
- var SectionStoreContext = (0, react.createContext)(null);
90
- var useIsomorphicLayoutEffect = typeof window === "undefined" ? react.useEffect : react.useLayoutEffect;
91
- function SectionProvider(arg0) {
92
- const { sections, children } = arg0;
93
- const [sectionStore] = (0, react.useState)(() => createSectionStore(sections));
94
- useVisibleSections(sectionStore);
95
- useIsomorphicLayoutEffect(() => {
96
- sectionStore.setState((state) => ({ sections: sections.map((section) => {
97
- const registeredSection = state.sections.find((item) => item.id === section.id);
98
- return {
99
- ...section,
100
- headingRef: registeredSection?.headingRef,
101
- offsetRem: registeredSection?.offsetRem ?? section.offsetRem
102
- };
103
- }) }));
104
- }, [sectionStore, sections]);
105
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionStoreContext.Provider, {
106
- value: sectionStore,
107
- children
108
- });
109
- }
110
- function useSectionStore(selector) {
111
- const store = (0, react.useContext)(SectionStoreContext);
112
- if (!store) throw new Error("[clarify] useSectionStore must be used within SectionProvider");
113
- return (0, zustand.useStore)(store, selector);
114
- }
115
- //#endregion
116
- //#region source/context.tsx
7
+ let lucide_react = require("lucide-react");
8
+ lucide_react = require_chunk.__toESM(lucide_react, 1);
9
+ let react_jsx_runtime = require("react/jsx-runtime");
10
+ let framer_motion = require("framer-motion");
11
+ let zustand = require("zustand");
12
+ //#region source/core/context.tsx
117
13
  var ClarifyConfigContext = (0, react.createContext)(null);
118
14
  var ClarifyLocaleContext = (0, react.createContext)(void 0);
119
15
  var OpenApisContext = (0, react.createContext)({});
@@ -126,7 +22,7 @@ function useOpenApis() {
126
22
  return (0, react.useContext)(OpenApisContext);
127
23
  }
128
24
  //#endregion
129
- //#region source/i18n.ts
25
+ //#region source/core/i18n.ts
130
26
  var builtInText = {
131
27
  en: {
132
28
  "actions.code": "Code",
@@ -144,6 +40,9 @@ var builtInText = {
144
40
  "contentActions.copyContentDescription": "Copy this page as {contentType} for LLMs",
145
41
  "contentActions.copyLink": "Copy {contentType} link",
146
42
  "contentActions.copyLinkDescription": "Copy the raw {contentType} content link for this page",
43
+ "contentActions.copyLlms": "Copy llms.txt",
44
+ "contentActions.copyLlmsDescription": "Copy the llms.txt link for this site",
45
+ "contentActions.copiedLlms": "Copied llms.txt",
147
46
  "contentActions.copyOptions": "Choose copy option",
148
47
  "contentActions.copiedContent": "Copied page",
149
48
  "contentActions.copiedLink": "Copied link",
@@ -216,6 +115,9 @@ var builtInText = {
216
115
  "contentActions.copyContentDescription": "将页面以 {contentType} 格式复制给 LLMs",
217
116
  "contentActions.copyLink": "复制 {contentType} 链接",
218
117
  "contentActions.copyLinkDescription": "复制当前页面的 {contentType} 原始内容链接",
118
+ "contentActions.copyLlms": "复制 llms.txt",
119
+ "contentActions.copyLlmsDescription": "复制此站点的 llms.txt 链接",
120
+ "contentActions.copiedLlms": "已复制 llms.txt",
219
121
  "contentActions.copyOptions": "选择复制选项",
220
122
  "contentActions.copiedContent": "已复制页面",
221
123
  "contentActions.copiedLink": "已复制链接",
@@ -288,894 +190,1027 @@ function useBuiltInText(locale) {
288
190
  return (key, replacements) => translateBuiltInText(resolvedLocale, key, replacements);
289
191
  }
290
192
  //#endregion
291
- //#region source/components/BuiltWithClarify.tsx
292
- function ClarifyMark(props) {
293
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
294
- viewBox: "0 0 279 200",
295
- "aria-hidden": "true",
296
- ...props,
297
- children: [
298
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
299
- 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",
300
- fill: "#00D492"
301
- }),
302
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
303
- 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",
304
- fill: "#00F6C9",
305
- fillOpacity: "0.6",
306
- transform: "rotate(-90 179 100)"
307
- }),
308
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
309
- 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",
310
- fill: "#00F692"
311
- })
312
- ]
313
- });
314
- }
315
- function BuiltWithClarify() {
316
- const t = useBuiltInText();
317
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
318
- href: "https://clarify.pub",
319
- target: "_blank",
320
- rel: "noreferrer",
321
- "aria-label": t("builtWith.label"),
322
- className: "clarify-built-with inline-flex items-center gap-1.5 rounded-full px-2 py-1 font-medium no-underline transition",
323
- children: [
324
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("builtWith.prefix") }),
325
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClarifyMark, { className: "clarify-built-with-logo h-3.5 w-5 flex-none" }),
326
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
327
- className: "clarify-built-with-brand font-semibold",
328
- children: "Clarify"
329
- })
330
- ]
331
- });
332
- }
333
- //#endregion
334
- //#region source/components/Callout.tsx
335
- var calloutStyles = {
336
- info: {
337
- 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",
338
- icon: "text-sky-600 dark:text-sky-400",
339
- title: "text-sky-900 dark:text-sky-100",
340
- Icon: lucide_react.Info
341
- },
342
- note: {
343
- container: "border-zinc-500/20 bg-zinc-50 text-zinc-900 dark:border-white/10 dark:bg-white/5 dark:text-zinc-200",
344
- icon: "text-zinc-500 dark:text-zinc-400",
345
- title: "text-zinc-900 dark:text-white",
346
- Icon: lucide_react.Info
347
- },
348
- tip: {
349
- 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",
350
- icon: "text-emerald-600 dark:text-emerald-400",
351
- title: "text-emerald-900 dark:text-emerald-100",
352
- Icon: lucide_react.Lightbulb
353
- },
354
- warning: {
355
- 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",
356
- icon: "text-amber-600 dark:text-amber-400",
357
- title: "text-amber-900 dark:text-amber-100",
358
- Icon: lucide_react.AlertTriangle
359
- },
360
- danger: {
361
- 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",
362
- icon: "text-rose-600 dark:text-rose-400",
363
- title: "text-rose-900 dark:text-rose-100",
364
- Icon: lucide_react.XCircle
365
- },
366
- success: {
367
- 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",
368
- icon: "text-emerald-600 dark:text-emerald-400",
369
- title: "text-emerald-900 dark:text-emerald-100",
370
- Icon: lucide_react.CheckCircle2
193
+ //#region source/utils/clipboard.ts
194
+ async function copyTextToClipboard(text) {
195
+ if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) try {
196
+ await navigator.clipboard.writeText(text);
197
+ return true;
198
+ } catch {}
199
+ if (typeof document === "undefined") return false;
200
+ const textarea = document.createElement("textarea");
201
+ textarea.value = text;
202
+ textarea.setAttribute("readonly", "");
203
+ textarea.style.position = "fixed";
204
+ textarea.style.top = "-9999px";
205
+ textarea.style.opacity = "0";
206
+ document.body.appendChild(textarea);
207
+ try {
208
+ textarea.select();
209
+ return document.execCommand("copy");
210
+ } catch {
211
+ return false;
212
+ } finally {
213
+ textarea.remove();
371
214
  }
372
- };
373
- var defaultTitleKeys = {
374
- info: "callout.info",
375
- note: "callout.note",
376
- tip: "callout.tip",
377
- warning: "callout.warning",
378
- danger: "callout.danger",
379
- success: "callout.success"
380
- };
381
- function Callout(arg0) {
382
- const { children, type = "info", title, icon = true, className, ...props } = arg0;
383
- const t = useBuiltInText();
384
- const style = calloutStyles[type];
385
- const Icon = style.Icon;
386
- const resolvedTitle = title === void 0 ? t(defaultTitleKeys[type]) : title;
387
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
388
- className: (0, clsx.default)("clarify-callout my-6 flex gap-3 rounded-(--clarify-theme-tokens-radius-xl) border p-4 text-sm/6", style.container, className),
389
- ...props,
390
- children: [icon ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
391
- className: (0, clsx.default)("mt-1 size-4 flex-none", style.icon),
392
- "aria-hidden": "true"
393
- }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
394
- className: "min-w-0 flex-1 *:first:mt-0 *:last:mb-0",
395
- children: [resolvedTitle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
396
- className: (0, clsx.default)("mb-1 font-semibold", style.title),
397
- children: resolvedTitle
398
- }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
399
- className: "*:first:mt-0 *:last:mb-0",
400
- children
401
- })]
402
- })]
403
- });
404
215
  }
405
216
  //#endregion
406
- //#region source/components/Card.tsx
407
- function toPascalCase(value) {
408
- return value.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join("");
217
+ //#region source/utils/href.ts
218
+ function isExternalHref(href) {
219
+ return /^[a-z][a-z\d+.-]*:/i.test(href) || href.startsWith("//");
409
220
  }
410
- function CardIcon(arg0) {
411
- const { name } = arg0;
412
- if (!name) return null;
413
- const Icon = lucide_react[toPascalCase(name)];
414
- if (!Icon) return null;
415
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
416
- 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)",
417
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
418
- className: "size-5",
419
- "aria-hidden": "true"
420
- })
421
- });
221
+ function hasLocalePrefix(href, config) {
222
+ const firstSegment = href.replace(/^\/+/, "").split("/")[0];
223
+ return Boolean(firstSegment && config.i18n?.locales.some((locale) => locale.code === firstSegment));
422
224
  }
423
- var cardGroupColumnStyles = {
424
- 1: "grid-cols-1",
425
- 2: "grid-cols-1 sm:grid-cols-2",
426
- 3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
427
- 4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4"
428
- };
429
- function CardGroup(arg0) {
430
- const { children, cols = 2, className } = arg0;
431
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
432
- className: (0, clsx.default)("not-prose my-10 grid gap-4", cardGroupColumnStyles[cols], className),
433
- children
434
- });
225
+ function localizeHref(href, config, locale) {
226
+ if (!locale || !config.i18n || isExternalHref(href) || href.startsWith("#")) return href;
227
+ if (locale === config.i18n.defaultLocale || hasLocalePrefix(href, config)) return href;
228
+ const cleanHref = href === "/" ? "" : href.replace(/^\/+/, "");
229
+ return `/${locale}${cleanHref ? `/${cleanHref}` : ""}`;
435
230
  }
436
- function Card(arg0) {
437
- const { title, icon, href, children, className, ...props } = arg0;
438
- const content = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
439
- className: "flex items-start gap-4",
440
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardIcon, { name: icon }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
441
- className: "min-w-0 flex-1",
442
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
443
- className: "m-0 text-base font-semibold text-[var(--clarify-theme-tokens-colors-foreground)] dark:text-white",
444
- children: title
445
- }), children ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
446
- className: "mt-2 text-sm/6 text-[var(--clarify-theme-tokens-colors-muted)] dark:text-zinc-400 *:m-0",
447
- children
448
- }) : null]
449
- })]
450
- }), href ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
451
- className: "absolute inset-0 rounded-[var(--clarify-theme-tokens-radius-xl)]",
452
- "aria-hidden": "true"
453
- }) : null] });
454
- const classes = (0, clsx.default)("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);
455
- if (!href) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
456
- className: classes,
457
- children: content
458
- });
459
- if (href.startsWith("/") && !href.startsWith("//")) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
460
- to: href,
461
- className: classes,
462
- ...props,
463
- children: content
464
- });
465
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
466
- href,
467
- className: classes,
468
- ...props,
469
- children: content
470
- });
231
+ function prefixHref(href, routePrefix = "/") {
232
+ if (isExternalHref(href) || href.startsWith("#")) return href;
233
+ if (!routePrefix || routePrefix === "/") return href.startsWith("/") ? href : `/${href}`;
234
+ const prefix = routePrefix.replace(/^\/+|\/+$/g, "");
235
+ const path = href.replace(/^\/+/, "");
236
+ if (!path) return `/${prefix}`;
237
+ if (path === prefix || path.startsWith(`${prefix}/`)) return `/${path}`;
238
+ return `/${prefix}/${path}`;
471
239
  }
472
240
  //#endregion
473
- //#region source/components/Code.tsx
474
- var languageNames = {
475
- js: "JavaScript",
476
- ts: "TypeScript",
477
- jsx: "React JSX",
478
- tsx: "React TSX",
479
- javascript: "JavaScript",
480
- typescript: "TypeScript",
481
- php: "PHP",
482
- python: "Python",
483
- ruby: "Ruby",
484
- go: "Go",
485
- bash: "Shell",
486
- sh: "Shell",
487
- shell: "Shell",
488
- json: "JSON"
489
- };
490
- function getPanelTitle(arg0) {
491
- const { title, language, fallbackTitle = "Code" } = arg0;
492
- if (title) return title;
493
- if (language && language in languageNames) return languageNames[language];
494
- return fallbackTitle;
241
+ //#region source/shell/ContentActions.tsx
242
+ function resolveContentArtifactUrl(contentArtifactUrl, routePrefix = "/") {
243
+ return prefixHref(contentArtifactUrl, routePrefix);
495
244
  }
496
- function getNodeText(node) {
497
- if (typeof node === "string" || typeof node === "number") return String(node);
498
- if (Array.isArray(node)) return node.map(getNodeText).join("");
499
- if ((0, react.isValidElement)(node)) return getNodeText(node.props.children);
500
- return "";
245
+ function getAbsoluteUrl(path) {
246
+ if (typeof window === "undefined") return path;
247
+ return new URL(path, window.location.href).href;
501
248
  }
502
- function ClipboardIcon(props) {
249
+ function ContentActions(arg0) {
250
+ const { hasTabs = false, route, routePrefix } = arg0;
251
+ const t = useBuiltInText();
252
+ const [copied, setCopied] = (0, react.useState)("idle");
253
+ if (!route?.contentArtifactUrl) return null;
254
+ const contentArtifactUrl = resolveContentArtifactUrl(route.contentArtifactUrl, routePrefix);
255
+ const isOpenApi = route.kind === "openapi";
256
+ const replacements = { contentType: isOpenApi ? "OpenAPI" : "Markdown" };
257
+ const viewLabel = isOpenApi ? t("contentActions.viewOpenApi") : t("contentActions.viewMarkdown");
258
+ const viewDescription = isOpenApi ? t("contentActions.viewOpenApiDescription") : t("contentActions.viewMarkdownDescription");
259
+ function markCopied(state) {
260
+ setCopied(state);
261
+ window.setTimeout(() => setCopied("idle"), 1600);
262
+ }
263
+ async function handleCopyContent() {
264
+ if (await copyTextToClipboard(await (await fetch(contentArtifactUrl)).text())) markCopied("content");
265
+ }
266
+ const llmsArtifactUrl = resolveContentArtifactUrl("/llms.txt", routePrefix);
267
+ async function handleCopyLink() {
268
+ if (await copyTextToClipboard(getAbsoluteUrl(contentArtifactUrl))) markCopied("link");
269
+ }
270
+ async function handleCopyLlms() {
271
+ if (await copyTextToClipboard(getAbsoluteUrl(llmsArtifactUrl))) markCopied("llms");
272
+ }
273
+ const actions = [{
274
+ key: "content",
275
+ label: t("contentActions.copyContent"),
276
+ description: t("contentActions.copyContentDescription", replacements),
277
+ icon: lucide_react.Copy,
278
+ run: handleCopyContent,
279
+ copiedLabel: t("contentActions.copiedContent")
280
+ }, {
281
+ key: "link",
282
+ label: t("contentActions.copyLink", replacements),
283
+ description: t("contentActions.copyLinkDescription", replacements),
284
+ icon: lucide_react.Link2,
285
+ run: handleCopyLink,
286
+ copiedLabel: t("contentActions.copiedLink")
287
+ }];
288
+ const llmsAction = {
289
+ key: "llms",
290
+ label: t("contentActions.copyLlms"),
291
+ description: t("contentActions.copyLlmsDescription"),
292
+ icon: lucide_react.FileText,
293
+ run: handleCopyLlms,
294
+ copiedLabel: t("contentActions.copiedLlms")
295
+ };
296
+ const primaryAction = actions[0];
297
+ const PrimaryIcon = copied === primaryAction.key ? lucide_react.Check : primaryAction.icon;
298
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
299
+ className: `clarify-content-actions sticky z-20 flex justify-end py-4 ${hasTabs ? "top-16 lg:top-30" : "top-16"}`,
300
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.Menu, {
301
+ as: "div",
302
+ className: "clarify-content-actions-menu relative inline-flex text-sm font-medium",
303
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
304
+ 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",
305
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
306
+ type: "button",
307
+ onClick: primaryAction.run,
308
+ className: "clarify-content-actions-primary clarify-ui-control inline-flex h-8 items-center gap-1.5 px-3 transition",
309
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PrimaryIcon, { className: "h-3.5 w-3.5" }), copied === primaryAction.key ? t("actions.copied") : primaryAction.label]
310
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuButton, {
311
+ 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",
312
+ "aria-label": t("contentActions.copyOptions"),
313
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronDown, { className: "h-3.5 w-3.5" })
314
+ })]
315
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.MenuItems, {
316
+ anchor: "bottom end",
317
+ 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",
318
+ children: [
319
+ actions.slice(0, 1).map((action) => {
320
+ const Icon = action.icon;
321
+ const isCopied = copied === action.key;
322
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
323
+ type: "button",
324
+ onClick: action.run,
325
+ 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",
326
+ children: [
327
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
328
+ 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",
329
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: "h-4 w-4" })
330
+ }),
331
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
332
+ className: "flex min-w-0 flex-1 flex-col px-1",
333
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
334
+ className: "clarify-ui-menu-title",
335
+ children: isCopied ? t("contentActions.copiedContent") : action.label
336
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
337
+ className: "clarify-ui-menu-description truncate",
338
+ children: action.description
339
+ })]
340
+ }),
341
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: `h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) transition ${isCopied ? "opacity-100" : "opacity-0"}` })
342
+ ]
343
+ }) }, action.key);
344
+ }),
345
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
346
+ href: contentArtifactUrl,
347
+ target: "_blank",
348
+ rel: "noreferrer",
349
+ 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",
350
+ children: [
351
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
352
+ 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",
353
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.FileText, { className: "h-4 w-4" })
354
+ }),
355
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
356
+ className: "flex min-w-0 flex-1 flex-col px-1",
357
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
358
+ className: "clarify-ui-menu-title flex items-center gap-1",
359
+ children: [viewLabel, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ExternalLink, { className: "clarify-ui-menu-icon h-3 w-3" })]
360
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
361
+ className: "clarify-ui-menu-description truncate",
362
+ children: viewDescription
363
+ })]
364
+ }),
365
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) opacity-0" })
366
+ ]
367
+ }) }),
368
+ actions.slice(1).map((action) => {
369
+ const Icon = action.icon;
370
+ const isCopied = copied === action.key;
371
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
372
+ type: "button",
373
+ onClick: action.run,
374
+ 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",
375
+ children: [
376
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
377
+ 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",
378
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: "h-4 w-4" })
379
+ }),
380
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
381
+ className: "flex min-w-0 flex-1 flex-col px-1",
382
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
383
+ className: "clarify-ui-menu-title",
384
+ children: isCopied ? action.copiedLabel ?? action.label : action.label
385
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
386
+ className: "clarify-ui-menu-description truncate",
387
+ children: action.description
388
+ })]
389
+ }),
390
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: `h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) transition ${isCopied ? "opacity-100" : "opacity-0"}` })
391
+ ]
392
+ }) }, action.key);
393
+ }),
394
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
395
+ type: "button",
396
+ onClick: llmsAction.run,
397
+ 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",
398
+ children: [
399
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
400
+ 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",
401
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.FileText, { className: "h-4 w-4" })
402
+ }),
403
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
404
+ className: "flex min-w-0 flex-1 flex-col px-1",
405
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
406
+ className: "clarify-ui-menu-title",
407
+ children: copied === llmsAction.key ? llmsAction.copiedLabel ?? llmsAction.label : llmsAction.label
408
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
409
+ className: "clarify-ui-menu-description truncate",
410
+ children: llmsAction.description
411
+ })]
412
+ }),
413
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: `h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) transition ${copied === llmsAction.key ? "opacity-100" : "opacity-0"}` })
414
+ ]
415
+ }) }, llmsAction.key)
416
+ ]
417
+ })]
418
+ })
419
+ });
420
+ }
421
+ //#endregion
422
+ //#region source/theme/ThemeProvider.tsx
423
+ var ThemeContext = (0, react.createContext)(null);
424
+ var storageKey = "clarify:theme";
425
+ function getSystemTheme() {
426
+ if (typeof window === "undefined") return "light";
427
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
428
+ }
429
+ function getStoredTheme() {
430
+ if (typeof window === "undefined") return "system";
431
+ try {
432
+ const storedTheme = window.localStorage.getItem(storageKey);
433
+ return storedTheme === "light" || storedTheme === "dark" || storedTheme === "system" ? storedTheme : "system";
434
+ } catch {
435
+ return "system";
436
+ }
437
+ }
438
+ function storeTheme(theme) {
439
+ if (typeof window === "undefined") return;
440
+ try {
441
+ window.localStorage.setItem(storageKey, theme);
442
+ } catch {}
443
+ }
444
+ function applyTheme(resolvedTheme) {
445
+ if (typeof document === "undefined") return;
446
+ document.documentElement.classList.toggle("dark", resolvedTheme === "dark");
447
+ document.documentElement.style.colorScheme = resolvedTheme;
448
+ }
449
+ function ThemeProvider(arg0) {
450
+ const { children } = arg0;
451
+ const [theme, setThemeState] = (0, react.useState)(() => getStoredTheme());
452
+ const [systemTheme, setSystemTheme] = (0, react.useState)(() => getSystemTheme());
453
+ const resolvedTheme = theme === "system" ? systemTheme : theme;
454
+ (0, react.useEffect)(() => {
455
+ applyTheme(resolvedTheme);
456
+ }, [resolvedTheme]);
457
+ (0, react.useEffect)(() => {
458
+ if (typeof window === "undefined") return;
459
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
460
+ function updateSystemTheme() {
461
+ setSystemTheme(mediaQuery.matches ? "dark" : "light");
462
+ }
463
+ updateSystemTheme();
464
+ mediaQuery.addEventListener("change", updateSystemTheme);
465
+ return () => mediaQuery.removeEventListener("change", updateSystemTheme);
466
+ }, []);
467
+ const value = (0, react.useMemo)(() => ({
468
+ theme,
469
+ resolvedTheme,
470
+ setTheme(nextTheme) {
471
+ setThemeState(nextTheme);
472
+ storeTheme(nextTheme);
473
+ }
474
+ }), [resolvedTheme, theme]);
475
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeContext.Provider, {
476
+ value,
477
+ children
478
+ });
479
+ }
480
+ function useTheme() {
481
+ const context = (0, react.useContext)(ThemeContext);
482
+ if (!context) throw new Error("[clarify] useTheme must be used within ThemeProvider");
483
+ return context;
484
+ }
485
+ //#endregion
486
+ //#region source/theme/ThemeToggle.tsx
487
+ function SunIcon(props) {
503
488
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
504
489
  viewBox: "0 0 20 20",
490
+ fill: "none",
505
491
  "aria-hidden": "true",
506
492
  ...props,
507
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
508
- strokeWidth: "0",
509
- 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"
510
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
511
- fill: "none",
512
- strokeLinejoin: "round",
513
- 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"
493
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M12.5 10a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Z" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
494
+ strokeLinecap: "round",
495
+ 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"
514
496
  })]
515
497
  });
516
498
  }
517
- function CopyButton(arg0) {
518
- const { code } = arg0;
499
+ function MoonIcon(props) {
500
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
501
+ viewBox: "0 0 20 20",
502
+ fill: "none",
503
+ "aria-hidden": "true",
504
+ ...props,
505
+ children: /* @__PURE__ */ (0, react_jsx_runtime.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" })
506
+ });
507
+ }
508
+ function ThemeToggle() {
509
+ const { resolvedTheme, setTheme } = useTheme();
519
510
  const t = useBuiltInText();
520
- const [copyCount, setCopyCount] = (0, react.useState)(0);
521
- const copied = copyCount > 0;
522
- (0, react.useEffect)(() => {
523
- if (copyCount === 0) return void 0;
524
- const timeout = window.setTimeout(() => setCopyCount(0), 1e3);
525
- return () => window.clearTimeout(timeout);
526
- }, [copyCount]);
527
- if (!code) return null;
511
+ const otherTheme = resolvedTheme === "dark" ? "light" : "dark";
528
512
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
529
513
  type: "button",
530
- className: (0, clsx.default)("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"),
531
- onClick: () => {
532
- window.navigator.clipboard.writeText(code).then(() => {
533
- setCopyCount((count) => count + 1);
534
- });
535
- },
536
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
537
- "aria-hidden": copied,
538
- className: (0, clsx.default)("pointer-events-none flex items-center gap-0.5 text-zinc-400 transition duration-300", copied && "-translate-y-1.5 opacity-0"),
539
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClipboardIcon, { className: "h-5 w-5 fill-zinc-500/20 stroke-zinc-500 transition-colors group-hover/button:stroke-zinc-400" }), t("actions.copy")]
540
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
541
- "aria-hidden": !copied,
542
- className: (0, clsx.default)("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"),
543
- children: t("actions.copied")
544
- })]
545
- });
546
- }
547
- function CodePanelHeader(arg0) {
548
- const { tag, label } = arg0;
549
- if (!tag && !label) return null;
550
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
551
- 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",
514
+ 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",
515
+ "aria-label": otherTheme === "dark" ? t("theme.switchToDark") : t("theme.switchToLight"),
516
+ onClick: () => setTheme(otherTheme),
552
517
  children: [
553
- tag ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
554
- className: "font-mono text-[0.625rem]/6 font-semibold text-[var(--clarify-theme-tokens-colors-primary)]",
555
- children: tag
556
- }) : null,
557
- tag && label ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "h-0.5 w-0.5 rounded-full bg-zinc-500" }) : null,
558
- label ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
559
- className: "font-mono text-xs text-zinc-400",
560
- children: label
561
- }) : null
518
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "absolute size-12 pointer-fine:hidden" }),
519
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SunIcon, { className: "h-5 w-5 stroke-(--clarify-theme-tokens-colors-foreground) dark:hidden" }),
520
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MoonIcon, { className: "hidden h-5 w-5 stroke-white dark:block" })
562
521
  ]
563
522
  });
564
523
  }
565
- function CodePanel(arg0) {
566
- const { children } = arg0;
567
- let { tag, label, code } = arg0;
568
- const child = react.Children.only(children);
569
- if ((0, react.isValidElement)(child)) {
570
- const props = child.props;
571
- tag = props.tag ?? tag;
572
- label = props.label ?? label;
573
- code = props.code ?? code ?? getNodeText(props.children);
524
+ //#endregion
525
+ //#region source/utils/path.ts
526
+ function normalizeRoutePath(path) {
527
+ const [pathname, suffix = ""] = path.split(/([?#].*)/, 2);
528
+ return `${pathname.replace(/^\/+/, "/").replace(/\/+$/, "") || "/"}${suffix}`;
529
+ }
530
+ function isSameRoutePath(a, b) {
531
+ if (!a || !b) return false;
532
+ return normalizeRoutePath(a) === normalizeRoutePath(b);
533
+ }
534
+ //#endregion
535
+ //#region source/utils/lucide.ts
536
+ /**
537
+ * Registry of all Lucide icon components keyed by their PascalCase export name.
538
+ *
539
+ * Access icons via index lookup (e.g. `lucideIconRegistry[name]`) so React
540
+ * tooling does not mistake the access for a component created during render.
541
+ */
542
+ var lucideIconRegistry = lucide_react;
543
+ function toPascalCase(value) {
544
+ return value.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join("");
545
+ }
546
+ /**
547
+ * Resolve an icon name into the matching Lucide registry key.
548
+ *
549
+ * Accepts both the exact PascalCase export name (e.g. `ArrowRight`) and
550
+ * kebab/space/snake variants (e.g. `arrow-right`), returning `undefined`
551
+ * when no matching icon exists.
552
+ */
553
+ function resolveLucideIconName(name) {
554
+ if (!name) return void 0;
555
+ if (lucideIconRegistry[name]) return name;
556
+ const pascalName = toPascalCase(name);
557
+ return lucideIconRegistry[pascalName] ? pascalName : void 0;
558
+ }
559
+ //#endregion
560
+ //#region source/shell/icons.tsx
561
+ function NavigationIcon(arg0) {
562
+ const { name, className } = arg0;
563
+ if (!name) return null;
564
+ const iconName = resolveLucideIconName(name);
565
+ if (!iconName) return null;
566
+ const Icon = lucideIconRegistry[iconName];
567
+ if (!Icon) return null;
568
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
569
+ className: (0, clsx.default)("shrink-0 stroke-current", className),
570
+ "aria-hidden": "true"
571
+ });
572
+ }
573
+ //#endregion
574
+ //#region source/utils/remToPx.ts
575
+ function remToPx(remValue) {
576
+ return remValue * (typeof window === "undefined" ? 16 : Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize));
577
+ }
578
+ //#endregion
579
+ //#region source/app/SectionProvider.tsx
580
+ function createSectionStore(sections) {
581
+ return (0, zustand.createStore)()((set) => ({
582
+ sections,
583
+ visibleSections: [],
584
+ setVisibleSections: (visibleSections) => set((state) => state.visibleSections.join() === visibleSections.join() ? {} : { visibleSections }),
585
+ registerHeading: ({ id, ref, offsetRem }) => set((state) => ({ sections: state.sections.map((section) => section.id === id ? {
586
+ ...section,
587
+ headingRef: ref,
588
+ offsetRem
589
+ } : section) }))
590
+ }));
591
+ }
592
+ function useVisibleSections(sectionStore) {
593
+ const setVisibleSections = (0, zustand.useStore)(sectionStore, (state) => state.setVisibleSections);
594
+ const sections = (0, zustand.useStore)(sectionStore, (state) => state.sections);
595
+ (0, react.useEffect)(() => {
596
+ function checkVisibleSections() {
597
+ const { innerHeight, scrollY } = window;
598
+ const viewportTop = scrollY;
599
+ const viewportBottom = scrollY + innerHeight;
600
+ const newVisibleSections = [];
601
+ for (let sectionIndex = 0; sectionIndex < sections.length; sectionIndex += 1) {
602
+ const { id, headingRef, offsetRem = 0 } = sections[sectionIndex];
603
+ if (!headingRef?.current) continue;
604
+ const offset = remToPx(offsetRem);
605
+ const top = headingRef.current.getBoundingClientRect().top + scrollY;
606
+ if (sectionIndex === 0 && top - offset > viewportTop) newVisibleSections.push("_top");
607
+ if ((sections[sectionIndex + 1]?.headingRef?.current?.getBoundingClientRect().top ?? Infinity) + scrollY > viewportTop && top < viewportBottom) newVisibleSections.push(id);
608
+ }
609
+ setVisibleSections(newVisibleSections);
610
+ }
611
+ const raf = window.requestAnimationFrame(() => checkVisibleSections());
612
+ window.addEventListener("scroll", checkVisibleSections, { passive: true });
613
+ window.addEventListener("resize", checkVisibleSections);
614
+ return () => {
615
+ window.cancelAnimationFrame(raf);
616
+ window.removeEventListener("scroll", checkVisibleSections);
617
+ window.removeEventListener("resize", checkVisibleSections);
618
+ };
619
+ }, [setVisibleSections, sections]);
620
+ }
621
+ var SectionStoreContext = (0, react.createContext)(null);
622
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? react.useEffect : react.useLayoutEffect;
623
+ function SectionProvider(arg0) {
624
+ const { sections, children } = arg0;
625
+ const [sectionStore] = (0, react.useState)(() => createSectionStore(sections));
626
+ useVisibleSections(sectionStore);
627
+ useIsomorphicLayoutEffect(() => {
628
+ sectionStore.setState((state) => ({
629
+ sections: sections.map((section) => {
630
+ const registeredSection = state.sections.find((item) => item.id === section.id);
631
+ return {
632
+ ...section,
633
+ headingRef: registeredSection?.headingRef,
634
+ offsetRem: registeredSection?.offsetRem ?? section.offsetRem
635
+ };
636
+ }),
637
+ visibleSections: []
638
+ }));
639
+ }, [sectionStore, sections]);
640
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionStoreContext.Provider, {
641
+ value: sectionStore,
642
+ children
643
+ });
644
+ }
645
+ function useSectionStore(selector) {
646
+ const store = (0, react.useContext)(SectionStoreContext);
647
+ if (!store) throw new Error("[clarify] useSectionStore must be used within SectionProvider");
648
+ return (0, zustand.useStore)(store, selector);
649
+ }
650
+ //#endregion
651
+ //#region source/components/Button.tsx
652
+ function ArrowIcon(props) {
653
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
654
+ viewBox: "0 0 20 20",
655
+ fill: "none",
656
+ "aria-hidden": "true",
657
+ ...props,
658
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
659
+ stroke: "currentColor",
660
+ strokeLinecap: "round",
661
+ strokeLinejoin: "round",
662
+ d: "m11.5 6.5 3 3.5m0 0-3 3.5m3-3.5h-9"
663
+ })
664
+ });
665
+ }
666
+ var buttonVariantStyles = {
667
+ 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",
668
+ 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",
669
+ 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",
670
+ 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",
671
+ text: "text-(--clarify-theme-tokens-colors-primary) hover:opacity-80 dark:text-(--clarify-theme-tokens-colors-primary) dark:hover:opacity-80"
672
+ };
673
+ function Button(arg0) {
674
+ const { variant = "primary", className, children, arrow, ...props } = arg0;
675
+ const classes = (0, clsx.default)("clarify-button inline-flex justify-center gap-0.5 overflow-hidden text-sm font-medium transition", buttonVariantStyles[variant], className);
676
+ const arrowIcon = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArrowIcon, { className: (0, clsx.default)("mt-0.5 h-5 w-5", variant === "text" && "relative top-px", arrow === "left" && "-ml-1 rotate-180", arrow === "right" && "-mr-1") });
677
+ const inner = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
678
+ arrow === "left" ? arrowIcon : null,
679
+ children,
680
+ arrow === "right" ? arrowIcon : null
681
+ ] });
682
+ if (typeof props.href === "undefined") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
683
+ className: classes,
684
+ ...props,
685
+ children: inner
686
+ });
687
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
688
+ className: classes,
689
+ ...props,
690
+ children: inner
691
+ });
692
+ }
693
+ //#endregion
694
+ //#region source/components/Callout.tsx
695
+ var calloutStyles = {
696
+ info: {
697
+ 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",
698
+ icon: "text-sky-600 dark:text-sky-400",
699
+ title: "text-sky-900 dark:text-sky-100",
700
+ Icon: lucide_react.Info
701
+ },
702
+ note: {
703
+ container: "border-zinc-500/20 bg-zinc-50 text-zinc-900 dark:border-white/10 dark:bg-white/5 dark:text-zinc-200",
704
+ icon: "text-zinc-500 dark:text-zinc-400",
705
+ title: "text-zinc-900 dark:text-white",
706
+ Icon: lucide_react.Info
707
+ },
708
+ tip: {
709
+ 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",
710
+ icon: "text-emerald-600 dark:text-emerald-400",
711
+ title: "text-emerald-900 dark:text-emerald-100",
712
+ Icon: lucide_react.Lightbulb
713
+ },
714
+ warning: {
715
+ 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",
716
+ icon: "text-amber-600 dark:text-amber-400",
717
+ title: "text-amber-900 dark:text-amber-100",
718
+ Icon: lucide_react.AlertTriangle
719
+ },
720
+ danger: {
721
+ 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",
722
+ icon: "text-rose-600 dark:text-rose-400",
723
+ title: "text-rose-900 dark:text-rose-100",
724
+ Icon: lucide_react.XCircle
725
+ },
726
+ success: {
727
+ 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",
728
+ icon: "text-emerald-600 dark:text-emerald-400",
729
+ title: "text-emerald-900 dark:text-emerald-100",
730
+ Icon: lucide_react.CheckCircle2
574
731
  }
575
- const copyText = code ?? getNodeText(children);
732
+ };
733
+ var defaultTitleKeys = {
734
+ info: "callout.info",
735
+ note: "callout.note",
736
+ tip: "callout.tip",
737
+ warning: "callout.warning",
738
+ danger: "callout.danger",
739
+ success: "callout.success"
740
+ };
741
+ function Callout(arg0) {
742
+ const { children, type = "info", title, icon = true, className, ...props } = arg0;
743
+ const t = useBuiltInText();
744
+ const style = calloutStyles[type];
745
+ const Icon = style.Icon;
746
+ const resolvedTitle = title === void 0 ? t(defaultTitleKeys[type]) : title;
576
747
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
577
- className: "clarify-code-panel group dark:bg-white/2.5",
578
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodePanelHeader, {
579
- tag,
580
- label
581
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
582
- className: "relative",
583
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
584
- className: "clarify-code-pre overflow-x-auto p-4 text-xs text-white",
748
+ className: (0, clsx.default)("clarify-callout my-6 flex gap-3 rounded-(--clarify-theme-tokens-radius-xl) border p-4 text-sm/6", style.container, className),
749
+ ...props,
750
+ children: [icon ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
751
+ className: (0, clsx.default)("mt-1 size-4 flex-none", style.icon),
752
+ "aria-hidden": "true"
753
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
754
+ className: "min-w-0 flex-1 *:first:mt-0 *:last:mb-0",
755
+ children: [resolvedTitle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
756
+ className: (0, clsx.default)("mb-1 font-semibold", style.title),
757
+ children: resolvedTitle
758
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
759
+ className: "*:first:mt-0 *:last:mb-0",
585
760
  children
586
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyButton, { code: copyText })]
761
+ })]
587
762
  })]
588
763
  });
589
764
  }
590
- function CodeGroupHeader(arg0) {
591
- const { title, children, selectedIndex } = arg0;
592
- const t = useBuiltInText();
593
- const hasTabs = react.Children.count(children) > 1;
594
- if (!title && !hasTabs) return null;
595
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
596
- 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",
597
- children: [title ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
598
- className: "mr-auto pt-3 text-xs font-semibold text-white",
599
- children: title
600
- }) : null, hasTabs ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.TabList, {
601
- className: "clarify-code-tabs -mb-px flex gap-4 text-xs font-medium",
602
- children: react.Children.map(children, (child, childIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.Tab, {
603
- className: (0, clsx.default)("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"),
604
- children: getPanelTitle({
605
- ...(0, react.isValidElement)(child) ? child.props : {},
606
- fallbackTitle: t("actions.code")
607
- })
608
- }))
609
- }) : null]
765
+ //#endregion
766
+ //#region source/components/Card.tsx
767
+ function CardIcon(arg0) {
768
+ const { name } = arg0;
769
+ if (!name) return null;
770
+ const iconName = resolveLucideIconName(name);
771
+ if (!iconName) return null;
772
+ const Icon = lucideIconRegistry[iconName];
773
+ if (!Icon) return null;
774
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
775
+ 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)",
776
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
777
+ className: "size-5",
778
+ "aria-hidden": "true"
779
+ })
610
780
  });
611
781
  }
612
- function CodeGroupPanels(arg0) {
613
- const { children, ...props } = arg0;
614
- if (react.Children.count(children) > 1) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.TabPanels, { children: react.Children.map(children, (child) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.TabPanel, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodePanel, {
615
- ...props,
616
- children: child
617
- }) })) });
618
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodePanel, {
619
- ...props,
782
+ var cardGroupColumnStyles = {
783
+ 1: "grid-cols-1",
784
+ 2: "grid-cols-1 sm:grid-cols-2",
785
+ 3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
786
+ 4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4"
787
+ };
788
+ function CardGroup(arg0) {
789
+ const { children, cols = 2, className } = arg0;
790
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
791
+ className: (0, clsx.default)("not-prose my-10 grid gap-4", cardGroupColumnStyles[cols], className),
620
792
  children
621
793
  });
622
794
  }
623
- function usePreventLayoutShift() {
624
- const positionRef = (0, react.useRef)(null);
625
- const rafRef = (0, react.useRef)(void 0);
626
- (0, react.useEffect)(() => {
627
- return () => {
628
- if (typeof rafRef.current !== "undefined") window.cancelAnimationFrame(rafRef.current);
629
- };
630
- }, []);
631
- return {
632
- positionRef,
633
- preventLayoutShift(callback) {
634
- if (!positionRef.current) return;
635
- const initialTop = positionRef.current.getBoundingClientRect().top;
636
- callback();
637
- rafRef.current = window.requestAnimationFrame(() => {
638
- const newTop = positionRef.current?.getBoundingClientRect().top ?? initialTop;
639
- window.scrollBy(0, newTop - initialTop);
640
- });
641
- }
642
- };
643
- }
644
- var usePreferredLanguageStore = (0, zustand.create)()((set) => ({
645
- preferredLanguages: [],
646
- addPreferredLanguage: (language) => set((state) => ({ preferredLanguages: [...state.preferredLanguages.filter((preferredLanguage) => preferredLanguage !== language), language] }))
647
- }));
648
- function useTabGroupProps(availableLanguages) {
649
- const { preferredLanguages, addPreferredLanguage } = usePreferredLanguageStore();
650
- const [selectedIndex, setSelectedIndex] = (0, react.useState)(0);
651
- const activeLanguage = [...availableLanguages].sort((a, z) => preferredLanguages.indexOf(z) - preferredLanguages.indexOf(a))[0];
652
- const languageIndex = availableLanguages.indexOf(activeLanguage);
653
- const newSelectedIndex = languageIndex === -1 ? selectedIndex : languageIndex;
654
- if (newSelectedIndex !== selectedIndex) setSelectedIndex(newSelectedIndex);
655
- const { positionRef, preventLayoutShift } = usePreventLayoutShift();
656
- return {
657
- as: "div",
658
- ref: positionRef,
659
- selectedIndex,
660
- onChange: (nextSelectedIndex) => {
661
- preventLayoutShift(() => addPreferredLanguage(availableLanguages[nextSelectedIndex]));
662
- }
663
- };
664
- }
665
- var CodeGroupContext = (0, react.createContext)(false);
666
- function CodeGroup(arg0) {
667
- const { children, title, ...props } = arg0;
668
- const t = useBuiltInText();
669
- const tabGroupProps = useTabGroupProps(react.Children.map(children, (child) => getPanelTitle({
670
- ...(0, react.isValidElement)(child) ? child.props : {},
671
- fallbackTitle: t("actions.code")
672
- })) ?? []);
673
- const hasTabs = react.Children.count(children) > 1;
674
- const containerClassName = "clarify-code-group my-6 overflow-hidden rounded-2xl bg-zinc-900 shadow-md dark:ring-1 dark:ring-white/10";
675
- const header = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeGroupHeader, {
676
- title,
677
- selectedIndex: tabGroupProps.selectedIndex,
678
- children
679
- });
680
- const panels = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeGroupPanels, {
681
- ...props,
682
- children
683
- });
684
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeGroupContext.Provider, {
685
- value: true,
686
- children: hasTabs ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.TabGroup, {
687
- ...tabGroupProps,
688
- className: containerClassName,
689
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
690
- className: "not-prose",
691
- children: [header, panels]
692
- })
693
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
694
- className: containerClassName,
695
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
696
- className: "not-prose",
697
- children: [header, panels]
698
- })
699
- })
795
+ function Card(arg0) {
796
+ const { title, icon, href, children, className, ...props } = arg0;
797
+ const content = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
798
+ className: "flex items-start gap-4",
799
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardIcon, { name: icon }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
800
+ className: "min-w-0 flex-1",
801
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
802
+ className: "m-0 text-base font-semibold text-(--clarify-theme-tokens-colors-foreground) dark:text-white",
803
+ children: title
804
+ }), children ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
805
+ className: "mt-2 text-sm/6 text-(--clarify-theme-tokens-colors-muted) dark:text-zinc-400 *:m-0",
806
+ children
807
+ }) : null]
808
+ })]
809
+ }), href ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
810
+ className: "absolute inset-0 rounded-(--clarify-theme-tokens-radius-xl)",
811
+ "aria-hidden": "true"
812
+ }) : null] });
813
+ const classes = (0, clsx.default)("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);
814
+ if (!href) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
815
+ className: classes,
816
+ children: content
700
817
  });
701
- }
702
- function Code(arg0) {
703
- const { children, ...props } = arg0;
704
- if ((0, react.useContext)(CodeGroupContext) && typeof children === "string") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
818
+ if (href.startsWith("/") && !href.startsWith("//")) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
819
+ to: href,
820
+ className: classes,
705
821
  ...props,
706
- dangerouslySetInnerHTML: { __html: children }
822
+ children: content
707
823
  });
708
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
824
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
825
+ href,
826
+ className: classes,
709
827
  ...props,
710
- children
828
+ children: content
711
829
  });
712
830
  }
713
- function Pre(arg0) {
714
- const { children, ...props } = arg0;
715
- if ((0, react.useContext)(CodeGroupContext)) return children;
716
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeGroup, {
717
- ...props,
718
- children
719
- });
831
+ //#endregion
832
+ //#region source/components/Code.tsx
833
+ var languageNames = {
834
+ js: "JavaScript",
835
+ ts: "TypeScript",
836
+ jsx: "React JSX",
837
+ tsx: "React TSX",
838
+ javascript: "JavaScript",
839
+ typescript: "TypeScript",
840
+ php: "PHP",
841
+ python: "Python",
842
+ ruby: "Ruby",
843
+ go: "Go",
844
+ bash: "Shell",
845
+ sh: "Shell",
846
+ shell: "Shell",
847
+ json: "JSON"
848
+ };
849
+ function getPanelTitle(arg0) {
850
+ const { title, language, fallbackTitle = "Code" } = arg0;
851
+ if (title) return title;
852
+ if (language && language in languageNames) return languageNames[language];
853
+ return fallbackTitle;
854
+ }
855
+ function getNodeText(node) {
856
+ if (typeof node === "string" || typeof node === "number") return String(node);
857
+ if (Array.isArray(node)) return node.map(getNodeText).join("");
858
+ if ((0, react.isValidElement)(node)) return getNodeText(node.props.children);
859
+ return "";
720
860
  }
721
- //#endregion
722
- //#region source/components/Feedback.tsx
723
- function CheckIcon(props) {
861
+ function ClipboardIcon(props) {
724
862
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
725
863
  viewBox: "0 0 20 20",
726
864
  "aria-hidden": "true",
727
865
  ...props,
728
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
729
- cx: "10",
730
- cy: "10",
731
- r: "10",
732
- strokeWidth: "0"
866
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
867
+ strokeWidth: "0",
868
+ 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"
733
869
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
734
870
  fill: "none",
735
- strokeLinecap: "round",
736
871
  strokeLinejoin: "round",
737
- strokeWidth: "1.5",
738
- d: "m6.75 10.813 2.438 2.437c1.218-4.469 4.062-6.5 4.062-6.5"
872
+ 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"
739
873
  })]
740
874
  });
741
875
  }
742
- function FeedbackButton(props) {
743
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
744
- type: "submit",
745
- 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",
746
- ...props
747
- });
748
- }
749
- var FeedbackForm = (0, react.forwardRef)(function FeedbackForm(arg0, ref) {
750
- const { onSubmit, className, ...props } = arg0;
751
- const t = useBuiltInText();
752
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
753
- ...props,
754
- ref,
755
- onSubmit,
756
- className: (0, clsx.default)(className, "clarify-feedback-form absolute inset-0 flex items-center justify-center gap-6 md:justify-start"),
757
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
758
- className: "text-sm text-zinc-600 dark:text-zinc-400",
759
- children: t("feedback.prompt")
760
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
761
- 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",
762
- children: [
763
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackButton, {
764
- "data-response": "yes",
765
- children: t("feedback.yes")
766
- }),
767
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "bg-zinc-900/10 dark:bg-white/10" }),
768
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackButton, {
769
- "data-response": "no",
770
- children: t("feedback.no")
771
- })
772
- ]
773
- })]
774
- });
775
- });
776
- var FeedbackThanks = (0, react.forwardRef)(function FeedbackThanks(arg0, ref) {
777
- const { className, ...props } = arg0;
876
+ function CopyButton(arg0) {
877
+ const { code } = arg0;
778
878
  const t = useBuiltInText();
779
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
780
- ...props,
781
- ref,
782
- className: (0, clsx.default)(className, "clarify-feedback-thanks absolute inset-0 flex justify-center md:justify-start"),
783
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
784
- 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",
785
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CheckIcon, { 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")]
786
- })
787
- });
788
- });
789
- function Feedback() {
790
- const [submitted, setSubmitted] = (0, react.useState)(false);
791
- function onSubmit(event) {
792
- event.preventDefault();
793
- setSubmitted(true);
794
- }
795
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
796
- className: "clarify-feedback relative h-8",
797
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.Transition, {
798
- show: !submitted,
799
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackForm, {
800
- className: "duration-300 data-closed:opacity-0 data-leave:pointer-events-none",
801
- onSubmit
802
- })
803
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.Transition, {
804
- show: submitted,
805
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackThanks, { className: "delay-150 duration-300 data-closed:opacity-0" })
879
+ const [copyCount, setCopyCount] = (0, react.useState)(0);
880
+ const copied = copyCount > 0;
881
+ (0, react.useEffect)(() => {
882
+ if (copyCount === 0) return void 0;
883
+ const timeout = window.setTimeout(() => setCopyCount(0), 1e3);
884
+ return () => window.clearTimeout(timeout);
885
+ }, [copyCount]);
886
+ if (!code) return null;
887
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
888
+ type: "button",
889
+ className: (0, clsx.default)("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"),
890
+ onClick: () => {
891
+ copyTextToClipboard(code).then((ok) => {
892
+ if (ok) setCopyCount((count) => count + 1);
893
+ });
894
+ },
895
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
896
+ "aria-hidden": copied,
897
+ className: (0, clsx.default)("pointer-events-none flex items-center gap-0.5 text-zinc-400 transition duration-300", copied && "-translate-y-1.5 opacity-0"),
898
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClipboardIcon, { className: "h-5 w-5 fill-zinc-500/20 stroke-zinc-500 transition-colors group-hover/button:stroke-zinc-400" }), t("actions.copy")]
899
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
900
+ "aria-hidden": !copied,
901
+ className: (0, clsx.default)("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"),
902
+ children: t("actions.copied")
806
903
  })]
807
904
  });
808
905
  }
809
- //#endregion
810
- //#region source/components/patterns.tsx
811
- function GridPattern(arg0) {
812
- const { width, height, x, y, squares, ...props } = arg0;
813
- const patternId = (0, react.useId)();
814
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
815
- "aria-hidden": "true",
816
- ...props,
906
+ function CodePanelHeader(arg0) {
907
+ const { tag, label } = arg0;
908
+ if (!tag && !label) return null;
909
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
910
+ 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",
817
911
  children: [
818
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pattern", {
819
- id: patternId,
820
- width,
821
- height,
822
- patternUnits: "userSpaceOnUse",
823
- x,
824
- y,
825
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
826
- d: `M.5 ${height}V.5H${width}`,
827
- fill: "none"
828
- })
829
- }) }),
830
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
831
- width: "100%",
832
- height: "100%",
833
- strokeWidth: 0,
834
- fill: `url(#${patternId})`
835
- }),
836
- squares ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
837
- x,
838
- y,
839
- className: "overflow-visible",
840
- children: squares.map(([squareX, squareY]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
841
- width: width + 1,
842
- height: height + 1,
843
- x: squareX * width,
844
- y: squareY * height,
845
- strokeWidth: "0"
846
- }, `${squareX}-${squareY}`))
912
+ tag ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
913
+ className: "clarify-code-panel-tag font-semibold text-(--clarify-theme-tokens-colors-primary)",
914
+ children: tag
915
+ }) : null,
916
+ tag && label ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "h-0.5 w-0.5 rounded-full bg-zinc-500" }) : null,
917
+ label ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
918
+ className: "text-xs text-zinc-400",
919
+ children: label
847
920
  }) : null
848
921
  ]
849
922
  });
850
923
  }
851
- function HeroPattern() {
852
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
853
- className: "absolute inset-0 -z-10 mx-0 max-w-none overflow-hidden",
854
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
855
- className: "absolute top-0 left-1/2 -ml-152 h-100 w-325 dark:mask-[linear-gradient(white,transparent)]",
856
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
857
- 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",
858
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GridPattern, {
859
- width: 72,
860
- height: 56,
861
- x: -12,
862
- y: 4,
863
- squares: [
864
- [4, 3],
865
- [2, 1],
866
- [7, 3],
867
- [10, 6]
868
- ],
869
- 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"
870
- })
871
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
872
- viewBox: "0 0 1113 440",
873
- "aria-hidden": "true",
874
- className: "absolute top-0 left-1/2 -ml-76 w-278.25 fill-white blur-[26px] dark:hidden",
875
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M.016 439.5s-9.5-300 434-300S882.516 20 882.516 20V0h230.004v439.5H.016Z" })
876
- })]
877
- })
878
- });
879
- }
880
- //#endregion
881
- //#region source/components/PageFooter.tsx
882
- function resolveLocalizedText$1(text, locale, fallbackLocale) {
883
- if (typeof text === "string") return text;
884
- return (locale ? text[locale] : void 0) ?? (fallbackLocale ? text[fallbackLocale] : void 0) ?? Object.values(text)[0] ?? "";
885
- }
886
- function isExternalHref$1(href) {
887
- return /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith("//");
888
- }
889
- function localeForPath$1(config, pathname) {
890
- const i18n = config.i18n;
891
- if (!i18n) return void 0;
892
- const firstSegment = pathname.split("/").filter(Boolean)[0];
893
- return i18n.locales.find((locale) => locale.code === firstSegment)?.code ?? i18n.defaultLocale;
894
- }
895
- function localizeHref$1(href, config, locale) {
896
- if (!locale || !config.i18n || isExternalHref$1(href) || href.startsWith("#")) return href;
897
- if (locale === config.i18n.defaultLocale) return href;
898
- const cleanHref = href === "/" ? "" : href.replace(/^\/+/, "");
899
- return `/${locale}${cleanHref ? `/${cleanHref}` : ""}`;
900
- }
901
- function FooterLink(arg0) {
902
- const { link, locale, config } = arg0;
903
- const external = link.external ?? isExternalHref$1(link.href);
904
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
905
- href: external ? link.href : localizeHref$1(link.href, config, locale),
906
- target: external ? "_blank" : void 0,
907
- rel: external ? "noreferrer" : void 0,
908
- className: "clarify-footer-link no-underline transition",
909
- children: resolveLocalizedText$1(link.label, locale, config.i18n?.defaultLocale)
924
+ function CodePanel(arg0) {
925
+ const { children } = arg0;
926
+ let { tag, label, code } = arg0;
927
+ const child = react.Children.only(children);
928
+ if ((0, react.isValidElement)(child)) {
929
+ const props = child.props;
930
+ tag = props.tag ?? tag;
931
+ label = props.label ?? label;
932
+ code = props.code ?? code ?? getNodeText(props.children);
933
+ }
934
+ const copyText = code ?? getNodeText(children);
935
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
936
+ className: "clarify-code-panel group dark:bg-white/2.5",
937
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodePanelHeader, {
938
+ tag,
939
+ label
940
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
941
+ className: "relative",
942
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
943
+ className: "clarify-code-pre overflow-x-auto p-4 text-xs text-white",
944
+ children
945
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyButton, { code: copyText })]
946
+ })]
910
947
  });
911
948
  }
912
- function SocialLink(arg0) {
913
- const { name, href } = arg0;
914
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
915
- href,
916
- target: "_blank",
917
- rel: "noreferrer",
918
- className: "clarify-footer-social capitalize no-underline transition",
919
- children: name
920
- });
921
- }
922
- function PageFooter() {
923
- const config = useClarifyConfig();
924
- const locale = localeForPath$1(config, (0, react_router_dom.useLocation)().pathname);
925
- const footer = config.footer;
926
- const links = footer?.links ?? [];
927
- const socials = Object.entries(footer?.socials ?? {});
928
- const copyright = footer?.copyright ? resolveLocalizedText$1(footer.copyright, locale, config.i18n?.defaultLocale) : void 0;
929
- const hasCustomFooter = Boolean(copyright || links.length > 0 || socials.length > 0);
930
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("footer", {
931
- className: (0, clsx.default)("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"),
932
- children: [hasCustomFooter ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
933
- className: "clarify-footer-content flex flex-col gap-3 text-right sm:text-left",
934
- children: [copyright ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
935
- className: "clarify-footer-copyright m-0",
936
- children: copyright
937
- }) : null, links.length > 0 || socials.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
938
- className: "clarify-footer-links flex flex-wrap justify-end gap-x-4 gap-y-2 sm:justify-start",
939
- children: [links.map((link) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FooterLink, {
940
- link,
941
- locale,
942
- config
943
- }, `${link.href}-${resolveLocalizedText$1(link.label, locale, config.i18n?.defaultLocale)}`)), socials.map(([name, href]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SocialLink, {
944
- name,
945
- href
946
- }, name))]
947
- }) : null]
948
- }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
949
- className: "clarify-footer-brand flex justify-end",
950
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BuiltWithClarify, {})
951
- })]
949
+ function CodeGroupHeader(arg0) {
950
+ const { title, children, selectedIndex } = arg0;
951
+ const t = useBuiltInText();
952
+ const hasTabs = react.Children.count(children) > 1;
953
+ if (!title && !hasTabs) return null;
954
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
955
+ 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",
956
+ children: [title ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
957
+ className: "mr-auto pt-3 text-xs font-semibold text-white",
958
+ children: title
959
+ }) : null, hasTabs ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.TabList, {
960
+ className: "clarify-code-tabs -mb-px flex gap-4 text-xs font-medium",
961
+ children: react.Children.map(children, (child, childIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.Tab, {
962
+ className: (0, clsx.default)("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"),
963
+ children: getPanelTitle({
964
+ ...(0, react.isValidElement)(child) ? child.props : {},
965
+ fallbackTitle: t("actions.code")
966
+ })
967
+ }))
968
+ }) : null]
952
969
  });
953
970
  }
954
- //#endregion
955
- //#region source/utils/path.ts
956
- function normalizeRoutePath(path) {
957
- const [pathname, suffix = ""] = path.split(/([?#].*)/, 2);
958
- return `${pathname.replace(/^\/+/, "/").replace(/\/+$/, "") || "/"}${suffix}`;
971
+ function CodeGroupPanels(arg0) {
972
+ const { children, ...props } = arg0;
973
+ if (react.Children.count(children) > 1) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.TabPanels, { children: react.Children.map(children, (child) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.TabPanel, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodePanel, {
974
+ ...props,
975
+ children: child
976
+ }) })) });
977
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodePanel, {
978
+ ...props,
979
+ children
980
+ });
959
981
  }
960
- function isSameRoutePath(a, b) {
961
- if (!a || !b) return false;
962
- return normalizeRoutePath(a) === normalizeRoutePath(b);
982
+ function usePreventLayoutShift() {
983
+ const positionRef = (0, react.useRef)(null);
984
+ const rafRef = (0, react.useRef)(void 0);
985
+ (0, react.useEffect)(() => {
986
+ return () => {
987
+ if (typeof rafRef.current !== "undefined") window.cancelAnimationFrame(rafRef.current);
988
+ };
989
+ }, []);
990
+ return {
991
+ positionRef,
992
+ preventLayoutShift(callback) {
993
+ if (!positionRef.current) return;
994
+ const initialTop = positionRef.current.getBoundingClientRect().top;
995
+ callback();
996
+ rafRef.current = window.requestAnimationFrame(() => {
997
+ const newTop = positionRef.current?.getBoundingClientRect().top ?? initialTop;
998
+ window.scrollBy(0, newTop - initialTop);
999
+ });
1000
+ }
1001
+ };
963
1002
  }
964
- //#endregion
965
- //#region source/components/PageNavigation.tsx
966
- function flattenNavigation(nodes) {
967
- return nodes.flatMap((node) => node.children?.length ? flattenNavigation(node.children) : [node]);
1003
+ var usePreferredLanguageStore = (0, zustand.create)()((set) => ({
1004
+ preferredLanguages: [],
1005
+ addPreferredLanguage: (language) => set((state) => ({ preferredLanguages: [...state.preferredLanguages.filter((preferredLanguage) => preferredLanguage !== language), language] }))
1006
+ }));
1007
+ function useTabGroupProps(availableLanguages) {
1008
+ const { preferredLanguages, addPreferredLanguage } = usePreferredLanguageStore();
1009
+ const [selectedIndex, setSelectedIndex] = (0, react.useState)(0);
1010
+ if (new Set(availableLanguages).size === availableLanguages.length) {
1011
+ const activeLanguage = [...availableLanguages].sort((a, z) => preferredLanguages.indexOf(z) - preferredLanguages.indexOf(a))[0];
1012
+ const languageIndex = availableLanguages.indexOf(activeLanguage);
1013
+ const newSelectedIndex = languageIndex === -1 ? selectedIndex : languageIndex;
1014
+ if (newSelectedIndex !== selectedIndex) setSelectedIndex(newSelectedIndex);
1015
+ }
1016
+ const { positionRef, preventLayoutShift } = usePreventLayoutShift();
1017
+ return {
1018
+ as: "div",
1019
+ ref: positionRef,
1020
+ selectedIndex,
1021
+ onChange: (nextSelectedIndex) => {
1022
+ setSelectedIndex(nextSelectedIndex);
1023
+ preventLayoutShift(() => addPreferredLanguage(availableLanguages[nextSelectedIndex]));
1024
+ }
1025
+ };
968
1026
  }
969
- function PageNavigation(arg0) {
970
- const { navigation, currentRoute } = arg0;
1027
+ var CodeGroupContext = (0, react.createContext)(false);
1028
+ function CodeGroup(arg0) {
1029
+ const { children, title, ...props } = arg0;
971
1030
  const t = useBuiltInText();
972
- if (!currentRoute) return null;
973
- const pageRoutes = flattenNavigation(navigation);
974
- const currentIndex = pageRoutes.findIndex((route) => isSameRoutePath(route.path, currentRoute.path));
975
- if (currentIndex === -1) return null;
976
- const previous = pageRoutes[currentIndex - 1];
977
- const next = pageRoutes[currentIndex + 1];
978
- if (!previous && !next) return null;
979
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("nav", {
980
- className: "clarify-page-navigation mt-6 grid gap-3 @3xl:grid-cols-2",
981
- "aria-label": t("navigation.previousNext"),
982
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageNavigationLink, {
983
- direction: "previous",
984
- route: previous
985
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageNavigationLink, {
986
- direction: "next",
987
- route: next
988
- })]
1031
+ const tabGroupProps = useTabGroupProps(react.Children.map(children, (child) => getPanelTitle({
1032
+ ...(0, react.isValidElement)(child) ? child.props : {},
1033
+ fallbackTitle: t("actions.code")
1034
+ })) ?? []);
1035
+ const hasTabs = react.Children.count(children) > 1;
1036
+ const containerClassName = "clarify-code-group my-6 overflow-hidden rounded-2xl bg-zinc-900 shadow-md dark:ring-1 dark:ring-white/10";
1037
+ const header = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeGroupHeader, {
1038
+ title,
1039
+ selectedIndex: tabGroupProps.selectedIndex,
1040
+ children
989
1041
  });
990
- }
991
- function PageNavigationLink(arg0) {
992
- const { direction, route } = arg0;
993
- const t = useBuiltInText();
994
- if (!route) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "hidden @3xl:block" });
995
- const isNext = direction === "next";
996
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_router_dom.Link, {
997
- to: normalizeRoutePath(route.path),
998
- className: (0, clsx.default)("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"),
999
- children: [
1000
- !isNext ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.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,
1001
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1002
- className: "min-w-0 flex-1",
1003
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1004
- className: "block text-[0.6875rem] font-medium uppercase tracking-wide text-(--clarify-theme-tokens-colors-muted)",
1005
- children: isNext ? t("navigation.next") : t("navigation.previous")
1006
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1007
- className: "mt-0.5 block truncate text-[0.8125rem] font-semibold text-(--clarify-theme-tokens-colors-foreground) dark:text-white",
1008
- children: route.title
1009
- })]
1010
- }),
1011
- isNext ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.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
1012
- ]
1042
+ const panels = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeGroupPanels, {
1043
+ ...props,
1044
+ children
1045
+ });
1046
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeGroupContext.Provider, {
1047
+ value: true,
1048
+ children: hasTabs ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.TabGroup, {
1049
+ ...tabGroupProps,
1050
+ className: containerClassName,
1051
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1052
+ className: "not-prose",
1053
+ children: [header, panels]
1054
+ })
1055
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1056
+ className: containerClassName,
1057
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1058
+ className: "not-prose",
1059
+ children: [header, panels]
1060
+ })
1061
+ })
1013
1062
  });
1014
1063
  }
1015
- //#endregion
1016
- //#region source/components/SiteLogo.tsx
1017
- function SiteLogo(arg0) {
1018
- const { logo, className } = arg0;
1019
- if (!logo) return null;
1020
- if (typeof logo === "string") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1021
- src: logo,
1022
- alt: "",
1023
- className: (0, clsx.default)("clarify-logo", className)
1064
+ function Code(arg0) {
1065
+ const { children, ...props } = arg0;
1066
+ if ((0, react.useContext)(CodeGroupContext) && typeof children === "string") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
1067
+ ...props,
1068
+ dangerouslySetInnerHTML: { __html: children }
1024
1069
  });
1025
- const lightLogo = logo.light ?? logo.dark;
1026
- const darkLogo = logo.dark ?? logo.light;
1027
- if (!lightLogo || !darkLogo) return null;
1028
- if (lightLogo === darkLogo) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1029
- src: lightLogo,
1030
- alt: "",
1031
- className: (0, clsx.default)("clarify-logo", className)
1070
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
1071
+ ...props,
1072
+ children
1032
1073
  });
1033
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1034
- src: lightLogo,
1035
- alt: "",
1036
- className: (0, clsx.default)("clarify-logo clarify-logo-light", className, "dark:hidden")
1037
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1038
- src: darkLogo,
1039
- alt: "",
1040
- className: (0, clsx.default)("clarify-logo clarify-logo-dark", className, "hidden dark:block")
1041
- })] });
1042
- }
1043
- //#endregion
1044
- //#region source/components/ThemeProvider.tsx
1045
- var ThemeContext = (0, react.createContext)(null);
1046
- var storageKey = "clarify:theme";
1047
- function getSystemTheme() {
1048
- if (typeof window === "undefined") return "light";
1049
- return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
1050
- }
1051
- function getStoredTheme() {
1052
- if (typeof window === "undefined") return "system";
1053
- const storedTheme = window.localStorage.getItem(storageKey);
1054
- return storedTheme === "light" || storedTheme === "dark" || storedTheme === "system" ? storedTheme : "system";
1055
1074
  }
1056
- function applyTheme(resolvedTheme) {
1057
- if (typeof document === "undefined") return;
1058
- document.documentElement.classList.toggle("dark", resolvedTheme === "dark");
1059
- document.documentElement.style.colorScheme = resolvedTheme;
1060
- }
1061
- function ThemeProvider(arg0) {
1062
- const { children } = arg0;
1063
- const [theme, setThemeState] = (0, react.useState)(() => getStoredTheme());
1064
- const [systemTheme, setSystemTheme] = (0, react.useState)(() => getSystemTheme());
1065
- const resolvedTheme = theme === "system" ? systemTheme : theme;
1066
- (0, react.useEffect)(() => {
1067
- applyTheme(resolvedTheme);
1068
- }, [resolvedTheme]);
1069
- (0, react.useEffect)(() => {
1070
- if (typeof window === "undefined") return;
1071
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
1072
- function updateSystemTheme() {
1073
- setSystemTheme(mediaQuery.matches ? "dark" : "light");
1074
- }
1075
- updateSystemTheme();
1076
- mediaQuery.addEventListener("change", updateSystemTheme);
1077
- return () => mediaQuery.removeEventListener("change", updateSystemTheme);
1078
- }, []);
1079
- const value = (0, react.useMemo)(() => ({
1080
- theme,
1081
- resolvedTheme,
1082
- setTheme(nextTheme) {
1083
- setThemeState(nextTheme);
1084
- if (typeof window !== "undefined") window.localStorage.setItem(storageKey, nextTheme);
1085
- }
1086
- }), [resolvedTheme, theme]);
1087
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeContext.Provider, {
1088
- value,
1075
+ function Pre(arg0) {
1076
+ const { children, ...props } = arg0;
1077
+ if ((0, react.useContext)(CodeGroupContext)) return children;
1078
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeGroup, {
1079
+ ...props,
1089
1080
  children
1090
1081
  });
1091
1082
  }
1092
- function useTheme() {
1093
- const context = (0, react.useContext)(ThemeContext);
1094
- if (!context) throw new Error("[clarify] useTheme must be used within ThemeProvider");
1095
- return context;
1083
+ //#endregion
1084
+ //#region source/components/Collapse.tsx
1085
+ function Collapse(arg0) {
1086
+ const { children, title, summary, defaultOpen = false, className, ...props } = arg0;
1087
+ const [open, setOpen] = (0, react.useState)(defaultOpen);
1088
+ const contentRef = (0, react.useRef)(null);
1089
+ const [maxHeight, setMaxHeight] = (0, react.useState)("0px");
1090
+ const summaryLabel = title ?? summary ?? "Details";
1091
+ const contentId = (0, react.useId)();
1092
+ (0, react.useLayoutEffect)(() => {
1093
+ if (!contentRef.current) return;
1094
+ setMaxHeight(open ? `${contentRef.current.scrollHeight}px` : "0px");
1095
+ }, [open, children]);
1096
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1097
+ className: (0, clsx.default)("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),
1098
+ ...props,
1099
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1100
+ type: "button",
1101
+ 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",
1102
+ "aria-expanded": open,
1103
+ "aria-controls": contentId,
1104
+ onClick: () => setOpen((value) => !value),
1105
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: summaryLabel }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronDown, {
1106
+ className: (0, clsx.default)("h-4 w-4 text-(--clarify-theme-tokens-colors-muted) transition-transform duration-200", open && "rotate-180"),
1107
+ "aria-hidden": "true"
1108
+ })]
1109
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1110
+ id: contentId,
1111
+ 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",
1112
+ style: {
1113
+ maxHeight,
1114
+ willChange: "max-height, opacity, transform"
1115
+ },
1116
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1117
+ ref: contentRef,
1118
+ className: (0, clsx.default)("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"),
1119
+ children
1120
+ })
1121
+ })]
1122
+ });
1096
1123
  }
1097
1124
  //#endregion
1098
- //#region source/components/ThemeToggle.tsx
1099
- function SunIcon(props) {
1125
+ //#region source/components/Feedback.tsx
1126
+ function CheckIcon(props) {
1100
1127
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
1101
1128
  viewBox: "0 0 20 20",
1102
- fill: "none",
1103
1129
  "aria-hidden": "true",
1104
1130
  ...props,
1105
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M12.5 10a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Z" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1131
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
1132
+ cx: "10",
1133
+ cy: "10",
1134
+ r: "10",
1135
+ strokeWidth: "0"
1136
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1137
+ fill: "none",
1106
1138
  strokeLinecap: "round",
1107
- 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"
1139
+ strokeLinejoin: "round",
1140
+ strokeWidth: "1.5",
1141
+ d: "m6.75 10.813 2.438 2.437c1.218-4.469 4.062-6.5 4.062-6.5"
1108
1142
  })]
1109
1143
  });
1110
1144
  }
1111
- function MoonIcon(props) {
1112
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1113
- viewBox: "0 0 20 20",
1114
- fill: "none",
1115
- "aria-hidden": "true",
1116
- ...props,
1117
- children: /* @__PURE__ */ (0, react_jsx_runtime.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" })
1145
+ function FeedbackButton(props) {
1146
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1147
+ type: "submit",
1148
+ 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",
1149
+ ...props
1118
1150
  });
1119
1151
  }
1120
- function ThemeToggle() {
1121
- const { resolvedTheme, setTheme } = useTheme();
1152
+ var FeedbackForm = (0, react.forwardRef)(function FeedbackForm(arg0, ref) {
1153
+ const { onSubmit, className, ...props } = arg0;
1122
1154
  const t = useBuiltInText();
1123
- const otherTheme = resolvedTheme === "dark" ? "light" : "dark";
1124
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1125
- type: "button",
1126
- 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",
1127
- "aria-label": otherTheme === "dark" ? t("theme.switchToDark") : t("theme.switchToLight"),
1128
- onClick: () => setTheme(otherTheme),
1129
- children: [
1130
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "absolute size-12 pointer-fine:hidden" }),
1131
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SunIcon, { className: "h-5 w-5 stroke-(--clarify-theme-tokens-colors-foreground) dark:hidden" }),
1132
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MoonIcon, { className: "hidden h-5 w-5 stroke-white dark:block" })
1133
- ]
1155
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
1156
+ ...props,
1157
+ ref,
1158
+ onSubmit,
1159
+ className: (0, clsx.default)(className, "clarify-feedback-form absolute inset-0 flex items-center justify-center gap-6 md:justify-start"),
1160
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1161
+ className: "text-sm text-zinc-600 dark:text-zinc-400",
1162
+ children: t("feedback.prompt")
1163
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1164
+ 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",
1165
+ children: [
1166
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackButton, {
1167
+ "data-response": "yes",
1168
+ children: t("feedback.yes")
1169
+ }),
1170
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "bg-zinc-900/10 dark:bg-white/10" }),
1171
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackButton, {
1172
+ "data-response": "no",
1173
+ children: t("feedback.no")
1174
+ })
1175
+ ]
1176
+ })]
1134
1177
  });
1135
- }
1136
- //#endregion
1137
- //#region source/components/index.tsx
1138
- function ArrowIcon(props) {
1139
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1140
- viewBox: "0 0 20 20",
1141
- fill: "none",
1142
- "aria-hidden": "true",
1178
+ });
1179
+ var FeedbackThanks = (0, react.forwardRef)(function FeedbackThanks(arg0, ref) {
1180
+ const { className, ...props } = arg0;
1181
+ const t = useBuiltInText();
1182
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1143
1183
  ...props,
1144
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1145
- stroke: "currentColor",
1146
- strokeLinecap: "round",
1147
- strokeLinejoin: "round",
1148
- d: "m11.5 6.5 3 3.5m0 0-3 3.5m3-3.5h-9"
1184
+ ref,
1185
+ className: (0, clsx.default)(className, "clarify-feedback-thanks absolute inset-0 flex justify-center md:justify-start"),
1186
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1187
+ 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",
1188
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CheckIcon, { 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")]
1149
1189
  })
1150
1190
  });
1151
- }
1152
- var buttonVariantStyles = {
1153
- 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",
1154
- 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",
1155
- 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",
1156
- 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",
1157
- text: "text-(--clarify-theme-tokens-colors-primary) hover:opacity-80 dark:text-(--clarify-theme-tokens-colors-primary) dark:hover:opacity-80"
1158
- };
1159
- function Button(arg0) {
1160
- const { variant = "primary", className, children, arrow, ...props } = arg0;
1161
- const classes = (0, clsx.default)("clarify-button inline-flex justify-center gap-0.5 overflow-hidden text-sm font-medium transition", buttonVariantStyles[variant], className);
1162
- const arrowIcon = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArrowIcon, { className: (0, clsx.default)("mt-0.5 h-5 w-5", variant === "text" && "relative top-px", arrow === "left" && "-ml-1 rotate-180", arrow === "right" && "-mr-1") });
1163
- const inner = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
1164
- arrow === "left" ? arrowIcon : null,
1165
- children,
1166
- arrow === "right" ? arrowIcon : null
1167
- ] });
1168
- if (typeof props.href === "undefined") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1169
- className: classes,
1170
- ...props,
1171
- children: inner
1172
- });
1173
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1174
- className: classes,
1175
- ...props,
1176
- children: inner
1191
+ });
1192
+ function Feedback() {
1193
+ const [submitted, setSubmitted] = (0, react.useState)(false);
1194
+ function onSubmit(event) {
1195
+ event.preventDefault();
1196
+ setSubmitted(true);
1197
+ }
1198
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1199
+ className: "clarify-feedback relative h-8",
1200
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.Transition, {
1201
+ show: !submitted,
1202
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackForm, {
1203
+ className: "duration-300 data-closed:opacity-0 data-leave:pointer-events-none",
1204
+ onSubmit
1205
+ })
1206
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.Transition, {
1207
+ show: submitted,
1208
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackThanks, { className: "delay-150 duration-300 data-closed:opacity-0" })
1209
+ })]
1177
1210
  });
1178
1211
  }
1212
+ //#endregion
1213
+ //#region source/components/Tag.tsx
1179
1214
  var tagVariantStyles = {
1180
1215
  small: "",
1181
1216
  medium: "rounded-lg px-1.5 ring-1 ring-inset"
@@ -1214,32 +1249,12 @@ function Tag(arg0) {
1214
1249
  const value = typeof children === "string" ? children.toUpperCase() : "";
1215
1250
  const resolvedColor = color ?? tagValueColorMap[value] ?? "emerald";
1216
1251
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1217
- className: (0, clsx.default)("clarify-tag font-mono text-[0.625rem]/6 font-bold", tagVariantStyles[variant], tagColorStyles[resolvedColor][variant]),
1252
+ className: (0, clsx.default)("clarify-tag font-bold", tagVariantStyles[variant], tagColorStyles[resolvedColor][variant]),
1218
1253
  children
1219
1254
  });
1220
1255
  }
1221
- function Logo(props) {
1222
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
1223
- viewBox: "0 0 99 24",
1224
- "aria-hidden": "true",
1225
- ...props,
1226
- className: (0, clsx.default)("clarify-logo", props.className),
1227
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1228
- className: "fill-(--clarify-theme-tokens-colors-primary)",
1229
- 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"
1230
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1231
- className: "fill-(--clarify-theme-tokens-colors-foreground) dark:fill-white",
1232
- 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"
1233
- })]
1234
- });
1235
- }
1236
- function Prose(arg0) {
1237
- const { as, className, ...props } = arg0;
1238
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(as ?? "div", {
1239
- className: (0, clsx.default)(className, "clarify-prose prose max-w-none dark:prose-invert", "[html_:where(&>*)]:w-full [html_:where(&>*)]:min-w-0 [html_:where(&>*)]:max-w-full"),
1240
- ...props
1241
- });
1242
- }
1256
+ //#endregion
1257
+ //#region source/components/Heading.tsx
1243
1258
  function AnchorIcon(props) {
1244
1259
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1245
1260
  viewBox: "0 0 20 20",
@@ -1259,7 +1274,7 @@ function Eyebrow(arg0) {
1259
1274
  tag ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tag, { children: tag }) : null,
1260
1275
  tag && label ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "h-0.5 w-0.5 rounded-full bg-zinc-300 dark:bg-zinc-600" }) : null,
1261
1276
  label ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1262
- className: "font-mono text-xs text-zinc-400",
1277
+ className: "text-xs text-zinc-400",
1263
1278
  children: label
1264
1279
  }) : null
1265
1280
  ]
@@ -1304,218 +1319,125 @@ function Heading(arg0) {
1304
1319
  ]);
1305
1320
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Eyebrow, {
1306
1321
  tag,
1307
- label
1308
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
1309
- ref,
1310
- className: (0, clsx.default)("clarify-heading", tag || label ? "mt-2 scroll-mt-32" : "scroll-mt-24", className),
1311
- ...props,
1312
- children: anchor ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Anchor, {
1313
- id: props.id,
1314
- inView,
1315
- children
1316
- }) : children
1317
- })] });
1318
- }
1319
- function DocShell(arg0) {
1320
- const { title, subtitle, children } = arg0;
1321
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("main", {
1322
- 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",
1323
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1324
- className: "mx-auto max-w-6xl",
1325
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
1326
- className: "mb-10",
1327
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
1328
- className: "text-3xl font-bold tracking-tight md:text-5xl",
1329
- children: title
1330
- }), subtitle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1331
- className: "mt-3 max-w-2xl text-zinc-600 dark:text-zinc-400",
1332
- children: subtitle
1333
- }) : null]
1334
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Prose, { children })]
1335
- })
1336
- });
1337
- }
1338
- function ApiEndpointCard(arg0) {
1339
- const { method, path, description, id } = arg0;
1340
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
1341
- id,
1342
- 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",
1343
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1344
- className: "flex items-center gap-3",
1345
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Tag, { children: method }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
1346
- className: "text-sm font-medium text-zinc-800 dark:text-zinc-200",
1347
- children: path
1348
- })]
1349
- }), description ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1350
- className: "mt-3 text-sm text-zinc-600 dark:text-zinc-400",
1351
- children: description
1352
- }) : null]
1353
- });
1354
- }
1355
- //#endregion
1356
- //#region source/shell/ContentActions.tsx
1357
- function resolveContentArtifactUrl(contentArtifactUrl, routePrefix = "/") {
1358
- if (!routePrefix || routePrefix === "/") return contentArtifactUrl;
1359
- return `/${routePrefix.replace(/^\/+|\/+$/g, "")}${contentArtifactUrl}`;
1360
- }
1361
- function getAbsoluteUrl(path) {
1362
- if (typeof window === "undefined") return path;
1363
- return new URL(path, window.location.href).href;
1364
- }
1365
- async function copyText(text) {
1366
- await navigator.clipboard.writeText(text);
1367
- }
1368
- function ContentActions(arg0) {
1369
- const { hasTabs = false, route, routePrefix } = arg0;
1370
- const t = useBuiltInText();
1371
- const [copied, setCopied] = (0, react.useState)("idle");
1372
- if (!route?.contentArtifactUrl) return null;
1373
- const contentArtifactUrl = resolveContentArtifactUrl(route.contentArtifactUrl, routePrefix);
1374
- const isOpenApi = route.kind === "openapi";
1375
- const replacements = { contentType: isOpenApi ? "OpenAPI" : "Markdown" };
1376
- const viewLabel = isOpenApi ? t("contentActions.viewOpenApi") : t("contentActions.viewMarkdown");
1377
- const viewDescription = isOpenApi ? t("contentActions.viewOpenApiDescription") : t("contentActions.viewMarkdownDescription");
1378
- function markCopied(state) {
1379
- setCopied(state);
1380
- window.setTimeout(() => setCopied("idle"), 1600);
1381
- }
1382
- async function handleCopyContent() {
1383
- await copyText(await (await fetch(contentArtifactUrl)).text());
1384
- markCopied("content");
1385
- }
1386
- async function handleCopyLink() {
1387
- await copyText(getAbsoluteUrl(contentArtifactUrl));
1388
- markCopied("link");
1389
- }
1390
- const actions = [{
1391
- key: "content",
1392
- label: t("contentActions.copyContent"),
1393
- description: t("contentActions.copyContentDescription", replacements),
1394
- icon: lucide_react.Copy,
1395
- run: handleCopyContent
1396
- }, {
1397
- key: "link",
1398
- label: t("contentActions.copyLink", replacements),
1399
- description: t("contentActions.copyLinkDescription", replacements),
1400
- icon: lucide_react.Link2,
1401
- run: handleCopyLink
1402
- }];
1403
- const primaryAction = actions[0];
1404
- const PrimaryIcon = copied === primaryAction.key ? lucide_react.Check : primaryAction.icon;
1405
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1406
- className: `clarify-content-actions sticky z-20 flex justify-end py-4 ${hasTabs ? "top-16 lg:top-30" : "top-16"}`,
1407
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.Menu, {
1408
- as: "div",
1409
- className: "clarify-content-actions-menu relative inline-flex text-sm font-medium",
1410
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1411
- 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",
1412
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1413
- type: "button",
1414
- onClick: primaryAction.run,
1415
- className: "clarify-content-actions-primary clarify-ui-control inline-flex h-8 items-center gap-1.5 px-3 transition",
1416
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PrimaryIcon, { className: "h-3.5 w-3.5" }), copied === primaryAction.key ? t("actions.copied") : primaryAction.label]
1417
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuButton, {
1418
- 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",
1419
- "aria-label": t("contentActions.copyOptions"),
1420
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronDown, { className: "h-3.5 w-3.5" })
1421
- })]
1422
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.MenuItems, {
1423
- anchor: "bottom end",
1424
- 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",
1425
- children: [
1426
- actions.slice(0, 1).map((action) => {
1427
- const Icon = action.icon;
1428
- const isCopied = copied === action.key;
1429
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1430
- type: "button",
1431
- onClick: action.run,
1432
- 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",
1433
- children: [
1434
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1435
- 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",
1436
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: "h-4 w-4" })
1437
- }),
1438
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1439
- className: "flex min-w-0 flex-1 flex-col px-1",
1440
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1441
- className: "clarify-ui-menu-title",
1442
- children: isCopied ? t("contentActions.copiedContent") : action.label
1443
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1444
- className: "clarify-ui-menu-description truncate",
1445
- children: action.description
1446
- })]
1447
- }),
1448
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: `h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) transition ${isCopied ? "opacity-100" : "opacity-0"}` })
1449
- ]
1450
- }) }, action.key);
1451
- }),
1452
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
1453
- href: contentArtifactUrl,
1454
- target: "_blank",
1455
- rel: "noreferrer",
1456
- 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",
1457
- children: [
1458
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1459
- 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",
1460
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.FileText, { className: "h-4 w-4" })
1461
- }),
1462
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1463
- className: "flex min-w-0 flex-1 flex-col px-1",
1464
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1465
- className: "clarify-ui-menu-title flex items-center gap-1",
1466
- children: [viewLabel, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ExternalLink, { className: "clarify-ui-menu-icon h-3 w-3" })]
1467
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1468
- className: "clarify-ui-menu-description truncate",
1469
- children: viewDescription
1470
- })]
1471
- }),
1472
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) opacity-0" })
1473
- ]
1474
- }) }),
1475
- actions.slice(1).map((action) => {
1476
- const Icon = action.icon;
1477
- const isCopied = copied === action.key;
1478
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1479
- type: "button",
1480
- onClick: action.run,
1481
- 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",
1482
- children: [
1483
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1484
- 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",
1485
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: "h-4 w-4" })
1486
- }),
1487
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1488
- className: "flex min-w-0 flex-1 flex-col px-1",
1489
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1490
- className: "clarify-ui-menu-title",
1491
- children: isCopied ? t("contentActions.copiedLink") : action.label
1492
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1493
- className: "clarify-ui-menu-description truncate",
1494
- children: action.description
1495
- })]
1496
- }),
1497
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: `h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) transition ${isCopied ? "opacity-100" : "opacity-0"}` })
1498
- ]
1499
- }) }, action.key);
1500
- })
1501
- ]
1322
+ label
1323
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
1324
+ ref,
1325
+ className: (0, clsx.default)("clarify-heading", tag || label ? "mt-2 scroll-mt-32" : "scroll-mt-24", className),
1326
+ ...props,
1327
+ children: anchor ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Anchor, {
1328
+ id: props.id,
1329
+ inView,
1330
+ children
1331
+ }) : children
1332
+ })] });
1333
+ }
1334
+ //#endregion
1335
+ //#region source/components/Logo.tsx
1336
+ function Logo(props) {
1337
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
1338
+ viewBox: "0 0 99 24",
1339
+ "aria-hidden": "true",
1340
+ ...props,
1341
+ className: (0, clsx.default)("clarify-logo", props.className),
1342
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1343
+ className: "fill-(--clarify-theme-tokens-colors-primary)",
1344
+ 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"
1345
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1346
+ className: "fill-(--clarify-theme-tokens-colors-foreground) dark:fill-white",
1347
+ 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"
1348
+ })]
1349
+ });
1350
+ }
1351
+ //#endregion
1352
+ //#region source/components/patterns.tsx
1353
+ function GridPattern(arg0) {
1354
+ const { width, height, x, y, squares, ...props } = arg0;
1355
+ const patternId = (0, react.useId)();
1356
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
1357
+ "aria-hidden": "true",
1358
+ ...props,
1359
+ children: [
1360
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pattern", {
1361
+ id: patternId,
1362
+ width,
1363
+ height,
1364
+ patternUnits: "userSpaceOnUse",
1365
+ x,
1366
+ y,
1367
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1368
+ d: `M.5 ${height}V.5H${width}`,
1369
+ fill: "none"
1370
+ })
1371
+ }) }),
1372
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
1373
+ width: "100%",
1374
+ height: "100%",
1375
+ strokeWidth: 0,
1376
+ fill: `url(#${patternId})`
1377
+ }),
1378
+ squares ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1379
+ x,
1380
+ y,
1381
+ className: "overflow-visible",
1382
+ children: squares.map(([squareX, squareY]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
1383
+ width: width + 1,
1384
+ height: height + 1,
1385
+ x: squareX * width,
1386
+ y: squareY * height,
1387
+ strokeWidth: "0"
1388
+ }, `${squareX}-${squareY}`))
1389
+ }) : null
1390
+ ]
1391
+ });
1392
+ }
1393
+ function HeroPattern() {
1394
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1395
+ className: "absolute inset-0 -z-10 mx-0 max-w-none overflow-hidden",
1396
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1397
+ className: "absolute top-0 left-1/2 -ml-152 h-100 w-325 dark:mask-[linear-gradient(white,transparent)]",
1398
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1399
+ 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",
1400
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GridPattern, {
1401
+ width: 72,
1402
+ height: 56,
1403
+ x: -12,
1404
+ y: 4,
1405
+ squares: [
1406
+ [4, 3],
1407
+ [2, 1],
1408
+ [7, 3],
1409
+ [10, 6]
1410
+ ],
1411
+ 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"
1412
+ })
1413
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1414
+ viewBox: "0 0 1113 440",
1415
+ "aria-hidden": "true",
1416
+ className: "absolute top-0 left-1/2 -ml-76 w-278.25 fill-white blur-[26px] dark:hidden",
1417
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M.016 439.5s-9.5-300 434-300S882.516 20 882.516 20V0h230.004v439.5H.016Z" })
1502
1418
  })]
1503
1419
  })
1504
1420
  });
1505
1421
  }
1506
1422
  //#endregion
1507
- //#region source/shell/icons.tsx
1508
- function NavigationIcon(arg0) {
1509
- const { name, className } = arg0;
1510
- if (!name) return null;
1511
- const Icon = lucide_react[name];
1512
- if (!Icon) return null;
1513
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
1514
- className: (0, clsx.default)("shrink-0 stroke-current", className),
1515
- "aria-hidden": "true"
1423
+ //#region source/components/Prose.tsx
1424
+ function Prose(arg0) {
1425
+ const { as, className, ...props } = arg0;
1426
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(as ?? "div", {
1427
+ className: (0, clsx.default)(className, "clarify-prose prose max-w-none dark:prose-invert", "[html_:where(&>*)]:w-full [html_:where(&>*)]:min-w-0 [html_:where(&>*)]:max-w-full"),
1428
+ ...props
1516
1429
  });
1517
1430
  }
1518
1431
  //#endregion
1432
+ //#region source/utils/hash.ts
1433
+ function safeDecodeURIComponent(value) {
1434
+ try {
1435
+ return decodeURIComponent(value);
1436
+ } catch {
1437
+ return value;
1438
+ }
1439
+ }
1440
+ //#endregion
1519
1441
  //#region source/shell/Navigation.tsx
1520
1442
  function useInitialValue(value, condition = true) {
1521
1443
  const [initialValue] = (0, react.useState)(value);
@@ -1551,7 +1473,7 @@ var sectionBadgeColorStyles = {
1551
1473
  function SectionBadge(arg0) {
1552
1474
  const { children } = arg0;
1553
1475
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1554
- className: (0, clsx.default)("clarify-navigation-section-badge inline-flex shrink-0 justify-end font-mono font-semibold uppercase tracking-wide", sectionBadgeColorStyles[children.toUpperCase()] ?? "clarify-ui-menu-description"),
1476
+ className: (0, clsx.default)("clarify-navigation-section-badge inline-flex shrink-0 justify-end font-semibold uppercase tracking-wide", sectionBadgeColorStyles[children.toUpperCase()] ?? "clarify-ui-menu-description"),
1555
1477
  children
1556
1478
  });
1557
1479
  }
@@ -1561,7 +1483,7 @@ function NavLink(arg0) {
1561
1483
  if (!isAnchorLink) return;
1562
1484
  const hashIndex = href.indexOf("#");
1563
1485
  if (hashIndex === -1) return;
1564
- const targetId = decodeURIComponent(href.slice(hashIndex + 1));
1486
+ const targetId = safeDecodeURIComponent(href.slice(hashIndex + 1));
1565
1487
  window.requestAnimationFrame(() => {
1566
1488
  document.getElementById(targetId)?.scrollIntoView();
1567
1489
  window.requestAnimationFrame(() => {
@@ -1584,7 +1506,7 @@ function NavLink(arg0) {
1584
1506
  }) : null,
1585
1507
  badge ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionBadge, { children: badge }) : null,
1586
1508
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1587
- className: "min-w-0 truncate",
1509
+ className: "min-w-0 truncate whitespace-nowrap",
1588
1510
  children
1589
1511
  })
1590
1512
  ]
@@ -1607,13 +1529,27 @@ function VisibleSectionHighlight(arg0) {
1607
1529
  const height = isPresent ? Math.max(1, visibleSections.length) * itemHeight : itemHeight;
1608
1530
  const top = group.links.findIndex((link) => isSameRoutePath(link.href, pathname)) * itemHeight + firstVisibleSectionIndex * itemHeight;
1609
1531
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.motion.div, {
1610
- layout: true,
1611
- initial: { opacity: 0 },
1532
+ initial: {
1533
+ opacity: 0,
1534
+ height: 0
1535
+ },
1612
1536
  animate: {
1613
1537
  opacity: 1,
1614
- transition: { delay: .2 }
1538
+ top,
1539
+ height,
1540
+ transition: {
1541
+ duration: .2,
1542
+ ease: "easeOut"
1543
+ }
1544
+ },
1545
+ exit: {
1546
+ opacity: 0,
1547
+ height: 0,
1548
+ transition: {
1549
+ duration: .15,
1550
+ ease: "easeIn"
1551
+ }
1615
1552
  },
1616
- exit: { opacity: 0 },
1617
1553
  className: "clarify-navigation-section-highlight absolute inset-x-0 top-0 will-change-transform",
1618
1554
  style: {
1619
1555
  borderRadius: "var(--clarify-theme-tokens-radius-sm)",
@@ -1627,14 +1563,26 @@ function ActivePageMarker(arg0) {
1627
1563
  const itemHeight = remToPx(2);
1628
1564
  const top = remToPx(.25) + group.links.findIndex((link) => isSameRoutePath(link.href, pathname)) * itemHeight;
1629
1565
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.motion.div, {
1630
- layout: true,
1631
1566
  className: "absolute left-2 h-6 w-px bg-(--clarify-theme-tokens-colors-primary)",
1632
- initial: { opacity: 0 },
1567
+ initial: {
1568
+ opacity: 0,
1569
+ top
1570
+ },
1633
1571
  animate: {
1634
1572
  opacity: 1,
1635
- transition: { delay: .2 }
1573
+ top,
1574
+ transition: {
1575
+ duration: .2,
1576
+ ease: "easeOut"
1577
+ }
1578
+ },
1579
+ exit: {
1580
+ opacity: 0,
1581
+ transition: {
1582
+ duration: .15,
1583
+ ease: "easeIn"
1584
+ }
1636
1585
  },
1637
- exit: { opacity: 0 },
1638
1586
  style: { top }
1639
1587
  });
1640
1588
  }
@@ -1645,8 +1593,7 @@ function NavigationGroup(arg0) {
1645
1593
  const isActiveGroup = group.links.findIndex((link) => isSameRoutePath(link.href, pathname)) !== -1;
1646
1594
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
1647
1595
  className: (0, clsx.default)("clarify-navigation-group relative mt-6", className),
1648
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(framer_motion.motion.h2, {
1649
- layout: "position",
1596
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", {
1650
1597
  className: "clarify-navigation-group-title flex items-center gap-2",
1651
1598
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavigationIcon, {
1652
1599
  name: group.icon,
@@ -1662,10 +1609,7 @@ function NavigationGroup(arg0) {
1662
1609
  pathname
1663
1610
  }) : null
1664
1611
  }),
1665
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.motion.div, {
1666
- layout: true,
1667
- className: "absolute inset-y-0 left-2 w-px bg-(--clarify-theme-tokens-colors-border) dark:bg-white/5"
1668
- }),
1612
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "absolute inset-y-0 left-2 w-px bg-(--clarify-theme-tokens-colors-border) dark:bg-white/5" }),
1669
1613
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.AnimatePresence, {
1670
1614
  initial: false,
1671
1615
  children: isActiveGroup ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActivePageMarker, {
@@ -1678,8 +1622,7 @@ function NavigationGroup(arg0) {
1678
1622
  className: "border-l border-transparent",
1679
1623
  children: group.links.map((link) => {
1680
1624
  const active = isSameRoutePath(link.href, pathname);
1681
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(framer_motion.motion.li, {
1682
- layout: "position",
1625
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
1683
1626
  className: "relative",
1684
1627
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavLink, {
1685
1628
  href: link.href,
@@ -1687,7 +1630,6 @@ function NavigationGroup(arg0) {
1687
1630
  active,
1688
1631
  children: link.title
1689
1632
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.AnimatePresence, {
1690
- mode: "popLayout",
1691
1633
  initial: false,
1692
1634
  children: active && sections.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.motion.ul, {
1693
1635
  role: "list",
@@ -1754,11 +1696,11 @@ function XIcon(props) {
1754
1696
  });
1755
1697
  }
1756
1698
  var IsInsideMobileNavigationContext = (0, react.createContext)(false);
1757
- function hasPath$2(nodes, pathname) {
1758
- return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath$2(node.children ?? [], pathname));
1699
+ function hasPath$1(nodes, pathname) {
1700
+ return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath$1(node.children ?? [], pathname));
1759
1701
  }
1760
1702
  function isActiveTab$1(tab, pathname) {
1761
- return isSameRoutePath(tab.path, pathname) || hasPath$2(tab.children, pathname);
1703
+ return isSameRoutePath(tab.path, pathname) || hasPath$1(tab.children, pathname);
1762
1704
  }
1763
1705
  function MobileTabsSelect(arg0) {
1764
1706
  const { tabs } = arg0;
@@ -1777,7 +1719,7 @@ function MobileTabsSelect(arg0) {
1777
1719
  name: activeTab.icon,
1778
1720
  className: "h-4 w-4 shrink-0 text-(--clarify-theme-tokens-colors-primary)"
1779
1721
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1780
- className: "truncate tracking-[-0.01em]",
1722
+ className: "truncate",
1781
1723
  children: activeTab.title
1782
1724
  })]
1783
1725
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
@@ -2205,20 +2147,39 @@ function MobileSearch(arg0) {
2205
2147
  });
2206
2148
  }
2207
2149
  //#endregion
2150
+ //#region source/shell/SiteLogo.tsx
2151
+ function SiteLogo(arg0) {
2152
+ const { logo, className } = arg0;
2153
+ if (!logo) return null;
2154
+ if (typeof logo === "string") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
2155
+ src: logo,
2156
+ alt: "",
2157
+ className: (0, clsx.default)("clarify-logo", className)
2158
+ });
2159
+ const lightLogo = logo.light ?? logo.dark;
2160
+ const darkLogo = logo.dark ?? logo.light;
2161
+ if (!lightLogo || !darkLogo) return null;
2162
+ if (lightLogo === darkLogo) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
2163
+ src: lightLogo,
2164
+ alt: "",
2165
+ className: (0, clsx.default)("clarify-logo", className)
2166
+ });
2167
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
2168
+ src: lightLogo,
2169
+ alt: "",
2170
+ className: (0, clsx.default)("clarify-logo clarify-logo-light", className, "dark:hidden")
2171
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
2172
+ src: darkLogo,
2173
+ alt: "",
2174
+ className: (0, clsx.default)("clarify-logo clarify-logo-dark", className, "hidden dark:block")
2175
+ })] });
2176
+ }
2177
+ //#endregion
2208
2178
  //#region source/shell/Header.tsx
2209
2179
  function resolveLocalizedText(text, locale, fallbackLocale) {
2210
2180
  if (typeof text === "string") return text;
2211
2181
  return (locale ? text[locale] : void 0) ?? (fallbackLocale ? text[fallbackLocale] : void 0) ?? Object.values(text)[0] ?? "";
2212
2182
  }
2213
- function isExternalHref(href) {
2214
- return /^[a-z][a-z0-9+.-]*:/i.test(href) || href.startsWith("//");
2215
- }
2216
- function localizeHref(href, config, locale) {
2217
- if (!locale || !config.i18n || isExternalHref(href) || href.startsWith("#")) return href;
2218
- if (locale === config.i18n.defaultLocale) return href;
2219
- const cleanHref = href === "/" ? "" : href.replace(/^\/+/, "");
2220
- return `/${locale}${cleanHref ? `/${cleanHref}` : ""}`;
2221
- }
2222
2183
  function localizedRoutePath(config, locale, route) {
2223
2184
  const alternatePath = route?.alternates?.[locale];
2224
2185
  if (alternatePath) return alternatePath;
@@ -2331,11 +2292,11 @@ function MobileNavbarMenu(arg0) {
2331
2292
  })]
2332
2293
  });
2333
2294
  }
2334
- function hasPath$1(nodes, pathname) {
2335
- return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath$1(node.children ?? [], pathname));
2295
+ function hasPath(nodes, pathname) {
2296
+ return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath(node.children ?? [], pathname));
2336
2297
  }
2337
2298
  function isActiveTab(tab, pathname) {
2338
- return isSameRoutePath(tab.path, pathname) || hasPath$1(tab.children, pathname);
2299
+ return isSameRoutePath(tab.path, pathname) || hasPath(tab.children, pathname);
2339
2300
  }
2340
2301
  function ProductTabs(arg0) {
2341
2302
  const { tabs } = arg0;
@@ -2352,7 +2313,7 @@ function ProductTabs(arg0) {
2352
2313
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_router_dom.Link, {
2353
2314
  to: tab.path,
2354
2315
  "aria-current": active ? "page" : void 0,
2355
- className: (0, clsx.default)("clarify-product-tab clarify-ui-tab relative inline-flex shrink-0 items-center gap-2 px-0 transition", active && "clarify-ui-tab-active"),
2316
+ className: (0, clsx.default)("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"),
2356
2317
  children: [
2357
2318
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavigationIcon, {
2358
2319
  name: tab.icon,
@@ -2363,9 +2324,9 @@ function ProductTabs(arg0) {
2363
2324
  layoutId: "clarify-product-tab-indicator",
2364
2325
  className: "absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-(--clarify-theme-tokens-colors-foreground) dark:bg-white",
2365
2326
  transition: {
2366
- type: "spring",
2367
- stiffness: 420,
2368
- damping: 36
2327
+ type: "tween",
2328
+ duration: .16,
2329
+ ease: "easeOut"
2369
2330
  }
2370
2331
  }) : null
2371
2332
  ]
@@ -2463,217 +2424,6 @@ var Header = (0, react.forwardRef)(function Header(arg0, ref) {
2463
2424
  });
2464
2425
  });
2465
2426
  //#endregion
2466
- //#region source/app/AppShell.tsx
2467
- function routeForPath(routes, pathname) {
2468
- return routes.find((route) => isSameRoutePath(route.path, pathname));
2469
- }
2470
- function sectionsForRoute(route) {
2471
- return route?.sections?.map((section) => ({
2472
- id: section.id,
2473
- title: section.title,
2474
- badge: section.badge,
2475
- tags: section.tags
2476
- })) ?? [];
2477
- }
2478
- function resolveRouteComponent(route) {
2479
- if (route.lazy) return (0, react.lazy)(route.component);
2480
- return route.component;
2481
- }
2482
- function scrollToHash(hash) {
2483
- if (!hash) return;
2484
- const targetId = decodeURIComponent(hash.slice(1));
2485
- window.requestAnimationFrame(() => {
2486
- document.getElementById(targetId)?.scrollIntoView();
2487
- window.requestAnimationFrame(() => {
2488
- window.dispatchEvent(new Event("scroll"));
2489
- });
2490
- });
2491
- }
2492
- function localeForPath(config, pathname, route) {
2493
- if (route?.locale) return route.locale;
2494
- const i18n = config.i18n;
2495
- if (!i18n) return void 0;
2496
- const firstSegment = pathname.split("/").filter(Boolean)[0];
2497
- return i18n.locales.find((locale) => locale.code === firstSegment)?.code ?? i18n.defaultLocale;
2498
- }
2499
- function isTabbedNavigation(navigation) {
2500
- return !Array.isArray(navigation) && "tabs" in navigation;
2501
- }
2502
- function hasPath(nodes, pathname) {
2503
- return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath(node.children ?? [], pathname));
2504
- }
2505
- function navigationFromTabs(navigation, pathname) {
2506
- return {
2507
- items: navigation.tabs.find((tab) => isSameRoutePath(tab.path, pathname) || hasPath(tab.children, pathname))?.children ?? navigation.tabs[0]?.children ?? [],
2508
- tabs: navigation.tabs
2509
- };
2510
- }
2511
- function navigationForLocale(navigation, locale, pathname) {
2512
- if (Array.isArray(navigation)) return { items: navigation };
2513
- if (isTabbedNavigation(navigation)) return navigationFromTabs(navigation, pathname);
2514
- if (!locale) return { items: [] };
2515
- const localizedNavigation = navigation[locale];
2516
- if (!localizedNavigation) return { items: [] };
2517
- return Array.isArray(localizedNavigation) ? { items: localizedNavigation } : navigationFromTabs(localizedNavigation, pathname);
2518
- }
2519
- function themeStyle(config) {
2520
- const { colors, radius } = config.theme.tokens;
2521
- const { layout } = config.theme;
2522
- return {
2523
- "--clarify-theme-tokens-colors-primary": colors.primary,
2524
- "--clarify-theme-tokens-colors-accent": colors.accent,
2525
- "--clarify-theme-tokens-colors-background": colors.background,
2526
- "--clarify-theme-tokens-colors-foreground": colors.foreground,
2527
- "--clarify-theme-tokens-colors-surface": colors.surface,
2528
- "--clarify-theme-tokens-colors-muted": colors.muted,
2529
- "--clarify-theme-tokens-colors-border": colors.border,
2530
- "--clarify-theme-tokens-colors-code-background": colors.codeBackground,
2531
- "--clarify-theme-tokens-radius-sm": radius.sm,
2532
- "--clarify-theme-tokens-radius-md": radius.md,
2533
- "--clarify-theme-tokens-radius-lg": radius.lg,
2534
- "--clarify-theme-tokens-radius-xl": radius.xl,
2535
- "--clarify-theme-layout-max-width": layout.maxWidth
2536
- };
2537
- }
2538
- function pageTitle(config, route) {
2539
- const routeTitle = route?.title?.trim();
2540
- if (!routeTitle || routeTitle === config.title) return config.title;
2541
- return `${routeTitle} - ${config.title}`;
2542
- }
2543
- function setNamedMeta(name, content) {
2544
- const existing = document.head.querySelector(`meta[name="${name}"]`);
2545
- if (!content) {
2546
- existing?.remove();
2547
- return;
2548
- }
2549
- const meta = existing ?? document.createElement("meta");
2550
- meta.name = name;
2551
- meta.content = content;
2552
- if (!existing) document.head.appendChild(meta);
2553
- }
2554
- function applyDocumentMetadata(config, route) {
2555
- document.title = pageTitle(config, route);
2556
- setNamedMeta("description", route?.description ?? config.description);
2557
- setNamedMeta("keywords", route?.keywords?.join(", "));
2558
- }
2559
- function applyRootThemeVariables(themeVariables) {
2560
- const rootStyle = document.documentElement.style;
2561
- for (const [property, value] of Object.entries(themeVariables)) rootStyle.setProperty(property, value);
2562
- return () => {
2563
- for (const property of Object.keys(themeVariables)) rootStyle.removeProperty(property);
2564
- };
2565
- }
2566
- function AppShell(arg0) {
2567
- const { config, routes, navigation } = arg0;
2568
- const location = (0, react_router_dom.useLocation)();
2569
- const pathname = normalizeRoutePath(location.pathname);
2570
- const currentRoute = routeForPath(routes, pathname);
2571
- const currentLocale = localeForPath(config, pathname, currentRoute);
2572
- const currentLocaleConfig = config.i18n?.locales.find((locale) => locale.code === currentLocale);
2573
- const currentNavigation = navigationForLocale(navigation, currentLocale, pathname);
2574
- const sections = sectionsForRoute(currentRoute);
2575
- const hasTabs = Boolean(currentNavigation.tabs?.length);
2576
- const themeVariables = themeStyle(config);
2577
- const renderRoutes = (0, react.useMemo)(() => routes.map((route) => ({
2578
- ...route,
2579
- component: resolveRouteComponent(route)
2580
- })), [routes]);
2581
- (0, react.useEffect)(() => applyRootThemeVariables(themeVariables), [themeVariables]);
2582
- (0, react.useEffect)(() => {
2583
- if (location.hash) {
2584
- scrollToHash(location.hash);
2585
- return;
2586
- }
2587
- window.scrollTo({
2588
- top: 0,
2589
- left: 0
2590
- });
2591
- window.requestAnimationFrame(() => {
2592
- window.dispatchEvent(new Event("scroll"));
2593
- });
2594
- }, [location.hash, location.pathname]);
2595
- (0, react.useEffect)(() => {
2596
- if (!currentLocale) return;
2597
- document.documentElement.lang = currentLocale;
2598
- if (currentLocaleConfig?.dir) document.documentElement.dir = currentLocaleConfig.dir;
2599
- else document.documentElement.removeAttribute("dir");
2600
- }, [currentLocale, currentLocaleConfig?.dir]);
2601
- (0, react.useEffect)(() => {
2602
- applyDocumentMetadata(config, currentRoute);
2603
- }, [config, currentRoute]);
2604
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClarifyLocaleContext.Provider, {
2605
- value: currentLocale,
2606
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionProvider, {
2607
- sections,
2608
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2609
- 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",
2610
- "data-theme-preset": config.theme.preset,
2611
- style: themeVariables,
2612
- children: [
2613
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Header, {
2614
- config,
2615
- navigation: currentNavigation.items,
2616
- tabs: currentNavigation.tabs,
2617
- routes,
2618
- currentLocale,
2619
- currentRoute
2620
- }),
2621
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2622
- 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)]",
2623
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.motion.aside, {
2624
- layoutScroll: true,
2625
- className: (0, clsx.default)("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"),
2626
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Navigation, { navigation: currentNavigation.items })
2627
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2628
- className: (0, clsx.default)("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"),
2629
- children: [
2630
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContentActions, {
2631
- hasTabs,
2632
- route: currentRoute,
2633
- routePrefix: config.routePrefix
2634
- }),
2635
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("main", {
2636
- className: "clarify-main min-w-0 flex-auto",
2637
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Suspense, {
2638
- fallback: null,
2639
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Routes, { children: renderRoutes.map((route) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Route, {
2640
- path: route.path,
2641
- element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(route.component, {})
2642
- }, route.path)) })
2643
- })
2644
- }),
2645
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageNavigation, {
2646
- navigation: currentNavigation.items,
2647
- currentRoute
2648
- })
2649
- ]
2650
- })]
2651
- }),
2652
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageFooter, {})
2653
- ]
2654
- })
2655
- })
2656
- });
2657
- }
2658
- //#endregion
2659
- Object.defineProperty(exports, "ApiEndpointCard", {
2660
- enumerable: true,
2661
- get: function() {
2662
- return ApiEndpointCard;
2663
- }
2664
- });
2665
- Object.defineProperty(exports, "AppShell", {
2666
- enumerable: true,
2667
- get: function() {
2668
- return AppShell;
2669
- }
2670
- });
2671
- Object.defineProperty(exports, "BuiltWithClarify", {
2672
- enumerable: true,
2673
- get: function() {
2674
- return BuiltWithClarify;
2675
- }
2676
- });
2677
2427
  Object.defineProperty(exports, "Button", {
2678
2428
  enumerable: true,
2679
2429
  get: function() {
@@ -2704,6 +2454,12 @@ Object.defineProperty(exports, "ClarifyConfigContext", {
2704
2454
  return ClarifyConfigContext;
2705
2455
  }
2706
2456
  });
2457
+ Object.defineProperty(exports, "ClarifyLocaleContext", {
2458
+ enumerable: true,
2459
+ get: function() {
2460
+ return ClarifyLocaleContext;
2461
+ }
2462
+ });
2707
2463
  Object.defineProperty(exports, "Code", {
2708
2464
  enumerable: true,
2709
2465
  get: function() {
@@ -2716,10 +2472,16 @@ Object.defineProperty(exports, "CodeGroup", {
2716
2472
  return CodeGroup;
2717
2473
  }
2718
2474
  });
2719
- Object.defineProperty(exports, "DocShell", {
2475
+ Object.defineProperty(exports, "Collapse", {
2720
2476
  enumerable: true,
2721
2477
  get: function() {
2722
- return DocShell;
2478
+ return Collapse;
2479
+ }
2480
+ });
2481
+ Object.defineProperty(exports, "ContentActions", {
2482
+ enumerable: true,
2483
+ get: function() {
2484
+ return ContentActions;
2723
2485
  }
2724
2486
  });
2725
2487
  Object.defineProperty(exports, "Feedback", {
@@ -2734,6 +2496,12 @@ Object.defineProperty(exports, "GridPattern", {
2734
2496
  return GridPattern;
2735
2497
  }
2736
2498
  });
2499
+ Object.defineProperty(exports, "Header", {
2500
+ enumerable: true,
2501
+ get: function() {
2502
+ return Header;
2503
+ }
2504
+ });
2737
2505
  Object.defineProperty(exports, "Heading", {
2738
2506
  enumerable: true,
2739
2507
  get: function() {
@@ -2752,16 +2520,16 @@ Object.defineProperty(exports, "Logo", {
2752
2520
  return Logo;
2753
2521
  }
2754
2522
  });
2755
- Object.defineProperty(exports, "OpenApisContext", {
2523
+ Object.defineProperty(exports, "Navigation", {
2756
2524
  enumerable: true,
2757
2525
  get: function() {
2758
- return OpenApisContext;
2526
+ return Navigation;
2759
2527
  }
2760
2528
  });
2761
- Object.defineProperty(exports, "PageFooter", {
2529
+ Object.defineProperty(exports, "OpenApisContext", {
2762
2530
  enumerable: true,
2763
2531
  get: function() {
2764
- return PageFooter;
2532
+ return OpenApisContext;
2765
2533
  }
2766
2534
  });
2767
2535
  Object.defineProperty(exports, "Pre", {
@@ -2800,16 +2568,40 @@ Object.defineProperty(exports, "ThemeToggle", {
2800
2568
  return ThemeToggle;
2801
2569
  }
2802
2570
  });
2803
- Object.defineProperty(exports, "__exportAll", {
2571
+ Object.defineProperty(exports, "copyTextToClipboard", {
2572
+ enumerable: true,
2573
+ get: function() {
2574
+ return copyTextToClipboard;
2575
+ }
2576
+ });
2577
+ Object.defineProperty(exports, "isExternalHref", {
2804
2578
  enumerable: true,
2805
2579
  get: function() {
2806
- return __exportAll;
2580
+ return isExternalHref;
2807
2581
  }
2808
2582
  });
2809
- Object.defineProperty(exports, "__toESM", {
2583
+ Object.defineProperty(exports, "isSameRoutePath", {
2810
2584
  enumerable: true,
2811
2585
  get: function() {
2812
- return __toESM;
2586
+ return isSameRoutePath;
2587
+ }
2588
+ });
2589
+ Object.defineProperty(exports, "localizeHref", {
2590
+ enumerable: true,
2591
+ get: function() {
2592
+ return localizeHref;
2593
+ }
2594
+ });
2595
+ Object.defineProperty(exports, "normalizeRoutePath", {
2596
+ enumerable: true,
2597
+ get: function() {
2598
+ return normalizeRoutePath;
2599
+ }
2600
+ });
2601
+ Object.defineProperty(exports, "prefixHref", {
2602
+ enumerable: true,
2603
+ get: function() {
2604
+ return prefixHref;
2813
2605
  }
2814
2606
  });
2815
2607
  Object.defineProperty(exports, "remToPx", {
@@ -2818,6 +2610,12 @@ Object.defineProperty(exports, "remToPx", {
2818
2610
  return remToPx;
2819
2611
  }
2820
2612
  });
2613
+ Object.defineProperty(exports, "safeDecodeURIComponent", {
2614
+ enumerable: true,
2615
+ get: function() {
2616
+ return safeDecodeURIComponent;
2617
+ }
2618
+ });
2821
2619
  Object.defineProperty(exports, "useBuiltInText", {
2822
2620
  enumerable: true,
2823
2621
  get: function() {
@@ -2849,4 +2647,4 @@ Object.defineProperty(exports, "useTheme", {
2849
2647
  }
2850
2648
  });
2851
2649
 
2852
- //# sourceMappingURL=AppShell-CZw1MrPG.cjs.map
2650
+ //# sourceMappingURL=shell-_MyLsMUI.cjs.map