@clarify-labs/renderer 0.6.6 → 0.7.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 (59) hide show
  1. package/output/{OpenApiOperation-CI_PeMSy.js → OpenApiOperation-CWSOhUVa.js} +84 -19
  2. package/output/OpenApiOperation-CWSOhUVa.js.map +1 -0
  3. package/output/{OpenApiOperation-CxQQyEHK.cjs → OpenApiOperation-ZXToVSFC.cjs} +89 -18
  4. package/output/OpenApiOperation-ZXToVSFC.cjs.map +1 -0
  5. package/output/{ThemeRoot-BhP5M3Hd.cjs → ThemeRoot-CEvwrGp5.cjs} +29 -186
  6. package/output/ThemeRoot-CEvwrGp5.cjs.map +1 -0
  7. package/output/{ThemeRoot-DErmHskn.js → ThemeRoot-C_ZdzSMu.js} +21 -178
  8. package/output/ThemeRoot-C_ZdzSMu.js.map +1 -0
  9. package/output/app/AppShell.d.ts +2 -0
  10. package/output/app/PageFooter.d.ts +5 -1
  11. package/output/client.cjs +5 -2
  12. package/output/client.d.ts +1 -0
  13. package/output/client.js +4 -3
  14. package/output/components/LocalizedLink.d.ts +6 -0
  15. package/output/components/WebFrame.d.ts +11 -0
  16. package/output/components/index.d.ts +4 -0
  17. package/output/context.d.ts +1 -1
  18. package/output/core/types.d.ts +7 -1
  19. package/output/index.cjs +5 -4
  20. package/output/index.d.ts +2 -2
  21. package/output/index.js +5 -5
  22. package/output/mdx/components.d.ts +1 -0
  23. package/output/mdx/primitives.d.ts +2 -2
  24. package/output/preview.cjs +61 -23
  25. package/output/preview.cjs.map +1 -1
  26. package/output/preview.js +61 -23
  27. package/output/preview.js.map +1 -1
  28. package/output/{render-HeCAMIGm.js → render-CnUd0XwZ.js} +6 -5
  29. package/output/render-CnUd0XwZ.js.map +1 -0
  30. package/output/{render-C_NHO3rz.cjs → render-zHU25Nm9.cjs} +6 -5
  31. package/output/render-zHU25Nm9.cjs.map +1 -0
  32. package/output/renderer.css +220 -29
  33. package/output/server.cjs +5 -4
  34. package/output/server.cjs.map +1 -1
  35. package/output/server.js +5 -4
  36. package/output/server.js.map +1 -1
  37. package/output/shell/Search.d.ts +4 -0
  38. package/output/shell/search/Highlight.d.ts +11 -0
  39. package/output/shell/search/SearchDialog.d.ts +13 -0
  40. package/output/shell/search/SearchInput.d.ts +8 -0
  41. package/output/shell/search/SearchResult.d.ts +10 -0
  42. package/output/shell/search/items.d.ts +3 -0
  43. package/output/shell/search/pagefind.d.ts +5 -0
  44. package/output/shell/search/types.d.ts +37 -0
  45. package/output/shell/search/useSearchProps.d.ts +10 -0
  46. package/output/{shell-DvTfFx6M.js → shell-CumiARRe.js} +472 -61
  47. package/output/shell-CumiARRe.js.map +1 -0
  48. package/output/{shell-D4tS8Jts.cjs → shell-xxhV0p7k.cjs} +524 -59
  49. package/output/shell-xxhV0p7k.cjs.map +1 -0
  50. package/output/theme/variables.d.ts +2 -0
  51. package/package.json +1 -1
  52. package/output/OpenApiOperation-CI_PeMSy.js.map +0 -1
  53. package/output/OpenApiOperation-CxQQyEHK.cjs.map +0 -1
  54. package/output/ThemeRoot-BhP5M3Hd.cjs.map +0 -1
  55. package/output/ThemeRoot-DErmHskn.js.map +0 -1
  56. package/output/render-C_NHO3rz.cjs.map +0 -1
  57. package/output/render-HeCAMIGm.js.map +0 -1
  58. package/output/shell-D4tS8Jts.cjs.map +0 -1
  59. package/output/shell-DvTfFx6M.js.map +0 -1
@@ -18,6 +18,9 @@ function useClarifyConfig() {
18
18
  if (!config) throw new Error("[clarify] useClarifyConfig must be used within a ClarifyConfigContext.Provider");
19
19
  return config;
20
20
  }
21
+ function useClarifyLocale() {
22
+ return (0, react.useContext)(ClarifyLocaleContext);
23
+ }
21
24
  function useOpenApis() {
22
25
  return (0, react.useContext)(OpenApisContext);
23
26
  }
