boltdocs 3.2.2 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/bin/boltdocs.js +20 -1
  2. package/bin/preloader.mjs +28 -0
  3. package/dist/{adapters-ByYY44Zy.mjs → adapters-BmB4TKCc.mjs} +1 -1
  4. package/dist/{adapters-DvmtpdSF.cjs → adapters-Cp1Maurn.cjs} +1 -1
  5. package/dist/audit-CLXjMzwQ.mjs +11 -0
  6. package/dist/audit-COgjnQ5n.cjs +11 -0
  7. package/dist/build-D6FfNA8m.cjs +6 -0
  8. package/dist/build-D_7SvwTh.mjs +6 -0
  9. package/dist/cache-CJE9nWLE.cjs +6 -0
  10. package/dist/cache-OY4HzIXl.mjs +6 -0
  11. package/dist/callout-oI_LCbxS.d.ts +71 -0
  12. package/dist/callout-plqx9Dw-.d.cts +71 -0
  13. package/dist/client/index.cjs +1265 -569
  14. package/dist/client/index.d.cts +3 -542
  15. package/dist/client/index.d.ts +3 -542
  16. package/dist/client/index.js +1167 -521
  17. package/dist/client/mdx.cjs +1 -1
  18. package/dist/client/mdx.d.cts +24 -2
  19. package/dist/client/mdx.d.ts +24 -2
  20. package/dist/client/mdx.js +1 -1
  21. package/dist/client/primitives.cjs +14 -4
  22. package/dist/client/primitives.d.cts +281 -38
  23. package/dist/client/primitives.d.ts +281 -38
  24. package/dist/client/primitives.js +5 -5
  25. package/dist/client/router.cjs +49 -0
  26. package/dist/client/router.d.cts +3 -0
  27. package/dist/client/router.d.ts +3 -0
  28. package/dist/client/router.js +8 -0
  29. package/dist/client/theme/reset.css +40 -4
  30. package/dist/{config-BpzaPsJj.d.cts → config-BoRlz0Ca.d.mts} +157 -14
  31. package/dist/{config-xtS0ZkMm.d.mts → config-CTsX_tGM.d.cts} +157 -14
  32. package/dist/config-Ceib-AOH.cjs +7 -0
  33. package/dist/config-DGLQsy7y.mjs +7 -0
  34. package/dist/{package-CH2ChQqw.cjs → config-files-BYHDOrKn.mjs} +1 -1
  35. package/dist/config-files-D9cdBMl2.cjs +6 -0
  36. package/dist/config-jJh8WYJI.cjs +6 -0
  37. package/dist/csp-C4LmN1ko.cjs +6 -0
  38. package/dist/csp-D6JEOqKh.mjs +6 -0
  39. package/dist/dev-B9l7fVoQ.cjs +6 -0
  40. package/dist/dev-CwOyh-wP.mjs +6 -0
  41. package/dist/{docs-layout-BdtZ9z6s.js → docs-layout-CbZ7LDRe.js} +504 -249
  42. package/dist/{docs-layout-CFWI15Id.cjs → docs-layout-vzfXed1Q.cjs} +516 -254
  43. package/dist/{doctor-BBtmNJE0.cjs → doctor-B1_YL0Wt.cjs} +1 -1
  44. package/dist/doctor-C7whl4ED.cjs +6 -0
  45. package/dist/doctor-DmQnml2k.mjs +6 -0
  46. package/dist/{generator-COepVWGi.cjs → generator-BlW45ST7.cjs} +5 -3
  47. package/dist/{generator-CcOBN5vI.mjs → generator-BwknNejd.mjs} +5 -3
  48. package/dist/{handler-XX7cLTqe.cjs → handler-CDEoKARD.cjs} +2 -2
  49. package/dist/{handler-DzQae4eA.mjs → handler-D7UyZlPm.mjs} +2 -2
  50. package/dist/{image-Bz87fCla.js → image-B-NDSDuY.js} +129 -11
  51. package/dist/{image-C4TlpMHn.cjs → image-Hnaa2bJd.cjs} +175 -9
  52. package/dist/index-C56bL-A-.d.cts +1344 -0
  53. package/dist/{sidebar-COTaMHR-.d.ts → index-CPUUKzxD.d.cts} +344 -327
  54. package/dist/{sidebar-CrEdJuHX.d.cts → index-Ci4kfOHF.d.ts} +344 -327
  55. package/dist/index-Cu9H6CRa.d.ts +1344 -0
  56. package/dist/link-CgdI6O2o.js +872 -0
  57. package/dist/{link-D1Gjkb-2.cjs → link-vZjmD-es.cjs} +406 -223
  58. package/dist/{mdx-BuO6a1f7.js → mdx-BRT71V5Q.js} +211 -168
  59. package/dist/{mdx-CD-tSjRG.cjs → mdx-D0Absdq5.cjs} +225 -169
  60. package/dist/native-BNCY7PRF.cjs +6 -0
  61. package/dist/native-Di9Fnfrv.mjs +6 -0
  62. package/dist/native-Kre2T5eS.cjs +6 -0
  63. package/dist/node/cache.cjs +1 -1
  64. package/dist/node/cache.d.cts +19 -3
  65. package/dist/node/cache.d.mts +19 -3
  66. package/dist/node/cache.mjs +1 -1
  67. package/dist/node/cli-entry.cjs +1 -9
  68. package/dist/node/cli-entry.mjs +1 -9
  69. package/dist/node/index.cjs +1 -1
  70. package/dist/node/index.d.cts +245 -17
  71. package/dist/node/index.d.mts +246 -18
  72. package/dist/node/index.mjs +1 -1
  73. package/dist/node/mdx/shiki-adapter.cjs +1 -1
  74. package/dist/node/mdx/shiki-adapter.d.cts +24 -3
  75. package/dist/node/mdx/shiki-adapter.d.mts +24 -2
  76. package/dist/node/mdx/shiki-adapter.mjs +1 -1
  77. package/dist/node-BFNCsPs3.mjs +23 -0
  78. package/dist/node-TpmWEqXM.cjs +23 -0
  79. package/dist/{package-DSSB8B5L.mjs → package-5EsGUTVl.mjs} +1 -1
  80. package/dist/package-Ca2WSiy2.cjs +6 -0
  81. package/dist/pages-external-BBw8ObVK.mjs +6 -0
  82. package/dist/pages-external-DPiPFxxP.cjs +6 -0
  83. package/dist/parser-BqTOsEUa.cjs +6 -0
  84. package/dist/parser-CGMY2lJ7.mjs +6 -0
  85. package/dist/plugin-CUmUZOLD.mjs +69 -0
  86. package/dist/plugin-Ds3RLYpy.cjs +69 -0
  87. package/dist/plugin-context-C-l90hFt.cjs +15 -0
  88. package/dist/plugin-context-wqHNSZum.mjs +15 -0
  89. package/dist/plugin-lifecycle-BAKNKOxd.cjs +6 -0
  90. package/dist/resolve-B7vWOd8R.cjs +6 -0
  91. package/dist/resolve-C2kKnk_5.mjs +6 -0
  92. package/dist/resolve-It1Iug83.cjs +6 -0
  93. package/dist/resolve-YdTrt_FG.mjs +6 -0
  94. package/dist/router-C3kygdRK.cjs +1285 -0
  95. package/dist/router-CZBxMRAH.js +987 -0
  96. package/dist/routes-BL4y79tb.mjs +6 -0
  97. package/dist/routes-C2nPecwu.cjs +6 -0
  98. package/dist/routes-U9L8psZ9.cjs +6 -0
  99. package/dist/{search-dialog-DFnlx8LO.js → search-dialog-BqkzDTq2.js} +107 -57
  100. package/dist/search-dialog-D3jtaw6w.cjs +525 -0
  101. package/dist/search-dialog-DRiXejws.js +501 -0
  102. package/dist/{search-dialog-DHqwjJuG.cjs → search-dialog-DmirOMPg.cjs} +1 -1
  103. package/dist/{search-dialog-D6TvjcuV.js → search-dialog-MmwxFMmE.js} +1 -1
  104. package/dist/{search-dialog-B1NERUNx.cjs → search-dialog-x_qHU8ty.cjs} +107 -58
  105. package/dist/server/index.cjs +1 -1
  106. package/dist/server/index.d.mts +1 -1
  107. package/dist/server/index.mjs +1 -1
  108. package/dist/update-check-BKqmYfwT.cjs +11 -0
  109. package/dist/update-check-QnrVR3q1.mjs +11 -0
  110. package/dist/utils-8lzafE49.mjs +7 -0
  111. package/dist/utils-ej6_SjIZ.cjs +7 -0
  112. package/dist/virtual-modules-Ca5tHk1X.cjs +30 -0
  113. package/dist/virtual-modules-Dlgt1fP0.mjs +30 -0
  114. package/package.json +18 -16
  115. package/src/shared/mdx-path.ts +12 -0
  116. package/src/shared/structured-data.ts +145 -0
  117. package/src/shared/types.ts +220 -16
  118. package/dist/banner-BMop1KLF.d.ts +0 -100
  119. package/dist/banner-CVD0GugR.d.cts +0 -100
  120. package/dist/cache-CO4Dy2uQ.cjs +0 -6
  121. package/dist/cache-Dk53iOo6.mjs +0 -6
  122. package/dist/config-CCXp3aXO.mjs +0 -7
  123. package/dist/config-CMd4XoFq.cjs +0 -6
  124. package/dist/config-DlGoEM9D.cjs +0 -7
  125. package/dist/csp-CRp_3U7a.cjs +0 -6
  126. package/dist/csp-oTC2ygvF.mjs +0 -6
  127. package/dist/doctor-Bv16QSrI.cjs +0 -7
  128. package/dist/doctor-DOAbSaiL.mjs +0 -7
  129. package/dist/headers-Ddwek8K7.mjs +0 -6
  130. package/dist/headers-dg4SDrjY.cjs +0 -6
  131. package/dist/link-2PzgTnaP.js +0 -673
  132. package/dist/meta-loader-C4Hu9RN9.mjs +0 -6
  133. package/dist/meta-loader-Dq1zcFnh.cjs +0 -6
  134. package/dist/node-B5hu_6qj.cjs +0 -104
  135. package/dist/node-BXtqM1uH.mjs +0 -6
  136. package/dist/node-C8725aw7.mjs +0 -104
  137. package/dist/node-aD1eisrR.cjs +0 -6
  138. package/dist/pages-external-BYa4JSda.mjs +0 -6
  139. package/dist/pages-external-XkYIs-d5.cjs +0 -6
  140. package/dist/parser-DCiEWkSk.cjs +0 -8
  141. package/dist/parser-qk9FIHJ7.mjs +0 -8
  142. package/dist/plugin-CX1OZ6jB.cjs +0 -73
  143. package/dist/plugin-CgfiWaFZ.mjs +0 -73
  144. package/dist/routes-BW6zsk7Z.mjs +0 -6
  145. package/dist/routes-BgoIB5wb.cjs +0 -6
  146. package/dist/routes-CORVxc02.cjs +0 -6
  147. package/dist/search-dialog-BRFno7HD.cjs +0 -330
  148. package/dist/search-dialog-BmxHiKwt.js +0 -312
  149. package/dist/shiki-adapter-CoQ6jyJ4.cjs +0 -6
  150. package/dist/shiki-adapter-D-aKw7PP.mjs +0 -6
  151. package/dist/utils-Crm9oPcV.mjs +0 -7
  152. package/dist/utils-D6Xtj0FZ.cjs +0 -7
  153. /package/dist/{errors-0zGHRLue.mjs → errors-N-b6Sn2G.mjs} +0 -0
  154. /package/dist/{index-1KsTDq4o.d.mts → index-lFoyzCXy.d.mts} +0 -0
  155. /package/dist/{types-generator-BXhv7Ill.cjs → types-generator-DDSA93P3.cjs} +0 -0
  156. /package/dist/{types-generator-bDPvUztF.mjs → types-generator-DG1GX1EZ.mjs} +0 -0
