boltdocs 3.2.1 → 3.3.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 (155) hide show
  1. package/bin/boltdocs.js +20 -1
  2. package/bin/preloader.mjs +28 -0
  3. package/dist/{adapters-ByYY44Zy.mjs → adapters-BmB4TKCc.mjs} +1 -1
  4. package/dist/{adapters-DvmtpdSF.cjs → adapters-Cp1Maurn.cjs} +1 -1
  5. package/dist/audit-CLXjMzwQ.mjs +11 -0
  6. package/dist/audit-COgjnQ5n.cjs +11 -0
  7. package/dist/build-BS2hefiL.cjs +6 -0
  8. package/dist/build-C5mNh9D-.mjs +6 -0
  9. package/dist/cache-CJE9nWLE.cjs +6 -0
  10. package/dist/cache-OY4HzIXl.mjs +6 -0
  11. package/dist/callout-oI_LCbxS.d.ts +71 -0
  12. package/dist/callout-plqx9Dw-.d.cts +71 -0
  13. package/dist/client/index.cjs +1265 -569
  14. package/dist/client/index.d.cts +3 -542
  15. package/dist/client/index.d.ts +3 -542
  16. package/dist/client/index.js +1167 -521
  17. package/dist/client/mdx.cjs +1 -1
  18. package/dist/client/mdx.d.cts +24 -2
  19. package/dist/client/mdx.d.ts +24 -2
  20. package/dist/client/mdx.js +1 -1
  21. package/dist/client/primitives.cjs +14 -4
  22. package/dist/client/primitives.d.cts +281 -38
  23. package/dist/client/primitives.d.ts +281 -38
  24. package/dist/client/primitives.js +5 -5
  25. package/dist/client/router.cjs +49 -0
  26. package/dist/client/router.d.cts +3 -0
  27. package/dist/client/router.d.ts +3 -0
  28. package/dist/client/router.js +8 -0
  29. package/dist/client/theme/reset.css +40 -4
  30. package/dist/{config-BpzaPsJj.d.cts → config-BoRlz0Ca.d.mts} +157 -14
  31. package/dist/{config-xtS0ZkMm.d.mts → config-CTsX_tGM.d.cts} +157 -14
  32. package/dist/config-Ceib-AOH.cjs +7 -0
  33. package/dist/config-DGLQsy7y.mjs +7 -0
  34. package/dist/{package-BcISI5-P.cjs → config-files-BYHDOrKn.mjs} +1 -1
  35. package/dist/config-files-D9cdBMl2.cjs +6 -0
  36. package/dist/config-jJh8WYJI.cjs +6 -0
  37. package/dist/csp-C4LmN1ko.cjs +6 -0
  38. package/dist/csp-D6JEOqKh.mjs +6 -0
  39. package/dist/dev-Ch3hEe5Y.cjs +6 -0
  40. package/dist/dev-QPNxysrd.mjs +6 -0
  41. package/dist/{docs-layout-BdtZ9z6s.js → docs-layout-CbZ7LDRe.js} +504 -249
  42. package/dist/{docs-layout-CFWI15Id.cjs → docs-layout-vzfXed1Q.cjs} +516 -254
  43. package/dist/{doctor-BBtmNJE0.cjs → doctor-B1_YL0Wt.cjs} +1 -1
  44. package/dist/doctor-C7whl4ED.cjs +6 -0
  45. package/dist/doctor-DmQnml2k.mjs +6 -0
  46. package/dist/{generator-COepVWGi.cjs → generator-BlW45ST7.cjs} +5 -3
  47. package/dist/{generator-CcOBN5vI.mjs → generator-BwknNejd.mjs} +5 -3
  48. package/dist/{handler-XX7cLTqe.cjs → handler-CDEoKARD.cjs} +2 -2
  49. package/dist/{handler-DzQae4eA.mjs → handler-D7UyZlPm.mjs} +2 -2
  50. package/dist/{image-Bz87fCla.js → image-B-NDSDuY.js} +129 -11
  51. package/dist/{image-C4TlpMHn.cjs → image-Hnaa2bJd.cjs} +175 -9
  52. package/dist/index-C56bL-A-.d.cts +1344 -0
  53. package/dist/{sidebar-COTaMHR-.d.ts → index-CPUUKzxD.d.cts} +344 -327
  54. package/dist/{sidebar-CrEdJuHX.d.cts → index-Ci4kfOHF.d.ts} +344 -327
  55. package/dist/index-Cu9H6CRa.d.ts +1344 -0
  56. package/dist/link-CgdI6O2o.js +872 -0
  57. package/dist/{link-D1Gjkb-2.cjs → link-vZjmD-es.cjs} +406 -223
  58. package/dist/{mdx-BuO6a1f7.js → mdx-BRT71V5Q.js} +211 -168
  59. package/dist/{mdx-CD-tSjRG.cjs → mdx-D0Absdq5.cjs} +225 -169
  60. package/dist/native-BNCY7PRF.cjs +6 -0
  61. package/dist/native-Di9Fnfrv.mjs +6 -0
  62. package/dist/native-Kre2T5eS.cjs +6 -0
  63. package/dist/node/cache.cjs +1 -1
  64. package/dist/node/cache.d.cts +19 -3
  65. package/dist/node/cache.d.mts +19 -3
  66. package/dist/node/cache.mjs +1 -1
  67. package/dist/node/cli-entry.cjs +1 -9
  68. package/dist/node/cli-entry.mjs +1 -9
  69. package/dist/node/index.cjs +1 -1
  70. package/dist/node/index.d.cts +245 -17
  71. package/dist/node/index.d.mts +246 -18
  72. package/dist/node/index.mjs +1 -1
  73. package/dist/node/mdx/shiki-adapter.cjs +1 -1
  74. package/dist/node/mdx/shiki-adapter.d.cts +24 -3
  75. package/dist/node/mdx/shiki-adapter.d.mts +24 -2
  76. package/dist/node/mdx/shiki-adapter.mjs +1 -1
  77. package/dist/node-Du5UL5wo.mjs +23 -0
  78. package/dist/node-DunuGqyp.cjs +23 -0
  79. package/dist/{package-CCYEAYeA.mjs → package-DA848keM.mjs} +1 -1
  80. package/dist/package-wplzySjz.cjs +6 -0
  81. package/dist/pages-external-BBw8ObVK.mjs +6 -0
  82. package/dist/pages-external-DPiPFxxP.cjs +6 -0
  83. package/dist/parser-BqTOsEUa.cjs +6 -0
  84. package/dist/parser-CGMY2lJ7.mjs +6 -0
  85. package/dist/plugin-BcTzvHAJ.mjs +69 -0
  86. package/dist/plugin-TulVMt1z.cjs +69 -0
  87. package/dist/plugin-context-C-l90hFt.cjs +15 -0
  88. package/dist/plugin-context-wqHNSZum.mjs +15 -0
  89. package/dist/plugin-lifecycle-B1BzSHdn.cjs +6 -0
  90. package/dist/resolve-B7vWOd8R.cjs +6 -0
  91. package/dist/resolve-C2kKnk_5.mjs +6 -0
  92. package/dist/resolve-It1Iug83.cjs +6 -0
  93. package/dist/resolve-YdTrt_FG.mjs +6 -0
  94. package/dist/router-C3kygdRK.cjs +1285 -0
  95. package/dist/router-CZBxMRAH.js +987 -0
  96. package/dist/routes-BL4y79tb.mjs +6 -0
  97. package/dist/routes-C2nPecwu.cjs +6 -0
  98. package/dist/routes-U9L8psZ9.cjs +6 -0
  99. package/dist/{search-dialog-DHqwjJuG.cjs → search-dialog-BCOHQGSt.cjs} +1 -1
  100. package/dist/search-dialog-Bp_P1MPP.js +481 -0
  101. package/dist/{search-dialog-DFnlx8LO.js → search-dialog-BqkzDTq2.js} +107 -57
  102. package/dist/{search-dialog-BRFno7HD.cjs → search-dialog-CIeIUhAn.cjs} +218 -43
  103. package/dist/{search-dialog-D6TvjcuV.js → search-dialog-DtmxmfEu.js} +1 -1
  104. package/dist/{search-dialog-B1NERUNx.cjs → search-dialog-x_qHU8ty.cjs} +107 -58
  105. package/dist/server/index.cjs +1 -1
  106. package/dist/server/index.d.mts +1 -1
  107. package/dist/server/index.mjs +1 -1
  108. package/dist/update-check-BKqmYfwT.cjs +11 -0
  109. package/dist/update-check-QnrVR3q1.mjs +11 -0
  110. package/dist/utils-8lzafE49.mjs +7 -0
  111. package/dist/utils-ej6_SjIZ.cjs +7 -0
  112. package/dist/virtual-modules-Ca5tHk1X.cjs +30 -0
  113. package/dist/virtual-modules-Dlgt1fP0.mjs +30 -0
  114. package/package.json +18 -16
  115. package/src/shared/mdx-path.ts +12 -0
  116. package/src/shared/structured-data.ts +145 -0
  117. package/src/shared/types.ts +220 -16
  118. package/dist/banner-BMop1KLF.d.ts +0 -100
  119. package/dist/banner-CVD0GugR.d.cts +0 -100
  120. package/dist/cache-CO4Dy2uQ.cjs +0 -6
  121. package/dist/cache-Dk53iOo6.mjs +0 -6
  122. package/dist/config-CCXp3aXO.mjs +0 -7
  123. package/dist/config-CMd4XoFq.cjs +0 -6
  124. package/dist/config-DlGoEM9D.cjs +0 -7
  125. package/dist/csp-CRp_3U7a.cjs +0 -6
  126. package/dist/csp-oTC2ygvF.mjs +0 -6
  127. package/dist/doctor-Bv16QSrI.cjs +0 -7
  128. package/dist/doctor-DOAbSaiL.mjs +0 -7
  129. package/dist/headers-Ddwek8K7.mjs +0 -6
  130. package/dist/headers-dg4SDrjY.cjs +0 -6
  131. package/dist/link-2PzgTnaP.js +0 -673
  132. package/dist/meta-loader-C4Hu9RN9.mjs +0 -6
  133. package/dist/meta-loader-Dq1zcFnh.cjs +0 -6
  134. package/dist/node-BXtqM1uH.mjs +0 -6
  135. package/dist/node-BlVk4EVg.cjs +0 -104
  136. package/dist/node-DOf4zhWc.mjs +0 -104
  137. package/dist/node-aD1eisrR.cjs +0 -6
  138. package/dist/pages-external-BYa4JSda.mjs +0 -6
  139. package/dist/pages-external-XkYIs-d5.cjs +0 -6
  140. package/dist/parser-DCiEWkSk.cjs +0 -8
  141. package/dist/parser-qk9FIHJ7.mjs +0 -8
  142. package/dist/plugin-C95kvu6h.mjs +0 -73
  143. package/dist/plugin-DM3u2bVj.cjs +0 -73
  144. package/dist/routes-BW6zsk7Z.mjs +0 -6
  145. package/dist/routes-BgoIB5wb.cjs +0 -6
  146. package/dist/routes-CORVxc02.cjs +0 -6
  147. package/dist/search-dialog-BmxHiKwt.js +0 -312
  148. package/dist/shiki-adapter-CoQ6jyJ4.cjs +0 -6
  149. package/dist/shiki-adapter-D-aKw7PP.mjs +0 -6
  150. package/dist/utils-Crm9oPcV.mjs +0 -7
  151. package/dist/utils-D6Xtj0FZ.cjs +0 -7
  152. /package/dist/{errors-0zGHRLue.mjs → errors-N-b6Sn2G.mjs} +0 -0
  153. /package/dist/{index-1KsTDq4o.d.mts → index-lFoyzCXy.d.mts} +0 -0
  154. /package/dist/{types-generator-BXhv7Ill.cjs → types-generator-DDSA93P3.cjs} +0 -0
  155. /package/dist/{types-generator-bDPvUztF.mjs → types-generator-DG1GX1EZ.mjs} +0 -0