@@ -330,10 +333,10 @@ function ContentActions(arg0) {
330
333
  const primaryAction = actions[0];
331
334
  const PrimaryIcon = primaryAction && copied === primaryAction.key ? lucide_react.Check : primaryAction?.icon ?? lucide_react.PencilLine;
332
335
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
333
- className: `clarify-content-actions sticky z-20 flex justify-end py-4 ${hasTabs ? "top-16 lg:top-30" : "top-16"}`,
336
+ className: `clarify-content-actions pointer-events-none sticky z-20 flex justify-end py-4 ${hasTabs ? "top-16 lg:top-30" : "top-16"}`,
334
337
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_headlessui_react.Menu, {
335
338
  as: "div",
336
- className: "clarify-content-actions-menu relative inline-flex text-sm font-medium",
339
+ className: "clarify-content-actions-menu pointer-events-auto relative inline-flex text-sm font-medium",
337
340
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
338
341
  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",
339
342
  children: [primaryAction ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
@@ -482,9 +485,178 @@ function ContentActions(arg0) {
482
485
  });
483
486
  }
484
487
  //#endregion
488
+ //#region source/theme/variables.ts
489
+ var themeStorageKey = "clarify:theme";
490
+ var clarifyThemePresets = {
491
+ default: {
492
+ preset: "default",
493
+ tokens: {
494
+ colors: {
495
+ primary: "#047857",
496
+ accent: "#0D9488",
497
+ background: "#ffffff",
498
+ foreground: "#111827",
499
+ surface: "#ffffff",
500
+ muted: "#64748b",
501
+ border: "rgb(15 23 42 / 0.12)",
502
+ codeBackground: "#f6fbf8"
503
+ },
504
+ radius: {
505
+ sm: "6px",
506
+ md: "10px",
507
+ lg: "14px",
508
+ xl: "18px"
509
+ }
510
+ },
511
+ layout: { maxWidth: "82rem" },
512
+ editor: false
513
+ },
514
+ base: {
515
+ preset: "base",
516
+ tokens: {
517
+ colors: {
518
+ primary: "#18181b",
519
+ accent: "#52525b",
520
+ background: "#ffffff",
521
+ foreground: "#18181b",
522
+ surface: "#ffffff",
523
+ muted: "#71717a",
524
+ border: "rgb(24 24 27 / 0.12)",
525
+ codeBackground: "#f4f4f5"
526
+ },
527
+ radius: {
528
+ sm: "6px",
529
+ md: "8px",
530
+ lg: "12px",
531
+ xl: "16px"
532
+ }
533
+ },
534
+ layout: { maxWidth: "80rem" },
535
+ editor: false
536
+ }
537
+ };
538
+ function cloneThemeColorValue(value) {
539
+ return typeof value === "string" ? value : { ...value };
540
+ }
541
+ function cloneTheme(theme) {
542
+ return {
543
+ preset: theme.preset,
544
+ tokens: {
545
+ colors: {
546
+ primary: cloneThemeColorValue(theme.tokens.colors.primary),
547
+ accent: cloneThemeColorValue(theme.tokens.colors.accent),
548
+ background: cloneThemeColorValue(theme.tokens.colors.background),
549
+ foreground: cloneThemeColorValue(theme.tokens.colors.foreground),
550
+ surface: cloneThemeColorValue(theme.tokens.colors.surface),
551
+ muted: cloneThemeColorValue(theme.tokens.colors.muted),
552
+ border: cloneThemeColorValue(theme.tokens.colors.border),
553
+ codeBackground: cloneThemeColorValue(theme.tokens.colors.codeBackground)
554
+ },
555
+ radius: { ...theme.tokens.radius }
556
+ },
557
+ layout: { ...theme.layout },
558
+ editor: theme.editor
559
+ };
560
+ }
561
+ function isModeColorValue(value) {
562
+ return typeof value === "object" && value !== null;
563
+ }
564
+ function resolveThemeColorValue(value, resolvedTheme = "light") {
565
+ if (!isModeColorValue(value)) return value;
566
+ return value[resolvedTheme] ?? value.light ?? value.dark ?? "";
567
+ }
568
+ function resolveThemeColors(colors, resolvedTheme = "light") {
569
+ return {
570
+ primary: resolveThemeColorValue(colors.primary, resolvedTheme),
571
+ accent: resolveThemeColorValue(colors.accent, resolvedTheme),
572
+ background: resolveThemeColorValue(colors.background, resolvedTheme),
573
+ foreground: resolveThemeColorValue(colors.foreground, resolvedTheme),
574
+ surface: resolveThemeColorValue(colors.surface, resolvedTheme),
575
+ muted: resolveThemeColorValue(colors.muted, resolvedTheme),
576
+ border: resolveThemeColorValue(colors.border, resolvedTheme),
577
+ codeBackground: resolveThemeColorValue(colors.codeBackground, resolvedTheme)
578
+ };
579
+ }
580
+ function matchesPresetTheme(theme) {
581
+ const preset = clarifyThemePresets[theme.preset];
582
+ return JSON.stringify({
583
+ tokens: theme.tokens,
584
+ layout: theme.layout
585
+ }) === JSON.stringify({
586
+ tokens: preset.tokens,
587
+ layout: preset.layout
588
+ });
589
+ }
590
+ function effectiveTheme(theme, resolvedTheme) {
591
+ if (resolvedTheme !== "dark" || !matchesPresetTheme(theme)) return theme;
592
+ return {
593
+ ...theme,
594
+ tokens: {
595
+ ...theme.tokens,
596
+ colors: {
597
+ ...theme.tokens.colors,
598
+ background: "#09090b",
599
+ foreground: "#ffffff",
600
+ surface: "#18181b",
601
+ muted: "#a1a1aa",
602
+ border: "rgb(255 255 255 / 0.1)",
603
+ codeBackground: "#18181b"
604
+ }
605
+ }
606
+ };
607
+ }
608
+ function themeToCssVariables(theme, resolvedTheme) {
609
+ const resolved = effectiveTheme(theme, resolvedTheme);
610
+ const colors = resolveThemeColors(resolved.tokens.colors, resolvedTheme);
611
+ const { radius } = resolved.tokens;
612
+ return {
613
+ "--clarify-theme-tokens-colors-primary": colors.primary,
614
+ "--clarify-theme-tokens-colors-accent": colors.accent,
615
+ "--clarify-theme-tokens-colors-background": colors.background,
616
+ "--clarify-theme-tokens-colors-foreground": colors.foreground,
617
+ "--clarify-theme-tokens-colors-surface": colors.surface,
618
+ "--clarify-theme-tokens-colors-muted": colors.muted,
619
+ "--clarify-theme-tokens-colors-border": colors.border,
620
+ "--clarify-theme-tokens-colors-code-background": colors.codeBackground,
621
+ "--clarify-theme-tokens-radius-sm": radius.sm,
622
+ "--clarify-theme-tokens-radius-md": radius.md,
623
+ "--clarify-theme-tokens-radius-lg": radius.lg,
624
+ "--clarify-theme-tokens-radius-xl": radius.xl,
625
+ "--clarify-theme-layout-max-width": resolved.layout.maxWidth
626
+ };
627
+ }
628
+ function themeBootstrapScript(theme = clarifyThemePresets.default) {
629
+ const darkVariables = themeToCssVariables(theme, "dark");
630
+ const lightVariables = themeToCssVariables(theme, "light");
631
+ return `(function(){try{var e=localStorage.getItem(${JSON.stringify(themeStorageKey)});var t=e==='dark'||e==='light'||e==='system'?e:'system';var r=t==='system'?window.matchMedia('(prefers-color-scheme: dark)').matches:t==='dark';var v=r?${JSON.stringify(darkVariables)}:${JSON.stringify(lightVariables)};var s=document.documentElement.style;for(var k in v)s.setProperty(k,v[k]);document.documentElement.classList.toggle('dark',r);document.documentElement.style.colorScheme=r?'dark':'light'}catch(e){}})();`;
632
+ }
633
+ function uniqueElements(elements) {
634
+ return Array.from(new Set(elements));
635
+ }
636
+ function resolveThemeVariableTargets(target) {
637
+ if (typeof document === "undefined") return [];
638
+ if (target instanceof HTMLElement) return [target];
639
+ if (typeof target === "string") return Array.from(document.querySelectorAll(target));
640
+ return uniqueElements([document.documentElement, ...Array.from(document.querySelectorAll(".clarify-app"))]);
641
+ }
642
+ function applyThemeCssVariables(variables, targets) {
643
+ const previousValues = /* @__PURE__ */ new Map();
644
+ for (const element of targets) {
645
+ const elementPreviousValues = /* @__PURE__ */ new Map();
646
+ for (const [property, value] of Object.entries(variables)) {
647
+ elementPreviousValues.set(property, element.style.getPropertyValue(property));
648
+ element.style.setProperty(property, value);
649
+ }
650
+ previousValues.set(element, elementPreviousValues);
651
+ }
652
+ return () => {
653
+ for (const [element, elementPreviousValues] of previousValues) for (const [property, previousValue] of elementPreviousValues) if (previousValue) element.style.setProperty(property, previousValue);
654
+ else element.style.removeProperty(property);
655
+ };
656
+ }
657
+ //#endregion
485
658
  //#region source/theme/ThemeProvider.tsx
486
659
  var ThemeContext = (0, react.createContext)(null);
487
- var storageKey = "clarify:theme";
488
660
  function getSystemTheme() {
489
661
  if (typeof window === "undefined") return "light";
490
662
  return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
@@ -492,7 +664,7 @@ function getSystemTheme() {
492
664
  function getStoredTheme() {
493
665
  if (typeof window === "undefined") return "system";
494
666
  try {
495
- const storedTheme = window.localStorage.getItem(storageKey);
667
+ const storedTheme = window.localStorage.getItem(themeStorageKey);
496
668
  return storedTheme === "light" || storedTheme === "dark" || storedTheme === "system" ? storedTheme : "system";
497
669
  } catch {
498
670
  return "system";
@@ -501,7 +673,7 @@ function getStoredTheme() {
501
673
  function storeTheme(theme) {
502
674
  if (typeof window === "undefined") return;
503
675
  try {
504
- window.localStorage.setItem(storageKey, theme);
676
+ window.localStorage.setItem(themeStorageKey, theme);
505
677
  } catch {}
506
678
  }
507
679
  function applyTheme(resolvedTheme) {
@@ -846,7 +1018,7 @@ function NavigationGroup(arg0) {
846
1018
  const [pathname, sections] = useInitialValue([normalizeRoutePath((0, react_router_dom.useLocation)().pathname), useSectionStore((s) => s.sections)], isInsideMobileNavigation);
847
1019
  const isActiveGroup = group.links.findIndex((link) => isSameRoutePath(link.href, pathname)) !== -1;
848
1020
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
849
- className: (0, clsx.default)("clarify-navigation-group relative mt-6", className),
1021
+ className: (0, clsx.default)("clarify-navigation-group relative mb-6", className),
850
1022
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h2", {
851
1023
  className: "clarify-navigation-group-title flex items-center gap-2",
852
1024
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(NavigationIcon, {
@@ -1045,7 +1217,7 @@ function MobileNavigation(arg0) {
1045
1217
  });
1046
1218
  }
1047
1219
  //#endregion
1048
- //#region source/shell/Search.tsx
1220
+ //#region source/shell/search/items.ts
1049
1221
  function routeGroupTitles(navigation) {
1050
1222
  const titles = /* @__PURE__ */ new Map();
1051
1223
  for (const node of navigation) if (node.children?.length) for (const child of node.children) titles.set(child.path, node.title);
@@ -1082,53 +1254,85 @@ function buildSearchItems(routes, navigation) {
1082
1254
  })) ?? []];
1083
1255
  });
1084
1256
  }
1085
- function escapeRegExp(value) {
1086
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1087
- }
1088
- function HighlightQuery(arg0) {
1089
- const { text, query } = arg0;
1090
- if (!query) return text;
1091
- 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", {
1092
- className: "bg-transparent text-(--clarify-theme-tokens-colors-primary) underline",
1093
- children: part
1094
- }, index) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: part }, index)) });
1257
+ //#endregion
1258
+ //#region source/shell/search/pagefind.ts
1259
+ var pagefindPromises = /* @__PURE__ */ new Map();
1260
+ function pagefindCacheKey(routePrefix, locale) {
1261
+ return `${routePrefix || "/"}:${locale || "default"}`;
1095
1262
  }