@@ -3,15 +3,16 @@
3
3
  * Copyright (c) 2026 Jesus Alcala
4
4
  * Licensed under the MIT License.
5
5
  */
6
- const require_link = require('./link-D1Gjkb-2.cjs');
7
- const require_image = require('./image-C4TlpMHn.cjs');
6
+ const require_router = require('./router-C3kygdRK.cjs');
7
+ const require_link = require('./link-vZjmD-es.cjs');
8
+ const require_image = require('./image-Hnaa2bJd.cjs');
8
9
  let react = require("react");
9
10
  let react_jsx_runtime = require("react/jsx-runtime");
10
11
  let react_aria_components = require("react-aria-components");
11
12
 
12
13
  //#region src/client/components/mdx/field.tsx
13
- const Field = ({ children, name, type, description, required }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
14
- className: "my-4 border border-subtle bg-surface/50 p-4 rounded-xl flex flex-col gap-1 text-sm select-none",
14
+ const Field = ({ children, name, type, description, required, className }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
15
+ className: require_link.cn("my-4 border border-subtle bg-surface/50 p-4 rounded-xl flex flex-col gap-1 text-sm select-none", className),
15
16
  children: [
16
17
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
17
18
  className: "flex items-center gap-2",
@@ -25,7 +26,7 @@ const Field = ({ children, name, type, description, required }) => /* @__PURE__
25
26
  children: type
26
27
  }),
27
28
  required && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
28
- className: "text-xs text-rose-500 font-semibold",
29
+ className: "text-xs text-danger-500 font-semibold",
29
30
  children: "required"
30
31
  })
31
32
  ]
@@ -132,8 +133,8 @@ const Typographics = {
132
133
 
133
134
  //#endregion
134
135
  //#region src/client/components/mdx/table.tsx
135
- const Table = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
136
- className: "my-6 w-full overflow-x-auto rounded-xl border border-subtle bg-surface/30",
136
+ const Table = ({ wrapperClassName, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
137
+ className: require_link.cn("my-6 w-full overflow-x-auto rounded-xl border border-subtle bg-surface/30", wrapperClassName),
137
138
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("table", {
138
139
  className: "w-full border-collapse text-left text-sm",
139
140
  ...props
@@ -167,62 +168,60 @@ const TableComponents = {
167
168
 
168
169
  //#endregion
169
170
  //#region src/client/components/mdx/callout.tsx
170
- const variantStyles = {
171
+ /**
172
+ * Default styled callout. Built on the style-neutral Callout primitive and
173
+ * themed through semantic variant tokens (`--color-{danger|success|warning|info|primary}-500`),
174
+ * so a custom theme can restyle it entirely from CSS.
175
+ */
176
+ const variantMeta = {
171
177
  note: {
172
- container: "bg-slate-500/5 dark:bg-slate-500/10 border-slate-500/40 text-slate-800 dark:text-slate-200",
173
- titleText: "text-slate-900 dark:text-slate-100",
174
- iconColor: "text-slate-500",
178
+ container: "bg-primary-500/10 border-primary-500/50",
179
+ accent: "text-primary-500",
175
180
  icon: require_link.Info,
176
181
  defaultTitle: "Note"
177
182
  },
178
183
  info: {
179
- container: "bg-indigo-500/5 dark:bg-indigo-500/10 border-indigo-500/40 text-indigo-800 dark:text-indigo-200",
180
- titleText: "text-indigo-900 dark:text-indigo-100",
181
- iconColor: "text-indigo-500",
184
+ container: "bg-info-500/10 border-info-500/50",
185
+ accent: "text-info-500",
182
186
  icon: require_link.Info,
183
187
  defaultTitle: "Info"
184
188
  },
185
189
  tip: {
186
- container: "bg-green-500/5 dark:bg-green-500/10 border-green-500/40 text-green-800 dark:text-green-200",
187
- titleText: "text-green-900 dark:text-green-100",
188
- iconColor: "text-green-500",
190
+ container: "bg-success-500/10 border-success-500/50",
191
+ accent: "text-success-500",
189
192
  icon: require_link.Lightbulb,
190
193
  defaultTitle: "Tip"
191
194
  },
192
195
  warning: {
193
- container: "bg-amber-500/5 dark:bg-amber-500/10 border-amber-500/40 text-amber-800 dark:text-amber-200",
194
- titleText: "text-amber-900 dark:text-amber-100",
195
- iconColor: "text-amber-500",
196
+ container: "bg-warning-500/10 border-warning-500/50",
197
+ accent: "text-warning-500",
196
198
  icon: require_link.AlertTriangle,
197
199
  defaultTitle: "Warning"
198
200
  },
199
201
  danger: {
200
- container: "bg-rose-500/5 dark:bg-rose-500/10 border-rose-500/40 text-rose-800 dark:text-rose-200",
201
- titleText: "text-rose-900 dark:text-rose-100",
202
- iconColor: "text-rose-500",
202
+ container: "bg-danger-500/10 border-danger-500/50",
203
+ accent: "text-danger-500",
203
204
  icon: require_link.AlertCircle,
204
205
  defaultTitle: "Danger"
205
206
  }
206
207
  };
207
- function Callout({ children, className = "", variant = "note", title, ...props }) {
208
- const styles = variantStyles[variant] || variantStyles.note;
209
- const Icon = styles.icon;
210
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
211
- className: require_link.cn("my-6 flex gap-4 p-4 rounded-xl border-2", styles.container, className),
212
- ...props,
213
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
214
- className: require_link.cn("shrink-0 pt-0.5", styles.iconColor),
208
+ function Callout({ children, className = "", variant = "note", title, iconClassName, titleClassName, bodyClassName, ...props }) {
209
+ const meta = variantMeta[variant] || variantMeta.note;
210
+ const Icon = meta.icon;
211
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_image.Callout, {
212
+ variant,
213
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
214
+ className: require_link.cn("pt-0.5", meta.accent, iconClassName),
215
215
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: "w-5 h-5 stroke-2" })
216
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
217
- className: "flex-1 text-[0.875rem] leading-[1.6]",
218
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
219
- className: require_link.cn("font-bold text-sm mb-1", styles.titleText),
220
- children: title || styles.defaultTitle
221
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
222
- className: "prose prose-neutral dark:prose-invert max-w-none [&>p]:m-0 [&>p+p]:mt-2",
223
- children
224
- })]
225
- })]
216
+ }),
217
+ title: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
218
+ className: require_link.cn("font-bold text-sm text-body", meta.accent, titleClassName),
219
+ children: title || meta.defaultTitle
220
+ }),
221
+ className: require_link.cn("my-6 rounded-xl border-2 text-body prose prose-neutral dark:prose-invert max-w-none", meta.container, className),
222
+ bodyClassName: require_link.cn("text-[0.875rem] leading-[1.6]", bodyClassName),
223
+ ...props,
224
+ children
226
225
  });
