boltdocs 3.3.5 → 3.4.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 (126) hide show
  1. package/dist/{adapters-BKzKe2mO.mjs → adapters-BXiBWAKs.mjs} +1 -1
  2. package/dist/{adapters-DwDTQoCG.cjs → adapters-Czl3WtQt.cjs} +1 -1
  3. package/dist/{build-B672n0hL.cjs → build-CNkXRdk8.cjs} +1 -1
  4. package/dist/{build-BVoMHMhw.mjs → build-CqUBsXVC.mjs} +1 -1
  5. package/dist/client/index.cjs +245 -56
  6. package/dist/client/index.d.cts +3 -3
  7. package/dist/client/index.d.ts +3 -3
  8. package/dist/client/index.js +246 -60
  9. package/dist/client/mdx.cjs +1 -1
  10. package/dist/client/mdx.js +1 -1
  11. package/dist/client/primitives.cjs +5 -5
  12. package/dist/client/primitives.d.cts +92 -42
  13. package/dist/client/primitives.d.ts +101 -51
  14. package/dist/client/primitives.js +4 -4
  15. package/dist/client/router.cjs +1 -1
  16. package/dist/client/router.d.cts +1 -1
  17. package/dist/client/router.d.ts +1 -1
  18. package/dist/client/router.js +1 -1
  19. package/dist/client/theme/reset.css +41 -0
  20. package/dist/config-B3SEoVjG.cjs +7 -0
  21. package/dist/{config-PLvresCv.cjs → config-Bfakeadu.cjs} +1 -1
  22. package/dist/config-CTcfF-0c.mjs +7 -0
  23. package/dist/dev-D1DmOSjn.mjs +6 -0
  24. package/dist/dev-DH6cSge8.cjs +6 -0
  25. package/dist/{docs-layout-CbZ7LDRe.js → docs-layout-CmntYM6p.js} +46 -147
  26. package/dist/{docs-layout-vzfXed1Q.cjs → docs-layout-DIgxJ5c7.cjs} +23 -130
  27. package/dist/{doctor-DMECtdK6.cjs → doctor-BLxm2alc.cjs} +1 -1
  28. package/dist/{doctor-FuFY1jBz.cjs → doctor-Dd-JMTRo.cjs} +1 -1
  29. package/dist/{doctor-i8Qmd8DJ.mjs → doctor-DogHujrP.mjs} +1 -1
  30. package/dist/{image-Hnaa2bJd.cjs → image-Bke2ojW1.cjs} +3 -3
  31. package/dist/{image-B-NDSDuY.js → image-CaY2w0ua.js} +2 -1
  32. package/dist/index--xbYbT8N.d.ts +343 -0
  33. package/dist/{index-Bg-JtZeK.d.cts → index-B_o5y34l.d.cts} +112 -13
  34. package/dist/{index-B3o307nd.d.ts → index-Bx0CUd7Q.d.ts} +112 -13
  35. package/dist/index-RK7W_Fxy.d.cts +343 -0
  36. package/dist/{link-CgdI6O2o.js → link-CSe_oD8Y.js} +137 -139
  37. package/dist/{link-vZjmD-es.cjs → link-Xb69Oy2F.cjs} +144 -169
  38. package/dist/{mdx-D0Absdq5.cjs → mdx-BCOrMd-P.cjs} +68 -16
  39. package/dist/{mdx-BRT71V5Q.js → mdx-BijiEbkp.js} +62 -15
  40. package/dist/{native-nLA4Jr0T.cjs → native-BbtRkce5.cjs} +1 -1
  41. package/dist/node/cli-entry.cjs +1 -1
  42. package/dist/node/cli-entry.mjs +1 -1
  43. package/dist/node/highlight.d.cts +2 -2
  44. package/dist/node/highlight.d.mts +2 -2
  45. package/dist/node/index.cjs +1 -1
  46. package/dist/node/index.d.cts +19 -37
  47. package/dist/node/index.d.mts +20 -38
  48. package/dist/node/index.mjs +1 -1
  49. package/dist/node/mdx/shiki-adapter.cjs +1 -1
  50. package/dist/node/mdx/shiki-adapter.d.cts +7 -2
  51. package/dist/node/mdx/shiki-adapter.d.mts +7 -2
  52. package/dist/node/mdx/shiki-adapter.mjs +1 -1
  53. package/dist/node-BgiLCa0I.cjs +39 -0
  54. package/dist/node-Da3tYBHo.mjs +39 -0
  55. package/dist/{package-CNqjEYE1.cjs → package-D1gVs5gQ.cjs} +1 -1
  56. package/dist/{package-sdcKhDhe.mjs → package-YgQJn3Yh.mjs} +1 -1
  57. package/dist/pages-external-B_r6gvqP.cjs +6 -0
  58. package/dist/pages-external-jmK7AHaO.mjs +6 -0
  59. package/dist/{parser-CD8Oo8qh.mjs → parser-CvNZc5s3.mjs} +1 -1
  60. package/dist/{parser-vPaKvzLp.cjs → parser-DJLWTiO-.cjs} +1 -1
  61. package/dist/plugin-DW9K2fW5.mjs +69 -0
  62. package/dist/plugin-NwGKyTJX.cjs +69 -0
  63. package/dist/{plugin-context-DuSg-Hax.mjs → plugin-context-COh-cbsW.mjs} +1 -1
  64. package/dist/{plugin-context-CscLcXjH.cjs → plugin-context-FIHaWn6r.cjs} +2 -2
  65. package/dist/{plugin-lifecycle-BywrEoWK.cjs → plugin-lifecycle-D9fTRaWY.cjs} +1 -1
  66. package/dist/{registry-BbB6NqSv.d.cts → registry-BFmzj1yg.d.mts} +1 -1
  67. package/dist/{registry-sJqDv0kE.d.mts → registry-BoswPzYV.d.cts} +1 -1
  68. package/dist/{resolve-C5rT6B21.mjs → resolve-5puUe7eS.mjs} +1 -1
  69. package/dist/{resolve-BelytNYR.cjs → resolve-CF4ZLfqx.cjs} +1 -1
  70. package/dist/route-paths-B6ocUfNY.cjs +6 -0
  71. package/dist/route-paths-DyDji4bX.mjs +6 -0
  72. package/dist/{router-CZBxMRAH.js → router-B5e8k4qK.js} +175 -10
  73. package/dist/{router-C3kygdRK.cjs → router-DKC0Lu0n.cjs} +204 -9
  74. package/dist/{routes-C3_w9fLX.cjs → routes-D55M8UrH.cjs} +1 -1
  75. package/dist/routes-DdE6Lfcl.cjs +6 -0
  76. package/dist/routes-_I_8PQYF.mjs +6 -0
  77. package/dist/{search-dialog-x_qHU8ty.cjs → search-dialog-BOQRHKTb.cjs} +197 -24
  78. package/dist/{search-dialog-BqkzDTq2.js → search-dialog-BXil4_7P.js} +190 -29
  79. package/dist/search-dialog-CwlBd-Mu.cjs +747 -0
  80. package/dist/{search-dialog-B9mdxsUC.js → search-dialog-D3Obh3eA.js} +1 -1
  81. package/dist/search-dialog-DeplpVEB.js +717 -0
  82. package/dist/{search-dialog-DCtm2dyR.cjs → search-dialog-cHXR5zhL.cjs} +1 -1
  83. package/dist/server/index.cjs +1 -1
  84. package/dist/server/index.d.mts +1 -1
  85. package/dist/server/index.mjs +1 -1
  86. package/dist/ssg-static-options-Br1_u9qp.mjs +6 -0
  87. package/dist/ssg-static-options-CVvGKM8i.cjs +6 -0
  88. package/dist/types-58Ac3UGI.d.cts +114 -0
  89. package/dist/types-BwnGf-1E.d.mts +114 -0
  90. package/dist/virtual-modules-C4-qxFlL.cjs +40 -0
  91. package/dist/virtual-modules-DiWUKJGP.mjs +40 -0
  92. package/package.json +8 -5
  93. package/src/shared/types.ts +133 -987
  94. package/dist/config-CrsQJHQz.cjs +0 -7
  95. package/dist/config-DC0nMMk7.mjs +0 -7
  96. package/dist/dev-B49V6O6p.mjs +0 -6
  97. package/dist/dev-DbuhNcF5.cjs +0 -6
  98. package/dist/index-CgWkOCCn.d.cts +0 -1193
  99. package/dist/index-CuNSD3E2.d.ts +0 -1193
  100. package/dist/node-BljvHMpS.cjs +0 -23
  101. package/dist/node-CWxGw4H4.mjs +0 -23
  102. package/dist/pages-external-BBw8ObVK.mjs +0 -6
  103. package/dist/pages-external-DPiPFxxP.cjs +0 -6
  104. package/dist/plugin-BPcm1cU0.mjs +0 -69
  105. package/dist/plugin-WUhxnpko.cjs +0 -69
  106. package/dist/routes-C0kb4ue6.cjs +0 -6
  107. package/dist/routes-C4wrLWwu.mjs +0 -6
  108. package/dist/search-dialog-Bp_ouN1c.cjs +0 -550
  109. package/dist/search-dialog-an2BNMj6.js +0 -526
  110. package/dist/types-Db6zToZH.d.mts +0 -975
  111. package/dist/types-o7iZ2BAR.d.cts +0 -975
  112. package/dist/virtual-modules-B2X4Ht2r.mjs +0 -39
  113. package/dist/virtual-modules-DPsdHKcu.cjs +0 -39
  114. /package/dist/{audit-CMc_ydRr.mjs → audit-CYAkXXvP.mjs} +0 -0
  115. /package/dist/{audit-CHkGiV3c.cjs → audit-DxCZZTuX.cjs} +0 -0
  116. /package/dist/{csp-BiGAG8aF.cjs → csp-B-gc2Iha.cjs} +0 -0
  117. /package/dist/{csp-D0BOH8ae.mjs → csp-f8DOcI_7.mjs} +0 -0
  118. /package/dist/{generator-BCrZL53x.cjs → generator-CBAPKY6r.cjs} +0 -0
  119. /package/dist/{generator-CFukoGa0.mjs → generator-MRpn-yp6.mjs} +0 -0
  120. /package/dist/{handler-Lex5DbvG.mjs → handler-DBZqoWt2.mjs} +0 -0
  121. /package/dist/{handler-Ch-Q9NAB.cjs → handler-ryZR9Q41.cjs} +0 -0
  122. /package/dist/{index-HAwIo4nZ.d.mts → index-CPr34I2C.d.mts} +0 -0
  123. /package/dist/{native-BYKMke79.mjs → native-DZ6WMwjG.mjs} +0 -0
  124. /package/dist/{native-BOet8hpE.cjs → native-DeKxny_T.cjs} +0 -0
  125. /package/dist/{update-check-BXD1atVv.mjs → update-check-BXx8te9F.mjs} +0 -0
  126. /package/dist/{update-check-DFQZyoSU.cjs → update-check-CiIeC7CX.cjs} +0 -0