1096
- function SearchResult(arg0) {
1097
- const { result, query, active, onSelect } = arg0;
1098
- const id = (0, react.useId)();
1099
- const hierarchy = [result.sectionTitle, result.pageTitle].filter((value) => typeof value === "string");
1100
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
1101
- id,
1102
- className: (0, clsx.default)("clarify-search-result group block cursor-default px-4 py-3", active && "clarify-search-result-active"),
1103
- "aria-selected": active,
1104
- onMouseDown: (event) => {
1105
- event.preventDefault();
1106
- onSelect();
1107
- },
1108
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1109
- className: "clarify-search-result-title",
1110
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightQuery, {
1111
- text: result.title,
1112
- query
1113
- })
1114
- }), hierarchy.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1115
- className: "clarify-search-result-hierarchy mt-1 truncate whitespace-nowrap",
1116
- children: hierarchy.map((item, itemIndex, items) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightQuery, {
1117
- text: item,
1118
- query
1119
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1120
- className: itemIndex === items.length - 1 ? "sr-only" : "clarify-search-result-separator mx-2",
1121
- children: "/"
1122
- })] }, `${item}-${itemIndex}`))
1123
- }) : null]
1263
+ function logSearchDebug(message, data) {
1264
+ if (typeof window === "undefined") return;
1265
+ console.info(`[clarify:search] ${message}`, data ?? "");
1266
+ }
1267
+ function loadPagefind(routePrefix, locale) {
1268
+ if (typeof window === "undefined") return Promise.resolve(null);
1269
+ const language = locale ?? document.documentElement.lang;
1270
+ const cacheKey = pagefindCacheKey(routePrefix, language);
1271
+ const cachedPagefind = pagefindPromises.get(cacheKey);
1272
+ if (cachedPagefind) {
1273
+ logSearchDebug("reuse Pagefind instance promise", {
1274
+ cacheKey,
1275
+ language,
1276
+ routePrefix
1277
+ });
1278
+ return cachedPagefind;
1279
+ }
1280
+ const pagefindUrl = prefixHref("/pagefind/pagefind.js", routePrefix);
1281
+ logSearchDebug("create Pagefind instance promise", {
1282
+ cacheKey,
1283
+ language,
1284
+ pagefindUrl,
1285
+ routePrefix
1286
+ });
1287
+ const pagefindPromise = import(
1288
+ /* @vite-ignore */
1289
+ pagefindUrl
1290
+ ).then(async (module) => {
1291
+ const previousLanguage = document.documentElement.lang;
1292
+ if (language) document.documentElement.lang = language;
1293
+ logSearchDebug("create Pagefind instance", {
1294
+ cacheKey,
1295
+ detectedLanguage: document.documentElement.lang,
1296
+ previousLanguage
1297
+ });
1298
+ const pagefind = module.createInstance();
1299
+ if (previousLanguage && previousLanguage !== language) document.documentElement.lang = previousLanguage;
1300
+ await pagefind.init?.();
1301
+ logSearchDebug("Pagefind instance ready", {
1302
+ cacheKey,
1303
+ language
1304
+ });
1305
+ return pagefind;
1306
+ }).catch((error) => {
1307
+ pagefindPromises.delete(cacheKey);
1308
+ console.warn("[clarify:search] Pagefind instance failed", {
1309
+ cacheKey,
1310
+ language,
1311
+ error
1312
+ });
1313
+ return null;
1124
1314
  });
1315
+ pagefindPromises.set(cacheKey, pagefindPromise);
1316
+ return pagefindPromise;
1317
+ }
1318
+ function normalizePagefindUrl(url, routePrefix) {
1319
+ const parsedUrl = new URL(url, window.location.origin);
1320
+ let pathname = parsedUrl.pathname;
1321
+ const prefix = routePrefix && routePrefix !== "/" ? `/${routePrefix.replace(/^\/+|\/+$/g, "")}` : "";
1322
+ if (prefix && (pathname === prefix || pathname.startsWith(`${prefix}/`))) pathname = pathname.slice(prefix.length) || "/";
1323
+ return `${pathname}${parsedUrl.search}${parsedUrl.hash}`;
1125
1324
  }
