@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
@@ -29,16 +29,16 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
29
29
  enumerable: true
30
30
  }) : target, mod));
31
31
  //#endregion
32
+ let clsx = require("clsx");
33
+ clsx = __toESM(clsx, 1);
32
34
  let framer_motion = require("framer-motion");
33
35
  let react = require("react");
34
36
  let react_router_dom = require("react-router-dom");
35
37
  let zustand = require("zustand");
36
38
  let react_jsx_runtime = require("react/jsx-runtime");
37
- let clsx = require("clsx");
38
- clsx = __toESM(clsx, 1);
39
- let _headlessui_react = require("@headlessui/react");
40
39
  let lucide_react = require("lucide-react");
41
40
  lucide_react = __toESM(lucide_react, 1);
41
+ let _headlessui_react = require("@headlessui/react");
42
42
  //#region source/utils/remToPx.ts
43
43
  function remToPx(remValue) {
44
44
  return remValue * (typeof window === "undefined" ? 16 : Number.parseFloat(window.getComputedStyle(document.documentElement).fontSize));
@@ -93,7 +93,14 @@ function SectionProvider(arg0) {
93
93
  const [sectionStore] = (0, react.useState)(() => createSectionStore(sections));
94
94
  useVisibleSections(sectionStore);
95
95
  useIsomorphicLayoutEffect(() => {
96
- sectionStore.setState({ sections });
96
+ sectionStore.setState((state) => ({ sections: sections.map((section) => {
97
+ const registeredSection = state.sections.find((item) => item.id === section.id);
98
+ return {
99
+ ...section,
100
+ headingRef: registeredSection?.headingRef,
101
+ offsetRem: registeredSection?.offsetRem ?? section.offsetRem
102
+ };
103
+ }) }));
97
104
  }, [sectionStore, sections]);
98
105
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionStoreContext.Provider, {
99
106
  value: sectionStore,
@@ -106,110 +113,179 @@ function useSectionStore(selector) {
106
113
  return (0, zustand.useStore)(store, selector);
107
114
  }
108
115
  //#endregion
109
- //#region source/components/SiteLogo.tsx
110
- function SiteLogo(arg0) {
111
- const { logo, className } = arg0;
112
- if (!logo) return null;
113
- if (typeof logo === "string") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
114
- src: logo,
115
- alt: "",
116
- className: (0, clsx.default)("clarify-logo", className)
117
- });
118
- const lightLogo = logo.light ?? logo.dark;
119
- const darkLogo = logo.dark ?? logo.light;
120
- if (!lightLogo || !darkLogo) return null;
121
- if (lightLogo === darkLogo) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
122
- src: lightLogo,
123
- alt: "",
124
- className: (0, clsx.default)("clarify-logo", className)
125
- });
126
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
127
- src: lightLogo,
128
- alt: "",
129
- className: (0, clsx.default)("clarify-logo clarify-logo-light", className, "dark:hidden")
130
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
131
- src: darkLogo,
132
- alt: "",
133
- className: (0, clsx.default)("clarify-logo clarify-logo-dark", className, "hidden dark:block")
134
- })] });
116
+ //#region source/context.tsx
117
+ var ClarifyConfigContext = (0, react.createContext)(null);
118
+ var ClarifyLocaleContext = (0, react.createContext)(void 0);
119
+ var OpenApisContext = (0, react.createContext)({});
120
+ function useClarifyConfig() {
121
+ const config = (0, react.useContext)(ClarifyConfigContext);
122
+ if (!config) throw new Error("[clarify] useClarifyConfig must be used within a ClarifyConfigContext.Provider");
123
+ return config;
135
124
  }
136
- //#endregion
137
- //#region source/shell/ContentActions.tsx
138
- function resolveRawContentUrl(rawContentUrl, routePrefix = "/") {
139
- if (!routePrefix || routePrefix === "/") return rawContentUrl;
140
- return `/${routePrefix.replace(/^\/+|\/+$/g, "")}${rawContentUrl}`;
125
+ function useOpenApis() {
126
+ return (0, react.useContext)(OpenApisContext);
141
127
  }
142
- function getAbsoluteUrl(path) {
143
- if (typeof window === "undefined") return path;
144
- return new URL(path, window.location.href).href;
128
+ //#endregion
129
+ //#region source/i18n.ts
130
+ var builtInText = {
131
+ en: {
132
+ "actions.code": "Code",
133
+ "actions.copy": "Copy",
134
+ "actions.copied": "Copied!",
135
+ "builtWith.label": "Built with Clarify",
136
+ "builtWith.prefix": "Built with",
137
+ "callout.danger": "Danger",
138
+ "callout.info": "Info",
139
+ "callout.note": "Note",
140
+ "callout.success": "Success",
141
+ "callout.tip": "Tip",
142
+ "callout.warning": "Warning",
143
+ "contentActions.copyContent": "Copy page",
144
+ "contentActions.copyContentDescription": "Copy this page as {contentType} for LLMs",
145
+ "contentActions.copyLink": "Copy {contentType} link",
146
+ "contentActions.copyLinkDescription": "Copy the raw {contentType} content link for this page",
147
+ "contentActions.copyOptions": "Choose copy option",
148
+ "contentActions.copiedContent": "Copied page",
149
+ "contentActions.copiedLink": "Copied link",
150
+ "contentActions.viewMarkdown": "View as Markdown",
151
+ "contentActions.viewMarkdownDescription": "View this page as plain text",
152
+ "contentActions.viewOpenApi": "View raw OpenAPI",
153
+ "contentActions.viewOpenApiDescription": "Open the API description file in a new tab",
154
+ "feedback.no": "No",
155
+ "feedback.prompt": "Was this page helpful?",
156
+ "feedback.thanks": "Thanks for your feedback!",
157
+ "feedback.yes": "Yes",
158
+ "navigation.documentation": "Documentation",
159
+ "navigation.next": "Next",
160
+ "navigation.previous": "Previous",
161
+ "navigation.previousNext": "Previous and next pages",
162
+ "navigation.toggle": "Toggle navigation",
163
+ "navbar.home": "Home",
164
+ "navbar.openLinks": "Open navigation links",
165
+ "navbar.sections": "Documentation sections",
166
+ "openapi.apiDocumentation": "API Documentation",
167
+ "openapi.bodyProperties": "Body properties",
168
+ "openapi.collapse": "Collapse",
169
+ "openapi.endpointNotFound": "Endpoint not found: {endpoint}",
170
+ "openapi.example": "Example",
171
+ "openapi.expand": "Expand",
172
+ "openapi.headers": "Headers",
173
+ "openapi.language": "Language",
174
+ "openapi.client": "Client",
175
+ "openapi.mediaType": "Media type",
176
+ "openapi.openApiReference": "OpenAPI Reference",
177
+ "openapi.operationParameter": "Operation parameter.",
178
+ "openapi.optional": "Optional.",
179
+ "openapi.parameter": "parameter",
180
+ "openapi.pathParameters": "Path parameters",
181
+ "openapi.queryParameters": "Query parameters",
182
+ "openapi.request": "Request",
183
+ "openapi.requestBody": "Request body",
184
+ "openapi.required": "Required.",
185
+ "openapi.requiredBadge": "required",
186
+ "openapi.response": "Response",
187
+ "openapi.responses": "Responses",
188
+ "openapi.schemaExample": "Schema example",
189
+ "openapi.scrollExamplesLeft": "Scroll examples left",
190
+ "openapi.scrollExamplesRight": "Scroll examples right",
191
+ "openapi.specNotFound": "OpenAPI spec not found: {specPath}",
192
+ "openapi.specPathMissing": "spec or specPath was not provided",
193
+ "openapi.status": "Status",
194
+ "openapi.version": "Version {version}",
195
+ "search.button": "Search...",
196
+ "search.noResults": "Nothing found for {query}.",
197
+ "search.placeholder": "Find something...",
198
+ "search.shortcutCtrl": "Ctrl ",
199
+ "theme.switchToDark": "Switch to dark theme",
200
+ "theme.switchToLight": "Switch to light theme",
201
+ "language.switch": "Switch language"
202
+ },
203
+ "zh-CN": {
204
+ "actions.code": "代码",
205
+ "actions.copy": "复制",
206
+ "actions.copied": "已复制!",
207
+ "builtWith.label": "由 Clarify 构建",
208
+ "builtWith.prefix": "构建来自",
209
+ "callout.danger": "危险",
210
+ "callout.info": "信息",
211
+ "callout.note": "注意",
212
+ "callout.success": "成功",
213
+ "callout.tip": "提示",
214
+ "callout.warning": "警告",
215
+ "contentActions.copyContent": "复制页面",
216
+ "contentActions.copyContentDescription": "将页面以 {contentType} 格式复制给 LLMs",
217
+ "contentActions.copyLink": "复制 {contentType} 链接",
218
+ "contentActions.copyLinkDescription": "复制当前页面的 {contentType} 原始内容链接",
219
+ "contentActions.copyOptions": "选择复制选项",
220
+ "contentActions.copiedContent": "已复制页面",
221
+ "contentActions.copiedLink": "已复制链接",
222
+ "contentActions.viewMarkdown": "以 Markdown 格式查看",
223
+ "contentActions.viewMarkdownDescription": "以纯文本查看此页面",
224
+ "contentActions.viewOpenApi": "查看 OpenAPI 原始内容",
225
+ "contentActions.viewOpenApiDescription": "在新标签页打开 API 描述文件",
226
+ "feedback.no": "否",
227
+ "feedback.prompt": "这个页面有帮助吗?",
228
+ "feedback.thanks": "感谢你的反馈!",
229
+ "feedback.yes": "是",
230
+ "navigation.documentation": "文档",
231
+ "navigation.next": "下一页",
232
+ "navigation.previous": "上一页",
233
+ "navigation.previousNext": "上一页和下一页",
234
+ "navigation.toggle": "切换导航",
235
+ "navbar.home": "首页",
236
+ "navbar.openLinks": "打开导航链接",
237
+ "navbar.sections": "文档栏目",
238
+ "openapi.apiDocumentation": "API 文档",
239
+ "openapi.bodyProperties": "请求体属性",
240
+ "openapi.collapse": "收起",
241
+ "openapi.endpointNotFound": "未找到端点:{endpoint}",
242
+ "openapi.example": "示例",
243
+ "openapi.expand": "展开",
244
+ "openapi.headers": "请求头",
245
+ "openapi.language": "语言",
246
+ "openapi.client": "客户端",
247
+ "openapi.mediaType": "媒体类型",
248
+ "openapi.openApiReference": "OpenAPI 参考",
249
+ "openapi.operationParameter": "操作参数。",
250
+ "openapi.optional": "可选。",
251
+ "openapi.parameter": "参数",
252
+ "openapi.pathParameters": "路径参数",
253
+ "openapi.queryParameters": "查询参数",
254
+ "openapi.request": "请求",
255
+ "openapi.requestBody": "请求体",
256
+ "openapi.required": "必填。",
257
+ "openapi.requiredBadge": "必填",
258
+ "openapi.response": "响应",
259
+ "openapi.responses": "响应",
260
+ "openapi.schemaExample": "Schema 示例",
261
+ "openapi.scrollExamplesLeft": "向左滚动示例",
262
+ "openapi.scrollExamplesRight": "向右滚动示例",
263
+ "openapi.specNotFound": "未找到 OpenAPI 描述文件:{specPath}",
264
+ "openapi.specPathMissing": "未提供 spec 或 specPath",
265
+ "openapi.status": "状态",
266
+ "openapi.version": "版本 {version}",
267
+ "search.button": "搜索...",
268
+ "search.noResults": "没有找到与 {query} 相关的结果。",
269
+ "search.placeholder": "搜索内容...",
270
+ "search.shortcutCtrl": "Ctrl ",
271
+ "theme.switchToDark": "切换到深色主题",
272
+ "theme.switchToLight": "切换到浅色主题",
273
+ "language.switch": "切换语言"
274
+ }
275
+ };
276
+ function resolveBuiltInLocale(locale) {
277
+ return locale === "zh-CN" || locale?.toLowerCase().startsWith("zh") ? "zh-CN" : "en";
145
278
  }
146
- async function copyText(text) {
147
- await navigator.clipboard.writeText(text);
279
+ function translateBuiltInText(locale, key, replacements = {}) {
280
+ let value = builtInText[resolveBuiltInLocale(locale)]?.[key] ?? builtInText.en[key];
281
+ for (const [name, replacement] of Object.entries(replacements)) value = value.replaceAll(`{${name}}`, replacement);
282
+ return value;
148
283
  }
149
- function ContentActions(arg0) {
150
- const { route, routePrefix } = arg0;
151
- const [copied, setCopied] = (0, react.useState)("idle");
152
- if (!route?.rawContentUrl) return null;
153
- const rawContentUrl = resolveRawContentUrl(route.rawContentUrl, routePrefix);
154
- const isOpenApi = route.kind === "openapi";
155
- const contentLabel = isOpenApi ? "复制 OpenAPI 内容" : "复制 Markdown 内容";
156
- const linkLabel = isOpenApi ? "复制 OpenAPI 链接" : "复制 Markdown 链接";
157
- function markCopied(state) {
158
- setCopied(state);
159
- window.setTimeout(() => setCopied("idle"), 1600);
160
- }
161
- async function handleCopyContent() {
162
- await copyText(await (await fetch(rawContentUrl)).text());
163
- markCopied("content");
164
- }
165
- async function handleCopyLink() {
166
- await copyText(getAbsoluteUrl(rawContentUrl));
167
- markCopied("link");
168
- }
169
- const actions = [{
170
- key: "content",
171
- label: contentLabel,
172
- icon: lucide_react.Copy,
173
- run: handleCopyContent
174
- }, {
175
- key: "link",
176
- label: linkLabel,
177
- icon: lucide_react.Link2,
178
- run: handleCopyLink
179
- }];
180
- const primaryAction = actions[0];
181
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
182
- className: "clarify-content-actions sticky top-16 z-20 flex justify-end py-4",
183
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.Menu, {
184
- as: "div",
185
- className: "clarify-content-actions-menu relative inline-flex text-xs font-medium",
186
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
187
- 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",
188
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
189
- type: "button",
190
- onClick: primaryAction.run,
191
- 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",
192
- children: [copied === primaryAction.key ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(primaryAction.icon, { className: "h-3.5 w-3.5" }), copied === primaryAction.key ? "已复制" : "复制页面"]
193
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuButton, {
194
- 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",
195
- "aria-label": "选择复制选项",
196
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronDown, { className: "h-3.5 w-3.5" })
197
- })]
198
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItems, {
199
- anchor: "bottom end",
200
- 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",
201
- children: actions.map((action) => {
202
- const Icon = copied === action.key ? lucide_react.Check : action.icon;
203
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
204
- type: "button",
205
- onClick: action.run,
206
- 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",
207
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: copied === action.key ? "已复制" : action.label })]
208
- }) }, action.key);
209
- })
210
- })]
211
- })
212
- });
284
+ function useBuiltInText(locale) {
285
+ const config = (0, react.useContext)(ClarifyConfigContext);
286
+ const currentLocale = (0, react.useContext)(ClarifyLocaleContext);
287
+ const resolvedLocale = locale ?? currentLocale ?? config?.i18n?.defaultLocale;
288
+ return (key, replacements) => translateBuiltInText(resolvedLocale, key, replacements);
213
289
  }