@@ -3,8 +3,9 @@
3
3
  * Copyright (c) 2026 Jesus Alcala
4
4
  * Licensed under the MIT License.
5
5
  */
6
- const require_router = require('./router-C3kygdRK.cjs');
6
+ const require_router = require('./router-DKC0Lu0n.cjs');
7
7
  let react = require("react");
8
+ react = require_router.__toESM(react);
8
9
  let react_jsx_runtime = require("react/jsx-runtime");
9
10
  let clsx = require("clsx");
10
11
  let tailwind_merge = require("tailwind-merge");
@@ -22,10 +23,10 @@ function getSavedPrefs() {
22
23
  return {};
23
24
  }
24
25
  }
25
- const globalRegistry$1 = globalThis;
26
- const existingContext = globalRegistry$1[BOLTDOCS_CONTEXT_SYMBOL];
26
+ const globalRegistry = globalThis;
27
+ const existingContext = globalRegistry[BOLTDOCS_CONTEXT_SYMBOL];
27
28
  const BoltdocsContext = existingContext || (0, react.createContext)(void 0);
28
- if (!existingContext) Reflect.set(globalRegistry$1, BOLTDOCS_CONTEXT_SYMBOL, BoltdocsContext);
29
+ if (!existingContext) Reflect.set(globalRegistry, BOLTDOCS_CONTEXT_SYMBOL, BoltdocsContext);
29
30
  function BoltdocsProvider({ children, initialLocale = "", initialVersion = "" }) {
30
31
  const [locale, setLocaleState] = (0, react.useState)(() => {
31
32
  if (initialLocale) return initialLocale;
@@ -48,7 +49,7 @@ function BoltdocsProvider({ children, initialLocale = "", initialVersion = "" })
48
49
  return newL;
49
50
  });
50
51
  if (typeof globalThis !== "undefined") Reflect.set(globalThis, BOLTDOCS_INSTANCE_SYMBOL, {
51
- ...globalThis[BOLTDOCS_INSTANCE_SYMBOL],
52
+ ...globalRegistry[BOLTDOCS_INSTANCE_SYMBOL],
52
53
  currentLocale: newL
53
54
  });
54
55
  if (typeof window !== "undefined") try {
@@ -66,7 +67,7 @@ function BoltdocsProvider({ children, initialLocale = "", initialVersion = "" })
66
67
  return newV;
67
68
  });