1325
+ //#endregion
1326
+ //#region source/shell/search/SearchInput.tsx
1126
1327
  var SearchInput = (0, react.forwardRef)(function SearchInput(arg0, inputRef) {
1127
- const { query, setQuery, onClose, onSubmit, activeDescendantId } = arg0;
1328
+ const { query, setQuery, onClose, onSubmit, activeDescendantId, loading = false } = arg0;
1128
1329
  const t = useBuiltInText();
1129
1330
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1130
1331
  className: "clarify-search-input group relative flex h-12",
1131
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Search, { 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", {
1332
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(loading ? lucide_react.LoaderCircle : lucide_react.Search, {
1333
+ "aria-hidden": "true",
1334
+ className: (0, clsx.default)("pointer-events-none absolute top-0 left-3 h-full w-5 stroke-(--clarify-theme-tokens-colors-muted)", loading && "animate-spin")
1335
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1132
1336
  ref: inputRef,
1133
1337
  "data-autofocus": true,
1134
1338
  role: "combobox",
@@ -1150,20 +1354,120 @@ var SearchInput = (0, react.forwardRef)(function SearchInput(arg0, inputRef) {
1150
1354
  })]
1151
1355
  });
1152
1356
  });
1357
+ //#endregion
1358
+ //#region source/shell/search/Highlight.tsx
1359
+ function stripHtml(value) {
1360
+ if (typeof document === "undefined") return value.replace(/<[^>]*>/g, "");
1361
+ const template = document.createElement("template");
1362
+ template.innerHTML = value;
1363
+ return template.content.textContent ?? "";
1364
+ }
1365
+ function escapeRegExp(value) {
1366
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1367
+ }
1368
+ function HighlightQuery(arg0) {
1369
+ const { text, query } = arg0;
1370
+ if (!query) return text;
1371
+ 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", {
1372
+ className: "bg-transparent text-(--clarify-theme-tokens-colors-primary) underline",
1373
+ children: part
1374
+ }, index) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: part }, index)) });
1375
+ }
1376
+ function renderExcerptNode(node, key) {
1377
+ if (node.nodeType === Node.TEXT_NODE) return node.textContent;
1378
+ if (node.nodeType !== Node.ELEMENT_NODE) return null;
1379
+ const element = node;
1380
+ const children = Array.from(element.childNodes).map((child, index) => renderExcerptNode(child, `${key}-${index}`));
1381
+ if (element.tagName.toLowerCase() === "mark") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("mark", {
1382
+ className: "bg-transparent text-(--clarify-theme-tokens-colors-primary) underline",
1383
+ children
1384
+ }, key);
1385
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children }, key);
1386
+ }
1387
+ function HighlightExcerpt(arg0) {
1388
+ const { excerpt, query } = arg0;
1389
+ if (typeof document === "undefined" || !excerpt.includes("<mark")) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightQuery, {
1390
+ text: stripHtml(excerpt),
1391
+ query
1392
+ });
1393
+ const template = document.createElement("template");
1394
+ template.innerHTML = excerpt;
1395
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: Array.from(template.content.childNodes).map((node, index) => renderExcerptNode(node, String(index))) });
1396
+ }
1397
+ //#endregion
1398
+ //#region source/shell/search/SearchResult.tsx
1399
+ function SearchResult(arg0) {
1400
+ const { result, query, active, onActive, onSelect } = arg0;
1401
+ const id = (0, react.useId)();
1402
+ const hierarchy = result.type === "quick" ? [result.sectionTitle, result.pageTitle].filter((value) => typeof value === "string") : [];
1403
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
1404
+ id,
1405
+ className: (0, clsx.default)("clarify-search-result group block cursor-pointer px-4 py-3", active && "clarify-search-result-active"),
1406
+ "aria-selected": active,
1407
+ onMouseEnter: onActive,
1408
+ onMouseMove: onActive,
1409
+ onMouseDown: (event) => {
1410
+ event.preventDefault();
1411
+ onSelect();
1412
+ },
1413
+ children: [
1414
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1415
+ className: "clarify-search-result-title",
1416
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightQuery, {
1417
+ text: result.title,
1418
+ query
1419
+ })
1420
+ }),
1421
+ hierarchy.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1422
+ className: "clarify-search-result-hierarchy mt-1 truncate whitespace-nowrap",
1423
+ children: hierarchy.map((item, itemIndex, items) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightQuery, {
1424
+ text: item,
1425
+ query
1426
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1427
+ className: itemIndex === items.length - 1 ? "sr-only" : "clarify-search-result-separator mx-2",
1428
+ children: "/"
1429
+ })] }, `${item}-${itemIndex}`))
1430
+ }) : null,
1431
+ result.type === "full-text" && result.excerpt ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1432
+ className: "clarify-search-result-excerpt mt-1 line-clamp-2 text-xs leading-5 text-(--clarify-theme-tokens-colors-muted)",
1433
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightExcerpt, {
1434
+ excerpt: result.excerpt,
1435
+ query
1436
+ })
1437
+ }) : null
1438
+ ]
1439
+ });
1440
+ }
1441
+ //#endregion
1442
+ //#region source/shell/search/SearchDialog.tsx
1153
1443
  function SearchDialog(arg0) {
1154
- const { open, setOpen, routes, navigation, className, onNavigate = () => {} } = arg0;
1444
+ const { open, setOpen, routes, navigation, routePrefix = "/", currentLocale, className, onNavigate = () => {} } = arg0;
1155
1445
  const t = useBuiltInText();
1156
1446
  const navigate = (0, react_router_dom.useNavigate)();
1157
1447
  const location = (0, react_router_dom.useLocation)();
1158
1448
  const inputRef = (0, react.useRef)(null);
1159
1449
  const [query, setQuery] = (0, react.useState)("");
1160
1450
  const [activeIndex, setActiveIndex] = (0, react.useState)(0);
1451
+ const [fullTextState, setFullTextState] = (0, react.useState)(null);
1452
+ const [pagefindState, setPagefindState] = (0, react.useState)(null);
1161
1453
  const searchItems = (0, react.useMemo)(() => buildSearchItems(routes, navigation), [navigation, routes]);
1162
- const results = (0, react.useMemo)(() => {
1454
+ const quickResults = (0, react.useMemo)(() => {
1163
1455
  const normalizedQuery = query.trim().toLowerCase();
1164
1456
  if (!normalizedQuery) return [];
1165
- return searchItems.filter((item) => item.keywords.includes(normalizedQuery)).slice(0, 8);
1457
+ return searchItems.filter((item) => item.keywords.includes(normalizedQuery)).slice(0, 8).map((item) => ({
1458
+ ...item,
1459
+ type: "quick"
1460
+ }));
1166
1461
  }, [query, searchItems]);
1462
+ const pagefindKey = pagefindCacheKey(routePrefix, currentLocale);
1463
+ const activePagefindState = pagefindState?.key === pagefindKey ? pagefindState : null;
1464
+ const pagefind = activePagefindState?.pagefind ?? null;
1465
+ const pagefindAvailable = activePagefindState?.available ?? null;
1466
+ const trimmedQuery = query.trim();
1467
+ const fullTextKey = `${pagefindKey}:${trimmedQuery}`;
1468
+ const results = (fullTextState?.key === fullTextKey ? fullTextState.results : null) ?? quickResults;
1469
+ const searchInputLoading = pagefindAvailable === null || Boolean(trimmedQuery && pagefind && fullTextState?.key !== fullTextKey);
1470
+ const showNoResults = query && results.length === 0 && pagefindAvailable !== null;
1167
1471
  (0, react.useEffect)(() => {
1168
1472
  setOpen(false);
1169
1473
  }, [
@@ -1172,6 +1476,98 @@ function SearchDialog(arg0) {
1172
1476
  location.hash,
1173
1477
  setOpen
1174
1478
  ]);
1479
+ (0, react.useEffect)(() => {
1480
+ let cancelled = false;
1481
+ logSearchDebug("locale or route prefix changed; reload Pagefind", {
1482
+ currentLocale,
1483
+ routePrefix,
1484
+ documentLanguage: document.documentElement.lang
1485
+ });
1486
+ loadPagefind(routePrefix, currentLocale).then((loadedPagefind) => {
1487
+ if (cancelled) {
1488
+ logSearchDebug("ignore stale Pagefind load", {
1489
+ currentLocale,
1490
+ routePrefix
1491
+ });
1492
+ return;
1493
+ }
1494
+ logSearchDebug("Pagefind load applied", {
1495
+ currentLocale,
1496
+ routePrefix,
1497
+ available: Boolean(loadedPagefind)
1498
+ });
1499
+ setPagefindState({
1500
+ key: pagefindKey,
1501
+ pagefind: loadedPagefind,
1502
+ available: Boolean(loadedPagefind)
1503
+ });
1504
+ });
1505
+ return () => {
1506
+ cancelled = true;
1507
+ logSearchDebug("cancel Pagefind load effect", {
1508
+ currentLocale,
1509
+ routePrefix
1510
+ });
1511
+ };
1512
+ }, [
1513
+ currentLocale,
1514
+ pagefindKey,
1515
+ routePrefix
1516
+ ]);
1517
+ (0, react.useEffect)(() => {
1518
+ let cancelled = false;
1519
+ if (!trimmedQuery || !pagefind) return void 0;
1520
+ Promise.resolve().then(async () => {
1521
+ if (cancelled) return;
1522
+ try {
1523
+ logSearchDebug("run Pagefind search", {
1524
+ currentLocale,
1525
+ query: trimmedQuery,
1526
+ routePrefix
1527
+ });
1528
+ const search = await pagefind.search(trimmedQuery, { limit: 8 });
1529
+ const data = await Promise.all(search.results.map(async (result) => ({
1530
+ id: result.id,
1531
+ data: await result.data()
1532
+ })));
1533
+ if (cancelled) return;
1534
+ logSearchDebug("Pagefind search results", {
1535
+ currentLocale,
1536
+ query: trimmedQuery,
1537
+ count: data.length
1538
+ });
1539
+ setFullTextState({
1540
+ key: fullTextKey,
1541
+ results: data.map(({ id, data }) => ({
1542
+ type: "full-text",
1543
+ id,
1544
+ title: data.meta.title || data.url,
1545
+ url: normalizePagefindUrl(data.url, routePrefix),
1546
+ excerpt: data.excerpt
1547
+ }))
1548
+ });
1549
+ } catch (error) {
1550
+ console.warn("[clarify:search] Pagefind search failed", {
1551
+ currentLocale,
1552
+ query: trimmedQuery,
1553
+ error
1554
+ });
1555
+ if (!cancelled) setFullTextState({
1556
+ key: fullTextKey,
1557
+ results: null
1558
+ });
1559
+ }
1560
+ });
1561
+ return () => {
1562
+ cancelled = true;
1563
+ };
1564
+ }, [
1565
+ currentLocale,
1566
+ fullTextKey,
1567
+ pagefind,
1568
+ routePrefix,
1569
+ trimmedQuery
1570
+ ]);
1175
1571
  (0, react.useEffect)(() => {
1176
1572
  if (open) return void 0;
1177
1573
  function onKeyDown(event) {
@@ -1224,10 +1620,11 @@ function SearchDialog(arg0) {
1224
1620
  query,
1225
1621
  setQuery: updateQuery,
1226
1622
  onClose: closeDialog,
1227
- onSubmit: () => selectResult()
1623
+ onSubmit: () => selectResult(),
1624
+ loading: searchInputLoading
1228
1625
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1229
1626
  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",
1230
- children: [query && results.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1627
+ children: [showNoResults ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1231
1628
  className: "p-6 text-center",
1232
1629
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.SearchX, { className: "mx-auto h-5 w-5 stroke-(--clarify-theme-tokens-colors-foreground) dark:stroke-zinc-600" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
1233
1630
  className: "mt-2 text-xs text-(--clarify-theme-tokens-colors-muted) dark:text-zinc-400",
@@ -1241,14 +1638,17 @@ function SearchDialog(arg0) {
1241
1638
  result,
1242
1639
  query,
1243
1640
  active: resultIndex === activeIndex,
1641
+ onActive: () => setActiveIndex(resultIndex),
1244
1642
  onSelect: () => selectResult(result)
1245
- }, result.url))
1643
+ }, result.type === "full-text" ? result.id : result.url))
1246
1644
  }) : null]
1247
1645
  })]