214
290
  //#endregion
215
291
  //#region source/components/BuiltWithClarify.tsx
@@ -237,23 +313,163 @@ function ClarifyMark(props) {
237
313
  });
238
314
  }
239
315
  function BuiltWithClarify() {
316
+ const t = useBuiltInText();
240
317
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
241
318
  href: "https://clarify.pub",
242
319
  target: "_blank",
243
320
  rel: "noreferrer",
244
- "aria-label": "Built with Clarify",
245
- 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",
321
+ "aria-label": t("builtWith.label"),
322
+ className: "clarify-built-with inline-flex items-center gap-1.5 rounded-full px-2 py-1 font-medium no-underline transition",
246
323
  children: [
247
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Built with" }),
324
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("builtWith.prefix") }),
248
325
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClarifyMark, { className: "clarify-built-with-logo h-3.5 w-5 flex-none" }),
249
326
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
250
- className: "font-semibold text-zinc-700 dark:text-zinc-300",
327
+ className: "clarify-built-with-brand font-semibold",
251
328
  children: "Clarify"
252
329
  })
253
330
  ]
254
331
  });
255
332
  }
256
333
  //#endregion
334
+ //#region source/components/Callout.tsx
335
+ var calloutStyles = {
336
+ info: {
337
+ container: "border-sky-500/20 bg-sky-50/50 text-sky-950 dark:border-sky-400/30 dark:bg-sky-400/5 dark:text-sky-100",
338
+ icon: "text-sky-600 dark:text-sky-400",
339
+ title: "text-sky-900 dark:text-sky-100",
340
+ Icon: lucide_react.Info
341
+ },
342
+ note: {
343
+ container: "border-zinc-500/20 bg-zinc-50 text-zinc-900 dark:border-white/10 dark:bg-white/5 dark:text-zinc-200",
344
+ icon: "text-zinc-500 dark:text-zinc-400",
345
+ title: "text-zinc-900 dark:text-white",
346
+ Icon: lucide_react.Info
347
+ },
348
+ tip: {
349
+ container: "border-emerald-500/20 bg-emerald-50/50 text-emerald-950 dark:border-emerald-400/30 dark:bg-emerald-400/5 dark:text-emerald-100",
350
+ icon: "text-emerald-600 dark:text-emerald-400",
351
+ title: "text-emerald-900 dark:text-emerald-100",
352
+ Icon: lucide_react.Lightbulb
353
+ },
354
+ warning: {
355
+ container: "border-amber-500/20 bg-amber-50/70 text-amber-950 dark:border-amber-400/30 dark:bg-amber-400/5 dark:text-amber-100",
356
+ icon: "text-amber-600 dark:text-amber-400",
357
+ title: "text-amber-900 dark:text-amber-100",
358
+ Icon: lucide_react.AlertTriangle
359
+ },
360
+ danger: {
361
+ container: "border-rose-500/20 bg-rose-50/70 text-rose-950 dark:border-rose-400/30 dark:bg-rose-400/5 dark:text-rose-100",
362
+ icon: "text-rose-600 dark:text-rose-400",
363
+ title: "text-rose-900 dark:text-rose-100",
364
+ Icon: lucide_react.XCircle
365
+ },
366
+ success: {
367
+ container: "border-emerald-500/20 bg-emerald-50/50 text-emerald-950 dark:border-emerald-400/30 dark:bg-emerald-400/5 dark:text-emerald-100",
368
+ icon: "text-emerald-600 dark:text-emerald-400",
369
+ title: "text-emerald-900 dark:text-emerald-100",
370
+ Icon: lucide_react.CheckCircle2
371
+ }
372
+ };
373
+ var defaultTitleKeys = {
374
+ info: "callout.info",
375
+ note: "callout.note",
376
+ tip: "callout.tip",
377
+ warning: "callout.warning",
378
+ danger: "callout.danger",
379
+ success: "callout.success"
380
+ };
381
+ function Callout(arg0) {
382
+ const { children, type = "info", title, icon = true, className, ...props } = arg0;
383
+ const t = useBuiltInText();
384
+ const style = calloutStyles[type];
385
+ const Icon = style.Icon;
386
+ const resolvedTitle = title === void 0 ? t(defaultTitleKeys[type]) : title;
387
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
388
+ className: (0, clsx.default)("clarify-callout my-6 flex gap-3 rounded-(--clarify-theme-tokens-radius-xl) border p-4 text-sm/6", style.container, className),
389
+ ...props,
390
+ children: [icon ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
391
+ className: (0, clsx.default)("mt-1 size-4 flex-none", style.icon),
392
+ "aria-hidden": "true"
393
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
394
+ className: "min-w-0 flex-1 *:first:mt-0 *:last:mb-0",
395
+ children: [resolvedTitle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
396
+ className: (0, clsx.default)("mb-1 font-semibold", style.title),
397
+ children: resolvedTitle
398
+ }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
399
+ className: "*:first:mt-0 *:last:mb-0",
400
+ children
401
+ })]
402
+ })]
403
+ });
404
+ }
405
+ //#endregion
406
+ //#region source/components/Card.tsx
407
+ function toPascalCase(value) {
408
+ return value.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join("");
409
+ }
410
+ function CardIcon(arg0) {
411
+ const { name } = arg0;
412
+ if (!name) return null;
413
+ const Icon = lucide_react[toPascalCase(name)];
414
+ if (!Icon) return null;
415
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
416
+ className: "flex size-9 flex-none items-center justify-center rounded-[var(--clarify-theme-tokens-radius-lg)] bg-(--clarify-ui-accent-background) text-(--clarify-ui-accent-text) ring-1 ring-(--clarify-ui-accent-border)",
417
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, {
418
+ className: "size-5",
419
+ "aria-hidden": "true"
420
+ })
421
+ });
422
+ }
423
+ var cardGroupColumnStyles = {
424
+ 1: "grid-cols-1",
425
+ 2: "grid-cols-1 sm:grid-cols-2",
426
+ 3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
427
+ 4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4"
428
+ };
429
+ function CardGroup(arg0) {
430
+ const { children, cols = 2, className } = arg0;
431
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
432
+ className: (0, clsx.default)("not-prose my-10 grid gap-4", cardGroupColumnStyles[cols], className),
433
+ children
434
+ });
435
+ }
436
+ function Card(arg0) {
437
+ const { title, icon, href, children, className, ...props } = arg0;
438
+ const content = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
439
+ className: "flex items-start gap-4",
440
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CardIcon, { name: icon }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
441
+ className: "min-w-0 flex-1",
442
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
443
+ className: "m-0 text-base font-semibold text-[var(--clarify-theme-tokens-colors-foreground)] dark:text-white",
444
+ children: title
445
+ }), children ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
446
+ className: "mt-2 text-sm/6 text-[var(--clarify-theme-tokens-colors-muted)] dark:text-zinc-400 *:m-0",
447
+ children
448
+ }) : null]
449
+ })]
450
+ }), href ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
451
+ className: "absolute inset-0 rounded-[var(--clarify-theme-tokens-radius-xl)]",
452
+ "aria-hidden": "true"
453
+ }) : null] });
454
+ const classes = (0, clsx.default)("group relative block rounded-[var(--clarify-theme-tokens-radius-xl)] border border-[color:var(--clarify-theme-tokens-colors-border)] bg-[var(--clarify-theme-tokens-colors-surface)] p-5 shadow-sm shadow-(--clarify-ui-accent-glow) transition hover:border-(--clarify-ui-accent-border) hover:shadow-md dark:bg-zinc-900/50", className);
455
+ if (!href) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
456
+ className: classes,
457
+ children: content
458
+ });
459
+ if (href.startsWith("/") && !href.startsWith("//")) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
460
+ to: href,
461
+ className: classes,
462
+ ...props,
463
+ children: content
464
+ });
465
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
466
+ href,
467
+ className: classes,
468
+ ...props,
469
+ children: content
470
+ });
471
+ }
472
+ //#endregion
257
473
  //#region source/components/Code.tsx
258
474
  var languageNames = {
259
475
  js: "JavaScript",
@@ -272,10 +488,10 @@ var languageNames = {
272
488
  json: "JSON"
273
489
  };
274
490
  function getPanelTitle(arg0) {
275
- const { title, language } = arg0;
491
+ const { title, language, fallbackTitle = "Code" } = arg0;
276
492
  if (title) return title;
277
493
  if (language && language in languageNames) return languageNames[language];
278
- return "Code";
494
+ return fallbackTitle;
279
495
  }
280
496
  function getNodeText(node) {
281
497
  if (typeof node === "string" || typeof node === "number") return String(node);
@@ -300,6 +516,7 @@ function ClipboardIcon(props) {
300
516
  }
301
517
  function CopyButton(arg0) {
302
518
  const { code } = arg0;
519
+ const t = useBuiltInText();
303
520
  const [copyCount, setCopyCount] = (0, react.useState)(0);
304
521
  const copied = copyCount > 0;
305
522
  (0, react.useEffect)(() => {
@@ -310,7 +527,7 @@ function CopyButton(arg0) {
310
527
  if (!code) return null;
311
528
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
312
529
  type: "button",
313
- className: (0, clsx.default)("clarify-code-copy group/button absolute top-3.5 right-4 overflow-hidden rounded-full py-1 pr-3 pl-2 text-2xs font-medium opacity-0 backdrop-blur-sm transition group-hover:opacity-100 focus:opacity-100", copied ? "bg-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"),
530
+ className: (0, clsx.default)("clarify-code-copy group/button absolute top-3.5 right-4 overflow-hidden rounded-full py-1 pr-3 pl-2 text-2xs font-medium opacity-0 backdrop-blur-sm transition group-hover:opacity-100 focus:opacity-100", copied ? "bg-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-primary)_12%,transparent)] ring-1 ring-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-primary)_24%,transparent)] ring-inset" : "bg-white/5 hover:bg-white/7.5 dark:bg-white/2.5 dark:hover:bg-white/5"),
314
531
  onClick: () => {
315
532
  window.navigator.clipboard.writeText(code).then(() => {
316
533
  setCopyCount((count) => count + 1);
@@ -319,11 +536,11 @@ function CopyButton(arg0) {
319
536
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
320
537
  "aria-hidden": copied,
321
538
  className: (0, clsx.default)("pointer-events-none flex items-center gap-0.5 text-zinc-400 transition duration-300", copied && "-translate-y-1.5 opacity-0"),
322
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClipboardIcon, { className: "h-5 w-5 fill-zinc-500/20 stroke-zinc-500 transition-colors group-hover/button:stroke-zinc-400" }), "Copy"]
539
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClipboardIcon, { className: "h-5 w-5 fill-zinc-500/20 stroke-zinc-500 transition-colors group-hover/button:stroke-zinc-400" }), t("actions.copy")]
323
540
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
324
541
  "aria-hidden": !copied,
325
- className: (0, clsx.default)("pointer-events-none absolute inset-0 flex items-center justify-center text-emerald-400 transition duration-300", !copied && "translate-y-1.5 opacity-0"),
326
- children: "Copied!"
542
+ className: (0, clsx.default)("pointer-events-none absolute inset-0 flex items-center justify-center text-[var(--clarify-theme-tokens-colors-primary)] transition duration-300", !copied && "translate-y-1.5 opacity-0"),
543
+ children: t("actions.copied")
327
544
  })]
328
545
  });
329
546
  }
@@ -334,7 +551,7 @@ function CodePanelHeader(arg0) {
334
551
  className: "clarify-code-panel-header flex h-9 items-center gap-2 border-y border-t-transparent border-b-white/7.5 bg-zinc-900 px-4 dark:border-b-white/5 dark:bg-white/1",
335
552
  children: [
336
553
  tag ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
337
- className: "font-mono text-[0.625rem]/6 font-semibold text-emerald-400",
554
+ className: "font-mono text-[0.625rem]/6 font-semibold text-[var(--clarify-theme-tokens-colors-primary)]",
338
555
  children: tag
339
556
  }) : null,
340
557
  tag && label ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "h-0.5 w-0.5 rounded-full bg-zinc-500" }) : null,
@@ -372,6 +589,7 @@ function CodePanel(arg0) {
372
589
  }
373
590
  function CodeGroupHeader(arg0) {
374
591
  const { title, children, selectedIndex } = arg0;
592
+ const t = useBuiltInText();
375
593
  const hasTabs = react.Children.count(children) > 1;
376
594
  if (!title && !hasTabs) return null;
377
595
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -382,8 +600,11 @@ function CodeGroupHeader(arg0) {
382
600
  }) : null, hasTabs ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.TabList, {
383
601
  className: "clarify-code-tabs -mb-px flex gap-4 text-xs font-medium",
384
602
  children: react.Children.map(children, (child, childIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.Tab, {
385
- className: (0, clsx.default)("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"),
386
- children: getPanelTitle((0, react.isValidElement)(child) ? child.props : {})
603
+ className: (0, clsx.default)("clarify-code-tab border-b py-3 transition data-selected:not-data-focus:outline-hidden", childIndex === selectedIndex ? "border-[var(--clarify-theme-tokens-colors-primary)] text-[var(--clarify-theme-tokens-colors-primary)]" : "border-transparent text-zinc-400 hover:text-zinc-300"),
604
+ children: getPanelTitle({
605
+ ...(0, react.isValidElement)(child) ? child.props : {},
606
+ fallbackTitle: t("actions.code")
607
+ })
387
608
  }))
388
609
  }) : null]
