boltdocs 2.7.10 → 2.7.11

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 (137) hide show
  1. package/dist/client/index.cjs +1929 -1
  2. package/dist/client/index.js +1880 -1
  3. package/dist/client/mdx.cjs +7 -1
  4. package/dist/client/mdx.js +7 -1
  5. package/dist/client/primitives.cjs +60 -1
  6. package/dist/client/primitives.js +20 -1
  7. package/dist/docs-layout-BXHV0xw_.cjs +1431 -0
  8. package/dist/docs-layout-DwFndmj5.js +1231 -0
  9. package/dist/icons-dev-3cZMyt8r.cjs +1204 -0
  10. package/dist/icons-dev-Df8OQ481.js +839 -0
  11. package/dist/image-DtrI2cw3.cjs +268 -0
  12. package/dist/image-jxPb-2iV.js +214 -0
  13. package/dist/mdx-BdWkJTeB.cjs +523 -0
  14. package/dist/mdx-UTTLFWJq.js +494 -0
  15. package/dist/node/cli-entry.cjs +1 -1
  16. package/dist/node/cli-entry.mjs +1 -1
  17. package/dist/node/index.cjs +1 -1
  18. package/dist/node/index.mjs +1 -1
  19. package/dist/{node-DtEDyN1u.cjs → node-BSM4qcDK.cjs} +1 -1
  20. package/dist/{node-_1jhMGYx.mjs → node-BspZN3R2.mjs} +1 -1
  21. package/dist/{package-DrwtlXfk.cjs → package-DIIrjuWI.cjs} +1 -1
  22. package/dist/{package--0Yf0t1N.mjs → package-K0zsjGIz.mjs} +1 -1
  23. package/dist/{search-dialog-ByvGScjt.js → search-dialog-BHuIiUC6.js} +3 -1
  24. package/dist/search-dialog-BNF10tDl.js +375 -0
  25. package/dist/search-dialog-BwkDuI9R.cjs +220 -0
  26. package/dist/search-dialog-C7xuvyNk.cjs +386 -0
  27. package/dist/search-dialog-CIQg6k8c.cjs +8 -0
  28. package/dist/search-dialog-D-DDN7zJ.js +208 -0
  29. package/package.json +3 -4
  30. package/dist/docs-layout-KoWNZc8_.js +0 -6
  31. package/dist/docs-layout-x2yKt2cL.cjs +0 -6
  32. package/dist/icons-dev-B_RZIyxu.js +0 -6
  33. package/dist/icons-dev-BlV3wWFT.cjs +0 -6
  34. package/dist/image-BHhTvQzr.cjs +0 -6
  35. package/dist/image-CqKzYD8f.js +0 -6
  36. package/dist/mdx-DudBEac0.js +0 -7
  37. package/dist/mdx-r4cDQxWu.cjs +0 -7
  38. package/dist/search-dialog-B584t9ZF.js +0 -6
  39. package/dist/search-dialog-BvBopRsZ.cjs +0 -6
  40. package/dist/search-dialog-Cyko6TJm.cjs +0 -6
  41. package/dist/search-dialog-D6BNohIJ.js +0 -6
  42. package/dist/search-dialog-DuYTIefy.cjs +0 -6
  43. package/src/client/app/config-context.tsx +0 -51
  44. package/src/client/app/doc-page.tsx +0 -38
  45. package/src/client/app/docs-layout.tsx +0 -28
  46. package/src/client/app/head.tsx +0 -122
  47. package/src/client/app/helmet-compat.tsx +0 -36
  48. package/src/client/app/mdx-component.tsx +0 -8
  49. package/src/client/app/mdx-components-context.tsx +0 -72
  50. package/src/client/app/routes-context.tsx +0 -34
  51. package/src/client/app/scroll-handler.tsx +0 -74
  52. package/src/client/app/theme-context.tsx +0 -103
  53. package/src/client/app/ui-context.tsx +0 -42
  54. package/src/client/components/docs-layout-default.tsx +0 -85
  55. package/src/client/components/icons-dev.tsx +0 -282
  56. package/src/client/components/mdx/callout.tsx +0 -97
  57. package/src/client/components/mdx/card.tsx +0 -99
  58. package/src/client/components/mdx/cards.tsx +0 -27
  59. package/src/client/components/mdx/code-block.tsx +0 -184
  60. package/src/client/components/mdx/field.tsx +0 -33
  61. package/src/client/components/mdx/image.tsx +0 -44
  62. package/src/client/components/mdx/index.ts +0 -19
  63. package/src/client/components/mdx/table.tsx +0 -54
  64. package/src/client/components/mdx/typographics.tsx +0 -120
  65. package/src/client/components/mdx/use-code-block.ts +0 -34
  66. package/src/client/components/primitives/breadcrumbs.tsx +0 -54
  67. package/src/client/components/primitives/button-group.tsx +0 -54
  68. package/src/client/components/primitives/button.tsx +0 -6
  69. package/src/client/components/primitives/code-block.tsx +0 -120
  70. package/src/client/components/primitives/docs-layout.tsx +0 -125
  71. package/src/client/components/primitives/error-boundary.tsx +0 -107
  72. package/src/client/components/primitives/heading.tsx +0 -128
  73. package/src/client/components/primitives/helpers/observer.ts +0 -141
  74. package/src/client/components/primitives/image.tsx +0 -26
  75. package/src/client/components/primitives/link.tsx +0 -102
  76. package/src/client/components/primitives/menu.tsx +0 -137
  77. package/src/client/components/primitives/navbar.tsx +0 -466
  78. package/src/client/components/primitives/on-this-page.tsx +0 -430
  79. package/src/client/components/primitives/page-nav.tsx +0 -51
  80. package/src/client/components/primitives/popover.tsx +0 -28
  81. package/src/client/components/primitives/search-dialog.tsx +0 -193
  82. package/src/client/components/primitives/sidebar.tsx +0 -423
  83. package/src/client/components/primitives/skeleton.tsx +0 -26
  84. package/src/client/components/primitives/tabs.tsx +0 -70
  85. package/src/client/components/primitives/tooltip.tsx +0 -81
  86. package/src/client/components/primitives/types.ts +0 -11
  87. package/src/client/components/ui-base/banner.tsx +0 -66
  88. package/src/client/components/ui-base/breadcrumbs.tsx +0 -44
  89. package/src/client/components/ui-base/copy-markdown.tsx +0 -107
  90. package/src/client/components/ui-base/error-boundary.tsx +0 -15
  91. package/src/client/components/ui-base/github-stars.tsx +0 -29
  92. package/src/client/components/ui-base/icons.tsx +0 -240
  93. package/src/client/components/ui-base/index.ts +0 -16
  94. package/src/client/components/ui-base/last-updated.tsx +0 -27
  95. package/src/client/components/ui-base/navbar.tsx +0 -266
  96. package/src/client/components/ui-base/not-found.tsx +0 -26
  97. package/src/client/components/ui-base/on-this-page.tsx +0 -57
  98. package/src/client/components/ui-base/page-nav.tsx +0 -50
  99. package/src/client/components/ui-base/search-dialog.tsx +0 -163
  100. package/src/client/components/ui-base/search-highlight.tsx +0 -10
  101. package/src/client/components/ui-base/sidebar.tsx +0 -92
  102. package/src/client/components/ui-base/tabs.tsx +0 -83
  103. package/src/client/components/ui-base/theme-toggle.tsx +0 -130
  104. package/src/client/components/ui-base/version-i18n.tsx +0 -80
  105. package/src/client/hooks/index.ts +0 -13
  106. package/src/client/hooks/use-analytics.ts +0 -272
  107. package/src/client/hooks/use-breadcrumbs.ts +0 -22
  108. package/src/client/hooks/use-i18n.ts +0 -182
  109. package/src/client/hooks/use-localized-to.ts +0 -113
  110. package/src/client/hooks/use-location.ts +0 -5
  111. package/src/client/hooks/use-navbar.ts +0 -130
  112. package/src/client/hooks/use-page-nav.ts +0 -46
  113. package/src/client/hooks/use-routes.ts +0 -108
  114. package/src/client/hooks/use-search-highlight.ts +0 -185
  115. package/src/client/hooks/use-search.ts +0 -118
  116. package/src/client/hooks/use-sidebar.ts +0 -205
  117. package/src/client/hooks/use-tabs.ts +0 -46
  118. package/src/client/hooks/use-version.ts +0 -111
  119. package/src/client/index.ts +0 -31
  120. package/src/client/mdx.ts +0 -2
  121. package/src/client/primitives.ts +0 -19
  122. package/src/client/ssg/boltdocs-shell.tsx +0 -148
  123. package/src/client/ssg/create-routes.tsx +0 -473
  124. package/src/client/ssg/index.ts +0 -4
  125. package/src/client/ssg/mdx-page.tsx +0 -38
  126. package/src/client/store/boltdocs-context.tsx +0 -137
  127. package/src/client/theme/neutral.css +0 -141
  128. package/src/client/theme/reset.css +0 -189
  129. package/src/client/types.ts +0 -116
  130. package/src/client/utils/cn.ts +0 -6
  131. package/src/client/utils/copy-clipboard.ts +0 -22
  132. package/src/client/utils/get-base-file-path.ts +0 -21
  133. package/src/client/utils/github.ts +0 -121
  134. package/src/client/utils/i18n.ts +0 -23
  135. package/src/client/utils/path.ts +0 -9
  136. package/src/client/utils/react-to-text.ts +0 -34
  137. package/src/client/virtual.d.ts +0 -24