1248
1646
  })
1249
1647
  })]
1250
1648
  });
1251
1649
  }
1650
+ //#endregion
1651
+ //#region source/shell/search/useSearchProps.ts
1252
1652
  function useSearchProps() {
1253
1653
  const buttonRef = (0, react.useRef)(null);
1254
1654
  const [open, setOpen] = (0, react.useState)(false);
@@ -1265,12 +1665,14 @@ function useSearchProps() {
1265
1665
  }
1266
1666
  };
1267
1667
  }
1668
+ //#endregion
1669
+ //#region source/shell/Search.tsx
1268
1670
  function getModifierKey() {
1269
1671
  if (typeof navigator === "undefined") return "Ctrl ";
1270
1672
  return /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform) ? "⌘" : "Ctrl ";
1271
1673
  }
1272
1674
  function Search(arg0) {
1273
- const { routes, navigation } = arg0;
1675
+ const { routes, navigation, routePrefix, currentLocale } = arg0;
1274
1676
  const t = useBuiltInText();
1275
1677
  const modifierKey = getModifierKey();
1276
1678
  const { buttonProps, dialogProps } = useSearchProps();
@@ -1300,13 +1702,15 @@ function Search(arg0) {
1300
1702
  className: "hidden lg:block",
1301
1703
  routes,
1302
1704
  navigation,
1705
+ routePrefix,
1706
+ currentLocale,
1303
1707
  ...dialogProps
1304
1708
  })