@@ -3,22 +3,97 @@
3
3
  * Copyright (c) 2026 Jesus Alcala
4
4
  * Licensed under the MIT License.
5
5
  */
6
- const require_link = require('./link-D1Gjkb-2.cjs');
7
- const require_search_dialog = require('./search-dialog-B1NERUNx.cjs');
6
+ const require_router = require('./router-C3kygdRK.cjs');
7
+ const require_link = require('./link-vZjmD-es.cjs');
8
+ const require_search_dialog = require('./search-dialog-x_qHU8ty.cjs');
8
9
  let react = require("react");
9
- let react_router_dom = require("react-router-dom");
10
10
  let react_jsx_runtime = require("react/jsx-runtime");
11
11
  let flexsearch = require("flexsearch");
12
12
  let virtual_boltdocs_search = require("virtual:boltdocs-search");
13
- virtual_boltdocs_search = require_link.__toESM(virtual_boltdocs_search);
13
+ virtual_boltdocs_search = require_router.__toESM(virtual_boltdocs_search);
14
14
 
15
+ //#region src/client/hooks/use-routes.ts
16
+ /**
17
+ * Hook to access the framework's routing state.
18
+ * Returns both the complete set of routes and a filtered list based on the current
19
+ * version and locale.
20
+ */
21
+ function useRoutes() {
22
+ const routeContext = require_link.useRoutesContext();
23
+ const allRoutes = routeContext.routes;
24
+ const routeIndex = routeContext.index || {
25
+ byPath: new Map(allRoutes.map((route) => [require_link.normalizePath(route.path), route])),
26
+ hintsByPath: /* @__PURE__ */ new Map(),
27
+ collectionNames: []
28
+ };
29
+ const config = require_link.useConfig();
30
+ const location = require_router.useLocation();
31
+ const { pathname } = location;
32
+ const { currentLocale: currentLocaleStore, currentVersion: currentVersionStore } = require_link.useBoltdocsContext();
33
+ const currentPath = require_link.normalizePath(pathname);
34
+ const currentRoute = routeIndex.byPath.get(currentPath);
35
+ const pathParts = pathname.split("/").filter(Boolean);
36
+ const urlLocale = config.i18n ? pathParts.find((part) => Array.isArray(config.i18n?.locales) ? config.i18n?.locales.includes(part) : part in (config.i18n?.locales || {})) : void 0;
37
+ const currentLocale = config.i18n ? urlLocale || currentLocaleStore || config.i18n.defaultLocale : void 0;
38
+ const configuredVersions = config.versions?.versions || [];
39
+ const currentVersion = config.versions ? configuredVersions.some((version) => version.path === currentVersionStore) ? currentVersionStore : config.versions.defaultVersion : void 0;
40
+ const routes = (0, react.useMemo)(() => {
41
+ if (!allRoutes) return [];
42
+ const alternateCounts = /* @__PURE__ */ new Map();
43
+ const defaultLocale = config.i18n?.defaultLocale || "";
44
+ const defaultVersion = config.versions?.defaultVersion || "";
45
+ for (const r of allRoutes) {
46
+ const locale = r.locale || defaultLocale;
47
+ const version = r.version || defaultVersion;
48
+ const key = `${r.filePath}::${locale}::${version}`;
49
+ alternateCounts.set(key, (alternateCounts.get(key) || 0) + 1);
50
+ }
51
+ return allRoutes.filter((r) => {
52
+ const localeMatch = config.i18n ? (r.locale || config.i18n.defaultLocale) === currentLocale : true;
53
+ const versionMatch = config.versions ? (r.version || config.versions.defaultVersion) === currentVersion : true;
54
+ if (!(localeMatch && versionMatch)) return false;
55
+ const pathParts = pathname.split("/").filter(Boolean);
56
+ const isCurrentLocalePrefixed = !!(config.i18n && pathParts.includes(currentLocaleStore || config.i18n.defaultLocale));
57
+ const isCurrentVersionPrefixed = !!(config.versions && !!currentVersion && pathParts.includes(currentVersion));
58
+ const isRouteLocalePrefixed = !!r.locale;
59
+ const isRouteVersionPrefixed = !!r.version;
60
+ const locale = r.locale || defaultLocale;
61
+ const version = r.version || defaultVersion;
62
+ const key = `${r.filePath}::${locale}::${version}`;
63
+ if ((alternateCounts.get(key) || 0) > 1) {
64
+ const localeMismatch = config.i18n && isCurrentLocalePrefixed !== isRouteLocalePrefixed;
65
+ const versionMismatch = config.versions && isCurrentVersionPrefixed !== isRouteVersionPrefixed;
66
+ if (localeMismatch || versionMismatch) return false;
67
+ }
68
+ return true;
69
+ });
70
+ }, [
71
+ allRoutes,
72
+ config,
73
+ pathname,
74
+ currentLocale,
75
+ currentVersion,
76
+ currentLocaleStore
77
+ ]);
78
+ const collections = (0, react.useMemo)(() => new Set(routeIndex.collectionNames), [routeIndex.collectionNames]);
79
+ return {
80
+ routes,
81
+ allRoutes,
82
+ currentRoute,
83
+ isCollectionPage: !!currentRoute?.collection || location.pathname.split("/").filter(Boolean).some((segment) => collections.has(segment.toLowerCase())),
84
+ currentLocale,
85
+ currentVersion
86
+ };
87
+ }
88
+
89
+ //#endregion
15
90
  //#region src/client/components/internal/error-boundary.tsx
