boltdocs 1.10.2 → 2.0.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 (250) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/dist/cache-7G6D532T.mjs +1 -0
  4. package/dist/chunk-A4HQPEPU.mjs +1 -0
  5. package/dist/chunk-BA5NH5HU.mjs +1 -0
  6. package/dist/chunk-BQCD3DWG.mjs +1 -0
  7. package/dist/chunk-H63UMKYF.mjs +1 -0
  8. package/dist/chunk-IWHRQHS7.mjs +1 -0
  9. package/dist/chunk-JZXLCA2E.mjs +1 -0
  10. package/dist/chunk-MFU7Q6WF.mjs +1 -0
  11. package/dist/chunk-QYPNX5UN.mjs +1 -0
  12. package/dist/chunk-XEAPSFMB.mjs +1 -0
  13. package/dist/client/components/mdx/index.d.mts +209 -0
  14. package/dist/client/components/mdx/index.d.ts +209 -0
  15. package/dist/client/components/mdx/index.js +1 -0
  16. package/dist/client/components/mdx/index.mjs +1 -0
  17. package/dist/client/hooks/index.d.mts +133 -0
  18. package/dist/client/hooks/index.d.ts +133 -0
  19. package/dist/client/hooks/index.js +1 -0
  20. package/dist/client/hooks/index.mjs +1 -0
  21. package/dist/client/index.d.mts +138 -298
  22. package/dist/client/index.d.ts +138 -298
  23. package/dist/client/index.js +1 -3630
  24. package/dist/client/index.mjs +1 -697
  25. package/dist/client/ssr.d.mts +7 -3
  26. package/dist/client/ssr.d.ts +7 -3
  27. package/dist/client/ssr.js +1 -2928
  28. package/dist/client/ssr.mjs +1 -33
  29. package/dist/{config-BsFQ-ErD.d.ts → config-CX4l-ZNp.d.mts} +42 -35
  30. package/dist/{config-BsFQ-ErD.d.mts → config-CX4l-ZNp.d.ts} +42 -35
  31. package/dist/node/index.d.mts +2 -4
  32. package/dist/node/index.d.ts +2 -4
  33. package/dist/node/index.js +31 -1161
  34. package/dist/node/index.mjs +31 -736
  35. package/dist/search-dialog-EB3N4TYM.mjs +1 -0
  36. package/dist/types-BuZWFT7r.d.ts +159 -0
  37. package/dist/types-CvT-SGbK.d.mts +159 -0
  38. package/dist/use-routes-5bAtAAYX.d.mts +30 -0
  39. package/dist/use-routes-BefRXY3v.d.ts +30 -0
  40. package/package.json +34 -12
  41. package/src/client/app/config-context.tsx +18 -0
  42. package/src/client/app/docs-layout.tsx +14 -0
  43. package/src/client/app/index.tsx +137 -262
  44. package/src/client/app/mdx-component.tsx +52 -0
  45. package/src/client/app/mdx-components-context.tsx +23 -0
  46. package/src/client/app/mdx-page.tsx +20 -0
  47. package/src/client/app/preload.tsx +38 -30
  48. package/src/client/app/router.tsx +30 -0
  49. package/src/client/app/scroll-handler.tsx +40 -0
  50. package/src/client/app/theme-context.tsx +75 -0
  51. package/src/client/components/default-layout.tsx +80 -0
  52. package/src/client/components/docs-layout.tsx +105 -0
  53. package/src/client/components/icons-dev.tsx +74 -0
  54. package/src/client/components/mdx/admonition.tsx +107 -0
  55. package/src/client/components/mdx/badge.tsx +41 -0
  56. package/src/client/components/mdx/button.tsx +35 -0
  57. package/src/client/components/mdx/card.tsx +124 -0
  58. package/src/client/components/mdx/code-block.tsx +119 -0
  59. package/src/client/components/mdx/component-preview.tsx +47 -0
  60. package/src/client/components/mdx/component-props.tsx +83 -0
  61. package/src/client/components/mdx/field.tsx +66 -0
  62. package/src/client/components/mdx/file-tree.tsx +287 -0
  63. package/src/client/components/mdx/hooks/use-code-block.ts +56 -0
  64. package/src/client/components/mdx/hooks/use-component-preview.ts +16 -0
  65. package/src/client/components/mdx/hooks/useTable.ts +74 -0
  66. package/src/client/components/mdx/hooks/useTabs.ts +68 -0
  67. package/src/client/components/mdx/image.tsx +23 -0
  68. package/src/client/components/mdx/index.ts +53 -0
  69. package/src/client/components/mdx/link.tsx +38 -0
  70. package/src/client/components/mdx/list.tsx +192 -0
  71. package/src/client/components/mdx/table.tsx +156 -0
  72. package/src/client/components/mdx/tabs.tsx +135 -0
  73. package/src/client/components/mdx/video.tsx +68 -0
  74. package/src/client/components/primitives/breadcrumbs.tsx +79 -0
  75. package/src/client/components/primitives/button-group.tsx +54 -0
  76. package/src/client/components/primitives/button.tsx +145 -0
  77. package/src/client/components/primitives/helpers/observer.ts +120 -0
  78. package/src/client/components/primitives/index.ts +17 -0
  79. package/src/client/components/primitives/link.tsx +122 -0
  80. package/src/client/components/primitives/menu.tsx +159 -0
  81. package/src/client/components/primitives/navbar.tsx +359 -0
  82. package/src/client/components/primitives/navigation-menu.tsx +116 -0
  83. package/src/client/components/primitives/on-this-page.tsx +461 -0
  84. package/src/client/components/primitives/page-nav.tsx +87 -0
  85. package/src/client/components/primitives/popover.tsx +47 -0
  86. package/src/client/components/primitives/search-dialog.tsx +183 -0
  87. package/src/client/components/primitives/sidebar.tsx +154 -0
  88. package/src/client/components/primitives/tabs.tsx +90 -0
  89. package/src/client/components/primitives/tooltip.tsx +83 -0
  90. package/src/client/components/primitives/types.ts +11 -0
  91. package/src/client/components/ui-base/breadcrumbs.tsx +42 -0
  92. package/src/client/components/ui-base/copy-markdown.tsx +112 -0
  93. package/src/client/components/ui-base/error-boundary.tsx +52 -0
  94. package/src/client/components/ui-base/github-stars.tsx +27 -0
  95. package/src/client/components/ui-base/head.tsx +69 -0
  96. package/src/client/components/ui-base/loading.tsx +87 -0
  97. package/src/client/components/ui-base/navbar.tsx +138 -0
  98. package/src/client/components/ui-base/not-found.tsx +24 -0
  99. package/src/client/components/ui-base/on-this-page.tsx +152 -0
  100. package/src/client/components/ui-base/page-nav.tsx +39 -0
  101. package/src/client/components/ui-base/powered-by.tsx +19 -0
  102. package/src/client/components/ui-base/progress-bar.tsx +67 -0
  103. package/src/client/components/ui-base/search-dialog.tsx +82 -0
  104. package/src/client/components/ui-base/sidebar.tsx +104 -0
  105. package/src/client/components/ui-base/tabs.tsx +65 -0
  106. package/src/client/components/ui-base/theme-toggle.tsx +32 -0
  107. package/src/client/hooks/index.ts +12 -0
  108. package/src/client/hooks/use-breadcrumbs.ts +22 -0
  109. package/src/client/hooks/use-i18n.ts +84 -0
  110. package/src/client/hooks/use-localized-to.ts +95 -0
  111. package/src/client/hooks/use-location.ts +5 -0
  112. package/src/client/hooks/use-navbar.ts +60 -0
  113. package/src/client/hooks/use-onthispage.ts +23 -0
  114. package/src/client/hooks/use-page-nav.ts +22 -0
  115. package/src/client/hooks/use-routes.ts +72 -0
  116. package/src/client/hooks/use-search.ts +71 -0
  117. package/src/client/hooks/use-sidebar.ts +49 -0
  118. package/src/client/hooks/use-tabs.ts +43 -0
  119. package/src/client/hooks/use-version.ts +78 -0
  120. package/src/client/index.ts +55 -17
  121. package/src/client/integrations/codesandbox.ts +179 -0
  122. package/src/client/ssr.tsx +27 -16
  123. package/src/client/theme/neutral.css +360 -0
  124. package/src/client/types.ts +131 -27
  125. package/src/client/utils/cn.ts +6 -0
  126. package/src/client/utils/copy-clipboard.ts +22 -0
  127. package/src/client/utils/get-base-file-path.ts +21 -0
  128. package/src/client/utils/github.ts +121 -0
  129. package/src/client/utils/use-on-change.ts +15 -0
  130. package/src/client/virtual.d.ts +24 -0
  131. package/src/node/cache.ts +156 -156
  132. package/src/node/config.ts +159 -103
  133. package/src/node/index.ts +13 -13
  134. package/src/node/mdx.ts +213 -61
  135. package/src/node/plugin/entry.ts +29 -18
  136. package/src/node/plugin/html.ts +11 -11
  137. package/src/node/plugin/index.ts +161 -84
  138. package/src/node/plugin/types.ts +2 -4
  139. package/src/node/routes/cache.ts +6 -6
  140. package/src/node/routes/index.ts +206 -113
  141. package/src/node/routes/parser.ts +102 -82
  142. package/src/node/routes/sorter.ts +15 -15
  143. package/src/node/routes/types.ts +24 -24
  144. package/src/node/ssg/index.ts +73 -47
  145. package/src/node/ssg/meta.ts +4 -4
  146. package/src/node/ssg/options.ts +5 -5
  147. package/src/node/ssg/sitemap.ts +14 -14
  148. package/src/node/utils.ts +54 -31
  149. package/tsconfig.json +25 -20
  150. package/tsup.config.ts +23 -14
  151. package/dist/PackageManagerTabs-NVT7G625.mjs +0 -99
  152. package/dist/SearchDialog-AGVF6JBO.mjs +0 -194
  153. package/dist/SearchDialog-YPDOM7Q6.css +0 -2847
  154. package/dist/Video-KNTY5BNO.mjs +0 -6
  155. package/dist/cache-KNL5B4EE.mjs +0 -12
  156. package/dist/chunk-7SFUJWTB.mjs +0 -211
  157. package/dist/chunk-FFBNU6IJ.mjs +0 -386
  158. package/dist/chunk-FMTOYQLO.mjs +0 -37
  159. package/dist/chunk-TKLQWU7H.mjs +0 -1920
  160. package/dist/chunk-Z7JHYNAS.mjs +0 -57
  161. package/dist/client/index.css +0 -2847
  162. package/dist/client/ssr.css +0 -2847
  163. package/dist/types-Dj-bfnC3.d.mts +0 -74
  164. package/dist/types-Dj-bfnC3.d.ts +0 -74
  165. package/src/client/theme/components/CodeBlock/CodeBlock.tsx +0 -61
  166. package/src/client/theme/components/CodeBlock/index.ts +0 -1
  167. package/src/client/theme/components/PackageManagerTabs/PackageManagerTabs.tsx +0 -131
  168. package/src/client/theme/components/PackageManagerTabs/index.ts +0 -1
  169. package/src/client/theme/components/PackageManagerTabs/pkg-tabs.css +0 -64
  170. package/src/client/theme/components/Playground/Playground.tsx +0 -180
  171. package/src/client/theme/components/Playground/index.ts +0 -1
  172. package/src/client/theme/components/Playground/playground.css +0 -238
  173. package/src/client/theme/components/Video/Video.tsx +0 -84
  174. package/src/client/theme/components/Video/index.ts +0 -1
  175. package/src/client/theme/components/Video/video.css +0 -41
  176. package/src/client/theme/components/mdx/Admonition.tsx +0 -80
  177. package/src/client/theme/components/mdx/Badge.tsx +0 -31
  178. package/src/client/theme/components/mdx/Button.tsx +0 -50
  179. package/src/client/theme/components/mdx/Card.tsx +0 -80
  180. package/src/client/theme/components/mdx/Field.tsx +0 -60
  181. package/src/client/theme/components/mdx/FileTree.tsx +0 -229
  182. package/src/client/theme/components/mdx/List.tsx +0 -57
  183. package/src/client/theme/components/mdx/Table.tsx +0 -151
  184. package/src/client/theme/components/mdx/Tabs.tsx +0 -123
  185. package/src/client/theme/components/mdx/index.ts +0 -27
  186. package/src/client/theme/components/mdx/mdx-components.css +0 -764
  187. package/src/client/theme/icons/bun.tsx +0 -62
  188. package/src/client/theme/icons/deno.tsx +0 -20
  189. package/src/client/theme/icons/discord.tsx +0 -12
  190. package/src/client/theme/icons/github.tsx +0 -15
  191. package/src/client/theme/icons/npm.tsx +0 -13
  192. package/src/client/theme/icons/pnpm.tsx +0 -72
  193. package/src/client/theme/icons/twitter.tsx +0 -12
  194. package/src/client/theme/styles/markdown.css +0 -394
  195. package/src/client/theme/styles/variables.css +0 -175
  196. package/src/client/theme/styles.css +0 -39
  197. package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +0 -68
  198. package/src/client/theme/ui/Breadcrumbs/index.ts +0 -1
  199. package/src/client/theme/ui/CopyMarkdown/CopyMarkdown.tsx +0 -82
  200. package/src/client/theme/ui/CopyMarkdown/copy-markdown.css +0 -112
  201. package/src/client/theme/ui/CopyMarkdown/index.ts +0 -1
  202. package/src/client/theme/ui/ErrorBoundary/ErrorBoundary.tsx +0 -50
  203. package/src/client/theme/ui/ErrorBoundary/error-boundary.css +0 -55
  204. package/src/client/theme/ui/ErrorBoundary/index.ts +0 -1
  205. package/src/client/theme/ui/Footer/footer.css +0 -32
  206. package/src/client/theme/ui/Head/Head.tsx +0 -69
  207. package/src/client/theme/ui/Head/index.ts +0 -1
  208. package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +0 -125
  209. package/src/client/theme/ui/LanguageSwitcher/index.ts +0 -1
  210. package/src/client/theme/ui/LanguageSwitcher/language-switcher.css +0 -98
  211. package/src/client/theme/ui/Layout/Layout.tsx +0 -203
  212. package/src/client/theme/ui/Layout/base.css +0 -106
  213. package/src/client/theme/ui/Layout/index.ts +0 -2
  214. package/src/client/theme/ui/Layout/pagination.css +0 -72
  215. package/src/client/theme/ui/Layout/responsive.css +0 -47
  216. package/src/client/theme/ui/Link/Link.tsx +0 -392
  217. package/src/client/theme/ui/Link/LinkPreview.tsx +0 -59
  218. package/src/client/theme/ui/Link/index.ts +0 -2
  219. package/src/client/theme/ui/Link/link-preview.css +0 -48
  220. package/src/client/theme/ui/Loading/Loading.tsx +0 -10
  221. package/src/client/theme/ui/Loading/index.ts +0 -1
  222. package/src/client/theme/ui/Loading/loading.css +0 -30
  223. package/src/client/theme/ui/Navbar/GithubStars.tsx +0 -27
  224. package/src/client/theme/ui/Navbar/Navbar.tsx +0 -193
  225. package/src/client/theme/ui/Navbar/Tabs.tsx +0 -99
  226. package/src/client/theme/ui/Navbar/index.ts +0 -2
  227. package/src/client/theme/ui/Navbar/navbar.css +0 -347
  228. package/src/client/theme/ui/NotFound/NotFound.tsx +0 -19
  229. package/src/client/theme/ui/NotFound/index.ts +0 -1
  230. package/src/client/theme/ui/NotFound/not-found.css +0 -64
  231. package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +0 -244
  232. package/src/client/theme/ui/OnThisPage/index.ts +0 -1
  233. package/src/client/theme/ui/OnThisPage/toc.css +0 -152
  234. package/src/client/theme/ui/PoweredBy/PoweredBy.tsx +0 -18
  235. package/src/client/theme/ui/PoweredBy/index.ts +0 -1
  236. package/src/client/theme/ui/PoweredBy/powered-by.css +0 -76
  237. package/src/client/theme/ui/ProgressBar/ProgressBar.css +0 -17
  238. package/src/client/theme/ui/ProgressBar/ProgressBar.tsx +0 -51
  239. package/src/client/theme/ui/ProgressBar/index.ts +0 -1
  240. package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +0 -209
  241. package/src/client/theme/ui/SearchDialog/index.ts +0 -1
  242. package/src/client/theme/ui/SearchDialog/search.css +0 -152
  243. package/src/client/theme/ui/Sidebar/Sidebar.tsx +0 -244
  244. package/src/client/theme/ui/Sidebar/index.ts +0 -1
  245. package/src/client/theme/ui/Sidebar/sidebar.css +0 -230
  246. package/src/client/theme/ui/ThemeToggle/ThemeToggle.tsx +0 -69
  247. package/src/client/theme/ui/ThemeToggle/index.ts +0 -1
  248. package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +0 -136
  249. package/src/client/theme/ui/VersionSwitcher/index.ts +0 -1
  250. package/src/client/utils.ts +0 -49
