@clarify-labs/renderer 0.1.0 → 0.4.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 (43) hide show
  1. package/output/{AppShell-DBgUlirU.cjs → AppShell-CZw1MrPG.cjs} +1119 -394
  2. package/output/AppShell-CZw1MrPG.cjs.map +1 -0
  3. package/output/{AppShell-C_bj6ZhV.js → AppShell-nQnuKyn2.js} +1098 -397
  4. package/output/AppShell-nQnuKyn2.js.map +1 -0
  5. package/output/client.cjs +1 -1
  6. package/output/client.js +1 -1
  7. package/output/components/Callout.d.ts +10 -0
  8. package/output/components/Card.d.ts +15 -0
  9. package/output/components/PageNavigation.d.ts +5 -0
  10. package/output/components/index.d.ts +5 -0
  11. package/output/context.d.ts +2 -0
  12. package/output/i18n.d.ts +5 -0
  13. package/output/index.cjs +1357 -346
  14. package/output/index.cjs.map +1 -1
  15. package/output/index.d.ts +2 -2
  16. package/output/index.js +1355 -347
  17. package/output/index.js.map +1 -1
  18. package/output/mdx/components.d.ts +3 -0
  19. package/output/mdx/primitives.d.ts +2 -2
  20. package/output/openapi/example-panels.d.ts +31 -0
  21. package/output/openapi/helpers.d.ts +24 -0
  22. package/output/openapi/index.d.ts +2 -19
  23. package/output/openapi/openapi-page.d.ts +19 -0
  24. package/output/openapi/request-code.d.ts +16 -0
  25. package/output/openapi/schema-properties.d.ts +15 -0
  26. package/output/openapi/spec-path.d.ts +2 -0
  27. package/output/openapi/types.d.ts +66 -0
  28. package/output/{render-Ca4Is683.js → render-BCiQn6Q1.js} +2 -2
  29. package/output/{render-Ca4Is683.js.map → render-BCiQn6Q1.js.map} +1 -1
  30. package/output/{render-CLI-MnH_.cjs → render-CZsdzmme.cjs} +2 -2
  31. package/output/{render-CLI-MnH_.cjs.map → render-CZsdzmme.cjs.map} +1 -1
  32. package/output/renderer.css +1636 -551
  33. package/output/server.cjs +1 -1
  34. package/output/server.js +1 -1
  35. package/output/shell/ContentActions.d.ts +1 -0
  36. package/output/shell/Header.d.ts +4 -3
  37. package/output/shell/icons.d.ts +4 -0
  38. package/output/shell/mobile.d.ts +2 -1
  39. package/output/types.d.ts +62 -9
  40. package/output/utils/path.d.ts +2 -0
  41. package/package.json +7 -1
  42. package/output/AppShell-C_bj6ZhV.js.map +0 -1
  43. package/output/AppShell-DBgUlirU.cjs.map +0 -1
@@ -1,12 +1,12 @@
1
+ import clsx from "clsx";
1
2
  import { AnimatePresence, motion, useInView, useIsPresent, useScroll, useTransform } from "framer-motion";