389
610
  });
@@ -444,7 +665,11 @@ function useTabGroupProps(availableLanguages) {
444
665
  var CodeGroupContext = (0, react.createContext)(false);
445
666
  function CodeGroup(arg0) {
446
667
  const { children, title, ...props } = arg0;
447
- const tabGroupProps = useTabGroupProps(react.Children.map(children, (child) => getPanelTitle((0, react.isValidElement)(child) ? child.props : {})) ?? []);
668
+ const t = useBuiltInText();
669
+ const tabGroupProps = useTabGroupProps(react.Children.map(children, (child) => getPanelTitle({
670
+ ...(0, react.isValidElement)(child) ? child.props : {},
671
+ fallbackTitle: t("actions.code")
672
+ })) ?? []);
448
673
  const hasTabs = react.Children.count(children) > 1;
449
674
  const containerClassName = "clarify-code-group my-6 overflow-hidden rounded-2xl bg-zinc-900 shadow-md dark:ring-1 dark:ring-white/10";
450
675
  const header = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeGroupHeader, {
@@ -523,6 +748,7 @@ function FeedbackButton(props) {
523
748
  }
524
749
  var FeedbackForm = (0, react.forwardRef)(function FeedbackForm(arg0, ref) {
525
750
  const { onSubmit, className, ...props } = arg0;
751
+ const t = useBuiltInText();
526
752
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
527
753
  ...props,
528
754
  ref,
@@ -530,18 +756,18 @@ var FeedbackForm = (0, react.forwardRef)(function FeedbackForm(arg0, ref) {
530
756
  className: (0, clsx.default)(className, "clarify-feedback-form absolute inset-0 flex items-center justify-center gap-6 md:justify-start"),
531
757
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
532
758
  className: "text-sm text-zinc-600 dark:text-zinc-400",
533
- children: "Was this page helpful?"
759
+ children: t("feedback.prompt")
534
760
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
535
761
  className: "clarify-feedback-actions group grid h-8 grid-cols-[1fr_1px_1fr] overflow-hidden rounded-full border border-zinc-900/10 dark:border-white/10",
536
762
  children: [
537
763
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackButton, {
538
764
  "data-response": "yes",
539
- children: "Yes"
765
+ children: t("feedback.yes")
540
766
  }),
541
767
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "bg-zinc-900/10 dark:bg-white/10" }),
542
768
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeedbackButton, {
543
769
  "data-response": "no",
544
- children: "No"
770
+ children: t("feedback.no")
545
771
  })
546
772
  ]
547
773
  })]
@@ -549,13 +775,14 @@ var FeedbackForm = (0, react.forwardRef)(function FeedbackForm(arg0, ref) {
549
775
  });
550
776
  var FeedbackThanks = (0, react.forwardRef)(function FeedbackThanks(arg0, ref) {
551
777
  const { className, ...props } = arg0;
778
+ const t = useBuiltInText();
552
779
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
553
780
  ...props,
554
781
  ref,
555
782
  className: (0, clsx.default)(className, "clarify-feedback-thanks absolute inset-0 flex justify-center md:justify-start"),
556
783
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
557
- 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",
558
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CheckIcon, { 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!"]
784
+ className: "flex items-center gap-3 rounded-full bg-(--clarify-ui-accent-background) py-1 pr-3 pl-1.5 text-sm text-(--clarify-ui-accent-text) ring-1 ring-(--clarify-ui-accent-border) ring-inset",
785
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CheckIcon, { className: "h-5 w-5 flex-none fill-(--clarify-ui-accent-text) stroke-white dark:fill-(--clarify-ui-accent-background) dark:stroke-(--clarify-ui-accent-text)" }), t("feedback.thanks")]
559
786
  })
560
787
  });
561
788
  });
@@ -627,7 +854,7 @@ function HeroPattern() {
627
854
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
628
855
  className: "absolute top-0 left-1/2 -ml-152 h-100 w-325 dark:mask-[linear-gradient(white,transparent)]",
629
856
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
630
- 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",
857
+ className: "absolute inset-0 bg-[linear-gradient(to_right,var(--clarify-theme-tokens-colors-primary),var(--clarify-theme-tokens-colors-accent))] opacity-35 mask-[radial-gradient(farthest-side_at_top,white,transparent)] dark:opacity-55",
631
858
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GridPattern, {
632
859
  width: 72,
633
860
  height: 56,
@@ -651,18 +878,6 @@ function HeroPattern() {
651
878
  });
652
879
  }
653
880
  //#endregion
654
- //#region source/context.tsx
655
- var ClarifyConfigContext = (0, react.createContext)(null);
656
- var OpenApisContext = (0, react.createContext)({});
657
- function useClarifyConfig() {
658
- const config = (0, react.useContext)(ClarifyConfigContext);
659
- if (!config) throw new Error("[clarify] useClarifyConfig must be used within a ClarifyConfigContext.Provider");
660
- return config;
661
- }
662
- function useOpenApis() {
663
- return (0, react.useContext)(OpenApisContext);
664
- }
665
- //#endregion
666
881
  //#region source/components/PageFooter.tsx
667
882
  function resolveLocalizedText$1(text, locale, fallbackLocale) {
668
883
  if (typeof text === "string") return text;
@@ -690,7 +905,7 @@ function FooterLink(arg0) {
690
905
  href: external ? link.href : localizeHref$1(link.href, config, locale),
691
906
  target: external ? "_blank" : void 0,
692
907
  rel: external ? "noreferrer" : void 0,
693
- className: "clarify-footer-link text-sm text-zinc-500 no-underline transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white",
908
+ className: "clarify-footer-link no-underline transition",
694
909
  children: resolveLocalizedText$1(link.label, locale, config.i18n?.defaultLocale)
695
910
  });
696
911
  }
@@ -700,7 +915,7 @@ function SocialLink(arg0) {
700
915
  href,
701
916
  target: "_blank",
702
917
  rel: "noreferrer",
703
- 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",
918
+ className: "clarify-footer-social capitalize no-underline transition",
704
919
  children: name
705
920
  });
706
921
  }
@@ -713,11 +928,11 @@ function PageFooter() {
713
928
  const copyright = footer?.copyright ? resolveLocalizedText$1(footer.copyright, locale, config.i18n?.defaultLocale) : void 0;
714
929
  const hasCustomFooter = Boolean(copyright || links.length > 0 || socials.length > 0);
715
930
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("footer", {
716
- className: (0, clsx.default)("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"),
931
+ className: (0, clsx.default)("clarify-page-footer mx-auto mt-16 flex w-full max-w-(--clarify-theme-layout-max-width) flex-col items-end gap-4 border-t border-(--clarify-theme-tokens-colors-border) px-4 py-8 sm:px-6 lg:mt-24 lg:px-5 dark:border-white/10", hasCustomFooter && "sm:flex-row sm:items-center sm:justify-between"),
717
932
  children: [hasCustomFooter ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
718
933
  className: "clarify-footer-content flex flex-col gap-3 text-right sm:text-left",
719
934
  children: [copyright ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
720
- className: "clarify-footer-copyright m-0 text-sm text-zinc-500 dark:text-zinc-400",
935
+ className: "clarify-footer-copyright m-0",
721
936
  children: copyright
722
937
  }) : null, links.length > 0 || socials.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
723
938
  className: "clarify-footer-links flex flex-wrap justify-end gap-x-4 gap-y-2 sm:justify-start",
@@ -737,6 +952,95 @@ function PageFooter() {
737
952
  });
738
953
  }
739
954
  //#endregion
955
+ //#region source/utils/path.ts
956
+ function normalizeRoutePath(path) {
957
+ const [pathname, suffix = ""] = path.split(/([?#].*)/, 2);
958
+ return `${pathname.replace(/^\/+/, "/").replace(/\/+$/, "") || "/"}${suffix}`;
959
+ }
960
+ function isSameRoutePath(a, b) {
961
+ if (!a || !b) return false;
962
+ return normalizeRoutePath(a) === normalizeRoutePath(b);
963
+ }
964
+ //#endregion
965
+ //#region source/components/PageNavigation.tsx
966
+ function flattenNavigation(nodes) {
967
+ return nodes.flatMap((node) => node.children?.length ? flattenNavigation(node.children) : [node]);
968
+ }
969
+ function PageNavigation(arg0) {
970
+ const { navigation, currentRoute } = arg0;
971
+ const t = useBuiltInText();
972
+ if (!currentRoute) return null;
973
+ const pageRoutes = flattenNavigation(navigation);
974
+ const currentIndex = pageRoutes.findIndex((route) => isSameRoutePath(route.path, currentRoute.path));
975
+ if (currentIndex === -1) return null;
976
+ const previous = pageRoutes[currentIndex - 1];
977
+ const next = pageRoutes[currentIndex + 1];
978
+ if (!previous && !next) return null;
979
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("nav", {
980
+ className: "clarify-page-navigation mt-6 grid gap-3 @3xl:grid-cols-2",
981
+ "aria-label": t("navigation.previousNext"),
982
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageNavigationLink, {
983
+ direction: "previous",
984
+ route: previous
985
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageNavigationLink, {
986
+ direction: "next",
987
+ route: next
988
+ })]
989
+ });
990
+ }
991
+ function PageNavigationLink(arg0) {
992
+ const { direction, route } = arg0;
993
+ const t = useBuiltInText();
994
+ if (!route) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "hidden @3xl:block" });
995
+ const isNext = direction === "next";
996
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_router_dom.Link, {
997
+ to: normalizeRoutePath(route.path),
998
+ className: (0, clsx.default)("group flex min-w-0 items-center gap-3 rounded-lg border border-(--clarify-theme-tokens-colors-border) px-4 py-3 no-underline transition hover:border-(--clarify-theme-tokens-colors-primary) hover:bg-(--clarify-theme-tokens-colors-surface) dark:border-white/10 dark:hover:border-(--clarify-theme-tokens-colors-primary) dark:hover:bg-white/2.5", isNext && "@3xl:justify-end @3xl:text-right"),
999
+ children: [
1000
+ !isNext ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronLeft, { className: "h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-muted) transition group-hover:text-(--clarify-theme-tokens-colors-primary)" }) : null,
1001
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1002
+ className: "min-w-0 flex-1",
1003
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1004
+ className: "block text-[0.6875rem] font-medium uppercase tracking-wide text-(--clarify-theme-tokens-colors-muted)",
1005
+ children: isNext ? t("navigation.next") : t("navigation.previous")
1006
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1007
+ className: "mt-0.5 block truncate text-[0.8125rem] font-semibold text-(--clarify-theme-tokens-colors-foreground) dark:text-white",
1008
+ children: route.title
1009
+ })]
1010
+ }),
1011
+ isNext ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronRight, { className: "h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-muted) transition group-hover:text-(--clarify-theme-tokens-colors-primary)" }) : null
1012
+ ]
1013
+ });
1014
+ }
1015
+ //#endregion
1016
+ //#region source/components/SiteLogo.tsx
1017
+ function SiteLogo(arg0) {
1018
+ const { logo, className } = arg0;
1019
+ if (!logo) return null;
1020
+ if (typeof logo === "string") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1021
+ src: logo,
1022
+ alt: "",
1023
+ className: (0, clsx.default)("clarify-logo", className)
1024
+ });
1025
+ const lightLogo = logo.light ?? logo.dark;
1026
+ const darkLogo = logo.dark ?? logo.light;
1027
+ if (!lightLogo || !darkLogo) return null;
1028
+ if (lightLogo === darkLogo) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1029
+ src: lightLogo,
1030
+ alt: "",
1031
+ className: (0, clsx.default)("clarify-logo", className)
1032
+ });
1033
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1034
+ src: lightLogo,
1035
+ alt: "",
1036
+ className: (0, clsx.default)("clarify-logo clarify-logo-light", className, "dark:hidden")
1037
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
1038
+ src: darkLogo,
1039
+ alt: "",
1040
+ className: (0, clsx.default)("clarify-logo clarify-logo-dark", className, "hidden dark:block")
1041
+ })] });
1042
+ }
1043
+ //#endregion
740
1044
  //#region source/components/ThemeProvider.tsx
741
1045
  var ThemeContext = (0, react.createContext)(null);
742
1046
  var storageKey = "clarify:theme";
@@ -815,15 +1119,16 @@ function MoonIcon(props) {
815
1119
  }
816
1120
  function ThemeToggle() {
817
1121
  const { resolvedTheme, setTheme } = useTheme();
1122
+ const t = useBuiltInText();
818
1123
  const otherTheme = resolvedTheme === "dark" ? "light" : "dark";
819
1124
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
820
1125
  type: "button",
821
- className: "clarify-theme-toggle flex size-6 items-center justify-center rounded-md transition hover:bg-zinc-900/5 dark:hover:bg-white/5",
822
- "aria-label": `Switch to ${otherTheme} theme`,
1126
+ className: "clarify-theme-toggle relative flex size-8 items-center justify-center rounded-(--clarify-theme-tokens-radius-md) transition hover:bg-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-foreground)_5%,transparent)] dark:hover:bg-white/5",
1127
+ "aria-label": otherTheme === "dark" ? t("theme.switchToDark") : t("theme.switchToLight"),
823
1128
  onClick: () => setTheme(otherTheme),
824
1129
  children: [
825
1130
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "absolute size-12 pointer-fine:hidden" }),
826
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SunIcon, { className: "h-5 w-5 stroke-zinc-900 dark:hidden" }),
1131
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SunIcon, { className: "h-5 w-5 stroke-(--clarify-theme-tokens-colors-foreground) dark:hidden" }),
827
1132
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MoonIcon, { className: "hidden h-5 w-5 stroke-white dark:block" })
828
1133
  ]
829
1134
  });
@@ -845,11 +1150,11 @@ function ArrowIcon(props) {
845
1150
  });
846
1151
  }