@@ -1,392 +0,0 @@
1
- import React from "react";
2
- import {
3
- Link as RouterLink,
4
- NavLink as RouterNavLink,
5
- LinkProps as RouterLinkProps,
6
- NavLinkProps as RouterNavLinkProps,
7
- useLocation,
8
- useNavigate,
9
- } from "react-router-dom";
10
- import { usePreload } from "../../../app/preload";
11
- import { useConfig } from "../../../app";
12
-
13
- function useLocalizedTo(to: RouterLinkProps["to"]) {
14
- const location = useLocation();
15
- const config = useConfig();
16
- if (!config || typeof to !== "string") return to;
17
- if (!config.i18n && !config.versions) return to;
18
-
19
- const basePath = "/docs";
20
- if (!to.startsWith(basePath)) return to;
21
-
22
- // 1. Detect current context from location
23
- const curSub = location.pathname.substring(basePath.length);
24
- const curParts = curSub.split("/").filter(Boolean);
25
-
26
- let currentVersion = config.versions?.defaultVersion;
27
- let currentLocale = config.i18n?.defaultLocale;
28
-
29
- let cIdx = 0;
30
- if (
31
- config.versions &&
32
- curParts.length > cIdx &&
33
- config.versions.versions[curParts[cIdx]]
34
- ) {
35
- currentVersion = curParts[cIdx];
36
- cIdx++;
37
- }
38
- if (
39
- config.i18n &&
40
- curParts.length > cIdx &&
41
- config.i18n.locales[curParts[cIdx]]
42
- ) {
43
- currentLocale = curParts[cIdx];
44
- }
45
-
46
- // 2. Parse the target `to` path
47
- const toSub = to.substring(basePath.length);
48
- const toParts = toSub.split("/").filter(Boolean);
49
-
50
- let tIdx = 0;
51
- let hasVersion = false;
52
- let hasLocale = false;
53
-
54
- if (
55
- config.versions &&
56
- toParts.length > tIdx &&
57
- config.versions.versions[toParts[tIdx]]
58
- ) {
59
- hasVersion = true;
60
- tIdx++;
61
- }
62
- if (
63
- config.i18n &&
64
- toParts.length > tIdx &&
65
- config.i18n.locales[toParts[tIdx]]
66
- ) {
67
- hasLocale = true;
68
- tIdx++;
69
- }
70
-
71
- // Extract just the actual route parts
72
- const routeParts = toParts.slice(tIdx);
73
-
74
- // Reconstruct path
75
- const finalParts = [];
76
- if (config.versions) {
77
- if (hasVersion) {
78
- finalParts.push(toParts[0]);
79
- } else if (currentVersion) {
80
- finalParts.push(currentVersion);
81
- }
82
- }
83
- if (config.i18n) {
84
- if (hasLocale) {
85
- finalParts.push(toParts[hasVersion ? 1 : 0]);
86
- } else if (currentLocale) {
87
- finalParts.push(currentLocale);
88
- }
89
- }
90
-
91
- finalParts.push(...routeParts);
92
-
93
- let finalPath = `${basePath}/${finalParts.join("/")}`;
94
- if (finalPath.endsWith("/")) {
95
- finalPath = finalPath.slice(0, -1);
96
- }
97
- return finalPath === basePath ? basePath : finalPath;
98
- }
99
-
100
- import { LinkPreview } from "./LinkPreview";
101
-
102
- export interface LinkProps extends Omit<RouterLinkProps, "prefetch"> {
103
- /** Should prefetch the page on hover? Options: 'hover' | 'none'. Default 'hover' */
104
- boltdocsPrefetch?: "hover" | "none";
105
- /** Should show a preview tooltip on hover? Default true */
106
- boltdocsPreview?: boolean;
107
- }
108
-
109
- export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
110
- (props, ref) => {
111
- const {
112
- boltdocsPrefetch = "hover",
113
- boltdocsPreview = true,
114
- onMouseEnter,
115
- onMouseLeave,
116
- onFocus,
117
- onBlur,
118
- onClick,
119
- to,
120
- ...rest
121
- } = props;
122
- const localizedTo = useLocalizedTo(to);
123
- const { preload, routes } = usePreload();
124
- const config = useConfig();
125
- const navigate = useNavigate();
126
-
127
- const shouldShowPreview =
128
- boltdocsPreview && config?.themeConfig?.linkPreview !== false;
129
-
130
- const [preview, setPreview] = React.useState<{
131
- visible: boolean;
132
- x: number;
133
- y: number;
134
- title: string;
135
- summary?: string;
136
- }>({ visible: false, x: 0, y: 0, title: "" });
137
-
138
- const handleMouseEnter = (e: React.MouseEvent<HTMLAnchorElement>) => {
139
- onMouseEnter?.(e);
140
- if (
141
- boltdocsPrefetch === "hover" &&
142
- typeof localizedTo === "string" &&
143
- localizedTo.startsWith("/")
144
- ) {
145
- preload(localizedTo);
146
- }
147
-
148
- if (
149
- shouldShowPreview &&
150
- typeof localizedTo === "string" &&
151
- localizedTo.startsWith("/")
152
- ) {
153
- const cleanPath = localizedTo.split("#")[0].split("?")[0];
154
- const route = routes.find(
155
- (r) => r.path === cleanPath || (cleanPath === "/" && r.path === ""),
156
- );
157
- if (route) {
158
- setPreview({
159
- visible: true,
160
- x: e.clientX,
161
- y: e.clientY,
162
- title: route.title,
163
- summary: route.description,
164
- });
165
- }
166
- }
167
- };
168
-
169
- const handleMouseMove = (e: React.MouseEvent<HTMLAnchorElement>) => {
170
- if (preview.visible) {
171
- setPreview((prev) => ({ ...prev, x: e.clientX, y: e.clientY }));
172
- }
173
- };
174
-
175
- const handleMouseLeave = (e: React.MouseEvent<HTMLAnchorElement>) => {
176
- onMouseLeave?.(e);
177
- setPreview((prev) => ({ ...prev, visible: false }));
178
- };
179
-
180
- const handleFocus = (e: React.FocusEvent<HTMLAnchorElement>) => {
181
- onFocus?.(e);
182
- if (
183
- boltdocsPrefetch === "hover" &&
184
- typeof localizedTo === "string" &&
185
- localizedTo.startsWith("/")
186
- ) {
187
- preload(localizedTo);
188
- }
189
- };
190
-
191
- const handleBlur = (e: React.FocusEvent<HTMLAnchorElement>) => {
192
- onBlur?.(e);
193
- setPreview((prev) => ({ ...prev, visible: false }));
194
- };
195
-
196
- const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
197
- // Allow user onClick to handle defaults or custom logic
198
- onClick?.(e);
199
- setPreview((prev) => ({ ...prev, visible: false }));
200
-
201
- // If default prevented or not a simple left click, don't handle
202
- if (
203
- e.defaultPrevented ||
204
- e.button !== 0 ||
205
- e.metaKey ||
206
- e.ctrlKey ||
207
- e.shiftKey ||
208
- e.altKey
209
- ) {
210
- return;
211
- }
212
-
213
- // Intercept navigation to wrap in startTransition
214
- if (typeof localizedTo === "string" && !localizedTo.startsWith("http")) {
215
- e.preventDefault();
216
- React.startTransition(() => {
217
- navigate(localizedTo);
218
- });
219
- }
220
- };
221
-
222
- return (
223
- <>
224
- <RouterLink
225
- ref={ref}
226
- to={localizedTo}
227
- onMouseEnter={handleMouseEnter}
228
- onMouseMove={handleMouseMove}
229
- onMouseLeave={handleMouseLeave}
230
- onFocus={handleFocus}
231
- onBlur={handleBlur}
232
- onClick={handleClick}
233
- {...rest}
234
- />
235
- {preview.visible && shouldShowPreview && (
236
- <LinkPreview
237
- isVisible={preview.visible}
238
- title={preview.title}
239
- summary={preview.summary}
240
- x={preview.x}
241
- y={preview.y}
242
- />
243
- )}
244
- </>
245
- );
246
- },
247
- );
248
- Link.displayName = "Link";
249
-
250
- export interface NavLinkProps extends Omit<RouterNavLinkProps, "prefetch"> {
251
- /** Should prefetch the page on hover? Options: 'hover' | 'none'. Default 'hover' */
252
- boltdocsPrefetch?: "hover" | "none";
253
- /** Should show a preview tooltip on hover? Default true */
254
- boltdocsPreview?: boolean;
255
- }
256
-
257
- export const NavLink = React.forwardRef<HTMLAnchorElement, NavLinkProps>(
258
- (props, ref) => {
259
- const {
260
- boltdocsPrefetch = "hover",
261
- boltdocsPreview = true,
262
- onMouseEnter,
263
- onMouseLeave,
264
- onFocus,
265
- onBlur,
266
- onClick,
267
- to,
268
- ...rest
269
- } = props;
270
-
271
- const localizedTo = useLocalizedTo(to);
272
- const { preload, routes } = usePreload();
273
- const config = useConfig();
274
- const navigate = useNavigate();
275
-
276
- const shouldShowPreview =
277
- boltdocsPreview && config?.themeConfig?.linkPreview !== false;
278
-
279
- const [preview, setPreview] = React.useState<{
280
- visible: boolean;
281
- x: number;
282
- y: number;
283
- title: string;
284
- summary?: string;
285
- }>({ visible: false, x: 0, y: 0, title: "" });
286
-
287
- const handleMouseEnter = (e: React.MouseEvent<HTMLAnchorElement>) => {
288
- onMouseEnter?.(e);
289
- if (
290
- boltdocsPrefetch === "hover" &&
291
- typeof localizedTo === "string" &&
292
- localizedTo.startsWith("/")
293
- ) {
294
- preload(localizedTo);
295
- }
296
-
297
- if (
298
- shouldShowPreview &&
299
- typeof localizedTo === "string" &&
300
- localizedTo.startsWith("/")
301
- ) {
302
- const cleanPath = localizedTo.split("#")[0].split("?")[0];
303
- const route = routes.find(
304
- (r) => r.path === cleanPath || (cleanPath === "/" && r.path === ""),
305
- );
306
- if (route) {
307
- setPreview({
308
- visible: true,
309
- x: e.clientX,
310
- y: e.clientY,
311
- title: route.title,
312
- summary: route.description,
313
- });
314
- }
315
- }
316
- };
317
-
318
- const handleMouseMove = (e: React.MouseEvent<HTMLAnchorElement>) => {
319
- if (preview.visible) {
320
- setPreview((prev) => ({ ...prev, x: e.clientX, y: e.clientY }));
321
- }
322
- };
323
-
324
- const handleMouseLeave = (e: React.MouseEvent<HTMLAnchorElement>) => {
325
- onMouseLeave?.(e);
326
- setPreview((prev) => ({ ...prev, visible: false }));
327
- };
328
-
329
- const handleFocus = (e: React.FocusEvent<HTMLAnchorElement>) => {
330
- onFocus?.(e);
331
- if (
332
- boltdocsPrefetch === "hover" &&
333
- typeof localizedTo === "string" &&
334
- localizedTo.startsWith("/")
335
- ) {
336
- preload(localizedTo);
337
- }
338
- };
339
-
340
- const handleBlur = (e: React.FocusEvent<HTMLAnchorElement>) => {
341
- onBlur?.(e);
342
- setPreview((prev) => ({ ...prev, visible: false }));
343
- };
344
-
345
- const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
346
- onClick?.(e);
347
- setPreview((prev) => ({ ...prev, visible: false }));
348
- if (
349
- e.defaultPrevented ||
350
- e.button !== 0 ||
351
- e.metaKey ||
352
- e.ctrlKey ||
353
- e.shiftKey ||
354
- e.altKey
355
- ) {
356
- return;
357
- }
358
- if (typeof localizedTo === "string" && !localizedTo.startsWith("http")) {
359
- e.preventDefault();
360
- React.startTransition(() => {
361
- navigate(localizedTo);
362
- });
363
- }
364
- };
365
-
366
- return (
367
- <>
368
- <RouterNavLink
369
- ref={ref}
370
- to={localizedTo}
371
- onMouseEnter={handleMouseEnter}
372
- onMouseMove={handleMouseMove}
373
- onMouseLeave={handleMouseLeave}
374
- onFocus={handleFocus}
375
- onBlur={handleBlur}
376
- onClick={handleClick}
377
- {...rest}
378
- />
379
- {preview.visible && shouldShowPreview && (
380
- <LinkPreview
381
- isVisible={preview.visible}
382
- title={preview.title}
383
- summary={preview.summary}
384
- x={preview.x}
385
- y={preview.y}
386
- />
387
- )}
388
- </>
389
- );
390
- },
391
- );
392
- NavLink.displayName = "NavLink";
@@ -1,59 +0,0 @@
1
- import { useEffect, useState, useRef } from "react";
2
- import { createPortal } from "react-dom";
3
- import "./link-preview.css";
4
-
5
- interface LinkPreviewProps {
6
- isVisible: boolean;
7
- title: string;
8
- summary?: string;
9
- x: number;
10
- y: number;
11
- }
12
-
13
- export function LinkPreview({
14
- isVisible,
15
- title,
16
- summary,
17
- x,
18
- y,
19
- }: LinkPreviewProps) {
20
- const ref = useRef<HTMLDivElement>(null);
21
- const [position, setPosition] = useState({ top: 0, left: 0 });
22
-
23
- useEffect(() => {
24
- if (ref.current) {
25
- const rect = ref.current.getBoundingClientRect();
26
- const padding = 12;
27
-
28
- let top = y + padding;
29
- let left = x + padding;
30
-
31
- // Keep within viewport
32
- if (left + rect.width > window.innerWidth - 20) {
33
- left = x - rect.width - padding;
34
- }
35
- if (top + rect.height > window.innerHeight - 20) {
36
- top = y - rect.height - padding;
37
- }
38
-
39
- setPosition({ top, left });
40
- }
41
- }, [x, y, isVisible]);
42
-
43
- return createPortal(
44
- <div
45
- ref={ref}
46
- className={`boltdocs-link-preview ${isVisible ? "is-visible" : ""}`}
47
- style={{
48
- top: position.top,
49
- left: position.left,
50
- }}
51
- >
52
- <div className="boltdocs-link-preview-content">
53
- <span className="boltdocs-link-preview-title">{title}</span>
54
- {summary && <p className="boltdocs-link-preview-summary">{summary}</p>}
55
- </div>
56
- </div>,
57
- document.body,
58
- );
59
- }
@@ -1,2 +0,0 @@
1
- export { Link, NavLink } from "./Link";
2
- export type { LinkProps, NavLinkProps } from "./Link";
@@ -1,48 +0,0 @@
1
- .boltdocs-link-preview {
2
- position: fixed;
3
- z-index: 1000;
4
- width: 260px;
5
- pointer-events: none;
6
- opacity: 0;
7
- transform: translateY(8px) scale(0.98);
8
- transition:
9
- opacity 0.15s cubic-bezier(0.4, 0, 0.2, 1),
10
- transform 0.15s cubic-bezier(0.4, 0, 0.2, 1);
11
- font-family: var(--ld-font-sans);
12
- }
13
-
14
- .boltdocs-link-preview.is-visible {
15
- opacity: 1;
16
- transform: translateY(0) scale(1);
17
- }
18
-
19
- .boltdocs-link-preview-content {
20
- padding: 0.85rem 1rem;
21
- background-color: var(--ld-navbar-bg);
22
- border: 1px solid var(--ld-border-subtle);
23
- border-radius: var(--ld-radius-lg);
24
- box-shadow:
25
- 0 10px 30px -10px rgba(0, 0, 0, 0.2),
26
- 0 4px 10px -5px rgba(0, 0, 0, 0.1);
27
- }
28
-
29
- .boltdocs-link-preview-title {
30
- display: block;
31
- font-weight: 600;
32
- font-size: 0.875rem;
33
- color: var(--ld-text-main);
34
- margin-bottom: 0.35rem;
35
- line-height: 1.3;
36
- }
37
-
38
- .boltdocs-link-preview-summary {
39
- display: block;
40
- font-size: 0.775rem;
41
- color: var(--ld-text-muted);
42
- line-height: 1.5;
43
- display: -webkit-box;
44
- -webkit-line-clamp: 3;
45
- line-clamp: 3;
46
- -webkit-box-orient: vertical;
47
- overflow: hidden;
48
- }
@@ -1,10 +0,0 @@
1
- import React from 'react';
2
-
3
- export function Loading() {
4
- return (
5
- <div className="boltdocs-loading">
6
- <div className="loading-spinner" />
7
- <p className="loading-text">Loading...</p>
8
- </div>
9
- );
10
- }
@@ -1 +0,0 @@
1
- export { Loading } from "./Loading";
@@ -1,30 +0,0 @@
1
- /* ─── Loading ─────────────────────────────────────────────── */
2
- .boltdocs-loading {
3
- display: flex;
4
- flex-direction: column;
5
- align-items: center;
6
- justify-content: center;
7
- min-height: 40vh;
8
- gap: 1rem;
9
- }
10
-
11
- .loading-spinner {
12
- width: 2.5rem;
13
- height: 2.5rem;
14
- border: 3px solid var(--ld-border-subtle);
15
- border-top-color: var(--ld-color-primary);
16
- border-radius: 50%;
17
- animation: boltdocs-spin 0.7s linear infinite;
18
- }
19
-
20
- @keyframes boltdocs-spin {
21
- to {
22
- transform: rotate(360deg);
23
- }
24
- }
25
-
26
- .loading-text {
27
- font-size: 0.875rem;
28
- color: var(--ld-text-dim);
29
- margin: 0;
30
- }
@@ -1,27 +0,0 @@
1
- import { useEffect, useState } from "react";
2
- import { GitHub } from "../../icons/github";
3
- import { getStarsRepo } from "../../../utils";
4
-
5
- export function GithubStars({ repo }: { repo: string }) {
6
- const [stars, setStars] = useState<string | null>(null);
7
-
8
- useEffect(() => {
9
- if (repo) {
10
- getStarsRepo(repo)
11
- .then((stars) => setStars(stars))
12
- .catch(() => setStars("0"));
13
- }
14
- }, [repo]);
15
-
16
- return (
17
- <a
18
- href={`https://github.com/${repo}`}
19
- target="_blank"
20
- rel="noopener noreferrer"
21
- className="navbar-github-stars"
22
- >
23
- <GitHub />
24
- {stars && <span>{stars}</span>}
25
- </a>
26
- );
27
- }