227
226
  }
228
227
 
@@ -251,109 +250,151 @@ const copyToClipboard = async (text) => {
251
250
  };
252
251
 
253
252
  //#endregion
254
- //#region src/client/components/mdx/use-code-block.ts
255
- function useCodeBlock(props) {
253
+ //#region src/client/components/mdx/use-copy-button.ts
254
+ /**
255
+ * Copy-to-clipboard state for a code block (or any copyable surface).
256
+ * `handleCopy(code)` copies the given text and shows a transient "copied"
257
+ * confirmation for 2 seconds.
258
+ */
259
+ function useCopyButton() {
256
260
  const [copied, setCopied] = (0, react.useState)(false);
257
- const [isExpanded, setIsExpanded] = (0, react.useState)(false);
258
- const [isExpandable, setIsExpandable] = (0, react.useState)(false);
259
- const [rated, setRated] = (0, react.useState)(null);
260
- const preRef = (0, react.useRef)(null);
261
261
  const timerRef = (0, react.useRef)(null);
262
- const customConfig = require_link.useConfig().integrations?.feedback?.custom;
263
- const showCodeBlockFeedback = !!(customConfig?.enabled && !props.plain);
264
- const lang = props.lang || props["data-lang"] || "";
265
- const isHighlighted = props["data-highlighted"] === "true" || typeof props.className === "string" && props.className.includes("shiki");
266
- const rawHighlightedHtml = props.highlightedHtml || props["data-highlighted-html"];
267
- const effectiveHighlightedHtml = typeof rawHighlightedHtml === "string" ? rawHighlightedHtml.replace(/<span class="line">\s*(?:<span[^>]*>\s*<\/span>)?\s*<\/span>\s*(<\/code>\s*<\/pre>)/g, "$1") : rawHighlightedHtml;
268
- const effectiveTitle = props.title || props["data-title"];
269
- const handleRate = (0, react.useCallback)(async (type) => {
270
- if (rated) return;
271
- setRated(type);
272
- try {
273
- const code = preRef.current?.textContent ?? "";
274
- const snippet = code.trim().slice(0, 100) + (code.length > 100 ? "..." : "");
275
- const blockId = `Code Block (${lang || "plain"}): \`${snippet}\``;
276
- const endpoint = customConfig?.endpoint || "/api/feedback";
277
- await fetch(endpoint, {
278
- method: "POST",
279
- headers: { "Content-Type": "application/json" },
280
- body: JSON.stringify({
281
- rating: type === "up" ? "good" : "bad",
282
- comment: `Rated code block: ${type === "up" ? "Helpful" : "Unhelpful"}`,
283
- path: window.location.pathname,
284
- title: document.title,
285
- blockId
286
- })
287
- });
288
- } catch (err) {
289
- console.error("Failed to submit code block feedback:", err);
290
- }
291
- }, [
292
- rated,
293
- lang,
294
- customConfig?.endpoint
295
- ]);
296
262
  (0, react.useEffect)(() => {
297
263
  return () => {
298
264
  if (timerRef.current) clearTimeout(timerRef.current);
299
265
  };
300
266
  }, []);
301
- const handleCopy = (0, react.useCallback)(async () => {
302
- copyToClipboard(preRef.current?.textContent ?? "");
303
- setCopied(true);
304
- if (timerRef.current) clearTimeout(timerRef.current);
305
- timerRef.current = setTimeout(() => {
306
- setCopied(false);
307
- timerRef.current = null;
308
- }, 2e3);
309
- }, []);
310
- (0, react.useEffect)(() => {
311
- const lines = (preRef.current?.textContent ?? "").trim().split("\n").length;
312
- setIsExpandable(lines > 6);
313
- }, [props.children, props.highlightedHtml]);
314
267
  return {
315
268
  copied,
269
+ handleCopy: (0, react.useCallback)((code) => {
270
+ copyToClipboard(code);
271
+ setCopied(true);
272
+ if (timerRef.current) clearTimeout(timerRef.current);
273
+ timerRef.current = setTimeout(() => {
274
+ setCopied(false);
275
+ timerRef.current = null;
276
+ }, 2e3);
277
+ }, [])
278
+ };
279
+ }
280
+
281
+ //#endregion
282
+ //#region src/client/components/mdx/use-expandable.ts
283
+ /**
284
+ * Expand / collapse behavior for long code blocks. Measures the rendered code
285
+ * through `preRef` and exposes whether the block is expandable, whether it
286
+ * should be visually truncated, and a toggle handler.
287
+ */
288
+ function useExpandable(options = {}) {
289
+ const { children, highlightedHtml, maxLines = 6 } = options;
290
+ const [isExpanded, setIsExpanded] = (0, react.useState)(false);
291
+ const [isExpandable, setIsExpandable] = (0, react.useState)(false);
292
+ const preRef = (0, react.useRef)(null);
293
+ const shouldTruncate = isExpandable && !isExpanded;
294
+ const toggle = () => setIsExpanded((prev) => !prev);
295
+ (0, react.useEffect)(() => {
296
+ const node = preRef.current;
297
+ if (!node) {
298
+ setIsExpandable(false);
299
+ return;
300
+ }
301
+ const lines = (node.textContent ?? "").trim().split("\n").length;
302
+ const hasOverflow = "scrollHeight" in node && "clientHeight" in node && Number(node.scrollHeight) > Number(node.clientHeight);
303
+ setIsExpandable(lines > maxLines || hasOverflow);
304
+ }, [
305
+ children,
306
+ highlightedHtml,
307
+ maxLines
308
+ ]);
309
+ return {
316
310
  isExpanded,
317
311
  setIsExpanded,
318
312
  isExpandable,
319
- preRef,
320
- handleCopy,
321
- shouldTruncate: isExpandable && !isExpanded,
322
- isHighlighted,
323
- effectiveHighlightedHtml,
324
- effectiveTitle,
325
- lang,
326
- showCodeBlockFeedback,
313
+ shouldTruncate,
314
+ toggle,
315
+ preRef
316
+ };
317
+ }
318
+
319
+ //#endregion
320
+ //#region src/client/components/mdx/use-code-block-feedback.ts
321
+ /**
322
+ * Thumbs-up / thumbs-down feedback for code blocks. Only enabled when the
323
+ * `feedback.custom` integration is configured in the site config. The submit
324
+ * behavior can be overridden via `submitFeedback`.
325
+ */
326
+ function useCodeBlockFeedback(options = {}) {
327
+ const { plain = false, lang = "", submitFeedback } = options;
328
+ const [rated, setRated] = (0, react.useState)(null);
329
+ const customConfig = require_link.useConfig().integrations?.feedback?.custom;
330
+ const enabled = !!(customConfig?.enabled && !plain);
331
+ return {
327
332
  rated,
328
- handleRate
333
+ handleRate: (0, react.useCallback)(async (type, code) => {
334
+ if (rated) return;
335
+ setRated(type);
336
+ const snippet = code ? code.trim().slice(0, 100) + (code.length > 100 ? "..." : "") : "";
337
+ const blockId = `Code Block (${lang || "plain"}): \`${snippet}\``;
338
+ const payload = {
339
+ rating: type === "up" ? "good" : "bad",
340
+ comment: `Rated code block: ${type === "up" ? "Helpful" : "Unhelpful"}`,
341
+ path: window.location.pathname,
342
+ title: document.title,
343
+ blockId,
344
+ lang,
345
+ snippet
346
+ };
347
+ try {
348
+ if (submitFeedback) {
349
+ await submitFeedback(payload);
350
+ return;
351
+ }
352
+ const endpoint = customConfig?.endpoint || "/api/feedback";
353
+ await fetch(endpoint, {
354
+ method: "POST",
355
+ headers: { "Content-Type": "application/json" },
356
+ body: JSON.stringify(payload)
357
+ });
358
+ } catch (err) {
359
+ console.error("Failed to submit code block feedback:", err);
360
+ }
361
+ }, [
362
+ rated,
363
+ lang,
364
+ customConfig?.endpoint,
365
+ submitFeedback
366
+ ]),
367
+ enabled
329
368
  };
330
369
  }
331
370
 
332
371
  //#endregion
333
372
  //#region src/client/components/mdx/code-block.tsx
334
- const CopyButton = ({ copied, handleCopy }) => {
373
+ const CopyButton = ({ copied, onCopy, className }) => {
335
374
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_image.Tooltip, {
336
375
  content: copied ? "Copied!" : "Copy code",
337
376
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_aria_components.Button, {
338
- onPress: handleCopy,
339
- className: require_link.cn("grid place-items-center size-8 bg-transparent outline-none cursor-pointer transition-all duration-200 hover:scale-110 active:scale-95 [&>svg]:size-4 [&>svg]:stroke-2 z-10", copied ? "text-emerald-400" : "text-muted hover:text-body"),
377
+ onPress: onCopy,
378
+ className: require_link.cn("grid place-items-center size-8 bg-transparent outline-none cursor-pointer transition-all duration-200 hover:scale-110 active:scale-95 [&>svg]:size-4 [&>svg]:stroke-2 z-10", copied ? "text-emerald-400" : "text-muted hover:text-body", className),
340
379
  "aria-label": "Copy code",
341
380
  children: copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Check, { size: 20 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_link.Copy, { size: 20 })
342
381
  })
343
382
  });
344
383
  };
