boltdocs 2.7.10 → 2.8.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 (193) hide show
  1. package/README.md +2 -2
  2. package/dist/banner-3N4Jd_L9.d.ts +100 -0
  3. package/dist/banner-MynZD_Ox.d.cts +100 -0
  4. package/dist/cache-BMUyNiiA.mjs +6 -0
  5. package/dist/cache-CKm45d2w.cjs +6 -0
  6. package/dist/client/index.cjs +2268 -1
  7. package/dist/client/index.d.cts +86 -110
  8. package/dist/client/index.d.ts +87 -111
  9. package/dist/client/index.js +2214 -1
  10. package/dist/client/mdx.cjs +12 -1
  11. package/dist/client/mdx.d.cts +39 -93
  12. package/dist/client/mdx.d.ts +38 -93
  13. package/dist/client/mdx.js +7 -1
  14. package/dist/client/primitives.cjs +60 -1
  15. package/dist/client/primitives.d.cts +411 -347
  16. package/dist/client/primitives.d.ts +411 -347
  17. package/dist/client/primitives.js +20 -1
  18. package/dist/docs-layout-CwCq42Zt.cjs +1348 -0
  19. package/dist/docs-layout-Dn6S5g59.js +1167 -0
  20. package/dist/doctor-BArviV8X.cjs +28 -0
  21. package/dist/doctor-CgLA7_Uv.mjs +28 -0
  22. package/dist/{doctor-CrytFkqW.cjs → doctor-DyNUVe96.cjs} +1 -1
  23. package/dist/{routes-DP1vmWRj.cjs → doctor-aN_leTbh.mjs} +1 -1
  24. package/dist/{generator-ClVanhvi.mjs → generator-BHCrLU6h.mjs} +2 -2
  25. package/dist/{generator-CHqxiQhF.cjs → generator-CC2yHzhZ.cjs} +2 -2
  26. package/dist/icons-dev-DvJ-hh9x.cjs +1209 -0
  27. package/dist/icons-dev-Oju24Wjp.js +845 -0
  28. package/dist/image-Ch4-GxdO.cjs +268 -0
  29. package/dist/image-Do8V9PCW.js +214 -0
  30. package/dist/mdx-D3A2_l7P.js +520 -0
  31. package/dist/mdx-PLhhPJRS.cjs +531 -0
  32. package/dist/node/cli-entry.cjs +3 -1
  33. package/dist/node/cli-entry.mjs +3 -1
  34. package/dist/node/index.cjs +1 -1
  35. package/dist/node/index.d.cts +258 -152
  36. package/dist/node/index.d.mts +258 -150
  37. package/dist/node/index.mjs +1 -1
  38. package/dist/node/routes/worker.cjs +1 -1
  39. package/dist/node/routes/worker.mjs +1 -1
  40. package/dist/node-BmlP0eBP.cjs +159 -0
  41. package/dist/node-Y8_4ayje.mjs +159 -0
  42. package/dist/package-2nFy_NsW.cjs +6 -0
  43. package/dist/{package--0Yf0t1N.mjs → package-DAbtltXX.mjs} +1 -1
  44. package/dist/parser-B7-6PyQz.cjs +6 -0
  45. package/dist/{parser-Aq8LoH-0.cjs → parser-BzB-zCkF.cjs} +1 -1
  46. package/dist/parser-WGZdWs0X.mjs +6 -0
  47. package/dist/routes-BDDSxAl0.mjs +6 -0
  48. package/dist/routes-DJNJ-rTt.cjs +6 -0
  49. package/dist/routes-DiYC4nD2.cjs +6 -0
  50. package/dist/routes-_Bb2f4eI.mjs +6 -0
  51. package/dist/search-dialog-BXVoecTx.cjs +483 -0
  52. package/dist/search-dialog-BYhOov4S.cjs +331 -0
  53. package/dist/search-dialog-C09riYmx.js +313 -0
  54. package/dist/search-dialog-CUeAfy-8.cjs +8 -0
  55. package/dist/search-dialog-D8gLkhUV.js +453 -0
  56. package/dist/search-dialog-DHc_8FFX.js +8 -0
  57. package/dist/{sidebar-CcBkrm06.d.cts → sidebar-DNq4_ZAa.d.ts} +118 -52
  58. package/dist/{sidebar-CyZS9YOm.d.ts → sidebar-Dlkgbxs6.d.cts} +118 -52
  59. package/dist/utils-BYITg7T5.mjs +7 -0
  60. package/dist/utils-Cjmx1hhk.cjs +7 -0
  61. package/dist/worker-pool-CtqklOXq.cjs +6 -0
  62. package/dist/worker-pool-k0DY6k8T.mjs +6 -0
  63. package/package.json +5 -6
  64. package/src/shared/config-utils.ts +4 -0
  65. package/src/shared/types.ts +52 -6
  66. package/dist/cache-Ba-DZQNH.cjs +0 -6
  67. package/dist/cache-BuMZ58L5.mjs +0 -6
  68. package/dist/cards-BakZPTz9.d.ts +0 -30
  69. package/dist/cards-CQn9mXZS.d.cts +0 -30
  70. package/dist/docs-layout-KoWNZc8_.js +0 -6
  71. package/dist/docs-layout-x2yKt2cL.cjs +0 -6
  72. package/dist/doctor-Be7Ly1oM.mjs +0 -21
  73. package/dist/doctor-jMxWZyLJ.cjs +0 -21
  74. package/dist/icons-dev-B_RZIyxu.js +0 -6
  75. package/dist/icons-dev-BlV3wWFT.cjs +0 -6
  76. package/dist/image-BHhTvQzr.cjs +0 -6
  77. package/dist/image-CqKzYD8f.js +0 -6
  78. package/dist/mdx-DudBEac0.js +0 -7
  79. package/dist/mdx-r4cDQxWu.cjs +0 -7
  80. package/dist/node-DtEDyN1u.cjs +0 -111
  81. package/dist/node-_1jhMGYx.mjs +0 -111
  82. package/dist/package-DrwtlXfk.cjs +0 -6
  83. package/dist/parser-CdNbqN5y.cjs +0 -6
  84. package/dist/parser-nE792MLO.mjs +0 -6
  85. package/dist/rolldown-runtime-fkIsjY3S.mjs +0 -6
  86. package/dist/routes-2k3tbUmC.cjs +0 -6
  87. package/dist/routes-CpxZIsMM.mjs +0 -6
  88. package/dist/search-dialog-B584t9ZF.js +0 -6
  89. package/dist/search-dialog-BvBopRsZ.cjs +0 -6
  90. package/dist/search-dialog-ByvGScjt.js +0 -6
  91. package/dist/search-dialog-Cyko6TJm.cjs +0 -6
  92. package/dist/search-dialog-D6BNohIJ.js +0 -6
  93. package/dist/search-dialog-DuYTIefy.cjs +0 -6
  94. package/dist/utils-CG65J0Sc.mjs +0 -7
  95. package/dist/utils-CKunkU96.cjs +0 -7
  96. package/dist/worker-pool-CGn7DrLb.mjs +0 -6
  97. package/dist/worker-pool-Crbqgw5R.cjs +0 -6
  98. package/src/client/app/config-context.tsx +0 -51
  99. package/src/client/app/doc-page.tsx +0 -38
  100. package/src/client/app/docs-layout.tsx +0 -28
  101. package/src/client/app/head.tsx +0 -122
  102. package/src/client/app/helmet-compat.tsx +0 -36
  103. package/src/client/app/mdx-component.tsx +0 -8
  104. package/src/client/app/mdx-components-context.tsx +0 -72
  105. package/src/client/app/routes-context.tsx +0 -34
  106. package/src/client/app/scroll-handler.tsx +0 -74
  107. package/src/client/app/theme-context.tsx +0 -103
  108. package/src/client/app/ui-context.tsx +0 -42
  109. package/src/client/components/docs-layout-default.tsx +0 -85
  110. package/src/client/components/icons-dev.tsx +0 -282
  111. package/src/client/components/mdx/callout.tsx +0 -97
  112. package/src/client/components/mdx/card.tsx +0 -99
  113. package/src/client/components/mdx/cards.tsx +0 -27
  114. package/src/client/components/mdx/code-block.tsx +0 -184
  115. package/src/client/components/mdx/field.tsx +0 -33
  116. package/src/client/components/mdx/image.tsx +0 -44
  117. package/src/client/components/mdx/index.ts +0 -19
  118. package/src/client/components/mdx/table.tsx +0 -54
  119. package/src/client/components/mdx/typographics.tsx +0 -120
  120. package/src/client/components/mdx/use-code-block.ts +0 -34
  121. package/src/client/components/primitives/breadcrumbs.tsx +0 -54
  122. package/src/client/components/primitives/button-group.tsx +0 -54
  123. package/src/client/components/primitives/button.tsx +0 -6
  124. package/src/client/components/primitives/code-block.tsx +0 -120
  125. package/src/client/components/primitives/docs-layout.tsx +0 -125
  126. package/src/client/components/primitives/error-boundary.tsx +0 -107
  127. package/src/client/components/primitives/heading.tsx +0 -128
  128. package/src/client/components/primitives/helpers/observer.ts +0 -141
  129. package/src/client/components/primitives/image.tsx +0 -26
  130. package/src/client/components/primitives/link.tsx +0 -102
  131. package/src/client/components/primitives/menu.tsx +0 -137
  132. package/src/client/components/primitives/navbar.tsx +0 -466
  133. package/src/client/components/primitives/on-this-page.tsx +0 -430
  134. package/src/client/components/primitives/page-nav.tsx +0 -51
  135. package/src/client/components/primitives/popover.tsx +0 -28
  136. package/src/client/components/primitives/search-dialog.tsx +0 -193
  137. package/src/client/components/primitives/sidebar.tsx +0 -423
  138. package/src/client/components/primitives/skeleton.tsx +0 -26
  139. package/src/client/components/primitives/tabs.tsx +0 -70
  140. package/src/client/components/primitives/tooltip.tsx +0 -81
  141. package/src/client/components/primitives/types.ts +0 -11
  142. package/src/client/components/ui-base/banner.tsx +0 -66
  143. package/src/client/components/ui-base/breadcrumbs.tsx +0 -44
  144. package/src/client/components/ui-base/copy-markdown.tsx +0 -107
  145. package/src/client/components/ui-base/error-boundary.tsx +0 -15
  146. package/src/client/components/ui-base/github-stars.tsx +0 -29
  147. package/src/client/components/ui-base/icons.tsx +0 -240
  148. package/src/client/components/ui-base/index.ts +0 -16
  149. package/src/client/components/ui-base/last-updated.tsx +0 -27
  150. package/src/client/components/ui-base/navbar.tsx +0 -266
  151. package/src/client/components/ui-base/not-found.tsx +0 -26
  152. package/src/client/components/ui-base/on-this-page.tsx +0 -57
  153. package/src/client/components/ui-base/page-nav.tsx +0 -50
  154. package/src/client/components/ui-base/search-dialog.tsx +0 -163
  155. package/src/client/components/ui-base/search-highlight.tsx +0 -10
  156. package/src/client/components/ui-base/sidebar.tsx +0 -92
  157. package/src/client/components/ui-base/tabs.tsx +0 -83
  158. package/src/client/components/ui-base/theme-toggle.tsx +0 -130
  159. package/src/client/components/ui-base/version-i18n.tsx +0 -80
  160. package/src/client/hooks/index.ts +0 -13
  161. package/src/client/hooks/use-analytics.ts +0 -272
  162. package/src/client/hooks/use-breadcrumbs.ts +0 -22
  163. package/src/client/hooks/use-i18n.ts +0 -182
  164. package/src/client/hooks/use-localized-to.ts +0 -113
  165. package/src/client/hooks/use-location.ts +0 -5
  166. package/src/client/hooks/use-navbar.ts +0 -130
  167. package/src/client/hooks/use-page-nav.ts +0 -46
  168. package/src/client/hooks/use-routes.ts +0 -108
  169. package/src/client/hooks/use-search-highlight.ts +0 -185
  170. package/src/client/hooks/use-search.ts +0 -118
  171. package/src/client/hooks/use-sidebar.ts +0 -205
  172. package/src/client/hooks/use-tabs.ts +0 -46
  173. package/src/client/hooks/use-version.ts +0 -111
  174. package/src/client/index.ts +0 -31
  175. package/src/client/mdx.ts +0 -2
  176. package/src/client/primitives.ts +0 -19
  177. package/src/client/ssg/boltdocs-shell.tsx +0 -148
  178. package/src/client/ssg/create-routes.tsx +0 -473
  179. package/src/client/ssg/index.ts +0 -4
  180. package/src/client/ssg/mdx-page.tsx +0 -38
  181. package/src/client/store/boltdocs-context.tsx +0 -137
  182. package/src/client/theme/neutral.css +0 -141
  183. package/src/client/theme/reset.css +0 -189
  184. package/src/client/types.ts +0 -116
  185. package/src/client/utils/cn.ts +0 -6
  186. package/src/client/utils/copy-clipboard.ts +0 -22
  187. package/src/client/utils/get-base-file-path.ts +0 -21
  188. package/src/client/utils/github.ts +0 -121
  189. package/src/client/utils/i18n.ts +0 -23
  190. package/src/client/utils/path.ts +0 -9
  191. package/src/client/utils/react-to-text.ts +0 -34
  192. package/src/client/virtual.d.ts +0 -24
  193. /package/dist/{meta-loader-CWg2gnbY.mjs → meta-loader-DzwDFtdT.mjs} +0 -0
