boltdocs 1.6.0 → 1.7.1

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 (57) hide show
  1. package/dist/{SearchDialog-J3KNRGNO.mjs → SearchDialog-6Z7CUAYJ.mjs} +8 -1
  2. package/dist/{SearchDialog-3QICRMWF.css → SearchDialog-GOZ6X53X.css} +385 -113
  3. package/dist/{chunk-HSPDIRTW.mjs → chunk-SFVOGJ2W.mjs} +955 -737
  4. package/dist/client/index.css +385 -113
  5. package/dist/client/index.d.mts +19 -7
  6. package/dist/client/index.d.ts +19 -7
  7. package/dist/client/index.js +964 -577
  8. package/dist/client/index.mjs +118 -1
  9. package/dist/client/ssr.css +385 -113
  10. package/dist/client/ssr.d.mts +3 -1
  11. package/dist/client/ssr.d.ts +3 -1
  12. package/dist/client/ssr.js +743 -474
  13. package/dist/client/ssr.mjs +3 -2
  14. package/dist/{config-DkZg5aCf.d.ts → config-D68h41CA.d.mts} +21 -2
  15. package/dist/{config-DkZg5aCf.d.mts → config-D68h41CA.d.ts} +21 -2
  16. package/dist/node/index.d.mts +12 -2
  17. package/dist/node/index.d.ts +12 -2
  18. package/dist/node/index.js +48 -21
  19. package/dist/node/index.mjs +48 -21
  20. package/dist/{types-DGIo1VKD.d.mts → types-BbceAHA0.d.mts} +15 -0
  21. package/dist/{types-DGIo1VKD.d.ts → types-BbceAHA0.d.ts} +15 -0
  22. package/package.json +1 -1
  23. package/src/client/app/index.tsx +16 -11
  24. package/src/client/index.ts +2 -0
  25. package/src/client/ssr.tsx +4 -1
  26. package/src/client/theme/components/mdx/Table.tsx +151 -0
  27. package/src/client/theme/components/mdx/index.ts +3 -0
  28. package/src/client/theme/components/mdx/mdx-components.css +128 -0
  29. package/src/client/theme/styles/markdown.css +8 -3
  30. package/src/client/theme/styles/variables.css +34 -9
  31. package/src/client/theme/ui/ErrorBoundary/ErrorBoundary.tsx +46 -0
  32. package/src/client/theme/ui/ErrorBoundary/index.ts +1 -0
  33. package/src/client/theme/ui/Layout/Layout.tsx +10 -11
  34. package/src/client/theme/ui/Layout/base.css +15 -3
  35. package/src/client/theme/ui/Link/Link.tsx +2 -2
  36. package/src/client/theme/ui/Link/LinkPreview.tsx +9 -14
  37. package/src/client/theme/ui/Link/link-preview.css +30 -27
  38. package/src/client/theme/ui/Navbar/Navbar.tsx +65 -17
  39. package/src/client/theme/ui/Navbar/Tabs.tsx +99 -0
  40. package/src/client/theme/ui/Navbar/navbar.css +119 -5
  41. package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +66 -57
  42. package/src/client/theme/ui/OnThisPage/toc.css +30 -10
  43. package/src/client/theme/ui/ProgressBar/ProgressBar.css +17 -0
  44. package/src/client/theme/ui/ProgressBar/ProgressBar.tsx +51 -0
  45. package/src/client/theme/ui/ProgressBar/index.ts +1 -0
  46. package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +11 -1
  47. package/src/client/theme/ui/Sidebar/Sidebar.tsx +97 -57
  48. package/src/client/theme/ui/Sidebar/sidebar.css +61 -67
  49. package/src/client/types.ts +12 -0
  50. package/src/node/config.ts +19 -1
  51. package/src/node/plugin/entry.ts +5 -1
  52. package/src/node/plugin/index.ts +2 -1
  53. package/src/node/routes/index.ts +13 -1
  54. package/src/node/routes/parser.ts +32 -7
  55. package/src/node/routes/types.ts +11 -1
  56. package/src/node/ssg/index.ts +2 -1
  57. package/src/node/ssg/options.ts +2 -0
@@ -4,77 +4,293 @@ import {
4
4
  } from "./chunk-FMTOYQLO.mjs";
5
5
 
6
6
  // src/client/theme/ui/Navbar/Navbar.tsx
7
- import React10 from "react";
7
+ import { Suspense as Suspense2, lazy as lazy2 } from "react";
8
+ import { Link as Link2, useLocation as useLocation11 } from "react-router-dom";
9
+ import { ChevronDown as ChevronDown3 } from "lucide-react";
8
10
 
9
- // src/client/theme/ui/Link/Link.tsx
10
- import React7 from "react";
11
- import {
12
- Link as RouterLink,
13
- NavLink as RouterNavLink,
14
- useLocation as useLocation7,
15
- useNavigate
16
- } from "react-router-dom";
11
+ // src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx
12
+ import { useState, useRef, useEffect } from "react";
13
+ import { Globe, ChevronDown } from "lucide-react";
14
+ import { useNavigate, useLocation } from "react-router-dom";
15
+ import { jsx, jsxs } from "react/jsx-runtime";
16
+ function getBaseFilePath(filePath, version, locale) {
17
+ let path = filePath;
18
+ if (version && (path === version || path.startsWith(version + "/"))) {
19
+ path = path === version ? "index.md" : path.slice(version.length + 1);
20
+ }
21
+ if (locale && (path === locale || path.startsWith(locale + "/"))) {
22
+ path = path === locale ? "index.md" : path.slice(locale.length + 1);
23
+ }
24
+ return path;
25
+ }
26
+ function LanguageSwitcher({
27
+ i18n,
28
+ currentLocale,
29
+ allRoutes
30
+ }) {
31
+ const [isOpen, setIsOpen] = useState(false);
32
+ const dropdownRef = useRef(null);
33
+ const navigate = useNavigate();
34
+ const location = useLocation();
35
+ useEffect(() => {
36
+ function handleClickOutside(event) {
37
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
38
+ setIsOpen(false);
39
+ }
40
+ }
41
+ document.addEventListener("mousedown", handleClickOutside);
42
+ return () => document.removeEventListener("mousedown", handleClickOutside);
43
+ }, []);
44
+ const handleSelect = (locale) => {
45
+ setIsOpen(false);
46
+ if (locale === currentLocale) return;
47
+ const currentRoute = allRoutes.find((r) => r.path === location.pathname);
48
+ let targetPath = "/";
49
+ if (currentRoute) {
50
+ const baseFile = getBaseFilePath(
51
+ currentRoute.filePath,
52
+ currentRoute.version,
53
+ currentRoute.locale
54
+ );
55
+ const targetRoute = allRoutes.find(
56
+ (r) => getBaseFilePath(r.filePath, r.version, r.locale) === baseFile && (r.locale || i18n.defaultLocale) === locale && r.version === currentRoute.version
57
+ );
58
+ if (targetRoute) {
59
+ targetPath = targetRoute.path;
60
+ } else {
61
+ const defaultIndexRoute = allRoutes.find(
62
+ (r) => getBaseFilePath(r.filePath, r.version, r.locale) === "index.md" && (r.locale || i18n.defaultLocale) === locale && r.version === currentRoute.version
63
+ );
64
+ targetPath = defaultIndexRoute ? defaultIndexRoute.path : locale === i18n.defaultLocale ? currentRoute.version ? `/${currentRoute.version}` : "/" : currentRoute.version ? `/${currentRoute.version}/${locale}` : `/${locale}`;
65
+ }
66
+ } else {
67
+ targetPath = locale === i18n.defaultLocale ? "/" : `/${locale}`;
68
+ }
69
+ navigate(targetPath);
70
+ };
71
+ return /* @__PURE__ */ jsxs("div", { className: "boltdocs-language-switcher", ref: dropdownRef, children: [
72
+ /* @__PURE__ */ jsxs(
73
+ "button",
74
+ {
75
+ className: "language-btn",
76
+ onClick: () => setIsOpen(!isOpen),
77
+ "aria-label": "Switch language",
78
+ "aria-expanded": isOpen,
79
+ "aria-haspopup": "listbox",
80
+ children: [
81
+ /* @__PURE__ */ jsx(Globe, { size: 18 }),
82
+ /* @__PURE__ */ jsx("span", { className: "language-label", children: i18n.locales[currentLocale] || currentLocale }),
83
+ /* @__PURE__ */ jsx(ChevronDown, { size: 14 })
84
+ ]
85
+ }
86
+ ),
87
+ isOpen && /* @__PURE__ */ jsx("div", { className: "language-dropdown", children: Object.entries(i18n.locales).map(([key, label]) => /* @__PURE__ */ jsx(
88
+ "button",
89
+ {
90
+ className: `language-option ${key === currentLocale ? "active" : ""}`,
91
+ onClick: () => handleSelect(key),
92
+ children: label
93
+ },
94
+ key
95
+ )) })
96
+ ] });
97
+ }
17
98
 