345
- const CodeBlockFeedback = ({ rated, onRate }) => {
384
+ const CodeBlockFeedback = ({ rated, onRate, className }) => {
346
385
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
347
- className: "flex items-center gap-0.5 border-r border-subtle pr-1.5 mr-1",
386
+ className: require_link.cn("flex items-center gap-0.5 border-r border-subtle pr-1.5 mr-1", className),
348
387
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_image.Tooltip, {
349
388
  content: rated === "up" ? "Helpful!" : "This code is helpful",
350
389
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_aria_components.Button, {
351
- onPress: (() => onRate("up")),
390
+ onPress: () => onRate("up"),
352
391
  isDisabled: rated !== null,
353
392
  className: require_link.cn("grid place-items-center size-8 bg-transparent outline-none cursor-pointer transition-all duration-200 hover:scale-110 active:scale-95 [&>svg]:size-4 [&>svg]:stroke-2 z-10", rated === "up" ? "text-emerald-500 dark:text-emerald-400" : rated === "down" ? "opacity-30 cursor-not-allowed text-muted" : "text-muted hover:text-body"),
354
393
  "aria-label": "Mark as helpful",
355
394
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
356
395
  xmlns: "http://www.w3.org/2000/svg",
396
+ role: "img",
397
+ "aria-label": "Thumb up",
357
398
  viewBox: "0 0 24 24",
358
399
  fill: "none",
359
400
  stroke: "currentColor",
@@ -366,12 +407,14 @@ const CodeBlockFeedback = ({ rated, onRate }) => {
366
407
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_image.Tooltip, {
367
408
  content: rated === "down" ? "Unhelpful" : "This code is unhelpful",
368
409
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_aria_components.Button, {
369
- onPress: (() => onRate("down")),
410
+ onPress: () => onRate("down"),
370
411
  isDisabled: rated !== null,
371
412
  className: require_link.cn("grid place-items-center size-8 bg-transparent outline-none cursor-pointer transition-all duration-200 hover:scale-110 active:scale-95 [&>svg]:size-4 [&>svg]:stroke-2 z-10", rated === "down" ? "text-rose-500 dark:text-rose-400" : rated === "up" ? "opacity-30 cursor-not-allowed text-muted" : "text-muted hover:text-body"),
372
413
  "aria-label": "Mark as unhelpful",
373
414
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
374
415
  xmlns: "http://www.w3.org/2000/svg",
416
+ role: "img",
417
+ "aria-label": "Thumb down",
375
418
  viewBox: "0 0 24 24",
376
419
  fill: "none",
377
420
  stroke: "currentColor",
@@ -385,49 +428,51 @@ const CodeBlockFeedback = ({ rated, onRate }) => {
385
428
  });
386
429
  };
387
430
  function CodeBlock(props) {
388
- const { children, hideCopy = false, highlightedHtml, "data-highlighted-html": dataHighlightedHtml, title, "data-title": dataTitle, "data-lang": dataLang, plain = false, lineNumbers, showLineNumbers, wordWrap, "word-wrap": wordWrapHyphen, metastring, ...rest } = props;
389
- const { className: shikiClassName, ...cleanRest } = rest;
390
- const { copied, isExpanded, setIsExpanded, isExpandable, preRef, handleCopy, shouldTruncate, isHighlighted, effectiveHighlightedHtml, effectiveTitle, showCodeBlockFeedback, rated, handleRate } = useCodeBlock(props);
431
+ const { children, hideCopy = false, highlightedHtml, "data-highlighted-html": dataHighlightedHtml, "data-highlighted": dataHighlighted, title, "data-title": dataTitle, lang: langProp, "data-lang": dataLang, plain = false, className: shikiClassName, lineNumbers, showLineNumbers, wordWrap, "word-wrap": wordWrapHyphen, metastring, feedbackClassName, copyButtonClassName, ...rest } = props;
432
+ const lang = langProp || dataLang || "";
433
+ const isHighlighted = dataHighlighted === "true" || typeof shikiClassName === "string" && shikiClassName.includes("shiki");
434
+ const rawHighlightedHtml = highlightedHtml || dataHighlightedHtml;
435
+ const effectiveHighlightedHtml = typeof rawHighlightedHtml === "string" ? rawHighlightedHtml.replace(/<span class="line">\s*(?:<span[^>]*>\s*<\/span>)?\s*<\/span>\s*(<\/code>\s*<\/pre>)/g, "$1") : rawHighlightedHtml;
436
+ const effectiveTitle = title || dataTitle;
437
+ const { copied, handleCopy } = useCopyButton();
438
+ const { isExpanded, isExpandable, shouldTruncate, toggle, preRef } = useExpandable({
439
+ children,
440
+ highlightedHtml: effectiveHighlightedHtml
441
+ });
442
+ const { rated, handleRate, enabled: showCodeBlockFeedback } = useCodeBlockFeedback({
443
+ plain,
444
+ lang
445
+ });
446
+ const onCopy = () => handleCopy(preRef.current?.textContent ?? "");
447
+ const onRate = (type) => handleRate(type, preRef.current?.textContent ?? "");
391
448
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_image.CodeBlock, {
392
449
  plain,
393
- className: props.className,
450
+ className: shikiClassName,
394
451
  children: [(effectiveTitle || !hideCopy) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_image.CodeBlockHeader, {
395
452
  className: require_link.cn({ "absolute top-2 left-0 w-full": !effectiveTitle }),
396
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_image.CodeBlockGroup, { children: effectiveTitle && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: effectiveTitle }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
397
- className: "flex items-center gap-1 bg-(--color-code-bg) pl-2 z-10",
398
- children: [showCodeBlockFeedback && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeBlockFeedback, {
399
- rated,
400
- onRate: handleRate
401
- }), !hideCopy && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyButton, {
402
- copied,
403
- handleCopy
404
- })]
405
- })]
453
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_image.CodeBlockGroup, { children: effectiveTitle && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: effectiveTitle }) }), (showCodeBlockFeedback || !hideCopy) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_image.CodeBlockActions, { children: [showCodeBlockFeedback && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CodeBlockFeedback, {
454
+ rated,
455
+ onRate,
456
+ className: feedbackClassName
457
+ }), !hideCopy && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopyButton, {
458
+ copied,
459
+ onCopy,
460
+ className: copyButtonClassName
461
+ })] })]
406
462
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_image.CodeBlockContent, {
407
463
  shouldTruncate,
408
- children: [effectiveHighlightedHtml ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
409
- ref: preRef,
410
- className: "shiki-wrapper overflow-x-auto [&>pre]:m-0! [&>pre]:rounded-none! [&>pre]:border-none! [&>pre]:bg-inherit! [&>pre>code]:grid! [&>pre>code]:p-5! [&>pre>code]:text-[0.875rem]! [&>pre>code]:leading-[1.6]! [&>.shiki.shiki-themes]:bg-transparent!",
411
- dangerouslySetInnerHTML: { __html: effectiveHighlightedHtml }
412
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
464
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_image.CodeBlockPre, {
413
465
  ref: preRef,
414
- className: require_link.cn("m-0! rounded-none! border-none! bg-transparent!", "text-[0.875rem] leading-[1.6] overflow-x-auto", shikiClassName, {
415
- "p-0! [&>code]:grid! [&>code]:p-5! [&>code]:bg-transparent!": isHighlighted,
416
- "p-5!": !isHighlighted
417
- }),
418
- ...cleanRest,
466
+ highlightedHtml: effectiveHighlightedHtml,
467
+ isHighlighted,
468
+ className: shikiClassName,
469
+ ...rest,
419
470
  children
420
- }), isExpandable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
421
- className: require_link.cn({
422
- "absolute bottom-0 inset-x-0 h-32 flex items-end justify-center pb-4 z-10": shouldTruncate,
423
- "relative flex justify-center pb-4 pt-1 -mt-4": !shouldTruncate
424
- }),
425
- style: shouldTruncate ? { backgroundImage: "linear-gradient(to top, var(--color-code-bg) 10%, transparent)" } : void 0,
426
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_aria_components.Button, {
427
- onPress: () => setIsExpanded(!isExpanded),
428
- className: "rounded-full bg-surface border border-subtle px-5 py-2 text-[0.8125rem] font-medium text-body outline-none cursor-pointer transition-all hover:bg-soft hover:-translate-y-px backdrop-blur-md",
429
- children: isExpanded ? "Show less" : "Expand code"
430
- })
471
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_image.CodeBlockExpand, {
472
+ isExpandable,
473
+ shouldTruncate,
474
+ isExpanded,
475
+ onToggle: toggle
431
476
  })]
