boltdocs 2.7.10 → 2.8.0

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