847
1152
  var buttonVariantStyles = {
848
- 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",
849
- 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",
850
- 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",
851
- 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",
852
- text: "text-emerald-500 hover:text-emerald-600 dark:text-emerald-400 dark:hover:text-emerald-500"
1153
+ primary: "rounded-full bg-(--clarify-theme-tokens-colors-foreground) px-3 py-1 text-white hover:opacity-80 dark:bg-(--clarify-theme-tokens-colors-primary)/10 dark:text-(--clarify-theme-tokens-colors-primary) dark:ring-1 dark:ring-inset dark:ring-(--clarify-theme-tokens-colors-primary)/20 dark:hover:opacity-80",
1154
+ secondary: "rounded-full bg-(--clarify-theme-tokens-colors-code-background) px-3 py-1 text-(--clarify-theme-tokens-colors-foreground) hover:opacity-80 dark:bg-zinc-800/40 dark:text-zinc-400 dark:ring-1 dark:ring-inset dark:ring-zinc-800 dark:hover:bg-zinc-800 dark:hover:text-zinc-300",
1155
+ filled: "rounded-full bg-(--clarify-theme-tokens-colors-foreground) px-3 py-1 text-white hover:opacity-80 dark:bg-(--clarify-theme-tokens-colors-primary) dark:hover:opacity-80",
1156
+ outline: "rounded-full px-3 py-1 text-(--clarify-theme-tokens-colors-muted) ring-1 ring-inset ring-(--clarify-theme-tokens-colors-border) hover:bg-[color-mix(in_srgb,var(--clarify-theme-tokens-colors-foreground)_2.5%,transparent)] hover:text-(--clarify-theme-tokens-colors-foreground) dark:text-zinc-400 dark:ring-white/10 dark:hover:bg-white/5 dark:hover:text-white",
1157
+ text: "text-(--clarify-theme-tokens-colors-primary) hover:opacity-80 dark:text-(--clarify-theme-tokens-colors-primary) dark:hover:opacity-80"
853
1158
  };
854
1159
  function Button(arg0) {
855
1160
  const { variant = "primary", className, children, arrow, ...props } = arg0;
@@ -893,8 +1198,8 @@ var tagColorStyles = {
893
1198
  medium: "bg-rose-50 text-red-500 ring-rose-200 dark:bg-rose-400/10 dark:text-rose-400 dark:ring-rose-500/20"
894
1199
  },
895
1200
  zinc: {
896
- small: "text-zinc-400 dark:text-zinc-500",
897
- medium: "bg-zinc-50 text-zinc-500 ring-zinc-200 dark:bg-zinc-400/10 dark:text-zinc-400 dark:ring-zinc-500/20"
1201
+ small: "text-(--clarify-theme-tokens-colors-muted) dark:text-zinc-500",
1202
+ 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"
898
1203
  }
899
1204
  };
900
1205
  var tagValueColorMap = {
@@ -909,7 +1214,7 @@ function Tag(arg0) {
909
1214
  const value = typeof children === "string" ? children.toUpperCase() : "";
910
1215
  const resolvedColor = color ?? tagValueColorMap[value] ?? "emerald";
911
1216
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
912
- className: (0, clsx.default)("clarify-tag font-mono text-[0.625rem]/6 font-semibold", tagVariantStyles[variant], tagColorStyles[resolvedColor][variant]),
1217
+ className: (0, clsx.default)("clarify-tag font-mono text-[0.625rem]/6 font-bold", tagVariantStyles[variant], tagColorStyles[resolvedColor][variant]),
913
1218
  children
914
1219
  });
915
1220
  }
@@ -920,10 +1225,10 @@ function Logo(props) {
920
1225
  ...props,
921
1226
  className: (0, clsx.default)("clarify-logo", props.className),
922
1227
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
923
- className: "fill-emerald-400",
1228
+ className: "fill-(--clarify-theme-tokens-colors-primary)",
924
1229
  d: "M16 8a5 5 0 0 0-5-5H5a5 5 0 0 0-5 5v13.927a1 1 0 0 0 1.623.782l3.684-2.93a4 4 0 0 1 2.49-.87H11a5 5 0 0 0 5-5V8Z"
925
1230
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
926
- className: "fill-zinc-900 dark:fill-white",
1231
+ className: "fill-(--clarify-theme-tokens-colors-foreground) dark:fill-white",
927
1232
  d: "M26.538 18h2.654v-3.999h2.576c2.672 0 4.456-1.723 4.456-4.333V9.65c0-2.61-1.784-4.333-4.456-4.333h-5.23V18Zm4.58-10.582c1.52 0 2.416.8 2.416 2.241v.018c0 1.441-.896 2.25-2.417 2.25h-1.925V7.418h1.925ZM38.051 18h2.566v-5.414c0-1.371.923-2.206 2.382-2.206.396 0 .791.061 1.178.15V8.287a3.843 3.843 0 0 0-.958-.123c-1.257 0-2.136.615-2.443 1.661h-.159V8.323h-2.566V18Zm11.55.202c2.979 0 4.772-1.88 4.772-5.036v-.018c0-3.128-1.82-5.036-4.773-5.036-2.953 0-4.772 1.916-4.772 5.036v.018c0 3.146 1.793 5.036 4.772 5.036Zm0-2.013c-1.372 0-2.145-1.116-2.145-3.023v-.018c0-1.89.782-3.023 2.144-3.023 1.354 0 2.145 1.134 2.145 3.023v.018c0 1.907-.782 3.023-2.145 3.023Zm10.52 1.846c.492 0 .967-.053 1.283-.114v-1.907a6.057 6.057 0 0 1-.755.044c-.87 0-1.24-.387-1.24-1.257v-4.544h1.995V8.323H59.41V6.012h-2.592v2.311h-1.495v1.934h1.495v5.133c0 1.88.949 2.645 3.304 2.645Zm7.287.167c2.98 0 4.772-1.88 4.772-5.036v-.018c0-3.128-1.82-5.036-4.772-5.036-2.954 0-4.773 1.916-4.773 5.036v.018c0 3.146 1.793 5.036 4.773 5.036Zm0-2.013c-1.372 0-2.145-1.116-2.145-3.023v-.018c0-1.89.782-3.023 2.145-3.023 1.353 0 2.144 1.134 2.144 3.023v.018c0 1.907-.782 3.023-2.144 3.023Zm10.767 2.013c2.522 0 4.034-1.353 4.297-3.463l.01-.053h-2.374l-.017.036c-.229.966-.853 1.467-1.908 1.467-1.37 0-2.135-1.08-2.135-3.04v-.018c0-1.934.755-3.006 2.135-3.006 1.099 0 1.74.615 1.908 1.556l.008.017h2.391v-.026c-.228-2.162-1.749-3.56-4.315-3.56-3.033 0-4.738 1.837-4.738 5.019v.017c0 3.217 1.714 5.054 4.738 5.054Zm10.257 0c2.98 0 4.772-1.88 4.772-5.036v-.018c0-3.128-1.82-5.036-4.772-5.036-2.953 0-4.773 1.916-4.773 5.036v.018c0 3.146 1.793 5.036 4.773 5.036Zm0-2.013c-1.371 0-2.145-1.116-2.145-3.023v-.018c0-1.89.782-3.023 2.145-3.023 1.353 0 2.144 1.134 2.144 3.023v.018c0 1.907-.782 3.023-2.144 3.023ZM95.025 18h2.566V4.623h-2.566V18Z"
928
1233
  })]
929
1234
  });
@@ -931,7 +1236,7 @@ function Logo(props) {
931
1236
  function Prose(arg0) {
932
1237
  const { as, className, ...props } = arg0;
933
1238
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(as ?? "div", {
934
- className: (0, clsx.default)(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]"),
1239
+ className: (0, clsx.default)(className, "clarify-prose prose max-w-none dark:prose-invert", "[html_:where(&>*)]:w-full [html_:where(&>*)]:min-w-0 [html_:where(&>*)]:max-w-full"),
935
1240
  ...props
936
1241
  });
937
1242
  }
@@ -975,7 +1280,7 @@ function Anchor(arg0) {
975
1280
  });
976
1281
  }
977
1282
  function Heading(arg0) {
978
- const { children, tag, label, level, anchor = true, ...props } = arg0;
1283
+ const { children, className, tag, label, level, anchor = true, ...props } = arg0;
979
1284
  const resolvedLevel = level ?? 2;
980
1285
  const Component = `h${resolvedLevel}`;
981
1286
  const ref = (0, react.useRef)(null);
@@ -1002,7 +1307,7 @@ function Heading(arg0) {
1002
1307
  label
1003
1308
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
1004
1309
  ref,
1005
- className: (0, clsx.default)("clarify-heading", tag || label ? "mt-2 scroll-mt-32" : "scroll-mt-24"),
1310
+ className: (0, clsx.default)("clarify-heading", tag || label ? "mt-2 scroll-mt-32" : "scroll-mt-24", className),
1006
1311
  ...props,
1007
1312
  children: anchor ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Anchor, {
1008
1313
  id: props.id,
@@ -1048,7 +1353,158 @@ function ApiEndpointCard(arg0) {
1048
1353
  });
1049
1354
  }
1050
1355
  //#endregion
1051
- //#region source/shell/Navigation.tsx
1356
+ //#region source/shell/ContentActions.tsx
1357
+ function resolveContentArtifactUrl(contentArtifactUrl, routePrefix = "/") {
1358
+ if (!routePrefix || routePrefix === "/") return contentArtifactUrl;
1359
+ return `/${routePrefix.replace(/^\/+|\/+$/g, "")}${contentArtifactUrl}`;
1360
+ }
1361
+ function getAbsoluteUrl(path) {
1362
+ if (typeof window === "undefined") return path;
1363
+ return new URL(path, window.location.href).href;
1364
+ }
1365
+ async function copyText(text) {
1366
+ await navigator.clipboard.writeText(text);
1367
+ }
1368
+ function ContentActions(arg0) {
1369
+ const { hasTabs = false, route, routePrefix } = arg0;
1370
+ const t = useBuiltInText();
1371
+ const [copied, setCopied] = (0, react.useState)("idle");
1372
+ if (!route?.contentArtifactUrl) return null;
1373
+ const contentArtifactUrl = resolveContentArtifactUrl(route.contentArtifactUrl, routePrefix);
1374
+ const isOpenApi = route.kind === "openapi";
1375
+ const replacements = { contentType: isOpenApi ? "OpenAPI" : "Markdown" };
1376
+ const viewLabel = isOpenApi ? t("contentActions.viewOpenApi") : t("contentActions.viewMarkdown");
1377
+ const viewDescription = isOpenApi ? t("contentActions.viewOpenApiDescription") : t("contentActions.viewMarkdownDescription");
1378
+ function markCopied(state) {
1379
+ setCopied(state);
1380
+ window.setTimeout(() => setCopied("idle"), 1600);
1381
+ }
1382
+ async function handleCopyContent() {
1383
+ await copyText(await (await fetch(contentArtifactUrl)).text());
1384
+ markCopied("content");
1385
+ }
1386
+ async function handleCopyLink() {
1387
+ await copyText(getAbsoluteUrl(contentArtifactUrl));
1388
+ markCopied("link");
1389
+ }
1390
+ const actions = [{
1391
+ key: "content",
1392
+ label: t("contentActions.copyContent"),
1393
+ description: t("contentActions.copyContentDescription", replacements),
1394
+ icon: lucide_react.Copy,
1395
+ run: handleCopyContent
1396
+ }, {
1397
+ key: "link",
1398
+ label: t("contentActions.copyLink", replacements),
1399
+ description: t("contentActions.copyLinkDescription", replacements),
1400
+ icon: lucide_react.Link2,
1401
+ run: handleCopyLink
1402
+ }];
1403
+ const primaryAction = actions[0];
1404
+ const PrimaryIcon = copied === primaryAction.key ? lucide_react.Check : primaryAction.icon;
1405
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1406
+ className: `clarify-content-actions sticky z-20 flex justify-end py-4 ${hasTabs ? "top-16 lg:top-30" : "top-16"}`,
1407
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.Menu, {
1408
+ as: "div",
1409
+ className: "clarify-content-actions-menu relative inline-flex text-sm font-medium",
1410
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1411
+ className: "clarify-content-actions-group inline-flex overflow-hidden rounded-full border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface)/90 shadow-sm shadow-zinc-900/5 backdrop-blur dark:border-white/10 dark:bg-zinc-900/80 dark:shadow-none",
1412
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1413
+ type: "button",
1414
+ onClick: primaryAction.run,
1415
+ className: "clarify-content-actions-primary clarify-ui-control inline-flex h-8 items-center gap-1.5 px-3 transition",
1416
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(PrimaryIcon, { className: "h-3.5 w-3.5" }), copied === primaryAction.key ? t("actions.copied") : primaryAction.label]
1417
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuButton, {
1418
+ className: "clarify-content-actions-trigger clarify-ui-control inline-flex h-8 w-8 items-center justify-center border-l border-(--clarify-theme-tokens-colors-border) transition dark:border-white/10",
1419
+ "aria-label": t("contentActions.copyOptions"),
1420
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronDown, { className: "h-3.5 w-3.5" })
1421
+ })]
1422
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.MenuItems, {
1423
+ anchor: "bottom end",
1424
+ className: "clarify-content-actions-list clarify-ui-menu z-30 mt-2 w-(--clarify-ui-action-menu-width) origin-top-right rounded-(--clarify-theme-tokens-radius-xl) border border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-surface) p-1.5 shadow-xl shadow-zinc-900/5 transition [--anchor-gap:--spacing(2)] focus:outline-none data-closed:scale-95 data-closed:opacity-0 dark:border-white/10 dark:bg-zinc-900 dark:shadow-none",
1425
+ children: [
1426
+ actions.slice(0, 1).map((action) => {
1427
+ const Icon = action.icon;
1428
+ const isCopied = copied === action.key;
1429
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1430
+ type: "button",
1431
+ onClick: action.run,
1432
+ className: "clarify-content-actions-item clarify-ui-menu-item group flex w-full items-center gap-2 rounded-(--clarify-theme-tokens-radius-lg) px-1.5 py-1.5 text-left transition",
1433
+ children: [
1434
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1435
+ className: "clarify-ui-menu-icon flex shrink-0 rounded-(--clarify-theme-tokens-radius-md) border border-(--clarify-theme-tokens-colors-border) p-1.5 dark:border-white/10",
1436
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: "h-4 w-4" })
1437
+ }),
1438
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1439
+ className: "flex min-w-0 flex-1 flex-col px-1",
1440
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1441
+ className: "clarify-ui-menu-title",
1442
+ children: isCopied ? t("contentActions.copiedContent") : action.label
1443
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1444
+ className: "clarify-ui-menu-description truncate",
1445
+ children: action.description
1446
+ })]
1447
+ }),
1448
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: `h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) transition ${isCopied ? "opacity-100" : "opacity-0"}` })
1449
+ ]
1450
+ }) }, action.key);
1451
+ }),
1452
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
1453
+ href: contentArtifactUrl,
1454
+ target: "_blank",
1455
+ rel: "noreferrer",
1456
+ className: "clarify-content-actions-item clarify-ui-menu-item group flex w-full items-center gap-2 rounded-(--clarify-theme-tokens-radius-lg) px-1.5 py-1.5 text-left no-underline transition",
1457
+ children: [
1458
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1459
+ className: "clarify-ui-menu-icon flex shrink-0 rounded-(--clarify-theme-tokens-radius-md) border border-(--clarify-theme-tokens-colors-border) p-1.5 dark:border-white/10",
1460
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.FileText, { className: "h-4 w-4" })
1461
+ }),
1462
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1463
+ className: "flex min-w-0 flex-1 flex-col px-1",
1464
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1465
+ className: "clarify-ui-menu-title flex items-center gap-1",
1466
+ children: [viewLabel, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ExternalLink, { className: "clarify-ui-menu-icon h-3 w-3" })]
1467
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1468
+ className: "clarify-ui-menu-description truncate",
1469
+ children: viewDescription
1470
+ })]
1471
+ }),
1472
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) opacity-0" })
1473
+ ]
1474
+ }) }),
1475
+ actions.slice(1).map((action) => {
1476
+ const Icon = action.icon;
1477
+ const isCopied = copied === action.key;
1478
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1479
+ type: "button",
1480
+ onClick: action.run,
1481
+ className: "clarify-content-actions-item clarify-ui-menu-item group flex w-full items-center gap-2 rounded-(--clarify-theme-tokens-radius-lg) px-1.5 py-1.5 text-left transition",
1482
+ children: [
1483
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1484
+ className: "clarify-ui-menu-icon flex shrink-0 rounded-(--clarify-theme-tokens-radius-md) border border-(--clarify-theme-tokens-colors-border) p-1.5 dark:border-white/10",
1485
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: "h-4 w-4" })
1486
+ }),
1487
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1488
+ className: "flex min-w-0 flex-1 flex-col px-1",
1489
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1490
+ className: "clarify-ui-menu-title",
1491
+ children: isCopied ? t("contentActions.copiedLink") : action.label
1492
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1493
+ className: "clarify-ui-menu-description truncate",
1494
+ children: action.description
1495
+ })]
1496
+ }),
1497
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: `h-3.5 w-3.5 shrink-0 text-(--clarify-theme-tokens-colors-primary) transition ${isCopied ? "opacity-100" : "opacity-0"}` })
1498
+ ]
1499
+ }) }, action.key);
1500
+ })
1501
+ ]
1502
+ })]
1503
+ })
1504
+ });
1505
+ }
1506
+ //#endregion
1507
+ //#region source/shell/icons.tsx
1052
1508
  function NavigationIcon(arg0) {
1053
1509
  const { name, className } = arg0;
1054
1510
  if (!name) return null;
@@ -1059,6 +1515,8 @@ function NavigationIcon(arg0) {
1059
1515
  "aria-hidden": "true"
1060
1516
  });