432
477
  })]
433
478
  });
@@ -435,15 +480,15 @@ function CodeBlock(props) {
435
480
 
436
481
  //#endregion
437
482
  //#region src/client/components/mdx/image.tsx
438
- const Image = ({ src, alt, title, theme, className, ...props }) => {
483
+ const Image = ({ src, alt, title, theme, className, figureClassName, figureInnerClassName, figcaptionClassName, ...props }) => {
439
484
  const { theme: themeContext } = require_image.useTheme();
440
485
  if (!src) return null;
441
486
  if (theme !== themeContext) return null;
442
487
  const caption = title || alt;
443
488
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("figure", {
444
- className: "my-6 sm:my-8 flex flex-col items-center justify-center group not-prose",
489
+ className: require_link.cn("my-6 sm:my-8 flex flex-col items-center justify-center group not-prose", figureClassName),
445
490
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
446
- className: "relative w-full overflow-hidden rounded-lg sm:rounded-2xl border border-subtle bg-soft/30 transition-all duration-300 sm:max-w-[85%] lg:max-w-full",
491
+ className: require_link.cn("relative w-full overflow-hidden rounded-lg sm:rounded-2xl border border-subtle bg-soft/30 transition-all duration-300 sm:max-w-[85%] lg:max-w-full", figureInnerClassName),
447
492
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_image.Image, {
448
493
  src,
449
494
  alt: alt || "",
@@ -454,7 +499,7 @@ const Image = ({ src, alt, title, theme, className, ...props }) => {
454
499
  ...props
455
500
  })
456
501
  }), caption && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("figcaption", {
457
- className: "mt-2 sm:mt-3 text-center text-xs sm:text-sm text-muted font-medium select-none tracking-wide opacity-90 sm:opacity-80 group-hover:opacity-100 transition-opacity duration-300 px-2",
502
+ className: require_link.cn("mt-2 sm:mt-3 text-center text-xs sm:text-sm text-muted font-medium select-none tracking-wide opacity-90 sm:opacity-80 group-hover:opacity-100 transition-opacity duration-300 px-2", figcaptionClassName),
458
503
  children: caption
459
504
  })]
460
505
  });