@@ -0,0 +1,331 @@
1
+ /**
2
+ * Boltdocs - https://boltdocs.vercel.app
3
+ * Copyright (c) 2026 Jesus Alcala
4
+ * Licensed under the MIT License.
5
+ */
6
+ const require_icons_dev = require('./icons-dev-DvJ-hh9x.cjs');
7
+ const require_search_dialog = require('./search-dialog-BXVoecTx.cjs');
8
+ let react = require("react");
9
+ let react_router_dom = require("react-router-dom");
10
+ let react_jsx_runtime = require("react/jsx-runtime");
11
+ let flexsearch = require("flexsearch");
12
+ let virtual_boltdocs_search = require("virtual:boltdocs-search");
13
+ virtual_boltdocs_search = require_icons_dev.__toESM(virtual_boltdocs_search);
14
+
15
+ //#region src/client/components/internal/error-boundary.tsx
16
+ function InternalFallback({ error, resetErrorBoundary }) {
17
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
18
+ className: "p-2 font-mono flex flex-col items-center justify-between min-h-[30vh]",
19
+ children: [
20
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
21
+ className: "text-lg font-semibold text-red-500",
22
+ children: "Something went wrong"
23
+ }),
24
+ error?.message && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
25
+ className: "text-sm mt-2 max-w-md overflow-auto whitespace-pre-wrap break-word",
26
+ children: error.message
27
+ }),
28
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
29
+ type: "button",
30
+ 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",
32
+ children: "Try again"
33
+ })
34
+ ]
35
+ });
36
+ }
37
+ function InternalErrorBoundary({ children, fallback }) {
38
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.ErrorBoundary, {
39
+ fallback,
40
+ FallbackComponent: !fallback ? InternalFallback : void 0,
41
+ children
42
+ });
43
+ }
44
+
45
+ //#endregion
46
+ //#region src/client/hooks/use-search.ts
47
+ function useSearch(routes) {
48
+ const { currentLocale, currentVersion } = require_icons_dev.useRoutes();
49
+ const algoliaConfig = require_icons_dev.useConfig().integrations?.algolia;
50
+ const [isOpen, setIsOpen] = (0, react.useState)(false);
51
+ const [query, setQuery] = (0, react.useState)("");
52
+ const [index, setIndex] = (0, react.useState)(null);
53
+ const [algoliaResults, setAlgoliaResults] = (0, react.useState)([]);
54
+ (0, react.useEffect)(() => {
55
+ if (algoliaConfig) return;
56
+ if (!isOpen || index) return;
57
+ const newIndex = new flexsearch.Index({
58
+ preset: "match",
59
+ tokenize: "full",
60
+ resolution: 9,
61
+ cache: true
62
+ });
63
+ for (const doc of virtual_boltdocs_search.default) newIndex.add(doc.id, `${doc.title} ${doc.content}`);
64
+ setIndex(newIndex);
65
+ }, [
66
+ isOpen,
67
+ index,
68
+ algoliaConfig
69
+ ]);
70
+ (0, react.useEffect)(() => {
71
+ if (!algoliaConfig) return;
72
+ if (!query) {
73
+ setAlgoliaResults([]);
74
+ return;
75
+ }
76
+ const delayDebounceFn = setTimeout(async () => {
77
+ try {
78
+ const url = `https://${algoliaConfig.appId}-dsn.algolia.net/1/indexes/${algoliaConfig.indexName}/query`;
79
+ const facetFilters = [];
80
+ if (currentLocale) facetFilters.push(`lang:${currentLocale}`);
81
+ if (currentVersion) facetFilters.push(`version:${currentVersion}`);
82
+ let params = `query=${encodeURIComponent(query)}&hitsPerPage=20`;
83
+ if (facetFilters.length > 0) params += `&facetFilters=${encodeURIComponent(JSON.stringify(facetFilters))}`;
84
+ const response = await fetch(url, {
85
+ method: "POST",
86
+ headers: {
87
+ "Content-Type": "application/json",
88
+ "X-Algolia-API-Key": algoliaConfig.apiKey,
89
+ "X-Algolia-Application-Id": algoliaConfig.appId
90
+ },
91
+ body: JSON.stringify({ params })
92
+ });
93
+ if (!response.ok) throw new Error(`Algolia search request failed: ${response.statusText}`);
94
+ setAlgoliaResults(((await response.json()).hits || []).map((hit) => {
95
+ let path = hit.url || "";
96
+ try {
97
+ if (path.startsWith("http://") || path.startsWith("https://")) {
98
+ const urlObj = new URL(path);
99
+ path = urlObj.pathname + urlObj.search + urlObj.hash;
100
+ }
101
+ } catch (e) {}
102
+ const hierarchy = hit.hierarchy || {};
103
+ const levels = [
104
+ hierarchy.lvl0,
105
+ hierarchy.lvl1,
106
+ hierarchy.lvl2,
107
+ hierarchy.lvl3,
108
+ hierarchy.lvl4,
109
+ hierarchy.lvl5,
110
+ hierarchy.lvl6
111
+ ].filter(Boolean);
112
+ const title = levels[levels.length - 1] || "Documentation";
113
+ const bio = levels.join(" > ");
114
+ return {
115
+ id: hit.objectID || path,
116
+ title,
117
+ path,
118
+ bio,
119
+ groupTitle: hierarchy.lvl0 || "Docs",
120
+ isHeading: !!hit.anchor || path.includes("#")
121
+ };
122
+ }));
123
+ } catch (err) {
124
+ console.error("Error fetching search results from Algolia:", err);
125
+ }
126
+ }, 250);
127
+ return () => clearTimeout(delayDebounceFn);
128
+ }, [
129
+ query,
130
+ algoliaConfig,
131
+ currentLocale,
132
+ currentVersion
133
+ ]);
134
+ const searchDataMap = (0, react.useMemo)(() => {
135
+ const map = /* @__PURE__ */ new Map();
136
+ for (const doc of virtual_boltdocs_search.default) map.set(doc.id, doc);
137
+ return map;
138
+ }, []);
139
+ return {
140
+ isOpen,
141
+ setIsOpen,
142
+ query,
143
+ setQuery,
144
+ list: (0, react.useMemo)(() => {
145
+ if (!query) return routes.filter((r) => {
146
+ const localeMatch = !currentLocale || r.locale === currentLocale;
147
+ const versionMatch = !currentVersion || r.version === currentVersion;
148
+ return localeMatch && versionMatch;
149
+ }).slice(0, 10).map((r) => ({
150
+ id: r.path,
151
+ title: r.title,
152
+ path: r.path,
153
+ bio: r.description || "",
154
+ groupTitle: r.groupTitle
155
+ }));
156
+ if (algoliaConfig) return algoliaResults;
157
+ if (!index) return [];
158
+ const searchResults = index.search(query, {
159
+ limit: 20,
160
+ suggest: true
161
+ });
162
+ const results = [];
163
+ const seen = /* @__PURE__ */ new Set();
164
+ for (const id of searchResults) {
165
+ const doc = searchDataMap.get(id);
166
+ if (!doc) continue;
167
+ const localeMatch = !currentLocale || doc.locale === currentLocale;
168
+ const versionMatch = !currentVersion || doc.version === currentVersion;
169
+ if (!localeMatch || !versionMatch) continue;
170
+ if (seen.has(doc.url)) continue;
171
+ seen.add(doc.url);
172
+ results.push({
173
+ id: doc.url,
174
+ title: doc.title,
175
+ path: doc.url,
176
+ bio: doc.display,
177
+ groupTitle: doc.display.split(" > ")[0],
178
+ isHeading: doc.url.includes("#")
179
+ });
180
+ }
181
+ return results.slice(0, 10);
182
+ }, [
183
+ query,
184
+ index,
185
+ currentLocale,
186
+ currentVersion,
187
+ routes,
188
+ searchDataMap,
189
+ algoliaConfig,
190
+ algoliaResults
191
+ ]),
192
+ input: {
193
+ value: query,
194
+ onChange: (e) => setQuery(e.target.value)
195
+ }
196
+ };
197
+ }
198
+
199
+ //#endregion
200
+ //#region src/client/components/ui-base/search-dialog.tsx
201
+ function Highlight({ text, query }) {
202
+ if (!query || !text) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: text });
203
+ const escapedQuery = query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
204
+ const regex = new RegExp(`(${escapedQuery})`, "gi");
205
+ 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", {
206
+ className: "bg-primary-500/20 text-primary-600 dark:text-primary-400 font-bold px-0.5 rounded-sm",
207
+ children: part
208
+ }, i) : part) });
209
+ }
210
+ function SearchDialog({ routes }) {
211
+ const { isOpen, setIsOpen, query, setQuery, list } = useSearch(routes);
212
+ const navigate = (0, react_router_dom.useNavigate)();
213
+ (0, react.useEffect)(() => {
214
+ const handleKeyDown = (e) => {
215
+ if ((/Mac/.test(navigator.userAgent) ? e.metaKey : e.ctrlKey) && (e.key === "k" || e.key === "j")) {
216
+ e.preventDefault();
217
+ setIsOpen((prev) => !prev);
218
+ }
219
+ };
220
+ window.addEventListener("keydown", handleKeyDown);
221
+ return () => window.removeEventListener("keydown", handleKeyDown);
222
+ }, [setIsOpen]);
223
+ const handleSelect = (0, react.useCallback)((key) => {
224
+ const path = String(key);
225
+ setIsOpen(false);
226
+ const [baseUrl, hash] = path.split("#");
227
+ navigate(`${baseUrl}${query ? `?hl=${encodeURIComponent(query)}` : ""}${hash ? `#${hash}` : ""}`);
228
+ if (hash) setTimeout(() => {
229
+ const el = document.getElementById(hash);
230
+ if (el) el.scrollIntoView({ behavior: "smooth" });
231
+ }, 100);
232
+ }, [
233
+ navigate,
234
+ setIsOpen,
235
+ query
236
+ ]);
237
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
238
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.Navbar.SearchTrigger.Desktop, {
239
+ onPress: () => setIsOpen(true),
240
+ className: "rounded-xl border border-subtle bg-surface text-muted transition-all duration-200 hover:border-primary-500/50 hover:text-body hover:bg-soft/50 hover:shadow-sm active:scale-[0.98] focus-visible:ring-2 focus-visible:ring-primary-500/30",
241
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
242
+ className: "flex items-center gap-2",
243
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Search, { size: 16 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
244
+ className: "hidden sm:inline-block",
245
+ children: "Search docs..."
246
+ })]
247
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.SearchTrigger.Kbd, { className: "[&_kbd]:bg-main [&_kbd]:border [&_kbd]:border-subtle [&_kbd]:rounded [&_kbd]:px-1.5 [&_kbd]:h-5 [&_kbd]:w-5" })]
248
+ }),
249
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.Navbar.SearchTrigger.Mobile, {
250
+ onPress: () => setIsOpen(true),
251
+ className: "rounded-xl text-muted transition-all duration-200 hover:text-body active:scale-95 focus-visible:ring-2 focus-visible:ring-primary-500/30",
252
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_icons_dev.Search, { size: 20 })
253
+ }),
254
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InternalErrorBoundary, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.Overlay, {
255
+ isOpen,
256
+ isDismissable: true,
257
+ onOpenChange: () => setIsOpen(false),
258
+ className: "fixed inset-0 z-100 flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs animate-fade-in",
259
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.Content, {
260
+ className: "w-full max-w-lg bg-main border border-subtle shadow-md rounded-2xl overflow-hidden p-6",
261
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.Dialog, {
262
+ "aria-label": "Search documentation",
263
+ className: "flex flex-col min-h-0 h-[450px]",
264
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.SearchDialog.Autocomplete, {
265
+ onSelectionChange: handleSelect,
266
+ className: "flex flex-col min-h-0",
267
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.SearchDialog.Input, {
268
+ value: query,
269
+ onChange: setQuery,
270
+ className: "flex items-center gap-2 border border-subtle bg-surface px-4 py-2.5 rounded-xl focus-within:border-primary-500 mb-4",
271
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.Input.SearchInput, {
272
+ placeholder: "Search documentation...",
273
+ className: "w-full bg-transparent outline-none text-body text-sm"
274
+ }), query && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.Input.Button, {
275
+ onPress: () => setQuery(""),
276
+ className: "text-muted hover:text-body text-xs cursor-pointer select-none",
277
+ children: "✕"
278
+ })]
279
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.List, {
280
+ items: list,
281
+ children: (item) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_search_dialog.SearchDialog.Item, {
282
+ onPress: () => handleSelect(item.id),
283
+ textValue: item.title,
284
+ 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",
285
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.Item.Icon, {
286
+ isHeading: item.isHeading,
287
+ className: "text-muted group-hover:text-primary-500 group-focus:text-primary-500"
288
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
289
+ className: "flex flex-col justify-center min-w-0",
290
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.Item.Title, {
291
+ className: "text-sm font-medium text-body truncate dark:group-hover:text-primary-100",
292
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Highlight, {
293
+ text: item.title,
294
+ query
295
+ })
296
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_search_dialog.SearchDialog.Item.Bio, {
297
+ className: "text-xs text-muted truncate",
298
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Highlight, {
299
+ text: item.bio,
300
+ query
301
+ })
302
+ })]
303
+ })]
304
+ }, item.id)
305
+ })]
306
+ })
307
+ })
308
+ })
309
+ }) })
310
+ ] });
311
+ }
312
+
313
+ //#endregion
314
+ Object.defineProperty(exports, 'InternalErrorBoundary', {
315
+ enumerable: true,
316
+ get: function () {
317
+ return InternalErrorBoundary;
318
+ }
319
+ });
320
+ Object.defineProperty(exports, 'SearchDialog', {
321
+ enumerable: true,
322
+ get: function () {
323
+ return SearchDialog;
324
+ }
325
+ });
326
+ Object.defineProperty(exports, 'useSearch', {
327
+ enumerable: true,
328
+ get: function () {
329
+ return useSearch;
330
+ }
331
+ });
@@ -0,0 +1,313 @@
1
+ /**
2
+ * Boltdocs - https://boltdocs.vercel.app
3
+ * Copyright (c) 2026 Jesus Alcala
4
+ * Licensed under the MIT License.
5
+ */
6
+ import { J as Search, et as useConfig, x as useRoutes } from "./icons-dev-Oju24Wjp.js";
7
+ import { n as Navbar, r as ErrorBoundary, t as SearchDialog$1 } from "./search-dialog-D8gLkhUV.js";
8
+ import { useCallback, useEffect, useMemo, useState } from "react";
9
+ import { useNavigate } from "react-router-dom";
10
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
+ import { Index } from "flexsearch";
12
+ import searchData from "virtual:boltdocs-search";
13
+
14
+ //#region src/client/components/internal/error-boundary.tsx
15
+ function InternalFallback({ error, resetErrorBoundary }) {
16
+ return /* @__PURE__ */ jsxs("div", {
17
+ className: "p-2 font-mono flex flex-col items-center justify-between min-h-[30vh]",
18
+ children: [
19
+ /* @__PURE__ */ jsx("p", {
20
+ className: "text-lg font-semibold text-red-500",
21
+ children: "Something went wrong"
22
+ }),
23
+ error?.message && /* @__PURE__ */ jsx("pre", {
24
+ className: "text-sm mt-2 max-w-md overflow-auto whitespace-pre-wrap break-word",
25
+ children: error.message
26
+ }),
27
+ /* @__PURE__ */ jsx("button", {
28
+ type: "button",
29
+ onClick: resetErrorBoundary,
30
+ 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",
31
+ children: "Try again"
32
+ })
33
+ ]
34
+ });
35
+ }
36
+ function InternalErrorBoundary({ children, fallback }) {
37
+ return /* @__PURE__ */ jsx(ErrorBoundary, {
38
+ fallback,
39
+ FallbackComponent: !fallback ? InternalFallback : void 0,
40
+ children
41
+ });
42
+ }
43
+
44
+ //#endregion
45
+ //#region src/client/hooks/use-search.ts
46
+ function useSearch(routes) {
47
+ const { currentLocale, currentVersion } = useRoutes();
48
+ const algoliaConfig = useConfig().integrations?.algolia;
49
+ const [isOpen, setIsOpen] = useState(false);
50
+ const [query, setQuery] = useState("");
51
+ const [index, setIndex] = useState(null);
52
+ const [algoliaResults, setAlgoliaResults] = useState([]);
53
+ useEffect(() => {
54
+ if (algoliaConfig) return;
55
+ if (!isOpen || index) return;
56
+ const newIndex = new Index({
57
+ preset: "match",
58
+ tokenize: "full",
59
+ resolution: 9,
60
+ cache: true
61
+ });
62
+ for (const doc of searchData) newIndex.add(doc.id, `${doc.title} ${doc.content}`);
63
+ setIndex(newIndex);
64
+ }, [
65
+ isOpen,
66
+ index,
67
+ algoliaConfig
68
+ ]);
69
+ useEffect(() => {
70
+ if (!algoliaConfig) return;
71
+ if (!query) {
72
+ setAlgoliaResults([]);
73
+ return;
74
+ }
75
+ const delayDebounceFn = setTimeout(async () => {
76
+ try {
77
+ const url = `https://${algoliaConfig.appId}-dsn.algolia.net/1/indexes/${algoliaConfig.indexName}/query`;
78
+ const facetFilters = [];
79
+ if (currentLocale) facetFilters.push(`lang:${currentLocale}`);
80
+ if (currentVersion) facetFilters.push(`version:${currentVersion}`);
81
+ let params = `query=${encodeURIComponent(query)}&hitsPerPage=20`;
82
+ if (facetFilters.length > 0) params += `&facetFilters=${encodeURIComponent(JSON.stringify(facetFilters))}`;
83
+ const response = await fetch(url, {
84
+ method: "POST",
85
+ headers: {
86
+ "Content-Type": "application/json",
87
+ "X-Algolia-API-Key": algoliaConfig.apiKey,
88
+ "X-Algolia-Application-Id": algoliaConfig.appId
89
+ },
90
+ body: JSON.stringify({ params })
91
+ });
92
+ if (!response.ok) throw new Error(`Algolia search request failed: ${response.statusText}`);
93
+ setAlgoliaResults(((await response.json()).hits || []).map((hit) => {
94
+ let path = hit.url || "";
95
+ try {
96
+ if (path.startsWith("http://") || path.startsWith("https://")) {
97
+ const urlObj = new URL(path);
98
+ path = urlObj.pathname + urlObj.search + urlObj.hash;
99
+ }
100
+ } catch (e) {}
101
+ const hierarchy = hit.hierarchy || {};
102
+ const levels = [
103
+ hierarchy.lvl0,
104
+ hierarchy.lvl1,
105
+ hierarchy.lvl2,
106
+ hierarchy.lvl3,
107
+ hierarchy.lvl4,
108
+ hierarchy.lvl5,
109
+ hierarchy.lvl6
110
+ ].filter(Boolean);
111
+ const title = levels[levels.length - 1] || "Documentation";
112
+ const bio = levels.join(" > ");
113
+ return {
114
+ id: hit.objectID || path,
115
+ title,
116
+ path,
117
+ bio,
118
+ groupTitle: hierarchy.lvl0 || "Docs",
119
+ isHeading: !!hit.anchor || path.includes("#")
120
+ };
121
+ }));
122
+ } catch (err) {
123
+ console.error("Error fetching search results from Algolia:", err);
124
+ }
125
+ }, 250);
126
+ return () => clearTimeout(delayDebounceFn);
127
+ }, [
128
+ query,
129
+ algoliaConfig,
130
+ currentLocale,
131
+ currentVersion
132
+ ]);
133
+ const searchDataMap = useMemo(() => {
134
+ const map = /* @__PURE__ */ new Map();
135
+ for (const doc of searchData) map.set(doc.id, doc);
136
+ return map;
137
+ }, []);
138
+ return {
139
+ isOpen,
140
+ setIsOpen,
141
+ query,
142
+ setQuery,
143
+ list: useMemo(() => {
144
+ if (!query) return routes.filter((r) => {
145
+ const localeMatch = !currentLocale || r.locale === currentLocale;
146
+ const versionMatch = !currentVersion || r.version === currentVersion;
147
+ return localeMatch && versionMatch;
148
+ }).slice(0, 10).map((r) => ({
149
+ id: r.path,
150
+ title: r.title,
151
+ path: r.path,
152
+ bio: r.description || "",
153
+ groupTitle: r.groupTitle
154
+ }));
155
+ if (algoliaConfig) return algoliaResults;
156
+ if (!index) return [];
157
+ const searchResults = index.search(query, {
158
+ limit: 20,
159
+ suggest: true
160
+ });
161
+ const results = [];
162
+ const seen = /* @__PURE__ */ new Set();
163
+ for (const id of searchResults) {
164
+ const doc = searchDataMap.get(id);
165
+ if (!doc) continue;
166
+ const localeMatch = !currentLocale || doc.locale === currentLocale;
167
+ const versionMatch = !currentVersion || doc.version === currentVersion;
168
+ if (!localeMatch || !versionMatch) continue;
169
+ if (seen.has(doc.url)) continue;
170
+ seen.add(doc.url);
171
+ results.push({
172
+ id: doc.url,
173
+ title: doc.title,
174
+ path: doc.url,
175
+ bio: doc.display,
176
+ groupTitle: doc.display.split(" > ")[0],
177
+ isHeading: doc.url.includes("#")
178
+ });
179
+ }
180
+ return results.slice(0, 10);
181
+ }, [
182
+ query,
183
+ index,
184
+ currentLocale,
185
+ currentVersion,
186
+ routes,
187
+ searchDataMap,
188
+ algoliaConfig,
189
+ algoliaResults
190
+ ]),
191
+ input: {
192
+ value: query,
193
+ onChange: (e) => setQuery(e.target.value)
194
+ }
195
+ };
196
+ }
197
+
198
+ //#endregion
199
+ //#region src/client/components/ui-base/search-dialog.tsx
200
+ function Highlight({ text, query }) {
201
+ if (!query || !text) return /* @__PURE__ */ jsx(Fragment, { children: text });
202
+ const escapedQuery = query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
203
+ const regex = new RegExp(`(${escapedQuery})`, "gi");
204
+ return /* @__PURE__ */ jsx(Fragment, { children: text.split(regex).map((part, i) => regex.test(part) ? /* @__PURE__ */ jsx("mark", {
205
+ className: "bg-primary-500/20 text-primary-600 dark:text-primary-400 font-bold px-0.5 rounded-sm",
206
+ children: part
207
+ }, i) : part) });
208
+ }
209
+ function SearchDialog({ routes }) {
210
+ const { isOpen, setIsOpen, query, setQuery, list } = useSearch(routes);
211
+ const navigate = useNavigate();
212
+ useEffect(() => {
213
+ const handleKeyDown = (e) => {
214
+ if ((/Mac/.test(navigator.userAgent) ? e.metaKey : e.ctrlKey) && (e.key === "k" || e.key === "j")) {
215
+ e.preventDefault();
216
+ setIsOpen((prev) => !prev);
217
+ }
218
+ };
219
+ window.addEventListener("keydown", handleKeyDown);
220
+ return () => window.removeEventListener("keydown", handleKeyDown);
221
+ }, [setIsOpen]);
222
+ const handleSelect = useCallback((key) => {
223
+ const path = String(key);
224
+ setIsOpen(false);
225
+ const [baseUrl, hash] = path.split("#");
226
+ navigate(`${baseUrl}${query ? `?hl=${encodeURIComponent(query)}` : ""}${hash ? `#${hash}` : ""}`);
227
+ if (hash) setTimeout(() => {
228
+ const el = document.getElementById(hash);
229
+ if (el) el.scrollIntoView({ behavior: "smooth" });
230
+ }, 100);
231
+ }, [
232
+ navigate,
233
+ setIsOpen,
234
+ query
235
+ ]);
236
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
237
+ /* @__PURE__ */ jsxs(Navbar.SearchTrigger.Desktop, {
238
+ onPress: () => setIsOpen(true),
239
+ className: "rounded-xl border border-subtle bg-surface text-muted transition-all duration-200 hover:border-primary-500/50 hover:text-body hover:bg-soft/50 hover:shadow-sm active:scale-[0.98] focus-visible:ring-2 focus-visible:ring-primary-500/30",
240
+ children: [/* @__PURE__ */ jsxs("div", {
241
+ className: "flex items-center gap-2",
242
+ children: [/* @__PURE__ */ jsx(Search, { size: 16 }), /* @__PURE__ */ jsx("span", {
243
+ className: "hidden sm:inline-block",
244
+ children: "Search docs..."
245
+ })]
246
+ }), /* @__PURE__ */ jsx(Navbar.SearchTrigger.Kbd, { className: "[&_kbd]:bg-main [&_kbd]:border [&_kbd]:border-subtle [&_kbd]:rounded [&_kbd]:px-1.5 [&_kbd]:h-5 [&_kbd]:w-5" })]
247
+ }),
248
+ /* @__PURE__ */ jsx(Navbar.SearchTrigger.Mobile, {
249
+ onPress: () => setIsOpen(true),
250
+ className: "rounded-xl text-muted transition-all duration-200 hover:text-body active:scale-95 focus-visible:ring-2 focus-visible:ring-primary-500/30",
251
+ children: /* @__PURE__ */ jsx(Search, { size: 20 })
252
+ }),
253
+ /* @__PURE__ */ jsx(InternalErrorBoundary, { children: /* @__PURE__ */ jsx(SearchDialog$1.Overlay, {
254
+ isOpen,
255
+ isDismissable: true,
256
+ 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",
258
+ children: /* @__PURE__ */ jsx(SearchDialog$1.Content, {
259
+ className: "w-full max-w-lg bg-main border border-subtle shadow-md rounded-2xl overflow-hidden p-6",
260
+ children: /* @__PURE__ */ jsx(SearchDialog$1.Dialog, {
261
+ "aria-label": "Search documentation",
262
+ className: "flex flex-col min-h-0 h-[450px]",
263
+ children: /* @__PURE__ */ jsxs(SearchDialog$1.Autocomplete, {
264
+ onSelectionChange: handleSelect,
265
+ className: "flex flex-col min-h-0",
266
+ children: [/* @__PURE__ */ jsxs(SearchDialog$1.Input, {
267
+ value: query,
268
+ onChange: setQuery,
269
+ className: "flex items-center gap-2 border border-subtle bg-surface px-4 py-2.5 rounded-xl focus-within:border-primary-500 mb-4",
270
+ children: [/* @__PURE__ */ jsx(SearchDialog$1.Input.SearchInput, {
271
+ placeholder: "Search documentation...",
272
+ className: "w-full bg-transparent outline-none text-body text-sm"
273
+ }), query && /* @__PURE__ */ jsx(SearchDialog$1.Input.Button, {
274
+ onPress: () => setQuery(""),
275
+ className: "text-muted hover:text-body text-xs cursor-pointer select-none",
276
+ children: "✕"
277
+ })]
278
+ }), /* @__PURE__ */ jsx(SearchDialog$1.List, {
279
+ items: list,
280
+ children: (item) => /* @__PURE__ */ jsxs(SearchDialog$1.Item, {
281
+ onPress: () => handleSelect(item.id),
282
+ textValue: item.title,
283
+ 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
+ children: [/* @__PURE__ */ jsx(SearchDialog$1.Item.Icon, {
285
+ isHeading: item.isHeading,
286
+ className: "text-muted group-hover:text-primary-500 group-focus:text-primary-500"
287
+ }), /* @__PURE__ */ jsxs("div", {
288
+ className: "flex flex-col justify-center min-w-0",
289
+ children: [/* @__PURE__ */ jsx(SearchDialog$1.Item.Title, {
290
+ className: "text-sm font-medium text-body truncate dark:group-hover:text-primary-100",
291
+ children: /* @__PURE__ */ jsx(Highlight, {
292
+ text: item.title,
293
+ query
294
+ })
295
+ }), /* @__PURE__ */ jsx(SearchDialog$1.Item.Bio, {
296
+ className: "text-xs text-muted truncate",
297
+ children: /* @__PURE__ */ jsx(Highlight, {
298
+ text: item.bio,
299
+ query
300
+ })
301
+ })]
302
+ })]
303
+ }, item.id)
304
+ })]
305
+ })
306
+ })
307
+ })
308
+ }) })
309
+ ] });
310
+ }
311
+
312
+ //#endregion
313
+ export { useSearch as n, InternalErrorBoundary as r, SearchDialog as t };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Boltdocs - https://boltdocs.vercel.app
3
+ * Copyright (c) 2026 Jesus Alcala
4
+ * Licensed under the MIT License.
5
+ */
6
+ const require_search_dialog = require('./search-dialog-BYhOov4S.cjs');
7
+
8
+ exports.SearchDialog = require_search_dialog.SearchDialog;