68
69
  if (typeof globalThis !== "undefined") Reflect.set(globalThis, BOLTDOCS_INSTANCE_SYMBOL, {
69
- ...globalThis[BOLTDOCS_INSTANCE_SYMBOL],
70
+ ...globalRegistry[BOLTDOCS_INSTANCE_SYMBOL],
70
71
  currentVersion: newV
71
72
  });
72
73
  if (typeof window !== "undefined") try {
@@ -105,41 +106,6 @@ function useBoltdocsContext() {
105
106
  return context;
106
107
  }
107
108
 
108
- //#endregion
109
- //#region src/client/app/config-context.tsx
110
- /**
111
- * Context for the global documentation configuration.
112
- * Using a global singleton pattern to survive dual-package or duplicated-code hazards.
113
- */
114
- const CONFIG_CONTEXT_SYMBOL = Symbol.for("__BDOCS_CONFIG_CONTEXT__");
115
- const CONFIG_INSTANCE_SYMBOL = Symbol.for("__BDOCS_CONFIG_INSTANCE__");
116
- const globalRegistry = globalThis;
117
- const existingConfigContext = globalRegistry[CONFIG_CONTEXT_SYMBOL];
118
- const ConfigContext = existingConfigContext || (0, react.createContext)(null);
119
- if (!existingConfigContext) globalRegistry[CONFIG_CONTEXT_SYMBOL] = ConfigContext;
120
- /**
121
- * Hook to access the Boltdocs configuration when one is available.
122
- *
123
- * Low-level primitives such as icons can also be rendered standalone (for
124
- * example in a component preview or a unit test), so they must not be forced
125
- * to mount the full application provider just to render an inline SVG.
126
- */
127
- function useOptionalConfig() {
128
- const context = (0, react.use)(ConfigContext);
129
- if (context) return context;
130
- const globalConfig = globalRegistry[CONFIG_INSTANCE_SYMBOL];
131
- if (globalConfig) return globalConfig;
132
- return null;
133
- }
134
- /**
135
- * Hook to access the Boltdocs configuration.
136
- */
137
- function useConfig() {
138
- const config = useOptionalConfig();
139
- if (!config) throw new Error("useConfig must be used within a ConfigProvider");
140
- return config;
141
- }
142
-
143
109
  //#endregion
144
110
  //#region src/client/components/ui-base/icons.tsx
145
111
  var icons_exports = /* @__PURE__ */ require_router.__exportAll({
@@ -547,6 +513,66 @@ const FaceBad = createIcon("FaceBad", /* @__PURE__ */ (0, react_jsx_runtime.jsxs
547
513
  })
548
514
  ] }));
