@clarify-labs/renderer 0.6.7 → 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
@@ -3,7 +3,7 @@ import { Fragment, Suspense, createContext, forwardRef, useContext, useEffect, u
3
3
  import { Link, useLocation, useNavigate } from "react-router-dom";
4
4
  import { CloseButton, Dialog, DialogBackdrop, DialogPanel, Menu, MenuButton, MenuItem, MenuItems, TransitionChild } from "@headlessui/react";
5
5
  import * as LucideIcons from "lucide-react";
6
- import { Check, ChevronDown, Copy, ExternalLink, FileText, Globe2, Link2, Menu as Menu$1, Moon, MoreHorizontal, PencilLine, Search, SearchX, Sun, X } from "lucide-react";
6
+ import { Check, ChevronDown, Copy, ExternalLink, FileText, Globe2, Link2, LoaderCircle, Menu as Menu$1, Moon, MoreHorizontal, PencilLine, Search, SearchX, Sun, X } from "lucide-react";
7
7
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
8
  import { AnimatePresence, motion, useIsPresent, useScroll, useTransform } from "framer-motion";
9
9
  import { create, createStore, useStore } from "zustand";
@@ -16,6 +16,9 @@ function useClarifyConfig() {
16
16
  if (!config) throw new Error("[clarify] useClarifyConfig must be used within a ClarifyConfigContext.Provider");
17
17
  return config;
18
18
  }
19
+ function useClarifyLocale() {
20
+ return useContext(ClarifyLocaleContext);
21
+ }
19
22
  function useOpenApis() {
20
23
  return useContext(OpenApisContext);
21
24
  }
@@ -328,10 +331,10 @@ function ContentActions(arg0) {
328
331
  const primaryAction = actions[0];
329
332
  const PrimaryIcon = primaryAction && copied === primaryAction.key ? Check : primaryAction?.icon ?? PencilLine;
330
333
  return /* @__PURE__ */ jsx("div", {
331
- className: `clarify-content-actions sticky z-20 flex justify-end py-4 ${hasTabs ? "top-16 lg:top-30" : "top-16"}`,
334
+ className: `clarify-content-actions pointer-events-none sticky z-20 flex justify-end py-4 ${hasTabs ? "top-16 lg:top-30" : "top-16"}`,
332
335
  children: /* @__PURE__ */ jsxs(Menu, {
333
336
  as: "div",
334
- className: "clarify-content-actions-menu relative inline-flex text-sm font-medium",
337
+ className: "clarify-content-actions-menu pointer-events-auto relative inline-flex text-sm font-medium",
335
338
  children: [/* @__PURE__ */ jsxs("div", {
336
339
  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",
337
340
  children: [primaryAction ? /* @__PURE__ */ jsxs("button", {
@@ -480,9 +483,178 @@ function ContentActions(arg0) {
480
483
  });
481
484
  }
482
485
  //#endregion
486
+ //#region source/theme/variables.ts
487
+ var themeStorageKey = "clarify:theme";
488
+ var clarifyThemePresets = {
489
+ default: {
490
+ preset: "default",
491
+ tokens: {
492
+ colors: {
493
+ primary: "#047857",
494
+ accent: "#0D9488",
495
+ background: "#ffffff",
496
+ foreground: "#111827",
497
+ surface: "#ffffff",
498
+ muted: "#64748b",
499
+ border: "rgb(15 23 42 / 0.12)",
500
+ codeBackground: "#f6fbf8"
501
+ },
502
+ radius: {
503
+ sm: "6px",
504
+ md: "10px",
505
+ lg: "14px",
506
+ xl: "18px"
507
+ }
508
+ },
509
+ layout: { maxWidth: "82rem" },
510
+ editor: false
511
+ },
512
+ base: {
513
+ preset: "base",
514
+ tokens: {
515
+ colors: {
516
+ primary: "#18181b",
517
+ accent: "#52525b",
518
+ background: "#ffffff",
519
+ foreground: "#18181b",
520
+ surface: "#ffffff",
521
+ muted: "#71717a",
522
+ border: "rgb(24 24 27 / 0.12)",
523
+ codeBackground: "#f4f4f5"
524
+ },
525
+ radius: {
526
+ sm: "6px",
527
+ md: "8px",
528
+ lg: "12px",
529
+ xl: "16px"
530
+ }
531
+ },
532
+ layout: { maxWidth: "80rem" },
533
+ editor: false
534
+ }
535
+ };
536
+ function cloneThemeColorValue(value) {
537
+ return typeof value === "string" ? value : { ...value };
538
+ }
539
+ function cloneTheme(theme) {
540
+ return {
541
+ preset: theme.preset,
542
+ tokens: {
543
+ colors: {
544
+ primary: cloneThemeColorValue(theme.tokens.colors.primary),
545
+ accent: cloneThemeColorValue(theme.tokens.colors.accent),
546
+ background: cloneThemeColorValue(theme.tokens.colors.background),
547
+ foreground: cloneThemeColorValue(theme.tokens.colors.foreground),
548
+ surface: cloneThemeColorValue(theme.tokens.colors.surface),
549
+ muted: cloneThemeColorValue(theme.tokens.colors.muted),
550
+ border: cloneThemeColorValue(theme.tokens.colors.border),
551
+ codeBackground: cloneThemeColorValue(theme.tokens.colors.codeBackground)
552
+ },
553
+ radius: { ...theme.tokens.radius }
554
+ },
555
+ layout: { ...theme.layout },
556
+ editor: theme.editor
557
+ };
558
+ }
559
+ function isModeColorValue(value) {
560
+ return typeof value === "object" && value !== null;
561
+ }
562
+ function resolveThemeColorValue(value, resolvedTheme = "light") {
563
+ if (!isModeColorValue(value)) return value;
564
+ return value[resolvedTheme] ?? value.light ?? value.dark ?? "";
565
+ }
566
+ function resolveThemeColors(colors, resolvedTheme = "light") {
567
+ return {
568
+ primary: resolveThemeColorValue(colors.primary, resolvedTheme),
569
+ accent: resolveThemeColorValue(colors.accent, resolvedTheme),
570
+ background: resolveThemeColorValue(colors.background, resolvedTheme),
571
+ foreground: resolveThemeColorValue(colors.foreground, resolvedTheme),
572
+ surface: resolveThemeColorValue(colors.surface, resolvedTheme),
573
+ muted: resolveThemeColorValue(colors.muted, resolvedTheme),
574
+ border: resolveThemeColorValue(colors.border, resolvedTheme),
575
+ codeBackground: resolveThemeColorValue(colors.codeBackground, resolvedTheme)
576
+ };
577
+ }
578
+ function matchesPresetTheme(theme) {
579
+ const preset = clarifyThemePresets[theme.preset];
580
+ return JSON.stringify({
581
+ tokens: theme.tokens,
582
+ layout: theme.layout
583
+ }) === JSON.stringify({
584
+ tokens: preset.tokens,
585
+ layout: preset.layout
586
+ });
587
+ }
588
+ function effectiveTheme(theme, resolvedTheme) {
589
+ if (resolvedTheme !== "dark" || !matchesPresetTheme(theme)) return theme;
590
+ return {
591
+ ...theme,
592
+ tokens: {
593
+ ...theme.tokens,
594
+ colors: {
595
+ ...theme.tokens.colors,
596
+ background: "#09090b",
597
+ foreground: "#ffffff",
598
+ surface: "#18181b",
599
+ muted: "#a1a1aa",
600
+ border: "rgb(255 255 255 / 0.1)",
601
+ codeBackground: "#18181b"
602
+ }
603
+ }
604
+ };
605
+ }
606
+ function themeToCssVariables(theme, resolvedTheme) {
607
+ const resolved = effectiveTheme(theme, resolvedTheme);
608
+ const colors = resolveThemeColors(resolved.tokens.colors, resolvedTheme);
609
+ const { radius } = resolved.tokens;
610
+ return {
611
+ "--clarify-theme-tokens-colors-primary": colors.primary,
612
+ "--clarify-theme-tokens-colors-accent": colors.accent,
613
+ "--clarify-theme-tokens-colors-background": colors.background,
614
+ "--clarify-theme-tokens-colors-foreground": colors.foreground,
615
+ "--clarify-theme-tokens-colors-surface": colors.surface,
616
+ "--clarify-theme-tokens-colors-muted": colors.muted,
617
+ "--clarify-theme-tokens-colors-border": colors.border,
618
+ "--clarify-theme-tokens-colors-code-background": colors.codeBackground,
619
+ "--clarify-theme-tokens-radius-sm": radius.sm,
620
+ "--clarify-theme-tokens-radius-md": radius.md,
621
+ "--clarify-theme-tokens-radius-lg": radius.lg,
622
+ "--clarify-theme-tokens-radius-xl": radius.xl,
623
+ "--clarify-theme-layout-max-width": resolved.layout.maxWidth
624
+ };
625
+ }
626
+ function themeBootstrapScript(theme = clarifyThemePresets.default) {
627
+ const darkVariables = themeToCssVariables(theme, "dark");
628
+ const lightVariables = themeToCssVariables(theme, "light");
629
+ 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){}})();`;
630
+ }
631
+ function uniqueElements(elements) {
632
+ return Array.from(new Set(elements));
633
+ }
634
+ function resolveThemeVariableTargets(target) {
635
+ if (typeof document === "undefined") return [];
636
+ if (target instanceof HTMLElement) return [target];
637
+ if (typeof target === "string") return Array.from(document.querySelectorAll(target));
638
+ return uniqueElements([document.documentElement, ...Array.from(document.querySelectorAll(".clarify-app"))]);
639
+ }
640
+ function applyThemeCssVariables(variables, targets) {
641
+ const previousValues = /* @__PURE__ */ new Map();
642
+ for (const element of targets) {
643
+ const elementPreviousValues = /* @__PURE__ */ new Map();
644
+ for (const [property, value] of Object.entries(variables)) {
645
+ elementPreviousValues.set(property, element.style.getPropertyValue(property));
646
+ element.style.setProperty(property, value);
647
+ }
648
+ previousValues.set(element, elementPreviousValues);
649
+ }
650
+ return () => {
651
+ for (const [element, elementPreviousValues] of previousValues) for (const [property, previousValue] of elementPreviousValues) if (previousValue) element.style.setProperty(property, previousValue);
652
+ else element.style.removeProperty(property);
653
+ };
654
+ }
655
+ //#endregion
483
656
  //#region source/theme/ThemeProvider.tsx
484
657
  var ThemeContext = createContext(null);
485
- var storageKey = "clarify:theme";
486
658
  function getSystemTheme() {
487
659
  if (typeof window === "undefined") return "light";
488
660
  return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
@@ -490,7 +662,7 @@ function getSystemTheme() {
490
662
  function getStoredTheme() {
491
663
  if (typeof window === "undefined") return "system";
492
664
  try {
493
- const storedTheme = window.localStorage.getItem(storageKey);
665
+ const storedTheme = window.localStorage.getItem(themeStorageKey);
494
666
  return storedTheme === "light" || storedTheme === "dark" || storedTheme === "system" ? storedTheme : "system";
495
667
  } catch {
496
668
  return "system";
@@ -499,7 +671,7 @@ function getStoredTheme() {
499
671
  function storeTheme(theme) {
500
672
  if (typeof window === "undefined") return;
501
673
  try {
502
- window.localStorage.setItem(storageKey, theme);
674
+ window.localStorage.setItem(themeStorageKey, theme);
503
675
  } catch {}
504
676
  }
505
677
  function applyTheme(resolvedTheme) {
@@ -844,7 +1016,7 @@ function NavigationGroup(arg0) {
844
1016
  const [pathname, sections] = useInitialValue([normalizeRoutePath(useLocation().pathname), useSectionStore((s) => s.sections)], isInsideMobileNavigation);
845
1017
  const isActiveGroup = group.links.findIndex((link) => isSameRoutePath(link.href, pathname)) !== -1;
846
1018
  return /* @__PURE__ */ jsxs("li", {
847
- className: clsx("clarify-navigation-group relative mt-6", className),
1019
+ className: clsx("clarify-navigation-group relative mb-6", className),
848
1020
  children: [/* @__PURE__ */ jsxs("h2", {
849
1021
  className: "clarify-navigation-group-title flex items-center gap-2",
850
1022
  children: [/* @__PURE__ */ jsx(NavigationIcon, {
@@ -1043,7 +1215,7 @@ function MobileNavigation(arg0) {
1043
1215
  });
1044
1216
  }
1045
1217
  //#endregion
1046
- //#region source/shell/Search.tsx
1218
+ //#region source/shell/search/items.ts
1047
1219
  function routeGroupTitles(navigation) {
1048
1220
  const titles = /* @__PURE__ */ new Map();
1049
1221
  for (const node of navigation) if (node.children?.length) for (const child of node.children) titles.set(child.path, node.title);
@@ -1080,53 +1252,85 @@ function buildSearchItems(routes, navigation) {
1080
1252
  })) ?? []];
1081
1253
  });
1082
1254
  }
1083
- function escapeRegExp(value) {
1084
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1085
- }
1086
- function HighlightQuery(arg0) {
1087
- const { text, query } = arg0;
1088
- if (!query) return text;
1089
- return /* @__PURE__ */ jsx(Fragment$1, { children: text.split(new RegExp(`(${escapeRegExp(query)})`, "ig")).map((part, index) => part.toLowerCase() === query.toLowerCase() ? /* @__PURE__ */ jsx("mark", {
1090
- className: "bg-transparent text-(--clarify-theme-tokens-colors-primary) underline",
1091
- children: part
1092
- }, index) : /* @__PURE__ */ jsx(Fragment, { children: part }, index)) });
1255
+ //#endregion
1256
+ //#region source/shell/search/pagefind.ts
1257
+ var pagefindPromises = /* @__PURE__ */ new Map();
1258
+ function pagefindCacheKey(routePrefix, locale) {
1259
+ return `${routePrefix || "/"}:${locale || "default"}`;
1093
1260
  }
1094
- function SearchResult(arg0) {
1095
- const { result, query, active, onSelect } = arg0;
1096
- const id = useId();
1097
- const hierarchy = [result.sectionTitle, result.pageTitle].filter((value) => typeof value === "string");
1098
- return /* @__PURE__ */ jsxs("li", {
1099
- id,
1100
- className: clsx("clarify-search-result group block cursor-default px-4 py-3", active && "clarify-search-result-active"),
1101
- "aria-selected": active,
1102
- onMouseDown: (event) => {
1103
- event.preventDefault();
1104
- onSelect();
1105
- },
1106
- children: [/* @__PURE__ */ jsx("div", {
1107
- className: "clarify-search-result-title",
1108
- children: /* @__PURE__ */ jsx(HighlightQuery, {
1109
- text: result.title,
1110
- query
1111
- })
1112
- }), hierarchy.length > 0 ? /* @__PURE__ */ jsx("div", {
1113
- className: "clarify-search-result-hierarchy mt-1 truncate whitespace-nowrap",
1114
- children: hierarchy.map((item, itemIndex, items) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(HighlightQuery, {
1115
- text: item,
1116
- query
1117
- }), /* @__PURE__ */ jsx("span", {
1118
- className: itemIndex === items.length - 1 ? "sr-only" : "clarify-search-result-separator mx-2",
1119
- children: "/"
1120
- })] }, `${item}-${itemIndex}`))
1121
- }) : null]
1261
+ function logSearchDebug(message, data) {
1262
+ if (typeof window === "undefined") return;
1263
+ console.info(`[clarify:search] ${message}`, data ?? "");
1264
+ }
1265
+ function loadPagefind(routePrefix, locale) {
1266
+ if (typeof window === "undefined") return Promise.resolve(null);
1267
+ const language = locale ?? document.documentElement.lang;
1268
+ const cacheKey = pagefindCacheKey(routePrefix, language);
1269
+ const cachedPagefind = pagefindPromises.get(cacheKey);
1270
+ if (cachedPagefind) {
1271
+ logSearchDebug("reuse Pagefind instance promise", {
1272
+ cacheKey,
1273
+ language,
1274
+ routePrefix
1275
+ });
1276
+ return cachedPagefind;
1277
+ }
1278
+ const pagefindUrl = prefixHref("/pagefind/pagefind.js", routePrefix);
1279
+ logSearchDebug("create Pagefind instance promise", {
1280
+ cacheKey,
1281
+ language,
1282
+ pagefindUrl,
1283
+ routePrefix
1284
+ });
1285
+ const pagefindPromise = import(
1286
+ /* @vite-ignore */
1287
+ pagefindUrl
1288
+ ).then(async (module) => {
1289
+ const previousLanguage = document.documentElement.lang;
1290
+ if (language) document.documentElement.lang = language;
1291
+ logSearchDebug("create Pagefind instance", {
1292
+ cacheKey,
1293
+ detectedLanguage: document.documentElement.lang,
1294
+ previousLanguage
1295
+ });
1296
+ const pagefind = module.createInstance();
1297
+ if (previousLanguage && previousLanguage !== language) document.documentElement.lang = previousLanguage;
1298
+ await pagefind.init?.();
1299
+ logSearchDebug("Pagefind instance ready", {
1300
+ cacheKey,
1301
+ language
1302
+ });
1303
+ return pagefind;
1304
+ }).catch((error) => {
1305
+ pagefindPromises.delete(cacheKey);
1306
+ console.warn("[clarify:search] Pagefind instance failed", {
1307
+ cacheKey,
1308
+ language,
1309
+ error
1310
+ });
1311
+ return null;
1122
1312
  });
1313
+ pagefindPromises.set(cacheKey, pagefindPromise);
1314
+ return pagefindPromise;
1315
+ }
1316
+ function normalizePagefindUrl(url, routePrefix) {
1317
+ const parsedUrl = new URL(url, window.location.origin);
1318
+ let pathname = parsedUrl.pathname;
1319
+ const prefix = routePrefix && routePrefix !== "/" ? `/${routePrefix.replace(/^\/+|\/+$/g, "")}` : "";
1320
+ if (prefix && (pathname === prefix || pathname.startsWith(`${prefix}/`))) pathname = pathname.slice(prefix.length) || "/";
1321
+ return `${pathname}${parsedUrl.search}${parsedUrl.hash}`;
1123
1322
  }
1323
+ //#endregion
1324
+ //#region source/shell/search/SearchInput.tsx
1124
1325
  var SearchInput = forwardRef(function SearchInput(arg0, inputRef) {
1125
- const { query, setQuery, onClose, onSubmit, activeDescendantId } = arg0;
1326
+ const { query, setQuery, onClose, onSubmit, activeDescendantId, loading = false } = arg0;
1126
1327
  const t = useBuiltInText();
1127
1328
  return /* @__PURE__ */ jsxs("div", {
1128
1329
  className: "clarify-search-input group relative flex h-12",
1129
- children: [/* @__PURE__ */ jsx(Search, { className: "pointer-events-none absolute top-0 left-3 h-full w-5 stroke-(--clarify-theme-tokens-colors-muted)" }), /* @__PURE__ */ jsx("input", {
1330
+ children: [/* @__PURE__ */ jsx(loading ? LoaderCircle : Search, {
1331
+ "aria-hidden": "true",
1332
+ className: clsx("pointer-events-none absolute top-0 left-3 h-full w-5 stroke-(--clarify-theme-tokens-colors-muted)", loading && "animate-spin")
1333
+ }), /* @__PURE__ */ jsx("input", {
1130
1334
  ref: inputRef,
1131
1335
  "data-autofocus": true,
1132
1336
  role: "combobox",
@@ -1148,20 +1352,120 @@ var SearchInput = forwardRef(function SearchInput(arg0, inputRef) {
1148
1352
  })]
1149
1353
  });
1150
1354
  });
1355
+ //#endregion
1356
+ //#region source/shell/search/Highlight.tsx
1357
+ function stripHtml(value) {
1358
+ if (typeof document === "undefined") return value.replace(/<[^>]*>/g, "");
1359
+ const template = document.createElement("template");
1360
+ template.innerHTML = value;
1361
+ return template.content.textContent ?? "";
1362
+ }
1363
+ function escapeRegExp(value) {
1364
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1365
+ }
1366
+ function HighlightQuery(arg0) {
1367
+ const { text, query } = arg0;
1368
+ if (!query) return text;
1369
+ return /* @__PURE__ */ jsx(Fragment$1, { children: text.split(new RegExp(`(${escapeRegExp(query)})`, "ig")).map((part, index) => part.toLowerCase() === query.toLowerCase() ? /* @__PURE__ */ jsx("mark", {
1370
+ className: "bg-transparent text-(--clarify-theme-tokens-colors-primary) underline",
1371
+ children: part
1372
+ }, index) : /* @__PURE__ */ jsx(Fragment, { children: part }, index)) });
1373
+ }
1374
+ function renderExcerptNode(node, key) {
1375
+ if (node.nodeType === Node.TEXT_NODE) return node.textContent;
1376
+ if (node.nodeType !== Node.ELEMENT_NODE) return null;
1377
+ const element = node;
1378
+ const children = Array.from(element.childNodes).map((child, index) => renderExcerptNode(child, `${key}-${index}`));
1379
+ if (element.tagName.toLowerCase() === "mark") return /* @__PURE__ */ jsx("mark", {
1380
+ className: "bg-transparent text-(--clarify-theme-tokens-colors-primary) underline",
1381
+ children
1382
+ }, key);
1383
+ return /* @__PURE__ */ jsx(Fragment, { children }, key);
1384
+ }
1385
+ function HighlightExcerpt(arg0) {
1386
+ const { excerpt, query } = arg0;
1387
+ if (typeof document === "undefined" || !excerpt.includes("<mark")) return /* @__PURE__ */ jsx(HighlightQuery, {
1388
+ text: stripHtml(excerpt),
1389
+ query
1390
+ });
1391
+ const template = document.createElement("template");
1392
+ template.innerHTML = excerpt;
1393
+ return /* @__PURE__ */ jsx(Fragment$1, { children: Array.from(template.content.childNodes).map((node, index) => renderExcerptNode(node, String(index))) });
1394
+ }
1395
+ //#endregion
1396
+ //#region source/shell/search/SearchResult.tsx
1397
+ function SearchResult(arg0) {
1398
+ const { result, query, active, onActive, onSelect } = arg0;
1399
+ const id = useId();
1400
+ const hierarchy = result.type === "quick" ? [result.sectionTitle, result.pageTitle].filter((value) => typeof value === "string") : [];
1401
+ return /* @__PURE__ */ jsxs("li", {
1402
+ id,
1403
+ className: clsx("clarify-search-result group block cursor-pointer px-4 py-3", active && "clarify-search-result-active"),
1404
+ "aria-selected": active,
1405
+ onMouseEnter: onActive,
1406
+ onMouseMove: onActive,
1407
+ onMouseDown: (event) => {
1408
+ event.preventDefault();
1409
+ onSelect();
1410
+ },
1411
+ children: [
1412
+ /* @__PURE__ */ jsx("div", {
1413
+ className: "clarify-search-result-title",
1414
+ children: /* @__PURE__ */ jsx(HighlightQuery, {
1415
+ text: result.title,
1416
+ query
1417
+ })
1418
+ }),
1419
+ hierarchy.length > 0 ? /* @__PURE__ */ jsx("div", {
1420
+ className: "clarify-search-result-hierarchy mt-1 truncate whitespace-nowrap",
1421
+ children: hierarchy.map((item, itemIndex, items) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(HighlightQuery, {
1422
+ text: item,
1423
+ query
1424
+ }), /* @__PURE__ */ jsx("span", {
1425
+ className: itemIndex === items.length - 1 ? "sr-only" : "clarify-search-result-separator mx-2",
1426
+ children: "/"
1427
+ })] }, `${item}-${itemIndex}`))
1428
+ }) : null,
1429
+ result.type === "full-text" && result.excerpt ? /* @__PURE__ */ jsx("p", {
1430
+ className: "clarify-search-result-excerpt mt-1 line-clamp-2 text-xs leading-5 text-(--clarify-theme-tokens-colors-muted)",
1431
+ children: /* @__PURE__ */ jsx(HighlightExcerpt, {
1432
+ excerpt: result.excerpt,
1433
+ query
1434
+ })
1435
+ }) : null
1436
+ ]
1437
+ });
1438
+ }
1439
+ //#endregion
1440
+ //#region source/shell/search/SearchDialog.tsx
1151
1441
  function SearchDialog(arg0) {
1152
- const { open, setOpen, routes, navigation, className, onNavigate = () => {} } = arg0;
1442
+ const { open, setOpen, routes, navigation, routePrefix = "/", currentLocale, className, onNavigate = () => {} } = arg0;
1153
1443
  const t = useBuiltInText();
1154
1444
  const navigate = useNavigate();
1155
1445
  const location = useLocation();
1156
1446
  const inputRef = useRef(null);
1157
1447
  const [query, setQuery] = useState("");
1158
1448
  const [activeIndex, setActiveIndex] = useState(0);
1449
+ const [fullTextState, setFullTextState] = useState(null);
1450
+ const [pagefindState, setPagefindState] = useState(null);
1159
1451
  const searchItems = useMemo(() => buildSearchItems(routes, navigation), [navigation, routes]);
1160
- const results = useMemo(() => {
1452
+ const quickResults = useMemo(() => {
1161
1453
  const normalizedQuery = query.trim().toLowerCase();
1162
1454
  if (!normalizedQuery) return [];
1163
- return searchItems.filter((item) => item.keywords.includes(normalizedQuery)).slice(0, 8);
1455
+ return searchItems.filter((item) => item.keywords.includes(normalizedQuery)).slice(0, 8).map((item) => ({
1456
+ ...item,
1457
+ type: "quick"
1458
+ }));
1164
1459
  }, [query, searchItems]);
1460
+ const pagefindKey = pagefindCacheKey(routePrefix, currentLocale);
1461
+ const activePagefindState = pagefindState?.key === pagefindKey ? pagefindState : null;
1462
+ const pagefind = activePagefindState?.pagefind ?? null;
1463
+ const pagefindAvailable = activePagefindState?.available ?? null;
1464
+ const trimmedQuery = query.trim();
1465
+ const fullTextKey = `${pagefindKey}:${trimmedQuery}`;
1466
+ const results = (fullTextState?.key === fullTextKey ? fullTextState.results : null) ?? quickResults;
1467
+ const searchInputLoading = pagefindAvailable === null || Boolean(trimmedQuery && pagefind && fullTextState?.key !== fullTextKey);
1468
+ const showNoResults = query && results.length === 0 && pagefindAvailable !== null;
1165
1469
  useEffect(() => {
1166
1470
  setOpen(false);
1167
1471
  }, [
@@ -1170,6 +1474,98 @@ function SearchDialog(arg0) {
1170
1474
  location.hash,
1171
1475
  setOpen
1172
1476
  ]);
1477
+ useEffect(() => {
1478
+ let cancelled = false;
1479
+ logSearchDebug("locale or route prefix changed; reload Pagefind", {
1480
+ currentLocale,
1481
+ routePrefix,
1482
+ documentLanguage: document.documentElement.lang
1483
+ });
1484
+ loadPagefind(routePrefix, currentLocale).then((loadedPagefind) => {
1485
+ if (cancelled) {
1486
+ logSearchDebug("ignore stale Pagefind load", {
1487
+ currentLocale,
1488
+ routePrefix
1489
+ });
1490
+ return;
1491
+ }
1492
+ logSearchDebug("Pagefind load applied", {
1493
+ currentLocale,
1494
+ routePrefix,
1495
+ available: Boolean(loadedPagefind)
1496
+ });
1497
+ setPagefindState({
1498
+ key: pagefindKey,
1499
+ pagefind: loadedPagefind,
1500
+ available: Boolean(loadedPagefind)
1501
+ });
1502
+ });
1503
+ return () => {
1504
+ cancelled = true;
1505
+ logSearchDebug("cancel Pagefind load effect", {
1506
+ currentLocale,
1507
+ routePrefix
1508
+ });
1509
+ };
1510
+ }, [
1511
+ currentLocale,
1512
+ pagefindKey,
1513
+ routePrefix
1514
+ ]);
1515
+ useEffect(() => {
1516
+ let cancelled = false;
1517
+ if (!trimmedQuery || !pagefind) return void 0;
1518
+ Promise.resolve().then(async () => {
1519
+ if (cancelled) return;
1520
+ try {
1521
+ logSearchDebug("run Pagefind search", {
1522
+ currentLocale,
1523
+ query: trimmedQuery,
1524
+ routePrefix
1525
+ });
1526
+ const search = await pagefind.search(trimmedQuery, { limit: 8 });
1527
+ const data = await Promise.all(search.results.map(async (result) => ({
1528
+ id: result.id,
1529
+ data: await result.data()
1530
+ })));
1531
+ if (cancelled) return;
1532
+ logSearchDebug("Pagefind search results", {
1533
+ currentLocale,
1534
+ query: trimmedQuery,
1535
+ count: data.length
1536
+ });
1537
+ setFullTextState({
1538
+ key: fullTextKey,
1539
+ results: data.map(({ id, data }) => ({
1540
+ type: "full-text",
1541
+ id,
1542
+ title: data.meta.title || data.url,
1543
+ url: normalizePagefindUrl(data.url, routePrefix),
1544
+ excerpt: data.excerpt
1545
+ }))
1546
+ });
1547
+ } catch (error) {
1548
+ console.warn("[clarify:search] Pagefind search failed", {
1549
+ currentLocale,
1550
+ query: trimmedQuery,
1551
+ error
1552
+ });
1553
+ if (!cancelled) setFullTextState({
1554
+ key: fullTextKey,
1555
+ results: null
1556
+ });
1557
+ }
1558
+ });
1559
+ return () => {
1560
+ cancelled = true;
1561
+ };
1562
+ }, [
1563
+ currentLocale,
1564
+ fullTextKey,
1565
+ pagefind,
1566
+ routePrefix,
1567
+ trimmedQuery
1568
+ ]);
1173
1569
  useEffect(() => {
1174
1570
  if (open) return void 0;
1175
1571
  function onKeyDown(event) {
@@ -1222,10 +1618,11 @@ function SearchDialog(arg0) {
1222
1618
  query,
1223
1619
  setQuery: updateQuery,
1224
1620
  onClose: closeDialog,
1225
- onSubmit: () => selectResult()
1621
+ onSubmit: () => selectResult(),
1622
+ loading: searchInputLoading
1226
1623
  }), /* @__PURE__ */ jsxs("div", {
1227
1624
  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",
1228
- children: [query && results.length === 0 ? /* @__PURE__ */ jsxs("div", {
1625
+ children: [showNoResults ? /* @__PURE__ */ jsxs("div", {
1229
1626
  className: "p-6 text-center",
1230
1627
  children: [/* @__PURE__ */ jsx(SearchX, { className: "mx-auto h-5 w-5 stroke-(--clarify-theme-tokens-colors-foreground) dark:stroke-zinc-600" }), /* @__PURE__ */ jsx("p", {
1231
1628
  className: "mt-2 text-xs text-(--clarify-theme-tokens-colors-muted) dark:text-zinc-400",
@@ -1239,14 +1636,17 @@ function SearchDialog(arg0) {
1239
1636
  result,
1240
1637
  query,
1241
1638
  active: resultIndex === activeIndex,
1639
+ onActive: () => setActiveIndex(resultIndex),
1242
1640
  onSelect: () => selectResult(result)
1243
- }, result.url))
1641
+ }, result.type === "full-text" ? result.id : result.url))
1244
1642
  }) : null]
1245
1643
  })]
1246
1644
  })
1247
1645
  })]
1248
1646
  });
1249
1647
  }
1648
+ //#endregion
1649
+ //#region source/shell/search/useSearchProps.ts
1250
1650
  function useSearchProps() {
1251
1651
  const buttonRef = useRef(null);
1252
1652
  const [open, setOpen] = useState(false);
@@ -1263,12 +1663,14 @@ function useSearchProps() {
1263
1663
  }
1264
1664
  };
1265
1665
  }
1666
+ //#endregion
1667
+ //#region source/shell/Search.tsx
1266
1668
  function getModifierKey() {
1267
1669
  if (typeof navigator === "undefined") return "Ctrl ";
1268
1670
  return /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform) ? "⌘" : "Ctrl ";
1269
1671
  }
1270
1672
  function Search$1(arg0) {
1271
- const { routes, navigation } = arg0;
1673
+ const { routes, navigation, routePrefix, currentLocale } = arg0;
1272
1674
  const t = useBuiltInText();
1273
1675
  const modifierKey = getModifierKey();
1274
1676
  const { buttonProps, dialogProps } = useSearchProps();
@@ -1298,13 +1700,15 @@ function Search$1(arg0) {
1298
1700
  className: "hidden lg:block",
1299
1701
  routes,
1300
1702
  navigation,
1703
+ routePrefix,
1704
+ currentLocale,
1301
1705
  ...dialogProps
1302
1706
  })
1303
1707
  })]
1304
1708
  });
1305
1709
  }
1306
1710
  function MobileSearch(arg0) {
1307
- const { routes, navigation, onNavigate } = arg0;
1711
+ const { routes, navigation, routePrefix, currentLocale, onNavigate } = arg0;
1308
1712
  const t = useBuiltInText();
1309
1713
  const { buttonProps, dialogProps } = useSearchProps();
1310
1714
  return /* @__PURE__ */ jsxs("div", {
@@ -1321,6 +1725,8 @@ function MobileSearch(arg0) {
1321
1725
  className: "lg:hidden",
1322
1726
  routes,
1323
1727
  navigation,
1728
+ routePrefix,
1729
+ currentLocale,
1324
1730
  onNavigate,
1325
1731
  ...dialogProps
1326
1732
  })
@@ -1518,6 +1924,7 @@ var Header = forwardRef(function Header(arg0, ref) {
1518
1924
  return /* @__PURE__ */ jsxs(motion.header, {
1519
1925
  ...props,
1520
1926
  ref,
1927
+ "data-pagefind-ignore": true,
1521
1928
  className: clsx(className, "clarify-header fixed inset-x-0 top-0 z-50 border-b border-(--clarify-theme-tokens-colors-border) bg-(--clarify-theme-tokens-colors-background)/(--bg-opacity-light) backdrop-blur-xs transition dark:border-white/10 dark:bg-zinc-950/(--bg-opacity-dark) dark:backdrop-blur-sm", isInsideMobileNavigation && "bg-(--clarify-theme-tokens-colors-background) dark:bg-zinc-950"),
1522
1929
  style: {
1523
1930
  "--bg-opacity-light": bgOpacityLight,
@@ -1545,7 +1952,7 @@ var Header = forwardRef(function Header(arg0, ref) {
1545
1952
  className: "clarify-brand flex min-w-0 items-center gap-2 no-underline",
1546
1953
  children: [/* @__PURE__ */ jsx(SiteLogo, {
1547
1954
  logo: config.logo,
1548
- className: "h-6 w-6 shrink-0"
1955
+ className: "h-6 w-auto shrink-0 object-contain"
1549
1956
  }), /* @__PURE__ */ jsx("span", {
1550
1957
  className: "clarify-brand-title truncate font-semibold",
1551
1958
  children: config.title
@@ -1556,7 +1963,9 @@ var Header = forwardRef(function Header(arg0, ref) {
1556
1963
  className: "clarify-header-center absolute left-1/2 hidden -translate-x-1/2 lg:block",
1557
1964
  children: /* @__PURE__ */ jsx(Search$1, {
1558
1965
  routes,
1559
- navigation
1966
+ navigation,
1967
+ routePrefix: config.routePrefix,
1968
+ currentLocale
1560
1969
  })
1561
1970
  }),
1562
1971
  /* @__PURE__ */ jsxs("div", {
@@ -1576,7 +1985,9 @@ var Header = forwardRef(function Header(arg0, ref) {
1576
1985
  config.navbar?.links?.length ? /* @__PURE__ */ jsx("div", { className: "hidden md:block md:h-5 md:w-px md:bg-(--clarify-theme-tokens-colors-border) md:dark:bg-white/15" }) : null,
1577
1986
  /* @__PURE__ */ jsx(MobileSearch, {
1578
1987
  routes,
1579
- navigation
1988
+ navigation,
1989
+ routePrefix: config.routePrefix,
1990
+ currentLocale
1580
1991
  }),
1581
1992
  /* @__PURE__ */ jsx(LanguageSwitcher, {
1582
1993
  config,
@@ -1596,6 +2007,6 @@ var Header = forwardRef(function Header(arg0, ref) {
1596
2007
  });
1597
2008
  });
1598
2009
  //#endregion
1599
- export { useClarifyConfig as C, OpenApisContext as S, prefixHref as _, useSectionStore as a, ClarifyConfigContext as b, resolveLucideIconName as c, ThemeToggle as d, ThemeProvider as f, localizeHref as g, isExternalHref as h, SectionProvider as i, isSameRoutePath as l, ContentActions as m, Navigation as n, remToPx as o, useTheme as p, safeDecodeURIComponent as r, lucideIconRegistry as s, Header as t, normalizeRoutePath as u, copyTextToClipboard as v, useOpenApis as w, ClarifyLocaleContext as x, useBuiltInText as y };
2010
+ export { OpenApisContext as A, isExternalHref as C, useBuiltInText as D, copyTextToClipboard as E, useClarifyLocale as M, useOpenApis as N, ClarifyConfigContext as O, ContentActions as S, prefixHref as T, resolveThemeColorValue as _, useSectionStore as a, themeStorageKey as b, resolveLucideIconName as c, ThemeToggle as d, ThemeProvider as f, cloneTheme as g, clarifyThemePresets as h, SectionProvider as i, useClarifyConfig as j, ClarifyLocaleContext as k, isSameRoutePath as l, applyThemeCssVariables as m, Navigation as n, remToPx as o, useTheme as p, safeDecodeURIComponent as r, lucideIconRegistry as s, Header as t, normalizeRoutePath as u, resolveThemeVariableTargets as v, localizeHref as w, themeToCssVariables as x, themeBootstrapScript as y };
1600
2011
 
1601
- //# sourceMappingURL=shell-DvTfFx6M.js.map
2012
+ //# sourceMappingURL=shell-CumiARRe.js.map