18
- // src/client/app/preload.tsx
19
- import { createContext, useContext, useCallback } from "react";
20
- import { jsx } from "react/jsx-runtime";
21
- var PreloadContext = createContext({
22
- preload: () => {
23
- },
24
- routes: []
25
- });
26
- function usePreload() {
27
- return useContext(PreloadContext);
99
+ // src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx
100
+ import { useState as useState2, useRef as useRef2, useEffect as useEffect2 } from "react";
101
+ import { ChevronDown as ChevronDown2 } from "lucide-react";
102
+ import { useNavigate as useNavigate2, useLocation as useLocation2 } from "react-router-dom";
103
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
104
+ function getBaseFilePath2(filePath, version, locale) {
105
+ let path = filePath;
106
+ if (version && (path === version || path.startsWith(version + "/"))) {
107
+ path = path === version ? "index.md" : path.slice(version.length + 1);
108
+ }
109
+ if (locale && (path === locale || path.startsWith(locale + "/"))) {
110
+ path = path === locale ? "index.md" : path.slice(locale.length + 1);
111
+ }
112
+ return path;
28
113
  }
29
- function PreloadProvider({
30
- routes,
31
- modules,
32
- children
114
+ function VersionSwitcher({
115
+ versions,
116
+ currentVersion,
117
+ currentLocale,
118
+ allRoutes
33
119
  }) {
34
- const preload = useCallback(
35
- (path) => {
36
- const cleanPath = path.split("#")[0].split("?")[0];
37
- const route = routes.find(
38
- (r) => r.path === cleanPath || cleanPath === "/" && r.path === ""
120
+ const [isOpen, setIsOpen] = useState2(false);
121
+ const dropdownRef = useRef2(null);
122
+ const navigate = useNavigate2();
123
+ const location = useLocation2();
124
+ useEffect2(() => {
125
+ function handleClickOutside(event) {
126
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
127
+ setIsOpen(false);
128
+ }
129
+ }
130
+ document.addEventListener("mousedown", handleClickOutside);
131
+ return () => document.removeEventListener("mousedown", handleClickOutside);
132
+ }, []);
133
+ const handleSelect = (version) => {
134
+ setIsOpen(false);
135
+ if (version === currentVersion) return;
136
+ const currentRoute = allRoutes.find((r) => r.path === location.pathname);
137
+ let targetPath = `/docs/${version}`;
138
+ if (currentRoute) {
139
+ const baseFile = getBaseFilePath2(
140
+ currentRoute.filePath,
141
+ currentRoute.version,
142
+ currentRoute.locale
39
143
  );
40
- if (route && route.filePath) {
41
- const loaderKey = Object.keys(modules).find(
42
- (k) => k.endsWith("/" + route.filePath)
144
+ const targetRoute = allRoutes.find(
145
+ (r) => getBaseFilePath2(r.filePath, r.version, r.locale) === baseFile && (r.version || versions.defaultVersion) === version && (currentLocale ? r.locale === currentLocale : !r.locale)
146
+ );
147
+ if (targetRoute) {
148
+ targetPath = targetRoute.path;
149
+ } else {
150
+ const versionIndexRoute = allRoutes.find(
151
+ (r) => getBaseFilePath2(r.filePath, r.version, r.locale) === "index.md" && (r.version || versions.defaultVersion) === version && (currentLocale ? r.locale === currentLocale : !r.locale)
43
152
  );
44
- if (loaderKey) {
45
- modules[loaderKey]().catch((err) => {
46
- console.error(`[boltdocs] Failed to preload route ${path}:`, err);
47
- });
48
- }
153
+ targetPath = versionIndexRoute ? versionIndexRoute.path : `/docs/${version}${currentLocale ? `/${currentLocale}` : ""}`;
49
154
  }
50
- },
51
- [routes, modules]
155
+ }
156
+ navigate(targetPath);
157
+ };
158
+ return /* @__PURE__ */ jsxs2(
159
+ "div",
160
+ {
161
+ className: "boltdocs-version-switcher",
162
+ ref: dropdownRef,
163
+ style: { position: "relative", display: "flex", alignItems: "center" },
164
+ children: [
165
+ /* @__PURE__ */ jsxs2(
166
+ "button",
167
+ {
168
+ className: "navbar-version",
169
+ onClick: () => setIsOpen(!isOpen),
170
+ "aria-label": "Switch version",
171
+ "aria-expanded": isOpen,
172
+ "aria-haspopup": "listbox",
173
+ style: {
174
+ fontFamily: "inherit",
175
+ padding: "0.25rem 0.5rem",
176
+ marginLeft: "0.5rem"
177
+ },
178
+ children: [
179
+ /* @__PURE__ */ jsx2("span", { children: versions.versions[currentVersion] || currentVersion }),
180
+ /* @__PURE__ */ jsx2(ChevronDown2, { size: 14 })
181
+ ]
182
+ }
183
+ ),
184
+ isOpen && /* @__PURE__ */ jsx2(
185
+ "div",
186
+ {
187
+ className: "language-dropdown",
188
+ style: {
189
+ left: "0.5rem",
190
+ right: "auto",
191
+ minWidth: "150px",
192
+ top: "calc(100% + 8px)"
193
+ },
194
+ children: Object.entries(versions.versions).map(([key, label]) => /* @__PURE__ */ jsx2(
195
+ "button",
196
+ {
197
+ className: `language-option ${key === currentVersion ? "active" : ""}`,
198
+ onClick: () => handleSelect(key),
199
+ children: label
200
+ },
201
+ key
202
+ ))
203
+ }
204
+ )
205
+ ]
206
+ }
52
207
  );
53
- return /* @__PURE__ */ jsx(PreloadContext.Provider, { value: { preload, routes }, children });
54
208
  }
55
209
 
56
- // src/client/app/index.tsx
57
- import React6, { useEffect as useEffect4, useState as useState6 } from "react";
58
- import ReactDOM from "react-dom/client";
59
- import {
60
- BrowserRouter,
61
- Routes,
62
- Route,
63
- Outlet,
64
- useLocation as useLocation6
65
- } from "react-router-dom";
210
+ // src/client/theme/ui/ThemeToggle/ThemeToggle.tsx
211
+ import { useEffect as useEffect3, useState as useState3 } from "react";
212
+ import { Sun, Moon } from "lucide-react";
213
+ import { jsx as jsx3 } from "react/jsx-runtime";
214
+ function ThemeToggle() {
215
+ const [theme, setTheme] = useState3("dark");
216
+ const [mounted, setMounted] = useState3(false);
217
+ useEffect3(() => {
218
+ setMounted(true);
219
+ const stored = localStorage.getItem("boltdocs-theme");
220
+ if (stored === "light" || stored === "dark") {
221
+ setTheme(stored);
222
+ } else {
223
+ const prefersDark = window.matchMedia(
224
+ "(prefers-color-scheme: dark)"
225
+ ).matches;
226
+ setTheme(prefersDark ? "dark" : "light");
227
+ }
228
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
229
+ const handleChange = (e) => {
230
+ if (!localStorage.getItem("boltdocs-theme")) {
231
+ setTheme(e.matches ? "dark" : "light");
232
+ }
233
+ };
234
+ mediaQuery.addEventListener("change", handleChange);
235
+ return () => mediaQuery.removeEventListener("change", handleChange);
236
+ }, []);
237
+ useEffect3(() => {
238
+ if (!mounted) return;
239
+ const root = document.documentElement;
240
+ if (theme === "light") {
241
+ root.classList.add("theme-light");
242
+ root.dataset.theme = "light";
243
+ } else {
244
+ root.classList.remove("theme-light");
245
+ root.dataset.theme = "dark";
246
+ }
247
+ }, [theme, mounted]);
248
+ const toggleTheme = () => {
249
+ const newTheme = theme === "dark" ? "light" : "dark";
250
+ setTheme(newTheme);
251
+ localStorage.setItem("boltdocs-theme", newTheme);
252
+ };
253
+ if (!mounted) {
254
+ return /* @__PURE__ */ jsx3("button", { className: "navbar-icon-btn", "aria-label": "Toggle theme", disabled: true, children: /* @__PURE__ */ jsx3("span", { style: { width: 20, height: 20, display: "inline-block" } }) });
255
+ }
256
+ return /* @__PURE__ */ jsx3(
257
+ "button",
258
+ {
259
+ className: "navbar-icon-btn",
260
+ onClick: toggleTheme,
261
+ "aria-label": "Toggle theme",
262
+ title: `Switch to ${theme === "dark" ? "light" : "dark"} theme`,
263
+ children: theme === "dark" ? /* @__PURE__ */ jsx3(Sun, { size: 20 }) : /* @__PURE__ */ jsx3(Moon, { size: 20 })
264
+ }
265
+ );
266
+ }
66
267
 
67
- // src/client/theme/ui/Layout/Layout.tsx
68
- import React4, { useState as useState4 } from "react";
69
- import { useLocation as useLocation5 } from "react-router-dom";
70
- import { ChevronLeft as ChevronLeft2, ChevronRight as ChevronRight3 } from "lucide-react";
268
+ // src/client/theme/icons/discord.tsx
269
+ import { jsx as jsx4 } from "react/jsx-runtime";
270
+ var Discord = (props) => /* @__PURE__ */ jsx4("svg", { ...props, viewBox: "0 0 256 199", preserveAspectRatio: "xMidYMid", children: /* @__PURE__ */ jsx4(
271
+ "path",
272
+ {
273
+ d: "M216.856 16.597A208.502 208.502 0 0 0 164.042 0c-2.275 4.113-4.933 9.645-6.766 14.046-19.692-2.961-39.203-2.961-58.533 0-1.832-4.4-4.55-9.933-6.846-14.046a207.809 207.809 0 0 0-52.855 16.638C5.618 67.147-3.443 116.4 1.087 164.956c22.169 16.555 43.653 26.612 64.775 33.193A161.094 161.094 0 0 0 79.735 175.3a136.413 136.413 0 0 1-21.846-10.632 108.636 108.636 0 0 0 5.356-4.237c42.122 19.702 87.89 19.702 129.51 0a131.66 131.66 0 0 0 5.355 4.237 136.07 136.07 0 0 1-21.886 10.653c4.006 8.02 8.638 15.67 13.873 22.848 21.142-6.58 42.646-16.637 64.815-33.213 5.316-56.288-9.08-105.09-38.056-148.36ZM85.474 135.095c-12.645 0-23.015-11.805-23.015-26.18s10.149-26.2 23.015-26.2c12.867 0 23.236 11.804 23.015 26.2.02 14.375-10.148 26.18-23.015 26.18Zm85.051 0c-12.645 0-23.014-11.805-23.014-26.18s10.148-26.2 23.014-26.2c12.867 0 23.236 11.804 23.015 26.2 0 14.375-10.148 26.18-23.015 26.18Z",
274
+ fill: "currentColor"
275
+ }
276
+ ) });
277
+
278
+ // src/client/theme/icons/twitter.tsx
279
+ import { jsx as jsx5 } from "react/jsx-runtime";
280
+ var XformerlyTwitter = (props) => /* @__PURE__ */ jsx5("svg", { ...props, fill: "none", viewBox: "0 0 1200 1227", children: /* @__PURE__ */ jsx5(
281
+ "path",
282
+ {
283
+ fill: "currentColor",
284
+ d: "M714.163 519.284 1160.89 0h-105.86L667.137 450.887 357.328 0H0l468.492 681.821L0 1226.37h105.866l409.625-476.152 327.181 476.152H1200L714.137 519.284h.026ZM569.165 687.828l-47.468-67.894-377.686-540.24h162.604l304.797 435.991 47.468 67.894 396.2 566.721H892.476L569.165 687.854v-.026Z"
285
+ }
286
+ ) });
71
287
 
72
288
  // src/client/theme/ui/Navbar/GithubStars.tsx
73
- import { useEffect, useState } from "react";
289
+ import { useEffect as useEffect4, useState as useState4 } from "react";
74
290
 
75
291
  // src/client/theme/icons/github.tsx
76
- import { jsx as jsx2 } from "react/jsx-runtime";
77
- var GitHub = (props) => /* @__PURE__ */ jsx2("svg", { ...props, viewBox: "0 0 1024 1024", fill: "none", children: /* @__PURE__ */ jsx2(
292
+ import { jsx as jsx6 } from "react/jsx-runtime";
293
+ var GitHub = (props) => /* @__PURE__ */ jsx6("svg", { ...props, viewBox: "0 0 1024 1024", fill: "none", children: /* @__PURE__ */ jsx6(
78
294
  "path",
79
295
  {
80
296
  fillRule: "evenodd",
@@ -86,15 +302,15 @@ var GitHub = (props) => /* @__PURE__ */ jsx2("svg", { ...props, viewBox: "0 0 10
86
302
  ) });
87
303
 
88
304
  // src/client/theme/ui/Navbar/GithubStars.tsx
89
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
305
+ import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
90
306
  function GithubStars({ repo }) {
91
- const [stars, setStars] = useState(null);
92
- useEffect(() => {
307
+ const [stars, setStars] = useState4(null);
308
+ useEffect4(() => {
93
309
  if (repo) {
94
310
  getStarsRepo(repo).then((stars2) => setStars(stars2)).catch(() => setStars("0"));
95
311
  }
96
312
  }, [repo]);
97
- return /* @__PURE__ */ jsxs(
313
+ return /* @__PURE__ */ jsxs3(
98
314
  "a",
99
315
  {
100
316
  href: `https://github.com/${repo}`,
@@ -102,22 +318,89 @@ function GithubStars({ repo }) {
102
318
  rel: "noopener noreferrer",
103
319
  className: "navbar-github-stars",
104
320
  children: [
105
- /* @__PURE__ */ jsx3(GitHub, {}),
106
- stars && /* @__PURE__ */ jsx3("span", { children: stars })
321
+ /* @__PURE__ */ jsx7(GitHub, {}),
322
+ stars && /* @__PURE__ */ jsx7("span", { children: stars })
107
323
  ]
108
324
  }
109
325
  );
110
326
  }
111
327
 
328
+ // src/client/theme/ui/Navbar/Tabs.tsx
329
+ import { useEffect as useEffect10, useRef as useRef6, useState as useState12 } from "react";
330
+ import { useLocation as useLocation10 } from "react-router-dom";
331
+
332
+ // src/client/theme/ui/Link/Link.tsx
333
+ import React10 from "react";
334
+ import {
335
+ Link as RouterLink,
336
+ NavLink as RouterNavLink,
337
+ useLocation as useLocation9,
338
+ useNavigate as useNavigate3
339
+ } from "react-router-dom";
340
+
341
+ // src/client/app/preload.tsx
342
+ import { createContext, useContext, useCallback } from "react";
343
+ import { jsx as jsx8 } from "react/jsx-runtime";
344
+ var PreloadContext = createContext({
345
+ preload: () => {
346
+ },
347
+ routes: []
348
+ });
349
+ function usePreload() {
350
+ return useContext(PreloadContext);
351
+ }
352
+ function PreloadProvider({
353
+ routes,
354
+ modules,
355
+ children
356
+ }) {
357
+ const preload = useCallback(
358
+ (path) => {
359
+ const cleanPath = path.split("#")[0].split("?")[0];
360
+ const route = routes.find(
361
+ (r) => r.path === cleanPath || cleanPath === "/" && r.path === ""
362
+ );
363
+ if (route && route.filePath) {
364
+ const loaderKey = Object.keys(modules).find(
365
+ (k) => k.endsWith("/" + route.filePath)
366
+ );
367
+ if (loaderKey) {
368
+ modules[loaderKey]().catch((err) => {
369
+ console.error(`[boltdocs] Failed to preload route ${path}:`, err);
370
+ });
371
+ }
372
+ }
373
+ },
374
+ [routes, modules]
375
+ );
376
+ return /* @__PURE__ */ jsx8(PreloadContext.Provider, { value: { preload, routes }, children });
377
+ }
378
+
379
+ // src/client/app/index.tsx
380
+ import React9, { useEffect as useEffect8, useState as useState10 } from "react";
381
+ import ReactDOM from "react-dom/client";
382
+ import {
383
+ BrowserRouter,
384
+ Routes,
385
+ Route,
386
+ Outlet,
387
+ useLocation as useLocation8
388
+ } from "react-router-dom";
389
+
390
+ // src/client/theme/ui/Layout/Layout.tsx
391
+ import React7 from "react";
392
+ import { useLocation as useLocation7 } from "react-router-dom";
393
+ import { ChevronLeft, ChevronRight as ChevronRight3 } from "lucide-react";
394
+
112
395
  // src/client/theme/ui/Sidebar/Sidebar.tsx
113
- import { useState as useState2 } from "react";
114
- import { useLocation } from "react-router-dom";
396
+ import { useState as useState5 } from "react";
397
+ import { useLocation as useLocation3 } from "react-router-dom";
115
398
 
116
399
  // src/client/theme/ui/PoweredBy/PoweredBy.tsx
117
400
  import { Zap } from "lucide-react";
118
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
401
+ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
119
402
  function PoweredBy() {
120
- return /* @__PURE__ */ jsx4("div", { className: "powered-by-container", children: /* @__PURE__ */ jsxs2(
403
+ return /* @__PURE__ */ jsx9("div", { className: "powered-by-container", children: /* @__PURE__ */ jsxs4(
121
404
  "a",
122
405
  {
123
406
  href: "https://github.com/jesusalcaladev/boltdocs",
@@ -125,17 +408,18 @@ function PoweredBy() {
125
408
  rel: "noopener noreferrer",
126
409
  className: "powered-by-link",
127
410
  children: [
128
- /* @__PURE__ */ jsx4(Zap, { className: "powered-by-icon", size: 12, fill: "currentColor" }),
129
- /* @__PURE__ */ jsx4("span", { children: "Powered by" }),
130
- /* @__PURE__ */ jsx4("span", { className: "powered-by-brand", children: "LiteDocs" })
411
+ /* @__PURE__ */ jsx9(Zap, { className: "powered-by-icon", size: 12, fill: "currentColor" }),
412
+ /* @__PURE__ */ jsx9("span", { children: "Powered by" }),
413
+ /* @__PURE__ */ jsx9("span", { className: "powered-by-brand", children: "LiteDocs" })
131
414
  ]
132
415
  }
133
416
  ) });
134
417
  }
135
418
 
136
419
  // src/client/theme/ui/Sidebar/Sidebar.tsx
137
- import { ChevronRight, PanelLeft } from "lucide-react";
138
- import { Fragment, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
420
+ import { ChevronRight } from "lucide-react";
421
+ import * as LucideIcons from "lucide-react";
422
+ import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
139
423
  function renderBadge(badgeRaw) {
140
424
  if (!badgeRaw) return null;
141
425
  let text = "";
@@ -156,7 +440,6 @@ function renderBadge(badgeRaw) {
156
440
  }
157
441
  }
158
442
  if (!text) return null;
159
- if (!text) return null;
160
443
  let typeClass = "badge-default";
161
444
  const lowerText = text.toLowerCase();
162
445
  if (lowerText === "new") {
@@ -166,18 +449,51 @@ function renderBadge(badgeRaw) {
166
449
  } else if (lowerText === "updated") {
167
450
  typeClass = "badge-updated";
168
451
  }
169
- return /* @__PURE__ */ jsx5("span", { className: `sidebar-badge ${typeClass}`, children: text });
452
+ return /* @__PURE__ */ jsx10("span", { className: `sidebar-badge ${typeClass}`, children: text });
453
+ }
454
+ function renderIcon(iconName, size = 16) {
455
+ if (!iconName) return null;
456
+ const trimmed = iconName.trim();
457
+ if (trimmed.startsWith("<svg") || trimmed.includes("http")) {
458
+ if (trimmed.startsWith("<svg")) {
459
+ return /* @__PURE__ */ jsx10(
460
+ "span",
461
+ {
462
+ className: "sidebar-icon svg-icon",
463
+ dangerouslySetInnerHTML: { __html: trimmed }
464
+ }
465
+ );
466
+ }
467
+ return /* @__PURE__ */ jsx10(
468
+ "img",
469
+ {
470
+ src: trimmed,
471
+ className: "sidebar-icon",
472
+ style: { width: size, height: size },
473
+ alt: ""
474
+ }
475
+ );
476
+ }
477
+ const IconComponent = LucideIcons[iconName];
478
+ if (IconComponent) {
479
+ return /* @__PURE__ */ jsx10(IconComponent, { size, className: "sidebar-icon lucide-icon" });
480
+ }
481
+ return null;
170
482
  }
171
483
  function Sidebar({
172
484
  routes,
173
- config,
174
- isCollapsed,
175
- onToggle
485
+ config
176
486
  }) {
177
- const location = useLocation();
487
+ const location = useLocation3();
488
+ const currentRoute = routes.find((r) => r.path === location.pathname);
489
+ const activeTabId = currentRoute?.tab?.toLowerCase();
490
+ const filteredRoutes = activeTabId ? routes.filter((r) => {
491
+ if (!r.tab) return true;
492
+ return r.tab.toLowerCase() === activeTabId;
493
+ }) : routes;
178
494
  const ungrouped = [];
179
495
  const groupMap = /* @__PURE__ */ new Map();
180
- for (const route of routes) {
496
+ for (const route of filteredRoutes) {
181
497
  if (!route.group) {
182
498
  ungrouped.push(route);
183
499
  } else {
@@ -185,49 +501,41 @@ function Sidebar({
185
501
  groupMap.set(route.group, {
186
502
  slug: route.group,
187
503
  title: route.groupTitle || route.group,
188
- routes: []
504
+ routes: [],
505
+ icon: route.groupIcon
189
506
  });
190
507
  }
191
508
  groupMap.get(route.group).routes.push(route);
192
509
  }
193
510
  }
194
511
  const groups = Array.from(groupMap.values());
195
- return /* @__PURE__ */ jsxs3("aside", { className: "boltdocs-sidebar", children: [
196
- onToggle && /* @__PURE__ */ jsx5("div", { className: "sidebar-collapse", children: /* @__PURE__ */ jsx5(
197
- "button",
198
- {
199
- className: "sidebar-collapse-btn",
200
- onClick: onToggle,
201
- "aria-label": isCollapsed ? "Expand Sidebar" : "Collapse Sidebar",
202
- title: isCollapsed ? "Expand Sidebar" : "Collapse Sidebar",
203
- children: /* @__PURE__ */ jsx5(PanelLeft, { size: 18 })
204
- }
205
- ) }),
206
- !isCollapsed && /* @__PURE__ */ jsxs3(Fragment, { children: [
207
- /* @__PURE__ */ jsxs3("nav", { "aria-label": "Main Navigation", children: [
208
- /* @__PURE__ */ jsx5("ul", { className: "sidebar-list", children: ungrouped.map((route) => /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsx5(
209
- Link,
210
- {
211
- to: route.path === "" ? "/" : route.path,
212
- className: `sidebar-link ${location.pathname === route.path ? "active" : ""}`,
213
- "aria-current": location.pathname === route.path ? "page" : void 0,
214
- children: /* @__PURE__ */ jsxs3("div", { className: "sidebar-link-content", children: [
215
- /* @__PURE__ */ jsx5("span", { children: route.title }),
216
- renderBadge(route.badge)
217
- ] })
218
- }
219
- ) }, route.path)) }),
220
- groups.map((group) => /* @__PURE__ */ jsx5(
221
- SidebarGroupSection,
222
- {
223
- group,
224
- currentPath: location.pathname
225
- },
226
- group.slug
227
- ))
228
- ] }),
229
- config.themeConfig?.poweredBy !== false && /* @__PURE__ */ jsx5(PoweredBy, {})
230
- ] })
512
+ return /* @__PURE__ */ jsxs5("aside", { className: "boltdocs-sidebar", children: [
513
+ /* @__PURE__ */ jsxs5("nav", { "aria-label": "Main Navigation", children: [
514
+ /* @__PURE__ */ jsx10("ul", { className: "sidebar-list", children: ungrouped.map((route) => /* @__PURE__ */ jsx10("li", { children: /* @__PURE__ */ jsx10(
515
+ Link,
516
+ {
517
+ to: route.path === "" ? "/" : route.path,
518
+ className: `sidebar-link ${location.pathname === route.path ? "active" : ""}`,
519
+ "aria-current": location.pathname === route.path ? "page" : void 0,
520
+ children: /* @__PURE__ */ jsxs5("div", { className: "sidebar-link-content", children: [
521
+ /* @__PURE__ */ jsxs5("div", { className: "sidebar-link-title-container", children: [
522
+ renderIcon(route.icon),
523
+ /* @__PURE__ */ jsx10("span", { children: route.title })
524
+ ] }),
525
+ renderBadge(route.badge)
526
+ ] })
527
+ }
528
+ ) }, route.path)) }),
529
+ groups.map((group) => /* @__PURE__ */ jsx10(
530
+ SidebarGroupSection,
531
+ {
532
+ group,
533
+ currentPath: location.pathname
534
+ },
535
+ group.slug
536
+ ))
537
+ ] }),
538
+ config.themeConfig?.poweredBy !== false && /* @__PURE__ */ jsx10(PoweredBy, {})
231
539
  ] });
232
540
  }
233
541
  function SidebarGroupSection({
@@ -235,9 +543,9 @@ function SidebarGroupSection({
235
543
  currentPath
236
544
  }) {
237
545
  const isActive = group.routes.some((r) => currentPath === r.path);
238
- const [open, setOpen] = useState2(true);
239
- return /* @__PURE__ */ jsxs3("div", { className: "sidebar-group", children: [
240
- /* @__PURE__ */ jsxs3(
546
+ const [open, setOpen] = useState5(true);
547
+ return /* @__PURE__ */ jsxs5("div", { className: "sidebar-group", children: [
548
+ /* @__PURE__ */ jsxs5(
241
549
  "button",
242
550
  {
243
551
  className: `sidebar-group-header ${isActive ? "active" : ""}`,
@@ -245,19 +553,22 @@ function SidebarGroupSection({
245
553
  "aria-expanded": open,
246
554
  "aria-controls": `sidebar-group-${group.slug}`,
247
555
  children: [
248
- /* @__PURE__ */ jsx5("span", { className: "sidebar-group-title", children: group.title }),
249
- /* @__PURE__ */ jsx5("span", { className: `sidebar-group-chevron ${open ? "open" : ""}`, children: /* @__PURE__ */ jsx5(ChevronRight, { size: 16 }) })
556
+ /* @__PURE__ */ jsx10("div", { className: "sidebar-group-header-content", children: /* @__PURE__ */ jsx10("span", { className: "sidebar-group-title", children: group.title }) }),
557
+ /* @__PURE__ */ jsx10("span", { className: `sidebar-group-chevron ${open ? "open" : ""}`, children: /* @__PURE__ */ jsx10(ChevronRight, { size: 16 }) })
250
558
  ]
251
559
  }
252
560
  ),
253
- open && /* @__PURE__ */ jsx5("ul", { className: "sidebar-group-list", id: `sidebar-group-${group.slug}`, children: group.routes.map((route) => /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsx5(
561
+ open && /* @__PURE__ */ jsx10("ul", { className: "sidebar-group-list", id: `sidebar-group-${group.slug}`, children: group.routes.map((route) => /* @__PURE__ */ jsx10("li", { children: /* @__PURE__ */ jsx10(
254
562
  Link,
255
563
  {
256
564
  to: route.path === "" ? "/" : route.path,
257
565
  className: `sidebar-link sidebar-link-nested ${currentPath === route.path ? "active" : ""}`,
258
566
  "aria-current": currentPath === route.path ? "page" : void 0,
259
- children: /* @__PURE__ */ jsxs3("div", { className: "sidebar-link-content", children: [
260
- /* @__PURE__ */ jsx5("span", { children: route.title }),
567
+ children: /* @__PURE__ */ jsxs5("div", { className: "sidebar-link-content", children: [
568
+ /* @__PURE__ */ jsxs5("div", { className: "sidebar-link-title-container", children: [
569
+ renderIcon(route.icon),
570
+ /* @__PURE__ */ jsx10("span", { children: route.title })
571
+ ] }),
261
572
  renderBadge(route.badge)
262
573
  ] })
263
574
  }
@@ -266,22 +577,23 @@ function SidebarGroupSection({
266
577
  }
267
578
 
268
579
  // src/client/theme/ui/OnThisPage/OnThisPage.tsx
269
- import { useEffect as useEffect2, useState as useState3, useRef, useCallback as useCallback2 } from "react";
270
- import { useLocation as useLocation2 } from "react-router-dom";
580
+ import { useEffect as useEffect5, useState as useState6, useRef as useRef3, useCallback as useCallback2 } from "react";
581
+ import { useLocation as useLocation4 } from "react-router-dom";
271
582
  import { Pencil, CircleHelp } from "lucide-react";
272
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
583
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
273
584
  function OnThisPage({
274
585
  headings = [],
275
586
  editLink,
276
587
  communityHelp,
277
588
  filePath
278
589
  }) {
279
- const [activeId, setActiveId] = useState3("");
280
- const [indicatorStyle, setIndicatorStyle] = useState3({});
281
- const observerRef = useRef(null);
282
- const location = useLocation2();
283
- const listRef = useRef(null);
284
- useEffect2(() => {
590
+ const [activeId, setActiveId] = useState6(null);
591
+ const [indicatorStyle, setIndicatorStyle] = useState6({});
592
+ const observerRef = useRef3(null);
593
+ const location = useLocation4();
594
+ const listRef = useRef3(null);
595
+ const visibleIdsRef = useRef3(/* @__PURE__ */ new Set());
596
+ useEffect5(() => {
285
597
  if (headings.length > 0) {
286
598
  const hash = window.location.hash.substring(1);
287
599
  if (hash && headings.some((h) => h.id === hash)) {
@@ -291,38 +603,55 @@ function OnThisPage({
291
603
  }
292
604
  }
293
605
  }, [location.pathname, headings]);
294
- useEffect2(() => {
606
+ useEffect5(() => {
295
607
  if (!activeId || !listRef.current) return;
296
- const activeElement = listRef.current.querySelector(
608
+ const activeLink = listRef.current.querySelector(
297
609
  `a[href="#${activeId}"]`
298
610
  );
299
- if (activeElement) {
300
- const { offsetTop, offsetHeight } = activeElement;
611
+ if (activeLink) {
612
+ const top = activeLink.offsetTop;
613
+ const height = activeLink.offsetHeight;
301
614
  setIndicatorStyle({
302
- transform: `translateY(${offsetTop}px)`,
303
- height: `${offsetHeight}px`,
615
+ transform: `translateY(${top}px)`,
616
+ height: `${height}px`,
304
617
  opacity: 1
305
618
  });
306
619
  }
307
620
  }, [activeId, headings]);
308
- useEffect2(() => {
621
+ useEffect5(() => {
309
622
  if (headings.length === 0) return;
623
+ visibleIdsRef.current.clear();
310
624
  if (observerRef.current) {
311
625
  observerRef.current.disconnect();
312
626
  }
313
627
  const callback = (entries) => {
314
- const visibleEntries = entries.filter((entry) => entry.isIntersecting);
315
- if (visibleEntries.length > 0) {
316
- const closest = visibleEntries.reduce((prev, curr) => {
317
- return Math.abs(curr.boundingClientRect.top - 100) < Math.abs(prev.boundingClientRect.top - 100) ? curr : prev;
318
- });
319
- setActiveId(closest.target.id);
628
+ entries.forEach((entry) => {
629
+ if (entry.isIntersecting) {
630
+ visibleIdsRef.current.add(entry.target.id);
631
+ } else {
632
+ visibleIdsRef.current.delete(entry.target.id);
633
+ }
634
+ });
635
+ const firstVisible = headings.find((h) => visibleIdsRef.current.has(h.id));
636
+ if (firstVisible) {
637
+ setActiveId(firstVisible.id);
638
+ } else {
639
+ const firstEl = document.getElementById(headings[0].id);
640
+ if (firstEl) {
641
+ const rect = firstEl.getBoundingClientRect();
642
+ if (rect.top > 200) {
643
+ setActiveId(headings[0].id);
644
+ return;
645
+ }
646
+ }
320
647
  }
321
648
  };
322
- observerRef.current = new IntersectionObserver(callback, {
323
- rootMargin: "-100px 0px -70% 0px",
649
+ const observerOptions = {
650
+ root: document.querySelector(".boltdocs-content"),
651
+ rootMargin: "-20% 0px -70% 0px",
324
652
  threshold: [0, 1]
325
- });
653
+ };
654
+ observerRef.current = new IntersectionObserver(callback, observerOptions);
326
655
  const observeHeadings = () => {
327
656
  headings.forEach(({ id }) => {
328
657
  const el = document.getElementById(id);
@@ -347,22 +676,20 @@ function OnThisPage({
347
676
  window.removeEventListener("scroll", handleScroll);
348
677
  };
349
678
  }, [headings, location.pathname]);
350
- useEffect2(() => {
679
+ useEffect5(() => {
351
680
  if (!activeId || !listRef.current) return;
352
681
  const activeLink = listRef.current.querySelector(
353
682
  `a[href="#${activeId}"]`
354
683
  );
355
684
  if (activeLink) {
356
- const container = listRef.current.closest(
357
- ".boltdocs-on-this-page"
358
- );
685
+ const container = listRef.current.parentElement;
359
686
  if (!container) return;
360
687
  const linkRect = activeLink.getBoundingClientRect();
361
688
  const containerRect = container.getBoundingClientRect();
362
689
  const isVisible = linkRect.top >= containerRect.top && linkRect.bottom <= containerRect.bottom;
363
690
  if (!isVisible) {
364
691
  activeLink.scrollIntoView({
365
- behavior: "smooth",
692
+ behavior: "auto",
366
693
  block: "nearest"
367
694
  });
368
695
  }
@@ -373,13 +700,7 @@ function OnThisPage({
373
700
  e.preventDefault();
374
701
  const el = document.getElementById(id);
375
702
  if (el) {
376
- const offset = 80;
377
- const bodyRect = document.body.getBoundingClientRect().top;
378
- const elementRect = el.getBoundingClientRect().top;
379
- const elementPosition = elementRect - bodyRect;
380
- const offsetPosition = elementPosition - offset;
381
- window.scrollTo({
382
- top: offsetPosition,
703
+ el.scrollIntoView({
383
704
  behavior: "smooth"
384
705
  });
385
706
  setActiveId(id);
@@ -389,11 +710,11 @@ function OnThisPage({
389
710
  []
390
711
  );
391
712
  if (headings.length === 0) return null;
392
- return /* @__PURE__ */ jsxs4("nav", { className: "boltdocs-on-this-page", "aria-label": "Table of contents", children: [
393
- /* @__PURE__ */ jsx6("p", { className: "on-this-page-title", children: "On this page" }),
394
- /* @__PURE__ */ jsxs4("div", { className: "on-this-page-container", children: [
395
- /* @__PURE__ */ jsx6("div", { className: "toc-indicator", style: indicatorStyle }),
396
- /* @__PURE__ */ jsx6("ul", { className: "on-this-page-list", ref: listRef, children: headings.map((h) => /* @__PURE__ */ jsx6("li", { className: h.level === 3 ? "toc-indent" : "", children: /* @__PURE__ */ jsx6(
713
+ return /* @__PURE__ */ jsxs6("nav", { className: "boltdocs-on-this-page", "aria-label": "Table of contents", children: [
714
+ /* @__PURE__ */ jsx11("p", { className: "on-this-page-title", children: "On this page" }),
715
+ /* @__PURE__ */ jsx11("div", { className: "on-this-page-container", children: /* @__PURE__ */ jsxs6("div", { className: "on-this-page-list-container", children: [
716
+ /* @__PURE__ */ jsx11("div", { className: "toc-indicator", style: indicatorStyle }),
717
+ /* @__PURE__ */ jsx11("ul", { className: "on-this-page-list", ref: listRef, children: headings.map((h) => /* @__PURE__ */ jsx11("li", { className: h.level === 3 ? "toc-indent" : "", children: /* @__PURE__ */ jsx11(
397
718
  "a",
398
719
  {
399
720
  href: `#${h.id}`,
@@ -403,11 +724,11 @@ function OnThisPage({
403
724
  children: h.text
404
725
  }
405
726
  ) }, h.id)) })
406
- ] }),
407
- (editLink || communityHelp) && /* @__PURE__ */ jsxs4("div", { className: "toc-help", children: [
408
- /* @__PURE__ */ jsx6("p", { className: "toc-help-title", children: "Need help?" }),
409
- /* @__PURE__ */ jsxs4("ul", { className: "toc-help-links", children: [
410
- editLink && filePath && /* @__PURE__ */ jsx6("li", { children: /* @__PURE__ */ jsxs4(
727
+ ] }) }),
728
+ (editLink || communityHelp) && /* @__PURE__ */ jsxs6("div", { className: "toc-help", children: [
729
+ /* @__PURE__ */ jsx11("p", { className: "toc-help-title", children: "Need help?" }),
730
+ /* @__PURE__ */ jsxs6("ul", { className: "toc-help-links", children: [
731
+ editLink && filePath && /* @__PURE__ */ jsx11("li", { children: /* @__PURE__ */ jsxs6(
411
732
  "a",
412
733
  {
413
734
  href: editLink.replace(":path", filePath),
@@ -415,12 +736,12 @@ function OnThisPage({
415
736
  rel: "noopener noreferrer",
416
737
  className: "toc-help-link",
417
738
  children: [
418
- /* @__PURE__ */ jsx6(Pencil, { size: 16 }),
739
+ /* @__PURE__ */ jsx11(Pencil, { size: 16 }),
419
740
  "Edit this page"
420
741
  ]
421
742
  }
422
743
  ) }),
423
- communityHelp && /* @__PURE__ */ jsx6("li", { children: /* @__PURE__ */ jsxs4(
744
+ communityHelp && /* @__PURE__ */ jsx11("li", { children: /* @__PURE__ */ jsxs6(
424
745
  "a",
425
746
  {
426
747
  href: communityHelp,
@@ -428,7 +749,7 @@ function OnThisPage({
428
749
  rel: "noopener noreferrer",
429
750
  className: "toc-help-link",
430
751
  children: [
431
- /* @__PURE__ */ jsx6(CircleHelp, { size: 16 }),
752
+ /* @__PURE__ */ jsx11(CircleHelp, { size: 16 }),
432
753
  "Community help"
433
754
  ]
434
755
  }
@@ -439,11 +760,11 @@ function OnThisPage({
439
760
  }
440
761
 
441
762
  // src/client/theme/ui/Head/Head.tsx
442
- import { useEffect as useEffect3 } from "react";
443
- import { useLocation as useLocation3 } from "react-router-dom";
763
+ import { useEffect as useEffect6 } from "react";
764
+ import { useLocation as useLocation5 } from "react-router-dom";
444
765
  function Head({ siteTitle, siteDescription, routes }) {
445
- const location = useLocation3();
446
- useEffect3(() => {
766
+ const location = useLocation5();
767
+ useEffect6(() => {
447
768
  const currentRoute = routes.find((r) => r.path === location.pathname);
448
769
  const pageTitle = currentRoute?.title;
449
770
  const pageDescription = currentRoute?.description || siteDescription || "";
@@ -489,25 +810,25 @@ function setMetaTag(attr, key, content) {
489
810
  }
490
811
 
491
812
  // src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx
492
- import { useLocation as useLocation4 } from "react-router-dom";
813
+ import { useLocation as useLocation6 } from "react-router-dom";
493
814
  import { Home, ChevronRight as ChevronRight2 } from "lucide-react";
494
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
815
+ import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
495
816
  function Breadcrumbs({ routes, config }) {
496
- const location = useLocation4();
817
+ const location = useLocation6();
497
818
  if (config.themeConfig?.breadcrumbs === false) return null;
498
819
  if (location.pathname === "/") return null;
499
820
  const currentRoute = routes.find((r) => r.path === location.pathname);
500
821
  const groupRoute = currentRoute?.group ? routes.find((r) => r.group === currentRoute.group) : null;
501
- return /* @__PURE__ */ jsx7("nav", { className: "boltdocs-breadcrumbs", "aria-label": "Breadcrumb", children: /* @__PURE__ */ jsxs5("ol", { className: "boltdocs-breadcrumbs-list", children: [
502
- /* @__PURE__ */ jsxs5("li", { className: "boltdocs-breadcrumbs-item", children: [
503
- /* @__PURE__ */ jsx7(Link, { to: "/", className: "boltdocs-breadcrumbs-link", children: /* @__PURE__ */ jsx7(Home, { size: 14 }) }),
504
- /* @__PURE__ */ jsx7("span", { className: "boltdocs-breadcrumbs-separator", children: /* @__PURE__ */ jsx7(ChevronRight2, { size: 14 }) })
822
+ return /* @__PURE__ */ jsx12("nav", { className: "boltdocs-breadcrumbs", "aria-label": "Breadcrumb", children: /* @__PURE__ */ jsxs7("ol", { className: "boltdocs-breadcrumbs-list", children: [
823
+ /* @__PURE__ */ jsxs7("li", { className: "boltdocs-breadcrumbs-item", children: [
824
+ /* @__PURE__ */ jsx12(Link, { to: "/", className: "boltdocs-breadcrumbs-link", children: /* @__PURE__ */ jsx12(Home, { size: 14 }) }),
825
+ /* @__PURE__ */ jsx12("span", { className: "boltdocs-breadcrumbs-separator", children: /* @__PURE__ */ jsx12(ChevronRight2, { size: 14 }) })
505
826
  ] }),
506
- currentRoute?.groupTitle && /* @__PURE__ */ jsxs5("li", { className: "boltdocs-breadcrumbs-item", children: [
507
- groupRoute ? /* @__PURE__ */ jsx7(Link, { to: groupRoute.path, className: "boltdocs-breadcrumbs-link", children: currentRoute.groupTitle }) : /* @__PURE__ */ jsx7("span", { className: "boltdocs-breadcrumbs-text", children: currentRoute.groupTitle }),
508
- /* @__PURE__ */ jsx7("span", { className: "boltdocs-breadcrumbs-separator", children: /* @__PURE__ */ jsx7(ChevronRight2, { size: 14 }) })
827
+ currentRoute?.groupTitle && /* @__PURE__ */ jsxs7("li", { className: "boltdocs-breadcrumbs-item", children: [
828
+ groupRoute ? /* @__PURE__ */ jsx12(Link, { to: groupRoute.path, className: "boltdocs-breadcrumbs-link", children: currentRoute.groupTitle }) : /* @__PURE__ */ jsx12("span", { className: "boltdocs-breadcrumbs-text", children: currentRoute.groupTitle }),
829
+ /* @__PURE__ */ jsx12("span", { className: "boltdocs-breadcrumbs-separator", children: /* @__PURE__ */ jsx12(ChevronRight2, { size: 14 }) })
509
830
  ] }),
510
- currentRoute?.title && /* @__PURE__ */ jsx7("li", { className: "boltdocs-breadcrumbs-item", children: /* @__PURE__ */ jsx7(
831
+ currentRoute?.title && /* @__PURE__ */ jsx12("li", { className: "boltdocs-breadcrumbs-item", children: /* @__PURE__ */ jsx12(
511
832
  "span",
512
833
  {
513
834
  className: "boltdocs-breadcrumbs-text boltdocs-breadcrumbs-active",
@@ -519,16 +840,93 @@ function Breadcrumbs({ routes, config }) {
519
840
  }
520
841
 
521
842
  // src/client/theme/ui/BackgroundGradient/BackgroundGradient.tsx
522
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
843
+ import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
523
844
  function BackgroundGradient() {
524
- return /* @__PURE__ */ jsxs6("div", { className: "boltdocs-background-glow", children: [
525
- /* @__PURE__ */ jsx8("div", { className: "glow-shape glow-1" }),
526
- /* @__PURE__ */ jsx8("div", { className: "glow-shape glow-2" })
845
+ return /* @__PURE__ */ jsxs8("div", { className: "boltdocs-background-glow", children: [
846
+ /* @__PURE__ */ jsx13("div", { className: "glow-shape glow-1" }),
847
+ /* @__PURE__ */ jsx13("div", { className: "glow-shape glow-2" })
527
848
  ] });
528
849
  }
529
850
 
851
+ // src/client/theme/ui/ProgressBar/ProgressBar.tsx
852
+ import { useEffect as useEffect7, useState as useState7 } from "react";
853
+ import { jsx as jsx14 } from "react/jsx-runtime";
854
+ function ProgressBar() {
855
+ const [progress, setProgress] = useState7(0);
856
+ useEffect7(() => {
857
+ let container = null;
858
+ let timer;
859
+ const handleScroll = () => {
860
+ if (!container) return;
861
+ const { scrollTop, scrollHeight, clientHeight } = container;
862
+ if (scrollHeight <= clientHeight) {
863
+ setProgress(0);
864
+ return;
865
+ }
866
+ const scrollPercent = scrollTop / (scrollHeight - clientHeight) * 100;
867
+ setProgress(Math.min(100, Math.max(0, scrollPercent)));
868
+ };
869
+ const attachListener = () => {
870
+ container = document.querySelector(".boltdocs-content");
871
+ if (container) {
872
+ container.addEventListener("scroll", handleScroll);
873
+ handleScroll();
874
+ if (timer) clearInterval(timer);
875
+ return true;
876
+ }
877
+ return false;
878
+ };
879
+ if (!attachListener()) {
880
+ timer = setInterval(attachListener, 100);
881
+ }
882
+ return () => {
883
+ if (container) container.removeEventListener("scroll", handleScroll);
884
+ if (timer) clearInterval(timer);
885
+ };
886
+ }, []);
887
+ return /* @__PURE__ */ jsx14("div", { className: "boltdocs-progress-container", children: /* @__PURE__ */ jsx14(
888
+ "div",
889
+ {
890
+ className: "boltdocs-progress-bar",
891
+ style: { width: `${progress}%` }
892
+ }
893
+ ) });
894
+ }
895
+
896
+ // src/client/theme/ui/ErrorBoundary/ErrorBoundary.tsx
897
+ import { Component } from "react";
898
+ import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
899
+ var ErrorBoundary = class extends Component {
900
+ state = {
901
+ hasError: false
902
+ };
903
+ static getDerivedStateFromError(error) {
904
+ return { hasError: true, error };
905
+ }
906
+ componentDidCatch(error, errorInfo) {
907
+ console.error("Uncaught error in Boltdocs Layout:", error, errorInfo);
908
+ }
909
+ render() {
910
+ if (this.state.hasError) {
911
+ return this.props.fallback || /* @__PURE__ */ jsxs9("div", { className: "boltdocs-error-boundary", children: [
912
+ /* @__PURE__ */ jsx15("div", { className: "boltdocs-error-title", children: "Something went wrong" }),
913
+ /* @__PURE__ */ jsx15("p", { className: "boltdocs-error-message", children: this.state.error?.message || "An unexpected error occurred while rendering this page." }),
914
+ /* @__PURE__ */ jsx15(
915
+ "button",
916
+ {
917
+ className: "boltdocs-error-retry",
918
+ onClick: () => this.setState({ hasError: false }),
919
+ children: "Try again"
920
+ }
921
+ )
922
+ ] });
923
+ }
924
+ return this.props.children;
925
+ }
926
+ };
927
+
530
928
  // src/client/theme/ui/Layout/Layout.tsx
531
- import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
929
+ import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
532
930
  function ThemeLayout({
533
931
  config,
534
932
  routes,
@@ -542,10 +940,9 @@ function ThemeLayout({
542
940
  className = "",
543
941
  style
544
942
  }) {
545
- const [isSidebarOpen, setIsSidebarOpen] = useState4(true);
546
943
  const siteTitle = config.themeConfig?.title || "Boltdocs";
547
944
  const siteDescription = config.themeConfig?.description || "";
548
- const location = useLocation5();
945
+ const location = useLocation7();
549
946
  const currentIndex = routes.findIndex((r) => r.path === location.pathname);
550
947
  const currentRoute = routes[currentIndex];
551
948
  const currentLocale = config.i18n ? currentRoute?.locale || config.i18n.defaultLocale : void 0;
@@ -561,13 +958,14 @@ function ThemeLayout({
561
958
  const prevPage = localIndex > 0 ? filteredRoutes[localIndex - 1] : null;
562
959
  const nextPage = localIndex >= 0 && localIndex < filteredRoutes.length - 1 ? filteredRoutes[localIndex + 1] : null;
563
960
  const { preload } = usePreload();
564
- React4.useEffect(() => {
961
+ React7.useEffect(() => {
565
962
  if (prevPage?.path) preload(prevPage.path);
566
963
  if (nextPage?.path) preload(nextPage.path);
567
964
  }, [prevPage, nextPage, preload]);
568
- return /* @__PURE__ */ jsxs7("div", { className: `boltdocs-layout ${className}`, style, children: [
569
- background !== void 0 ? background : /* @__PURE__ */ jsx9(BackgroundGradient, {}),
570
- head !== void 0 ? head : /* @__PURE__ */ jsx9(
965
+ return /* @__PURE__ */ jsxs10("div", { className: `boltdocs-layout ${className}`, style, children: [
966
+ /* @__PURE__ */ jsx16(ProgressBar, {}),
967
+ background !== void 0 ? background : /* @__PURE__ */ jsx16(BackgroundGradient, {}),
968
+ head !== void 0 ? head : /* @__PURE__ */ jsx16(
571
969
  Head,
572
970
  {
573
971
  siteTitle,
@@ -575,7 +973,7 @@ function ThemeLayout({
575
973
  routes
576
974
  }
577
975
  ),
578
- navbar !== void 0 ? navbar : /* @__PURE__ */ jsx9(
976
+ navbar !== void 0 ? navbar : /* @__PURE__ */ jsx16(
579
977
  Navbar,
580
978
  {
581
979
  config,
@@ -585,90 +983,76 @@ function ThemeLayout({
585
983
  currentVersion
586
984
  }
587
985
  ),
588
- /* @__PURE__ */ jsxs7(
589
- "div",
590
- {
591
- className: `boltdocs-main-container ${!isSidebarOpen ? "sidebar-collapsed" : ""}`,
592
- children: [
593
- sidebar !== void 0 ? sidebar : /* @__PURE__ */ jsx9(
594
- Sidebar,
986
+ /* @__PURE__ */ jsxs10("div", { className: "boltdocs-main-container", children: [
987
+ sidebar !== void 0 ? sidebar : /* @__PURE__ */ jsx16(Sidebar, { routes: filteredRoutes, config }),
988
+ /* @__PURE__ */ jsxs10("main", { className: "boltdocs-content", children: [
989
+ breadcrumbs !== void 0 ? breadcrumbs : /* @__PURE__ */ jsx16(Breadcrumbs, { routes: filteredRoutes, config }),
990
+ /* @__PURE__ */ jsx16("div", { className: "boltdocs-page", children: /* @__PURE__ */ jsx16(ErrorBoundary, { children }) }),
991
+ (prevPage || nextPage) && /* @__PURE__ */ jsxs10("nav", { className: "page-nav", "aria-label": "Pagination", children: [
992
+ prevPage ? /* @__PURE__ */ jsxs10(
993
+ Link,
595
994
  {
596
- routes: filteredRoutes,
597
- config,
598
- isCollapsed: !isSidebarOpen,
599
- onToggle: () => setIsSidebarOpen(!isSidebarOpen)
995
+ to: prevPage.path || "/",
996
+ className: "page-nav-link page-nav-link--prev",
997
+ children: [
998
+ /* @__PURE__ */ jsxs10("div", { className: "page-nav-info", children: [
999
+ /* @__PURE__ */ jsx16("span", { className: "page-nav-label", children: "Previous" }),
1000
+ /* @__PURE__ */ jsx16("span", { className: "page-nav-title", children: prevPage.title })
1001
+ ] }),
1002
+ /* @__PURE__ */ jsx16(ChevronLeft, { className: "page-nav-arrow", size: 16 })
1003
+ ]
600
1004
  }
601
- ),
602
- /* @__PURE__ */ jsxs7("main", { className: "boltdocs-content", children: [
603
- breadcrumbs !== void 0 ? breadcrumbs : /* @__PURE__ */ jsx9(Breadcrumbs, { routes: filteredRoutes, config }),
604
- /* @__PURE__ */ jsx9("div", { className: "boltdocs-page", children }),
605
- (prevPage || nextPage) && /* @__PURE__ */ jsxs7("nav", { className: "page-nav", "aria-label": "Pagination", children: [
606
- prevPage ? /* @__PURE__ */ jsxs7(
607
- Link,
608
- {
609
- to: prevPage.path || "/",
610
- className: "page-nav-link page-nav-link--prev",
611
- children: [
612
- /* @__PURE__ */ jsxs7("div", { className: "page-nav-info", children: [
613
- /* @__PURE__ */ jsx9("span", { className: "page-nav-label", children: "Previous" }),
614
- /* @__PURE__ */ jsx9("span", { className: "page-nav-title", children: prevPage.title })
615
- ] }),
616
- /* @__PURE__ */ jsx9(ChevronLeft2, { className: "page-nav-arrow", size: 16 })
617
- ]
618
- }
619
- ) : /* @__PURE__ */ jsx9("span", {}),
620
- nextPage ? /* @__PURE__ */ jsxs7(
621
- Link,
622
- {
623
- to: nextPage.path || "/",
624
- className: "page-nav-link page-nav-link--next",
625
- children: [
626
- /* @__PURE__ */ jsxs7("div", { className: "page-nav-info", children: [
627
- /* @__PURE__ */ jsx9("span", { className: "page-nav-label", children: "Next" }),
628
- /* @__PURE__ */ jsx9("span", { className: "page-nav-title", children: nextPage.title })
629
- ] }),
630
- /* @__PURE__ */ jsx9(ChevronRight3, { className: "page-nav-arrow", size: 16 })
631
- ]
632
- }
633
- ) : /* @__PURE__ */ jsx9("span", {})
634
- ] })
635
- ] }),
636
- toc !== void 0 ? toc : /* @__PURE__ */ jsx9(
637
- OnThisPage,
1005
+ ) : /* @__PURE__ */ jsx16("span", {}),
1006
+ nextPage ? /* @__PURE__ */ jsxs10(
1007
+ Link,
638
1008
  {
639
- headings: routes[currentIndex]?.headings,
640
- editLink: config.themeConfig?.editLink,
641
- communityHelp: config.themeConfig?.communityHelp,
642
- filePath: routes[currentIndex]?.filePath
1009
+ to: nextPage.path || "/",
1010
+ className: "page-nav-link page-nav-link--next",
1011
+ children: [
1012
+ /* @__PURE__ */ jsxs10("div", { className: "page-nav-info", children: [
1013
+ /* @__PURE__ */ jsx16("span", { className: "page-nav-label", children: "Next" }),
1014
+ /* @__PURE__ */ jsx16("span", { className: "page-nav-title", children: nextPage.title })
1015
+ ] }),
1016
+ /* @__PURE__ */ jsx16(ChevronRight3, { className: "page-nav-arrow", size: 16 })
1017
+ ]
643
1018
  }
644
- )
645
- ]
646
- }
647
- )
1019
+ ) : /* @__PURE__ */ jsx16("span", {})
1020
+ ] })
1021
+ ] }),
1022
+ toc !== void 0 ? toc : /* @__PURE__ */ jsx16(
1023
+ OnThisPage,
1024
+ {
1025
+ headings: routes[currentIndex]?.headings,
1026
+ editLink: config.themeConfig?.editLink,
1027
+ communityHelp: config.themeConfig?.communityHelp,
1028
+ filePath: routes[currentIndex]?.filePath
1029
+ }
1030
+ )
1031
+ ] })
648
1032
  ] });
649
1033
  }
650
1034
 
651
1035
  // src/client/theme/ui/NotFound/NotFound.tsx
652
1036
  import { ArrowLeft } from "lucide-react";
653
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1037
+ import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
654
1038
  function NotFound() {
655
- return /* @__PURE__ */ jsx10("div", { className: "boltdocs-not-found", children: /* @__PURE__ */ jsxs8("div", { className: "not-found-content", children: [
656
- /* @__PURE__ */ jsx10("span", { className: "not-found-code", children: "404" }),
657
- /* @__PURE__ */ jsx10("h1", { className: "not-found-title", children: "Page Not Found" }),
658
- /* @__PURE__ */ jsx10("p", { className: "not-found-text", children: "The page you're looking for doesn't exist or has been moved." }),
659
- /* @__PURE__ */ jsxs8(Link, { to: "/", className: "not-found-link", children: [
660
- /* @__PURE__ */ jsx10(ArrowLeft, { size: 16 }),
1039
+ return /* @__PURE__ */ jsx17("div", { className: "boltdocs-not-found", children: /* @__PURE__ */ jsxs11("div", { className: "not-found-content", children: [
1040
+ /* @__PURE__ */ jsx17("span", { className: "not-found-code", children: "404" }),
1041
+ /* @__PURE__ */ jsx17("h1", { className: "not-found-title", children: "Page Not Found" }),
1042
+ /* @__PURE__ */ jsx17("p", { className: "not-found-text", children: "The page you're looking for doesn't exist or has been moved." }),
1043
+ /* @__PURE__ */ jsxs11(Link, { to: "/", className: "not-found-link", children: [
1044
+ /* @__PURE__ */ jsx17(ArrowLeft, { size: 16 }),
661
1045
  " Go to Home"
662
1046
  ] })
663
1047
  ] }) });
664
1048
  }
665
1049
 
666
1050
  // src/client/theme/ui/Loading/Loading.tsx
667
- import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1051
+ import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
668
1052
  function Loading() {
669
- return /* @__PURE__ */ jsxs9("div", { className: "boltdocs-loading", children: [
670
- /* @__PURE__ */ jsx11("div", { className: "loading-spinner" }),
671
- /* @__PURE__ */ jsx11("p", { className: "loading-text", children: "Loading..." })
1053
+ return /* @__PURE__ */ jsxs12("div", { className: "boltdocs-loading", children: [
1054
+ /* @__PURE__ */ jsx18("div", { className: "loading-spinner" }),
1055
+ /* @__PURE__ */ jsx18("p", { className: "loading-text", children: "Loading..." })
672
1056
  ] });
673
1057
  }
674
1058
 
@@ -684,34 +1068,34 @@ import {
684
1068
  import { Link as LucideLink } from "lucide-react";
685
1069
 
686
1070
  // src/client/theme/components/CodeBlock/CodeBlock.tsx
687
- import { useState as useState5, useRef as useRef2, useCallback as useCallback3 } from "react";
1071
+ import { useState as useState9, useRef as useRef4, useCallback as useCallback3 } from "react";
688
1072
  import { Copy, Check } from "lucide-react";
689
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1073
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
690
1074
  function CodeBlock({ children, ...props }) {
691
- const [copied, setCopied] = useState5(false);
692
- const preRef = useRef2(null);
1075
+ const [copied, setCopied] = useState9(false);
1076
+ const preRef = useRef4(null);
693
1077
  const handleCopy = useCallback3(async () => {
694
1078
  const code = preRef.current?.textContent || "";
695
1079
  copyToClipboard(code);
696
1080
  setCopied(true);
697
1081
  setTimeout(() => setCopied(false), 2e3);
698
1082
  }, []);
699
- return /* @__PURE__ */ jsxs10("div", { className: "code-block-wrapper", children: [
700
- /* @__PURE__ */ jsx12(
1083
+ return /* @__PURE__ */ jsxs13("div", { className: "code-block-wrapper", children: [
1084
+ /* @__PURE__ */ jsx19(
701
1085
  "button",
702
1086
  {
703
1087
  className: `code-block-copy ${copied ? "copied" : ""}`,
704
1088
  onClick: handleCopy,
705
1089
  "aria-label": "Copy code",
706
- children: copied ? /* @__PURE__ */ jsx12(Check, { size: 16 }) : /* @__PURE__ */ jsx12(Copy, { size: 16 })
1090
+ children: copied ? /* @__PURE__ */ jsx19(Check, { size: 16 }) : /* @__PURE__ */ jsx19(Copy, { size: 16 })
707
1091
  }
708
1092
  ),
709
- /* @__PURE__ */ jsx12("pre", { ref: preRef, ...props, children })
1093
+ /* @__PURE__ */ jsx19("pre", { ref: preRef, ...props, children })
710
1094
  ] });
711
1095
  }
712
1096
 
713
1097
  // src/client/app/index.tsx
714
- import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
1098
+ import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
715
1099
  var ConfigContext = createContext2(null);
716
1100
  function useConfig() {
717
1101
  return useContext2(ConfigContext);
@@ -730,71 +1114,72 @@ var Heading = ({
730
1114
  children
731
1115
  }) => {
732
1116
  const Tag = `h${level}`;
733
- return /* @__PURE__ */ jsxs11(Tag, { id, className: "boltdocs-heading", children: [
1117
+ return /* @__PURE__ */ jsxs14(Tag, { id, className: "boltdocs-heading", children: [
734
1118
  children,
735
- id && /* @__PURE__ */ jsx13("a", { href: `#${id}`, className: "header-anchor", "aria-label": "Anchor", children: /* @__PURE__ */ jsx13(LucideLink, { size: 16 }) })
1119
+ id && /* @__PURE__ */ jsx20("a", { href: `#${id}`, className: "header-anchor", "aria-label": "Anchor", children: /* @__PURE__ */ jsx20(LucideLink, { size: 16 }) })
736
1120
  ] });
737
1121
  };
738
1122
  var mdxComponents = {
739
- h1: (props) => /* @__PURE__ */ jsx13(Heading, { level: 1, ...props }),
740
- h2: (props) => /* @__PURE__ */ jsx13(Heading, { level: 2, ...props }),
741
- h3: (props) => /* @__PURE__ */ jsx13(Heading, { level: 3, ...props }),
742
- h4: (props) => /* @__PURE__ */ jsx13(Heading, { level: 4, ...props }),
743
- h5: (props) => /* @__PURE__ */ jsx13(Heading, { level: 5, ...props }),
744
- h6: (props) => /* @__PURE__ */ jsx13(Heading, { level: 6, ...props }),
745
- pre: (props) => /* @__PURE__ */ jsx13(CodeBlock, { ...props, children: props.children }),
746
- video: (props) => /* @__PURE__ */ jsx13(Suspense, { fallback: /* @__PURE__ */ jsx13("div", { className: "video-skeleton" }), children: /* @__PURE__ */ jsx13(Video, { ...props }) }),
747
- PackageManagerTabs: (props) => /* @__PURE__ */ jsx13(Suspense, { fallback: /* @__PURE__ */ jsx13("div", { className: "pkg-tabs-skeleton" }), children: /* @__PURE__ */ jsx13(PackageManagerTabs, { ...props }) })
1123
+ h1: (props) => /* @__PURE__ */ jsx20(Heading, { level: 1, ...props }),
1124
+ h2: (props) => /* @__PURE__ */ jsx20(Heading, { level: 2, ...props }),
1125
+ h3: (props) => /* @__PURE__ */ jsx20(Heading, { level: 3, ...props }),
1126
+ h4: (props) => /* @__PURE__ */ jsx20(Heading, { level: 4, ...props }),
1127
+ h5: (props) => /* @__PURE__ */ jsx20(Heading, { level: 5, ...props }),
1128
+ h6: (props) => /* @__PURE__ */ jsx20(Heading, { level: 6, ...props }),
1129
+ pre: (props) => /* @__PURE__ */ jsx20(CodeBlock, { ...props, children: props.children }),
1130
+ video: (props) => /* @__PURE__ */ jsx20(Suspense, { fallback: /* @__PURE__ */ jsx20("div", { className: "video-skeleton" }), children: /* @__PURE__ */ jsx20(Video, { ...props }) }),
1131
+ PackageManagerTabs: (props) => /* @__PURE__ */ jsx20(Suspense, { fallback: /* @__PURE__ */ jsx20("div", { className: "pkg-tabs-skeleton" }), children: /* @__PURE__ */ jsx20(PackageManagerTabs, { ...props }) })
748
1132
  };
749
1133
  function AppShell({
750
1134
  initialRoutes,
751
1135
  initialConfig,
1136
+ docsDirName,
752
1137
  modules,
753
1138
  hot,
754
1139
  homePage: HomePage,
755
1140
  components: customComponents = {}
756
1141
  }) {
757
- const [routesInfo, setRoutesInfo] = useState6(initialRoutes);
758
- const [config] = useState6(initialConfig);
1142
+ const [routesInfo, setRoutesInfo] = useState10(initialRoutes);
1143
+ const [config] = useState10(initialConfig);
759
1144
  const resolveRoutes = (infos) => {
760
1145
  return infos.filter(
761
1146
  (route) => !(HomePage && (route.path === "/" || route.path === ""))
762
1147
  ).map((route) => {
763
1148
  const loaderKey = Object.keys(modules).find(
764
- (k) => k.endsWith("/" + route.filePath)
1149
+ (k) => k === `/${docsDirName}/${route.filePath}`
765
1150
  );
766
1151
  const loader = loaderKey ? modules[loaderKey] : null;
767
1152
  return {
768
1153
  ...route,
769
- Component: React6.lazy(() => {
1154
+ Component: React9.lazy(() => {
770
1155
  if (!loader)
771
- return Promise.resolve({ default: () => /* @__PURE__ */ jsx13(NotFound, {}) });
1156
+ return Promise.resolve({ default: () => /* @__PURE__ */ jsx20(NotFound, {}) });
772
1157
  return loader();
773
1158
  })
774
1159
  };
775
1160
  });
776
1161
  };
777
- const [resolvedRoutes, setResolvedRoutes] = useState6(
1162
+ const [resolvedRoutes, setResolvedRoutes] = useState10(
778
1163
  () => resolveRoutes(initialRoutes)
779
1164
  );
780
- useEffect4(() => {
1165
+ useEffect8(() => {
781
1166
  if (hot) {
782
1167
  hot.on("boltdocs:routes-update", (newRoutes) => {
783
1168
  setRoutesInfo(newRoutes);
784
1169
  });
785
1170
  }
786
1171
  }, [hot]);
787
- useEffect4(() => {
1172
+ useEffect8(() => {
788
1173
  setResolvedRoutes(resolveRoutes(routesInfo));
789
- }, [routesInfo, modules]);
790
- return /* @__PURE__ */ jsx13(ConfigContext.Provider, { value: config, children: /* @__PURE__ */ jsxs11(PreloadProvider, { routes: routesInfo, modules, children: [
791
- /* @__PURE__ */ jsx13(ScrollHandler, {}),
792
- /* @__PURE__ */ jsxs11(Routes, { children: [
793
- HomePage && /* @__PURE__ */ jsx13(
1174
+ }, [routesInfo, modules, docsDirName]);
1175
+ return /* @__PURE__ */ jsx20(ConfigContext.Provider, { value: config, children: /* @__PURE__ */ jsxs14(PreloadProvider, { routes: routesInfo, modules, children: [
1176
+ /* @__PURE__ */ jsx20(ScrollHandler, {}),
1177
+ /* @__PURE__ */ jsxs14(Routes, { children: [
1178
+ HomePage && /* @__PURE__ */ jsx20(
794
1179
  Route,
795
1180
  {
796
1181
  path: "/",
797
- element: /* @__PURE__ */ jsx13(
1182
+ element: /* @__PURE__ */ jsx20(
798
1183
  ThemeLayout,
799
1184
  {
800
1185
  config,
@@ -803,20 +1188,20 @@ function AppShell({
803
1188
  toc: null,
804
1189
  breadcrumbs: null,
805
1190
  ...config.themeConfig?.layoutProps,
806
- children: /* @__PURE__ */ jsx13(HomePage, {})
1191
+ children: /* @__PURE__ */ jsx20(HomePage, {})
807
1192
  }
808
1193
  )
809
1194
  }
810
1195
  ),
811
- /* @__PURE__ */ jsx13(
1196
+ /* @__PURE__ */ jsx20(
812
1197
  Route,
813
1198
  {
814
- element: /* @__PURE__ */ jsx13(DocsLayout, { config, routes: routesInfo }),
815
- children: resolvedRoutes.map((route) => /* @__PURE__ */ jsx13(
1199
+ element: /* @__PURE__ */ jsx20(DocsLayout, { config, routes: routesInfo }),
1200
+ children: resolvedRoutes.map((route) => /* @__PURE__ */ jsx20(
816
1201
  Route,
817
1202
  {
818
1203
  path: route.path === "" ? "/" : route.path,
819
- element: /* @__PURE__ */ jsx13(React6.Suspense, { fallback: /* @__PURE__ */ jsx13(Loading, {}), children: /* @__PURE__ */ jsx13(
1204
+ element: /* @__PURE__ */ jsx20(React9.Suspense, { fallback: /* @__PURE__ */ jsx20(Loading, {}), children: /* @__PURE__ */ jsx20(
820
1205
  MdxPage,
821
1206
  {
822
1207
  Component: route.Component,
@@ -829,17 +1214,17 @@ function AppShell({
829
1214
  },
830
1215
  "docs-layout"
831
1216
  ),
832
- /* @__PURE__ */ jsx13(
1217
+ /* @__PURE__ */ jsx20(
833
1218
  Route,
834
1219
  {
835
1220
  path: "*",
836
- element: /* @__PURE__ */ jsx13(
1221
+ element: /* @__PURE__ */ jsx20(
837
1222
  ThemeLayout,
838
1223
  {
839
1224
  config,
840
1225
  routes: routesInfo,
841
1226
  ...config.themeConfig?.layoutProps,
842
- children: /* @__PURE__ */ jsx13(NotFound, {})
1227
+ children: /* @__PURE__ */ jsx20(NotFound, {})
843
1228
  }
844
1229
  )
845
1230
  }
@@ -848,25 +1233,27 @@ function AppShell({
848
1233
  ] }) });
849
1234
  }
850
1235
  function ScrollHandler() {
851
- const { pathname, hash } = useLocation6();
1236
+ const { pathname, hash } = useLocation8();
852
1237
  useLayoutEffect(() => {
1238
+ const container = document.querySelector(".boltdocs-content");
1239
+ if (!container) return;
853
1240
  if (hash) {
854
1241
  const id = hash.replace("#", "");
855
1242
  const element = document.getElementById(id);
856
1243
  if (element) {
857
1244
  const offset = 80;
858
- const bodyRect = document.body.getBoundingClientRect().top;
1245
+ const containerRect = container.getBoundingClientRect().top;
859
1246
  const elementRect = element.getBoundingClientRect().top;
860
- const elementPosition = elementRect - bodyRect;
861
- const offsetPosition = elementPosition - offset;
862
- window.scrollTo({
1247
+ const elementPosition = elementRect - containerRect;
1248
+ const offsetPosition = elementPosition - offset + container.scrollTop;
1249
+ container.scrollTo({
863
1250
  top: offsetPosition,
864
1251
  behavior: "smooth"
865
1252
  });
866
1253
  return;
867
1254
  }
868
1255
  }
869
- window.scrollTo(0, 0);
1256
+ container.scrollTo(0, 0);
870
1257
  }, [pathname, hash]);
871
1258
  return null;
872
1259
  }
@@ -874,36 +1261,37 @@ function DocsLayout({
874
1261
  config,
875
1262
  routes
876
1263
  }) {
877
- return /* @__PURE__ */ jsx13(
1264
+ return /* @__PURE__ */ jsx20(
878
1265
  ThemeLayout,
879
1266
  {
880
1267
  config,
881
1268
  routes,
882
1269
  ...config.themeConfig?.layoutProps,
883
- children: /* @__PURE__ */ jsx13(Outlet, {})
1270
+ children: /* @__PURE__ */ jsx20(Outlet, {})
884
1271
  }
885
1272
  );
886
1273
  }
887
1274
  function MdxPage({
888
- Component,
1275
+ Component: Component2,
889
1276
  customComponents = {}
890
1277
  }) {
891
1278
  const allComponents = { ...mdxComponents, ...customComponents };
892
- return /* @__PURE__ */ jsx13(MDXProvider, { components: allComponents, children: /* @__PURE__ */ jsx13(Component, {}) });
1279
+ return /* @__PURE__ */ jsx20(MDXProvider, { components: allComponents, children: /* @__PURE__ */ jsx20(Component2, {}) });
893
1280
  }
894
1281
  function createBoltdocsApp(options) {
895
- const { target, routes, config, modules, hot, homePage } = options;
1282
+ const { target, routes, docsDirName, config, modules, hot, homePage } = options;
896
1283
  const container = document.querySelector(target);
897
1284
  if (!container) {
898
1285
  throw new Error(
899
1286
  `[boltdocs] Mount target "${target}" not found in document.`
900
1287
  );
901
1288
  }
902
- const app = /* @__PURE__ */ jsx13(React6.StrictMode, { children: /* @__PURE__ */ jsx13(BrowserRouter, { children: /* @__PURE__ */ jsx13(
1289
+ const app = /* @__PURE__ */ jsx20(React9.StrictMode, { children: /* @__PURE__ */ jsx20(BrowserRouter, { children: /* @__PURE__ */ jsx20(
903
1290
  AppShell,
904
1291
  {
905
1292
  initialRoutes: routes,
906
1293
  initialConfig: config,
1294
+ docsDirName,
907
1295
  modules,
908
1296
  hot,
909
1297
  homePage,
@@ -915,9 +1303,9 @@ function createBoltdocsApp(options) {
915
1303
  }
916
1304
 
917
1305
  // src/client/theme/ui/Link/LinkPreview.tsx
918
- import { useEffect as useEffect5, useState as useState7, useRef as useRef3 } from "react";
1306
+ import { useEffect as useEffect9, useState as useState11, useRef as useRef5 } from "react";
919
1307
  import { createPortal } from "react-dom";
920
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1308
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
921
1309
  function LinkPreview({
922
1310
  isVisible,
923
1311
  title,
@@ -925,30 +1313,25 @@ function LinkPreview({
925
1313
  x,
926
1314
  y
927
1315
  }) {
928
- const [mounted, setMounted] = useState7(false);
929
- const ref = useRef3(null);
930
- const [position, setPosition] = useState7({ top: 0, left: 0 });
931
- useEffect5(() => {
932
- setMounted(true);
933
- }, []);
934
- useEffect5(() => {
935
- if (isVisible && ref.current) {
1316
+ const ref = useRef5(null);
1317
+ const [position, setPosition] = useState11({ top: 0, left: 0 });
1318
+ useEffect9(() => {
1319
+ if (ref.current) {
936
1320
  const rect = ref.current.getBoundingClientRect();
937
- const padding = 15;
1321
+ const padding = 12;
938
1322
  let top = y + padding;
939
1323
  let left = x + padding;
940
- if (left + rect.width > window.innerWidth) {
1324
+ if (left + rect.width > window.innerWidth - 20) {
941
1325
  left = x - rect.width - padding;
942
1326
  }
943
- if (top + rect.height > window.innerHeight) {
1327
+ if (top + rect.height > window.innerHeight - 20) {
944
1328
  top = y - rect.height - padding;
945
1329
  }
946
1330
  setPosition({ top, left });
947
1331
  }
948
- }, [isVisible, x, y]);
949
- if (!mounted) return null;
1332
+ }, [x, y, isVisible]);
950
1333
  return createPortal(
951
- /* @__PURE__ */ jsxs12(
1334
+ /* @__PURE__ */ jsx21(
952
1335
  "div",
953
1336
  {
954
1337
  ref,
@@ -957,10 +1340,10 @@ function LinkPreview({
957
1340
  top: position.top,
958
1341
  left: position.left
959
1342
  },
960
- children: [
961
- /* @__PURE__ */ jsx14("span", { className: "boltdocs-link-preview-title", children: title }),
962
- summary && /* @__PURE__ */ jsx14("p", { className: "boltdocs-link-preview-summary", children: summary })
963
- ]
1343
+ children: /* @__PURE__ */ jsxs15("div", { className: "boltdocs-link-preview-content", children: [
1344
+ /* @__PURE__ */ jsx21("span", { className: "boltdocs-link-preview-title", children: title }),
1345
+ summary && /* @__PURE__ */ jsx21("p", { className: "boltdocs-link-preview-summary", children: summary })
1346
+ ] })
964
1347
  }
965
1348
  ),
966
1349
  document.body
@@ -968,9 +1351,9 @@ function LinkPreview({
968
1351
  }
969
1352
 
970
1353
  // src/client/theme/ui/Link/Link.tsx
971
- import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
1354
+ import { Fragment, jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
972
1355
  function useLocalizedTo(to) {
973
- const location = useLocation7();
1356
+ const location = useLocation9();
974
1357
  const config = useConfig();
975
1358
  if (!config || typeof to !== "string") return to;
976
1359
  if (!config.i18n && !config.versions) return to;
@@ -1024,7 +1407,7 @@ function useLocalizedTo(to) {
1024
1407
  }
1025
1408
  return finalPath === basePath ? basePath : finalPath;
1026
1409
  }
1027
- var Link = React7.forwardRef(
1410
+ var Link = React10.forwardRef(
1028
1411
  (props, ref) => {
1029
1412
  const {
1030
1413
  boltdocsPrefetch = "hover",
@@ -1040,9 +1423,9 @@ var Link = React7.forwardRef(
1040
1423
  const localizedTo = useLocalizedTo(to);
1041
1424
  const { preload, routes } = usePreload();
1042
1425
  const config = useConfig();
1043
- const navigate = useNavigate();
1426
+ const navigate = useNavigate3();
1044
1427
  const shouldShowPreview = boltdocsPreview && config?.themeConfig?.linkPreview !== false;
1045
- const [preview, setPreview] = React7.useState({ visible: false, x: 0, y: 0, title: "" });
1428
+ const [preview, setPreview] = React10.useState({ visible: false, x: 0, y: 0, title: "" });
1046
1429
  const handleMouseEnter = (e) => {
1047
1430
  onMouseEnter?.(e);
1048
1431
  if (boltdocsPrefetch === "hover" && typeof localizedTo === "string" && localizedTo.startsWith("/")) {
@@ -1091,13 +1474,13 @@ var Link = React7.forwardRef(
1091
1474
  }
1092
1475
  if (typeof localizedTo === "string" && !localizedTo.startsWith("http")) {
1093
1476
  e.preventDefault();
1094
- React7.startTransition(() => {
1477
+ React10.startTransition(() => {
1095
1478
  navigate(localizedTo);
1096
1479
  });
1097
1480
  }
1098
1481
  };
1099
- return /* @__PURE__ */ jsxs13(Fragment2, { children: [
1100
- /* @__PURE__ */ jsx15(
1482
+ return /* @__PURE__ */ jsxs16(Fragment, { children: [
1483
+ /* @__PURE__ */ jsx22(
1101
1484
  RouterLink,
1102
1485
  {
1103
1486
  ref,
@@ -1111,7 +1494,7 @@ var Link = React7.forwardRef(
1111
1494
  ...rest
1112
1495
  }
1113
1496
  ),
1114
- shouldShowPreview && /* @__PURE__ */ jsx15(
1497
+ preview.visible && shouldShowPreview && /* @__PURE__ */ jsx22(
1115
1498
  LinkPreview,
1116
1499
  {
1117
1500
  isVisible: preview.visible,
@@ -1125,7 +1508,7 @@ var Link = React7.forwardRef(
1125
1508
  }
1126
1509
  );
1127
1510
  Link.displayName = "Link";
1128
- var NavLink = React7.forwardRef(
1511
+ var NavLink = React10.forwardRef(
1129
1512
  (props, ref) => {
1130
1513
  const {
1131
1514
  boltdocsPrefetch = "hover",
@@ -1141,9 +1524,9 @@ var NavLink = React7.forwardRef(
1141
1524
  const localizedTo = useLocalizedTo(to);
1142
1525
  const { preload, routes } = usePreload();
1143
1526
  const config = useConfig();
1144
- const navigate = useNavigate();
1527
+ const navigate = useNavigate3();
1145
1528
  const shouldShowPreview = boltdocsPreview && config?.themeConfig?.linkPreview !== false;
1146
- const [preview, setPreview] = React7.useState({ visible: false, x: 0, y: 0, title: "" });
1529
+ const [preview, setPreview] = React10.useState({ visible: false, x: 0, y: 0, title: "" });
1147
1530
  const handleMouseEnter = (e) => {
1148
1531
  onMouseEnter?.(e);
1149
1532
  if (boltdocsPrefetch === "hover" && typeof localizedTo === "string" && localizedTo.startsWith("/")) {
@@ -1187,330 +1570,123 @@ var NavLink = React7.forwardRef(
1187
1570
  const handleClick = (e) => {
1188
1571
  onClick?.(e);
1189
1572
  setPreview((prev) => ({ ...prev, visible: false }));
1190
- if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {
1191
- return;
1192
- }
1193
- if (typeof localizedTo === "string" && !localizedTo.startsWith("http")) {
1194
- e.preventDefault();
1195
- React7.startTransition(() => {
1196
- navigate(localizedTo);
1197
- });
1198
- }
1199
- };
1200
- return /* @__PURE__ */ jsxs13(Fragment2, { children: [
1201
- /* @__PURE__ */ jsx15(
1202
- RouterNavLink,
1203
- {
1204
- ref,
1205
- to: localizedTo,
1206
- onMouseEnter: handleMouseEnter,
1207
- onMouseMove: handleMouseMove,
1208
- onMouseLeave: handleMouseLeave,
1209
- onFocus: handleFocus,
1210
- onBlur: handleBlur,
1211
- onClick: handleClick,
1212
- ...rest
1213
- }
1214
- ),
1215
- shouldShowPreview && /* @__PURE__ */ jsx15(
1216
- LinkPreview,
1217
- {
1218
- isVisible: preview.visible,
1219
- title: preview.title,
1220
- summary: preview.summary,
1221
- x: preview.x,
1222
- y: preview.y
1223
- }
1224
- )
1225
- ] });
1226
- }
1227
- );
1228
- NavLink.displayName = "NavLink";
1229
-
1230
- // src/client/theme/ui/Navbar/Navbar.tsx
1231
- import { ChevronDown as ChevronDown3 } from "lucide-react";
1232
-
1233
- // src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx
1234
- import { useState as useState8, useRef as useRef4, useEffect as useEffect6 } from "react";
1235
- import { Globe, ChevronDown } from "lucide-react";
1236
- import { useNavigate as useNavigate2, useLocation as useLocation8 } from "react-router-dom";
1237
- import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
1238
- function getBaseFilePath(filePath, version, locale) {
1239
- let path = filePath;
1240
- if (version && (path === version || path.startsWith(version + "/"))) {
1241
- path = path === version ? "index.md" : path.slice(version.length + 1);
1242
- }
1243
- if (locale && (path === locale || path.startsWith(locale + "/"))) {
1244
- path = path === locale ? "index.md" : path.slice(locale.length + 1);
1245
- }
1246
- return path;
1247
- }
1248
- function LanguageSwitcher({
1249
- i18n,
1250
- currentLocale,
1251
- allRoutes
1252
- }) {
1253
- const [isOpen, setIsOpen] = useState8(false);
1254
- const dropdownRef = useRef4(null);
1255
- const navigate = useNavigate2();
1256
- const location = useLocation8();
1257
- useEffect6(() => {
1258
- function handleClickOutside(event) {
1259
- if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
1260
- setIsOpen(false);
1261
- }
1262
- }
1263
- document.addEventListener("mousedown", handleClickOutside);
1264
- return () => document.removeEventListener("mousedown", handleClickOutside);
1265
- }, []);
1266
- const handleSelect = (locale) => {
1267
- setIsOpen(false);
1268
- if (locale === currentLocale) return;
1269
- const currentRoute = allRoutes.find((r) => r.path === location.pathname);
1270
- let targetPath = "/";
1271
- if (currentRoute) {
1272
- const baseFile = getBaseFilePath(
1273
- currentRoute.filePath,
1274
- currentRoute.version,
1275
- currentRoute.locale
1276
- );
1277
- const targetRoute = allRoutes.find(
1278
- (r) => getBaseFilePath(r.filePath, r.version, r.locale) === baseFile && (r.locale || i18n.defaultLocale) === locale && r.version === currentRoute.version
1279
- );
1280
- if (targetRoute) {
1281
- targetPath = targetRoute.path;
1282
- } else {
1283
- const defaultIndexRoute = allRoutes.find(
1284
- (r) => getBaseFilePath(r.filePath, r.version, r.locale) === "index.md" && (r.locale || i18n.defaultLocale) === locale && r.version === currentRoute.version
1285
- );
1286
- targetPath = defaultIndexRoute ? defaultIndexRoute.path : locale === i18n.defaultLocale ? currentRoute.version ? `/${currentRoute.version}` : "/" : currentRoute.version ? `/${currentRoute.version}/${locale}` : `/${locale}`;
1287
- }
1288
- } else {
1289
- targetPath = locale === i18n.defaultLocale ? "/" : `/${locale}`;
1290
- }
1291
- navigate(targetPath);
1292
- };
1293
- return /* @__PURE__ */ jsxs14("div", { className: "boltdocs-language-switcher", ref: dropdownRef, children: [
1294
- /* @__PURE__ */ jsxs14(
1295
- "button",
1296
- {
1297
- className: "language-btn",
1298
- onClick: () => setIsOpen(!isOpen),
1299
- "aria-label": "Switch language",
1300
- "aria-expanded": isOpen,
1301
- "aria-haspopup": "listbox",
1302
- children: [
1303
- /* @__PURE__ */ jsx16(Globe, { size: 18 }),
1304
- /* @__PURE__ */ jsx16("span", { className: "language-label", children: i18n.locales[currentLocale] || currentLocale }),
1305
- /* @__PURE__ */ jsx16(ChevronDown, { size: 14 })
1306
- ]
1573
+ if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {
1574
+ return;
1307
1575
  }
1308
- ),
1309
- isOpen && /* @__PURE__ */ jsx16("div", { className: "language-dropdown", children: Object.entries(i18n.locales).map(([key, label]) => /* @__PURE__ */ jsx16(
1310
- "button",
1311
- {
1312
- className: `language-option ${key === currentLocale ? "active" : ""}`,
1313
- onClick: () => handleSelect(key),
1314
- children: label
1315
- },
1316
- key
1317
- )) })
1318
- ] });
1319
- }
1320
-
1321
- // src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx
1322
- import { useState as useState9, useRef as useRef5, useEffect as useEffect7 } from "react";
1323
- import { ChevronDown as ChevronDown2 } from "lucide-react";
1324
- import { useNavigate as useNavigate3, useLocation as useLocation9 } from "react-router-dom";
1325
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
1326
- function getBaseFilePath2(filePath, version, locale) {
1327
- let path = filePath;
1328
- if (version && (path === version || path.startsWith(version + "/"))) {
1329
- path = path === version ? "index.md" : path.slice(version.length + 1);
1330
- }
1331
- if (locale && (path === locale || path.startsWith(locale + "/"))) {
1332
- path = path === locale ? "index.md" : path.slice(locale.length + 1);
1333
- }
1334
- return path;
1335
- }
1336
- function VersionSwitcher({
1337
- versions,
1338
- currentVersion,
1339
- currentLocale,
1340
- allRoutes
1341
- }) {
1342
- const [isOpen, setIsOpen] = useState9(false);
1343
- const dropdownRef = useRef5(null);
1344
- const navigate = useNavigate3();
1345
- const location = useLocation9();
1346
- useEffect7(() => {
1347
- function handleClickOutside(event) {
1348
- if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
1349
- setIsOpen(false);
1576
+ if (typeof localizedTo === "string" && !localizedTo.startsWith("http")) {
1577
+ e.preventDefault();
1578
+ React10.startTransition(() => {
1579
+ navigate(localizedTo);
1580
+ });
1350
1581
  }
1582
+ };
1583
+ return /* @__PURE__ */ jsxs16(Fragment, { children: [
1584
+ /* @__PURE__ */ jsx22(
1585
+ RouterNavLink,
1586
+ {
1587
+ ref,
1588
+ to: localizedTo,
1589
+ onMouseEnter: handleMouseEnter,
1590
+ onMouseMove: handleMouseMove,
1591
+ onMouseLeave: handleMouseLeave,
1592
+ onFocus: handleFocus,
1593
+ onBlur: handleBlur,
1594
+ onClick: handleClick,
1595
+ ...rest
1596
+ }
1597
+ ),
1598
+ preview.visible && shouldShowPreview && /* @__PURE__ */ jsx22(
1599
+ LinkPreview,
1600
+ {
1601
+ isVisible: preview.visible,
1602
+ title: preview.title,
1603
+ summary: preview.summary,
1604
+ x: preview.x,
1605
+ y: preview.y
1606
+ }
1607
+ )
1608
+ ] });
1609
+ }
1610
+ );
1611
+ NavLink.displayName = "NavLink";
1612
+
1613
+ // src/client/theme/ui/Navbar/Tabs.tsx
1614
+ import * as Icons from "lucide-react";
1615
+ import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
1616
+ function Tabs({ tabs, routes }) {
1617
+ const location = useLocation10();
1618
+ const containerRef = useRef6(null);
1619
+ const tabRefs = useRef6([]);
1620
+ const [indicatorStyle, setIndicatorStyle] = useState12({
1621
+ opacity: 0,
1622
+ transform: "translateX(0) scaleX(0)",
1623
+ width: 0
1624
+ });
1625
+ const currentRoute = routes.find((r) => r.path === location.pathname);
1626
+ const currentTabId = currentRoute?.tab?.toLowerCase();
1627
+ const activeIndex = tabs.findIndex(
1628
+ (tab) => currentTabId ? currentTabId === tab.id.toLowerCase() : false
1629
+ );
1630
+ const finalActiveIndex = activeIndex === -1 ? 0 : activeIndex;
1631
+ useEffect10(() => {
1632
+ const activeTab = tabRefs.current[finalActiveIndex];
1633
+ if (activeTab) {
1634
+ setIndicatorStyle({
1635
+ opacity: 1,
1636
+ width: activeTab.offsetWidth,
1637
+ transform: `translateX(${activeTab.offsetLeft}px)`
1638
+ });
1351
1639
  }
1352
- document.addEventListener("mousedown", handleClickOutside);
1353
- return () => document.removeEventListener("mousedown", handleClickOutside);
1354
- }, []);
1355
- const handleSelect = (version) => {
1356
- setIsOpen(false);
1357
- if (version === currentVersion) return;
1358
- const currentRoute = allRoutes.find((r) => r.path === location.pathname);
1359
- let targetPath = `/docs/${version}`;
1360
- if (currentRoute) {
1361
- const baseFile = getBaseFilePath2(
1362
- currentRoute.filePath,
1363
- currentRoute.version,
1364
- currentRoute.locale
1365
- );
1366
- const targetRoute = allRoutes.find(
1367
- (r) => getBaseFilePath2(r.filePath, r.version, r.locale) === baseFile && (r.version || versions.defaultVersion) === version && (currentLocale ? r.locale === currentLocale : !r.locale)
1640
+ }, [finalActiveIndex, tabs, location.pathname]);
1641
+ if (!tabs || tabs.length === 0) return null;
1642
+ const renderTabIcon = (iconName) => {
1643
+ if (!iconName) return null;
1644
+ if (iconName.trim().startsWith("<svg")) {
1645
+ return /* @__PURE__ */ jsx23(
1646
+ "span",
1647
+ {
1648
+ className: "tab-icon svg-icon",
1649
+ dangerouslySetInnerHTML: { __html: iconName }
1650
+ }
1368
1651
  );
1369
- if (targetRoute) {
1370
- targetPath = targetRoute.path;
1371
- } else {
1372
- const versionIndexRoute = allRoutes.find(
1373
- (r) => getBaseFilePath2(r.filePath, r.version, r.locale) === "index.md" && (r.version || versions.defaultVersion) === version && (currentLocale ? r.locale === currentLocale : !r.locale)
1374
- );
1375
- targetPath = versionIndexRoute ? versionIndexRoute.path : `/docs/${version}${currentLocale ? `/${currentLocale}` : ""}`;
1376
- }
1377
- }
1378
- navigate(targetPath);
1379
- };
1380
- return /* @__PURE__ */ jsxs15(
1381
- "div",
1382
- {
1383
- className: "boltdocs-version-switcher",
1384
- ref: dropdownRef,
1385
- style: { position: "relative", display: "flex", alignItems: "center" },
1386
- children: [
1387
- /* @__PURE__ */ jsxs15(
1388
- "button",
1389
- {
1390
- className: "navbar-version",
1391
- onClick: () => setIsOpen(!isOpen),
1392
- "aria-label": "Switch version",
1393
- "aria-expanded": isOpen,
1394
- "aria-haspopup": "listbox",
1395
- style: {
1396
- fontFamily: "inherit",
1397
- padding: "0.25rem 0.5rem",
1398
- marginLeft: "0.5rem"
1399
- },
1400
- children: [
1401
- /* @__PURE__ */ jsx17("span", { children: versions.versions[currentVersion] || currentVersion }),
1402
- /* @__PURE__ */ jsx17(ChevronDown2, { size: 14 })
1403
- ]
1404
- }
1405
- ),
1406
- isOpen && /* @__PURE__ */ jsx17(
1407
- "div",
1408
- {
1409
- className: "language-dropdown",
1410
- style: {
1411
- left: "0.5rem",
1412
- right: "auto",
1413
- minWidth: "150px",
1414
- top: "calc(100% + 8px)"
1415
- },
1416
- children: Object.entries(versions.versions).map(([key, label]) => /* @__PURE__ */ jsx17(
1417
- "button",
1418
- {
1419
- className: `language-option ${key === currentVersion ? "active" : ""}`,
1420
- onClick: () => handleSelect(key),
1421
- children: label
1422
- },
1423
- key
1424
- ))
1425
- }
1426
- )
1427
- ]
1428
- }
1429
- );
1430
- }
1431
-
1432
- // src/client/theme/ui/ThemeToggle/ThemeToggle.tsx
1433
- import { useEffect as useEffect8, useState as useState10 } from "react";
1434
- import { Sun, Moon } from "lucide-react";
1435
- import { jsx as jsx18 } from "react/jsx-runtime";
1436
- function ThemeToggle() {
1437
- const [theme, setTheme] = useState10("dark");
1438
- const [mounted, setMounted] = useState10(false);
1439
- useEffect8(() => {
1440
- setMounted(true);
1441
- const stored = localStorage.getItem("boltdocs-theme");
1442
- if (stored === "light" || stored === "dark") {
1443
- setTheme(stored);
1444
- } else {
1445
- const prefersDark = window.matchMedia(
1446
- "(prefers-color-scheme: dark)"
1447
- ).matches;
1448
- setTheme(prefersDark ? "dark" : "light");
1449
1652
  }
1450
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
1451
- const handleChange = (e) => {
1452
- if (!localStorage.getItem("boltdocs-theme")) {
1453
- setTheme(e.matches ? "dark" : "light");
1454
- }
1455
- };
1456
- mediaQuery.addEventListener("change", handleChange);
1457
- return () => mediaQuery.removeEventListener("change", handleChange);
1458
- }, []);
1459
- useEffect8(() => {
1460
- if (!mounted) return;
1461
- const root = document.documentElement;
1462
- if (theme === "light") {
1463
- root.classList.add("theme-light");
1464
- root.dataset.theme = "light";
1465
- } else {
1466
- root.classList.remove("theme-light");
1467
- root.dataset.theme = "dark";
1653
+ const LucideIcon = Icons[iconName];
1654
+ if (LucideIcon) {
1655
+ return /* @__PURE__ */ jsx23(LucideIcon, { size: 16, className: "tab-icon lucide-icon" });
1468
1656
  }
1469
- }, [theme, mounted]);
1470
- const toggleTheme = () => {
1471
- const newTheme = theme === "dark" ? "light" : "dark";
1472
- setTheme(newTheme);
1473
- localStorage.setItem("boltdocs-theme", newTheme);
1657
+ return /* @__PURE__ */ jsx23("img", { src: iconName, alt: "", className: "tab-icon img-icon" });
1474
1658
  };
1475
- if (!mounted) {
1476
- return /* @__PURE__ */ jsx18("button", { className: "navbar-icon-btn", "aria-label": "Toggle theme", disabled: true, children: /* @__PURE__ */ jsx18("span", { style: { width: 20, height: 20, display: "inline-block" } }) });
1477
- }
1478
- return /* @__PURE__ */ jsx18(
1479
- "button",
1480
- {
1481
- className: "navbar-icon-btn",
1482
- onClick: toggleTheme,
1483
- "aria-label": "Toggle theme",
1484
- title: `Switch to ${theme === "dark" ? "light" : "dark"} theme`,
1485
- children: theme === "dark" ? /* @__PURE__ */ jsx18(Sun, { size: 20 }) : /* @__PURE__ */ jsx18(Moon, { size: 20 })
1486
- }
1487
- );
1659
+ return /* @__PURE__ */ jsx23("div", { className: "boltdocs-tabs-container", children: /* @__PURE__ */ jsxs17("div", { className: "boltdocs-tabs", ref: containerRef, children: [
1660
+ tabs.map((tab, index) => {
1661
+ const isActive = index === finalActiveIndex;
1662
+ const firstRoute = routes.find(
1663
+ (r) => r.tab && r.tab.toLowerCase() === tab.id.toLowerCase()
1664
+ );
1665
+ const linkTo = firstRoute ? firstRoute.path : "#";
1666
+ return /* @__PURE__ */ jsxs17(
1667
+ Link,
1668
+ {
1669
+ to: linkTo,
1670
+ ref: (el) => {
1671
+ tabRefs.current[index] = el;
1672
+ },
1673
+ className: `boltdocs-tab-item ${isActive ? "active" : ""}`,
1674
+ children: [
1675
+ renderTabIcon(tab.icon),
1676
+ /* @__PURE__ */ jsx23("span", { children: tab.text })
1677
+ ]
1678
+ },
1679
+ tab.id
1680
+ );
1681
+ }),
1682
+ /* @__PURE__ */ jsx23("div", { className: "boltdocs-tab-indicator", style: indicatorStyle })
1683
+ ] }) });
1488
1684
  }
1489
1685
 
1490
- // src/client/theme/icons/discord.tsx
1491
- import { jsx as jsx19 } from "react/jsx-runtime";
1492
- var Discord = (props) => /* @__PURE__ */ jsx19("svg", { ...props, viewBox: "0 0 256 199", preserveAspectRatio: "xMidYMid", children: /* @__PURE__ */ jsx19(
1493
- "path",
1494
- {
1495
- d: "M216.856 16.597A208.502 208.502 0 0 0 164.042 0c-2.275 4.113-4.933 9.645-6.766 14.046-19.692-2.961-39.203-2.961-58.533 0-1.832-4.4-4.55-9.933-6.846-14.046a207.809 207.809 0 0 0-52.855 16.638C5.618 67.147-3.443 116.4 1.087 164.956c22.169 16.555 43.653 26.612 64.775 33.193A161.094 161.094 0 0 0 79.735 175.3a136.413 136.413 0 0 1-21.846-10.632 108.636 108.636 0 0 0 5.356-4.237c42.122 19.702 87.89 19.702 129.51 0a131.66 131.66 0 0 0 5.355 4.237 136.07 136.07 0 0 1-21.886 10.653c4.006 8.02 8.638 15.67 13.873 22.848 21.142-6.58 42.646-16.637 64.815-33.213 5.316-56.288-9.08-105.09-38.056-148.36ZM85.474 135.095c-12.645 0-23.015-11.805-23.015-26.18s10.149-26.2 23.015-26.2c12.867 0 23.236 11.804 23.015 26.2.02 14.375-10.148 26.18-23.015 26.18Zm85.051 0c-12.645 0-23.014-11.805-23.014-26.18s10.148-26.2 23.014-26.2c12.867 0 23.236 11.804 23.015 26.2 0 14.375-10.148 26.18-23.015 26.18Z",
1496
- fill: "currentColor"
1497
- }
1498
- ) });
1499
-
1500
- // src/client/theme/icons/twitter.tsx
1501
- import { jsx as jsx20 } from "react/jsx-runtime";
1502
- var XformerlyTwitter = (props) => /* @__PURE__ */ jsx20("svg", { ...props, fill: "none", viewBox: "0 0 1200 1227", children: /* @__PURE__ */ jsx20(
1503
- "path",
1504
- {
1505
- fill: "currentColor",
1506
- d: "M714.163 519.284 1160.89 0h-105.86L667.137 450.887 357.328 0H0l468.492 681.821L0 1226.37h105.866l409.625-476.152 327.181 476.152H1200L714.137 519.284h.026ZM569.165 687.828l-47.468-67.894-377.686-540.24h162.604l304.797 435.991 47.468 67.894 396.2 566.721H892.476L569.165 687.854v-.026Z"
1507
- }
1508
- ) });
1509
-
1510
1686
  // src/client/theme/ui/Navbar/Navbar.tsx
1511
- import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
1512
- var SearchDialog = React10.lazy(
1513
- () => import("./SearchDialog-J3KNRGNO.mjs").then((m) => ({ default: m.SearchDialog }))
1687
+ import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
1688
+ var SearchDialog = lazy2(
1689
+ () => import("./SearchDialog-6Z7CUAYJ.mjs").then((m) => ({ default: m.SearchDialog }))
1514
1690
  );
1515
1691
  var ICON_MAP = {
1516
1692
  discord: Discord,
@@ -1523,81 +1699,123 @@ function Navbar({
1523
1699
  currentLocale,
1524
1700
  currentVersion
1525
1701
  }) {
1702
+ const location = useLocation11();
1703
+ const isHomePage = location.pathname === "/";
1526
1704
  const title = config.themeConfig?.title || "Boltdocs";
1527
1705
  const navItems = config.themeConfig?.navbar || [];
1528
1706
  const socialLinks = config.themeConfig?.socialLinks || [];
1529
- return /* @__PURE__ */ jsx21("header", { className: "boltdocs-navbar", children: /* @__PURE__ */ jsxs16("div", { className: "navbar-container", children: [
1530
- /* @__PURE__ */ jsxs16("div", { className: "navbar-left", children: [
1531
- /* @__PURE__ */ jsx21("div", { className: "navbar-logo", children: /* @__PURE__ */ jsxs16(Link, { to: "/", children: [
1532
- config.themeConfig?.logo ? config.themeConfig.logo.trim().startsWith("<svg") ? /* @__PURE__ */ jsx21(
1533
- "span",
1534
- {
1535
- className: "navbar-logo-svg",
1536
- dangerouslySetInnerHTML: {
1537
- __html: config.themeConfig.logo
1538
- }
1539
- }
1540
- ) : /* @__PURE__ */ jsx21(
1541
- "img",
1542
- {
1543
- src: config.themeConfig.logo,
1544
- alt: title,
1545
- className: "navbar-logo-img"
1546
- }
1547
- ) : null,
1548
- title
1549
- ] }) }),
1550
- config.versions && currentVersion && allRoutes ? /* @__PURE__ */ jsx21(
1551
- VersionSwitcher,
1552
- {
1553
- versions: config.versions,
1554
- currentVersion,
1555
- currentLocale,
1556
- allRoutes
1557
- }
1558
- ) : config.themeConfig?.version ? /* @__PURE__ */ jsxs16("div", { className: "navbar-version", children: [
1559
- config.themeConfig.version,
1560
- " ",
1561
- /* @__PURE__ */ jsx21(ChevronDown3, { size: 14 })
1562
- ] }) : null,
1563
- /* @__PURE__ */ jsx21("nav", { className: "navbar-links", "aria-label": "Top Navigation", children: navItems.map((item, i) => /* @__PURE__ */ jsx21(Link, { to: item.link, children: item.text }, i)) })
1564
- ] }),
1565
- /* @__PURE__ */ jsxs16("div", { className: "navbar-right", children: [
1566
- /* @__PURE__ */ jsx21(
1567
- React10.Suspense,
1568
- {
1569
- fallback: /* @__PURE__ */ jsx21("div", { className: "navbar-search-placeholder" }),
1570
- children: /* @__PURE__ */ jsx21(SearchDialog, { routes: routes || [] })
1571
- }
1572
- ),
1573
- config.i18n && currentLocale && allRoutes && /* @__PURE__ */ jsx21(
1574
- LanguageSwitcher,
1707
+ const hasTabs = !isHomePage && config.themeConfig?.tabs && config.themeConfig.tabs.length > 0;
1708
+ const leftItems = navItems.filter((item) => item.position !== "right");
1709
+ const rightItems = navItems.filter((item) => item.position === "right");
1710
+ const renderNavItem = (item, i) => {
1711
+ const text = item.label || item.text || "";
1712
+ const href = item.to || item.href || item.link || "";
1713
+ const isExternal = href.startsWith("http") || href.startsWith("//") || href.includes("://");
1714
+ return /* @__PURE__ */ jsxs18(Link2, { to: href, target: isExternal ? "_blank" : void 0, children: [
1715
+ text,
1716
+ isExternal && /* @__PURE__ */ jsx24("span", { className: "navbar-external-icon", children: /* @__PURE__ */ jsxs18(
1717
+ "svg",
1575
1718
  {
1576
- i18n: config.i18n,
1577
- currentLocale,
1578
- allRoutes
1719
+ viewBox: "0 0 24 24",
1720
+ width: "13",
1721
+ height: "13",
1722
+ stroke: "currentColor",
1723
+ strokeWidth: "2",
1724
+ fill: "none",
1725
+ strokeLinecap: "round",
1726
+ strokeLinejoin: "round",
1727
+ children: [
1728
+ /* @__PURE__ */ jsx24("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
1729
+ /* @__PURE__ */ jsx24("polyline", { points: "15 3 21 3 21 9" }),
1730
+ /* @__PURE__ */ jsx24("line", { x1: "10", y1: "14", x2: "21", y2: "3" })
1731
+ ]
1579
1732
  }
1580
- ),
1581
- /* @__PURE__ */ jsx21(ThemeToggle, {}),
1582
- config.themeConfig?.githubRepo && /* @__PURE__ */ jsx21(GithubStars, { repo: config.themeConfig.githubRepo }),
1583
- socialLinks.length > 0 && /* @__PURE__ */ jsx21("div", { className: "navbar-divider" }),
1584
- /* @__PURE__ */ jsx21("div", { className: "navbar-icons", children: socialLinks.map((link, i) => {
1585
- const IconComp = ICON_MAP[link.icon.toLowerCase()];
1586
- return /* @__PURE__ */ jsx21(
1587
- "a",
1588
- {
1589
- href: link.link,
1590
- target: "_blank",
1591
- rel: "noopener noreferrer",
1592
- className: "navbar-icon-btn",
1593
- "aria-label": link.icon,
1594
- children: IconComp ? /* @__PURE__ */ jsx21(IconComp, {}) : /* @__PURE__ */ jsx21("span", { children: link.icon })
1595
- },
1596
- i
1597
- );
1598
- }) })
1599
- ] })
1600
- ] }) });
1733
+ ) })
1734
+ ] }, i);
1735
+ };
1736
+ return /* @__PURE__ */ jsxs18("header", { className: `boltdocs-navbar ${hasTabs ? "has-tabs" : ""}`, children: [
1737
+ /* @__PURE__ */ jsxs18(
1738
+ "div",
1739
+ {
1740
+ className: "navbar-container",
1741
+ style: { height: "var(--ld-navbar-height)" },
1742
+ children: [
1743
+ /* @__PURE__ */ jsxs18("div", { className: "navbar-left", children: [
1744
+ /* @__PURE__ */ jsx24("div", { className: "navbar-logo", children: /* @__PURE__ */ jsxs18(Link2, { to: "/", children: [
1745
+ config.themeConfig?.logo ? config.themeConfig.logo.trim().startsWith("<svg") ? /* @__PURE__ */ jsx24(
1746
+ "span",
1747
+ {
1748
+ className: "navbar-logo-svg",
1749
+ dangerouslySetInnerHTML: {
1750
+ __html: config.themeConfig.logo
1751
+ }
1752
+ }
1753
+ ) : /* @__PURE__ */ jsx24(
1754
+ "img",
1755
+ {
1756
+ src: config.themeConfig.logo,
1757
+ alt: title,
1758
+ className: "navbar-logo-img"
1759
+ }
1760
+ ) : null,
1761
+ title
1762
+ ] }) }),
1763
+ config.versions && currentVersion && allRoutes ? /* @__PURE__ */ jsx24(
1764
+ VersionSwitcher,
1765
+ {
1766
+ versions: config.versions,
1767
+ currentVersion,
1768
+ currentLocale,
1769
+ allRoutes
1770
+ }
1771
+ ) : config.themeConfig?.version ? /* @__PURE__ */ jsxs18("div", { className: "navbar-version", children: [
1772
+ config.themeConfig.version,
1773
+ " ",
1774
+ /* @__PURE__ */ jsx24(ChevronDown3, { size: 14 })
1775
+ ] }) : null,
1776
+ /* @__PURE__ */ jsx24("nav", { className: "navbar-links", "aria-label": "Top Navigation Left", children: leftItems.map(renderNavItem) })
1777
+ ] }),
1778
+ /* @__PURE__ */ jsxs18("div", { className: "navbar-right", children: [
1779
+ /* @__PURE__ */ jsx24("nav", { className: "navbar-links", "aria-label": "Top Navigation Right", children: rightItems.map(renderNavItem) }),
1780
+ /* @__PURE__ */ jsx24(Suspense2, { fallback: /* @__PURE__ */ jsx24("div", { className: "navbar-search-placeholder" }), children: /* @__PURE__ */ jsx24(SearchDialog, { routes: routes || [] }) }),
1781
+ config.i18n && currentLocale && allRoutes && /* @__PURE__ */ jsx24(
1782
+ LanguageSwitcher,
1783
+ {
1784
+ i18n: config.i18n,
1785
+ currentLocale,
1786
+ allRoutes
1787
+ }
1788
+ ),
1789
+ /* @__PURE__ */ jsx24(ThemeToggle, {}),
1790
+ config.themeConfig?.githubRepo && /* @__PURE__ */ jsx24(GithubStars, { repo: config.themeConfig.githubRepo }),
1791
+ socialLinks.length > 0 && /* @__PURE__ */ jsx24("div", { className: "navbar-divider" }),
1792
+ /* @__PURE__ */ jsx24("div", { className: "navbar-icons", children: socialLinks.map((link, i) => {
1793
+ const IconComp = ICON_MAP[link.icon.toLowerCase()];
1794
+ return /* @__PURE__ */ jsx24(
1795
+ "a",
1796
+ {
1797
+ href: link.link,
1798
+ target: "_blank",
1799
+ rel: "noopener noreferrer",
1800
+ className: "navbar-icon-btn",
1801
+ "aria-label": link.icon,
1802
+ children: IconComp ? /* @__PURE__ */ jsx24(IconComp, {}) : /* @__PURE__ */ jsx24("span", { children: link.icon })
1803
+ },
1804
+ i
1805
+ );
1806
+ }) })
1807
+ ] })
1808
+ ]
1809
+ }
1810
+ ),
1811
+ hasTabs && config.themeConfig?.tabs && /* @__PURE__ */ jsx24(
1812
+ Tabs,
1813
+ {
1814
+ tabs: config.themeConfig.tabs,
1815
+ routes: allRoutes || routes || []
1816
+ }
1817
+ )
1818
+ ] });
1601
1819
  }
1602
1820
 
1603
1821
  export {