549
515
 
516
+ //#endregion
517
+ //#region src/client/router/prefetch-viewport.ts
518
+ /**
519
+ * Viewport-triggered route prefetching.
520
+ *
521
+ * Hover prefetching only warms a link once the pointer commits to it, which
522
+ * misses the most common case: a reader scrolls the sidebar, reads a heading,
523
+ * and clicks without ever hovering. Every destination they are plausibly
524
+ * heading for sits on screen, untouched.
525
+ *
526
+ * A single shared `IntersectionObserver` watches anchors registered by
527
+ * `Link` and fires the normal prefetch pipeline when one becomes visible, so
528
+ * the route chunk and its loader data are already cached by the time the click
529
+ * lands. Hover keeps working and still wins: whichever signal arrives first
530
+ * populates `prefetchCache`, and the other is a cache hit.
531
+ *
532
+ * The existing prefetch queue bounds the cost (two in flight, a shallow
533
+ * backlog) and drops work when saturated, so this stays opportunistic
534
+ * exactly like hover prefetching is.
535
+ */
536
+ /**
537
+ * Start slightly before the link is on screen so a short scroll already feels
538
+ * instant, without warming the whole page below the fold.
539
+ */
540
+ const VIEWPORT_PREFETCH_MARGIN = "200px 0px";
541
+ let observer = null;
542
+ const pending = /* @__PURE__ */ new WeakMap();
543
+ function getObserver() {
544
+ if (typeof window === "undefined") return null;
545
+ if (typeof IntersectionObserver === "undefined") return null;
546
+ if (observer) return observer;
547
+ observer = new IntersectionObserver((entries) => {
548
+ for (const entry of entries) {
549
+ if (!entry.isIntersecting) continue;
550
+ const run = pending.get(entry.target);
551
+ if (!run) continue;
552
+ observer?.unobserve(entry.target);
553
+ pending.delete(entry.target);
554
+ run();
555
+ }
556
+ }, { rootMargin: VIEWPORT_PREFETCH_MARGIN });
557
+ return observer;
558
+ }
559
+ /**
560
+ * Watches `element` and invokes `run` once it approaches the viewport.
561
+ *
562
+ * Returns a cleanup function. Safe to call during SSR, where it is a no-op.
563
+ */
564
+ function observeForPrefetch(element, run) {
565
+ if (!element) return () => {};
566
+ const target = getObserver();
567
+ if (!target) return () => {};
568
+ pending.set(element, run);
569
+ target.observe(element);
570
+ return () => {
571
+ target.unobserve(element);
572
+ pending.delete(element);
573
+ };
574
+ }
575
+
550
576
  //#endregion