1305
1709
  })]
1306
1710
  });
1307
1711
  }
1308
1712
  function MobileSearch(arg0) {
1309
- const { routes, navigation, onNavigate } = arg0;
1713
+ const { routes, navigation, routePrefix, currentLocale, onNavigate } = arg0;
1310
1714
  const t = useBuiltInText();
1311
1715
  const { buttonProps, dialogProps } = useSearchProps();
1312
1716
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -1323,6 +1727,8 @@ function MobileSearch(arg0) {
1323
1727
  className: "lg:hidden",
1324
1728
  routes,
1325
1729
  navigation,
1730
+ routePrefix,
1731
+ currentLocale,
1326
1732
  onNavigate,
1327
1733
  ...dialogProps
1328
1734
  })
@@ -1520,6 +1926,7 @@ var Header = (0, react.forwardRef)(function Header(arg0, ref) {
1520
1926
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(framer_motion.motion.header, {
1521
1927
  ...props,
1522
1928
  ref,
1929
+ "data-pagefind-ignore": true,
1523
1930
  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"),
1524
1931
  style: {
1525
1932
  "--bg-opacity-light": bgOpacityLight,
@@ -1547,7 +1954,7 @@ var Header = (0, react.forwardRef)(function Header(arg0, ref) {
1547
1954
  className: "clarify-brand flex min-w-0 items-center gap-2 no-underline",
1548
1955
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SiteLogo, {
1549
1956
  logo: config.logo,
1550
- className: "h-6 w-6 shrink-0"
1957
+ className: "h-6 w-auto shrink-0 object-contain"
1551
1958
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1552
1959
  className: "clarify-brand-title truncate font-semibold",
1553
1960
  children: config.title
@@ -1558,7 +1965,9 @@ var Header = (0, react.forwardRef)(function Header(arg0, ref) {
1558
1965
  className: "clarify-header-center absolute left-1/2 hidden -translate-x-1/2 lg:block",
1559
1966
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Search, {
1560
1967
  routes,
1561
- navigation
1968
+ navigation,
1969
+ routePrefix: config.routePrefix,
1970
+ currentLocale
1562
1971
  })
1563
1972
  }),
1564
1973
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -1578,7 +1987,9 @@ var Header = (0, react.forwardRef)(function Header(arg0, ref) {
1578
1987
  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,
1579
1988
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileSearch, {
1580
1989
  routes,
1581
- navigation
1990
+ navigation,
1991
+ routePrefix: config.routePrefix,
1992
+ currentLocale
1582
1993
  }),
1583
1994
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LanguageSwitcher, {
1584
1995
  config,
@@ -1652,6 +2063,24 @@ Object.defineProperty(exports, "ThemeToggle", {
1652
2063
  return ThemeToggle;
1653
2064
  }
1654
2065
  });
2066
+ Object.defineProperty(exports, "applyThemeCssVariables", {
2067
+ enumerable: true,
2068
+ get: function() {
2069
+ return applyThemeCssVariables;
2070
+ }
2071
+ });
2072
+ Object.defineProperty(exports, "clarifyThemePresets", {
2073
+ enumerable: true,
2074
+ get: function() {
2075
+ return clarifyThemePresets;
2076
+ }
2077
+ });
2078
+ Object.defineProperty(exports, "cloneTheme", {
2079
+ enumerable: true,
2080
+ get: function() {
2081
+ return cloneTheme;
2082
+ }
2083
+ });
1655
2084
  Object.defineProperty(exports, "copyTextToClipboard", {
1656
2085
  enumerable: true,
1657
2086
  get: function() {
@@ -1706,12 +2135,42 @@ Object.defineProperty(exports, "resolveLucideIconName", {
1706
2135
  return resolveLucideIconName;
1707
2136
  }
1708
2137
  });
2138
+ Object.defineProperty(exports, "resolveThemeColorValue", {
2139
+ enumerable: true,
2140
+ get: function() {
2141
+ return resolveThemeColorValue;
2142
+ }
2143
+ });
2144
+ Object.defineProperty(exports, "resolveThemeVariableTargets", {
2145
+ enumerable: true,
2146
+ get: function() {
2147
+ return resolveThemeVariableTargets;
2148
+ }
2149
+ });
1709
2150
  Object.defineProperty(exports, "safeDecodeURIComponent", {
1710
2151
  enumerable: true,
1711
2152
  get: function() {
1712
2153
  return safeDecodeURIComponent;
1713
2154
  }
1714
2155
  });
2156
+ Object.defineProperty(exports, "themeBootstrapScript", {
2157
+ enumerable: true,
2158
+ get: function() {
2159
+ return themeBootstrapScript;
2160
+ }
2161
+ });
2162
+ Object.defineProperty(exports, "themeStorageKey", {
2163
+ enumerable: true,
2164
+ get: function() {
2165
+ return themeStorageKey;
2166
+ }
2167
+ });
2168
+ Object.defineProperty(exports, "themeToCssVariables", {
2169
+ enumerable: true,
2170
+ get: function() {
2171
+ return themeToCssVariables;
2172
+ }
2173
+ });
1715
2174
  Object.defineProperty(exports, "useBuiltInText", {
1716
2175
  enumerable: true,
1717
2176
  get: function() {
@@ -1724,6 +2183,12 @@ Object.defineProperty(exports, "useClarifyConfig", {
1724
2183
  return useClarifyConfig;
1725
2184
  }
1726
2185
  });
2186
+ Object.defineProperty(exports, "useClarifyLocale", {
2187
+ enumerable: true,
2188
+ get: function() {
2189
+ return useClarifyLocale;
2190
+ }
2191
+ });
1727
2192
  Object.defineProperty(exports, "useOpenApis", {
1728
2193
  enumerable: true,
1729
2194
  get: function() {
@@ -1743,4 +2208,4 @@ Object.defineProperty(exports, "useTheme", {
1743
2208
  }
1744
2209
  });
1745
2210
 
1746
- //# sourceMappingURL=shell-D4tS8Jts.cjs.map
2211
+ //# sourceMappingURL=shell-xxhV0p7k.cjs.map