16
- function InternalFallback({ error, resetErrorBoundary }) {
91
+ function InternalFallback({ error, resetErrorBoundary, className }) {
17
92
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
18
- className: "p-2 font-mono flex flex-col items-center justify-between min-h-[30vh]",
93
+ className: require_link.cn("p-2 font-mono flex flex-col items-center justify-between min-h-[30vh]", className),
19
94
  children: [
20
95
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
21
- className: "text-lg font-semibold text-red-500",
96
+ className: "text-lg font-semibold text-danger-500",
22
97
  children: "Something went wrong"
23
98
  }),
24
99
  error?.message && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
@@ -28,7 +103,7 @@ function InternalFallback({ error, resetErrorBoundary }) {
28
103
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
29
104
  type: "button",
30
105
  onClick: resetErrorBoundary,
31
- className: "px-2 py-3 mt-2 bg-slate-100 rounded border-slate-200 border font-mono font-semibold text-slate-700 hover:scale-105 transition-transform active:scale-95 cursor-pointer",
106
+ className: "px-2 py-3 mt-2 bg-soft rounded border-subtle border font-mono font-semibold text-body hover:scale-105 transition-transform active:scale-95 cursor-pointer",
32
107
  children: "Try again"
33
108
  })
34
109
  ]
@@ -45,14 +120,98 @@ function InternalErrorBoundary({ children, fallback }) {
45
120
  //#endregion
46
121
  //#region src/client/hooks/use-search.ts
47
122
  function useSearch(routes) {
48
- const { currentLocale, currentVersion } = require_link.useRoutes();
123
+ const { currentLocale, currentVersion } = useRoutes();
49
124
  const config = require_link.useConfig();
50
125
  const algoliaConfig = config.integrations?.search?.algolia;
51
126
  const [isOpen, setIsOpen] = (0, react.useState)(false);
52
127
  const [query, setQuery] = (0, react.useState)("");
53
128
  const [index, setIndex] = (0, react.useState)(null);
54
129
  const [algoliaResults, setAlgoliaResults] = (0, react.useState)([]);
55
- const navigate = (0, react_router_dom.useNavigate)();
130
+ const [searchData, setSearchData] = (0, react.useState)([]);
131
+ const [searchDataLoading, setSearchDataLoading] = (0, react.useState)(false);
132
+ const [searchDataError, setSearchDataError] = (0, react.useState)(null);
133
+ const searchGeneration = (0, react.useRef)(0);
134
+ const loadingGeneration = (0, react.useRef)(null);
135
+ const navigate = require_router.useNavigate();
136
+ (0, react.useEffect)(() => {
137
+ if (algoliaConfig || !isOpen) return;
138
+ if (searchData.length > 0) return;
139
+ setSearchDataLoading(true);
140
+ setSearchDataError(null);
141
+ let active = true;
142
+ const generation = ++searchGeneration.current;
143
+ loadingGeneration.current = generation;
144
+ (0, virtual_boltdocs_search.default)().then((data) => {
145
+ if (!active || generation !== searchGeneration.current) return;
146
+ setSearchData(data || []);
147
+ if (loadingGeneration.current === generation) {
148
+ loadingGeneration.current = null;
149
+ setSearchDataLoading(false);
150
+ }
151
+ }).catch((err) => {
152
+ if (!active || generation !== searchGeneration.current) return;
153
+ console.error("[boltdocs] Failed to load search index:", err);
154
+ setSearchDataError(err);
155
+ if (loadingGeneration.current === generation) {
156
+ loadingGeneration.current = null;
157
+ setSearchDataLoading(false);
158
+ }
159
+ });
160
+ return () => {
161
+ active = false;
162
+ };
163
+ }, [
164
+ isOpen,
165
+ algoliaConfig,
166
+ searchData.length
167
+ ]);
168
+ (0, react.useEffect)(() => {
169
+ if (!{}.hot) return;
170
+ const applyFrontmatterDelta = (payload) => {
171
+ const updated = payload.search?.updated ?? [];
172
+ const deleted = new Set(payload.search?.deleted ?? []);
173
+ searchGeneration.current += 1;
174
+ if (loadingGeneration.current !== null) {
175
+ loadingGeneration.current = null;
176
+ setSearchDataLoading(false);
177
+ }
178
+ setSearchData((prev) => {
179
+ const map = new Map(prev.map((d) => [d.id, d]));
180
+ for (const doc of updated) map.set(doc.id, doc);
181
+ for (const id of deleted) map.delete(id);
182
+ return Array.from(map.values());
183
+ });
184
+ setIndex(null);
185
+ };
186
+ const refreshFromAsset = async () => {
187
+ const generation = ++searchGeneration.current;
188
+ loadingGeneration.current = generation;
189
+ setSearchDataLoading(true);
190
+ try {
191
+ const data = await (0, virtual_boltdocs_search.default)({ bustCache: true });
192
+ if (generation !== searchGeneration.current) return;
193
+ setSearchData(data || []);
194
+ setSearchDataError(null);
195
+ setIndex(null);
196
+ } catch (error) {
197
+ if (generation !== searchGeneration.current) return;
198
+ console.error("[boltdocs] Failed to refresh search index:", error);
199
+ setSearchDataError(error instanceof Error ? error : new Error(String(error)));
200
+ } finally {
201
+ if (generation === searchGeneration.current) {
202
+ loadingGeneration.current = null;
203
+ setSearchDataLoading(false);
204
+ }
205
+ }
206
+ };
207
+ const hot = {}.hot;
208
+ hot.on("boltdocs:frontmatter-update", applyFrontmatterDelta);
209
+ hot.on("boltdocs:mdx-update", refreshFromAsset);
210
+ return () => {
211
+ hot.off?.("boltdocs:frontmatter-update", applyFrontmatterDelta);
212
+ hot.off?.("boltdocs:mdx-update", refreshFromAsset);
213
+ };
214
+ }, []);
56
215
  (0, react.useEffect)(() => {
57
216
  const handleKeyDown = (e) => {
58
217
  if ((/Mac/.test(navigator.userAgent) ? e.metaKey : e.ctrlKey) && (e.key === "k" || e.key === "j")) {
@@ -65,29 +224,30 @@ function useSearch(routes) {
65
224
  }, []);
66
225
  const handleSelect = (0, react.useCallback)((key) => {
67
226
  const path = String(key);
227
+ if (!path) return;
68
228
  setIsOpen(false);
69
- const [baseUrl, hash] = path.split("#");
70
- navigate(`${baseUrl}${query ? `?hl=${encodeURIComponent(query)}` : ""}${hash ? `#${hash}` : ""}`);
71
- if (hash) setTimeout(() => {
72
- const el = document.getElementById(hash);
73
- if (el) el.scrollIntoView({ behavior: "smooth" });
74
- }, 100);
229
+ const url = new URL(path, window.location.origin);
230
+ if (query) url.searchParams.set("hl", query);
231
+ navigate(`${url.pathname}${url.search}${url.hash}`);
75
232
  }, [navigate, query]);
76
233
  (0, react.useEffect)(() => {
77
234
  if (algoliaConfig) return;
78
- if (!isOpen || index) return;
235
+ if (!isOpen || searchData.length === 0 || index) return;
79
236
  const newIndex = new flexsearch.Index({
80
- preset: "match",
81
- tokenize: "full",
82
- resolution: 9,
237
+ tokenize: "forward",
83
238
  cache: true
84
239
  });
85
- for (const doc of virtual_boltdocs_search.default) newIndex.add(doc.id, `${doc.title} ${doc.content}`);
240
+ for (let i = 0; i < searchData.length; i++) {
241
+ const doc = searchData[i];
242
+ if (!doc) continue;
243
+ newIndex.add(i, `${doc.title} ${doc.content}`);
244
+ }
86
245
  setIndex(newIndex);
87
246
  }, [
88
247
  isOpen,
89
248
  index,
90
- algoliaConfig
249
+ algoliaConfig,
250
+ searchData
91
251
  ]);
92
252
  (0, react.useEffect)(() => {
93
253
  if (!algoliaConfig) return;
@@ -120,7 +280,7 @@ function useSearch(routes) {
120
280
  const urlObj = new URL(path);
121
281
  path = urlObj.pathname + urlObj.search + urlObj.hash;
122
282
  }
123
- } catch (e) {}
283
+ } catch {}
124
284
  const hierarchy = hit.hierarchy || {};
125
285
  const levels = [
126
286
  hierarchy.lvl0,
@@ -153,11 +313,6 @@ function useSearch(routes) {
153
313
  currentLocale,
154
314
  currentVersion
155
315
  ]);
156
- const searchDataMap = (0, react.useMemo)(() => {
157
- const map = /* @__PURE__ */ new Map();
158
- for (const doc of virtual_boltdocs_search.default) map.set(doc.id, doc);
159
- return map;
160
- }, []);
161
316
  return {
162
317
  isOpen,
163
318
  setIsOpen,
@@ -184,11 +339,12 @@ function useSearch(routes) {
184
339
  const results = [];
185
340
  const seen = /* @__PURE__ */ new Set();
186
341
  for (const id of searchResults) {
187
- const doc = searchDataMap.get(id);
342
+ const doc = searchData[typeof id === "number" ? id : Number(id)];
188
343
  if (!doc) continue;
189
344
  const docLocale = doc.locale || config.i18n?.defaultLocale;
190
345
  const docVersion = doc.version || config.versions?.defaultVersion;
191
- if (!(!currentLocale || docLocale === currentLocale) || !(!currentVersion || docVersion === currentVersion)) continue;
346
+ const localeMatch = !currentLocale || docLocale === currentLocale || !doc.locale && currentLocale === config.i18n?.defaultLocale;
347
+ if (!(!currentVersion || docVersion === currentVersion)) continue;
192
348
  if (seen.has(doc.url)) continue;
193
349
  seen.add(doc.url);
194
350
  results.push({
@@ -197,21 +353,24 @@ function useSearch(routes) {
197
353
  path: doc.url,
198
354
  bio: doc.display,
199
355
  groupTitle: doc.display.split(" > ")[0],
200
- isHeading: doc.url.includes("#")
356
+ isHeading: doc.url.includes("#"),
357
+ localeMatch
201
358
  });
202
359
  }
203
- return results.slice(0, 10);
360
+ return results.filter((result) => result.localeMatch).slice(0, 10);
204
361
  }, [
205
362
  query,
206
363
  index,
207
364
  currentLocale,
208
365
  currentVersion,
209
366
  routes,
210
- searchDataMap,
367
+ searchData,
211
368
  algoliaConfig,
212
369
  algoliaResults,
213
370
  config
214
371
  ]),
372
+ searchDataLoading,
373
+ searchDataError,
215
374
  handleSelect,
216
375
  input: {
217
376
  value: query,
@@ -222,17 +381,17 @@ function useSearch(routes) {
222
381
 
223
382
  //#endregion
224
383
  //#region src/client/components/ui-base/search-dialog.tsx
225
- function Highlight({ text, query }) {
384
+ function Highlight({ text, query, markClassName }) {
226
385
  if (!query || !text) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: text });
227
386
  const escapedQuery = query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
228
387
  const regex = new RegExp(`(${escapedQuery})`, "gi");
229
388
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: text.split(regex).map((part, i) => regex.test(part) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("mark", {
230
- className: "bg-primary-500/20 text-primary-600 dark:text-primary-400 font-bold px-0.5 rounded-sm",
389
+ className: require_link.cn("bg-primary-500/20 text-primary-600 dark:text-primary-400 font-bold px-0.5 rounded-sm", markClassName),
231
390
  children: part
232
391
  }, i) : part) });
233
392
  }
234
- function SearchDialog({ routes }) {
235
- const { isOpen, setIsOpen, query, setQuery, list, handleSelect } = useSearch(routes);
393
+ function SearchDialog({ routes, className, markClassName }) {
394
+ const { isOpen, setIsOpen, query, setQuery, list, searchDataLoading, searchDataError, handleSelect } = useSearch(routes);
236
395
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
237
396
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Navbar.SearchTrigger.Desktop, {
238
397
  onPress: () => setIsOpen(true),
@@ -254,14 +413,13 @@ function SearchDialog({ routes }) {
254
413
  isOpen,
255
414
  isDismissable: true,
256
415
  onOpenChange: () => setIsOpen(false),
257
- className: "fixed inset-0 z-100 flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs animate-fade-in",
416
+ className: require_link.cn("fixed inset-0 z-100 flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs animate-fade-in", className),
258
417
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.Content, {
259
418
  className: "w-full max-w-lg bg-main border border-subtle shadow-md rounded-2xl overflow-hidden p-6",
260
419
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.Dialog, {
261
420
  "aria-label": "Search documentation",
262
421
  className: "flex flex-col min-h-0 h-[450px]",
263
422
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.SearchDialog.Autocomplete, {
264
- onSelectionChange: handleSelect,
265
423
  className: "flex flex-col min-h-0",
266
424
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.SearchDialog.Input, {
267
425
  value: query,
@@ -275,10 +433,19 @@ function SearchDialog({ routes }) {
275
433
  className: "text-muted hover:text-body hover:bg-surface rounded-md p-1 cursor-pointer select-none transition-colors",
276
434
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.X, { size: 16 })
277
435
  })]
278
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.List, {
436
+ }), searchDataLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
437
+ className: "flex flex-1 items-center justify-center px-4 py-8 text-sm text-muted",
438
+ children: "Loading search index…"
439
+ }) : searchDataError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
440
+ className: "flex flex-1 items-center justify-center px-4 py-8 text-center text-sm text-muted",
441
+ children: "Search is temporarily unavailable."
442
+ }) : query && list.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
443
+ className: "flex flex-1 items-center justify-center px-4 py-8 text-sm text-muted",
444
+ children: "No results found."
445
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.List, {
279
446
  items: list,
447
+ onAction: handleSelect,
280
448
  children: (item) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.SearchDialog.Item, {
281
- onPress: () => handleSelect(item.id),
282
449
  textValue: item.title,
283
450
  className: "flex items-center gap-3 px-4 py-2 rounded-xl group dark:hover:bg-primary-300/40 hover:bg-primary-200/50 transition-colors duration-100",
284
451
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.Item.Icon, {
@@ -290,13 +457,15 @@ function SearchDialog({ routes }) {
290
457
  className: "text-sm font-medium text-body truncate dark:group-hover:text-primary-100",
291
458
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Highlight, {
292
459
  text: item.title,
293
- query
460
+ query,
461
+ markClassName
294
462
  })
295
463
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.Item.Bio, {
296
464
  className: "text-xs text-muted truncate",
297
465
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Highlight, {
298
466
  text: item.bio,
299
- query
467
+ query,
468
+ markClassName
300
469
  })
301
470
  })]
302
471
  })]
@@ -322,6 +491,12 @@ Object.defineProperty(exports, 'SearchDialog', {
322
491
  return SearchDialog;
323
492
  }
324
493
  });
494
+ Object.defineProperty(exports, 'useRoutes', {
495
+ enumerable: true,
496
+ get: function () {
497
+ return useRoutes;
498
+ }
499
+ });
325
500
  Object.defineProperty(exports, 'useSearch', {
326
501
  enumerable: true,
327
502
  get: function () {
@@ -3,6 +3,6 @@
3
3
  * Copyright (c) 2026 Jesus Alcala
4
4
  * Licensed under the MIT License.
5
5
  */
6
- import { t as SearchDialog } from "./search-dialog-BmxHiKwt.js";
6
+ import { t as SearchDialog } from "./search-dialog-Bp_P1MPP.js";
7
7
 
8
8
  export { SearchDialog };