551
577
  //#region src/client/utils/path.ts
552
578
  /**
@@ -573,13 +599,58 @@ function resolvePublicAssetUrl(value, base) {
573
599
 
574
600
  //#endregion
575
601
  //#region src/client/app/routes-context.tsx
602
+ const emptyRouteIndex = {
603
+ byPath: /* @__PURE__ */ new Map(),
604
+ hintsByPath: /* @__PURE__ */ new Map(),
605
+ collectionNames: [],
606
+ byCollectionPath: /* @__PURE__ */ new Map(),
607
+ countsByFilePath: /* @__PURE__ */ new Map()
608
+ };
609
+ function getCollectionPathKey(route) {
610
+ if (!route.collection) return void 0;
611
+ const parts = normalizePath(route.path).split("/").filter(Boolean);
612
+ const collectionIndex = parts.indexOf(route.collection);
613
+ if (collectionIndex < 0) return void 0;
614
+ return `/${parts.slice(collectionIndex).join("/")}`;
615
+ }
616
+ /** Build all client route lookup structures in one cached pass. */
617
+ function createRouteIndex(routes) {
618
+ const byPath = /* @__PURE__ */ new Map();
619
+ const hintsByPath = /* @__PURE__ */ new Map();
620
+ const byCollectionPath = /* @__PURE__ */ new Map();
621
+ const countsByFilePath = /* @__PURE__ */ new Map();
622
+ const collectionNames = /* @__PURE__ */ new Set();
623
+ for (const route of routes) {
624
+ if (!route.path) continue;
625
+ const path = normalizePath(route.path);
626
+ byPath.set(path, route);
627
+ hintsByPath.set(path, {
628
+ path: route.path,
629
+ kind: route.collection ? "collection" : void 0,
630
+ collection: route.collection
631
+ });
632
+ countsByFilePath.set(route.filePath, (countsByFilePath.get(route.filePath) || 0) + 1);
633
+ if (route.collection) {
634
+ collectionNames.add(route.collection);
635
+ const collectionPath = getCollectionPathKey(route);
636
+ if (collectionPath) {
637
+ const variants = byCollectionPath.get(collectionPath) || [];
638
+ variants.push(route);
639
+ byCollectionPath.set(collectionPath, variants);
640
+ }
641
+ }
642
+ }
643
+ return {
644
+ byPath,
645
+ hintsByPath,
646
+ byCollectionPath,
647
+ countsByFilePath,
648
+ collectionNames: [...collectionNames]
649
+ };
650
+ }
576
651
  const RoutesContext = (0, react.createContext)({
577
652
  routes: [],
578
- index: {
579
- byPath: /* @__PURE__ */ new Map(),
580
- hintsByPath: /* @__PURE__ */ new Map(),
581
- collectionNames: []
582
- }
653
+ index: emptyRouteIndex
583
654
  });
584
655
  /**
585
656
  * Hook to access the processed routes list from the closest provider.
@@ -592,27 +663,7 @@ function useRoutesContext() {
592
663
  */