@@ -0,0 +1,1231 @@
1
+ /**
2
+ * Boltdocs - https://boltdocs.vercel.app
3
+ * Copyright (c) 2026 Jesus Alcala
4
+ * Licensed under the MIT License.
5
+ */
6
+ import { D as ChevronRight, E as ChevronLeft, Y as icons_exports, Z as normalizePath, _ as Link, b as useLocalizedTo, nt as useConfig, w as Check, y as cn } from "./icons-dev-Df8OQ481.js";
7
+ import { useLocation } from "react-router-dom";
8
+ import { Children, Component, createContext, use, useContext, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
9
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
+ import * as RAC from "react-aria-components";
11
+ import { Breadcrumb, Breadcrumbs, Popover } from "react-aria-components";
12
+ import virtualIcons from "virtual:boltdocs-icons";
13
+ import scrollIntoView from "scroll-into-view-if-needed";
14
+
15
+ //#region src/client/components/primitives/breadcrumbs.tsx
16
+ const Breadcrumbs$1 = ({ children, className, ...props }) => {
17
+ return /* @__PURE__ */ jsx(Breadcrumbs, {
18
+ className: cn("flex flex-wrap items-center", className),
19
+ ...props,
20
+ children
21
+ });
22
+ };
23
+ const BreadcrumbsItem = ({ children, className, ...props }) => {
24
+ return /* @__PURE__ */ jsx(Breadcrumb, {
25
+ className: cn("flex items-center", className),
26
+ ...props,
27
+ children
28
+ });
29
+ };
30
+ const BreadcrumbsLink = ({ children, href, className, ...props }) => {
31
+ return /* @__PURE__ */ jsx(Link, {
32
+ href,
33
+ className: cn("cursor-pointer", className),
34
+ ...props,
35
+ children
36
+ });
37
+ };
38
+ const BreadcrumbsSeparator = ({ className }) => {
39
+ return /* @__PURE__ */ jsx(ChevronRight, {
40
+ size: 14,
41
+ className: cn("shrink-0", className)
42
+ });
43
+ };
44
+ Breadcrumbs$1.Root = Breadcrumbs$1;
45
+ Breadcrumbs$1.Item = BreadcrumbsItem;
46
+ Breadcrumbs$1.Link = BreadcrumbsLink;
47
+ Breadcrumbs$1.Separator = BreadcrumbsSeparator;
48
+
49
+ //#endregion
50
+ //#region src/client/components/primitives/button.tsx
51
+ const Button$1 = ({ ...props }) => {
52
+ return /* @__PURE__ */ jsx(RAC.Button, { ...props });
53
+ };
54
+
55
+ //#endregion
56
+ //#region src/client/components/primitives/button-group.tsx
57
+ const ButtonGroup = ({ children, className, vertical = false }) => {
58
+ return /* @__PURE__ */ jsx("div", {
59
+ className: cn("inline-flex", vertical ? "flex-col" : "flex-row", !vertical && [
60
+ "[&>*:not(:first-child)]:-ml-px",
61
+ "[&>*:first-child]:rounded-r-none",
62
+ "[&>*:last-child]:rounded-l-none",
63
+ "[&>*:not(:first-child):not(:last-child)]:rounded-none",
64
+ className?.includes("rounded-full") && ["[&>*:first-child]:rounded-l-full", "[&>*:last-child]:rounded-r-full"],
65
+ className?.includes("rounded-xl") && ["[&>*:first-child]:rounded-l-xl", "[&>*:last-child]:rounded-r-xl"],
66
+ className?.includes("rounded-lg") && ["[&>*:first-child]:rounded-l-lg", "[&>*:last-child]:rounded-r-lg"]
67
+ ], vertical && [
68
+ "[&>*:not(:first-child)]:-mt-px",
69
+ "[&>*:first-child]:rounded-b-none",
70
+ "[&>*:last-child]:rounded-t-none",
71
+ "[&>*:not(:first-child):not(:last-child)]:rounded-none",
72
+ className?.includes("rounded-full") && ["[&>*:first-child]:rounded-t-full", "[&>*:last-child]:rounded-b-full"]
73
+ ], className),
74
+ children
75
+ });
76
+ };
77
+
78
+ //#endregion
79
+ //#region src/client/components/primitives/popover.tsx
80
+ /**
81
+ * A reusable Popover primitive with premium glassmorphism styling and smooth animations.
82
+ */
83
+ const Popover$1 = ({ children, className, ...props }) => {
84
+ return /* @__PURE__ */ jsx(Popover, {
85
+ offset: 8,
86
+ className: cn("z-50 overflow-auto outline-none transition-none", className),
87
+ ...props,
88
+ children
89
+ });
90
+ };
91
+
92
+ //#endregion
93
+ //#region src/client/components/primitives/menu.tsx
94
+ function MenuTrigger({ placement, className, ...props }) {
95
+ const [trigger, menu] = Children.toArray(props.children).slice(0, 2);
96
+ return /* @__PURE__ */ jsxs(RAC.MenuTrigger, {
97
+ ...props,
98
+ children: [trigger, /* @__PURE__ */ jsx(Popover$1, {
99
+ placement,
100
+ className,
101
+ children: menu
102
+ })]
103
+ });
104
+ }
105
+ function SubmenuTrigger({ className, ...props }) {
106
+ const [trigger, menu] = Children.toArray(props.children).slice(0, 2);
107
+ return /* @__PURE__ */ jsxs(RAC.SubmenuTrigger, {
108
+ ...props,
109
+ children: [trigger, /* @__PURE__ */ jsx(Popover$1, {
110
+ offset: -4,
111
+ crossOffset: -4,
112
+ className,
113
+ children: menu
114
+ })]
115
+ });
116
+ }
117
+ /**
118
+ * The Menu container.
119
+ */
120
+ function Menu(props) {
121
+ return /* @__PURE__ */ jsx(RAC.Menu, {
122
+ ...props,
123
+ className: RAC.composeRenderProps(props.className, (className) => cn("outline-none overflow-auto", className))
124
+ });
125
+ }
126
+ /**
127
+ * MenuItem with support for selection states and submenus.
128
+ */
129
+ function MenuItem(props) {
130
+ const textValue = props.textValue || (typeof props.children === "string" ? props.children : void 0);
131
+ return /* @__PURE__ */ jsx(RAC.MenuItem, {
132
+ ...props,
133
+ textValue,
134
+ className: RAC.composeRenderProps(props.className, (className) => cn("group relative flex flex-row items-center cursor-default outline-none", className)),
135
+ children: RAC.composeRenderProps(props.children, (children, { selectionMode, isSelected, hasSubmenu }) => /* @__PURE__ */ jsxs(Fragment, { children: [
136
+ selectionMode === "multiple" && /* @__PURE__ */ jsx("span", {
137
+ className: "flex items-center shrink-0 justify-center",
138
+ children: isSelected && /* @__PURE__ */ jsx(Check, { className: "size-3.5" })
139
+ }),
140
+ /* @__PURE__ */ jsx("div", {
141
+ className: "flex flex-row w-full items-center",
142
+ children
143
+ }),
144
+ hasSubmenu && /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 ml-auto" })
145
+ ] }))
146
+ });
147
+ }
148
+ function MenuSection({ title, ...props }) {
149
+ return /* @__PURE__ */ jsxs(RAC.MenuSection, {
150
+ ...props,
151
+ className: cn("flex flex-col", props.className),
152
+ children: [title && /* @__PURE__ */ jsx(RAC.Header, {
153
+ className: "select-none",
154
+ children: title
155
+ }), /* @__PURE__ */ jsx(RAC.Collection, {
156
+ items: props.items,
157
+ children: props.children
158
+ })]
159
+ });
160
+ }
161
+ /**
162
+ * MenuSeparator for visual division.
163
+ */
164
+ function MenuSeparator(props) {
165
+ return /* @__PURE__ */ jsx(RAC.Separator, {
166
+ ...props,
167
+ className: cn("border-t", props.className)
168
+ });
169
+ }
170
+ Menu.Root = Menu;
171
+ Menu.Item = MenuItem;
172
+ Menu.Trigger = MenuTrigger;
173
+ Menu.SubTrigger = SubmenuTrigger;
174
+ Menu.Section = MenuSection;
175
+ Menu.Separator = MenuSeparator;
176
+
177
+ //#endregion
178
+ //#region src/client/components/primitives/error-boundary.tsx
179
+ var ErrorBoundary = class extends Component {
180
+ state = {
181
+ hasError: false,
182
+ error: null
183
+ };
184
+ static getDerivedStateFromError(error) {
185
+ return {
186
+ hasError: true,
187
+ error
188
+ };
189
+ }
190
+ componentDidCatch(error, errorInfo) {
191
+ if (this.props.onError) this.props.onError(error, errorInfo);
192
+ else console.error("ErrorBoundary caught an unhandled error:", error, errorInfo);
193
+ }
194
+ resetErrorBoundary = () => {
195
+ if (this.props.onReset) this.props.onReset();
196
+ this.setState({
197
+ hasError: false,
198
+ error: null
199
+ });
200
+ };
201
+ render() {
202
+ const { hasError, error } = this.state;
203
+ const { children, fallback, FallbackComponent } = this.props;
204
+ if (hasError && error) {
205
+ if (FallbackComponent) return /* @__PURE__ */ jsx(FallbackComponent, {
206
+ error,
207
+ resetErrorBoundary: this.resetErrorBoundary
208
+ });
209
+ if (fallback) return fallback;
210
+ return /* @__PURE__ */ jsx(ErrorBoundaryFallback, {
211
+ error,
212
+ resetErrorBoundary: this.resetErrorBoundary
213
+ });
214
+ }
215
+ return children;
216
+ }
217
+ };
218
+ function ErrorBoundaryFallback({ error, resetErrorBoundary }) {
219
+ return /* @__PURE__ */ jsxs("div", {
220
+ className: "flex flex-col items-center justify-center min-h-[40vh] text-center gap-4 px-6 py-8 border border-subtle bg-surface rounded-2xl max-w-lg mx-auto shadow-xs",
221
+ children: [
222
+ /* @__PURE__ */ jsx("div", {
223
+ className: "text-lg font-bold text-rose-600 dark:text-rose-400",
224
+ children: "Something went wrong"
225
+ }),
226
+ /* @__PURE__ */ jsx("p", {
227
+ className: "text-sm text-muted max-w-sm leading-relaxed",
228
+ children: error?.message || "An unexpected error occurred while rendering this page."
229
+ }),
230
+ /* @__PURE__ */ jsx(Button$1, {
231
+ className: "rounded-xl border border-subtle bg-main px-6 py-2.5 text-xs font-semibold text-body hover:bg-primary-50/50 hover:border-primary-500/50 transition-all duration-300 cursor-pointer outline-none select-none",
232
+ onPress: resetErrorBoundary,
233
+ children: "Try again"
234
+ })
235
+ ]
236
+ });
237
+ }
238
+
239
+ //#endregion
240
+ //#region src/client/components/primitives/tabs.tsx
241
+ const Tabs = ({ children, className = "", ...props }) => {
242
+ return /* @__PURE__ */ jsx("div", {
243
+ className: cn("w-full", className),
244
+ ...props,
245
+ children
246
+ });
247
+ };
248
+ const TabsList = ({ children, className = "" }) => {
249
+ return /* @__PURE__ */ jsx("div", {
250
+ role: "tablist",
251
+ className: cn("relative flex flex-row items-center", className),
252
+ children
253
+ });
254
+ };
255
+ const TabsItem = ({ children, id, selected, className = "", ...props }) => {
256
+ return /* @__PURE__ */ jsx("button", {
257
+ role: "tab",
258
+ "aria-selected": selected,
259
+ "data-selected": selected,
260
+ className: cn("outline-none cursor-pointer bg-transparent border-none", className),
261
+ ...props,
262
+ children
263
+ });
264
+ };
265
+ const TabsContent = ({ children, className = "" }) => {
266
+ return /* @__PURE__ */ jsx("div", {
267
+ className: cn("outline-none", className),
268
+ children
269
+ });
270
+ };
271
+ const TabsIndicator = ({ className = "", style }) => {
272
+ return /* @__PURE__ */ jsx("div", {
273
+ className: cn("absolute bottom-0", className),
274
+ style
275
+ });
276
+ };
277
+ Tabs.Root = Tabs;
278
+ Tabs.List = TabsList;
279
+ Tabs.Item = TabsItem;
280
+ Tabs.Content = TabsContent;
281
+ Tabs.Indicator = TabsIndicator;
282
+
283
+ //#endregion
284
+ //#region src/client/app/ui-context.tsx
285
+ const UIContext = createContext(void 0);
286
+ function UIProvider({ children }) {
287
+ const [isSidebarOpen, setIsSidebarOpen] = useState(false);
288
+ const location = useLocation();
289
+ const toggleSidebar = () => setIsSidebarOpen((prev) => !prev);
290
+ const closeSidebar = () => setIsSidebarOpen(false);
291
+ useEffect(() => {
292
+ setIsSidebarOpen(false);
293
+ }, [location.pathname]);
294
+ return /* @__PURE__ */ jsx(UIContext.Provider, {
295
+ value: {
296
+ isSidebarOpen,
297
+ toggleSidebar,
298
+ closeSidebar
299
+ },
300
+ children
301
+ });
302
+ }
303
+ function useUI() {
304
+ const context = useContext(UIContext);
305
+ if (context === void 0) return {
306
+ isSidebarOpen: false,
307
+ toggleSidebar: () => {},
308
+ closeSidebar: () => {}
309
+ };
310
+ return context;
311
+ }
312
+
313
+ //#endregion
314
+ //#region src/client/components/primitives/helpers/observer.ts
315
+ function getItemId(url) {
316
+ if (url.startsWith("#")) return url.slice(1);
317
+ return null;
318
+ }
319
+ var Observer = class {
320
+ items = [];
321
+ single = false;
322
+ observer = null;
323
+ onChange;
324
+ callback(_entries) {
325
+ for (const item of this.items) {
326
+ const element = document.getElementById(item.id);
327
+ if (!element) {
328
+ item.active = false;
329
+ item.fallback = false;
330
+ continue;
331
+ }
332
+ const rect = element.getBoundingClientRect();
333
+ const viewportHeight = typeof window !== "undefined" ? window.innerHeight : 1e3;
334
+ const isInViewport = rect.bottom > 0 && rect.top < viewportHeight;
335
+ item.active = isInViewport;
336
+ item.fallback = !isInViewport && rect.top > 0 && rect.top < viewportHeight * 2;
337
+ }
338
+ if (this.single) {
339
+ let highlightIdx = -1;
340
+ const visibleItems = this.items.map((item, idx) => ({
341
+ item,
342
+ idx
343
+ })).filter(({ item }) => item.active);
344
+ if (visibleItems.length > 0) highlightIdx = visibleItems[0].idx;
345
+ else {
346
+ const fallbackItems = this.items.map((item, idx) => ({
347
+ item,
348
+ idx
349
+ })).filter(({ item }) => item.fallback);
350
+ if (fallbackItems.length > 0) highlightIdx = fallbackItems[0].idx;
351
+ else if (this.items.length > 0) highlightIdx = 0;
352
+ }
353
+ this.items = this.items.map((item, idx) => ({
354
+ ...item,
355
+ active: idx === highlightIdx,
356
+ t: idx === highlightIdx ? Date.now() : item.t
357
+ }));
358
+ } else this.items = this.items.map((item, idx) => ({
359
+ ...item,
360
+ active: item.active,
361
+ t: item.active ? Date.now() : item.t
362
+ }));
363
+ this.onChange?.();
364
+ }
365
+ setItems(newItems) {
366
+ const observer = this.observer;
367
+ if (observer) for (const item of this.items) {
368
+ const element = document.getElementById(item.id);
369
+ if (!element) continue;
370
+ observer.unobserve(element);
371
+ }
372
+ this.items = [];
373
+ for (const item of newItems) {
374
+ const id = getItemId(item.url);
375
+ if (!id) continue;
376
+ this.items.push({
377
+ id,
378
+ active: false,
379
+ fallback: false,
380
+ t: 0,
381
+ original: item
382
+ });
383
+ }
384
+ this.watchItems();
385
+ if (typeof window !== "undefined") {
386
+ setTimeout(() => this.watchItems(), 100);
387
+ setTimeout(() => this.watchItems(), 500);
388
+ setTimeout(() => this.watchItems(), 1e3);
389
+ }
390
+ this.onChange?.();
391
+ }
392
+ watch(options) {
393
+ if (this.observer) return;
394
+ this.observer = new IntersectionObserver(this.callback.bind(this), options);
395
+ this.watchItems();
396
+ }
397
+ watchItems() {
398
+ if (!this.observer) return;
399
+ for (const item of this.items) {
400
+ const element = document.getElementById(item.id);
401
+ if (!element) continue;
402
+ this.observer.observe(element);
403
+ }
404
+ }
405
+ unwatch() {
406
+ this.observer?.disconnect();
407
+ this.observer = null;
408
+ }
409
+ };
410
+
411
+ //#endregion
412
+ //#region src/client/components/primitives/on-this-page.tsx
413
+ const ItemsContext = createContext(null);
414
+ const ScrollContext = createContext(null);
415
+ function useItems() {
416
+ const ctx = use(ItemsContext);
417
+ if (!ctx) throw new Error(`Component must be used under the <AnchorProvider /> component.`);
418
+ return ctx;
419
+ }
420
+ function useActiveAnchor() {
421
+ const items = useItems();
422
+ return useMemo(() => {
423
+ let out;
424
+ for (const item of items) {
425
+ if (!item.active) continue;
426
+ if (!out || item.t > out.t) out = item;
427
+ }
428
+ return out?.id;
429
+ }, [items]);
430
+ }
431
+ function useActiveAnchors() {
432
+ const items = useItems();
433
+ return useMemo(() => {
434
+ const out = [];
435
+ for (const item of items) if (item.active) out.push(item.id);
436
+ return out;
437
+ }, [items]);
438
+ }
439
+ /** Optional: add auto-scroll to TOC items. */
440
+ function ScrollProvider({ containerRef, children }) {
441
+ return /* @__PURE__ */ jsx(ScrollContext.Provider, {
442
+ value: containerRef,
443
+ children
444
+ });
445
+ }
446
+ function AnchorProvider({ toc, single = false, observerOptions, children }) {
447
+ const observer = useMemo(() => new Observer(), []);
448
+ const [items, setItems] = useState(observer.items);
449
+ observer.single = single;
450
+ useEffect(() => {
451
+ observer.setItems(toc);
452
+ }, [observer, toc]);
453
+ useEffect(() => {
454
+ const defaultOptions = {
455
+ rootMargin: "-80px 0% -60% 0%",
456
+ threshold: 0
457
+ };
458
+ const options = observerOptions ? {
459
+ ...defaultOptions,
460
+ ...observerOptions
461
+ } : defaultOptions;
462
+ observer.watch(options);
463
+ observer.onChange = () => setItems([...observer.items]);
464
+ return () => {
465
+ observer.unwatch();
466
+ };
467
+ }, [observer]);
468
+ return /* @__PURE__ */ jsx(ItemsContext.Provider, {
469
+ value: items,
470
+ children
471
+ });
472
+ }
473
+ const OnThisPage = ({ children, className }) => {
474
+ return /* @__PURE__ */ jsx("nav", {
475
+ className: cn("sticky top-navbar hidden xl:flex flex-col shrink-0", "w-toc", "py-4 pl-6 pr-4", className),
476
+ children
477
+ });
478
+ };
479
+ const OnThisPageHeader = ({ children, className, ...props }) => {
480
+ return /* @__PURE__ */ jsx("div", {
481
+ className: cn("mb-4 text-xs font-bold text-body", className),
482
+ ...props,
483
+ children
484
+ });
485
+ };
486
+ const OnThisPageContent = ({ children, className, ref, ...props }) => {
487
+ const internalRef = useRef(null);
488
+ useImperativeHandle(ref, () => internalRef.current);
489
+ return /* @__PURE__ */ jsx("div", {
490
+ ref: internalRef,
491
+ className: cn("relative overflow-y-auto boltdocs-otp-content pb-12", "max-h-[70%]", className),
492
+ style: {
493
+ maskImage: "linear-gradient(to bottom, black 90%, transparent 100%)",
494
+ WebkitMaskImage: "linear-gradient(to bottom, black 90%, transparent 100%)"
495
+ },
496
+ ...props,
497
+ children
498
+ });
499
+ };
500
+ OnThisPageContent.displayName = "OnThisPageContent";
501
+ const OnThisPageList = ({ children, className }) => {
502
+ return /* @__PURE__ */ jsx("ul", {
503
+ className: cn("relative space-y-0.5 text-sm border-l border-subtle", className),
504
+ children
505
+ });
506
+ };
507
+ const OnThisPageItem = ({ level, children, className }) => {
508
+ return /* @__PURE__ */ jsx("li", {
509
+ className: cn(level === 3 && "pl-3", className),
510
+ children
511
+ });
512
+ };
513
+ const OnThisPageLink = ({ children, href, active, onClick, className }) => {
514
+ const items = use(ItemsContext);
515
+ const containerRef = use(ScrollContext);
516
+ const id = href ? getItemId(href) : null;
517
+ const anchorRef = useRef(null);
518
+ const computedActive = active !== void 0 ? active : id && items ? !!items.find((i) => i.id === id)?.active : false;
519
+ useEffect(() => {
520
+ if (computedActive && anchorRef.current && containerRef?.current) scrollIntoView(anchorRef.current, {
521
+ behavior: "smooth",
522
+ block: "center",
523
+ inline: "center",
524
+ scrollMode: "if-needed",
525
+ boundary: containerRef.current
526
+ });
527
+ }, [computedActive, containerRef]);
528
+ const handleClick = (e) => {
529
+ if (onClick) onClick(e);
530
+ else if (href && href.startsWith("#")) {
531
+ e.preventDefault();
532
+ const elementId = href.slice(1);
533
+ const el = document.getElementById(elementId);
534
+ if (el) {
535
+ el.scrollIntoView({ behavior: "smooth" });
536
+ window.history.pushState(null, "", href);
537
+ }
538
+ }
539
+ };
540
+ return /* @__PURE__ */ jsx("a", {
541
+ ref: anchorRef,
542
+ href,
543
+ onClick: handleClick,
544
+ "data-active": computedActive,
545
+ className: cn("block py-0.5 pl-4 text-[13px] outline-none transition-colors", computedActive ? "text-primary-500" : "text-muted hover:text-body", className),
546
+ children
547
+ });
548
+ };
549
+ const OnThisPageIndicator = ({ style, className }) => {
550
+ const containerRef = useRef(null);
551
+ const [internalStyle, setInternalStyle] = useState({
552
+ opacity: 0,
553
+ ...style
554
+ });
555
+ useEffect(() => {
556
+ const parent = containerRef.current?.parentElement;
557
+ if (!parent) return;
558
+ const activeLinks = parent.querySelectorAll("a[data-active=\"true\"]");
559
+ if (activeLinks.length > 0) {
560
+ const firstActiveLink = activeLinks[0];
561
+ const lastActiveLink = activeLinks[activeLinks.length - 1];
562
+ const firstRect = firstActiveLink.getBoundingClientRect();
563
+ const lastRect = lastActiveLink.getBoundingClientRect();
564
+ const parentRect = parent.getBoundingClientRect();
565
+ const offsetTop = firstRect.top - parentRect.top;
566
+ const height = lastRect.bottom - firstRect.top;
567
+ setInternalStyle({
568
+ transform: `translateY(${offsetTop}px)`,
569
+ height: `${height}px`,
570
+ opacity: 1,
571
+ ...style
572
+ });
573
+ } else setInternalStyle({
574
+ opacity: 0,
575
+ ...style
576
+ });
577
+ }, [useItems(), style]);
578
+ return /* @__PURE__ */ jsx("div", {
579
+ ref: containerRef,
580
+ className: cn("absolute -left-px w-0.5 rounded-full bg-primary-500", className),
581
+ style: {
582
+ transition: "transform 180ms cubic-bezier(0.2, 0.8, 0.2, 1), height 180ms cubic-bezier(0.2, 0.8, 0.2, 1), opacity 150ms",
583
+ ...internalStyle
584
+ }
585
+ });
586
+ };
587
+ /**
588
+ * High-level automated list of toc items
589
+ */
590
+ function OnThisPageItems({ headings = [], className }) {
591
+ const activeIds = useActiveAnchors();
592
+ if (headings.length === 0) return null;
593
+ return /* @__PURE__ */ jsxs(OnThisPageList, {
594
+ className,
595
+ children: [/* @__PURE__ */ jsx(OnThisPageIndicator, {}), headings.map((h) => /* @__PURE__ */ jsx(OnThisPageItem, {
596
+ level: h.level,
597
+ children: /* @__PURE__ */ jsx(OnThisPageLink, {
598
+ href: `#${h.id}`,
599
+ active: activeIds.includes(h.id),
600
+ children: h.text
601
+ })
602
+ }, h.id))]
603
+ });
604
+ }
605
+ /**
606
+ * High-level automated Table of Contents tree
607
+ */
608
+ function OnThisPageTree({ headings = [], className }) {
609
+ const toc = useMemo(() => headings.map((h) => ({
610
+ title: h.text,
611
+ url: `#${h.id}`,
612
+ depth: h.level
613
+ })), [headings]);
614
+ const scrollContainerRef = useRef(null);
615
+ if (headings.length === 0) return null;
616
+ return /* @__PURE__ */ jsx(AnchorProvider, {
617
+ toc,
618
+ single: false,
619
+ children: /* @__PURE__ */ jsx(ScrollProvider, {
620
+ containerRef: scrollContainerRef,
621
+ children: /* @__PURE__ */ jsx(OnThisPageContent, {
622
+ ref: scrollContainerRef,
623
+ children: /* @__PURE__ */ jsx(OnThisPageItems, {
624
+ headings,
625
+ className
626
+ })
627
+ })
628
+ })
629
+ });
630
+ }
631
+ OnThisPage.Root = OnThisPage;
632
+ OnThisPage.Header = OnThisPageHeader;
633
+ OnThisPage.Content = OnThisPageContent;
634
+ OnThisPage.List = OnThisPageList;
635
+ OnThisPage.Item = OnThisPageItem;
636
+ OnThisPage.Link = OnThisPageLink;
637
+ OnThisPage.Indicator = OnThisPageIndicator;
638
+ OnThisPage.Items = OnThisPageItems;
639
+ OnThisPage.Tree = OnThisPageTree;
640
+
641
+ //#endregion
642
+ //#region src/client/components/primitives/page-nav.tsx
643
+ const PageNav = ({ children, className }) => {
644
+ return /* @__PURE__ */ jsx("nav", {
645
+ className: cn("grid sm:grid-cols-2 gap-4", className),
646
+ children
647
+ });
648
+ };
649
+ const PageNavLink = ({ children, to, direction, className }) => {
650
+ const isNext = direction === "next";
651
+ return /* @__PURE__ */ jsxs(Link, {
652
+ href: to,
653
+ className: cn("flex items-center outline-none no-underline", isNext ? "justify-end" : "justify-start", className),
654
+ children: [
655
+ !isNext && /* @__PURE__ */ jsx(ChevronLeft, { className: "shrink-0" }),
656
+ /* @__PURE__ */ jsx("div", {
657
+ className: "flex flex-col flex-1",
658
+ children
659
+ }),
660
+ isNext && /* @__PURE__ */ jsx(ChevronRight, { className: "shrink-0" })
661
+ ]
662
+ });
663
+ };
664
+ const PageNavTitle = ({ children, className }) => {
665
+ return /* @__PURE__ */ jsx("span", {
666
+ className: cn(className),
667
+ children
668
+ });
669
+ };
670
+ const PageNavDescription = ({ children, className }) => {
671
+ return /* @__PURE__ */ jsx("span", {
672
+ className: cn("truncate", className),
673
+ children
674
+ });
675
+ };
676
+ const PageNavIcon = ({ children }) => {
677
+ return /* @__PURE__ */ jsx(Fragment, { children });
678
+ };
679
+ PageNav.Root = PageNav;
680
+ PageNav.Link = PageNavLink;
681
+ PageNav.Title = PageNavTitle;
682
+ PageNav.Description = PageNavDescription;
683
+ PageNav.Icon = PageNavIcon;
684
+
685
+ //#endregion
686
+ //#region src/client/hooks/use-sidebar.ts
687
+ function useSidebar(routes) {
688
+ const config = useConfig();
689
+ const currentPath = normalizePath(useLocation().pathname);
690
+ return useMemo(() => {
691
+ const activeRoute = routes.find((r) => normalizePath(r.path) === currentPath);
692
+ const activeTabId = activeRoute?.tab?.toLowerCase();
693
+ const filteredRoutes = activeTabId ? routes.filter((r) => !r.tab || r.tab.toLowerCase() === activeTabId) : routes;
694
+ const directoryMeta = {};
695
+ if (config.directoryMeta) for (const [key, value] of Object.entries(config.directoryMeta)) {
696
+ const cleanKey = key.split("/").filter((part) => !part.startsWith("(") || !part.endsWith(")")).map((part) => part.replace(/^\d+-/, "")).join("/");
697
+ directoryMeta[cleanKey === "" ? "." : cleanKey] = value;
698
+ }
699
+ const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1).replace(/-/g, " ");
700
+ const rootNodesMap = /* @__PURE__ */ new Map();
701
+ const ungrouped = [];
702
+ const getOrCreateNode = (parts, rootStore) => {
703
+ let currentMap = rootStore;
704
+ let parentPath = "";
705
+ let lastNode = null;
706
+ for (let i = 0; i < parts.length; i++) {
707
+ const segment = parts[i];
708
+ const currentRelPath = parentPath ? `${parentPath}/${segment}` : segment;
709
+ if (!currentMap.has(segment)) {
710
+ const meta = directoryMeta[currentRelPath] || {};
711
+ const newNode = {
712
+ path: "#",
713
+ title: meta.title || capitalize(segment),
714
+ componentPath: "",
715
+ filePath: "",
716
+ icon: meta.icon,
717
+ groupPosition: typeof meta.order === "number" ? meta.order : 999,
718
+ subRoutes: []
719
+ };
720
+ currentMap.set(segment, newNode);
721
+ }
722
+ lastNode = currentMap.get(segment);
723
+ if (!lastNode._subMap) lastNode._subMap = /* @__PURE__ */ new Map();
724
+ currentMap = lastNode._subMap;
725
+ parentPath = currentRelPath;
726
+ }
727
+ return lastNode;
728
+ };
729
+ const sortedRoutes = [...filteredRoutes].sort((a, b) => {
730
+ return (a.sidebarPosition ?? a.order ?? 999) - (b.sidebarPosition ?? b.order ?? 999);
731
+ });
732
+ for (const route of sortedRoutes) {
733
+ if (route.sidebarHidden) continue;
734
+ const parts = route.slugParts || [];
735
+ const fileName = route.filePath.split("/").pop() || "";
736
+ const isIndex = /^index\.mdx?$/.test(fileName);
737
+ if (parts.length === 0) {
738
+ if (route.filePath) ungrouped.push(route);
739
+ continue;
740
+ }
741
+ if (isIndex) {
742
+ const containerNode = getOrCreateNode(parts, rootNodesMap);
743
+ if (containerNode) {
744
+ containerNode.path = route.path;
745
+ containerNode.title = route.title || containerNode.title;
746
+ containerNode.icon = route.icon || containerNode.icon;
747
+ containerNode.badge = route.badge;
748
+ containerNode.sidebarPosition = route.sidebarPosition;
749
+ containerNode.frontmatter = route.frontmatter;
750
+ }
751
+ } else {
752
+ const parentNode = getOrCreateNode(parts, rootNodesMap);
753
+ if (parentNode) parentNode.subRoutes.push(route);
754
+ }
755
+ }
756
+ const finalizeTree = (nodes, currentPathPrefix = "") => {
757
+ nodes.forEach((node) => {
758
+ if (node._subMap) {
759
+ const childDirs = Array.from(node._subMap.values());
760
+ node.subRoutes = [...node.subRoutes || [], ...childDirs];
761
+ delete node._subMap;
762
+ }
763
+ if (node.subRoutes && node.subRoutes.length > 0) node.subRoutes = finalizeTree(node.subRoutes);
764
+ });
765
+ return nodes.sort((a, b) => {
766
+ const posA = a.sidebarPosition ?? a.groupPosition ?? 999;
767
+ const posB = b.sidebarPosition ?? b.groupPosition ?? 999;
768
+ if (posA !== posB) return posA - posB;
769
+ return a.title.localeCompare(b.title);
770
+ });
771
+ };
772
+ const finalizedTopNodes = finalizeTree(Array.from(rootNodesMap.values()));
773
+ finalizedTopNodes.map((node) => {
774
+ return {
775
+ slug: node.title.toLowerCase().replace(/\s+/g, "-"),
776
+ title: node.title,
777
+ icon: node.icon,
778
+ routes: [node]
779
+ };
780
+ });
781
+ return {
782
+ groups: finalizedTopNodes.map((node) => {
783
+ if (node.subRoutes && node.subRoutes.length > 0) return {
784
+ slug: node.title.toLowerCase().replace(/\s+/g, "-"),
785
+ title: node.title,
786
+ icon: node.icon,
787
+ routes: node.subRoutes
788
+ };
789
+ ungrouped.push(node);
790
+ return null;
791
+ }).filter(Boolean),
792
+ ungrouped: finalizeTree(ungrouped),
793
+ activeRoute,
794
+ activePath: currentPath,
795
+ config
796
+ };
797
+ }, [
798
+ routes,
799
+ config,
800
+ currentPath
801
+ ]);
802
+ }
803
+
804
+ //#endregion
805
+ //#region src/client/components/primitives/sidebar.tsx
806
+ let sidebarScrollPos = 0;
807
+ function getIcon(iconName) {
808
+ if (!iconName) return void 0;
809
+ const icons = {
810
+ ...icons_exports,
811
+ ...virtualIcons
812
+ };
813
+ return icons[iconName] || icons[iconName + "Icon"] || void 0;
814
+ }
815
+ /**
816
+ * Internal Badge component for links
817
+ */
818
+ const Badge = ({ badge }) => {
819
+ const colors = {
820
+ new: "bg-primary-500/10 text-primary-500 border border-primary-500/20",
821
+ updated: "bg-emerald-500/10 text-emerald-500 border border-emerald-500/20",
822
+ deprecated: "bg-danger-500/10 text-danger-500 border border-danger-500/20"
823
+ };
824
+ const text = typeof badge === "string" ? badge : badge?.text;
825
+ if (!text) return null;
826
+ return /* @__PURE__ */ jsx("span", {
827
+ className: cn("ml-auto flex h-5 items-center rounded-md text-[10px] font-bold px-1.5 py-0.5 uppercase tracking-wider", colors[text] || colors.new),
828
+ children: text
829
+ });
830
+ };
831
+ /**
832
+ * Desktop Sidebar Container
833
+ */
834
+ function SidebarRoot({ children, className }) {
835
+ return /* @__PURE__ */ jsx("aside", {
836
+ className: cn("hidden lg:flex flex-col w-sidebar sticky top-navbar h-[calc(100vh-var(--spacing-navbar))] border-r border-subtle bg-main", className),
837
+ children
838
+ });
839
+ }
840
+ /**
841
+ * Mobile Sidebar Modal
842
+ */
843
+ function SidebarMobile({ children, className }) {
844
+ const { isSidebarOpen, closeSidebar } = useUI();
845
+ return /* @__PURE__ */ jsx(RAC.ModalOverlay, {
846
+ isOpen: isSidebarOpen,
847
+ onOpenChange: (open) => !open && closeSidebar(),
848
+ isDismissable: true,
849
+ className: cn("fixed inset-0 z-50 bg-black/20 backdrop-blur-sm lg:hidden", "entering:animate-in entering:fade-in exiting:animate-out exiting:fade-out duration-300"),
850
+ children: /* @__PURE__ */ jsx(RAC.Modal, {
851
+ className: cn("fixed top-0 left-0 bottom-0 w-80 bg-main border-r border-subtle shadow-2xl outline-none", "entering:animate-in entering:slide-in-from-left exiting:animate-out exiting:slide-out-to-left duration-300", className),
852
+ children: /* @__PURE__ */ jsx(RAC.Dialog, {
853
+ className: "h-full focus:outline-none outline-none flex flex-col",
854
+ children
855
+ })
856
+ })
857
+ });
858
+ }
859
+ /**
860
+ * Shared Header for Sidebar
861
+ */
862
+ function SidebarHeader({ children, className }) {
863
+ return /* @__PURE__ */ jsx("div", {
864
+ className: cn("flex items-center justify-between p-4 border-b border-subtle", className),
865
+ children
866
+ });
867
+ }
868
+ /**
869
+ * Scrollable Content Wrapper
870
+ */
871
+ function SidebarContent({ children, className }) {
872
+ const scrollRef = useRef(null);
873
+ useLayoutEffect(() => {
874
+ if (scrollRef.current) scrollRef.current.scrollTop = sidebarScrollPos;
875
+ }, []);
876
+ useEffect(() => {
877
+ const el = scrollRef.current;
878
+ if (!el) return;
879
+ const handleScroll = () => {
880
+ sidebarScrollPos = el.scrollTop;
881
+ };
882
+ el.addEventListener("scroll", handleScroll, { passive: true });
883
+ return () => el.removeEventListener("scroll", handleScroll);
884
+ }, []);
885
+ return /* @__PURE__ */ jsx("div", {
886
+ ref: scrollRef,
887
+ className: cn("flex-1 overflow-y-auto p-4 pb-16 custom-scrollbar", className),
888
+ children: /* @__PURE__ */ jsx("nav", {
889
+ className: "flex flex-col gap-6",
890
+ children
891
+ })
892
+ });
893
+ }
894
+ /**
895
+ * Navigation Group
896
+ */
897
+ const SidebarGroup = ({ title, icon: Icon, children, className }) => {
898
+ return /* @__PURE__ */ jsxs("div", {
899
+ className,
900
+ children: [title && /* @__PURE__ */ jsxs("h4", {
901
+ className: "px-2 mb-2 flex items-center gap-2 text-[11px] font-bold uppercase tracking-widest text-muted/50",
902
+ children: [Icon && /* @__PURE__ */ jsx(Icon, { size: 12 }), title]
903
+ }), /* @__PURE__ */ jsx("div", {
904
+ className: "flex flex-col gap-0.5",
905
+ children
906
+ })]
907
+ });
908
+ };
909
+ const SidebarLink = ({ label, href, active, icon: Icon, badge, className }) => {
910
+ return /* @__PURE__ */ jsxs(Link, {
911
+ href,
912
+ className: cn("group flex items-center gap-2.5 rounded-lg px-2.5 py-1.5 text-sm transition-all outline-none", active ? "bg-primary-500/10 text-primary-500 font-medium shadow-sm" : "text-muted hover:bg-surface hover:text-body", className),
913
+ children: [
914
+ Icon && /* @__PURE__ */ jsx(Icon, {
915
+ size: 16,
916
+ className: cn(active ? "text-primary-500" : "text-muted group-hover:text-body")
917
+ }),
918
+ /* @__PURE__ */ jsx("span", {
919
+ className: "truncate",
920
+ children: label
921
+ }),
922
+ badge && /* @__PURE__ */ jsx(Badge, { badge })
923
+ ]
924
+ });
925
+ };
926
+ /**
927
+ * Nested SubGroup
928
+ */
929
+ const SidebarSubGroup = ({ label, href, active, icon: Icon, badge, isOpen, onToggle, children, className }) => {
930
+ return /* @__PURE__ */ jsxs("div", {
931
+ className: "flex flex-col gap-0.5",
932
+ children: [/* @__PURE__ */ jsxs("div", {
933
+ className: "group relative flex items-center",
934
+ children: [/* @__PURE__ */ jsx(SidebarLink, {
935
+ label,
936
+ href,
937
+ active,
938
+ icon: Icon,
939
+ badge,
940
+ className: cn("flex-1 pr-8", className)
941
+ }), /* @__PURE__ */ jsx("button", {
942
+ onClick: (e) => {
943
+ e.preventDefault();
944
+ e.stopPropagation();
945
+ onToggle();
946
+ },
947
+ className: "absolute right-1 p-1.5 text-muted hover:text-body transition-colors outline-none cursor-pointer",
948
+ children: /* @__PURE__ */ jsx(ChevronRight, {
949
+ size: 14,
950
+ className: cn("transition-transform duration-200", isOpen && "rotate-90")
951
+ })
952
+ })]
953
+ }), isOpen && /* @__PURE__ */ jsx("div", {
954
+ className: "ml-4 pl-3 border-l border-subtle/50 mt-0.5 flex flex-col gap-0.5",
955
+ children
956
+ })]
957
+ });
958
+ };
959
+ function SidebarItem({ route, activePath, activeRoute, className }) {
960
+ const localizedHref = useLocalizedTo(route.path);
961
+ const isCurrent = activePath === (localizedHref.endsWith("/") ? localizedHref.slice(0, -1) : localizedHref) || !!activeRoute?.filePath && !!route.filePath && activeRoute.filePath === route.filePath;
962
+ const hasChildren = !!route.routes?.length || !!route.subRoutes?.length;
963
+ const children = route.routes || route.subRoutes;
964
+ const [isOpen, setIsOpen] = useState(() => activePath.startsWith(localizedHref) || !!activeRoute?.filePath && !!route.filePath && activeRoute.filePath === route.filePath);
965
+ const [prevActivePath, setPrevActivePath] = useState(activePath);
966
+ if (activePath !== prevActivePath) {
967
+ setPrevActivePath(activePath);
968
+ if (activePath.startsWith(localizedHref) || !!activeRoute?.filePath && !!route.filePath && activeRoute.filePath === route.filePath) setIsOpen(true);
969
+ }
970
+ if (hasChildren) return /* @__PURE__ */ jsx(SidebarSubGroup, {
971
+ label: route.title,
972
+ href: route.path,
973
+ active: isCurrent,
974
+ icon: getIcon(route.icon),
975
+ badge: route.badge,
976
+ isOpen,
977
+ onToggle: () => setIsOpen(!isOpen),
978
+ className,
979
+ children: children?.map((subRoute) => /* @__PURE__ */ jsx(SidebarItem, {
980
+ route: subRoute,
981
+ activePath,
982
+ activeRoute
983
+ }, subRoute.path))
984
+ });
985
+ return /* @__PURE__ */ jsx(SidebarLink, {
986
+ label: route.title,
987
+ href: route.path,
988
+ active: isCurrent,
989
+ icon: getIcon(route.icon),
990
+ badge: route.badge,
991
+ className
992
+ });
993
+ }
994
+ function SidebarItems({ routes, className }) {
995
+ const { groups, ungrouped, activePath, activeRoute } = useSidebar(routes);
996
+ return /* @__PURE__ */ jsxs("div", {
997
+ className: cn("flex flex-col gap-6", className),
998
+ children: [ungrouped.length > 0 && /* @__PURE__ */ jsx(SidebarGroup, { children: ungrouped.map((route) => /* @__PURE__ */ jsx(SidebarItem, {
999
+ route,
1000
+ activePath,
1001
+ activeRoute
1002
+ }, route.path)) }), groups.map((group) => /* @__PURE__ */ jsx(SidebarGroup, {
1003
+ title: group.title,
1004
+ icon: getIcon(group.icon),
1005
+ children: group.routes.map((route) => /* @__PURE__ */ jsx(SidebarItem, {
1006
+ route,
1007
+ activePath,
1008
+ activeRoute
1009
+ }, route.path))
1010
+ }, group.title))]
1011
+ });
1012
+ }
1013
+ /**
1014
+ * Main Sidebar Export
1015
+ */
1016
+ const Sidebar = Object.assign(SidebarRoot, {
1017
+ Root: SidebarRoot,
1018
+ Mobile: SidebarMobile,
1019
+ Header: SidebarHeader,
1020
+ Content: SidebarContent,
1021
+ Group: SidebarGroup,
1022
+ Link: SidebarLink,
1023
+ SubGroup: SidebarSubGroup,
1024
+ Item: SidebarItem,
1025
+ Items: SidebarItems
1026
+ });
1027
+
1028
+ //#endregion
1029
+ //#region src/client/hooks/use-location.ts
1030
+ const useLocation$1 = () => {
1031
+ return useLocation();
1032
+ };
1033
+
1034
+ //#endregion
1035
+ //#region src/client/hooks/use-search-highlight.ts
1036
+ /**
1037
+ * Hook to highlight search terms based on the 'hl' query parameter.
1038
+ */
1039
+ function useSearchHighlight(containerSelector = ".boltdocs-page") {
1040
+ const { search } = useLocation$1();
1041
+ const query = new URLSearchParams(search).get("hl");
1042
+ useEffect(() => {
1043
+ if (!query) {
1044
+ clearHighlights(containerSelector);
1045
+ return;
1046
+ }
1047
+ const container = document.querySelector(containerSelector);
1048
+ if (!container) return;
1049
+ let rafId;
1050
+ const observer = new MutationObserver((mutations) => {
1051
+ if (mutations.some((m) => {
1052
+ const addedNodes = Array.from(m.addedNodes);
1053
+ const removedNodes = Array.from(m.removedNodes);
1054
+ return addedNodes.some((n) => !(n instanceof HTMLElement && n.hasAttribute("data-search-highlight"))) || removedNodes.some((n) => !(n instanceof HTMLElement && n.hasAttribute("data-search-highlight")));
1055
+ })) run();
1056
+ });
1057
+ function run() {
1058
+ cancelAnimationFrame(rafId);
1059
+ rafId = requestAnimationFrame(() => {
1060
+ observer.disconnect();
1061
+ clearHighlights(containerSelector);
1062
+ const terms = query.split(/\s+/).map((t) => t.trim()).filter((t) => t.length >= 2);
1063
+ if (terms.length > 0) highlightTerms(container, terms);
1064
+ observer.observe(container, {
1065
+ childList: true,
1066
+ subtree: true
1067
+ });
1068
+ });
1069
+ }
1070
+ run();
1071
+ return () => {
1072
+ cancelAnimationFrame(rafId);
1073
+ observer.disconnect();
1074
+ clearHighlights(containerSelector);
1075
+ };
1076
+ }, [
1077
+ query,
1078
+ search,
1079
+ containerSelector
1080
+ ]);
1081
+ }
1082
+ function clearHighlights(selector) {
1083
+ document.querySelectorAll(`${selector} mark[data-search-highlight]`).forEach((mark) => {
1084
+ try {
1085
+ const parent = mark.parentNode;
1086
+ if (parent && parent.contains(mark)) {
1087
+ const text = mark.textContent || "";
1088
+ parent.replaceChild(document.createTextNode(text), mark);
1089
+ }
1090
+ } catch (e) {}
1091
+ });
1092
+ }
1093
+ function highlightTerms(container, terms) {
1094
+ const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT, { acceptNode: (node) => {
1095
+ const parent = node.parentElement;
1096
+ if (parent && (parent.tagName === "SCRIPT" || parent.tagName === "STYLE" || parent.tagName === "MARK" || parent.closest("pre") || parent.closest("code"))) return NodeFilter.FILTER_REJECT;
1097
+ return NodeFilter.FILTER_ACCEPT;
1098
+ } });
1099
+ const nodes = [];
1100
+ let node;
1101
+ while (node = walker.nextNode()) nodes.push(node);
1102
+ const accentMap = {
1103
+ a: "[aáàäâã]",
1104
+ e: "[eéèëê]",
1105
+ i: "[iíìïî]",
1106
+ o: "[oóòöôõ]",
1107
+ u: "[uúùüû]",
1108
+ n: "[nñ]",
1109
+ c: "[cç]"
1110
+ };
1111
+ const prepareRegex = (term) => {
1112
+ let pattern = term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1113
+ pattern = pattern.split("").map((char) => {
1114
+ return accentMap[char.toLowerCase()] || char;
1115
+ }).join("");
1116
+ return pattern;
1117
+ };
1118
+ const combinedPattern = terms.map(prepareRegex).join("|");
1119
+ const regex = new RegExp(`(${combinedPattern})`, "gi");
1120
+ const matchRegexes = terms.map((term) => {
1121
+ const p = prepareRegex(term);
1122
+ return new RegExp(`^${p}$`, "i");
1123
+ });
1124
+ nodes.forEach((textNode) => {
1125
+ const text = textNode.textContent;
1126
+ if (text && regex.test(text)) {
1127
+ const fragment = document.createDocumentFragment();
1128
+ text.split(regex).forEach((part) => {
1129
+ if (matchRegexes.some((rx) => rx.test(part))) {
1130
+ const mark = document.createElement("mark");
1131
+ mark.textContent = part;
1132
+ mark.setAttribute("data-search-highlight", "true");
1133
+ fragment.appendChild(mark);
1134
+ } else if (part) fragment.appendChild(document.createTextNode(part));
1135
+ });
1136
+ if (textNode.parentNode) textNode.parentNode.replaceChild(fragment, textNode);
1137
+ }
1138
+ });
1139
+ }
1140
+
1141
+ //#endregion
1142
+ //#region src/client/components/ui-base/search-highlight.tsx
1143
+ /**
1144
+ * Component that enables search term highlighting on the page.
1145
+ * It doesn't render anything visible.
1146
+ */
1147
+ function SearchHighlight() {
1148
+ useSearchHighlight(".boltdocs-page");
1149
+ return null;
1150
+ }
1151
+
1152
+ //#endregion
1153
+ //#region src/client/components/primitives/docs-layout.tsx
1154
+ /**
1155
+ * Root layout shell. Renders a full-height flex column.
1156
+ *
1157
+ * Usage:
1158
+ * ```tsx
1159
+ * <DocsLayout>
1160
+ * <Navbar />
1161
+ * <DocsLayout.Body>...</DocsLayout.Body>
1162
+ * </DocsLayout>
1163
+ * ```
1164
+ */
1165
+ function DocsLayoutRoot({ children, className, style }) {
1166
+ return /* @__PURE__ */ jsx("div", {
1167
+ className: cn("h-screen flex flex-col overflow-hidden bg-main text-body", className),
1168
+ style,
1169
+ children
1170
+ });
1171
+ }
1172
+ /**
1173
+ * Horizontal flex container for sidebar + content + toc.
1174
+ */
1175
+ function Body({ children, className, style }) {
1176
+ return /* @__PURE__ */ jsx("div", {
1177
+ className: cn("mx-auto flex flex-1 w-full max-w-(--breakpoint-3xl) bg-main overflow-hidden", className),
1178
+ style,
1179
+ children
1180
+ });
1181
+ }
1182
+ /**
1183
+ * Main scrollable content area.
1184
+ */
1185
+ function Content({ children, className, style }) {
1186
+ return /* @__PURE__ */ jsx("main", {
1187
+ className: cn("boltdocs-content flex-1 min-w-0 overflow-y-auto", "contain-layout", className),
1188
+ style,
1189
+ children
1190
+ });
1191
+ }
1192
+ /**
1193
+ * MDX Content wrapper with standard page padding and max-width logic.
1194
+ */
1195
+ function ContentMdx({ children, className, style }) {
1196
+ return /* @__PURE__ */ jsxs("div", {
1197
+ className: cn("boltdocs-page mx-auto pt-4 pb-20 px-4 sm:px-8", className),
1198
+ style,
1199
+ children: [/* @__PURE__ */ jsx(SearchHighlight, {}), children]
1200
+ });
1201
+ }
1202
+ /**
1203
+ * Content header area (breadcrumbs, title, description, etc).
1204
+ */
1205
+ function Header({ children, className, style }) {
1206
+ return /* @__PURE__ */ jsx("header", {
1207
+ className: cn("mb-10", className),
1208
+ style,
1209
+ children
1210
+ });
1211
+ }
1212
+ /**
1213
+ * Footer area inside the content section (page nav).
1214
+ */
1215
+ function Footer({ children, className, style }) {
1216
+ return /* @__PURE__ */ jsx("div", {
1217
+ className: cn("mt-20", className),
1218
+ style,
1219
+ children
1220
+ });
1221
+ }
1222
+ const DocsLayout = Object.assign(DocsLayoutRoot, {
1223
+ Body,
1224
+ Content,
1225
+ ContentMdx,
1226
+ Header,
1227
+ Footer
1228
+ });
1229
+
1230
+ //#endregion
1231
+ export { Popover$1 as A, useItems as C, ErrorBoundary as D, Tabs as E, Button$1 as M, Breadcrumbs$1 as N, ErrorBoundaryFallback as O, useActiveAnchors as S, useUI as T, OnThisPage as _, SidebarContent as a, ScrollProvider as b, SidebarItem as c, SidebarMobile as d, SidebarRoot as f, AnchorProvider as g, PageNav as h, Sidebar as i, ButtonGroup as j, Menu as k, SidebarItems as l, useSidebar as m, useSearchHighlight as n, SidebarGroup as o, SidebarSubGroup as p, useLocation$1 as r, SidebarHeader as s, DocsLayout as t, SidebarLink as u, OnThisPageItems as v, UIProvider as w, useActiveAnchor as x, OnThisPageTree as y };