1061
1517
  }
1518
+ //#endregion
1519
+ //#region source/shell/Navigation.tsx
1062
1520
  function useInitialValue(value, condition = true) {
1063
1521
  const [initialValue] = (0, react.useState)(value);
1064
1522
  return condition ? initialValue : value;
@@ -1066,11 +1524,11 @@ function useInitialValue(value, condition = true) {
1066
1524
  function normalizePath(path) {
1067
1525
  return path === "" ? "/" : path;
1068
1526
  }
1069
- function navigationToGroups(navigation) {
1527
+ function navigationToGroups(navigation, defaultTitle) {
1070
1528
  return navigation.map((node) => {
1071
1529
  const children = node.children?.length ? node.children : [node];
1072
1530
  return {
1073
- title: node.children?.length ? node.title : "Documentation",
1531
+ title: node.children?.length ? node.title : defaultTitle,
1074
1532
  icon: node.icon,
1075
1533
  links: children.map((child) => ({
1076
1534
  title: child.title,
@@ -1080,18 +1538,6 @@ function navigationToGroups(navigation) {
1080
1538
  };
1081
1539
  });
1082
1540
  }
1083
- function TopLevelNavItem$1(arg0) {
1084
- const { href, children } = arg0;
1085
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
1086
- className: "md:hidden",
1087
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.CloseButton, {
1088
- as: react_router_dom.Link,
1089
- to: href,
1090
- className: "block py-1 text-sm text-zinc-600 transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white",
1091
- children
1092
- })
1093
- });
1094
- }
1095
1541
  var sectionBadgeColorStyles = {
1096
1542
  GET: "text-emerald-500 dark:text-emerald-400",
1097
1543
  POST: "text-sky-500 dark:text-sky-400",
@@ -1105,7 +1551,7 @@ var sectionBadgeColorStyles = {
1105
1551
  function SectionBadge(arg0) {
1106
1552
  const { children } = arg0;
1107
1553
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1108
- className: (0, clsx.default)("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"),
1554
+ className: (0, clsx.default)("clarify-navigation-section-badge inline-flex shrink-0 justify-end font-mono font-semibold uppercase tracking-wide", sectionBadgeColorStyles[children.toUpperCase()] ?? "clarify-ui-menu-description"),
1109
1555
  children
1110
1556
  });
1111
1557
  }
@@ -1118,6 +1564,9 @@ function NavLink(arg0) {
1118
1564
  const targetId = decodeURIComponent(href.slice(hashIndex + 1));
1119
1565
  window.requestAnimationFrame(() => {
1120
1566
  document.getElementById(targetId)?.scrollIntoView();
1567
+ window.requestAnimationFrame(() => {
1568
+ window.dispatchEvent(new Event("scroll"));
1569
+ });
1121
1570
  });
1122
1571
  }
1123
1572
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.CloseButton, {
@@ -1125,7 +1574,7 @@ function NavLink(arg0) {
1125
1574
  to: href,
1126
1575
  "aria-current": active ? "page" : void 0,
1127
1576
  onClick: handleClick,
1128
- className: (0, clsx.default)("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"),
1577
+ className: (0, clsx.default)("clarify-navigation-link flex h-8 items-center justify-between gap-2 pr-3 transition", isAnchorLink ? "clarify-navigation-anchor-link pl-7" : "pl-4"),
1129
1578
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1130
1579
  className: "flex min-w-0 flex-1 items-center gap-2",
1131
1580
  children: [
@@ -1156,7 +1605,7 @@ function VisibleSectionHighlight(arg0) {
1156
1605
  const firstVisibleSectionIndex = Math.max(0, [{ id: "_top" }, ...sections].findIndex((section) => section.id === visibleSections[0]));
1157
1606
  const itemHeight = remToPx(2);
1158
1607
  const height = isPresent ? Math.max(1, visibleSections.length) * itemHeight : itemHeight;
1159
- const top = group.links.findIndex((link) => link.href === pathname) * itemHeight + firstVisibleSectionIndex * itemHeight;
1608
+ const top = group.links.findIndex((link) => isSameRoutePath(link.href, pathname)) * itemHeight + firstVisibleSectionIndex * itemHeight;
1160
1609
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.motion.div, {
1161
1610
  layout: true,
1162
1611
  initial: { opacity: 0 },
@@ -1165,9 +1614,9 @@ function VisibleSectionHighlight(arg0) {
1165
1614
  transition: { delay: .2 }
1166
1615
  },
1167
1616
  exit: { opacity: 0 },
1168
- className: "absolute inset-x-0 top-0 bg-zinc-800/2.5 will-change-transform dark:bg-white/2.5",
1617
+ className: "clarify-navigation-section-highlight absolute inset-x-0 top-0 will-change-transform",
1169
1618
  style: {
1170
- borderRadius: 8,
1619
+ borderRadius: "var(--clarify-theme-tokens-radius-sm)",
1171
1620
  height,
1172
1621
  top
1173
1622
  }
@@ -1176,10 +1625,10 @@ function VisibleSectionHighlight(arg0) {
1176
1625
  function ActivePageMarker(arg0) {
1177
1626
  const { group, pathname } = arg0;
1178
1627
  const itemHeight = remToPx(2);
1179
- const top = remToPx(.25) + group.links.findIndex((link) => link.href === pathname) * itemHeight;
1628
+ const top = remToPx(.25) + group.links.findIndex((link) => isSameRoutePath(link.href, pathname)) * itemHeight;
1180
1629
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.motion.div, {
1181
1630
  layout: true,
1182
- className: "absolute left-2 h-6 w-px bg-emerald-500",
1631
+ className: "absolute left-2 h-6 w-px bg-(--clarify-theme-tokens-colors-primary)",
1183
1632
  initial: { opacity: 0 },
1184
1633
  animate: {
1185
1634
  opacity: 1,
@@ -1192,16 +1641,16 @@ function ActivePageMarker(arg0) {
1192
1641
  function NavigationGroup(arg0) {
1193
1642
  const { group, className } = arg0;
1194
1643
  const isInsideMobileNavigation = useIsInsideMobileNavigation();
1195
- const [pathname, sections] = useInitialValue([(0, react_router_dom.useLocation)().pathname, useSectionStore((s) => s.sections)], isInsideMobileNavigation);
1196
- const isActiveGroup = group.links.findIndex((link) => link.href === pathname) !== -1;
1644
+ const [pathname, sections] = useInitialValue([normalizeRoutePath((0, react_router_dom.useLocation)().pathname), useSectionStore((s) => s.sections)], isInsideMobileNavigation);
1645
+ const isActiveGroup = group.links.findIndex((link) => isSameRoutePath(link.href, pathname)) !== -1;
1197
1646
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
1198
1647
  className: (0, clsx.default)("clarify-navigation-group relative mt-6", className),
1199
1648
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(framer_motion.motion.h2, {
1200
1649
  layout: "position",
1201
- className: "clarify-navigation-group-title flex items-center gap-2 text-xs font-semibold text-zinc-900 dark:text-white",
1650
+ className: "clarify-navigation-group-title flex items-center gap-2",
1202
1651
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavigationIcon, {
1203
1652
  name: group.icon,
1204
- className: "h-3.5 w-3.5"
1653
+ className: "clarify-navigation-group-title-icon h-3.5 w-3.5"
1205
1654
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: group.title })]
1206
1655
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1207
1656
  className: "relative mt-3 pl-2",
@@ -1215,7 +1664,7 @@ function NavigationGroup(arg0) {
1215
1664
  }),
1216
1665
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.motion.div, {
1217
1666
  layout: true,
1218
- className: "absolute inset-y-0 left-2 w-px bg-zinc-900/10 dark:bg-white/5"
1667
+ className: "absolute inset-y-0 left-2 w-px bg-(--clarify-theme-tokens-colors-border) dark:bg-white/5"
1219
1668
  }),
1220
1669
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.AnimatePresence, {
1221
1670
  initial: false,
@@ -1227,38 +1676,41 @@ function NavigationGroup(arg0) {
1227
1676
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
1228
1677
  role: "list",
1229
1678
  className: "border-l border-transparent",
1230
- children: group.links.map((link) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(framer_motion.motion.li, {
1231
- layout: "position",
1232
- className: "relative",
1233
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavLink, {
1234
- href: link.href,
1235
- icon: link.icon,
1236
- active: link.href === pathname,
1237
- children: link.title
1238
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.AnimatePresence, {
1239
- mode: "popLayout",
1240
- initial: false,
1241
- children: link.href === pathname && sections.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.motion.ul, {
1242
- role: "list",
1243
- initial: { opacity: 0 },
1244
- animate: {
1245
- opacity: 1,
1246
- transition: { delay: .1 }
1247
- },
1248
- exit: {
1249
- opacity: 0,
1250
- transition: { duration: .15 }
1251
- },
1252
- children: sections.map((section) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavLink, {
1253
- href: `${link.href}#${section.id}`,
1254
- badge: section.badge,
1255
- tags: section.tags,
1256
- isAnchorLink: true,
1257
- children: section.title
1258
- }) }, section.id))
1259
- }) : null
1260
- })]
1261
- }, link.href))
1679
+ children: group.links.map((link) => {
1680
+ const active = isSameRoutePath(link.href, pathname);
1681
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(framer_motion.motion.li, {
1682
+ layout: "position",
1683
+ className: "relative",
1684
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavLink, {
1685
+ href: link.href,
1686
+ icon: link.icon,
1687
+ active,
1688
+ children: link.title
1689
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.AnimatePresence, {
1690
+ mode: "popLayout",
1691
+ initial: false,
1692
+ children: active && sections.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.motion.ul, {
1693
+ role: "list",
1694
+ initial: { opacity: 0 },
1695
+ animate: {
1696
+ opacity: 1,
1697
+ transition: { delay: .1 }
1698
+ },
1699
+ exit: {
1700
+ opacity: 0,
1701
+ transition: { duration: .15 }
1702
+ },
1703
+ children: sections.map((section) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavLink, {
1704
+ href: `${link.href}#${section.id}`,
1705
+ badge: section.badge,
1706
+ tags: section.tags,
1707
+ isAnchorLink: true,
1708
+ children: section.title
1709
+ }) }, section.id))
1710
+ }) : null
1711
+ })]
1712
+ }, link.href);
1713
+ })
1262
1714
  })
1263
1715
  ]
1264
1716
  })]
@@ -1266,19 +1718,16 @@ function NavigationGroup(arg0) {
1266
1718
  }