593
664
  function RoutesProvider({ routes: initialRoutes, children }) {
594
665
  const [routes, setRoutes] = (0, react.useState)(initialRoutes);
595
- const index = (0, react.useMemo)(() => {
596
- const byPath = /* @__PURE__ */ new Map();
597
- const hintsByPath = /* @__PURE__ */ new Map();
598
- const collectionNames = /* @__PURE__ */ new Set();
599
- for (const route of routes) {
600
- if (!route.path) continue;
601
- const path = normalizePath(route.path);
602
- byPath.set(path, route);
603
- hintsByPath.set(path, {
604
- path: route.path,
605
- kind: route.collection ? "collection" : void 0,
606
- collection: route.collection
607
- });
608
- if (route.collection) collectionNames.add(route.collection);
609
- }
610
- return {
611
- byPath,
612
- hintsByPath,
613
- collectionNames: [...collectionNames]
614
- };
615
- }, [routes]);
666
+ const index = (0, react.useMemo)(() => createRouteIndex(routes), [routes]);
616
667
  (0, react.useEffect)(() => {
617
668
  if (!{}.hot) return;
618
669
  const handler = (payload) => {
@@ -643,7 +694,7 @@ function RoutesProvider({ routes: initialRoutes, children }) {
643
694
  //#endregion
644
695
  //#region src/client/hooks/use-localized-to.ts
645
696
  function useLocalizedTo(to) {
646
- const config = useConfig();
697
+ const config = require_router.useConfig();
647
698
  const routeContext = useRoutesContext();
648
699
  const routeIndex = routeContext.index || {
649
700
  byPath: new Map(routeContext.routes.map((route) => [route.path, route])),
@@ -706,74 +757,6 @@ function cn(...inputs) {
706
757
  return (0, tailwind_merge.twMerge)((0, clsx.clsx)(inputs));
707
758
  }
708
759
 
709
- //#endregion
710
- //#region src/client/view-transitions.ts
711
- function resolveOptions(options) {
712
- if (options?.enabled === false) return void 0;
713
- return {
714
- enabled: true,
715
- ...options?.types?.length ? { types: options.types } : {}
716
- };
717
- }
718
- function isNativeViewTransitionSupported() {
719
- return typeof document !== "undefined" && typeof document.startViewTransition === "function";
720
- }
721
- /**
722
- * Starts a native document transition when the browser supports it. On older
723
- * browsers, the update still runs normally and the function returns null.
724
- */
725
- function startViewTransition(update, options) {
726
- const resolved = resolveOptions(options);
727
- if (typeof document === "undefined" || resolved?.enabled !== true) {
728
- update();
729
- return null;
730
- }
731
- const start = document.startViewTransition;
732
- if (!start) {
733
- update();
734
- return null;
735
- }
736
- const types = options?.types;
737
- return start.call(document, {
738
- update,
739
- ...types?.length ? { types } : {}
740
- });
741
- }
742
- /**
743
- * Returns a transition-aware runner that follows the project's experimental
744
- * configuration. It is safe to use in custom layouts and external pages.
745
- *
746
- * The returned value is callable for backwards compatibility:
747
- * `transition(() => setState(...))`. It also exposes `run` and `start` aliases
748
- * for discoverability in editor autocomplete.
749
- */
750
- function useViewTransition() {
751
- const configured = useOptionalConfig()?.experimental?.viewTransitions;
752
- const enabled = configured === true || typeof configured === "object" && configured.enabled === true;
753
- const supported = isNativeViewTransitionSupported();
754
- const run = (0, react.useCallback)((update, options) => {
755
- if (!enabled && options?.enabled !== true) {
756
- update();
757
- return null;
758
- }
759
- const configuredTypes = typeof configured === "object" ? configured.types : void 0;
760
- return startViewTransition(update, {
761
- ...options,
762
- types: options?.types || configuredTypes
763
- });
764
- }, [configured, enabled]);
765
- return (0, react.useMemo)(() => Object.assign(run, {
766
- run,
767
- start: run,
768
- enabled,
769
- supported
770
- }), [
771
- enabled,
772
- run,
773
- supported
774
- ]);
775
- }
776
-
777
760
  //#endregion
778
761
  //#region src/client/components/primitives/link.tsx
779
762
  /**
@@ -785,7 +768,7 @@ function Link(props) {
785
768
  const target = href ?? to ?? "";
786
769
  const navigate = require_router.useNavigate();
787
770
  const prefetchRoute = require_router.usePrefetch();
788
- const runTransition = useViewTransition();
771
+ const runTransition = require_router.useViewTransition();
789
772
  const localizedHref = useLocalizedTo(target);
790
773
  const handleClick = (e) => {
791
774
  onClick?.(e);
@@ -801,7 +784,7 @@ function Link(props) {
801
784
  }
802
785
  };
803
786
  const handlePrefetch = () => {
804
- if (prefetch === "hover" && localizedHref) prefetchRoute(localizedHref);
787
+ if (prefetch !== "none" && localizedHref) prefetchRoute(localizedHref);
805
788
  };
806
789
  const handleMouseEnter = (e) => {
807
790
  onMouseEnter?.(e);
@@ -811,9 +794,25 @@ function Link(props) {
811
794
  onFocus?.(e);
812
795
  handlePrefetch();
813
796
  };
797
+ const anchorRef = react.default.useRef(null);
798
+ const setRef = react.default.useCallback((node) => {
799
+ anchorRef.current = node;
800
+ if (typeof ref === "function") ref(node);
801
+ else if (ref) ref.current = node;
802
+ }, [ref]);
803
+ react.default.useEffect(() => {
804
+ if (prefetch !== "viewport" || !localizedHref) return;
805
+ return observeForPrefetch(anchorRef.current, () => {
806
+ prefetchRoute(localizedHref);
807
+ });
808
+ }, [
809
+ prefetch,
810
+ localizedHref,
811
+ prefetchRoute
812
+ ]);
814
813
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
815
814
  ...rest,
816
- ref,
815
+ ref: setRef,
817
816
  href: localizedHref,
818
817
  target: linkTarget,
819
818
  download,
@@ -906,12 +905,6 @@ Object.defineProperty(exports, 'CircleHelp', {
906
905
  return CircleHelp;
907
906
  }
908
907
  });
909
- Object.defineProperty(exports, 'ConfigContext', {
910
- enumerable: true,
911
- get: function () {
912
- return ConfigContext;
913
- }
914
- });
915
908
  Object.defineProperty(exports, 'Copy', {
916
909
  enumerable: true,
917
910
  get: function () {
@@ -1074,6 +1067,12 @@ Object.defineProperty(exports, 'cn', {
1074
1067
  return cn;
1075
1068
  }
1076
1069
  });
1070
+ Object.defineProperty(exports, 'createRouteIndex', {
1071
+ enumerable: true,
1072
+ get: function () {
1073
+ return createRouteIndex;
1074
+ }
1075
+ });
1077
1076
  Object.defineProperty(exports, 'icons_exports', {
1078
1077
  enumerable: true,
1079
1078
  get: function () {
@@ -1092,45 +1091,21 @@ Object.defineProperty(exports, 'resolvePublicAssetUrl', {
1092
1091
  return resolvePublicAssetUrl;
1093
1092
  }
1094
1093
  });
1095
- Object.defineProperty(exports, 'startViewTransition', {
1096
- enumerable: true,
1097
- get: function () {
1098
- return startViewTransition;
1099
- }
1100
- });
1101
1094
  Object.defineProperty(exports, 'useBoltdocsContext', {
1102
1095
  enumerable: true,
1103
1096
  get: function () {
1104
1097
  return useBoltdocsContext;
1105
1098
  }
1106
1099
  });
1107
- Object.defineProperty(exports, 'useConfig', {
1108
- enumerable: true,
1109
- get: function () {
1110
- return useConfig;
1111
- }
1112
- });
1113
1100
  Object.defineProperty(exports, 'useLocalizedTo', {
1114
1101
  enumerable: true,
1115
1102
  get: function () {
1116
1103
  return useLocalizedTo;
1117
1104
  }
1118
1105
  });
1119
- Object.defineProperty(exports, 'useOptionalConfig', {
1120
- enumerable: true,
1121
- get: function () {
1122
- return useOptionalConfig;
1123
- }
1124
- });
1125
1106
  Object.defineProperty(exports, 'useRoutesContext', {
1126
1107
  enumerable: true,
1127
1108
  get: function () {
1128
1109
  return useRoutesContext;
1129
1110
  }
1130
- });
1131
- Object.defineProperty(exports, 'useViewTransition', {
1132
- enumerable: true,
1133
- get: function () {
1134
- return useViewTransition;
1135
- }
1136
1111
  });
@@ -3,9 +3,9 @@
3
3
  * Copyright (c) 2026 Jesus Alcala
4
4
  * Licensed under the MIT License.
5
5
  */
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');
6
+ const require_router = require('./router-DKC0Lu0n.cjs');
7
+ const require_link = require('./link-Xb69Oy2F.cjs');
8
+ const require_image = require('./image-Bke2ojW1.cjs');
9
9
  let react = require("react");
10
10
  let react_jsx_runtime = require("react/jsx-runtime");
11
11
  let react_aria_components = require("react-aria-components");
@@ -281,6 +281,18 @@ function useCopyButton() {
281
281
  //#endregion
282
282
  //#region src/client/components/mdx/use-expandable.ts
283
283
  /**
284
+ * Counts the rendered lines of a pre-rendered Shiki block.
285
+ *
286
+ * `data-highlighted-html` holds the same markup the server writes, so the count
287
+ * is available before the DOM exists. Returns 0 when there is no HTML, which
288
+ * leaves the caller on the DOM-measured path.
289
+ */
290
+ function countHighlightedLines(highlightedHtml) {
291
+ if (!highlightedHtml) return 0;
292
+ const spans = highlightedHtml.split("<span class=\"line\"").length - 1;
293
+ return spans > 0 ? spans : highlightedHtml.split("\n").length;
294
+ }
295
+ /**
284
296
  * Expand / collapse behavior for long code blocks. Measures the rendered code
285
297
  * through `preRef` and exposes whether the block is expandable, whether it
286
298
  * should be visually truncated, and a toggle handler.
@@ -288,7 +300,7 @@ function useCopyButton() {
288
300
  function useExpandable(options = {}) {
289
301
  const { children, highlightedHtml, maxLines = 6 } = options;
290
302
  const [isExpanded, setIsExpanded] = (0, react.useState)(false);
291
- const [isExpandable, setIsExpandable] = (0, react.useState)(false);
303
+ const [isExpandable, setIsExpandable] = (0, react.useState)(countHighlightedLines(highlightedHtml) > maxLines);
292
304
  const preRef = (0, react.useRef)(null);
293
305
  const shouldTruncate = isExpandable && !isExpanded;
294
306
  const toggle = () => setIsExpanded((prev) => !prev);
@@ -326,7 +338,7 @@ function useExpandable(options = {}) {
326
338
  function useCodeBlockFeedback(options = {}) {
327
339
  const { plain = false, lang = "", submitFeedback } = options;
328
340
  const [rated, setRated] = (0, react.useState)(null);
329
- const customConfig = require_link.useConfig().integrations?.feedback?.custom;
341
+ const customConfig = require_router.useConfig().integrations?.feedback?.custom;
330
342
  const enabled = !!(customConfig?.enabled && !plain);
331
343
  return {
332
344
  rated,
@@ -577,6 +589,46 @@ function Cards({ children, className, cols = 2, ...props }) {
577
589
  });
578
590
  }
579
591
 
592
+ //#endregion
593
+ //#region src/client/utils/date.ts
594
+ /**
595
+ * Deterministic date formatting for server-rendered output.
596
+ *
597
+ * `toLocaleDateString` with no locale resolves against the *runtime* default,
598
+ * which is not the same in Node and in a browser: the server rendered
599
+ * "26 de septiembre de 2026" from an `es` system locale while the client
600
+ * produced "September 26, 2026". That is a text mismatch during hydration and
601
+ * React throws away the server HTML and re-renders the whole page.
602
+ *
603
+ * The time zone has to be pinned for the same reason. A frontmatter date such
604
+ * as `2026-09-27` parses as UTC midnight, so any zone behind UTC renders the
605
+ * previous day and any zone ahead renders the correct one, which is a second,
606
+ * environment-dependent mismatch.
607
+ *
608
+ * Both are therefore explicit here. Callers that genuinely want a different
609
+ * locale can pass one, and it is still deterministic because it is fixed in
610
+ * the markup rather than inferred.
611
+ */
612
+ const DEFAULT_LOCALE = "en-US";
613
+ const DEFAULT_TIME_ZONE = "UTC";
614
+ /**
615
+ * Formats a date as a stable, locale- and zone-pinned string.
616
+ *
617
+ * Returns an empty string for values that are not real dates so callers can
618
+ * render nothing rather than "Invalid Date".
619
+ */
620
+ function formatDeterministicDate(date, options = {}) {
621
+ if (date === void 0 || date === null || date === "") return "";
622
+ const parsed = date instanceof Date ? date : new Date(date);
623
+ if (Number.isNaN(parsed.getTime())) return "";
624
+ return parsed.toLocaleDateString(options.locale ?? DEFAULT_LOCALE, {
625
+ year: "numeric",
626
+ month: options.month ?? "long",
627
+ day: options.day ?? "numeric",
628
+ timeZone: options.timeZone ?? DEFAULT_TIME_ZONE
629
+ });
630
+ }
631
+
580
632
  //#endregion
581
633
  //#region src/client/components/mdx/last-updated.tsx
582
634
  /**
@@ -587,11 +639,7 @@ function LastUpdated({ date, className }) {
587
639
  if (!date) return null;
588
640
  const d = new Date(date);
589
641
  if (Number.isNaN(d.getTime())) return null;
590
- const formattedDate = d.toLocaleDateString(void 0, {
591
- year: "numeric",
592
- month: "long",
593
- day: "numeric"
594
- });
642
+ const formattedDate = formatDeterministicDate(d);
595
643
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
596
644
  className: require_link.cn("mt-16 pt-6 border-t border-subtle flex items-center justify-between text-xs text-muted select-none", className),
597
645
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
@@ -703,13 +751,11 @@ function normalizeBadge(badge) {
703
751
  }
704
752
  function formatDate(date, locale) {
705
753
  if (date === void 0 || date === null || date === "") return null;
706
- const d = date instanceof Date ? date : new Date(date);
707
- if (Number.isNaN(d.getTime())) return null;
708
- return d.toLocaleDateString(locale ?? "en-US", {
709
- year: "numeric",
710
- month: "short",
711
- day: "numeric"
754
+ const formatted = formatDeterministicDate(date, {
755
+ locale,
756
+ month: "short"
712
757
  });
758
+ return formatted === "" ? null : formatted;
713
759
  }
714
760
  const VARIANT_DEFAULT_ICON = {
715
761
  success: require_link.Check,
@@ -806,6 +852,12 @@ Object.defineProperty(exports, 'copyToClipboard', {
806
852
  return copyToClipboard;
807
853
  }
808
854
  });
855
+ Object.defineProperty(exports, 'formatDeterministicDate', {
856
+ enumerable: true,
857
+ get: function () {
858
+ return formatDeterministicDate;
859
+ }
860
+ });
809
861
  Object.defineProperty(exports, 'mdx_components_default', {
810
862
  enumerable: true,
811
863
  get: function () {