@@ -466,7 +511,7 @@ const ImageComponents = {
466
511
 
467
512
  //#endregion
468
513
  //#region src/client/components/mdx/card.tsx
469
- function Card({ className, title, icon, href, children, ...props }) {
514
+ function Card({ className, title, icon, href, children, headerClassName, iconClassName, titleClassName, bodyClassName, ...props }) {
470
515
  const cardRef = (0, react.useRef)(null);
471
516
  const handleMouseMove = (e) => {
472
517
  if (!cardRef.current) return;
@@ -477,7 +522,7 @@ function Card({ className, title, icon, href, children, ...props }) {
477
522
  cardRef.current.style.setProperty("--mouse-y", `${y}px`);
478
523
  };
479
524
  const Wrapper = href ? "a" : "div";
480
- const spotlightColor = "var(--color-primary-500, #eb5828)";
525
+ const spotlightColor = "var(--color-primary-500)";
481
526
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Wrapper, {
482
527
  ref: cardRef,
483
528
  href,
@@ -500,17 +545,17 @@ function Card({ className, title, icon, href, children, ...props }) {
500
545
  }
501
546
  }),
502
547
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
503
- className: "relative z-10 flex items-center gap-3",
548
+ className: require_link.cn("relative z-10 flex items-center gap-3", headerClassName),
504
549
  children: [icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
505
- className: require_link.cn("shrink-0 transition-transform duration-500 group-hover:rotate-15 group-hover:scale-110 flex items-center justify-center text-muted group-hover:text-primary-500", "[&>svg]:w-6 [&>svg]:h-6 [&>svg]:stroke-[1.5]"),
550
+ className: require_link.cn("shrink-0 transition-transform duration-500 group-hover:rotate-15 group-hover:scale-110 flex items-center justify-center text-muted group-hover:text-primary-500", "[&>svg]:w-6 [&>svg]:h-6 [&>svg]:stroke-[1.5]", iconClassName),
506
551
  children: icon
507
552
  }), title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
508
- className: "font-semibold text-base m-0 leading-none text-body",
553
+ className: require_link.cn("font-semibold text-base m-0 leading-none text-body", titleClassName),
509
554
  children: title
510
555
  })]
