boltdocs 1.10.2 → 1.11.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 (225) hide show
  1. package/package.json +29 -7
  2. package/src/client/app/config-context.tsx +18 -0
  3. package/src/client/app/docs-layout.tsx +14 -0
  4. package/src/client/app/index.tsx +132 -260
  5. package/src/client/app/mdx-component.tsx +52 -0
  6. package/src/client/app/mdx-components-context.tsx +23 -0
  7. package/src/client/app/mdx-page.tsx +20 -0
  8. package/src/client/app/preload.tsx +38 -30
  9. package/src/client/app/router.tsx +30 -0
  10. package/src/client/app/scroll-handler.tsx +40 -0
  11. package/src/client/app/theme-context.tsx +75 -0
  12. package/src/client/components/default-layout.tsx +80 -0
  13. package/src/client/components/docs-layout.tsx +105 -0
  14. package/src/client/components/icons-dev.tsx +74 -0
  15. package/src/client/components/mdx/admonition.tsx +107 -0
  16. package/src/client/components/mdx/badge.tsx +41 -0
  17. package/src/client/components/mdx/button.tsx +35 -0
  18. package/src/client/components/mdx/card.tsx +124 -0
  19. package/src/client/components/mdx/code-block.tsx +119 -0
  20. package/src/client/components/mdx/component-preview.tsx +47 -0
  21. package/src/client/components/mdx/component-props.tsx +83 -0
  22. package/src/client/components/mdx/field.tsx +66 -0
  23. package/src/client/components/mdx/file-tree.tsx +287 -0
  24. package/src/client/components/mdx/hooks/use-code-block.ts +56 -0
  25. package/src/client/components/mdx/hooks/use-component-preview.ts +16 -0
  26. package/src/client/components/mdx/hooks/useTable.ts +74 -0
  27. package/src/client/components/mdx/hooks/useTabs.ts +68 -0
  28. package/src/client/components/mdx/image.tsx +23 -0
  29. package/src/client/components/mdx/index.ts +53 -0
  30. package/src/client/components/mdx/link.tsx +38 -0
  31. package/src/client/components/mdx/list.tsx +192 -0
  32. package/src/client/components/mdx/table.tsx +156 -0
  33. package/src/client/components/mdx/tabs.tsx +135 -0
  34. package/src/client/components/mdx/video.tsx +68 -0
  35. package/src/client/components/primitives/breadcrumbs.tsx +79 -0
  36. package/src/client/components/primitives/button-group.tsx +54 -0
  37. package/src/client/components/primitives/button.tsx +145 -0
  38. package/src/client/components/primitives/helpers/observer.ts +120 -0
  39. package/src/client/components/primitives/index.ts +17 -0
  40. package/src/client/components/primitives/link.tsx +122 -0
  41. package/src/client/components/primitives/menu.tsx +159 -0
  42. package/src/client/components/primitives/navbar.tsx +359 -0
  43. package/src/client/components/primitives/navigation-menu.tsx +116 -0
  44. package/src/client/components/primitives/on-this-page.tsx +461 -0
  45. package/src/client/components/primitives/page-nav.tsx +87 -0
  46. package/src/client/components/primitives/popover.tsx +47 -0
  47. package/src/client/components/primitives/search-dialog.tsx +183 -0
  48. package/src/client/components/primitives/sidebar.tsx +154 -0
  49. package/src/client/components/primitives/tabs.tsx +90 -0
  50. package/src/client/components/primitives/tooltip.tsx +83 -0
  51. package/src/client/components/primitives/types.ts +11 -0
  52. package/src/client/components/ui-base/breadcrumbs.tsx +42 -0
  53. package/src/client/components/ui-base/copy-markdown.tsx +112 -0
  54. package/src/client/components/ui-base/error-boundary.tsx +52 -0
  55. package/src/client/components/ui-base/github-stars.tsx +27 -0
  56. package/src/client/components/ui-base/head.tsx +69 -0
  57. package/src/client/components/ui-base/loading.tsx +87 -0
  58. package/src/client/components/ui-base/navbar.tsx +138 -0
  59. package/src/client/components/ui-base/not-found.tsx +24 -0
  60. package/src/client/components/ui-base/on-this-page.tsx +152 -0
  61. package/src/client/components/ui-base/page-nav.tsx +39 -0
  62. package/src/client/components/ui-base/powered-by.tsx +19 -0
  63. package/src/client/components/ui-base/progress-bar.tsx +67 -0
  64. package/src/client/components/ui-base/search-dialog.tsx +82 -0
  65. package/src/client/components/ui-base/sidebar.tsx +104 -0
  66. package/src/client/components/ui-base/tabs.tsx +65 -0
  67. package/src/client/components/ui-base/theme-toggle.tsx +32 -0
  68. package/src/client/hooks/index.ts +12 -0
  69. package/src/client/hooks/use-breadcrumbs.ts +22 -0
  70. package/src/client/hooks/use-i18n.ts +84 -0
  71. package/src/client/hooks/use-localized-to.ts +95 -0
  72. package/src/client/hooks/use-location.ts +5 -0
  73. package/src/client/hooks/use-navbar.ts +60 -0
  74. package/src/client/hooks/use-onthispage.ts +23 -0
  75. package/src/client/hooks/use-page-nav.ts +22 -0
  76. package/src/client/hooks/use-routes.ts +72 -0
  77. package/src/client/hooks/use-search.ts +71 -0
  78. package/src/client/hooks/use-sidebar.ts +49 -0
  79. package/src/client/hooks/use-tabs.ts +43 -0
  80. package/src/client/hooks/use-version.ts +78 -0
  81. package/src/client/index.ts +55 -17
  82. package/src/client/integrations/codesandbox.ts +179 -0
  83. package/src/client/ssr.tsx +27 -16
  84. package/src/client/theme/neutral.css +360 -0
  85. package/src/client/types.ts +131 -27
  86. package/src/client/utils/cn.ts +6 -0
  87. package/src/client/utils/copy-clipboard.ts +22 -0
  88. package/src/client/utils/get-base-file-path.ts +21 -0
  89. package/src/client/utils/github.ts +121 -0
  90. package/src/client/utils/use-on-change.ts +15 -0
  91. package/src/client/virtual.d.ts +24 -0
  92. package/src/node/cache.ts +156 -156
  93. package/src/node/config.ts +159 -103
  94. package/src/node/index.ts +13 -13
  95. package/src/node/mdx.ts +213 -61
  96. package/src/node/plugin/entry.ts +29 -18
  97. package/src/node/plugin/html.ts +11 -11
  98. package/src/node/plugin/index.ts +161 -83
  99. package/src/node/plugin/types.ts +2 -4
  100. package/src/node/routes/cache.ts +6 -6
  101. package/src/node/routes/index.ts +206 -113
  102. package/src/node/routes/parser.ts +106 -81
  103. package/src/node/routes/sorter.ts +15 -15
  104. package/src/node/routes/types.ts +24 -24
  105. package/src/node/ssg/index.ts +46 -46
  106. package/src/node/ssg/meta.ts +4 -4
  107. package/src/node/ssg/options.ts +5 -5
  108. package/src/node/ssg/sitemap.ts +14 -14
  109. package/src/node/utils.ts +31 -31
  110. package/tsconfig.json +25 -20
  111. package/tsup.config.ts +23 -14
  112. package/dist/PackageManagerTabs-NVT7G625.mjs +0 -99
  113. package/dist/SearchDialog-AGVF6JBO.mjs +0 -194
  114. package/dist/SearchDialog-YPDOM7Q6.css +0 -2847
  115. package/dist/Video-KNTY5BNO.mjs +0 -6
  116. package/dist/cache-KNL5B4EE.mjs +0 -12
  117. package/dist/chunk-7SFUJWTB.mjs +0 -211
  118. package/dist/chunk-FFBNU6IJ.mjs +0 -386
  119. package/dist/chunk-FMTOYQLO.mjs +0 -37
  120. package/dist/chunk-TKLQWU7H.mjs +0 -1920
  121. package/dist/chunk-Z7JHYNAS.mjs +0 -57
  122. package/dist/client/index.css +0 -2847
  123. package/dist/client/index.d.mts +0 -372
  124. package/dist/client/index.d.ts +0 -372
  125. package/dist/client/index.js +0 -3630
  126. package/dist/client/index.mjs +0 -697
  127. package/dist/client/ssr.css +0 -2847
  128. package/dist/client/ssr.d.mts +0 -27
  129. package/dist/client/ssr.d.ts +0 -27
  130. package/dist/client/ssr.js +0 -2928
  131. package/dist/client/ssr.mjs +0 -33
  132. package/dist/config-BsFQ-ErD.d.mts +0 -159
  133. package/dist/config-BsFQ-ErD.d.ts +0 -159
  134. package/dist/node/index.d.mts +0 -91
  135. package/dist/node/index.d.ts +0 -91
  136. package/dist/node/index.js +0 -1187
  137. package/dist/node/index.mjs +0 -762
  138. package/dist/types-Dj-bfnC3.d.mts +0 -74
  139. package/dist/types-Dj-bfnC3.d.ts +0 -74
  140. package/src/client/theme/components/CodeBlock/CodeBlock.tsx +0 -61
  141. package/src/client/theme/components/CodeBlock/index.ts +0 -1
  142. package/src/client/theme/components/PackageManagerTabs/PackageManagerTabs.tsx +0 -131
  143. package/src/client/theme/components/PackageManagerTabs/index.ts +0 -1
  144. package/src/client/theme/components/PackageManagerTabs/pkg-tabs.css +0 -64
  145. package/src/client/theme/components/Playground/Playground.tsx +0 -180
  146. package/src/client/theme/components/Playground/index.ts +0 -1
  147. package/src/client/theme/components/Playground/playground.css +0 -238
  148. package/src/client/theme/components/Video/Video.tsx +0 -84
  149. package/src/client/theme/components/Video/index.ts +0 -1
  150. package/src/client/theme/components/Video/video.css +0 -41
  151. package/src/client/theme/components/mdx/Admonition.tsx +0 -80
  152. package/src/client/theme/components/mdx/Badge.tsx +0 -31
  153. package/src/client/theme/components/mdx/Button.tsx +0 -50
  154. package/src/client/theme/components/mdx/Card.tsx +0 -80
  155. package/src/client/theme/components/mdx/Field.tsx +0 -60
  156. package/src/client/theme/components/mdx/FileTree.tsx +0 -229
  157. package/src/client/theme/components/mdx/List.tsx +0 -57
  158. package/src/client/theme/components/mdx/Table.tsx +0 -151
  159. package/src/client/theme/components/mdx/Tabs.tsx +0 -123
  160. package/src/client/theme/components/mdx/index.ts +0 -27
  161. package/src/client/theme/components/mdx/mdx-components.css +0 -764
  162. package/src/client/theme/icons/bun.tsx +0 -62
  163. package/src/client/theme/icons/deno.tsx +0 -20
  164. package/src/client/theme/icons/discord.tsx +0 -12
  165. package/src/client/theme/icons/github.tsx +0 -15
  166. package/src/client/theme/icons/npm.tsx +0 -13
  167. package/src/client/theme/icons/pnpm.tsx +0 -72
  168. package/src/client/theme/icons/twitter.tsx +0 -12
  169. package/src/client/theme/styles/markdown.css +0 -394
  170. package/src/client/theme/styles/variables.css +0 -175
  171. package/src/client/theme/styles.css +0 -39
  172. package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +0 -68
  173. package/src/client/theme/ui/Breadcrumbs/index.ts +0 -1
  174. package/src/client/theme/ui/CopyMarkdown/CopyMarkdown.tsx +0 -82
  175. package/src/client/theme/ui/CopyMarkdown/copy-markdown.css +0 -112
  176. package/src/client/theme/ui/CopyMarkdown/index.ts +0 -1
  177. package/src/client/theme/ui/ErrorBoundary/ErrorBoundary.tsx +0 -50
  178. package/src/client/theme/ui/ErrorBoundary/error-boundary.css +0 -55
  179. package/src/client/theme/ui/ErrorBoundary/index.ts +0 -1
  180. package/src/client/theme/ui/Footer/footer.css +0 -32
  181. package/src/client/theme/ui/Head/Head.tsx +0 -69
  182. package/src/client/theme/ui/Head/index.ts +0 -1
  183. package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +0 -125
  184. package/src/client/theme/ui/LanguageSwitcher/index.ts +0 -1
  185. package/src/client/theme/ui/LanguageSwitcher/language-switcher.css +0 -98
  186. package/src/client/theme/ui/Layout/Layout.tsx +0 -203
  187. package/src/client/theme/ui/Layout/base.css +0 -106
  188. package/src/client/theme/ui/Layout/index.ts +0 -2
  189. package/src/client/theme/ui/Layout/pagination.css +0 -72
  190. package/src/client/theme/ui/Layout/responsive.css +0 -47
  191. package/src/client/theme/ui/Link/Link.tsx +0 -392
  192. package/src/client/theme/ui/Link/LinkPreview.tsx +0 -59
  193. package/src/client/theme/ui/Link/index.ts +0 -2
  194. package/src/client/theme/ui/Link/link-preview.css +0 -48
  195. package/src/client/theme/ui/Loading/Loading.tsx +0 -10
  196. package/src/client/theme/ui/Loading/index.ts +0 -1
  197. package/src/client/theme/ui/Loading/loading.css +0 -30
  198. package/src/client/theme/ui/Navbar/GithubStars.tsx +0 -27
  199. package/src/client/theme/ui/Navbar/Navbar.tsx +0 -193
  200. package/src/client/theme/ui/Navbar/Tabs.tsx +0 -99
  201. package/src/client/theme/ui/Navbar/index.ts +0 -2
  202. package/src/client/theme/ui/Navbar/navbar.css +0 -347
  203. package/src/client/theme/ui/NotFound/NotFound.tsx +0 -19
  204. package/src/client/theme/ui/NotFound/index.ts +0 -1
  205. package/src/client/theme/ui/NotFound/not-found.css +0 -64
  206. package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +0 -244
  207. package/src/client/theme/ui/OnThisPage/index.ts +0 -1
  208. package/src/client/theme/ui/OnThisPage/toc.css +0 -152
  209. package/src/client/theme/ui/PoweredBy/PoweredBy.tsx +0 -18
  210. package/src/client/theme/ui/PoweredBy/index.ts +0 -1
  211. package/src/client/theme/ui/PoweredBy/powered-by.css +0 -76
  212. package/src/client/theme/ui/ProgressBar/ProgressBar.css +0 -17
  213. package/src/client/theme/ui/ProgressBar/ProgressBar.tsx +0 -51
  214. package/src/client/theme/ui/ProgressBar/index.ts +0 -1
  215. package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +0 -209
  216. package/src/client/theme/ui/SearchDialog/index.ts +0 -1
  217. package/src/client/theme/ui/SearchDialog/search.css +0 -152
  218. package/src/client/theme/ui/Sidebar/Sidebar.tsx +0 -244
  219. package/src/client/theme/ui/Sidebar/index.ts +0 -1
  220. package/src/client/theme/ui/Sidebar/sidebar.css +0 -230
  221. package/src/client/theme/ui/ThemeToggle/ThemeToggle.tsx +0 -69
  222. package/src/client/theme/ui/ThemeToggle/index.ts +0 -1
  223. package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +0 -136
  224. package/src/client/theme/ui/VersionSwitcher/index.ts +0 -1
  225. 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
- }