1267
1719
  function Navigation(arg0) {
1268
1720
  const { navigation, className } = arg0;
1269
- const groups = navigationToGroups(navigation);
1721
+ const groups = navigationToGroups(navigation, useBuiltInText()("navigation.documentation"));
1270
1722
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
1271
1723
  className: (0, clsx.default)("clarify-navigation", className),
1272
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
1724
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
1273
1725
  role: "list",
1274
1726
  className: "clarify-navigation-list",
1275
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TopLevelNavItem$1, {
1276
- href: "/",
1277
- children: "Home"
1278
- }), groups.map((group, groupIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavigationGroup, {
1727
+ children: groups.map((group, groupIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavigationGroup, {
1279
1728
  group,
1280
- className: groupIndex === 0 ? "md:mt-0" : ""
1281
- }, group.title))]
1729
+ className: groupIndex === 0 ? "mt-0" : ""
1730
+ }, group.title))
1282
1731
  })
1283
1732
  });
1284
1733
  }
@@ -1305,8 +1754,84 @@ function XIcon(props) {
1305
1754
  });
1306
1755
  }
1307
1756
  var IsInsideMobileNavigationContext = (0, react.createContext)(false);
1757
+ function hasPath$2(nodes, pathname) {
1758
+ return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath$2(node.children ?? [], pathname));
1759
+ }
1760
+ function isActiveTab$1(tab, pathname) {
1761
+ return isSameRoutePath(tab.path, pathname) || hasPath$2(tab.children, pathname);
1762
+ }
1763
+ function MobileTabsSelect(arg0) {
1764
+ const { tabs } = arg0;
1765
+ const pathname = normalizeRoutePath((0, react_router_dom.useLocation)().pathname);
1766
+ const { close } = useMobileNavigationStore();
1767
+ if (!tabs?.length) return null;
1768
+ const activeTab = tabs.find((tab) => isActiveTab$1(tab, pathname)) ?? tabs[0];
1769
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.Menu, {
1770
+ as: "div",
1771
+ className: "clarify-mobile-tabs-select mb-6",
1772
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.MenuButton, {
1773
+ 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",
1774
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1775
+ className: "flex min-w-0 items-center gap-2",
1776
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavigationIcon, {
1777
+ name: activeTab.icon,
1778
+ className: "h-4 w-4 shrink-0 text-(--clarify-theme-tokens-colors-primary)"
1779
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1780
+ className: "truncate tracking-[-0.01em]",
1781
+ children: activeTab.title
1782
+ })]
1783
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1784
+ width: "8",
1785
+ height: "24",
1786
+ viewBox: "0 -9 3 24",
1787
+ "aria-hidden": "true",
1788
+ className: "shrink-0 overflow-visible text-(--clarify-theme-tokens-colors-muted) transition-transform group-aria-expanded:rotate-180",
1789
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1790
+ d: "M0 0L3 3L0 6",
1791
+ fill: "none",
1792
+ stroke: "currentColor",
1793
+ strokeWidth: "1.5",
1794
+ strokeLinecap: "round"
1795
+ })
1796
+ })]
1797
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItems, {
1798
+ 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",
1799
+ children: tabs.map((tab) => {
1800
+ const active = isActiveTab$1(tab, pathname);
1801
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_router_dom.Link, {
1802
+ to: tab.path,
1803
+ onClick: close,
1804
+ className: (0, clsx.default)("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"),
1805
+ "aria-current": active ? "page" : void 0,
1806
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1807
+ className: "flex min-w-0 items-start gap-2",
1808
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavigationIcon, {
1809
+ name: tab.icon,
1810
+ className: "mt-0.5 h-4 w-4 shrink-0"
1811
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1812
+ className: "min-w-0 whitespace-normal wrap-anywhere font-medium leading-5",
1813
+ children: tab.title
1814
+ })]
1815
+ }), active ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1816
+ viewBox: "0 0 20 20",
1817
+ fill: "none",
1818
+ "aria-hidden": "true",
1819
+ className: "mt-0.5 h-4 w-4 shrink-0",
1820
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1821
+ d: "m5 10 3 3 7-7",
1822
+ stroke: "currentColor",
1823
+ strokeWidth: "1.8",
1824
+ strokeLinecap: "round",
1825
+ strokeLinejoin: "round"
1826
+ })
1827
+ }) : null]
1828
+ }) }, `${tab.title}-${tab.path}`);
1829
+ })
1830
+ })]
1831
+ });
1832
+ }
1308
1833
  function MobileNavigationDialog(arg0) {
1309
- const { config, isOpen, navigation, routes, currentLocale, currentRoute, close } = arg0;
1834
+ const { config, isOpen, navigation, tabs, routes, currentLocale, currentRoute, close } = arg0;
1310
1835
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.Dialog, {
1311
1836
  transition: true,
1312
1837
  open: isOpen,
@@ -1314,18 +1839,19 @@ function MobileNavigationDialog(arg0) {
1314
1839
  className: "clarify-mobile-navigation-dialog fixed inset-0 z-50 lg:hidden",
1315
1840
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.DialogBackdrop, {
1316
1841
  transition: true,
1317
- 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"
1842
+ 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"
1318
1843
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.DialogPanel, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.TransitionChild, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Header, {
1319
1844
  config,
1320
1845
  navigation,
1846
+ tabs,
1321
1847
  routes,
1322
1848
  currentLocale,
1323
1849
  currentRoute,
1324
1850
  className: "data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in"
1325
- }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.TransitionChild, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.motion.div, {
1851
+ }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.TransitionChild, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(framer_motion.motion.div, {
1326
1852
  layoutScroll: true,
1327
- 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",
1328
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Navigation, { navigation })
1853
+ 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",
1854
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileTabsSelect, { tabs }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Navigation, { navigation })]
1329
1855
  }) })] })]
1330
1856
  });
1331
1857
  }
@@ -1339,23 +1865,25 @@ var useMobileNavigationStore = (0, zustand.create)()((set) => ({
1339
1865
  toggle: () => set((state) => ({ isOpen: !state.isOpen }))
1340
1866
  }));
1341
1867
  function MobileNavigation(arg0) {
1342
- const { config, navigation, routes, currentLocale, currentRoute } = arg0;
1868
+ const { config, navigation, tabs, routes, currentLocale, currentRoute } = arg0;
1343
1869
  const isInsideMobileNavigation = useIsInsideMobileNavigation();
1344
1870
  const { isOpen, toggle, close } = useMobileNavigationStore();
1871
+ const t = useBuiltInText();
1345
1872
  const ToggleIcon = isOpen ? XIcon : MenuIcon;
1346
1873
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(IsInsideMobileNavigationContext.Provider, {
1347
1874
  value: true,
1348
1875
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1349
1876
  type: "button",
1350
- 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",
1351
- "aria-label": "Toggle navigation",
1877
+ className: "clarify-mobile-navigation-button clarify-ui-icon-button relative flex size-6 items-center justify-center rounded-(--clarify-theme-tokens-radius-md) transition",
1878
+ "aria-label": t("navigation.toggle"),
1352
1879
  onClick: toggle,
1353
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "absolute size-12 pointer-fine:hidden" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleIcon, { className: "w-2.5 stroke-zinc-900 dark:stroke-white" })]
1880
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "absolute size-12 pointer-fine:hidden" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleIcon, { className: "w-2.5 stroke-(--clarify-theme-tokens-colors-foreground) dark:stroke-white" })]
1354
1881
  }), !isInsideMobileNavigation ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Suspense, {
1355
1882
  fallback: null,
1356
1883
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileNavigationDialog, {
1357
1884
  config,
1358
1885
  navigation,
1886
+ tabs,
1359
1887
  routes,
1360
1888
  currentLocale,
1361
1889
  currentRoute,
@@ -1436,7 +1964,7 @@ function HighlightQuery(arg0) {
1436
1964
  const { text, query } = arg0;
1437
1965
  if (!query) return text;
1438
1966
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: text.split(new RegExp(`(${escapeRegExp(query)})`, "ig")).map((part, index) => part.toLowerCase() === query.toLowerCase() ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("mark", {
1439
- className: "bg-transparent text-emerald-500 underline",
1967
+ className: "bg-transparent text-(--clarify-theme-tokens-colors-primary) underline",
1440
1968
  children: part
1441
1969
  }, index) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: part }, index)) });
1442
1970
  }
@@ -1446,25 +1974,25 @@ function SearchResult(arg0) {
1446
1974
  const hierarchy = [result.sectionTitle, result.pageTitle].filter((value) => typeof value === "string");
1447
1975
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
1448
1976
  id,
1449
- className: (0, clsx.default)("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"),
1977
+ className: (0, clsx.default)("clarify-search-result group block cursor-default px-4 py-3", active && "clarify-search-result-active"),
1450
1978
  "aria-selected": active,
1451
1979
  onMouseDown: (event) => {
1452
1980
  event.preventDefault();
1453
1981
  onSelect();
1454
1982
  },
1455
1983
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1456
- className: "text-sm font-medium text-zinc-900 group-aria-selected:text-emerald-500 dark:text-white",
1984
+ className: "clarify-search-result-title",
1457
1985
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightQuery, {
1458
1986
  text: result.title,
1459
1987
  query
1460
1988
  })
1461
1989
  }), hierarchy.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1462
- className: "mt-1 truncate text-2xs whitespace-nowrap text-zinc-500",
1990
+ className: "clarify-search-result-hierarchy mt-1 truncate whitespace-nowrap",
1463
1991
  children: hierarchy.map((item, itemIndex, items) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightQuery, {
1464
1992
  text: item,
1465
1993
  query
1466
1994
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1467
- className: itemIndex === items.length - 1 ? "sr-only" : "mx-2 text-zinc-300 dark:text-zinc-700",
1995
+ className: itemIndex === items.length - 1 ? "sr-only" : "clarify-search-result-separator mx-2",
1468
1996
  children: "/"
1469
1997
  })] }, `${item}-${itemIndex}`))
1470
1998
  }) : null]
@@ -1472,9 +2000,10 @@ function SearchResult(arg0) {
1472
2000
  }
1473
2001
  var SearchInput = (0, react.forwardRef)(function SearchInput(arg0, inputRef) {
1474
2002
  const { query, setQuery, onClose, onSubmit, activeDescendantId } = arg0;
2003
+ const t = useBuiltInText();
1475
2004
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1476
2005
  className: "clarify-search-input group relative flex h-12",
1477
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SearchIcon, { className: "pointer-events-none absolute top-0 left-3 h-full w-5 stroke-zinc-500" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
2006
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SearchIcon, { className: "pointer-events-none absolute top-0 left-3 h-full w-5 stroke-(--clarify-theme-tokens-colors-muted)" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1478
2007
  ref: inputRef,
1479
2008
  "data-autofocus": true,
1480
2009
  role: "combobox",
@@ -1491,13 +2020,14 @@ var SearchInput = (0, react.forwardRef)(function SearchInput(arg0, inputRef) {
1491
2020
  onSubmit();
1492
2021
  }
1493
2022
  },
1494
- placeholder: "Find something...",
1495
- 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"
2023
+ placeholder: t("search.placeholder"),
2024
+ 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"
1496
2025
  })]
1497
2026
  });
1498
2027
  });