511
556
  }),
512
557
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
513
- className: "relative z-10 text-[0.875rem] leading-[1.6] opacity-90 prose prose-neutral dark:prose-invert max-w-none [&>p]:m-0 [&>p+p]:mt-2",
558
+ className: require_link.cn("relative z-10 text-[0.875rem] leading-[1.6] opacity-90 prose prose-neutral dark:prose-invert max-w-none [&>p]:m-0 [&>p+p]:mt-2", bodyClassName),
514
559
  children
515
560
  })
516
561
  ]
@@ -538,7 +583,7 @@ function Cards({ children, className, cols = 2, ...props }) {
538
583
  * A subtle display for when the page was last updated.
539
584
  * Small, opaque, and positioned at the bottom of the content with a thin top border divider.
540
585
  */
541
- function LastUpdated({ date }) {
586
+ function LastUpdated({ date, className }) {
542
587
  if (!date) return null;
543
588
  const d = new Date(date);
544
589
  if (Number.isNaN(d.getTime())) return null;
@@ -548,7 +593,7 @@ function LastUpdated({ date }) {
548
593
  day: "numeric"
549
594
  });
550
595
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
551
- className: "mt-16 pt-6 border-t border-subtle flex items-center justify-between text-xs text-muted select-none",
596
+ className: require_link.cn("mt-16 pt-6 border-t border-subtle flex items-center justify-between text-xs text-muted select-none", className),
552
597
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
553
598
  className: "italic",
554
599
  children: ["Last updated on ", formattedDate]
@@ -672,18 +717,17 @@ const VARIANT_DEFAULT_ICON = {
672
717
  warning: require_link.AlertTriangle,
673
718
  danger: require_link.AlertCircle
674
719
  };
675
- function TimelineRoot({ children, className, compact = false, ...props }) {
720
+ function TimelineRoot({ children, className, compact = false, connectorClassName, ...props }) {
676
721
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ol", {
677
- role: "list",
678
722
  className: require_link.cn("relative my-8 ms-3", compact ? "space-y-3" : "space-y-7", className),
679
723
  ...props,
680
724
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
681
725
  "aria-hidden": "true",
682
- className: "pointer-events-none absolute top-3 bottom-3 start-[5.5px] w-px bg-subtle"
726
+ className: require_link.cn("pointer-events-none absolute top-3 bottom-3 start-[5.5px] w-px bg-subtle", connectorClassName)
683
727
  }), children]
684
728
  });
685
729
  }
686
- function TimelineItem({ date, title, badge, icon, variant = "primary", locale, className, children, ...props }) {
730
+ function TimelineItem({ date, title, badge, icon, variant = "primary", locale, className, children, dotClassName, headerClassName, timeClassName, badgeClassName, titleClassName, bodyClassName, ...props }) {
687
731
  const palette = VARIANT_PALETTE[variant] ?? VARIANT_PALETTE.primary;
688
732
  const formatted = formatDate(date, locale);
689
733
  const badgeCfg = normalizeBadge(badge);
@@ -707,26 +751,26 @@ function TimelineItem({ date, title, badge, icon, variant = "primary", locale, c
707
751
  children: [
708
752
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
709
753
  ...a11yProps,
710
- className: require_link.cn("absolute start-0 top-1 flex items-center justify-center w-3 h-3 rounded-full", "bg-surface border-2 shadow-sm", palette.ring),
754
+ className: require_link.cn("absolute start-0 top-1 flex items-center justify-center w-3 h-3 rounded-full", "bg-surface border-2 shadow-sm", palette.ring, dotClassName),
711
755
  children: dot
712
756
  }),
713
757
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
714
- className: "flex items-center gap-2 flex-wrap mb-1",
758
+ className: require_link.cn("flex items-center gap-2 flex-wrap mb-1", headerClassName),
715
759
  children: [formatted && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("time", {
716
760
  dateTime: date instanceof Date ? date.toISOString() : new Date(date).toISOString(),
717
- className: "text-[11px] uppercase tracking-wider font-mono tabular-nums text-muted select-none",
761
+ className: require_link.cn("text-[11px] uppercase tracking-wider font-mono tabular-nums text-muted select-none", timeClassName),
718
762
  children: formatted
719
763
  }), badgeCfg && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
720
- className: require_link.cn("inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-bold uppercase tracking-wide border", palette.badgeBg, palette.badgeText, palette.badgeBorder),
764
+ className: require_link.cn("inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-bold uppercase tracking-wide border", palette.badgeBg, palette.badgeText, palette.badgeBorder, badgeClassName),
721
765
  children: badgeCfg.text
722
766
  })]
723
767
  }),
724
768
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
725
- className: "text-base font-semibold text-body m-0 leading-snug",
769
+ className: require_link.cn("text-base font-semibold text-body m-0 leading-snug", titleClassName),
726
770
  children: title
727
771
  }),
728
772
  children && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
729
- className: "mt-2 text-[0.9rem] leading-[1.6] text-paragraph prose prose-neutral dark:prose-invert max-w-none [&>p]:m-0 [&>p+p]:mt-2 [&_a]:text-primary-500 [&_a]:no-underline hover:[&_a]:underline",
773
+ className: require_link.cn("mt-2 text-[0.9rem] leading-[1.6] text-paragraph prose prose-neutral dark:prose-invert max-w-none [&>p]:m-0 [&>p+p]:mt-2 [&_a]:text-primary-500 [&_a]:no-underline hover:[&_a]:underline", bodyClassName),
730
774
  children
731
775
  })
732
776
  ]
@@ -768,9 +812,21 @@ Object.defineProperty(exports, 'mdx_components_default', {
768
812
  return mdx_components_default;
769
813
  }
770
814
  });