2
- import { Children, Fragment, Suspense, createContext, forwardRef, isValidElement, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
3
+ import { Children, Fragment, Suspense, createContext, forwardRef, isValidElement, lazy, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
3
4
  import { Link, Route, Routes, useLocation, useNavigate } from "react-router-dom";
4
5
  import { create, createStore, useStore } from "zustand";
5
6
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
6
- import clsx from "clsx";
7
- import { CloseButton, Dialog, DialogBackdrop, DialogPanel, Menu, MenuButton, MenuItem, MenuItems, Tab, TabGroup, TabList, TabPanel, TabPanels, Transition, TransitionChild } from "@headlessui/react";
8
7
  import * as LucideIcons from "lucide-react";
9
- import { Check, ChevronDown, Copy, Link2 } from "lucide-react";
8
+ import { AlertTriangle, Check, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, Copy, ExternalLink, FileText, Info, Lightbulb, Link2, MoreHorizontal, XCircle } from "lucide-react";
9
+ import { CloseButton, Dialog, DialogBackdrop, DialogPanel, Menu, MenuButton, MenuItem, MenuItems, Tab, TabGroup, TabList, TabPanel, TabPanels, Transition, TransitionChild } from "@headlessui/react";
10
10
  //#region source/utils/remToPx.ts
11
11
  function remToPx(remValue) {
12
12
  return remValue * (typeof window === "undefined" ? 16 : Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize));
@@ -61,7 +61,14 @@ function SectionProvider(arg0) {
61
61
  const [sectionStore] = useState(() => createSectionStore(sections));
62
62
  useVisibleSections(sectionStore);
63
63
  useIsomorphicLayoutEffect(() => {
64
- sectionStore.setState({ sections });
64
+ sectionStore.setState((state) => ({ sections: sections.map((section) => {
65
+ const registeredSection = state.sections.find((item) => item.id === section.id);
66
+ return {
67
+ ...section,
68
+ headingRef: registeredSection?.headingRef,
69
+ offsetRem: registeredSection?.offsetRem ?? section.offsetRem
70
+ };
71
+ }) }));
65
72
  }, [sectionStore, sections]);
66
73
  return /* @__PURE__ */ jsx(SectionStoreContext.Provider, {
67
74
  value: sectionStore,
@@ -74,110 +81,179 @@ function useSectionStore(selector) {
74
81
  return useStore(store, selector);
75
82
  }
76
83
  //#endregion
77
- //#region source/components/SiteLogo.tsx
78
- function SiteLogo(arg0) {
79
- const { logo, className } = arg0;
80
- if (!logo) return null;
81
- if (typeof logo === "string") return /* @__PURE__ */ jsx("img", {
82
- src: logo,
83
- alt: "",
84
- className: clsx("clarify-logo", className)
85
- });
86
- const lightLogo = logo.light ?? logo.dark;
87
- const darkLogo = logo.dark ?? logo.light;
88
- if (!lightLogo || !darkLogo) return null;
89
- if (lightLogo === darkLogo) return /* @__PURE__ */ jsx("img", {
90
- src: lightLogo,
91
- alt: "",
92
- className: clsx("clarify-logo", className)
93
- });
94
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("img", {
95
- src: lightLogo,
96
- alt: "",
97
- className: clsx("clarify-logo clarify-logo-light", className, "dark:hidden")
98
- }), /* @__PURE__ */ jsx("img", {
99
- src: darkLogo,
100
- alt: "",
101
- className: clsx("clarify-logo clarify-logo-dark", className, "hidden dark:block")
102
- })] });
84
+ //#region source/context.tsx
85
+ var ClarifyConfigContext = createContext(null);
86
+ var ClarifyLocaleContext = createContext(void 0);
87
+ var OpenApisContext = createContext({});
88
+ function useClarifyConfig() {
89
+ const config = useContext(ClarifyConfigContext);
90
+ if (!config) throw new Error("[clarify] useClarifyConfig must be used within a ClarifyConfigContext.Provider");
91
+ return config;
92
+ }
93
+ function useOpenApis() {
94
+ return useContext(OpenApisContext);
103
95
  }
104
96
  //#endregion
105
- //#region source/shell/ContentActions.tsx
106
- function resolveRawContentUrl(rawContentUrl, routePrefix = "/") {
107
- if (!routePrefix || routePrefix === "/") return rawContentUrl;
108
- return `/${routePrefix.replace(/^\/+|\/+$/g, "")}${rawContentUrl}`;
97
+ //#region source/i18n.ts
98
+ var builtInText = {
99
+ en: {
100
+ "actions.code": "Code",
101
+ "actions.copy": "Copy",
102
+ "actions.copied": "Copied!",
103
+ "builtWith.label": "Built with Clarify",
104
+ "builtWith.prefix": "Built with",
105
+ "callout.danger": "Danger",
106
+ "callout.info": "Info",
107
+ "callout.note": "Note",
108
+ "callout.success": "Success",
109
+ "callout.tip": "Tip",
110
+ "callout.warning": "Warning",
111
+ "contentActions.copyContent": "Copy page",
112
+ "contentActions.copyContentDescription": "Copy this page as {contentType} for LLMs",
113
+ "contentActions.copyLink": "Copy {contentType} link",
114
+ "contentActions.copyLinkDescription": "Copy the raw {contentType} content link for this page",
115
+ "contentActions.copyOptions": "Choose copy option",
116
+ "contentActions.copiedContent": "Copied page",
117
+ "contentActions.copiedLink": "Copied link",
118
+ "contentActions.viewMarkdown": "View as Markdown",
119
+ "contentActions.viewMarkdownDescription": "View this page as plain text",
120
+ "contentActions.viewOpenApi": "View raw OpenAPI",
121
+ "contentActions.viewOpenApiDescription": "Open the API description file in a new tab",
122
+ "feedback.no": "No",
123
+ "feedback.prompt": "Was this page helpful?",
124
+ "feedback.thanks": "Thanks for your feedback!",
125
+ "feedback.yes": "Yes",
126
+ "navigation.documentation": "Documentation",
127
+ "navigation.next": "Next",
128
+ "navigation.previous": "Previous",
129
+ "navigation.previousNext": "Previous and next pages",
130
+ "navigation.toggle": "Toggle navigation",
131
+ "navbar.home": "Home",
132
+ "navbar.openLinks": "Open navigation links",
133
+ "navbar.sections": "Documentation sections",
134
+ "openapi.apiDocumentation": "API Documentation",
135
+ "openapi.bodyProperties": "Body properties",
136
+ "openapi.collapse": "Collapse",
137
+ "openapi.endpointNotFound": "Endpoint not found: {endpoint}",
138
+ "openapi.example": "Example",
139
+ "openapi.expand": "Expand",
140
+ "openapi.headers": "Headers",
141
+ "openapi.language": "Language",
142
+ "openapi.client": "Client",
143
+ "openapi.mediaType": "Media type",
144
+ "openapi.openApiReference": "OpenAPI Reference",
145
+ "openapi.operationParameter": "Operation parameter.",
146
+ "openapi.optional": "Optional.",
147
+ "openapi.parameter": "parameter",
148
+ "openapi.pathParameters": "Path parameters",
149
+ "openapi.queryParameters": "Query parameters",
150
+ "openapi.request": "Request",
151
+ "openapi.requestBody": "Request body",
152
+ "openapi.required": "Required.",
153
+ "openapi.requiredBadge": "required",
154
+ "openapi.response": "Response",
155
+ "openapi.responses": "Responses",
156
+ "openapi.schemaExample": "Schema example",
157
+ "openapi.scrollExamplesLeft": "Scroll examples left",
158
+ "openapi.scrollExamplesRight": "Scroll examples right",
159
+ "openapi.specNotFound": "OpenAPI spec not found: {specPath}",
160
+ "openapi.specPathMissing": "spec or specPath was not provided",
161
+ "openapi.status": "Status",
162
+ "openapi.version": "Version {version}",
163
+ "search.button": "Search...",
164
+ "search.noResults": "Nothing found for {query}.",
165
+ "search.placeholder": "Find something...",
166
+ "search.shortcutCtrl": "Ctrl ",
167
+ "theme.switchToDark": "Switch to dark theme",
168
+ "theme.switchToLight": "Switch to light theme",
169
+ "language.switch": "Switch language"
170
+ },
171
+ "zh-CN": {
172
+ "actions.code": "代码",
173
+ "actions.copy": "复制",
174
+ "actions.copied": "已复制!",
175
+ "builtWith.label": "由 Clarify 构建",
176
+ "builtWith.prefix": "构建来自",
177
+ "callout.danger": "危险",
178
+ "callout.info": "信息",
179
+ "callout.note": "注意",
180
+ "callout.success": "成功",
181
+ "callout.tip": "提示",
182
+ "callout.warning": "警告",
183
+ "contentActions.copyContent": "复制页面",
184
+ "contentActions.copyContentDescription": "将页面以 {contentType} 格式复制给 LLMs",
185
+ "contentActions.copyLink": "复制 {contentType} 链接",
186
+ "contentActions.copyLinkDescription": "复制当前页面的 {contentType} 原始内容链接",
187
+ "contentActions.copyOptions": "选择复制选项",
188
+ "contentActions.copiedContent": "已复制页面",
189
+ "contentActions.copiedLink": "已复制链接",
190
+ "contentActions.viewMarkdown": "以 Markdown 格式查看",
191
+ "contentActions.viewMarkdownDescription": "以纯文本查看此页面",
192
+ "contentActions.viewOpenApi": "查看 OpenAPI 原始内容",
193
+ "contentActions.viewOpenApiDescription": "在新标签页打开 API 描述文件",
194
+ "feedback.no": "否",
195
+ "feedback.prompt": "这个页面有帮助吗?",
196
+ "feedback.thanks": "感谢你的反馈!",
197
+ "feedback.yes": "是",
198
+ "navigation.documentation": "文档",
199
+ "navigation.next": "下一页",
200
+ "navigation.previous": "上一页",
201
+ "navigation.previousNext": "上一页和下一页",
202
+ "navigation.toggle": "切换导航",
203
+ "navbar.home": "首页",
204
+ "navbar.openLinks": "打开导航链接",
205
+ "navbar.sections": "文档栏目",
206
+ "openapi.apiDocumentation": "API 文档",
207
+ "openapi.bodyProperties": "请求体属性",
208
+ "openapi.collapse": "收起",
209
+ "openapi.endpointNotFound": "未找到端点:{endpoint}",
210
+ "openapi.example": "示例",
211
+ "openapi.expand": "展开",
212
+ "openapi.headers": "请求头",
213
+ "openapi.language": "语言",
214
+ "openapi.client": "客户端",
215
+ "openapi.mediaType": "媒体类型",
216
+ "openapi.openApiReference": "OpenAPI 参考",
217
+ "openapi.operationParameter": "操作参数。",
218
+ "openapi.optional": "可选。",
219
+ "openapi.parameter": "参数",
220
+ "openapi.pathParameters": "路径参数",
221
+ "openapi.queryParameters": "查询参数",
222
+ "openapi.request": "请求",
223
+ "openapi.requestBody": "请求体",
224
+ "openapi.required": "必填。",
225
+ "openapi.requiredBadge": "必填",
226
+ "openapi.response": "响应",
227
+ "openapi.responses": "响应",
228
+ "openapi.schemaExample": "Schema 示例",
229
+ "openapi.scrollExamplesLeft": "向左滚动示例",
230
+ "openapi.scrollExamplesRight": "向右滚动示例",
231
+ "openapi.specNotFound": "未找到 OpenAPI 描述文件:{specPath}",
232
+ "openapi.specPathMissing": "未提供 spec 或 specPath",
233
+ "openapi.status": "状态",
234
+ "openapi.version": "版本 {version}",
235
+ "search.button": "搜索...",
236
+ "search.noResults": "没有找到与 {query} 相关的结果。",
237
+ "search.placeholder": "搜索内容...",
238
+ "search.shortcutCtrl": "Ctrl ",
239
+ "theme.switchToDark": "切换到深色主题",
240
+ "theme.switchToLight": "切换到浅色主题",
241
+ "language.switch": "切换语言"
242
+ }
243
+ };
244
+ function resolveBuiltInLocale(locale) {
245
+ return locale === "zh-CN" || locale?.toLowerCase().startsWith("zh") ? "zh-CN" : "en";
109
246
  }
110
- function getAbsoluteUrl(path) {
111
- if (typeof window === "undefined") return path;
112
- return new URL(path, window.location.href).href;
247
+ function translateBuiltInText(locale, key, replacements = {}) {
248
+ let value = builtInText[resolveBuiltInLocale(locale)]?.[key] ?? builtInText.en[key];
249
+ for (const [name, replacement] of Object.entries(replacements)) value = value.replaceAll(`{${name}}`, replacement);
250
+ return value;
113
251
  }
114
- async function copyText(text) {
115
- await navigator.clipboard.writeText(text);
116
- }
117
- function ContentActions(arg0) {
118
- const { route, routePrefix } = arg0;
119
- const [copied, setCopied] = useState("idle");
120
- if (!route?.rawContentUrl) return null;
121
- const rawContentUrl = resolveRawContentUrl(route.rawContentUrl, routePrefix);
122
- const isOpenApi = route.kind === "openapi";
123
- const contentLabel = isOpenApi ? "复制 OpenAPI 内容" : "复制 Markdown 内容";
124
- const linkLabel = isOpenApi ? "复制 OpenAPI 链接" : "复制 Markdown 链接";
125
- function markCopied(state) {
126
- setCopied(state);
127
- window.setTimeout(() => setCopied("idle"), 1600);
128
- }
129
- async function handleCopyContent() {
130
- await copyText(await (await fetch(rawContentUrl)).text());
131
- markCopied("content");
132
- }
133
- async function handleCopyLink() {
134
- await copyText(getAbsoluteUrl(rawContentUrl));
135
- markCopied("link");
136
- }
137
- const actions = [{
138
- key: "content",
139
- label: contentLabel,
140
- icon: Copy,
141
- run: handleCopyContent
142
- }, {
143
- key: "link",
144
- label: linkLabel,
145
- icon: Link2,
146
- run: handleCopyLink
147
- }];
148
- const primaryAction = actions[0];
149
- return /* @__PURE__ */ jsx("div", {
150
- className: "clarify-content-actions sticky top-16 z-20 flex justify-end py-4",
151
- children: /* @__PURE__ */ jsxs(Menu, {
152
- as: "div",
153
- className: "clarify-content-actions-menu relative inline-flex text-xs font-medium",
154
- children: [/* @__PURE__ */ jsxs("div", {
155
- className: "clarify-content-actions-group inline-flex overflow-hidden rounded-full border border-zinc-900/10 bg-white/85 backdrop-blur dark:border-white/10 dark:bg-white/5",
156
- children: [/* @__PURE__ */ jsxs("button", {
157
- type: "button",
158
- onClick: primaryAction.run,
159
- className: "clarify-content-actions-primary inline-flex h-8 items-center gap-1.5 px-3 text-zinc-600 transition hover:bg-zinc-100 hover:text-zinc-950 dark:text-zinc-300 dark:hover:bg-white/10 dark:hover:text-white",
160
- children: [copied === primaryAction.key ? /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx(primaryAction.icon, { className: "h-3.5 w-3.5" }), copied === primaryAction.key ? "已复制" : "复制页面"]
161
- }), /* @__PURE__ */ jsx(MenuButton, {
162
- className: "clarify-content-actions-trigger inline-flex h-8 w-8 items-center justify-center border-l border-zinc-900/10 text-zinc-500 transition hover:bg-zinc-100 hover:text-zinc-950 dark:border-white/10 dark:text-zinc-400 dark:hover:bg-white/10 dark:hover:text-white",
163
- "aria-label": "选择复制选项",
164
- children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5" })
165
- })]
166
- }), /* @__PURE__ */ jsx(MenuItems, {
167
- anchor: "bottom end",
168
- className: "clarify-content-actions-list z-30 mt-2 w-52 origin-top-right rounded-2xl border border-zinc-900/10 bg-white p-1 text-xs shadow-md transition [--anchor-gap:--spacing(2)] focus:outline-none data-closed:scale-95 data-closed:opacity-0 dark:border-white/10 dark:bg-zinc-900",
169
- children: actions.map((action) => {
170
- const Icon = copied === action.key ? Check : action.icon;
171
- return /* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsxs("button", {
172
- type: "button",
173
- onClick: action.run,
174
- className: "clarify-content-actions-item flex w-full items-center gap-2 rounded-xl px-3 py-2 text-left text-zinc-600 transition data-focus:bg-zinc-100 data-focus:text-zinc-950 dark:text-zinc-300 dark:data-focus:bg-white/10 dark:data-focus:text-white",
175
- children: [/* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ jsx("span", { children: copied === action.key ? "已复制" : action.label })]
176
- }) }, action.key);
177
- })
178
- })]
179
- })
180
- });
252
+ function useBuiltInText(locale) {
253
+ const config = useContext(ClarifyConfigContext);
254
+ const currentLocale = useContext(ClarifyLocaleContext);
255
+ const resolvedLocale = locale ?? currentLocale ?? config?.i18n?.defaultLocale;
256
+ return (key, replacements) => translateBuiltInText(resolvedLocale, key, replacements);
181
257
  }
182
258
  //#endregion
183
259
  //#region source/components/BuiltWithClarify.tsx
@@ -205,23 +281,163 @@ function ClarifyMark(props) {
205
281
  });
206
282
  }
207
283
  function BuiltWithClarify() {
284
+ const t = useBuiltInText();
208
285
  return /* @__PURE__ */ jsxs("a", {
209
286
  href: "https://clarify.pub",
210
287
  target: "_blank",
211
288
  rel: "noreferrer",
212
- "aria-label": "Built with Clarify",
213
- className: "clarify-built-with inline-flex items-center gap-1.5 rounded-full px-2 py-1 text-xs font-medium text-zinc-500 no-underline transition hover:bg-zinc-900/2.5 hover:text-zinc-900 dark:text-zinc-500 dark:hover:bg-white/5 dark:hover:text-white",
289
+ "aria-label": t("builtWith.label"),
290
+ className: "clarify-built-with inline-flex items-center gap-1.5 rounded-full px-2 py-1 font-medium no-underline transition",
214
291
  children: [
215
- /* @__PURE__ */ jsx("span", { children: "Built with" }),
292
+ /* @__PURE__ */ jsx("span", { children: t("builtWith.prefix") }),
216
293
  /* @__PURE__ */ jsx(ClarifyMark, { className: "clarify-built-with-logo h-3.5 w-5 flex-none" }),
217
294
  /* @__PURE__ */ jsx("span", {
218
- className: "font-semibold text-zinc-700 dark:text-zinc-300",
295
+ className: "clarify-built-with-brand font-semibold",
219
296
  children: "Clarify"
220
297
  })
221
298
  ]
222
299
  });
223
300
  }
224
301
  //#endregion
302
+ //#region source/components/Callout.tsx
303
+ var calloutStyles = {
304
+ info: {
305
+ container: "border-sky-500/20 bg-sky-50/50 text-sky-950 dark:border-sky-400/30 dark:bg-sky-400/5 dark:text-sky-100",
306
+ icon: "text-sky-600 dark:text-sky-400",
307
+ title: "text-sky-900 dark:text-sky-100",
308
+ Icon: Info
309
+ },
310
+ note: {
311
+ container: "border-zinc-500/20 bg-zinc-50 text-zinc-900 dark:border-white/10 dark:bg-white/5 dark:text-zinc-200",
312
+ icon: "text-zinc-500 dark:text-zinc-400",
313
+ title: "text-zinc-900 dark:text-white",
314
+ Icon: Info
315
+ },
316
+ tip: {
317
+ container: "border-emerald-500/20 bg-emerald-50/50 text-emerald-950 dark:border-emerald-400/30 dark:bg-emerald-400/5 dark:text-emerald-100",
318
+ icon: "text-emerald-600 dark:text-emerald-400",
319
+ title: "text-emerald-900 dark:text-emerald-100",
320
+ Icon: Lightbulb
321
+ },
322
+ warning: {
323
+ container: "border-amber-500/20 bg-amber-50/70 text-amber-950 dark:border-amber-400/30 dark:bg-amber-400/5 dark:text-amber-100",
324
+ icon: "text-amber-600 dark:text-amber-400",
325
+ title: "text-amber-900 dark:text-amber-100",
326
+ Icon: AlertTriangle
327
+ },
328
+ danger: {
329
+ container: "border-rose-500/20 bg-rose-50/70 text-rose-950 dark:border-rose-400/30 dark:bg-rose-400/5 dark:text-rose-100",
330
+ icon: "text-rose-600 dark:text-rose-400",
331
+ title: "text-rose-900 dark:text-rose-100",
332
+ Icon: XCircle
333
+ },
334
+ success: {
335
+ container: "border-emerald-500/20 bg-emerald-50/50 text-emerald-950 dark:border-emerald-400/30 dark:bg-emerald-400/5 dark:text-emerald-100",
336
+ icon: "text-emerald-600 dark:text-emerald-400",
337
+ title: "text-emerald-900 dark:text-emerald-100",
338
+ Icon: CheckCircle2
339
+ }
340
+ };
341
+ var defaultTitleKeys = {
342
+ info: "callout.info",
343
+ note: "callout.note",
344
+ tip: "callout.tip",
345
+ warning: "callout.warning",
346
+ danger: "callout.danger",
347
+ success: "callout.success"
348
+ };
349
+ function Callout(arg0) {
350
+ const { children, type = "info", title, icon = true, className, ...props } = arg0;
351
+ const t = useBuiltInText();
352
+ const style = calloutStyles[type];
353
+ const Icon = style.Icon;
354
+ const resolvedTitle = title === void 0 ? t(defaultTitleKeys[type]) : title;
355
+ return /* @__PURE__ */ jsxs("div", {
356
+ className: clsx("clarify-callout my-6 flex gap-3 rounded-(--clarify-theme-tokens-radius-xl) border p-4 text-sm/6", style.container, className),
357
+ ...props,
358
+ children: [icon ? /* @__PURE__ */ jsx(Icon, {
359
+ className: clsx("mt-1 size-4 flex-none", style.icon),
360
+ "aria-hidden": "true"
361
+ }) : null, /* @__PURE__ */ jsxs("div", {
362
+ className: "min-w-0 flex-1 *:first:mt-0 *:last:mb-0",
363
+ children: [resolvedTitle ? /* @__PURE__ */ jsx("p", {
364
+ className: clsx("mb-1 font-semibold", style.title),
365
+ children: resolvedTitle
366
+ }) : null, /* @__PURE__ */ jsx("div", {
367
+ className: "*:first:mt-0 *:last:mb-0",
368
+ children
369
+ })]
370
+ })]
371
+ });
372
+ }
373
+ //#endregion
374
+ //#region source/components/Card.tsx
375
+ function toPascalCase(value) {
376
+ return value.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join("");
377
+ }
378
+ function CardIcon(arg0) {
379
+ const { name } = arg0;
380
+ if (!name) return null;
381
+ const Icon = LucideIcons[toPascalCase(name)];
382
+ if (!Icon) return null;
383
+ return /* @__PURE__ */ jsx("span", {
384
+ className: "flex size-9 flex-none items-center justify-center rounded-[var(--clarify-theme-tokens-radius-lg)] bg-(--clarify-ui-accent-background) text-(--clarify-ui-accent-text) ring-1 ring-(--clarify-ui-accent-border)",
385
+ children: /* @__PURE__ */ jsx(Icon, {
386
+ className: "size-5",
387
+ "aria-hidden": "true"
388
+ })
389
+ });
390
+ }
391
+ var cardGroupColumnStyles = {
392
+ 1: "grid-cols-1",
393
+ 2: "grid-cols-1 sm:grid-cols-2",
394
+ 3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
395
+ 4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4"
396
+ };
397
+ function CardGroup(arg0) {
398
+ const { children, cols = 2, className } = arg0;
399
+ return /* @__PURE__ */ jsx("div", {
400
+ className: clsx("not-prose my-10 grid gap-4", cardGroupColumnStyles[cols], className),
401
+ children
402
+ });
403
+ }
404
+ function Card(arg0) {
405
+ const { title, icon, href, children, className, ...props } = arg0;
406
+ const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
407
+ className: "flex items-start gap-4",
408
+ children: [/* @__PURE__ */ jsx(CardIcon, { name: icon }), /* @__PURE__ */ jsxs("div", {
409
+ className: "min-w-0 flex-1",
410
+ children: [/* @__PURE__ */ jsx("h3", {
411
+ className: "m-0 text-base font-semibold text-[var(--clarify-theme-tokens-colors-foreground)] dark:text-white",
412
+ children: title
413
+ }), children ? /* @__PURE__ */ jsx("div", {
414
+ className: "mt-2 text-sm/6 text-[var(--clarify-theme-tokens-colors-muted)] dark:text-zinc-400 *:m-0",
415
+ children
416
+ }) : null]
417
+ })]
418
+ }), href ? /* @__PURE__ */ jsx("span", {
419
+ className: "absolute inset-0 rounded-[var(--clarify-theme-tokens-radius-xl)]",
420
+ "aria-hidden": "true"
421
+ }) : null] });
422
+ const classes = clsx("group relative block rounded-[var(--clarify-theme-tokens-radius-xl)] border border-[color:var(--clarify-theme-tokens-colors-border)] bg-[var(--clarify-theme-tokens-colors-surface)] p-5 shadow-sm shadow-(--clarify-ui-accent-glow) transition hover:border-(--clarify-ui-accent-border) hover:shadow-md dark:bg-zinc-900/50", className);
423
+ if (!href) return /* @__PURE__ */ jsx("div", {
424
+ className: classes,
425
+ children: content
426
+ });
427
+ if (href.startsWith("/") && !href.startsWith("//")) return /* @__PURE__ */ jsx(Link, {
428
+ to: href,
429
+ className: classes,
430
+ ...props,
431
+ children: content
432
+ });
433
+ return /* @__PURE__ */ jsx("a", {
434
+ href,
435
+ className: classes,
436
+ ...props,
437
+ children: content
438
+ });
439
+ }
440
+ //#endregion
225
441
  //#region source/components/Code.tsx
226
442
  var languageNames = {
227
443
  js: "JavaScript",
@@ -240,10 +456,10 @@ var languageNames = {
240
456
  json: "JSON"
241
457
  };
242
458
  function getPanelTitle(arg0) {
243
- const { title, language } = arg0;
459
+ const { title, language, fallbackTitle = "Code" } = arg0;
244
460
  if (title) return title;
245
461
  if (language && language in languageNames) return languageNames[language];
246
- return "Code";
462
+ return fallbackTitle;
247
463
  }
248
464
  function getNodeText(node) {
249
465
  if (typeof node === "string" || typeof node === "number") return String(node);
@@ -251,7 +467,7 @@ function getNodeText(node) {
251
467
  if (isValidElement(node)) return getNodeText(node.props.children);
252
468
  return "";
253
469
  }
254
- function ClipboardIcon(props) {
470
+ function ClipboardIcon$1(props) {
255
471
  return /* @__PURE__ */ jsxs("svg", {
256
472
  viewBox: "0 0 20 20",
257
473
  "aria-hidden": "true",
@@ -268,6 +484,7 @@ function ClipboardIcon(props) {
268
484
  }
269
485
  function CopyButton(arg0) {
270
486
  const { code } = arg0;
487
+ const t = useBuiltInText();
271
488
  const [copyCount, setCopyCount] = useState(0);
272
489
  const copied = copyCount > 0;
273
490
  useEffect(() => {
@@ -278,7 +495,7 @@ function CopyButton(arg0) {
278
495
  if (!code) return null;
279
496
  return /* @__PURE__ */ jsxs("button", {
280
497
  type: "button",
281
- className: clsx("clarify-code-copy group/button absolute top-3.5 right-4 overflow-hidden rounded-full py-1 pr-3 pl-2 text-2xs font-medium opacity-0 backdrop-blur-sm transition group-hover:opacity-100 focus:opacity-100", copied ? "bg-emerald-400/10 ring-1 ring-emerald-400/20 ring-inset" : "bg-white/5 hover:bg-white/7.5 dark:bg-white/2.5 dark:hover:bg-white/5"),
498
+ className: clsx("clarify-code-copy group/button absolute top-3.5 right-4 overflow-hidden rounded-full py-1 pr-3 pl-2 text-2xs font-medium opacity-0 backdrop-blur-sm transition group-hover:opacity-100 focus:opacity-100", copied ? "bg-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-primary)_12%,transparent)] ring-1 ring-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-primary)_24%,transparent)] ring-inset" : "bg-white/5 hover:bg-white/7.5 dark:bg-white/2.5 dark:hover:bg-white/5"),
282
499
  onClick: () => {
283
500
  window.navigator.clipboard.writeText(code).then(() => {
284
501
  setCopyCount((count) => count + 1);
@@ -287,11 +504,11 @@ function CopyButton(arg0) {
287
504
  children: [/* @__PURE__ */ jsxs("span", {
288
505
  "aria-hidden": copied,
289
506
  className: clsx("pointer-events-none flex items-center gap-0.5 text-zinc-400 transition duration-300", copied && "-translate-y-1.5 opacity-0"),
290
- children: [/* @__PURE__ */ jsx(ClipboardIcon, { className: "h-5 w-5 fill-zinc-500/20 stroke-zinc-500 transition-colors group-hover/button:stroke-zinc-400" }), "Copy"]
507
+ children: [/* @__PURE__ */ jsx(ClipboardIcon$1, { className: "h-5 w-5 fill-zinc-500/20 stroke-zinc-500 transition-colors group-hover/button:stroke-zinc-400" }), t("actions.copy")]
291
508
  }), /* @__PURE__ */ jsx("span", {
292
509
  "aria-hidden": !copied,
293
- className: clsx("pointer-events-none absolute inset-0 flex items-center justify-center text-emerald-400 transition duration-300", !copied && "translate-y-1.5 opacity-0"),
294
- children: "Copied!"
510
+ className: clsx("pointer-events-none absolute inset-0 flex items-center justify-center text-[var(--clarify-theme-tokens-colors-primary)] transition duration-300", !copied && "translate-y-1.5 opacity-0"),
511
+ children: t("actions.copied")
295
512
  })]
296
513
  });
297
514
  }
@@ -302,7 +519,7 @@ function CodePanelHeader(arg0) {
302
519
  className: "clarify-code-panel-header flex h-9 items-center gap-2 border-y border-t-transparent border-b-white/7.5 bg-zinc-900 px-4 dark:border-b-white/5 dark:bg-white/1",
303
520
  children: [
304
521
  tag ? /* @__PURE__ */ jsx("span", {
305
- className: "font-mono text-[0.625rem]/6 font-semibold text-emerald-400",
522
+ className: "font-mono text-[0.625rem]/6 font-semibold text-[var(--clarify-theme-tokens-colors-primary)]",
306
523
  children: tag
307
524
  }) : null,
308
525
  tag && label ? /* @__PURE__ */ jsx("span", { className: "h-0.5 w-0.5 rounded-full bg-zinc-500" }) : null,
@@ -340,6 +557,7 @@ function CodePanel(arg0) {
340
557
  }
341
558
  function CodeGroupHeader(arg0) {
342
559
  const { title, children, selectedIndex } = arg0;
560
+ const t = useBuiltInText();
343
561
  const hasTabs = Children.count(children) > 1;
344
562
  if (!title && !hasTabs) return null;
345
563
  return /* @__PURE__ */ jsxs("div", {
@@ -350,8 +568,11 @@ function CodeGroupHeader(arg0) {
350
568
  }) : null, hasTabs ? /* @__PURE__ */ jsx(TabList, {
351
569
  className: "clarify-code-tabs -mb-px flex gap-4 text-xs font-medium",
352
570
  children: Children.map(children, (child, childIndex) => /* @__PURE__ */ jsx(Tab, {
353
- className: clsx("clarify-code-tab border-b py-3 transition data-selected:not-data-focus:outline-hidden", childIndex === selectedIndex ? "border-emerald-500 text-emerald-400" : "border-transparent text-zinc-400 hover:text-zinc-300"),
354
- children: getPanelTitle(isValidElement(child) ? child.props : {})
571
+ className: clsx("clarify-code-tab border-b py-3 transition data-selected:not-data-focus:outline-hidden", childIndex === selectedIndex ? "border-[var(--clarify-theme-tokens-colors-primary)] text-[var(--clarify-theme-tokens-colors-primary)]" : "border-transparent text-zinc-400 hover:text-zinc-300"),
572
+ children: getPanelTitle({
573
+ ...isValidElement(child) ? child.props : {},
574
+ fallbackTitle: t("actions.code")
575
+ })
355
576
  }))
356
577
  }) : null]
357
578
  });
@@ -412,7 +633,11 @@ function useTabGroupProps(availableLanguages) {
412
633
  var CodeGroupContext = createContext(false);
413
634
  function CodeGroup(arg0) {
414
635
  const { children, title, ...props } = arg0;
415
- const tabGroupProps = useTabGroupProps(Children.map(children, (child) => getPanelTitle(isValidElement(child) ? child.props : {})) ?? []);
636
+ const t = useBuiltInText();
637
+ const tabGroupProps = useTabGroupProps(Children.map(children, (child) => getPanelTitle({
638
+ ...isValidElement(child) ? child.props : {},
639
+ fallbackTitle: t("actions.code")
640
+ })) ?? []);
416
641
  const hasTabs = Children.count(children) > 1;
417
642
  const containerClassName = "clarify-code-group my-6 overflow-hidden rounded-2xl bg-zinc-900 shadow-md dark:ring-1 dark:ring-white/10";
418
643
  const header = /* @__PURE__ */ jsx(CodeGroupHeader, {
@@ -491,6 +716,7 @@ function FeedbackButton(props) {
491
716
  }
492
717
  var FeedbackForm = forwardRef(function FeedbackForm(arg0, ref) {
493
718
  const { onSubmit, className, ...props } = arg0;
719
+ const t = useBuiltInText();
494
720
  return /* @__PURE__ */ jsxs("form", {
495
721
  ...props,
496
722
  ref,
@@ -498,18 +724,18 @@ var FeedbackForm = forwardRef(function FeedbackForm(arg0, ref) {
498
724
  className: clsx(className, "clarify-feedback-form absolute inset-0 flex items-center justify-center gap-6 md:justify-start"),
499
725
  children: [/* @__PURE__ */ jsx("p", {
500
726
  className: "text-sm text-zinc-600 dark:text-zinc-400",
501
- children: "Was this page helpful?"
727
+ children: t("feedback.prompt")
502
728
  }), /* @__PURE__ */ jsxs("div", {
503
729
  className: "clarify-feedback-actions group grid h-8 grid-cols-[1fr_1px_1fr] overflow-hidden rounded-full border border-zinc-900/10 dark:border-white/10",
504
730
  children: [
505
731
  /* @__PURE__ */ jsx(FeedbackButton, {
506
732
  "data-response": "yes",
507
- children: "Yes"
733
+ children: t("feedback.yes")
508
734
  }),
509
735
  /* @__PURE__ */ jsx("div", { className: "bg-zinc-900/10 dark:bg-white/10" }),
510
736
  /* @__PURE__ */ jsx(FeedbackButton, {
511
737
  "data-response": "no",
512
- children: "No"
738
+ children: t("feedback.no")
513
739
  })
514
740
  ]
515
741
  })]
@@ -517,13 +743,14 @@ var FeedbackForm = forwardRef(function FeedbackForm(arg0, ref) {
517
743
  });
518
744
  var FeedbackThanks = forwardRef(function FeedbackThanks(arg0, ref) {
519
745
  const { className, ...props } = arg0;
746
+ const t = useBuiltInText();
520
747
  return /* @__PURE__ */ jsx("div", {
521
748
  ...props,
522
749
  ref,
523
750
  className: clsx(className, "clarify-feedback-thanks absolute inset-0 flex justify-center md:justify-start"),
524
751
  children: /* @__PURE__ */ jsxs("div", {
525
- className: "flex items-center gap-3 rounded-full bg-emerald-50/50 py-1 pr-3 pl-1.5 text-sm text-emerald-900 ring-1 ring-emerald-500/20 ring-inset dark:bg-emerald-500/5 dark:text-emerald-200 dark:ring-emerald-500/30",
526
- children: [/* @__PURE__ */ jsx(CheckIcon$1, { className: "h-5 w-5 flex-none fill-emerald-500 stroke-white dark:fill-emerald-200/20 dark:stroke-emerald-200" }), "Thanks for your feedback!"]
752
+ className: "flex items-center gap-3 rounded-full bg-(--clarify-ui-accent-background) py-1 pr-3 pl-1.5 text-sm text-(--clarify-ui-accent-text) ring-1 ring-(--clarify-ui-accent-border) ring-inset",
753
+ children: [/* @__PURE__ */ jsx(CheckIcon$1, { className: "h-5 w-5 flex-none fill-(--clarify-ui-accent-text) stroke-white dark:fill-(--clarify-ui-accent-background) dark:stroke-(--clarify-ui-accent-text)" }), t("feedback.thanks")]
527
754
  })
528
755
  });
529
756
  });
@@ -595,7 +822,7 @@ function HeroPattern() {
595
822
  children: /* @__PURE__ */ jsxs("div", {
596
823
  className: "absolute top-0 left-1/2 -ml-152 h-100 w-325 dark:mask-[linear-gradient(white,transparent)]",
597
824
  children: [/* @__PURE__ */ jsx("div", {
598
- className: "absolute inset-0 bg-linear-to-r from-[#36b49f] to-[#DBFF75] opacity-40 mask-[radial-gradient(farthest-side_at_top,white,transparent)] dark:from-[#36b49f]/30 dark:to-[#DBFF75]/30 dark:opacity-100",
825
+ className: "absolute inset-0 bg-[linear-gradient(to_right,var(--clarify-theme-tokens-colors-primary),var(--clarify-theme-tokens-colors-accent))] opacity-35 mask-[radial-gradient(farthest-side_at_top,white,transparent)] dark:opacity-55",
599
826
  children: /* @__PURE__ */ jsx(GridPattern, {
600
827
  width: 72,
601
828
  height: 56,
@@ -619,18 +846,6 @@ function HeroPattern() {
619
846
  });
620
847
  }
621
848
  //#endregion
622
- //#region source/context.tsx
623
- var ClarifyConfigContext = createContext(null);
624
- var OpenApisContext = createContext({});
625
- function useClarifyConfig() {
626
- const config = useContext(ClarifyConfigContext);
627
- if (!config) throw new Error("[clarify] useClarifyConfig must be used within a ClarifyConfigContext.Provider");
628
- return config;
629
- }
630
- function useOpenApis() {
631
- return useContext(OpenApisContext);
632
- }
633
- //#endregion
634
849
  //#region source/components/PageFooter.tsx
635
850
  function resolveLocalizedText$1(text, locale, fallbackLocale) {
636
851
  if (typeof text === "string") return text;
@@ -658,7 +873,7 @@ function FooterLink(arg0) {
658
873
  href: external ? link.href : localizeHref$1(link.href, config, locale),
659
874
  target: external ? "_blank" : void 0,
660
875
  rel: external ? "noreferrer" : void 0,
661
- className: "clarify-footer-link text-sm text-zinc-500 no-underline transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white",
876
+ className: "clarify-footer-link no-underline transition",
662
877
  children: resolveLocalizedText$1(link.label, locale, config.i18n?.defaultLocale)
663
878
  });
664
879
  }
@@ -668,7 +883,7 @@ function SocialLink(arg0) {
668
883
  href,
669
884
  target: "_blank",
670
885
  rel: "noreferrer",
671
- className: "clarify-footer-social text-sm capitalize text-zinc-500 no-underline transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white",
886
+ className: "clarify-footer-social capitalize no-underline transition",
672
887
  children: name
673
888
  });
674
889
  }
@@ -681,11 +896,11 @@ function PageFooter() {
681
896
  const copyright = footer?.copyright ? resolveLocalizedText$1(footer.copyright, locale, config.i18n?.defaultLocale) : void 0;
682
897
  const hasCustomFooter = Boolean(copyright || links.length > 0 || socials.length > 0);
683
898
  return /* @__PURE__ */ jsxs("footer", {
684
- className: clsx("clarify-page-footer mx-auto mt-16 flex w-full max-w-3xl flex-col items-end gap-4 border-t border-zinc-900/10 pt-8 xl:max-w-[56rem] 2xl:max-w-[64rem] dark:border-white/10", hasCustomFooter && "sm:flex-row sm:items-center sm:justify-between"),
899
+ className: clsx("clarify-page-footer mx-auto mt-16 flex w-full max-w-(--clarify-theme-layout-max-width) flex-col items-end gap-4 border-t border-(--clarify-theme-tokens-colors-border) px-4 py-8 sm:px-6 lg:mt-24 lg:px-5 dark:border-white/10", hasCustomFooter && "sm:flex-row sm:items-center sm:justify-between"),
685
900
  children: [hasCustomFooter ? /* @__PURE__ */ jsxs("div", {
686
901
  className: "clarify-footer-content flex flex-col gap-3 text-right sm:text-left",
687
902
  children: [copyright ? /* @__PURE__ */ jsx("p", {
688
- className: "clarify-footer-copyright m-0 text-sm text-zinc-500 dark:text-zinc-400",
903
+ className: "clarify-footer-copyright m-0",
689
904
  children: copyright
690
905
  }) : null, links.length > 0 || socials.length > 0 ? /* @__PURE__ */ jsxs("div", {
691
906
  className: "clarify-footer-links flex flex-wrap justify-end gap-x-4 gap-y-2 sm:justify-start",
@@ -705,6 +920,95 @@ function PageFooter() {
705
920
  });
706
921
  }
707
922
  //#endregion
923
+ //#region source/utils/path.ts
924
+ function normalizeRoutePath(path) {
925
+ const [pathname, suffix = ""] = path.split(/([?#].*)/, 2);
926
+ return `${pathname.replace(/^\/+/, "/").replace(/\/+$/, "") || "/"}${suffix}`;
927
+ }
928
+ function isSameRoutePath(a, b) {
929
+ if (!a || !b) return false;
930
+ return normalizeRoutePath(a) === normalizeRoutePath(b);
931
+ }
932
+ //#endregion
933
+ //#region source/components/PageNavigation.tsx
934
+ function flattenNavigation(nodes) {
935
+ return nodes.flatMap((node) => node.children?.length ? flattenNavigation(node.children) : [node]);
936
+ }
937
+ function PageNavigation(arg0) {
938
+ const { navigation, currentRoute } = arg0;
939
+ const t = useBuiltInText();
940
+ if (!currentRoute) return null;
941
+ const pageRoutes = flattenNavigation(navigation);
942
+ const currentIndex = pageRoutes.findIndex((route) => isSameRoutePath(route.path, currentRoute.path));
943
+ if (currentIndex === -1) return null;
944
+ const previous = pageRoutes[currentIndex - 1];
945
+ const next = pageRoutes[currentIndex + 1];
946
+ if (!previous && !next) return null;
947
+ return /* @__PURE__ */ jsxs("nav", {
948
+ className: "clarify-page-navigation mt-6 grid gap-3 @3xl:grid-cols-2",
949
+ "aria-label": t("navigation.previousNext"),
950
+ children: [/* @__PURE__ */ jsx(PageNavigationLink, {
951
+ direction: "previous",
952
+ route: previous
953
+ }), /* @__PURE__ */ jsx(PageNavigationLink, {
954
+ direction: "next",
955
+ route: next
956
+ })]
957
+ });
958
+ }
959
+ function PageNavigationLink(arg0) {
960
+ const { direction, route } = arg0;
961
+ const t = useBuiltInText();
962
+ if (!route) return /* @__PURE__ */ jsx("div", { className: "hidden @3xl:block" });
963
+ const isNext = direction === "next";
964
+ return /* @__PURE__ */ jsxs(Link, {
965
+ to: normalizeRoutePath(route.path),
966
+ className: clsx("group flex min-w-0 items-center gap-3 rounded-lg border border-(--clarify-theme-tokens-colors-border) px-4 py-3 no-underline transition hover:border-(--clarify-theme-tokens-colors-primary) hover:bg-(--clarify-theme-tokens-colors-surface) dark:border-white/10 dark:hover:border-(--clarify-theme-tokens-colors-primary) dark:hover:bg-white/2.5", isNext && "@3xl:justify-end @3xl:text-right"),
967
+ children: [
968
+ !isNext ? /* @__PURE__ */ jsx(ChevronLeft, { className: "h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-muted) transition group-hover:text-(--clarify-theme-tokens-colors-primary)" }) : null,
969
+ /* @__PURE__ */ jsxs("span", {
970
+ className: "min-w-0 flex-1",
971
+ children: [/* @__PURE__ */ jsx("span", {
972
+ className: "block text-[0.6875rem] font-medium uppercase tracking-wide text-(--clarify-theme-tokens-colors-muted)",
973
+ children: isNext ? t("navigation.next") : t("navigation.previous")
974
+ }), /* @__PURE__ */ jsx("span", {
975
+ className: "mt-0.5 block truncate text-[0.8125rem] font-semibold text-(--clarify-theme-tokens-colors-foreground) dark:text-white",
976
+ children: route.title
977
+ })]
978
+ }),
979
+ isNext ? /* @__PURE__ */ jsx(ChevronRight, { className: "h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-muted) transition group-hover:text-(--clarify-theme-tokens-colors-primary)" }) : null
980
+ ]
981
+ });
982
+ }
983
+ //#endregion
984
+ //#region source/components/SiteLogo.tsx
985
+ function SiteLogo(arg0) {
986
+ const { logo, className } = arg0;
987
+ if (!logo) return null;
988
+ if (typeof logo === "string") return /* @__PURE__ */ jsx("img", {
989
+ src: logo,
990
+ alt: "",
991
+ className: clsx("clarify-logo", className)
992
+ });
993
+ const lightLogo = logo.light ?? logo.dark;
994
+ const darkLogo = logo.dark ?? logo.light;
995
+ if (!lightLogo || !darkLogo) return null;
996
+ if (lightLogo === darkLogo) return /* @__PURE__ */ jsx("img", {
997
+ src: lightLogo,
998
+ alt: "",
999
+ className: clsx("clarify-logo", className)
1000
+ });
1001
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("img", {
1002
+ src: lightLogo,
1003
+ alt: "",
1004
+ className: clsx("clarify-logo clarify-logo-light", className, "dark:hidden")
1005
+ }), /* @__PURE__ */ jsx("img", {
1006
+ src: darkLogo,
1007
+ alt: "",
1008
+ className: clsx("clarify-logo clarify-logo-dark", className, "hidden dark:block")
1009
+ })] });
1010
+ }
1011
+ //#endregion
708
1012
  //#region source/components/ThemeProvider.tsx
709
1013
  var ThemeContext = createContext(null);
710
1014
  var storageKey = "clarify:theme";
@@ -783,15 +1087,16 @@ function MoonIcon(props) {
783
1087
  }
784
1088
  function ThemeToggle() {
785
1089
  const { resolvedTheme, setTheme } = useTheme();
1090
+ const t = useBuiltInText();
786
1091
  const otherTheme = resolvedTheme === "dark" ? "light" : "dark";
787
1092
  return /* @__PURE__ */ jsxs("button", {
788
1093
  type: "button",
789
- className: "clarify-theme-toggle flex size-6 items-center justify-center rounded-md transition hover:bg-zinc-900/5 dark:hover:bg-white/5",
790
- "aria-label": `Switch to ${otherTheme} theme`,
1094
+ className: "clarify-theme-toggle relative flex size-8 items-center justify-center rounded-(--clarify-theme-tokens-radius-md) transition hover:bg-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-foreground)_5%,transparent)] dark:hover:bg-white/5",
1095
+ "aria-label": otherTheme === "dark" ? t("theme.switchToDark") : t("theme.switchToLight"),
791
1096
  onClick: () => setTheme(otherTheme),
792
1097
  children: [
793
1098
  /* @__PURE__ */ jsx("span", { className: "absolute size-12 pointer-fine:hidden" }),
794
- /* @__PURE__ */ jsx(SunIcon, { className: "h-5 w-5 stroke-zinc-900 dark:hidden" }),
1099
+ /* @__PURE__ */ jsx(SunIcon, { className: "h-5 w-5 stroke-(--clarify-theme-tokens-colors-foreground) dark:hidden" }),
795
1100
  /* @__PURE__ */ jsx(MoonIcon, { className: "hidden h-5 w-5 stroke-white dark:block" })
796
1101
  ]
797
1102
  });
@@ -813,11 +1118,11 @@ function ArrowIcon(props) {
813
1118
  });
814
1119
  }
815
1120
  var buttonVariantStyles = {
816
- primary: "rounded-full bg-zinc-900 px-3 py-1 text-white hover:bg-zinc-700 dark:bg-emerald-400/10 dark:text-emerald-400 dark:ring-1 dark:ring-inset dark:ring-emerald-400/20 dark:hover:text-emerald-300 dark:hover:ring-emerald-300",
817
- secondary: "rounded-full bg-zinc-100 px-3 py-1 text-zinc-900 hover:bg-zinc-200 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",
818
- filled: "rounded-full bg-zinc-900 px-3 py-1 text-white hover:bg-zinc-700 dark:bg-emerald-500 dark:hover:bg-emerald-400",
819
- outline: "rounded-full px-3 py-1 text-zinc-700 ring-1 ring-inset ring-zinc-900/10 hover:bg-zinc-900/2.5 hover:text-zinc-900 dark:text-zinc-400 dark:ring-white/10 dark:hover:bg-white/5 dark:hover:text-white",
820
- text: "text-emerald-500 hover:text-emerald-600 dark:text-emerald-400 dark:hover:text-emerald-500"
1121
+ primary: "rounded-full bg-(--clarify-theme-tokens-colors-foreground) px-3 py-1 text-white hover:opacity-80 dark:bg-(--clarify-theme-tokens-colors-primary)/10 dark:text-(--clarify-theme-tokens-colors-primary) dark:ring-1 dark:ring-inset dark:ring-(--clarify-theme-tokens-colors-primary)/20 dark:hover:opacity-80",
1122
+ secondary: "rounded-full bg-(--clarify-theme-tokens-colors-code-background) px-3 py-1 text-(--clarify-theme-tokens-colors-foreground) hover:opacity-80 dark:bg-zinc-800/40 dark:text-zinc-400 dark:ring-1 dark:ring-inset dark:ring-zinc-800 dark:hover:bg-zinc-800 dark:hover:text-zinc-300",
1123
+ filled: "rounded-full bg-(--clarify-theme-tokens-colors-foreground) px-3 py-1 text-white hover:opacity-80 dark:bg-(--clarify-theme-tokens-colors-primary) dark:hover:opacity-80",
1124
+ outline: "rounded-full px-3 py-1 text-(--clarify-theme-tokens-colors-muted) ring-1 ring-inset ring-(--clarify-theme-tokens-colors-border) hover:bg-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-foreground)_2.5%,transparent)] hover:text-(--clarify-theme-tokens-colors-foreground) dark:text-zinc-400 dark:ring-white/10 dark:hover:bg-white/5 dark:hover:text-white",
1125
+ text: "text-(--clarify-theme-tokens-colors-primary) hover:opacity-80 dark:text-(--clarify-theme-tokens-colors-primary) dark:hover:opacity-80"
821
1126
  };
822
1127
  function Button(arg0) {
823
1128
  const { variant = "primary", className, children, arrow, ...props } = arg0;
@@ -861,8 +1166,8 @@ var tagColorStyles = {
861
1166
  medium: "bg-rose-50 text-red-500 ring-rose-200 dark:bg-rose-400/10 dark:text-rose-400 dark:ring-rose-500/20"
862
1167
  },
863
1168
  zinc: {
864
- small: "text-zinc-400 dark:text-zinc-500",
865
- medium: "bg-zinc-50 text-zinc-500 ring-zinc-200 dark:bg-zinc-400/10 dark:text-zinc-400 dark:ring-zinc-500/20"
1169
+ small: "text-(--clarify-theme-tokens-colors-muted) dark:text-zinc-500",
1170
+ medium: "bg-(--clarify-theme-tokens-colors-code-background) text-(--clarify-theme-tokens-colors-muted) ring-(--clarify-theme-tokens-colors-border) dark:bg-zinc-400/10 dark:text-zinc-400 dark:ring-zinc-500/20"
866
1171
  }
867
1172
  };
868
1173
  var tagValueColorMap = {
@@ -877,7 +1182,7 @@ function Tag(arg0) {
877
1182
  const value = typeof children === "string" ? children.toUpperCase() : "";
878
1183
  const resolvedColor = color ?? tagValueColorMap[value] ?? "emerald";
879
1184
  return /* @__PURE__ */ jsx("span", {
880
- className: clsx("clarify-tag font-mono text-[0.625rem]/6 font-semibold", tagVariantStyles[variant], tagColorStyles[resolvedColor][variant]),
1185
+ className: clsx("clarify-tag font-mono text-[0.625rem]/6 font-bold", tagVariantStyles[variant], tagColorStyles[resolvedColor][variant]),
881
1186
  children
882
1187
  });
883
1188
  }
@@ -888,10 +1193,10 @@ function Logo(props) {
888
1193
  ...props,
889
1194
  className: clsx("clarify-logo", props.className),
890
1195
  children: [/* @__PURE__ */ jsx("path", {
891
- className: "fill-emerald-400",
1196
+ className: "fill-(--clarify-theme-tokens-colors-primary)",
892
1197
  d: "M16 8a5 5 0 0 0-5-5H5a5 5 0 0 0-5 5v13.927a1 1 0 0 0 1.623.782l3.684-2.93a4 4 0 0 1 2.49-.87H11a5 5 0 0 0 5-5V8Z"
893
1198
  }), /* @__PURE__ */ jsx("path", {
894
- className: "fill-zinc-900 dark:fill-white",
1199
+ className: "fill-(--clarify-theme-tokens-colors-foreground) dark:fill-white",
895
1200
  d: "M26.538 18h2.654v-3.999h2.576c2.672 0 4.456-1.723 4.456-4.333V9.65c0-2.61-1.784-4.333-4.456-4.333h-5.23V18Zm4.58-10.582c1.52 0 2.416.8 2.416 2.241v.018c0 1.441-.896 2.25-2.417 2.25h-1.925V7.418h1.925ZM38.051 18h2.566v-5.414c0-1.371.923-2.206 2.382-2.206.396 0 .791.061 1.178.15V8.287a3.843 3.843 0 0 0-.958-.123c-1.257 0-2.136.615-2.443 1.661h-.159V8.323h-2.566V18Zm11.55.202c2.979 0 4.772-1.88 4.772-5.036v-.018c0-3.128-1.82-5.036-4.773-5.036-2.953 0-4.772 1.916-4.772 5.036v.018c0 3.146 1.793 5.036 4.772 5.036Zm0-2.013c-1.372 0-2.145-1.116-2.145-3.023v-.018c0-1.89.782-3.023 2.144-3.023 1.354 0 2.145 1.134 2.145 3.023v.018c0 1.907-.782 3.023-2.145 3.023Zm10.52 1.846c.492 0 .967-.053 1.283-.114v-1.907a6.057 6.057 0 0 1-.755.044c-.87 0-1.24-.387-1.24-1.257v-4.544h1.995V8.323H59.41V6.012h-2.592v2.311h-1.495v1.934h1.495v5.133c0 1.88.949 2.645 3.304 2.645Zm7.287.167c2.98 0 4.772-1.88 4.772-5.036v-.018c0-3.128-1.82-5.036-4.772-5.036-2.954 0-4.773 1.916-4.773 5.036v.018c0 3.146 1.793 5.036 4.773 5.036Zm0-2.013c-1.372 0-2.145-1.116-2.145-3.023v-.018c0-1.89.782-3.023 2.145-3.023 1.353 0 2.144 1.134 2.144 3.023v.018c0 1.907-.782 3.023-2.144 3.023Zm10.767 2.013c2.522 0 4.034-1.353 4.297-3.463l.01-.053h-2.374l-.017.036c-.229.966-.853 1.467-1.908 1.467-1.37 0-2.135-1.08-2.135-3.04v-.018c0-1.934.755-3.006 2.135-3.006 1.099 0 1.74.615 1.908 1.556l.008.017h2.391v-.026c-.228-2.162-1.749-3.56-4.315-3.56-3.033 0-4.738 1.837-4.738 5.019v.017c0 3.217 1.714 5.054 4.738 5.054Zm10.257 0c2.98 0 4.772-1.88 4.772-5.036v-.018c0-3.128-1.82-5.036-4.772-5.036-2.953 0-4.773 1.916-4.773 5.036v.018c0 3.146 1.793 5.036 4.773 5.036Zm0-2.013c-1.371 0-2.145-1.116-2.145-3.023v-.018c0-1.89.782-3.023 2.145-3.023 1.353 0 2.144 1.134 2.144 3.023v.018c0 1.907-.782 3.023-2.144 3.023ZM95.025 18h2.566V4.623h-2.566V18Z"
896
1201
  })]
897
1202
  });
@@ -899,7 +1204,7 @@ function Logo(props) {
899
1204
  function Prose(arg0) {
900
1205
  const { as, className, ...props } = arg0;
901
1206
  return /* @__PURE__ */ jsx(as ?? "div", {
902
- className: clsx(className, "clarify-prose prose dark:prose-invert", "[html_:where(&>*)]:mx-auto [html_:where(&>*)]:w-full [html_:where(&>*)]:max-w-3xl xl:[html_:where(&>*)]:max-w-[56rem] 2xl:[html_:where(&>*)]:max-w-[64rem] [html_:where(&>.not-prose)]:max-w-5xl 2xl:[html_:where(&>.not-prose)]:max-w-[76rem]"),
1207
+ className: clsx(className, "clarify-prose prose max-w-none dark:prose-invert", "[html_:where(&>*)]:w-full [html_:where(&>*)]:min-w-0 [html_:where(&>*)]:max-w-full"),
903
1208
  ...props
904
1209
  });
905
1210
  }
@@ -943,7 +1248,7 @@ function Anchor(arg0) {
943
1248
  });
944
1249
  }
945
1250
  function Heading(arg0) {
946
- const { children, tag, label, level, anchor = true, ...props } = arg0;
1251
+ const { children, className, tag, label, level, anchor = true, ...props } = arg0;
947
1252
  const resolvedLevel = level ?? 2;
948
1253
  const Component = `h${resolvedLevel}`;
949
1254
  const ref = useRef(null);
@@ -970,7 +1275,7 @@ function Heading(arg0) {
970
1275
  label
971
1276
  }), /* @__PURE__ */ jsx(Component, {
972
1277
  ref,
973
- className: clsx("clarify-heading", tag || label ? "mt-2 scroll-mt-32" : "scroll-mt-24"),
1278
+ className: clsx("clarify-heading", tag || label ? "mt-2 scroll-mt-32" : "scroll-mt-24", className),
974
1279
  ...props,
975
1280
  children: anchor ? /* @__PURE__ */ jsx(Anchor, {
976
1281
  id: props.id,
@@ -1016,7 +1321,158 @@ function ApiEndpointCard(arg0) {
1016
1321
  });
1017
1322
  }
1018
1323
  //#endregion
1019
- //#region source/shell/Navigation.tsx
1324
+ //#region source/shell/ContentActions.tsx
1325
+ function resolveContentArtifactUrl(contentArtifactUrl, routePrefix = "/") {
1326
+ if (!routePrefix || routePrefix === "/") return contentArtifactUrl;
1327
+ return `/${routePrefix.replace(/^\/+|\/+$/g, "")}${contentArtifactUrl}`;
1328
+ }
1329
+ function getAbsoluteUrl(path) {
1330
+ if (typeof window === "undefined") return path;
1331
+ return new URL(path, window.location.href).href;
1332
+ }
1333
+ async function copyText(text) {
1334
+ await navigator.clipboard.writeText(text);
1335
+ }
1336
+ function ContentActions(arg0) {
1337
+ const { hasTabs = false, route, routePrefix } = arg0;
1338
+ const t = useBuiltInText();
1339
+ const [copied, setCopied] = useState("idle");
1340
+ if (!route?.contentArtifactUrl) return null;
1341
+ const contentArtifactUrl = resolveContentArtifactUrl(route.contentArtifactUrl, routePrefix);
1342
+ const isOpenApi = route.kind === "openapi";
1343
+ const replacements = { contentType: isOpenApi ? "OpenAPI" : "Markdown" };
1344
+ const viewLabel = isOpenApi ? t("contentActions.viewOpenApi") : t("contentActions.viewMarkdown");
1345
+ const viewDescription = isOpenApi ? t("contentActions.viewOpenApiDescription") : t("contentActions.viewMarkdownDescription");
1346
+ function markCopied(state) {
1347
+ setCopied(state);
1348
+ window.setTimeout(() => setCopied("idle"), 1600);
1349
+ }
1350
+ async function handleCopyContent() {
1351
+ await copyText(await (await fetch(contentArtifactUrl)).text());
1352
+ markCopied("content");
1353
+ }
1354
+ async function handleCopyLink() {
1355
+ await copyText(getAbsoluteUrl(contentArtifactUrl));
1356
+ markCopied("link");
1357
+ }
1358
+ const actions = [{
1359
+ key: "content",
1360
+ label: t("contentActions.copyContent"),
1361
+ description: t("contentActions.copyContentDescription", replacements),
1362
+ icon: Copy,
1363
+ run: handleCopyContent
1364
+ }, {
1365
+ key: "link",
1366
+ label: t("contentActions.copyLink", replacements),
1367
+ description: t("contentActions.copyLinkDescription", replacements),
1368
+ icon: Link2,
1369
+ run: handleCopyLink
1370
+ }];
1371
+ const primaryAction = actions[0];
1372
+ const PrimaryIcon = copied === primaryAction.key ? Check : primaryAction.icon;
1373
+ return /* @__PURE__ */ jsx("div", {
1374
+ className: `clarify-content-actions sticky z-20 flex justify-end py-4 ${hasTabs ? "top-16 lg:top-30" : "top-16"}`,
1375
+ children: /* @__PURE__ */ jsxs(Menu, {
1376
+ as: "div",
1377
+ className: "clarify-content-actions-menu relative inline-flex text-sm font-medium",
1378
+ children: [/* @__PURE__ */ jsxs("div", {
1379
+ className: "clarify-content-actions-group inline-flex overflow-hidden rounded-full border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface)/90 shadow-sm shadow-zinc-900/5 backdrop-blur dark:border-white/10 dark:bg-zinc-900/80 dark:shadow-none",
1380
+ children: [/* @__PURE__ */ jsxs("button", {
1381
+ type: "button",
1382
+ onClick: primaryAction.run,
1383
+ className: "clarify-content-actions-primary clarify-ui-control inline-flex h-8 items-center gap-1.5 px-3 transition",
1384
+ children: [/* @__PURE__ */ jsx(PrimaryIcon, { className: "h-3.5 w-3.5" }), copied === primaryAction.key ? t("actions.copied") : primaryAction.label]
1385
+ }), /* @__PURE__ */ jsx(MenuButton, {
1386
+ className: "clarify-content-actions-trigger clarify-ui-control inline-flex h-8 w-8 items-center justify-center border-l border-(--clarify-theme-tokens-colors-border) transition dark:border-white/10",
1387
+ "aria-label": t("contentActions.copyOptions"),
1388
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5" })
1389
+ })]
1390
+ }), /* @__PURE__ */ jsxs(MenuItems, {
1391
+ anchor: "bottom end",
1392
+ className: "clarify-content-actions-list clarify-ui-menu z-30 mt-2 w-(--clarify-ui-action-menu-width) origin-top-right rounded-(--clarify-theme-tokens-radius-xl) border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface) p-1.5 shadow-xl shadow-zinc-900/5 transition [--anchor-gap:--spacing(2)] focus:outline-none data-closed:scale-95 data-closed:opacity-0 dark:border-white/10 dark:bg-zinc-900 dark:shadow-none",
1393
+ children: [
1394
+ actions.slice(0, 1).map((action) => {
1395
+ const Icon = action.icon;
1396
+ const isCopied = copied === action.key;
1397
+ return /* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsxs("button", {
1398
+ type: "button",
1399
+ onClick: action.run,
1400
+ className: "clarify-content-actions-item clarify-ui-menu-item group flex w-full items-center gap-2 rounded-(--clarify-theme-tokens-radius-lg) px-1.5 py-1.5 text-left transition",
1401
+ children: [
1402
+ /* @__PURE__ */ jsx("span", {
1403
+ className: "clarify-ui-menu-icon flex shrink-0 rounded-(--clarify-theme-tokens-radius-md) border border-(--clarify-theme-tokens-colors-border) p-1.5 dark:border-white/10",
1404
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" })
1405
+ }),
1406
+ /* @__PURE__ */ jsxs("span", {
1407
+ className: "flex min-w-0 flex-1 flex-col px-1",
1408
+ children: [/* @__PURE__ */ jsx("span", {
1409
+ className: "clarify-ui-menu-title",
1410
+ children: isCopied ? t("contentActions.copiedContent") : action.label
1411
+ }), /* @__PURE__ */ jsx("span", {
1412
+ className: "clarify-ui-menu-description truncate",
1413
+ children: action.description
1414
+ })]
1415
+ }),
1416
+ /* @__PURE__ */ jsx(Check, { className: `h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) transition ${isCopied ? "opacity-100" : "opacity-0"}` })
1417
+ ]
1418
+ }) }, action.key);
1419
+ }),
1420
+ /* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsxs("a", {
1421
+ href: contentArtifactUrl,
1422
+ target: "_blank",
1423
+ rel: "noreferrer",
1424
+ className: "clarify-content-actions-item clarify-ui-menu-item group flex w-full items-center gap-2 rounded-(--clarify-theme-tokens-radius-lg) px-1.5 py-1.5 text-left no-underline transition",
1425
+ children: [
1426
+ /* @__PURE__ */ jsx("span", {
1427
+ className: "clarify-ui-menu-icon flex shrink-0 rounded-(--clarify-theme-tokens-radius-md) border border-(--clarify-theme-tokens-colors-border) p-1.5 dark:border-white/10",
1428
+ children: /* @__PURE__ */ jsx(FileText, { className: "h-4 w-4" })
1429
+ }),
1430
+ /* @__PURE__ */ jsxs("span", {
1431
+ className: "flex min-w-0 flex-1 flex-col px-1",
1432
+ children: [/* @__PURE__ */ jsxs("span", {
1433
+ className: "clarify-ui-menu-title flex items-center gap-1",
1434
+ children: [viewLabel, /* @__PURE__ */ jsx(ExternalLink, { className: "clarify-ui-menu-icon h-3 w-3" })]
1435
+ }), /* @__PURE__ */ jsx("span", {
1436
+ className: "clarify-ui-menu-description truncate",
1437
+ children: viewDescription
1438
+ })]
1439
+ }),
1440
+ /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) opacity-0" })
1441
+ ]
1442
+ }) }),
1443
+ actions.slice(1).map((action) => {
1444
+ const Icon = action.icon;
1445
+ const isCopied = copied === action.key;
1446
+ return /* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsxs("button", {
1447
+ type: "button",
1448
+ onClick: action.run,
1449
+ className: "clarify-content-actions-item clarify-ui-menu-item group flex w-full items-center gap-2 rounded-(--clarify-theme-tokens-radius-lg) px-1.5 py-1.5 text-left transition",
1450
+ children: [
1451
+ /* @__PURE__ */ jsx("span", {
1452
+ className: "clarify-ui-menu-icon flex shrink-0 rounded-(--clarify-theme-tokens-radius-md) border border-(--clarify-theme-tokens-colors-border) p-1.5 dark:border-white/10",
1453
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" })
1454
+ }),
1455
+ /* @__PURE__ */ jsxs("span", {
1456
+ className: "flex min-w-0 flex-1 flex-col px-1",
1457
+ children: [/* @__PURE__ */ jsx("span", {
1458
+ className: "clarify-ui-menu-title",
1459
+ children: isCopied ? t("contentActions.copiedLink") : action.label
1460
+ }), /* @__PURE__ */ jsx("span", {
1461
+ className: "clarify-ui-menu-description truncate",
1462
+ children: action.description
1463
+ })]
1464
+ }),
1465
+ /* @__PURE__ */ jsx(Check, { className: `h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) transition ${isCopied ? "opacity-100" : "opacity-0"}` })
1466
+ ]
1467
+ }) }, action.key);
1468
+ })
1469
+ ]
1470
+ })]
1471
+ })
1472
+ });
1473
+ }
1474
+ //#endregion
1475
+ //#region source/shell/icons.tsx
1020
1476
  function NavigationIcon(arg0) {
1021
1477
  const { name, className } = arg0;
1022
1478
  if (!name) return null;
@@ -1027,6 +1483,8 @@ function NavigationIcon(arg0) {
1027
1483
  "aria-hidden": "true"
1028
1484
  });
1029
1485
  }
1486
+ //#endregion
1487
+ //#region source/shell/Navigation.tsx
1030
1488
  function useInitialValue(value, condition = true) {
1031
1489
  const [initialValue] = useState(value);
1032
1490
  return condition ? initialValue : value;
@@ -1034,11 +1492,11 @@ function useInitialValue(value, condition = true) {
1034
1492
  function normalizePath(path) {
1035
1493
  return path === "" ? "/" : path;
1036
1494
  }
1037
- function navigationToGroups(navigation) {
1495
+ function navigationToGroups(navigation, defaultTitle) {
1038
1496
  return navigation.map((node) => {
1039
1497
  const children = node.children?.length ? node.children : [node];
1040
1498
  return {
1041
- title: node.children?.length ? node.title : "Documentation",
1499
+ title: node.children?.length ? node.title : defaultTitle,
1042
1500
  icon: node.icon,
1043
1501
  links: children.map((child) => ({
1044
1502
  title: child.title,
@@ -1048,18 +1506,6 @@ function navigationToGroups(navigation) {
1048
1506
  };
1049
1507
  });
1050
1508
  }
1051
- function TopLevelNavItem$1(arg0) {
1052
- const { href, children } = arg0;
1053
- return /* @__PURE__ */ jsx("li", {
1054
- className: "md:hidden",
1055
- children: /* @__PURE__ */ jsx(CloseButton, {
1056
- as: Link,
1057
- to: href,
1058
- className: "block py-1 text-sm text-zinc-600 transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white",
1059
- children
1060
- })
1061
- });
1062
- }
1063
1509
  var sectionBadgeColorStyles = {
1064
1510
  GET: "text-emerald-500 dark:text-emerald-400",
1065
1511
  POST: "text-sky-500 dark:text-sky-400",
@@ -1073,7 +1519,7 @@ var sectionBadgeColorStyles = {
1073
1519
  function SectionBadge(arg0) {
1074
1520
  const { children } = arg0;
1075
1521
  return /* @__PURE__ */ jsx("span", {
1076
- className: clsx("inline-flex shrink-0 justify-end font-mono text-[0.625rem]/6 font-semibold uppercase tracking-wide", sectionBadgeColorStyles[children.toUpperCase()] ?? "text-zinc-500 dark:text-zinc-400"),
1522
+ className: clsx("clarify-navigation-section-badge inline-flex shrink-0 justify-end font-mono font-semibold uppercase tracking-wide", sectionBadgeColorStyles[children.toUpperCase()] ?? "clarify-ui-menu-description"),
1077
1523
  children
1078
1524
  });
1079
1525
  }
@@ -1086,6 +1532,9 @@ function NavLink(arg0) {
1086
1532
  const targetId = decodeURIComponent(href.slice(hashIndex + 1));
1087
1533
  window.requestAnimationFrame(() => {
1088
1534
  document.getElementById(targetId)?.scrollIntoView();
1535
+ window.requestAnimationFrame(() => {
1536
+ window.dispatchEvent(new Event("scroll"));
1537
+ });
1089
1538
  });
1090
1539
  }
1091
1540
  return /* @__PURE__ */ jsxs(CloseButton, {
@@ -1093,7 +1542,7 @@ function NavLink(arg0) {
1093
1542
  to: href,
1094
1543
  "aria-current": active ? "page" : void 0,
1095
1544
  onClick: handleClick,
1096
- className: clsx("clarify-navigation-link flex justify-between gap-2 py-1 pr-3 text-sm transition", isAnchorLink ? "clarify-navigation-anchor-link pl-7" : "pl-4", active ? "text-zinc-900 dark:text-white" : "text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white"),
1545
+ className: clsx("clarify-navigation-link flex h-8 items-center justify-between gap-2 pr-3 transition", isAnchorLink ? "clarify-navigation-anchor-link pl-7" : "pl-4"),
1097
1546
  children: [/* @__PURE__ */ jsxs("span", {
1098
1547
  className: "flex min-w-0 flex-1 items-center gap-2",
1099
1548
  children: [
@@ -1124,7 +1573,7 @@ function VisibleSectionHighlight(arg0) {
1124
1573
  const firstVisibleSectionIndex = Math.max(0, [{ id: "_top" }, ...sections].findIndex((section) => section.id === visibleSections[0]));
1125
1574
  const itemHeight = remToPx(2);
1126
1575
  const height = isPresent ? Math.max(1, visibleSections.length) * itemHeight : itemHeight;
1127
- const top = group.links.findIndex((link) => link.href === pathname) * itemHeight + firstVisibleSectionIndex * itemHeight;
1576
+ const top = group.links.findIndex((link) => isSameRoutePath(link.href, pathname)) * itemHeight + firstVisibleSectionIndex * itemHeight;
1128
1577
  return /* @__PURE__ */ jsx(motion.div, {
1129
1578
  layout: true,
1130
1579
  initial: { opacity: 0 },
@@ -1133,9 +1582,9 @@ function VisibleSectionHighlight(arg0) {
1133
1582
  transition: { delay: .2 }
1134
1583
  },
1135
1584
  exit: { opacity: 0 },
1136
- className: "absolute inset-x-0 top-0 bg-zinc-800/2.5 will-change-transform dark:bg-white/2.5",
1585
+ className: "clarify-navigation-section-highlight absolute inset-x-0 top-0 will-change-transform",
1137
1586
  style: {
1138
- borderRadius: 8,
1587
+ borderRadius: "var(--clarify-theme-tokens-radius-sm)",
1139
1588
  height,
1140
1589
  top
1141
1590
  }
@@ -1144,10 +1593,10 @@ function VisibleSectionHighlight(arg0) {
1144
1593
  function ActivePageMarker(arg0) {
1145
1594
  const { group, pathname } = arg0;
1146
1595
  const itemHeight = remToPx(2);
1147
- const top = remToPx(.25) + group.links.findIndex((link) => link.href === pathname) * itemHeight;
1596
+ const top = remToPx(.25) + group.links.findIndex((link) => isSameRoutePath(link.href, pathname)) * itemHeight;
1148
1597
  return /* @__PURE__ */ jsx(motion.div, {
1149
1598
  layout: true,
1150
- className: "absolute left-2 h-6 w-px bg-emerald-500",
1599
+ className: "absolute left-2 h-6 w-px bg-(--clarify-theme-tokens-colors-primary)",
1151
1600
  initial: { opacity: 0 },
1152
1601
  animate: {
1153
1602
  opacity: 1,
@@ -1160,16 +1609,16 @@ function ActivePageMarker(arg0) {
1160
1609
  function NavigationGroup(arg0) {
1161
1610
  const { group, className } = arg0;
1162
1611
  const isInsideMobileNavigation = useIsInsideMobileNavigation();
1163
- const [pathname, sections] = useInitialValue([useLocation().pathname, useSectionStore((s) => s.sections)], isInsideMobileNavigation);
1164
- const isActiveGroup = group.links.findIndex((link) => link.href === pathname) !== -1;
1612
+ const [pathname, sections] = useInitialValue([normalizeRoutePath(useLocation().pathname), useSectionStore((s) => s.sections)], isInsideMobileNavigation);
1613
+ const isActiveGroup = group.links.findIndex((link) => isSameRoutePath(link.href, pathname)) !== -1;
1165
1614
  return /* @__PURE__ */ jsxs("li", {
1166
1615
  className: clsx("clarify-navigation-group relative mt-6", className),
1167
1616
  children: [/* @__PURE__ */ jsxs(motion.h2, {
1168
1617
  layout: "position",
1169
- className: "clarify-navigation-group-title flex items-center gap-2 text-xs font-semibold text-zinc-900 dark:text-white",
1618
+ className: "clarify-navigation-group-title flex items-center gap-2",
1170
1619
  children: [/* @__PURE__ */ jsx(NavigationIcon, {
1171
1620
  name: group.icon,
1172
- className: "h-3.5 w-3.5"
1621
+ className: "clarify-navigation-group-title-icon h-3.5 w-3.5"
1173
1622
  }), /* @__PURE__ */ jsx("span", { children: group.title })]
1174
1623
  }), /* @__PURE__ */ jsxs("div", {
1175
1624
  className: "relative mt-3 pl-2",
@@ -1183,7 +1632,7 @@ function NavigationGroup(arg0) {
1183
1632
  }),
1184
1633
  /* @__PURE__ */ jsx(motion.div, {
1185
1634
  layout: true,
1186
- className: "absolute inset-y-0 left-2 w-px bg-zinc-900/10 dark:bg-white/5"
1635
+ className: "absolute inset-y-0 left-2 w-px bg-(--clarify-theme-tokens-colors-border) dark:bg-white/5"
1187
1636
  }),
1188
1637
  /* @__PURE__ */ jsx(AnimatePresence, {
1189
1638
  initial: false,
@@ -1195,38 +1644,41 @@ function NavigationGroup(arg0) {
1195
1644
  /* @__PURE__ */ jsx("ul", {
1196
1645
  role: "list",
1197
1646
  className: "border-l border-transparent",
1198
- children: group.links.map((link) => /* @__PURE__ */ jsxs(motion.li, {
1199
- layout: "position",
1200
- className: "relative",
1201
- children: [/* @__PURE__ */ jsx(NavLink, {
1202
- href: link.href,
1203
- icon: link.icon,
1204
- active: link.href === pathname,
1205
- children: link.title
1206
- }), /* @__PURE__ */ jsx(AnimatePresence, {
1207
- mode: "popLayout",
1208
- initial: false,
1209
- children: link.href === pathname && sections.length > 0 ? /* @__PURE__ */ jsx(motion.ul, {
1210
- role: "list",
1211
- initial: { opacity: 0 },
1212
- animate: {
1213
- opacity: 1,
1214
- transition: { delay: .1 }
1215
- },
1216
- exit: {
1217
- opacity: 0,
1218
- transition: { duration: .15 }
1219
- },
1220
- children: sections.map((section) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(NavLink, {
1221
- href: `${link.href}#${section.id}`,
1222
- badge: section.badge,
1223
- tags: section.tags,
1224
- isAnchorLink: true,
1225
- children: section.title
1226
- }) }, section.id))
1227
- }) : null
1228
- })]
1229
- }, link.href))
1647
+ children: group.links.map((link) => {
1648
+ const active = isSameRoutePath(link.href, pathname);
1649
+ return /* @__PURE__ */ jsxs(motion.li, {
1650
+ layout: "position",
1651
+ className: "relative",
1652
+ children: [/* @__PURE__ */ jsx(NavLink, {
1653
+ href: link.href,
1654
+ icon: link.icon,
1655
+ active,
1656
+ children: link.title
1657
+ }), /* @__PURE__ */ jsx(AnimatePresence, {
1658
+ mode: "popLayout",
1659
+ initial: false,
1660
+ children: active && sections.length > 0 ? /* @__PURE__ */ jsx(motion.ul, {
1661
+ role: "list",
1662
+ initial: { opacity: 0 },
1663
+ animate: {
1664
+ opacity: 1,
1665
+ transition: { delay: .1 }
1666
+ },
1667
+ exit: {
1668
+ opacity: 0,
1669
+ transition: { duration: .15 }
1670
+ },
1671
+ children: sections.map((section) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(NavLink, {
1672
+ href: `${link.href}#${section.id}`,
1673
+ badge: section.badge,
1674
+ tags: section.tags,
1675
+ isAnchorLink: true,
1676
+ children: section.title
1677
+ }) }, section.id))
1678
+ }) : null
1679
+ })]
1680
+ }, link.href);
1681
+ })
1230
1682
  })
1231
1683
  ]
1232
1684
  })]
@@ -1234,19 +1686,16 @@ function NavigationGroup(arg0) {
1234
1686
  }
1235
1687
  function Navigation(arg0) {
1236
1688
  const { navigation, className } = arg0;
1237
- const groups = navigationToGroups(navigation);
1689
+ const groups = navigationToGroups(navigation, useBuiltInText()("navigation.documentation"));
1238
1690
  return /* @__PURE__ */ jsx("nav", {
1239
1691
  className: clsx("clarify-navigation", className),
1240
- children: /* @__PURE__ */ jsxs("ul", {
1692
+ children: /* @__PURE__ */ jsx("ul", {
1241
1693
  role: "list",
1242
1694
  className: "clarify-navigation-list",
1243
- children: [/* @__PURE__ */ jsx(TopLevelNavItem$1, {
1244
- href: "/",
1245
- children: "Home"
1246
- }), groups.map((group, groupIndex) => /* @__PURE__ */ jsx(NavigationGroup, {
1695
+ children: groups.map((group, groupIndex) => /* @__PURE__ */ jsx(NavigationGroup, {
1247
1696
  group,
1248
- className: groupIndex === 0 ? "md:mt-0" : ""
1249
- }, group.title))]
1697
+ className: groupIndex === 0 ? "mt-0" : ""
1698
+ }, group.title))
1250
1699
  })
1251
1700
  });
1252
1701
  }
@@ -1273,8 +1722,84 @@ function XIcon(props) {
1273
1722
  });
1274
1723
  }
1275
1724
  var IsInsideMobileNavigationContext = createContext(false);
1725
+ function hasPath$2(nodes, pathname) {
1726
+ return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath$2(node.children ?? [], pathname));
1727
+ }
1728
+ function isActiveTab$1(tab, pathname) {
1729
+ return isSameRoutePath(tab.path, pathname) || hasPath$2(tab.children, pathname);
1730
+ }
1731
+ function MobileTabsSelect(arg0) {
1732
+ const { tabs } = arg0;
1733
+ const pathname = normalizeRoutePath(useLocation().pathname);
1734
+ const { close } = useMobileNavigationStore();
1735
+ if (!tabs?.length) return null;
1736
+ const activeTab = tabs.find((tab) => isActiveTab$1(tab, pathname)) ?? tabs[0];
1737
+ return /* @__PURE__ */ jsxs(Menu, {
1738
+ as: "div",
1739
+ className: "clarify-mobile-tabs-select mb-6",
1740
+ children: [/* @__PURE__ */ jsxs(MenuButton, {
1741
+ className: "clarify-mobile-tabs-select-trigger clarify-ui-control group flex h-10 w-full items-center justify-between gap-2 rounded-(--clarify-theme-tokens-radius-xl) border border-(--clarify-theme-tokens-colors-border) px-4 text-left font-semibold shadow-xs shadow-zinc-900/5 transition dark:border-white/10",
1742
+ children: [/* @__PURE__ */ jsxs("span", {
1743
+ className: "flex min-w-0 items-center gap-2",
1744
+ children: [/* @__PURE__ */ jsx(NavigationIcon, {
1745
+ name: activeTab.icon,
1746
+ className: "h-4 w-4 shrink-0 text-(--clarify-theme-tokens-colors-primary)"
1747
+ }), /* @__PURE__ */ jsx("span", {
1748
+ className: "truncate tracking-[-0.01em]",
1749
+ children: activeTab.title
1750
+ })]
1751
+ }), /* @__PURE__ */ jsx("svg", {
1752
+ width: "8",
1753
+ height: "24",
1754
+ viewBox: "0 -9 3 24",
1755
+ "aria-hidden": "true",
1756
+ className: "shrink-0 overflow-visible text-(--clarify-theme-tokens-colors-muted) transition-transform group-aria-expanded:rotate-180",
1757
+ children: /* @__PURE__ */ jsx("path", {
1758
+ d: "M0 0L3 3L0 6",
1759
+ fill: "none",
1760
+ stroke: "currentColor",
1761
+ strokeWidth: "1.5",
1762
+ strokeLinecap: "round"
1763
+ })
1764
+ })]
1765
+ }), /* @__PURE__ */ jsx(MenuItems, {
1766
+ className: "clarify-mobile-tabs-select-list clarify-ui-menu mt-2 flex flex-col gap-1 rounded-(--clarify-theme-tokens-radius-xl) border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface) p-1 shadow-lg shadow-zinc-900/5 focus:outline-none dark:border-white/10 dark:bg-zinc-900 dark:shadow-none",
1767
+ children: tabs.map((tab) => {
1768
+ const active = isActiveTab$1(tab, pathname);
1769
+ return /* @__PURE__ */ jsx(MenuItem, { children: /* @__PURE__ */ jsxs(Link, {
1770
+ to: tab.path,
1771
+ onClick: close,
1772
+ className: clsx("clarify-mobile-tabs-select-item clarify-ui-menu-item flex items-center justify-between gap-3 rounded-(--clarify-theme-tokens-radius-lg) px-3 py-2.5 no-underline transition", active && "clarify-ui-menu-item-active"),
1773
+ "aria-current": active ? "page" : void 0,
1774
+ children: [/* @__PURE__ */ jsxs("span", {
1775
+ className: "flex min-w-0 items-start gap-2",
1776
+ children: [/* @__PURE__ */ jsx(NavigationIcon, {
1777
+ name: tab.icon,
1778
+ className: "mt-0.5 h-4 w-4 shrink-0"
1779
+ }), /* @__PURE__ */ jsx("span", {
1780
+ className: "min-w-0 whitespace-normal wrap-anywhere font-medium leading-5",
1781
+ children: tab.title
1782
+ })]
1783
+ }), active ? /* @__PURE__ */ jsx("svg", {
1784
+ viewBox: "0 0 20 20",
1785
+ fill: "none",
1786
+ "aria-hidden": "true",
1787
+ className: "mt-0.5 h-4 w-4 shrink-0",
1788
+ children: /* @__PURE__ */ jsx("path", {
1789
+ d: "m5 10 3 3 7-7",
1790
+ stroke: "currentColor",
1791
+ strokeWidth: "1.8",
1792
+ strokeLinecap: "round",
1793
+ strokeLinejoin: "round"
1794
+ })
1795
+ }) : null]
1796
+ }) }, `${tab.title}-${tab.path}`);
1797
+ })
1798
+ })]
1799
+ });
1800
+ }
1276
1801
  function MobileNavigationDialog(arg0) {
1277
- const { config, isOpen, navigation, routes, currentLocale, currentRoute, close } = arg0;
1802
+ const { config, isOpen, navigation, tabs, routes, currentLocale, currentRoute, close } = arg0;
1278
1803
  return /* @__PURE__ */ jsxs(Dialog, {
1279
1804
  transition: true,
1280
1805
  open: isOpen,
@@ -1282,18 +1807,19 @@ function MobileNavigationDialog(arg0) {
1282
1807
  className: "clarify-mobile-navigation-dialog fixed inset-0 z-50 lg:hidden",
1283
1808
  children: [/* @__PURE__ */ jsx(DialogBackdrop, {
1284
1809
  transition: true,
1285
- className: "clarify-mobile-navigation-backdrop fixed inset-0 top-14 bg-zinc-400/20 backdrop-blur-xs data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in dark:bg-black/40"
1810
+ className: "clarify-mobile-navigation-backdrop clarify-ui-backdrop fixed inset-0 top-14 backdrop-blur-xs data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in"
1286
1811
  }), /* @__PURE__ */ jsxs(DialogPanel, { children: [/* @__PURE__ */ jsx(TransitionChild, { children: /* @__PURE__ */ jsx(Header, {
1287
1812
  config,
1288
1813
  navigation,
1814
+ tabs,
1289
1815
  routes,
1290
1816
  currentLocale,
1291
1817
  currentRoute,
1292
1818
  className: "data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in"
1293
- }) }), /* @__PURE__ */ jsx(TransitionChild, { children: /* @__PURE__ */ jsx(motion.div, {
1819
+ }) }), /* @__PURE__ */ jsx(TransitionChild, { children: /* @__PURE__ */ jsxs(motion.div, {
1294
1820
  layoutScroll: true,
1295
- className: "clarify-mobile-navigation-panel fixed top-14 bottom-0 left-0 w-full overflow-y-auto bg-white px-4 pt-6 pb-4 shadow-lg ring-1 shadow-zinc-900/10 ring-zinc-900/7.5 duration-500 ease-in-out data-closed:-translate-x-full min-[416px]:max-w-sm sm:px-6 sm:pb-10 dark:bg-zinc-950 dark:ring-zinc-800",
1296
- children: /* @__PURE__ */ jsx(Navigation, { navigation })
1821
+ className: "clarify-mobile-navigation-panel fixed top-14 bottom-0 left-0 w-full overflow-y-auto bg-(--clarify-theme-tokens-colors-background) px-4 pt-6 pb-4 shadow-lg ring-1 shadow-zinc-900/10 ring-(--clarify-theme-tokens-colors-border) duration-500 ease-in-out data-closed:-translate-x-full min-[416px]:max-w-sm sm:px-6 sm:pb-10 dark:bg-zinc-950 dark:ring-zinc-800",
1822
+ children: [/* @__PURE__ */ jsx(MobileTabsSelect, { tabs }), /* @__PURE__ */ jsx(Navigation, { navigation })]
1297
1823
  }) })] })]
1298
1824
  });
1299
1825
  }
@@ -1307,23 +1833,25 @@ var useMobileNavigationStore = create()((set) => ({
1307
1833
  toggle: () => set((state) => ({ isOpen: !state.isOpen }))
1308
1834
  }));
1309
1835
  function MobileNavigation(arg0) {
1310
- const { config, navigation, routes, currentLocale, currentRoute } = arg0;
1836
+ const { config, navigation, tabs, routes, currentLocale, currentRoute } = arg0;
1311
1837
  const isInsideMobileNavigation = useIsInsideMobileNavigation();
1312
1838
  const { isOpen, toggle, close } = useMobileNavigationStore();
1839
+ const t = useBuiltInText();
1313
1840
  const ToggleIcon = isOpen ? XIcon : MenuIcon;
1314
1841
  return /* @__PURE__ */ jsxs(IsInsideMobileNavigationContext.Provider, {
1315
1842
  value: true,
1316
1843
  children: [/* @__PURE__ */ jsxs("button", {
1317
1844
  type: "button",
1318
- className: "clarify-mobile-navigation-button relative flex size-6 items-center justify-center rounded-md transition hover:bg-zinc-900/5 dark:hover:bg-white/5",
1319
- "aria-label": "Toggle navigation",
1845
+ className: "clarify-mobile-navigation-button clarify-ui-icon-button relative flex size-6 items-center justify-center rounded-(--clarify-theme-tokens-radius-md) transition",
1846
+ "aria-label": t("navigation.toggle"),
1320
1847
  onClick: toggle,
1321
- children: [/* @__PURE__ */ jsx("span", { className: "absolute size-12 pointer-fine:hidden" }), /* @__PURE__ */ jsx(ToggleIcon, { className: "w-2.5 stroke-zinc-900 dark:stroke-white" })]
1848
+ children: [/* @__PURE__ */ jsx("span", { className: "absolute size-12 pointer-fine:hidden" }), /* @__PURE__ */ jsx(ToggleIcon, { className: "w-2.5 stroke-(--clarify-theme-tokens-colors-foreground) dark:stroke-white" })]
1322
1849
  }), !isInsideMobileNavigation ? /* @__PURE__ */ jsx(Suspense, {
1323
1850
  fallback: null,
1324
1851
  children: /* @__PURE__ */ jsx(MobileNavigationDialog, {
1325
1852
  config,
1326
1853
  navigation,
1854
+ tabs,
1327
1855
  routes,
1328
1856
  currentLocale,
1329
1857
  currentRoute,
@@ -1404,7 +1932,7 @@ function HighlightQuery(arg0) {
1404
1932
  const { text, query } = arg0;
1405
1933
  if (!query) return text;
1406
1934
  return /* @__PURE__ */ jsx(Fragment$1, { children: text.split(new RegExp(`(${escapeRegExp(query)})`, "ig")).map((part, index) => part.toLowerCase() === query.toLowerCase() ? /* @__PURE__ */ jsx("mark", {
1407
- className: "bg-transparent text-emerald-500 underline",
1935
+ className: "bg-transparent text-(--clarify-theme-tokens-colors-primary) underline",
1408
1936
  children: part
1409
1937
  }, index) : /* @__PURE__ */ jsx(Fragment, { children: part }, index)) });
1410
1938
  }
@@ -1414,25 +1942,25 @@ function SearchResult(arg0) {
1414
1942
  const hierarchy = [result.sectionTitle, result.pageTitle].filter((value) => typeof value === "string");
1415
1943
  return /* @__PURE__ */ jsxs("li", {
1416
1944
  id,
1417
- className: clsx("clarify-search-result group block cursor-default px-4 py-3 aria-selected:bg-zinc-50 dark:aria-selected:bg-zinc-800/50", active && "bg-zinc-50 dark:bg-zinc-800/50"),
1945
+ className: clsx("clarify-search-result group block cursor-default px-4 py-3", active && "clarify-search-result-active"),
1418
1946
  "aria-selected": active,
1419
1947
  onMouseDown: (event) => {
1420
1948
  event.preventDefault();
1421
1949
  onSelect();
1422
1950
  },
1423
1951
  children: [/* @__PURE__ */ jsx("div", {
1424
- className: "text-sm font-medium text-zinc-900 group-aria-selected:text-emerald-500 dark:text-white",
1952
+ className: "clarify-search-result-title",
1425
1953
  children: /* @__PURE__ */ jsx(HighlightQuery, {
1426
1954
  text: result.title,
1427
1955
  query
1428
1956
  })
1429
1957
  }), hierarchy.length > 0 ? /* @__PURE__ */ jsx("div", {
1430
- className: "mt-1 truncate text-2xs whitespace-nowrap text-zinc-500",
1958
+ className: "clarify-search-result-hierarchy mt-1 truncate whitespace-nowrap",
1431
1959
  children: hierarchy.map((item, itemIndex, items) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(HighlightQuery, {
1432
1960
  text: item,
1433
1961
  query
1434
1962
  }), /* @__PURE__ */ jsx("span", {
1435
- className: itemIndex === items.length - 1 ? "sr-only" : "mx-2 text-zinc-300 dark:text-zinc-700",
1963
+ className: itemIndex === items.length - 1 ? "sr-only" : "clarify-search-result-separator mx-2",
1436
1964
  children: "/"
1437
1965
  })] }, `${item}-${itemIndex}`))
1438
1966
  }) : null]
@@ -1440,9 +1968,10 @@ function SearchResult(arg0) {
1440
1968
  }
1441
1969
  var SearchInput = forwardRef(function SearchInput(arg0, inputRef) {
1442
1970
  const { query, setQuery, onClose, onSubmit, activeDescendantId } = arg0;
1971
+ const t = useBuiltInText();
1443
1972
  return /* @__PURE__ */ jsxs("div", {
1444
1973
  className: "clarify-search-input group relative flex h-12",
1445
- children: [/* @__PURE__ */ jsx(SearchIcon, { className: "pointer-events-none absolute top-0 left-3 h-full w-5 stroke-zinc-500" }), /* @__PURE__ */ jsx("input", {
1974
+ children: [/* @__PURE__ */ jsx(SearchIcon, { className: "pointer-events-none absolute top-0 left-3 h-full w-5 stroke-(--clarify-theme-tokens-colors-muted)" }), /* @__PURE__ */ jsx("input", {
1446
1975
  ref: inputRef,
1447
1976
  "data-autofocus": true,
1448
1977
  role: "combobox",
@@ -1459,13 +1988,14 @@ var SearchInput = forwardRef(function SearchInput(arg0, inputRef) {
1459
1988
  onSubmit();
1460
1989
  }
1461
1990
  },
1462
- placeholder: "Find something...",
1463
- className: "flex-auto appearance-none bg-transparent pr-4 pl-10 text-zinc-900 outline-hidden placeholder:text-zinc-500 focus:w-full focus:flex-none sm:text-sm dark:text-white [&::-webkit-search-cancel-button]:hidden [&::-webkit-search-decoration]:hidden [&::-webkit-search-results-button]:hidden [&::-webkit-search-results-decoration]:hidden"
1991
+ placeholder: t("search.placeholder"),
1992
+ className: "clarify-search-field flex-auto appearance-none bg-transparent pr-4 pl-10 outline-hidden focus:w-full focus:flex-none [&::-webkit-search-cancel-button]:hidden [&::-webkit-search-decoration]:hidden [&::-webkit-search-results-button]:hidden [&::-webkit-search-results-decoration]:hidden"
1464
1993
  })]
1465
1994
  });
1466
1995
  });
1467
1996
  function SearchDialog(arg0) {
1468
1997
  const { open, setOpen, routes, navigation, className, onNavigate = () => {} } = arg0;
1998
+ const t = useBuiltInText();
1469
1999
  const navigate = useNavigate();
1470
2000
  const location = useLocation();
1471
2001
  const inputRef = useRef(null);
@@ -1516,12 +2046,12 @@ function SearchDialog(arg0) {
1516
2046
  className: clsx("clarify-search-dialog fixed inset-0 z-50", className),
1517
2047
  children: [/* @__PURE__ */ jsx(DialogBackdrop, {
1518
2048
  transition: true,
1519
- className: "clarify-search-backdrop fixed inset-0 bg-zinc-400/25 backdrop-blur-xs data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in dark:bg-black/40"
2049
+ className: "clarify-search-backdrop clarify-ui-backdrop fixed inset-0 backdrop-blur-xs data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in"
1520
2050
  }), /* @__PURE__ */ jsx("div", {
1521
2051
  className: "fixed inset-0 overflow-y-auto px-4 py-4 sm:px-6 sm:py-20 md:py-32 lg:px-8 lg:py-[15vh]",
1522
2052
  children: /* @__PURE__ */ jsxs(DialogPanel, {
1523
2053
  transition: true,
1524
- className: "clarify-search-panel mx-auto transform-gpu overflow-hidden rounded-lg bg-zinc-50 shadow-xl ring-1 ring-zinc-900/7.5 data-closed:scale-95 data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in sm:max-w-xl dark:bg-zinc-900 dark:ring-zinc-800",
2054
+ className: "clarify-search-panel mx-auto transform-gpu overflow-hidden rounded-(--clarify-theme-tokens-radius-lg) bg-(--clarify-theme-tokens-colors-surface) shadow-xl ring-1 ring-(--clarify-theme-tokens-colors-border) data-closed:scale-95 data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in sm:max-w-xl dark:bg-zinc-900 dark:ring-zinc-800",
1525
2055
  onKeyDown: (event) => {
1526
2056
  if (event.key === "ArrowDown") {
1527
2057
  event.preventDefault();
@@ -1539,24 +2069,12 @@ function SearchDialog(arg0) {
1539
2069
  onClose: closeDialog,
1540
2070
  onSubmit: () => selectResult()
1541
2071
  }), /* @__PURE__ */ jsxs("div", {
1542
- className: "border-t border-zinc-200 bg-white empty:hidden dark:border-zinc-100/5 dark:bg-white/2.5",
2072
+ className: "border-t border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-background) empty:hidden dark:border-zinc-100/5 dark:bg-white/2.5",
1543
2073
  children: [query && results.length === 0 ? /* @__PURE__ */ jsxs("div", {
1544
2074
  className: "p-6 text-center",
1545
- children: [/* @__PURE__ */ jsx(NoResultsIcon, { className: "mx-auto h-5 w-5 stroke-zinc-900 dark:stroke-zinc-600" }), /* @__PURE__ */ jsxs("p", {
1546
- className: "mt-2 text-xs text-zinc-700 dark:text-zinc-400",
1547
- children: [
1548
- "Nothing found for",
1549
- " ",
1550
- /* @__PURE__ */ jsxs("strong", {
1551
- className: "font-semibold wrap-break-word text-zinc-900 dark:text-white",
1552
- children: [
1553
- "‘",
1554
- query,
1555
- "’"
1556
- ]
1557
- }),
1558
- "."
1559
- ]
2075
+ children: [/* @__PURE__ */ jsx(NoResultsIcon, { className: "mx-auto h-5 w-5 stroke-(--clarify-theme-tokens-colors-foreground) dark:stroke-zinc-600" }), /* @__PURE__ */ jsx("p", {
2076
+ className: "mt-2 text-xs text-(--clarify-theme-tokens-colors-muted) dark:text-zinc-400",
2077
+ children: t("search.noResults", { query })
1560
2078
  })]
1561
2079
  }) : null, results.length ? /* @__PURE__ */ jsx("ul", {
1562
2080
  id: "clarify-search-results",
@@ -1596,19 +2114,20 @@ function getModifierKey() {
1596
2114
  }
1597
2115
  function Search(arg0) {
1598
2116
  const { routes, navigation } = arg0;
2117
+ const t = useBuiltInText();
1599
2118
  const modifierKey = getModifierKey();
1600
2119
  const { buttonProps, dialogProps } = useSearchProps();
1601
2120
  return /* @__PURE__ */ jsxs("div", {
1602
- className: "clarify-search hidden lg:block lg:max-w-md lg:flex-auto",
2121
+ className: "clarify-search hidden w-80 max-w-[36vw] lg:block",
1603
2122
  children: [/* @__PURE__ */ jsxs("button", {
1604
2123
  type: "button",
1605
- className: "clarify-search-button hidden h-8 w-full items-center gap-2 rounded-full bg-white pr-3 pl-2 text-sm text-zinc-500 ring-1 ring-zinc-900/10 transition hover:ring-zinc-900/20 lg:flex dark:bg-white/5 dark:text-zinc-400 dark:ring-white/10 dark:ring-inset dark:hover:ring-white/20",
2124
+ className: "clarify-search-button hidden h-9 w-full items-center gap-2 rounded-(--clarify-theme-tokens-radius-lg) bg-(--clarify-theme-tokens-colors-surface) pr-3 pl-2.5 font-medium ring-1 ring-(--clarify-theme-tokens-colors-border) transition hover:bg-(--clarify-theme-tokens-colors-background) lg:flex dark:bg-white/5 dark:ring-white/10 dark:ring-inset dark:hover:bg-white/10",
1606
2125
  ...buttonProps,
1607
2126
  children: [
1608
2127
  /* @__PURE__ */ jsx(SearchIcon, { className: "h-5 w-5 stroke-current" }),
1609
- "Find something...",
2128
+ t("search.button"),
1610
2129
  /* @__PURE__ */ jsxs("kbd", {
1611
- className: "ml-auto text-2xs text-zinc-400 dark:text-zinc-500",
2130
+ className: "clarify-search-shortcut ml-auto rounded-(--clarify-theme-tokens-radius-sm) bg-(--clarify-theme-tokens-colors-background) px-1.5 py-0.5 ring-1 ring-(--clarify-theme-tokens-colors-border) dark:bg-white/5 dark:ring-white/10",
1612
2131
  children: [/* @__PURE__ */ jsx("kbd", {
1613
2132
  className: "font-sans",
1614
2133
  children: modifierKey
@@ -1631,15 +2150,16 @@ function Search(arg0) {
1631
2150
  }
1632
2151
  function MobileSearch(arg0) {
1633
2152
  const { routes, navigation, onNavigate } = arg0;
2153
+ const t = useBuiltInText();
1634
2154
  const { buttonProps, dialogProps } = useSearchProps();
1635
2155
  return /* @__PURE__ */ jsxs("div", {
1636
2156
  className: "clarify-mobile-search contents lg:hidden",
1637
2157
  children: [/* @__PURE__ */ jsxs("button", {
1638
2158
  type: "button",
1639
- className: "clarify-mobile-search-button relative flex size-6 items-center justify-center rounded-md transition hover:bg-zinc-900/5 lg:hidden dark:hover:bg-white/5",
1640
- "aria-label": "Find something...",
2159
+ className: "clarify-mobile-search-button clarify-ui-control relative flex size-6 items-center justify-center rounded-(--clarify-theme-tokens-radius-md) transition lg:hidden",
2160
+ "aria-label": t("search.placeholder"),
1641
2161
  ...buttonProps,
1642
- children: [/* @__PURE__ */ jsx("span", { className: "absolute size-12 pointer-fine:hidden" }), /* @__PURE__ */ jsx(SearchIcon, { className: "h-5 w-5 stroke-zinc-900 dark:stroke-white" })]
2162
+ children: [/* @__PURE__ */ jsx("span", { className: "absolute size-12 pointer-fine:hidden" }), /* @__PURE__ */ jsx(SearchIcon, { className: "h-5 w-5 stroke-(--clarify-theme-tokens-colors-foreground) dark:stroke-white" })]
1643
2163
  }), /* @__PURE__ */ jsx(Suspense, {
1644
2164
  fallback: null,
1645
2165
  children: /* @__PURE__ */ jsx(SearchDialog, {
@@ -1684,6 +2204,7 @@ function LanguageIcon(props) {
1684
2204
  }
1685
2205
  function LanguageSwitcher(arg0) {
1686
2206
  const { config, currentLocale, currentRoute } = arg0;
2207
+ const t = useBuiltInText();
1687
2208
  const location = useLocation();
1688
2209
  const i18n = config.i18n;
1689
2210
  if (!i18n || i18n.locales.length < 2) return null;
@@ -1694,8 +2215,8 @@ function LanguageSwitcher(arg0) {
1694
2215
  as: "div",
1695
2216
  className: "clarify-language-switcher relative",
1696
2217
  children: [/* @__PURE__ */ jsxs(MenuButton, {
1697
- className: "clarify-language-switcher-button flex h-7 items-center gap-1.5 rounded-md px-1.5 text-sm/5 font-medium text-zinc-600 transition hover:bg-zinc-900/5 hover:text-zinc-900 dark:text-zinc-400 dark:hover:bg-white/5 dark:hover:text-white",
1698
- "aria-label": "Switch language",
2218
+ className: "clarify-language-switcher-button clarify-ui-control flex h-7 items-center gap-1.5 rounded-(--clarify-theme-tokens-radius-md) px-1.5 transition",
2219
+ "aria-label": t("language.switch"),
1699
2220
  children: [
1700
2221
  /* @__PURE__ */ jsx("span", { className: "absolute size-12 pointer-fine:hidden" }),
1701
2222
  /* @__PURE__ */ jsx(LanguageIcon, { className: "h-5 w-5 stroke-current" }),
@@ -1706,19 +2227,19 @@ function LanguageSwitcher(arg0) {
1706
2227
  ]
1707
2228
  }), /* @__PURE__ */ jsx(MenuItems, {
1708
2229
  transition: true,
1709
- className: "clarify-language-switcher-menu absolute right-0 z-50 mt-2 w-44 rounded-xl bg-white p-1 text-sm shadow-lg ring-1 shadow-zinc-900/5 ring-zinc-900/10 transition data-closed:scale-95 data-closed:opacity-0 data-enter:duration-100 data-enter:ease-out data-leave:duration-75 data-leave:ease-in dark:bg-zinc-900 dark:ring-white/10",
2230
+ className: "clarify-language-switcher-menu clarify-ui-menu absolute right-0 z-50 mt-2 w-(--clarify-ui-menu-width) rounded-(--clarify-theme-tokens-radius-xl) bg-(--clarify-theme-tokens-colors-surface) p-1 shadow-lg ring-1 shadow-zinc-900/5 ring-(--clarify-theme-tokens-colors-border) transition data-closed:scale-95 data-closed:opacity-0 data-enter:duration-100 data-enter:ease-out data-leave:duration-75 data-leave:ease-in dark:bg-zinc-900 dark:ring-white/10",
1710
2231
  children: i18n.locales.flatMap((locale) => {
1711
2232
  const localizedPath = localizedRoutePath(config, locale.code, currentRoute);
1712
2233
  if (!localizedPath) return [];
1713
2234
  const selected = locale.code === selectedLocale;
1714
2235
  return [/* @__PURE__ */ jsx(MenuItem, { children: ({ focus }) => /* @__PURE__ */ jsxs(Link, {
1715
2236
  to: `${localizedPath}${suffix}`,
1716
- className: clsx("clarify-language-switcher-item flex items-center justify-between rounded-lg px-3 py-2 no-underline transition", focus && "bg-zinc-100 dark:bg-white/5", selected ? "text-zinc-900 dark:text-white" : "text-zinc-600 dark:text-zinc-400"),
2237
+ className: clsx("clarify-language-switcher-item clarify-ui-menu-item flex items-center justify-between rounded-(--clarify-theme-tokens-radius-lg) px-3 py-2 no-underline transition", focus && "clarify-ui-menu-item-focus", selected && "clarify-ui-menu-item-active"),
1717
2238
  "aria-current": selected ? "true" : void 0,
1718
2239
  lang: locale.code,
1719
2240
  dir: locale.dir,
1720
2241
  children: [/* @__PURE__ */ jsx("span", { children: locale.label }), /* @__PURE__ */ jsx("span", {
1721
- className: "text-xs text-zinc-400 dark:text-zinc-500",
2242
+ className: "clarify-ui-menu-code",
1722
2243
  children: locale.code
1723
2244
  })]
1724
2245
  }) }, locale.code)];
@@ -1730,95 +2251,189 @@ function TopLevelNavItem(arg0) {
1730
2251
  const { href, children } = arg0;
1731
2252
  if (isExternalHref(href)) return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", {
1732
2253
  href,
1733
- className: "text-sm/5 text-zinc-600 transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white",
2254
+ className: "clarify-ui-top-link transition",
1734
2255
  target: "_blank",
1735
2256
  rel: "noreferrer",
1736
2257
  children
1737
2258
  }) });
1738
2259
  return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(Link, {
1739
2260
  to: href,
1740
- className: "text-sm/5 text-zinc-600 transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white",
2261
+ className: "clarify-ui-top-link transition",
1741
2262
  children
1742
2263
  }) });
1743
2264
  }
2265
+ function MobileNavbarMenu(arg0) {
2266
+ const { links, config, currentLocale } = arg0;
2267
+ const t = useBuiltInText();
2268
+ if (!links?.length) return null;
2269
+ return /* @__PURE__ */ jsxs(Menu, {
2270
+ as: "div",
2271
+ className: "clarify-mobile-navbar-menu relative md:hidden",
2272
+ children: [/* @__PURE__ */ jsxs(MenuButton, {
2273
+ className: "clarify-mobile-navbar-menu-button clarify-ui-control relative flex size-8 items-center justify-center rounded-(--clarify-theme-tokens-radius-md) transition",
2274
+ "aria-label": t("navbar.openLinks"),
2275
+ children: [/* @__PURE__ */ jsx("span", { className: "absolute size-12 pointer-fine:hidden" }), /* @__PURE__ */ jsx(MoreHorizontal, { className: "h-5 w-5" })]
2276
+ }), /* @__PURE__ */ jsx(MenuItems, {
2277
+ transition: true,
2278
+ anchor: "bottom end",
2279
+ className: "clarify-mobile-navbar-menu-list clarify-ui-menu z-50 mt-2 w-(--clarify-ui-menu-width) rounded-(--clarify-theme-tokens-radius-xl) border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface) p-1 shadow-lg transition [--anchor-gap:--spacing(2)] focus:outline-none data-closed:scale-95 data-closed:opacity-0 dark:border-white/10 dark:bg-zinc-900",
2280
+ children: links.map((link) => {
2281
+ const label = resolveLocalizedText(link.label, currentLocale, config.i18n?.defaultLocale);
2282
+ const href = localizeHref(link.href, config, currentLocale);
2283
+ const external = isExternalHref(href);
2284
+ return /* @__PURE__ */ jsx(MenuItem, { children: ({ focus }) => {
2285
+ const className = clsx("clarify-mobile-navbar-menu-item clarify-ui-menu-item block rounded-(--clarify-theme-tokens-radius-lg) px-3 py-2 no-underline transition", focus && "clarify-ui-menu-item-focus");
2286
+ return external ? /* @__PURE__ */ jsx("a", {
2287
+ href,
2288
+ target: "_blank",
2289
+ rel: "noreferrer",
2290
+ className,
2291
+ children: label
2292
+ }) : /* @__PURE__ */ jsx(Link, {
2293
+ to: href,
2294
+ className,
2295
+ children: label
2296
+ });
2297
+ } }, link.href);
2298
+ })
2299
+ })]
2300
+ });
2301
+ }
2302
+ function hasPath$1(nodes, pathname) {
2303
+ return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath$1(node.children ?? [], pathname));
2304
+ }
2305
+ function isActiveTab(tab, pathname) {
2306
+ return isSameRoutePath(tab.path, pathname) || hasPath$1(tab.children, pathname);
2307
+ }
2308
+ function ProductTabs(arg0) {
2309
+ const { tabs } = arg0;
2310
+ const t = useBuiltInText();
2311
+ const pathname = normalizeRoutePath(useLocation().pathname);
2312
+ if (!tabs?.length) return null;
2313
+ return /* @__PURE__ */ jsx("div", {
2314
+ className: "clarify-product-tabs hidden h-14 border-t border-(--clarify-theme-tokens-colors-border) lg:block dark:border-white/10",
2315
+ children: /* @__PURE__ */ jsx("nav", {
2316
+ className: "clarify-product-tabs-nav mx-auto flex h-full w-full max-w-(--clarify-theme-layout-max-width) items-stretch gap-6 overflow-x-auto px-5",
2317
+ "aria-label": t("navbar.sections"),
2318
+ children: tabs.map((tab) => {
2319
+ const active = isActiveTab(tab, pathname);
2320
+ return /* @__PURE__ */ jsxs(Link, {
2321
+ to: tab.path,
2322
+ "aria-current": active ? "page" : void 0,
2323
+ className: clsx("clarify-product-tab clarify-ui-tab relative inline-flex shrink-0 items-center gap-2 px-0 transition", active && "clarify-ui-tab-active"),
2324
+ children: [
2325
+ /* @__PURE__ */ jsx(NavigationIcon, {
2326
+ name: tab.icon,
2327
+ className: "h-4 w-4"
2328
+ }),
2329
+ /* @__PURE__ */ jsx("span", { children: tab.title }),
2330
+ active ? /* @__PURE__ */ jsx(motion.span, {
2331
+ layoutId: "clarify-product-tab-indicator",
2332
+ className: "absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-(--clarify-theme-tokens-colors-foreground) dark:bg-white",
2333
+ transition: {
2334
+ type: "spring",
2335
+ stiffness: 420,
2336
+ damping: 36
2337
+ }
2338
+ }) : null
2339
+ ]
2340
+ }, `${tab.title}-${tab.path}`);
2341
+ })
2342
+ })
2343
+ });
2344
+ }
1744
2345
  var Header = forwardRef(function Header(arg0, ref) {
1745
- const { config, navigation, routes, currentLocale, currentRoute, className, ...props } = arg0;
2346
+ const { config, navigation, tabs, routes, currentLocale, currentRoute, className, ...props } = arg0;
2347
+ const t = useBuiltInText();
1746
2348
  const { isOpen: mobileNavIsOpen } = useMobileNavigationStore();
1747
2349
  const isInsideMobileNavigation = useIsInsideMobileNavigation();
1748
2350
  const { scrollY } = useScroll();
1749
- const bgOpacityLight = useTransform(scrollY, [0, 72], ["50%", "90%"]);
1750
- const bgOpacityDark = useTransform(scrollY, [0, 72], ["20%", "80%"]);
1751
- return /* @__PURE__ */ jsxs(motion.div, {
2351
+ const bgOpacityLight = useTransform(scrollY, [0, 72], ["70%", "95%"]);
2352
+ const bgOpacityDark = useTransform(scrollY, [0, 72], ["60%", "92%"]);
2353
+ return /* @__PURE__ */ jsxs(motion.header, {
1752
2354
  ...props,
1753
2355
  ref,
1754
- className: clsx(className, "clarify-header fixed inset-x-0 top-0 z-50 flex h-14 items-center justify-between gap-12 px-4 transition sm:px-6 lg:left-72 lg:z-30 lg:px-8 xl:left-80", !isInsideMobileNavigation && "backdrop-blur-xs lg:left-72 xl:left-80 dark:backdrop-blur-sm", isInsideMobileNavigation ? "bg-white dark:bg-zinc-950" : "bg-white/(--bg-opacity-light) dark:bg-zinc-950/(--bg-opacity-dark)"),
2356
+ className: clsx(className, "clarify-header fixed inset-x-0 top-0 z-50 border-b border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-background)/(--bg-opacity-light) backdrop-blur-xs transition dark:border-white/10 dark:bg-zinc-950/(--bg-opacity-dark) dark:backdrop-blur-sm", isInsideMobileNavigation && "bg-(--clarify-theme-tokens-colors-background) dark:bg-zinc-950"),
1755
2357
  style: {
1756
2358
  "--bg-opacity-light": bgOpacityLight,
1757
2359
  "--bg-opacity-dark": bgOpacityDark
1758
2360
  },
1759
- children: [
1760
- /* @__PURE__ */ jsx("div", { className: clsx("absolute inset-x-0 top-full h-px transition", (isInsideMobileNavigation || !mobileNavIsOpen) && "bg-zinc-900/7.5 dark:bg-white/7.5") }),
1761
- /* @__PURE__ */ jsx("div", { className: "hidden lg:block" }),
1762
- /* @__PURE__ */ jsxs("div", {
1763
- className: "clarify-mobile-brand flex items-center gap-5 lg:hidden",
1764
- children: [/* @__PURE__ */ jsx(MobileNavigation, {
1765
- config,
1766
- navigation,
1767
- routes,
1768
- currentLocale,
1769
- currentRoute
1770
- }), config.logo ? /* @__PURE__ */ jsxs(CloseButton, {
1771
- as: Link,
1772
- to: localizeHref("/", config, currentLocale),
1773
- "aria-label": "Home",
1774
- className: "clarify-brand flex items-center gap-2 no-underline",
1775
- children: [/* @__PURE__ */ jsx(SiteLogo, {
1776
- logo: config.logo,
1777
- className: "h-6 w-6"
1778
- }), /* @__PURE__ */ jsx("span", {
1779
- className: "sr-only",
1780
- children: config.title
2361
+ children: [/* @__PURE__ */ jsxs("div", {
2362
+ className: clsx("clarify-header-main relative mx-auto flex h-14 w-full max-w-(--clarify-theme-layout-max-width) items-center justify-between gap-6 px-4 sm:px-6 lg:px-5", (isInsideMobileNavigation || !mobileNavIsOpen) && "shadow-none"),
2363
+ children: [
2364
+ /* @__PURE__ */ jsxs("div", {
2365
+ className: "clarify-header-left flex min-w-0 items-center gap-5",
2366
+ children: [/* @__PURE__ */ jsx("div", {
2367
+ className: "clarify-mobile-brand flex items-center gap-5 lg:hidden",
2368
+ children: /* @__PURE__ */ jsx(MobileNavigation, {
2369
+ config,
2370
+ navigation,
2371
+ tabs,
2372
+ routes,
2373
+ currentLocale,
2374
+ currentRoute
2375
+ })
2376
+ }), /* @__PURE__ */ jsxs(CloseButton, {
2377
+ as: Link,
2378
+ to: localizeHref("/", config, currentLocale),
2379
+ "aria-label": t("navbar.home"),
2380
+ className: "clarify-brand flex min-w-0 items-center gap-2 no-underline",
2381
+ children: [/* @__PURE__ */ jsx(SiteLogo, {
2382
+ logo: config.logo,
2383
+ className: "h-6 w-6 shrink-0"
2384
+ }), /* @__PURE__ */ jsx("span", {
2385
+ className: "clarify-brand-title truncate font-semibold",
2386
+ children: config.title
2387
+ })]
1781
2388
  })]
1782
- }) : null]
1783
- }),
1784
- /* @__PURE__ */ jsxs("div", {
1785
- className: "clarify-header-actions flex items-center gap-5",
1786
- children: [
1787
- /* @__PURE__ */ jsx(Search, {
2389
+ }),
2390
+ /* @__PURE__ */ jsx("div", {
2391
+ className: "clarify-header-center absolute left-1/2 hidden -translate-x-1/2 lg:block",
2392
+ children: /* @__PURE__ */ jsx(Search, {
1788
2393
  routes,
1789
2394
  navigation
1790
- }),
1791
- config.navbar?.links?.length ? /* @__PURE__ */ jsx("nav", {
1792
- className: "clarify-top-nav hidden md:block",
1793
- children: /* @__PURE__ */ jsx("ul", {
1794
- role: "list",
1795
- className: "flex items-center gap-8",
1796
- children: config.navbar.links.map((link) => /* @__PURE__ */ jsx(TopLevelNavItem, {
1797
- href: localizeHref(link.href, config, currentLocale),
1798
- children: resolveLocalizedText(link.label, currentLocale, config.i18n?.defaultLocale)
1799
- }, link.href))
2395
+ })
2396
+ }),
2397
+ /* @__PURE__ */ jsxs("div", {
2398
+ className: "clarify-header-actions flex shrink-0 items-center gap-5",
2399
+ children: [
2400
+ config.navbar?.links?.length ? /* @__PURE__ */ jsx("nav", {
2401
+ className: "clarify-top-nav hidden md:block",
2402
+ children: /* @__PURE__ */ jsx("ul", {
2403
+ role: "list",
2404
+ className: "flex items-center gap-8",
2405
+ children: config.navbar.links.map((link) => /* @__PURE__ */ jsx(TopLevelNavItem, {
2406
+ href: localizeHref(link.href, config, currentLocale),
2407
+ children: resolveLocalizedText(link.label, currentLocale, config.i18n?.defaultLocale)
2408
+ }, link.href))
2409
+ })
2410
+ }) : null,
2411
+ config.navbar?.links?.length ? /* @__PURE__ */ jsx("div", { className: "hidden md:block md:h-5 md:w-px md:bg-(--clarify-theme-tokens-colors-border) md:dark:bg-white/15" }) : null,
2412
+ /* @__PURE__ */ jsx(MobileSearch, {
2413
+ routes,
2414
+ navigation
2415
+ }),
2416
+ /* @__PURE__ */ jsx(LanguageSwitcher, {
2417
+ config,
2418
+ currentLocale,
2419
+ currentRoute
2420
+ }),
2421
+ /* @__PURE__ */ jsx(ThemeToggle, {}),
2422
+ /* @__PURE__ */ jsx(MobileNavbarMenu, {
2423
+ links: config.navbar?.links,
2424
+ config,
2425
+ currentLocale
1800
2426
  })
1801
- }) : null,
1802
- config.navbar?.links?.length ? /* @__PURE__ */ jsx("div", { className: "hidden md:block md:h-5 md:w-px md:bg-zinc-900/10 md:dark:bg-white/15" }) : null,
1803
- /* @__PURE__ */ jsx(MobileSearch, {
1804
- routes,
1805
- navigation
1806
- }),
1807
- /* @__PURE__ */ jsx(LanguageSwitcher, {
1808
- config,
1809
- currentLocale,
1810
- currentRoute
1811
- }),
1812
- /* @__PURE__ */ jsx(ThemeToggle, {})
1813
- ]
1814
- })
1815
- ]
2427
+ ]
2428
+ })
2429
+ ]
2430
+ }), /* @__PURE__ */ jsx(ProductTabs, { tabs })]
1816
2431
  });
1817
2432
  });
1818
2433
  //#endregion
1819
2434
  //#region source/app/AppShell.tsx
1820
2435
  function routeForPath(routes, pathname) {
1821
- return routes.find((route) => route.path === pathname || `/${route.path}` === pathname);
2436
+ return routes.find((route) => isSameRoutePath(route.path, pathname));
1822
2437
  }
1823
2438
  function sectionsForRoute(route) {
1824
2439
  return route?.sections?.map((section) => ({
@@ -1828,11 +2443,18 @@ function sectionsForRoute(route) {
1828
2443
  tags: section.tags
1829
2444
  })) ?? [];
1830
2445
  }
2446
+ function resolveRouteComponent(route) {
2447
+ if (route.lazy) return lazy(route.component);
2448
+ return route.component;
2449
+ }
1831
2450
  function scrollToHash(hash) {
1832
2451
  if (!hash) return;
1833
2452
  const targetId = decodeURIComponent(hash.slice(1));
1834
2453
  window.requestAnimationFrame(() => {
1835
2454
  document.getElementById(targetId)?.scrollIntoView();
2455
+ window.requestAnimationFrame(() => {
2456
+ window.dispatchEvent(new Event("scroll"));
2457
+ });
1836
2458
  });
1837
2459
  }
1838
2460
  function localeForPath(config, pathname, route) {
@@ -1842,25 +2464,101 @@ function localeForPath(config, pathname, route) {
1842
2464
  const firstSegment = pathname.split("/").filter(Boolean)[0];
1843
2465
  return i18n.locales.find((locale) => locale.code === firstSegment)?.code ?? i18n.defaultLocale;
1844
2466
  }
1845
- function navigationForLocale(navigation, locale) {
1846
- if (Array.isArray(navigation)) return navigation;
1847
- if (!locale) return [];
1848
- return navigation[locale] ?? [];
2467
+ function isTabbedNavigation(navigation) {
2468
+ return !Array.isArray(navigation) && "tabs" in navigation;
2469
+ }
2470
+ function hasPath(nodes, pathname) {
2471
+ return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath(node.children ?? [], pathname));
2472
+ }
2473
+ function navigationFromTabs(navigation, pathname) {
2474
+ return {
2475
+ items: navigation.tabs.find((tab) => isSameRoutePath(tab.path, pathname) || hasPath(tab.children, pathname))?.children ?? navigation.tabs[0]?.children ?? [],
2476
+ tabs: navigation.tabs
2477
+ };
2478
+ }
2479
+ function navigationForLocale(navigation, locale, pathname) {
2480
+ if (Array.isArray(navigation)) return { items: navigation };
2481
+ if (isTabbedNavigation(navigation)) return navigationFromTabs(navigation, pathname);
2482
+ if (!locale) return { items: [] };
2483
+ const localizedNavigation = navigation[locale];
2484
+ if (!localizedNavigation) return { items: [] };
2485
+ return Array.isArray(localizedNavigation) ? { items: localizedNavigation } : navigationFromTabs(localizedNavigation, pathname);
2486
+ }
2487
+ function themeStyle(config) {
2488
+ const { colors, radius } = config.theme.tokens;
2489
+ const { layout } = config.theme;
2490
+ return {
2491
+ "--clarify-theme-tokens-colors-primary": colors.primary,
2492
+ "--clarify-theme-tokens-colors-accent": colors.accent,
2493
+ "--clarify-theme-tokens-colors-background": colors.background,
2494
+ "--clarify-theme-tokens-colors-foreground": colors.foreground,
2495
+ "--clarify-theme-tokens-colors-surface": colors.surface,
2496
+ "--clarify-theme-tokens-colors-muted": colors.muted,
2497
+ "--clarify-theme-tokens-colors-border": colors.border,
2498
+ "--clarify-theme-tokens-colors-code-background": colors.codeBackground,
2499
+ "--clarify-theme-tokens-radius-sm": radius.sm,
2500
+ "--clarify-theme-tokens-radius-md": radius.md,
2501
+ "--clarify-theme-tokens-radius-lg": radius.lg,
2502
+ "--clarify-theme-tokens-radius-xl": radius.xl,
2503
+ "--clarify-theme-layout-max-width": layout.maxWidth
2504
+ };
2505
+ }
2506
+ function pageTitle(config, route) {
2507
+ const routeTitle = route?.title?.trim();
2508
+ if (!routeTitle || routeTitle === config.title) return config.title;
2509
+ return `${routeTitle} - ${config.title}`;
1849
2510
  }
1850
- function homePathForLocale(config, locale) {
1851
- if (!locale || !config.i18n || locale === config.i18n.defaultLocale) return "/";
1852
- return `/${locale}`;
2511
+ function setNamedMeta(name, content) {
2512
+ const existing = document.head.querySelector(`meta[name="${name}"]`);
2513
+ if (!content) {
2514
+ existing?.remove();
2515
+ return;
2516
+ }
2517
+ const meta = existing ?? document.createElement("meta");
2518
+ meta.name = name;
2519
+ meta.content = content;
2520
+ if (!existing) document.head.appendChild(meta);
2521
+ }
2522
+ function applyDocumentMetadata(config, route) {
2523
+ document.title = pageTitle(config, route);
2524
+ setNamedMeta("description", route?.description ?? config.description);
2525
+ setNamedMeta("keywords", route?.keywords?.join(", "));
2526
+ }
2527
+ function applyRootThemeVariables(themeVariables) {
2528
+ const rootStyle = document.documentElement.style;
2529
+ for (const [property, value] of Object.entries(themeVariables)) rootStyle.setProperty(property, value);
2530
+ return () => {
2531
+ for (const property of Object.keys(themeVariables)) rootStyle.removeProperty(property);
2532
+ };
1853
2533
  }
1854
2534
  function AppShell(arg0) {
1855
2535
  const { config, routes, navigation } = arg0;
1856
2536
  const location = useLocation();
1857
- const currentRoute = routeForPath(routes, location.pathname);
1858
- const currentLocale = localeForPath(config, location.pathname, currentRoute);
2537
+ const pathname = normalizeRoutePath(location.pathname);
2538
+ const currentRoute = routeForPath(routes, pathname);
2539
+ const currentLocale = localeForPath(config, pathname, currentRoute);
1859
2540
  const currentLocaleConfig = config.i18n?.locales.find((locale) => locale.code === currentLocale);
1860
- const currentNavigation = navigationForLocale(navigation, currentLocale);
2541
+ const currentNavigation = navigationForLocale(navigation, currentLocale, pathname);
1861
2542
  const sections = sectionsForRoute(currentRoute);
2543
+ const hasTabs = Boolean(currentNavigation.tabs?.length);
2544
+ const themeVariables = themeStyle(config);
2545
+ const renderRoutes = useMemo(() => routes.map((route) => ({
2546
+ ...route,
2547
+ component: resolveRouteComponent(route)
2548
+ })), [routes]);
2549
+ useEffect(() => applyRootThemeVariables(themeVariables), [themeVariables]);
1862
2550
  useEffect(() => {
1863
- scrollToHash(location.hash);
2551
+ if (location.hash) {
2552
+ scrollToHash(location.hash);
2553
+ return;
2554
+ }
2555
+ window.scrollTo({
2556
+ top: 0,
2557
+ left: 0
2558
+ });
2559
+ window.requestAnimationFrame(() => {
2560
+ window.dispatchEvent(new Event("scroll"));
2561
+ });
1864
2562
  }, [location.hash, location.pathname]);
1865
2563
  useEffect(() => {
1866
2564
  if (!currentLocale) return;
@@ -1868,61 +2566,64 @@ function AppShell(arg0) {
1868
2566
  if (currentLocaleConfig?.dir) document.documentElement.dir = currentLocaleConfig.dir;
1869
2567
  else document.documentElement.removeAttribute("dir");
1870
2568
  }, [currentLocale, currentLocaleConfig?.dir]);
1871
- return /* @__PURE__ */ jsx(SectionProvider, {
1872
- sections,
1873
- children: /* @__PURE__ */ jsxs("div", {
1874
- className: "clarify-app h-full min-h-screen bg-white lg:ml-72 xl:ml-80 dark:bg-zinc-950",
1875
- children: [/* @__PURE__ */ jsx(motion.header, {
1876
- layoutScroll: true,
1877
- className: "clarify-shell contents lg:pointer-events-none lg:fixed lg:inset-0 lg:z-40 lg:flex",
1878
- children: /* @__PURE__ */ jsxs("div", {
1879
- className: "clarify-sidebar contents lg:pointer-events-auto lg:block lg:w-72 lg:overflow-y-auto lg:border-r lg:border-zinc-900/10 lg:bg-white lg:px-6 lg:pt-4 lg:pb-8 xl:w-80 lg:dark:border-white/10 lg:dark:bg-zinc-950",
1880
- children: [
1881
- /* @__PURE__ */ jsx("div", {
1882
- className: "clarify-sidebar-brand hidden lg:flex",
1883
- children: /* @__PURE__ */ jsxs(Link, {
1884
- to: homePathForLocale(config, currentLocale),
1885
- "aria-label": "Home",
1886
- className: "clarify-brand flex items-center gap-2 no-underline",
1887
- children: [/* @__PURE__ */ jsx(SiteLogo, {
1888
- logo: config.logo,
1889
- className: "h-6 w-6"
1890
- }), /* @__PURE__ */ jsx("span", {
1891
- className: "clarify-brand-title text-sm font-semibold text-zinc-900 dark:text-white",
1892
- children: config.title
1893
- })]
1894
- })
1895
- }),
1896
- /* @__PURE__ */ jsx(Header, {
1897
- config,
1898
- navigation: currentNavigation,
1899
- routes,
1900
- currentLocale,
1901
- currentRoute
1902
- }),
1903
- /* @__PURE__ */ jsx(Navigation, {
1904
- navigation: currentNavigation,
1905
- className: "clarify-navigation hidden lg:mt-10 lg:block"
1906
- })
1907
- ]
1908
- })
1909
- }), /* @__PURE__ */ jsxs("div", {
1910
- className: "clarify-content relative flex min-h-screen flex-col px-4 pt-14 sm:px-6 lg:px-8",
1911
- children: [/* @__PURE__ */ jsx(ContentActions, {
1912
- route: currentRoute,
1913
- routePrefix: config.routePrefix
1914
- }), /* @__PURE__ */ jsx("main", {
1915
- className: "clarify-main flex-auto",
1916
- children: /* @__PURE__ */ jsx(Routes, { children: routes.map((route) => /* @__PURE__ */ jsx(Route, {
1917
- path: route.path,
1918
- element: /* @__PURE__ */ jsx(route.component, {})
1919
- }, route.path)) })
1920
- })]
1921
- })]
2569
+ useEffect(() => {
2570
+ applyDocumentMetadata(config, currentRoute);
2571
+ }, [config, currentRoute]);
2572
+ return /* @__PURE__ */ jsx(ClarifyLocaleContext.Provider, {
2573
+ value: currentLocale,
2574
+ children: /* @__PURE__ */ jsx(SectionProvider, {
2575
+ sections,
2576
+ children: /* @__PURE__ */ jsxs("div", {
2577
+ className: "clarify-app h-full min-h-screen bg-(--clarify-theme-tokens-colors-background) text-(--clarify-theme-tokens-colors-foreground) dark:bg-zinc-950 dark:text-white",
2578
+ "data-theme-preset": config.theme.preset,
2579
+ style: themeVariables,
2580
+ children: [
2581
+ /* @__PURE__ */ jsx(Header, {
2582
+ config,
2583
+ navigation: currentNavigation.items,
2584
+ tabs: currentNavigation.tabs,
2585
+ routes,
2586
+ currentLocale,
2587
+ currentRoute
2588
+ }),
2589
+ /* @__PURE__ */ jsxs("div", {
2590
+ className: "clarify-layout mx-auto grid w-full max-w-(--clarify-theme-layout-max-width) grid-cols-1 lg:grid-cols-[18rem_minmax(0,1fr)] xl:grid-cols-[20rem_minmax(0,1fr)]",
2591
+ children: [/* @__PURE__ */ jsx(motion.aside, {
2592
+ layoutScroll: true,
2593
+ className: clsx("clarify-sidebar hidden lg:sticky lg:z-30 lg:block lg:h-[calc(100vh-3.5rem)] lg:self-start lg:overflow-y-auto lg:bg-(--clarify-theme-tokens-colors-background) lg:px-5 lg:pb-8 xl:px-6 lg:dark:bg-zinc-950", hasTabs ? "lg:top-28 lg:h-[calc(100vh-7rem)] lg:pt-6" : "lg:top-14 lg:pt-6"),
2594
+ children: /* @__PURE__ */ jsx(Navigation, { navigation: currentNavigation.items })
2595
+ }), /* @__PURE__ */ jsxs("div", {
2596
+ className: clsx("clarify-content @container relative flex min-h-screen min-w-0 flex-col px-4 sm:px-6 lg:px-8 xl:px-10", hasTabs ? "pt-14 lg:pt-28" : "pt-14"),
2597
+ children: [
2598
+ /* @__PURE__ */ jsx(ContentActions, {
2599
+ hasTabs,
2600
+ route: currentRoute,
2601
+ routePrefix: config.routePrefix
2602
+ }),
2603
+ /* @__PURE__ */ jsx("main", {
2604
+ className: "clarify-main min-w-0 flex-auto",
2605
+ children: /* @__PURE__ */ jsx(Suspense, {
2606
+ fallback: null,
2607
+ children: /* @__PURE__ */ jsx(Routes, { children: renderRoutes.map((route) => /* @__PURE__ */ jsx(Route, {
2608
+ path: route.path,
2609
+ element: /* @__PURE__ */ jsx(route.component, {})
2610
+ }, route.path)) })
2611
+ })
2612
+ }),
2613
+ /* @__PURE__ */ jsx(PageNavigation, {
2614
+ navigation: currentNavigation.items,
2615
+ currentRoute
2616
+ })
2617
+ ]
2618
+ })]
2619
+ }),
2620
+ /* @__PURE__ */ jsx(PageFooter, {})
2621
+ ]
2622
+ })
1922
2623
  })
1923
2624
  });
1924
2625
  }
1925
2626
  //#endregion
1926
- export { BuiltWithClarify as C, remToPx as E, Pre as S, useSectionStore as T, GridPattern as _, Heading as a, Code as b, Tag as c, useTheme as d, PageFooter as f, useOpenApis as g, useClarifyConfig as h, DocShell as i, ThemeToggle as l, OpenApisContext as m, ApiEndpointCard as n, Logo as o, ClarifyConfigContext as p, Button as r, Prose as s, AppShell as t, ThemeProvider as u, HeroPattern as v, SectionProvider as w, CodeGroup as x, Feedback as y };
2627
+ export { remToPx as A, useBuiltInText as C, useOpenApis as D, useClarifyConfig as E, SectionProvider as O, BuiltWithClarify as S, OpenApisContext as T, CodeGroup as _, Heading as a, CardGroup as b, Tag as c, useTheme as d, PageFooter as f, Code as g, Feedback as h, DocShell as i, useSectionStore as k, ThemeToggle as l, HeroPattern as m, ApiEndpointCard as n, Logo as o, GridPattern as p, Button as r, Prose as s, AppShell as t, ThemeProvider as u, Pre as v, ClarifyConfigContext as w, Callout as x, Card as y };
1927
2628
 
1928
- //# sourceMappingURL=AppShell-C_bj6ZhV.js.map
2629
+ //# sourceMappingURL=AppShell-nQnuKyn2.js.map