1499
2028
  function SearchDialog(arg0) {
1500
2029
  const { open, setOpen, routes, navigation, className, onNavigate = () => {} } = arg0;
2030
+ const t = useBuiltInText();
1501
2031
  const navigate = (0, react_router_dom.useNavigate)();
1502
2032
  const location = (0, react_router_dom.useLocation)();
1503
2033
  const inputRef = (0, react.useRef)(null);
@@ -1548,12 +2078,12 @@ function SearchDialog(arg0) {
1548
2078
  className: (0, clsx.default)("clarify-search-dialog fixed inset-0 z-50", className),
1549
2079
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.DialogBackdrop, {
1550
2080
  transition: true,
1551
- 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"
2081
+ 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"
1552
2082
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1553
2083
  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]",
1554
2084
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.DialogPanel, {
1555
2085
  transition: true,
1556
- 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",
2086
+ 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",
1557
2087
  onKeyDown: (event) => {
1558
2088
  if (event.key === "ArrowDown") {
1559
2089
  event.preventDefault();
@@ -1571,24 +2101,12 @@ function SearchDialog(arg0) {
1571
2101
  onClose: closeDialog,
1572
2102
  onSubmit: () => selectResult()
1573
2103
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1574
- className: "border-t border-zinc-200 bg-white empty:hidden dark:border-zinc-100/5 dark:bg-white/2.5",
2104
+ 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",
1575
2105
  children: [query && results.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1576
2106
  className: "p-6 text-center",
1577
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NoResultsIcon, { className: "mx-auto h-5 w-5 stroke-zinc-900 dark:stroke-zinc-600" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
1578
- className: "mt-2 text-xs text-zinc-700 dark:text-zinc-400",
1579
- children: [
1580
- "Nothing found for",
1581
- " ",
1582
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", {
1583
- className: "font-semibold wrap-break-word text-zinc-900 dark:text-white",
1584
- children: [
1585
- "‘",
1586
- query,
1587
- "’"
1588
- ]
1589
- }),
1590
- "."
1591
- ]
2107
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NoResultsIcon, { className: "mx-auto h-5 w-5 stroke-(--clarify-theme-tokens-colors-foreground) dark:stroke-zinc-600" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2108
+ className: "mt-2 text-xs text-(--clarify-theme-tokens-colors-muted) dark:text-zinc-400",
2109
+ children: t("search.noResults", { query })
1592
2110
  })]
1593
2111
  }) : null, results.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
1594
2112
  id: "clarify-search-results",
@@ -1628,19 +2146,20 @@ function getModifierKey() {
1628
2146
  }
1629
2147
  function Search(arg0) {
1630
2148
  const { routes, navigation } = arg0;
2149
+ const t = useBuiltInText();
1631
2150
  const modifierKey = getModifierKey();
1632
2151
  const { buttonProps, dialogProps } = useSearchProps();
1633
2152
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1634
- className: "clarify-search hidden lg:block lg:max-w-md lg:flex-auto",
2153
+ className: "clarify-search hidden w-80 max-w-[36vw] lg:block",
1635
2154
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1636
2155
  type: "button",
1637
- 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",
2156
+ 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",
1638
2157
  ...buttonProps,
1639
2158
  children: [
1640
2159
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SearchIcon, { className: "h-5 w-5 stroke-current" }),
1641
- "Find something...",
2160
+ t("search.button"),
1642
2161
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("kbd", {
1643
- className: "ml-auto text-2xs text-zinc-400 dark:text-zinc-500",
2162
+ 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",
1644
2163
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("kbd", {
1645
2164
  className: "font-sans",
1646
2165
  children: modifierKey
@@ -1663,15 +2182,16 @@ function Search(arg0) {
1663
2182
  }
1664
2183
  function MobileSearch(arg0) {
1665
2184
  const { routes, navigation, onNavigate } = arg0;
2185
+ const t = useBuiltInText();
1666
2186
  const { buttonProps, dialogProps } = useSearchProps();
1667
2187
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1668
2188
  className: "clarify-mobile-search contents lg:hidden",
1669
2189
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1670
2190
  type: "button",
1671
- 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",
1672
- "aria-label": "Find something...",
2191
+ 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",
2192
+ "aria-label": t("search.placeholder"),
1673
2193
  ...buttonProps,
1674
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "absolute size-12 pointer-fine:hidden" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SearchIcon, { className: "h-5 w-5 stroke-zinc-900 dark:stroke-white" })]
2194
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "absolute size-12 pointer-fine:hidden" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SearchIcon, { className: "h-5 w-5 stroke-(--clarify-theme-tokens-colors-foreground) dark:stroke-white" })]
1675
2195
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Suspense, {
1676
2196
  fallback: null,
1677
2197
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SearchDialog, {
@@ -1716,6 +2236,7 @@ function LanguageIcon(props) {
1716
2236
  }
1717
2237
  function LanguageSwitcher(arg0) {
1718
2238
  const { config, currentLocale, currentRoute } = arg0;
2239
+ const t = useBuiltInText();
1719
2240
  const location = (0, react_router_dom.useLocation)();
1720
2241
  const i18n = config.i18n;
1721
2242
  if (!i18n || i18n.locales.length < 2) return null;
@@ -1726,8 +2247,8 @@ function LanguageSwitcher(arg0) {
1726
2247
  as: "div",
1727
2248
  className: "clarify-language-switcher relative",
1728
2249
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.MenuButton, {
1729
- 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",
1730
- "aria-label": "Switch language",
2250
+ 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",
2251
+ "aria-label": t("language.switch"),
1731
2252
  children: [
1732
2253
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "absolute size-12 pointer-fine:hidden" }),
1733
2254
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LanguageIcon, { className: "h-5 w-5 stroke-current" }),
@@ -1738,19 +2259,19 @@ function LanguageSwitcher(arg0) {
1738
2259
  ]
1739
2260
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItems, {
1740
2261
  transition: true,
1741
- 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",
2262
+ 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",
1742
2263
  children: i18n.locales.flatMap((locale) => {
1743
2264
  const localizedPath = localizedRoutePath(config, locale.code, currentRoute);
1744
2265
  if (!localizedPath) return [];
1745
2266
  const selected = locale.code === selectedLocale;
1746
2267
  return [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItem, { children: ({ focus }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_router_dom.Link, {
1747
2268
  to: `${localizedPath}${suffix}`,
1748
- className: (0, clsx.default)("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"),
2269
+ className: (0, clsx.default)("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"),
1749
2270
  "aria-current": selected ? "true" : void 0,
1750
2271
  lang: locale.code,
1751
2272
  dir: locale.dir,
1752
2273
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: locale.label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1753
- className: "text-xs text-zinc-400 dark:text-zinc-500",
2274
+ className: "clarify-ui-menu-code",
1754
2275
  children: locale.code
1755
2276
  })]
1756
2277
  }) }, locale.code)];
@@ -1762,95 +2283,189 @@ function TopLevelNavItem(arg0) {
1762
2283
  const { href, children } = arg0;
1763
2284
  if (isExternalHref(href)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1764
2285
  href,
1765
- className: "text-sm/5 text-zinc-600 transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white",
2286
+ className: "clarify-ui-top-link transition",
1766
2287
  target: "_blank",
1767
2288
  rel: "noreferrer",
1768
2289
  children
1769
2290
  }) });
1770
2291
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
1771
2292
  to: href,
1772
- className: "text-sm/5 text-zinc-600 transition hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-white",
2293
+ className: "clarify-ui-top-link transition",
1773
2294
  children
1774
2295
  }) });
1775
2296
  }
2297
+ function MobileNavbarMenu(arg0) {
2298
+ const { links, config, currentLocale } = arg0;
2299
+ const t = useBuiltInText();
2300
+ if (!links?.length) return null;
2301
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.Menu, {
2302
+ as: "div",
2303
+ className: "clarify-mobile-navbar-menu relative md:hidden",
2304
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.MenuButton, {
2305
+ className: "clarify-mobile-navbar-menu-button clarify-ui-control relative flex size-8 items-center justify-center rounded-(--clarify-theme-tokens-radius-md) transition",
2306
+ "aria-label": t("navbar.openLinks"),
2307
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "absolute size-12 pointer-fine:hidden" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.MoreHorizontal, { className: "h-5 w-5" })]
2308
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItems, {
2309
+ transition: true,
2310
+ anchor: "bottom end",
2311
+ 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",
2312
+ children: links.map((link) => {
2313
+ const label = resolveLocalizedText(link.label, currentLocale, config.i18n?.defaultLocale);
2314
+ const href = localizeHref(link.href, config, currentLocale);
2315
+ const external = isExternalHref(href);
2316
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_headlessui_react.MenuItem, { children: ({ focus }) => {
2317
+ const className = (0, clsx.default)("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");
2318
+ return external ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
2319
+ href,
2320
+ target: "_blank",
2321
+ rel: "noreferrer",
2322
+ className,
2323
+ children: label
2324
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Link, {
2325
+ to: href,
2326
+ className,
2327
+ children: label
2328
+ });
2329
+ } }, link.href);
2330
+ })
2331
+ })]
2332
+ });
2333
+ }
2334
+ function hasPath$1(nodes, pathname) {
2335
+ return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath$1(node.children ?? [], pathname));
2336
+ }
2337
+ function isActiveTab(tab, pathname) {
2338
+ return isSameRoutePath(tab.path, pathname) || hasPath$1(tab.children, pathname);
2339
+ }
2340
+ function ProductTabs(arg0) {
2341
+ const { tabs } = arg0;
2342
+ const t = useBuiltInText();
2343
+ const pathname = normalizeRoutePath((0, react_router_dom.useLocation)().pathname);
2344
+ if (!tabs?.length) return null;
2345
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2346
+ className: "clarify-product-tabs hidden h-14 border-t border-(--clarify-theme-tokens-colors-border) lg:block dark:border-white/10",
2347
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
2348
+ 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",
2349
+ "aria-label": t("navbar.sections"),
2350
+ children: tabs.map((tab) => {
2351
+ const active = isActiveTab(tab, pathname);
2352
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_router_dom.Link, {
2353
+ to: tab.path,
2354
+ "aria-current": active ? "page" : void 0,
2355
+ className: (0, clsx.default)("clarify-product-tab clarify-ui-tab relative inline-flex shrink-0 items-center gap-2 px-0 transition", active && "clarify-ui-tab-active"),
2356
+ children: [
2357
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavigationIcon, {
2358
+ name: tab.icon,
2359
+ className: "h-4 w-4"
2360
+ }),
2361
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: tab.title }),
2362
+ active ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.motion.span, {
2363
+ layoutId: "clarify-product-tab-indicator",
2364
+ className: "absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-(--clarify-theme-tokens-colors-foreground) dark:bg-white",
2365
+ transition: {
2366
+ type: "spring",
2367
+ stiffness: 420,
2368
+ damping: 36
2369
+ }
2370
+ }) : null
2371
+ ]
2372
+ }, `${tab.title}-${tab.path}`);
2373
+ })
2374
+ })
2375
+ });
2376
+ }
1776
2377
  var Header = (0, react.forwardRef)(function Header(arg0, ref) {
1777
- const { config, navigation, routes, currentLocale, currentRoute, className, ...props } = arg0;
2378
+ const { config, navigation, tabs, routes, currentLocale, currentRoute, className, ...props } = arg0;
2379
+ const t = useBuiltInText();
1778
2380
  const { isOpen: mobileNavIsOpen } = useMobileNavigationStore();
1779
2381
  const isInsideMobileNavigation = useIsInsideMobileNavigation();
1780
2382
  const { scrollY } = (0, framer_motion.useScroll)();
1781
- const bgOpacityLight = (0, framer_motion.useTransform)(scrollY, [0, 72], ["50%", "90%"]);
1782
- const bgOpacityDark = (0, framer_motion.useTransform)(scrollY, [0, 72], ["20%", "80%"]);
1783
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(framer_motion.motion.div, {
2383
+ const bgOpacityLight = (0, framer_motion.useTransform)(scrollY, [0, 72], ["70%", "95%"]);
2384
+ const bgOpacityDark = (0, framer_motion.useTransform)(scrollY, [0, 72], ["60%", "92%"]);
2385
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(framer_motion.motion.header, {
1784
2386
  ...props,
1785
2387
  ref,
1786
- className: (0, clsx.default)(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)"),
2388
+ className: (0, clsx.default)(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"),
1787
2389
  style: {
1788
2390
  "--bg-opacity-light": bgOpacityLight,
1789
2391
  "--bg-opacity-dark": bgOpacityDark
1790
2392
  },
1791
- children: [
1792
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: (0, clsx.default)("absolute inset-x-0 top-full h-px transition", (isInsideMobileNavigation || !mobileNavIsOpen) && "bg-zinc-900/7.5 dark:bg-white/7.5") }),
1793
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "hidden lg:block" }),
1794
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1795
- className: "clarify-mobile-brand flex items-center gap-5 lg:hidden",
1796
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileNavigation, {
1797
- config,
1798
- navigation,
1799
- routes,
1800
- currentLocale,
1801
- currentRoute
1802
- }), config.logo ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.CloseButton, {
1803
- as: react_router_dom.Link,
1804
- to: localizeHref("/", config, currentLocale),
1805
- "aria-label": "Home",
1806
- className: "clarify-brand flex items-center gap-2 no-underline",
1807
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SiteLogo, {
1808
- logo: config.logo,
1809
- className: "h-6 w-6"
1810
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1811
- className: "sr-only",
1812
- children: config.title
2393
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2394
+ className: (0, clsx.default)("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"),
2395
+ children: [
2396
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2397
+ className: "clarify-header-left flex min-w-0 items-center gap-5",
2398
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2399
+ className: "clarify-mobile-brand flex items-center gap-5 lg:hidden",
2400
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileNavigation, {
2401
+ config,
2402
+ navigation,
2403
+ tabs,
2404
+ routes,
2405
+ currentLocale,
2406
+ currentRoute
2407
+ })
2408
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.CloseButton, {
2409
+ as: react_router_dom.Link,
2410
+ to: localizeHref("/", config, currentLocale),
2411
+ "aria-label": t("navbar.home"),
2412
+ className: "clarify-brand flex min-w-0 items-center gap-2 no-underline",
2413
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SiteLogo, {
2414
+ logo: config.logo,
2415
+ className: "h-6 w-6 shrink-0"
2416
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2417
+ className: "clarify-brand-title truncate font-semibold",
2418
+ children: config.title
2419
+ })]
1813
2420
  })]
1814
- }) : null]
1815
- }),
1816
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1817
- className: "clarify-header-actions flex items-center gap-5",
1818
- children: [
1819
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Search, {
2421
+ }),
2422
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2423
+ className: "clarify-header-center absolute left-1/2 hidden -translate-x-1/2 lg:block",
2424
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Search, {
1820
2425
  routes,
1821
2426
  navigation
1822
- }),
1823
- config.navbar?.links?.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
1824
- className: "clarify-top-nav hidden md:block",
1825
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
1826
- role: "list",
1827
- className: "flex items-center gap-8",
1828
- children: config.navbar.links.map((link) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TopLevelNavItem, {
1829
- href: localizeHref(link.href, config, currentLocale),
1830
- children: resolveLocalizedText(link.label, currentLocale, config.i18n?.defaultLocale)
1831
- }, link.href))
2427
+ })
2428
+ }),
2429
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2430
+ className: "clarify-header-actions flex shrink-0 items-center gap-5",
2431
+ children: [
2432
+ config.navbar?.links?.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
2433
+ className: "clarify-top-nav hidden md:block",
2434
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
2435
+ role: "list",
2436
+ className: "flex items-center gap-8",
2437
+ children: config.navbar.links.map((link) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TopLevelNavItem, {
2438
+ href: localizeHref(link.href, config, currentLocale),
2439
+ children: resolveLocalizedText(link.label, currentLocale, config.i18n?.defaultLocale)
2440
+ }, link.href))
2441
+ })
2442
+ }) : null,
2443
+ config.navbar?.links?.length ? /* @__PURE__ */ (0, react_jsx_runtime.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,
2444
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileSearch, {
2445
+ routes,
2446
+ navigation
2447
+ }),
2448
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LanguageSwitcher, {
2449
+ config,
2450
+ currentLocale,
2451
+ currentRoute
2452
+ }),
2453
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeToggle, {}),
2454
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileNavbarMenu, {
2455
+ links: config.navbar?.links,
2456
+ config,
2457
+ currentLocale
1832
2458
  })
1833
- }) : null,
1834
- config.navbar?.links?.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "hidden md:block md:h-5 md:w-px md:bg-zinc-900/10 md:dark:bg-white/15" }) : null,
1835
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileSearch, {
1836
- routes,
1837
- navigation
1838
- }),
1839
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LanguageSwitcher, {
1840
- config,
1841
- currentLocale,
1842
- currentRoute
1843
- }),
1844
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeToggle, {})
1845
- ]
1846
- })
1847
- ]
2459
+ ]
2460
+ })
2461
+ ]
2462
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProductTabs, { tabs })]
1848
2463
  });
1849
2464
  });
1850
2465
  //#endregion
1851
2466
  //#region source/app/AppShell.tsx