771
- Object.defineProperty(exports, 'useCodeBlock', {
815
+ Object.defineProperty(exports, 'useCodeBlockFeedback', {
816
+ enumerable: true,
817
+ get: function () {
818
+ return useCodeBlockFeedback;
819
+ }
820
+ });
821
+ Object.defineProperty(exports, 'useCopyButton', {
822
+ enumerable: true,
823
+ get: function () {
824
+ return useCopyButton;
825
+ }
826
+ });
827
+ Object.defineProperty(exports, 'useExpandable', {
772
828
  enumerable: true,
773
829
  get: function () {
774
- return useCodeBlock;
830
+ return useExpandable;
775
831
  }
776
832
  });
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Boltdocs - https://boltdocs.vercel.app
3
+ * Copyright (c) 2026 Jesus Alcala
4
+ * Licensed under the MIT License.
5
+ */
6
+ const e=require(`./chunk-D1Md3oWO.cjs`),t=require(`./utils-ej6_SjIZ.cjs`),n=require(`./errors-vKw8CkiX.cjs`),r=require(`./cache-CJE9nWLE.cjs`);let i=require(`node:path`);i=e.r(i);function a(e){return(e||``).replace(/\\/g,`/`).split(`/`).filter(Boolean)}function o(e,t){return t.length>0&&t.every((t,n)=>e[n]===t)}function s(e,t){let n=t?.versions;if(!n)return{publicSegments:[],consumed:0};let r=n.prefix||``,i=a(r);for(let t of n.versions){let n=a(t.path);if(n.length===0)continue;if(o(e,n))return{version:t.path,publicSegments:n,consumed:n.length};let s=[...i,...n];if(o(e,s))return{version:t.path,publicSegments:s,consumed:s.length};if(r&&!r.includes(`/`)&&e[0]===`${r}${t.path}`)return{version:t.path,publicSegments:[`${r}${t.path}`],consumed:1}}return{publicSegments:[],consumed:0}}function c(e,n,r,a,o){let c=i.default.relative(n,e).replace(/\\/g,`/`),l=c.split(`/`).filter(Boolean),u,d,f,p,m=s(l,a);if(d=m.version,l=l.slice(m.consumed),a?.i18n&&l.length>0){let e=l[0];(Array.isArray(a.i18n.locales)?a.i18n.locales.includes(e):a.i18n.locales[e])&&(u=e,l=l.slice(1))}if(l.length>0){let e=l[0].match(/^\((.+)\)$/);e&&(f=e[1].toLowerCase(),l=l.slice(1))}if(l.length>0){let e=l[0].match(/^\[(.+)\]$/);e&&(p=e[1].toLowerCase(),l=l.slice(1))}let h=[...l],g=l.map(e=>t.h(e)).join(`/`),_=o?o.startsWith(`/`)?o:`/${o}`:t.a(g||`index.md`),v=r.replace(/\\/g,`/`).replace(/\/$/,``)||`/`,y=[...m.publicSegments,u,!o&&!p?f:void 0].filter(Boolean),b=(p?[...y,p,_]:[v,...y,_]).join(`/`).replace(/\\/g,`/`).replace(/\/+/g,`/`).replace(/\/$/,``)||`/`;return{relativePath:c,finalPath:b.startsWith(`/`)?b:`/${b}`,remainingParts:h,locale:u,version:d,inferredTab:f,subRouteGroup:void 0,collection:p}}const l=[`og:`,`twitter:`,`article:`,`music:`,`video:`,`profile:`,`book:`],u=[`noindex`,`robots`,`canonical`,`keywords`,`author`];function d(e){let t={};e.seo&&typeof e.seo==`object`&&Object.assign(t,e.seo);for(let n of Object.keys(e))(u.includes(n)||l.some(e=>n.startsWith(e)))&&(t[n]=e[n]);return e.hidden===!0&&t.noindex===void 0&&(t.noindex=!0),Object.keys(t).length>0?t:void 0}function f(e){return{title:e.title?t.p(String(e.title)):void 0,badge:e.badge?t.p(String(e.badge)):void 0,description:e.description?t.p(String(e.description)):void 0}}function p(e,n){if(e.groupPosition!==void 0)return e.groupPosition;if(e.sidebarPosition!==void 0)return e.sidebarPosition;if(n.remainingParts.length<=1)return;let r=t.i(n.remainingParts[n.remainingParts.length-2]);return r===void 0?void 0:Number(r)}function m(e){let r;try{r=decodeURIComponent(e)}catch{throw t.l(`SECURITY_ERROR`,`Invalid encoding in path`,{file:e}),new n.t(`Security breach: Invalid characters or encoding in path`)}if(r.length>260)throw new n.n(`Path length exceeds limit`);return r}function h(e,r){let a=e.replace(/\\/g,`/`),o=r.replace(/\\/g,`/`),s=m(a),c=i.default.resolve(s),l=i.default.resolve(o);if(i.default.sep===`/`){let e=e=>{let t=e.replace(/\\/g,`/`);return/^[a-zA-Z]:/.test(t)&&(t=t.replace(/^[a-zA-Z]:/,``)),i.default.resolve(t)};c=e(s),l=e(o)}let u=i.default.relative(l,c).replace(/\\/g,`/`);if(u.startsWith(`../`)||u!==`.`&&!t._.test(u))throw new n.n(`Security breach: File is outside of docs directory, contains null bytes, or invalid path characters: ${i.default.basename(s)}`);return{normalizedFile:a,normalizedDocsDir:o,relativePath:u}}async function g(e,n,a,o,s,l){let u=l??r.t,{normalizedFile:m,normalizedDocsDir:g}=h(e,a),_=n.frontmatter??{},v=c(i.default.resolve(m),i.default.resolve(g),o,s,_.permalink),y=f(_),b=d(_),x=i.default.basename(v.relativePath),S=t.h(x),C=v.remainingParts.map(e=>t.h(e)).slice(0,-1),w=/^_?index\.mdx?$/.test(S),T=_.sidebarPosition??t.i(x),E=C.join(`/`),D=_.description?t.p(String(_.description)).trim():n.description,O={route:{path:v.finalPath,componentPath:e,filePath:v.relativePath,title:y.title||t.h(i.default.basename(m,i.default.extname(m))),description:D,sidebarPosition:T,headings:n.headings,locale:v.locale,version:v.version,badge:y.badge,icon:_.icon?String(_.icon):void 0,tab:v.inferredTab,subRouteGroup:v.subRouteGroup,slugParts:C,_content:n.plainText,_rawContent:n.content,date:_.date,lastUpdated:_.lastUpdated,category:_.category,order:_.order,sidebarLabel:_.sidebarLabel,sidebarHidden:_.sidebarHidden||_.hidden,seo:b,frontmatter:_,collection:v.collection,tags:_.tags,author:typeof _.author==`string`?_.author:_.author?.name,draft:_.draft,excerpt:_.excerpt,coverImage:_.coverImage||_.cover},relativeDir:v.collection?void 0:E||void 0,isGroupIndex:w,inferredTab:v.inferredTab,inferredCollection:v.collection,groupMeta:w?{title:_.groupTitle||y.title||(C.length>0?t.t(C[C.length-1]):``),position:p(_,v),icon:_.icon?String(_.icon):void 0}:void 0,inferredGroupPosition:v.remainingParts.length>1?t.i(v.remainingParts[v.remainingParts.length-2]):void 0};return await u.set(e,O),O}Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return g}});