1852
2467
  function routeForPath(routes, pathname) {
1853
- return routes.find((route) => route.path === pathname || `/${route.path}` === pathname);
2468
+ return routes.find((route) => isSameRoutePath(route.path, pathname));
1854
2469
  }
1855
2470
  function sectionsForRoute(route) {
1856
2471
  return route?.sections?.map((section) => ({
@@ -1860,11 +2475,18 @@ function sectionsForRoute(route) {
1860
2475
  tags: section.tags
1861
2476
  })) ?? [];
1862
2477
  }
2478
+ function resolveRouteComponent(route) {
2479
+ if (route.lazy) return (0, react.lazy)(route.component);
2480
+ return route.component;
2481
+ }
1863
2482
  function scrollToHash(hash) {
1864
2483
  if (!hash) return;
1865
2484
  const targetId = decodeURIComponent(hash.slice(1));
1866
2485
  window.requestAnimationFrame(() => {
1867
2486
  document.getElementById(targetId)?.scrollIntoView();
2487
+ window.requestAnimationFrame(() => {
2488
+ window.dispatchEvent(new Event("scroll"));
2489
+ });
1868
2490
  });
1869
2491
  }
1870
2492
  function localeForPath(config, pathname, route) {
@@ -1874,25 +2496,101 @@ function localeForPath(config, pathname, route) {
1874
2496
  const firstSegment = pathname.split("/").filter(Boolean)[0];
1875
2497
  return i18n.locales.find((locale) => locale.code === firstSegment)?.code ?? i18n.defaultLocale;
1876
2498
  }
1877
- function navigationForLocale(navigation, locale) {
1878
- if (Array.isArray(navigation)) return navigation;
1879
- if (!locale) return [];
1880
- return navigation[locale] ?? [];
2499
+ function isTabbedNavigation(navigation) {
2500
+ return !Array.isArray(navigation) && "tabs" in navigation;
1881
2501
  }
1882
- function homePathForLocale(config, locale) {
1883
- if (!locale || !config.i18n || locale === config.i18n.defaultLocale) return "/";
1884
- return `/${locale}`;
2502
+ function hasPath(nodes, pathname) {
2503
+ return nodes.some((node) => isSameRoutePath(node.path, pathname) || hasPath(node.children ?? [], pathname));
2504
+ }
2505
+ function navigationFromTabs(navigation, pathname) {
2506
+ return {
2507
+ items: navigation.tabs.find((tab) => isSameRoutePath(tab.path, pathname) || hasPath(tab.children, pathname))?.children ?? navigation.tabs[0]?.children ?? [],
2508
+ tabs: navigation.tabs
2509
+ };
2510
+ }
2511
+ function navigationForLocale(navigation, locale, pathname) {
2512
+ if (Array.isArray(navigation)) return { items: navigation };
2513
+ if (isTabbedNavigation(navigation)) return navigationFromTabs(navigation, pathname);
2514
+ if (!locale) return { items: [] };
2515
+ const localizedNavigation = navigation[locale];
2516
+ if (!localizedNavigation) return { items: [] };
2517
+ return Array.isArray(localizedNavigation) ? { items: localizedNavigation } : navigationFromTabs(localizedNavigation, pathname);
2518
+ }
2519
+ function themeStyle(config) {
2520
+ const { colors, radius } = config.theme.tokens;
2521
+ const { layout } = config.theme;
2522
+ return {
2523
+ "--clarify-theme-tokens-colors-primary": colors.primary,
2524
+ "--clarify-theme-tokens-colors-accent": colors.accent,
2525
+ "--clarify-theme-tokens-colors-background": colors.background,
2526
+ "--clarify-theme-tokens-colors-foreground": colors.foreground,
2527
+ "--clarify-theme-tokens-colors-surface": colors.surface,
2528
+ "--clarify-theme-tokens-colors-muted": colors.muted,
2529
+ "--clarify-theme-tokens-colors-border": colors.border,
2530
+ "--clarify-theme-tokens-colors-code-background": colors.codeBackground,
2531
+ "--clarify-theme-tokens-radius-sm": radius.sm,
2532
+ "--clarify-theme-tokens-radius-md": radius.md,
2533
+ "--clarify-theme-tokens-radius-lg": radius.lg,
2534
+ "--clarify-theme-tokens-radius-xl": radius.xl,
2535
+ "--clarify-theme-layout-max-width": layout.maxWidth
2536
+ };
2537
+ }
2538
+ function pageTitle(config, route) {
2539
+ const routeTitle = route?.title?.trim();
2540
+ if (!routeTitle || routeTitle === config.title) return config.title;
2541
+ return `${routeTitle} - ${config.title}`;
2542
+ }
2543
+ function setNamedMeta(name, content) {
2544
+ const existing = document.head.querySelector(`meta[name="${name}"]`);
2545
+ if (!content) {
2546
+ existing?.remove();
2547
+ return;
2548
+ }
2549
+ const meta = existing ?? document.createElement("meta");
2550
+ meta.name = name;
2551
+ meta.content = content;
2552
+ if (!existing) document.head.appendChild(meta);
2553
+ }
2554
+ function applyDocumentMetadata(config, route) {
2555
+ document.title = pageTitle(config, route);
2556
+ setNamedMeta("description", route?.description ?? config.description);
2557
+ setNamedMeta("keywords", route?.keywords?.join(", "));
2558
+ }
2559
+ function applyRootThemeVariables(themeVariables) {
2560
+ const rootStyle = document.documentElement.style;
2561
+ for (const [property, value] of Object.entries(themeVariables)) rootStyle.setProperty(property, value);
2562
+ return () => {
2563
+ for (const property of Object.keys(themeVariables)) rootStyle.removeProperty(property);
2564
+ };
1885
2565
  }
1886
2566
  function AppShell(arg0) {
1887
2567
  const { config, routes, navigation } = arg0;
1888
2568
  const location = (0, react_router_dom.useLocation)();
1889
- const currentRoute = routeForPath(routes, location.pathname);
1890
- const currentLocale = localeForPath(config, location.pathname, currentRoute);
2569
+ const pathname = normalizeRoutePath(location.pathname);
2570
+ const currentRoute = routeForPath(routes, pathname);
2571
+ const currentLocale = localeForPath(config, pathname, currentRoute);
1891
2572
  const currentLocaleConfig = config.i18n?.locales.find((locale) => locale.code === currentLocale);
1892
- const currentNavigation = navigationForLocale(navigation, currentLocale);
2573
+ const currentNavigation = navigationForLocale(navigation, currentLocale, pathname);
1893
2574
  const sections = sectionsForRoute(currentRoute);
2575
+ const hasTabs = Boolean(currentNavigation.tabs?.length);
2576
+ const themeVariables = themeStyle(config);
2577
+ const renderRoutes = (0, react.useMemo)(() => routes.map((route) => ({
2578
+ ...route,
2579
+ component: resolveRouteComponent(route)
2580
+ })), [routes]);
2581
+ (0, react.useEffect)(() => applyRootThemeVariables(themeVariables), [themeVariables]);
1894
2582
  (0, react.useEffect)(() => {
1895
- scrollToHash(location.hash);
2583
+ if (location.hash) {
2584
+ scrollToHash(location.hash);
2585
+ return;
2586
+ }
2587
+ window.scrollTo({
2588
+ top: 0,
2589
+ left: 0
2590
+ });
2591
+ window.requestAnimationFrame(() => {
2592
+ window.dispatchEvent(new Event("scroll"));
2593
+ });
1896
2594
  }, [location.hash, location.pathname]);
1897
2595
  (0, react.useEffect)(() => {
1898
2596
  if (!currentLocale) return;
@@ -1900,57 +2598,60 @@ function AppShell(arg0) {
1900
2598
  if (currentLocaleConfig?.dir) document.documentElement.dir = currentLocaleConfig.dir;
1901
2599
  else document.documentElement.removeAttribute("dir");
1902
2600
  }, [currentLocale, currentLocaleConfig?.dir]);
1903
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionProvider, {
1904
- sections,
1905
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1906
- className: "clarify-app h-full min-h-screen bg-white lg:ml-72 xl:ml-80 dark:bg-zinc-950",
1907
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.motion.header, {
1908
- layoutScroll: true,
1909
- className: "clarify-shell contents lg:pointer-events-none lg:fixed lg:inset-0 lg:z-40 lg:flex",
1910
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1911
- 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",
1912
- children: [
1913
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1914
- className: "clarify-sidebar-brand hidden lg:flex",
1915
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_router_dom.Link, {
1916
- to: homePathForLocale(config, currentLocale),
1917
- "aria-label": "Home",
1918
- className: "clarify-brand flex items-center gap-2 no-underline",
1919
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SiteLogo, {
1920
- logo: config.logo,
1921
- className: "h-6 w-6"
1922
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1923
- className: "clarify-brand-title text-sm font-semibold text-zinc-900 dark:text-white",
1924
- children: config.title
1925
- })]
1926
- })
1927
- }),
1928
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Header, {
1929
- config,
1930
- navigation: currentNavigation,
1931
- routes,
1932
- currentLocale,
1933
- currentRoute
1934
- }),
1935
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Navigation, {
1936
- navigation: currentNavigation,
1937
- className: "clarify-navigation hidden lg:mt-10 lg:block"
1938
- })
1939
- ]
1940
- })
1941
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1942
- className: "clarify-content relative flex min-h-screen flex-col px-4 pt-14 sm:px-6 lg:px-8",
1943
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContentActions, {
1944
- route: currentRoute,
1945
- routePrefix: config.routePrefix
1946
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("main", {
1947
- className: "clarify-main flex-auto",
1948
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Routes, { children: routes.map((route) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Route, {
1949
- path: route.path,
1950
- element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(route.component, {})
1951
- }, route.path)) })
1952
- })]
1953
- })]
2601
+ (0, react.useEffect)(() => {
2602
+ applyDocumentMetadata(config, currentRoute);
2603
+ }, [config, currentRoute]);
2604
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClarifyLocaleContext.Provider, {
2605
+ value: currentLocale,
2606
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SectionProvider, {
2607
+ sections,
2608
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2609
+ className: "clarify-app h-full min-h-screen bg-(--clarify-theme-tokens-colors-background) text-(--clarify-theme-tokens-colors-foreground) dark:bg-zinc-950 dark:text-white",
2610
+ "data-theme-preset": config.theme.preset,
2611
+ style: themeVariables,
2612
+ children: [
2613
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Header, {
2614
+ config,
2615
+ navigation: currentNavigation.items,
2616
+ tabs: currentNavigation.tabs,
2617
+ routes,
2618
+ currentLocale,
2619
+ currentRoute
2620
+ }),
2621
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2622
+ className: "clarify-layout mx-auto grid w-full max-w-(--clarify-theme-layout-max-width) grid-cols-1 lg:grid-cols-[18rem_minmax(0,1fr)] xl:grid-cols-[20rem_minmax(0,1fr)]",
2623
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(framer_motion.motion.aside, {
2624
+ layoutScroll: true,
2625
+ className: (0, clsx.default)("clarify-sidebar hidden lg:sticky lg:z-30 lg:block lg:h-[calc(100vh-3.5rem)] lg:self-start lg:overflow-y-auto lg:bg-(--clarify-theme-tokens-colors-background) lg:px-5 lg:pb-8 xl:px-6 lg:dark:bg-zinc-950", hasTabs ? "lg:top-28 lg:h-[calc(100vh-7rem)] lg:pt-6" : "lg:top-14 lg:pt-6"),
2626
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Navigation, { navigation: currentNavigation.items })
2627
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2628
+ className: (0, clsx.default)("clarify-content @container relative flex min-h-screen min-w-0 flex-col px-4 sm:px-6 lg:px-8 xl:px-10", hasTabs ? "pt-14 lg:pt-28" : "pt-14"),
2629
+ children: [
2630
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContentActions, {
2631
+ hasTabs,
2632
+ route: currentRoute,
2633
+ routePrefix: config.routePrefix
2634
+ }),
2635
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("main", {
2636
+ className: "clarify-main min-w-0 flex-auto",
2637
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Suspense, {
2638
+ fallback: null,
2639
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Routes, { children: renderRoutes.map((route) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.Route, {
2640
+ path: route.path,
2641
+ element: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(route.component, {})
2642
+ }, route.path)) })
2643
+ })
2644
+ }),
2645
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageNavigation, {
2646
+ navigation: currentNavigation.items,
2647
+ currentRoute
2648
+ })
2649
+ ]
2650
+ })]
2651
+ }),
2652
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageFooter, {})
2653
+ ]
2654
+ })
1954
2655
  })
1955
2656
  });
1956
2657
  }
@@ -1979,6 +2680,24 @@ Object.defineProperty(exports, "Button", {
1979
2680
  return Button;
1980
2681
  }
1981
2682
  });
2683
+ Object.defineProperty(exports, "Callout", {
2684
+ enumerable: true,
2685
+ get: function() {
2686
+ return Callout;
2687
+ }
2688
+ });
2689
+ Object.defineProperty(exports, "Card", {
2690
+ enumerable: true,
2691
+ get: function() {
2692
+ return Card;
2693
+ }
2694
+ });
2695
+ Object.defineProperty(exports, "CardGroup", {
2696
+ enumerable: true,
2697
+ get: function() {
2698
+ return CardGroup;
2699
+ }
2700
+ });
1982
2701
  Object.defineProperty(exports, "ClarifyConfigContext", {
1983
2702
  enumerable: true,
1984
2703
  get: function() {
@@ -2099,6 +2818,12 @@ Object.defineProperty(exports, "remToPx", {
2099
2818
  return remToPx;
2100
2819
  }
2101
2820
  });
2821
+ Object.defineProperty(exports, "useBuiltInText", {
2822
+ enumerable: true,
2823
+ get: function() {
2824
+ return useBuiltInText;
2825
+ }
2826
+ });
2102
2827
  Object.defineProperty(exports, "useClarifyConfig", {
2103
2828
  enumerable: true,
2104
2829
  get: function() {
@@ -2124,4 +2849,4 @@ Object.defineProperty(exports, "useTheme", {
2124
2849
  }
2125
2850
  });
2126
2851
 
2127
- //# sourceMappingURL=AppShell-DBgUlirU.cjs.map
2852
+ //# sourceMappingURL=AppShell-CZw1MrPG.cjs.map