boltdocs 1.10.1 → 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 (226) 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 -18
  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-BEVZQ74P.css +0 -2679
  114. package/dist/SearchDialog-MEWGAONO.mjs +0 -194
  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-OZLYRXAD.mjs +0 -1914
  121. package/dist/chunk-Z7JHYNAS.mjs +0 -57
  122. package/dist/client/index.css +0 -2679
  123. package/dist/client/index.d.mts +0 -379
  124. package/dist/client/index.d.ts +0 -379
  125. package/dist/client/index.js +0 -3594
  126. package/dist/client/index.mjs +0 -658
  127. package/dist/client/ssr.css +0 -2679
  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 -2930
  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 -40
  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 -124
  146. package/src/client/theme/components/Playground/index.ts +0 -1
  147. package/src/client/theme/components/Playground/playground.css +0 -168
  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 -341
  170. package/src/client/theme/styles/variables.css +0 -187
  171. package/src/client/theme/styles.css +0 -38
  172. package/src/client/theme/ui/BackgroundGradient/BackgroundGradient.tsx +0 -10
  173. package/src/client/theme/ui/BackgroundGradient/index.ts +0 -1
  174. package/src/client/theme/ui/Breadcrumbs/Breadcrumbs.tsx +0 -68
  175. package/src/client/theme/ui/Breadcrumbs/index.ts +0 -1
  176. package/src/client/theme/ui/CopyMarkdown/CopyMarkdown.tsx +0 -82
  177. package/src/client/theme/ui/CopyMarkdown/copy-markdown.css +0 -114
  178. package/src/client/theme/ui/CopyMarkdown/index.ts +0 -1
  179. package/src/client/theme/ui/ErrorBoundary/ErrorBoundary.tsx +0 -46
  180. package/src/client/theme/ui/ErrorBoundary/index.ts +0 -1
  181. package/src/client/theme/ui/Footer/footer.css +0 -32
  182. package/src/client/theme/ui/Head/Head.tsx +0 -69
  183. package/src/client/theme/ui/Head/index.ts +0 -1
  184. package/src/client/theme/ui/LanguageSwitcher/LanguageSwitcher.tsx +0 -125
  185. package/src/client/theme/ui/LanguageSwitcher/index.ts +0 -1
  186. package/src/client/theme/ui/LanguageSwitcher/language-switcher.css +0 -98
  187. package/src/client/theme/ui/Layout/Layout.tsx +0 -208
  188. package/src/client/theme/ui/Layout/base.css +0 -105
  189. package/src/client/theme/ui/Layout/index.ts +0 -2
  190. package/src/client/theme/ui/Layout/pagination.css +0 -72
  191. package/src/client/theme/ui/Layout/responsive.css +0 -36
  192. package/src/client/theme/ui/Link/Link.tsx +0 -392
  193. package/src/client/theme/ui/Link/LinkPreview.tsx +0 -59
  194. package/src/client/theme/ui/Link/index.ts +0 -2
  195. package/src/client/theme/ui/Link/link-preview.css +0 -48
  196. package/src/client/theme/ui/Loading/Loading.tsx +0 -10
  197. package/src/client/theme/ui/Loading/index.ts +0 -1
  198. package/src/client/theme/ui/Loading/loading.css +0 -30
  199. package/src/client/theme/ui/Navbar/GithubStars.tsx +0 -27
  200. package/src/client/theme/ui/Navbar/Navbar.tsx +0 -193
  201. package/src/client/theme/ui/Navbar/Tabs.tsx +0 -99
  202. package/src/client/theme/ui/Navbar/index.ts +0 -2
  203. package/src/client/theme/ui/Navbar/navbar.css +0 -347
  204. package/src/client/theme/ui/NotFound/NotFound.tsx +0 -19
  205. package/src/client/theme/ui/NotFound/index.ts +0 -1
  206. package/src/client/theme/ui/NotFound/not-found.css +0 -64
  207. package/src/client/theme/ui/OnThisPage/OnThisPage.tsx +0 -244
  208. package/src/client/theme/ui/OnThisPage/index.ts +0 -1
  209. package/src/client/theme/ui/OnThisPage/toc.css +0 -152
  210. package/src/client/theme/ui/PoweredBy/PoweredBy.tsx +0 -18
  211. package/src/client/theme/ui/PoweredBy/index.ts +0 -1
  212. package/src/client/theme/ui/PoweredBy/powered-by.css +0 -76
  213. package/src/client/theme/ui/ProgressBar/ProgressBar.css +0 -17
  214. package/src/client/theme/ui/ProgressBar/ProgressBar.tsx +0 -51
  215. package/src/client/theme/ui/ProgressBar/index.ts +0 -1
  216. package/src/client/theme/ui/SearchDialog/SearchDialog.tsx +0 -209
  217. package/src/client/theme/ui/SearchDialog/index.ts +0 -1
  218. package/src/client/theme/ui/SearchDialog/search.css +0 -152
  219. package/src/client/theme/ui/Sidebar/Sidebar.tsx +0 -244
  220. package/src/client/theme/ui/Sidebar/index.ts +0 -1
  221. package/src/client/theme/ui/Sidebar/sidebar.css +0 -230
  222. package/src/client/theme/ui/ThemeToggle/ThemeToggle.tsx +0 -69
  223. package/src/client/theme/ui/ThemeToggle/index.ts +0 -1
  224. package/src/client/theme/ui/VersionSwitcher/VersionSwitcher.tsx +0 -136
  225. package/src/client/theme/ui/VersionSwitcher/index.ts +0 -1
  226. package/src/client/utils.ts +0 -49
@@ -1,18 +1,18 @@
1
- import React, { createContext, useContext, useCallback } from "react";
2
- import { ComponentRoute } from "../types";
1
+ import { createContext, use, useCallback, useRef } from 'react'
2
+ import type { ComponentRoute } from '../types'
3
3
 
4
4
  interface PreloadContextType {
5
- preload: (path: string) => void;
6
- routes: ComponentRoute[];
5
+ preload: (path: string) => void
6
+ routes: ComponentRoute[]
7
7
  }
8
8
 
9
9
  const PreloadContext = createContext<PreloadContextType>({
10
10
  preload: () => {},
11
11
  routes: [],
12
- });
12
+ })
13
13
 
14
14
  export function usePreload() {
15
- return useContext(PreloadContext);
15
+ return use(PreloadContext)
16
16
  }
17
17
 
18
18
  export function PreloadProvider({
@@ -20,39 +20,47 @@ export function PreloadProvider({
20
20
  modules,
21
21
  children,
22
22
  }: {
23
- routes: ComponentRoute[];
24
- modules: Record<string, () => Promise<any>>;
25
- children: React.ReactNode;
23
+ routes: ComponentRoute[]
24
+ modules: Record<string, () => Promise<unknown>>
25
+ children: React.ReactNode
26
26
  }) {
27
+ const preloadTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
28
+
27
29
  const preload = useCallback(
28
30
  (path: string) => {
29
- // Normalize path (remove hash and search)
30
- const cleanPath = path.split("#")[0].split("?")[0];
31
-
32
- // Support index routes matching "/"
33
- const route = routes.find(
34
- (r) => r.path === cleanPath || (cleanPath === "/" && r.path === ""),
35
- );
36
-
37
- if (route && route.filePath) {
38
- const loaderKey = Object.keys(modules).find((k) =>
39
- k.endsWith("/" + route.filePath),
40
- );
41
-
42
- if (loaderKey) {
43
- // Trigger the dynamic import
44
- modules[loaderKey]().catch((err: any) => {
45
- console.error(`[boltdocs] Failed to preload route ${path}:`, err);
46
- });
47
- }
31
+ if (preloadTimerRef.current) {
32
+ clearTimeout(preloadTimerRef.current)
48
33
  }
34
+
35
+ preloadTimerRef.current = setTimeout(() => {
36
+ // Normalize path (remove hash and search)
37
+ const cleanPath = path.split('#')[0].split('?')[0]
38
+
39
+ // Support index routes matching "/"
40
+ const route = routes.find(
41
+ (r) => r.path === cleanPath || (cleanPath === '/' && r.path === ''),
42
+ )
43
+
44
+ if (route?.filePath) {
45
+ const loaderKey = Object.keys(modules).find((k) =>
46
+ k.endsWith('/' + route.filePath),
47
+ )
48
+
49
+ if (loaderKey) {
50
+ // Trigger the dynamic import
51
+ modules[loaderKey]().catch((err: unknown) => {
52
+ console.error(`[boltdocs] Failed to preload route ${path}:`, err)
53
+ })
54
+ }
55
+ }
56
+ }, 100) // 100ms debounce
49
57
  },
50
58
  [routes, modules],
51
- );
59
+ )
52
60
 
53
61
  return (
54
62
  <PreloadContext.Provider value={{ preload, routes }}>
55
63
  {children}
56
64
  </PreloadContext.Provider>
57
- );
65
+ )
58
66
  }
@@ -0,0 +1,30 @@
1
+ import type React from 'react'
2
+ import { startTransition } from 'react'
3
+ import { RouterProvider } from 'react-aria-components'
4
+ import { useNavigate, useHref } from 'react-router-dom'
5
+
6
+ /**
7
+ * Connects React Aria Components (RAC) to React Router.
8
+ * This ensures all RAC links and buttons use client-side navigation
9
+ * instead of full page reloads.
10
+ */
11
+ export function BoltdocsRouterProvider({
12
+ children,
13
+ }: {
14
+ children: React.ReactNode
15
+ }) {
16
+ const navigate = useNavigate()
17
+
18
+ return (
19
+ <RouterProvider
20
+ navigate={(to, options) => {
21
+ startTransition(() => {
22
+ navigate(to, options)
23
+ })
24
+ }}
25
+ useHref={useHref}
26
+ >
27
+ {children as any}
28
+ </RouterProvider>
29
+ )
30
+ }
@@ -0,0 +1,40 @@
1
+ import { useLayoutEffect } from 'react'
2
+ import { useLocation } from 'react-router-dom'
3
+
4
+ /**
5
+ * Handles scroll restoration and hash scrolling on navigation.
6
+ * It ensures the page scrolls to top on pathname changes,
7
+ * or specifically to an anchor element if a hash is present.
8
+ */
9
+ export function ScrollHandler() {
10
+ const { pathname, hash } = useLocation()
11
+
12
+ // biome-ignore lint/correctness/useExhaustiveDependencies: pathname is used as a trigger for scroll-to-top on navigation
13
+ useLayoutEffect(() => {
14
+ const container = document.querySelector('.boltdocs-content')
15
+ if (!container) return
16
+
17
+ if (hash) {
18
+ const id = hash.replace('#', '')
19
+ const element = document.getElementById(id)
20
+ if (element) {
21
+ const offset = 80
22
+ const containerRect = container.getBoundingClientRect().top
23
+ const elementRect = element.getBoundingClientRect().top
24
+ const elementPosition = elementRect - containerRect
25
+ const offsetPosition = elementPosition - offset + container.scrollTop
26
+
27
+ container.scrollTo({
28
+ top: offsetPosition,
29
+ behavior: 'smooth',
30
+ })
31
+ return
32
+ }
33
+ }
34
+
35
+ // Scroll to top on navigation when no hash is specified
36
+ container.scrollTo(0, 0)
37
+ }, [pathname, hash])
38
+
39
+ return null
40
+ }
@@ -0,0 +1,75 @@
1
+ import { createContext, use, useEffect, useState } from 'react'
2
+
3
+ type Theme = 'light' | 'dark'
4
+
5
+ interface ThemeContextType {
6
+ theme: Theme
7
+ toggleTheme: () => void
8
+ setTheme: (theme: Theme) => void
9
+ }
10
+
11
+ const ThemeContext = createContext<ThemeContextType | undefined>(undefined)
12
+
13
+ export function ThemeProvider({ children }: { children: React.ReactNode }) {
14
+ const [theme, setThemeState] = useState<Theme>('dark')
15
+ const [mounted, setMounted] = useState(false)
16
+
17
+ useEffect(() => {
18
+ setMounted(true)
19
+ const stored = localStorage.getItem('boltdocs-theme')
20
+ if (stored === 'light' || stored === 'dark') {
21
+ setThemeState(stored as Theme)
22
+ } else {
23
+ const prefersDark = window.matchMedia(
24
+ '(prefers-color-scheme: dark)',
25
+ ).matches
26
+ setThemeState(prefersDark ? 'dark' : 'light')
27
+ }
28
+
29
+ const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
30
+ const handleChange = (e: MediaQueryListEvent) => {
31
+ if (!localStorage.getItem('boltdocs-theme')) {
32
+ setThemeState(e.matches ? 'dark' : 'light')
33
+ }
34
+ }
35
+ mediaQuery.addEventListener('change', handleChange)
36
+ return () => mediaQuery.removeEventListener('change', handleChange)
37
+ }, [])
38
+
39
+ useEffect(() => {
40
+ if (!mounted) return
41
+ const root = document.documentElement
42
+ if (theme === 'light') {
43
+ root.classList.add('theme-light')
44
+ root.dataset.theme = 'light'
45
+ } else {
46
+ root.classList.remove('theme-light')
47
+ root.dataset.theme = 'dark'
48
+ }
49
+ }, [theme, mounted])
50
+
51
+ const toggleTheme = () => {
52
+ const newTheme = theme === 'dark' ? 'light' : 'dark'
53
+ setThemeState(newTheme)
54
+ localStorage.setItem('boltdocs-theme', newTheme)
55
+ }
56
+
57
+ const setTheme = (newTheme: Theme) => {
58
+ setThemeState(newTheme)
59
+ localStorage.setItem('boltdocs-theme', newTheme)
60
+ }
61
+
62
+ return (
63
+ <ThemeContext.Provider value={{ theme, toggleTheme, setTheme }}>
64
+ {children}
65
+ </ThemeContext.Provider>
66
+ )
67
+ }
68
+
69
+ export function useTheme() {
70
+ const context = use(ThemeContext)
71
+ if (context === undefined) {
72
+ throw new Error('useTheme must be used within a ThemeProvider')
73
+ }
74
+ return context
75
+ }
@@ -0,0 +1,80 @@
1
+ import { DocsLayout } from '@components/docs-layout'
2
+ import { Navbar } from '@components/ui-base/navbar'
3
+ import { Sidebar } from '@components/ui-base/sidebar'
4
+ import { OnThisPage } from '@components/ui-base/on-this-page'
5
+ import { Head } from '@components/ui-base/head'
6
+ import { Breadcrumbs } from '@components/ui-base/breadcrumbs'
7
+ import { PageNav } from '@components/ui-base/page-nav'
8
+ import { ProgressBar } from '@components/ui-base/progress-bar'
9
+ import { ErrorBoundary } from '@components/ui-base/error-boundary'
10
+ import { CopyMarkdown } from '@components/ui-base/copy-markdown'
11
+ import { useRoutes } from '@client/hooks/use-routes'
12
+ import { useConfig } from '@client/app/config-context'
13
+ import { useMdxComponents } from '@client/app/mdx-components-context'
14
+
15
+ import { useLocation } from 'react-router-dom'
16
+
17
+ export interface LayoutProps {
18
+ children: React.ReactNode
19
+ }
20
+
21
+ /**
22
+ * The built-in default layout for Boltdocs.
23
+ * Users who create their own `layout.tsx` can import the same building blocks
24
+ * and rearrange, wrap, or replace any section.
25
+ */
26
+ export function DefaultLayout({ children }: LayoutProps) {
27
+ const { routes: filteredRoutes, allRoutes, currentRoute } = useRoutes()
28
+ const { pathname } = useLocation()
29
+ const config = useConfig()
30
+ const mdxComponents = useMdxComponents()
31
+ const CopyMarkdownComp = (mdxComponents.CopyMarkdown as any) || CopyMarkdown
32
+
33
+ const isHome = pathname === '/' || pathname === ''
34
+
35
+ return (
36
+ <DocsLayout>
37
+ <ProgressBar />
38
+ <Head
39
+ siteTitle={config.themeConfig?.title || 'Boltdocs'}
40
+ siteDescription={config.themeConfig?.description || ''}
41
+ routes={allRoutes}
42
+ />
43
+ <Navbar />
44
+
45
+ <DocsLayout.Body>
46
+ {!isHome && <Sidebar routes={filteredRoutes} config={config} />}
47
+
48
+ <DocsLayout.Content>
49
+ {!isHome && (
50
+ <DocsLayout.ContentHeader>
51
+ <Breadcrumbs />
52
+ <CopyMarkdownComp
53
+ mdxRaw={currentRoute?._rawContent}
54
+ route={currentRoute}
55
+ config={config.themeConfig?.copyMarkdown}
56
+ />
57
+ </DocsLayout.ContentHeader>
58
+ )}
59
+
60
+ <ErrorBoundary>{children}</ErrorBoundary>
61
+
62
+ {!isHome && (
63
+ <DocsLayout.ContentFooter>
64
+ <PageNav />
65
+ </DocsLayout.ContentFooter>
66
+ )}
67
+ </DocsLayout.Content>
68
+
69
+ {!isHome && (
70
+ <OnThisPage
71
+ headings={currentRoute?.headings}
72
+ editLink={config.themeConfig?.editLink}
73
+ communityHelp={config.themeConfig?.communityHelp}
74
+ filePath={currentRoute?.filePath}
75
+ />
76
+ )}
77
+ </DocsLayout.Body>
78
+ </DocsLayout>
79
+ )
80
+ }
@@ -0,0 +1,105 @@
1
+ import type React from 'react'
2
+ import { cn } from '@client/utils/cn'
3
+
4
+ /**
5
+ * Props shared by all layout slot components.
6
+ */
7
+ interface SlotProps {
8
+ children?: React.ReactNode
9
+ className?: string
10
+ style?: React.CSSProperties
11
+ }
12
+
13
+ /**
14
+ * Root layout shell. Renders a full-height flex column.
15
+ *
16
+ * Usage:
17
+ * ```tsx
18
+ * <DocsLayout>
19
+ * <Navbar />
20
+ * <DocsLayout.Body>...</DocsLayout.Body>
21
+ * </DocsLayout>
22
+ * ```
23
+ */
24
+ function DocsLayoutRoot({ children, className, style }: SlotProps) {
25
+ return (
26
+ <div
27
+ className={cn(
28
+ 'h-screen flex flex-col overflow-hidden bg-bg-main text-text-main',
29
+ className,
30
+ )}
31
+ style={style}
32
+ >
33
+ {children}
34
+ </div>
35
+ )
36
+ }
37
+
38
+ /**
39
+ * Horizontal flex container for sidebar + content + toc.
40
+ */
41
+ function Body({ children, className, style }: SlotProps) {
42
+ return (
43
+ <div
44
+ className={cn(
45
+ 'mx-auto flex flex-1 w-full max-w-(--breakpoint-3xl) bg-bg-main overflow-hidden',
46
+ className,
47
+ )}
48
+ style={style}
49
+ >
50
+ {children}
51
+ </div>
52
+ )
53
+ }
54
+
55
+ /**
56
+ * Main scrollable content area.
57
+ */
58
+ function Content({ children, className, style }: SlotProps) {
59
+ return (
60
+ <main
61
+ className={cn(
62
+ 'boltdocs-content flex-1 min-w-0 overflow-y-auto',
63
+ className,
64
+ )}
65
+ style={style}
66
+ >
67
+ <div className="boltdocs-page mx-auto max-w-content-max pt-4 pb-20 px-4 sm:px-8">
68
+ {children}
69
+ </div>
70
+ </main>
71
+ )
72
+ }
73
+
74
+ /**
75
+ * Content header row (breadcrumbs + copy markdown).
76
+ */
77
+ function ContentHeader({ children, className, style }: SlotProps) {
78
+ return (
79
+ <div
80
+ className={cn('flex items-center justify-between mb-10', className)}
81
+ style={style}
82
+ >
83
+ {children}
84
+ </div>
85
+ )
86
+ }
87
+
88
+ /**
89
+ * Footer area inside the content section (page nav).
90
+ */
91
+ function ContentFooter({ children, className, style }: SlotProps) {
92
+ return (
93
+ <div className={cn('mt-20', className)} style={style}>
94
+ {children}
95
+ </div>
96
+ )
97
+ }
98
+
99
+ // Attach sub-components to the root
100
+ export const DocsLayout = Object.assign(DocsLayoutRoot, {
101
+ Body,
102
+ Content,
103
+ ContentHeader,
104
+ ContentFooter,
105
+ })
@@ -0,0 +1,74 @@
1
+ import type { SVGProps } from 'react'
2
+
3
+ type WrapperProps = SVGProps<SVGSVGElement> & {
4
+ size?: number
5
+ }
6
+
7
+ function wrapperProps(props: WrapperProps) {
8
+ const { size = 20, ...rest } = props
9
+ return {
10
+ ...rest,
11
+ width: size,
12
+ height: size,
13
+ }
14
+ }
15
+
16
+ export const Github = (props: WrapperProps) => (
17
+ <svg
18
+ xmlns="http://www.w3.org/2000/svg"
19
+ viewBox="0 0 24 24"
20
+ fill="currentColor"
21
+ {...wrapperProps(props)}
22
+ >
23
+ <title>{'GitHub'}</title>
24
+ <path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
25
+ </svg>
26
+ )
27
+
28
+ export const Discord = (props: WrapperProps) => (
29
+ <svg
30
+ xmlns="http://www.w3.org/2000/svg"
31
+ viewBox="0 0 24 24"
32
+ fill="currentColor"
33
+ {...wrapperProps(props)}
34
+ >
35
+ <title>{'Discord'}</title>
36
+ <path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418Z" />
37
+ </svg>
38
+ )
39
+
40
+ export const XSocial = (props: WrapperProps) => (
41
+ <svg
42
+ xmlns="http://www.w3.org/2000/svg"
43
+ viewBox="0 0 24 24"
44
+ fill="currentColor"
45
+ {...wrapperProps(props)}
46
+ >
47
+ <title>{'X'}</title>
48
+ <path d="M14.234 10.162 22.977 0h-2.072l-7.591 8.824L7.251 0H.258l9.168 13.343L.258 24H2.33l8.016-9.318L16.749 24h6.993zm-2.837 3.299-.929-1.329L3.076 1.56h3.182l5.965 8.532.929 1.329 7.754 11.09h-3.182z" />
49
+ </svg>
50
+ )
51
+
52
+ export const CodeSandbox = (props: WrapperProps) => (
53
+ <svg
54
+ xmlns="http://www.w3.org/2000/svg"
55
+ viewBox="0 0 24 24"
56
+ fill="currentColor"
57
+ {...wrapperProps(props)}
58
+ >
59
+ <title>{'CodeSandbox'}</title>
60
+ <path d="M0 24h24V0H0v2.455h21.546v19.09H2.454V0H0Z" />
61
+ </svg>
62
+ )
63
+
64
+ export const Bluesky = (props: WrapperProps) => (
65
+ <svg
66
+ xmlns="http://www.w3.org/2000/svg"
67
+ viewBox="0 0 24 24"
68
+ fill="currentColor"
69
+ {...wrapperProps(props)}
70
+ >
71
+ <title>{'Bluesky'}</title>
72
+ <path d="M5.202 2.857C7.954 4.922 10.913 9.11 12 11.358c1.087-2.247 4.046-6.436 6.798-8.501C20.783 1.366 24 .213 24 3.883c0 .732-.42 6.156-.667 7.037-.856 3.061-3.978 3.842-6.755 3.37 4.854.826 6.089 3.562 3.422 6.299-5.065 5.196-7.28-1.304-7.847-2.97-.104-.305-.152-.448-.153-.327 0-.121-.05.022-.153.327-.568 1.666-2.782 8.166-7.847 2.97-2.667-2.737-1.432-5.473 3.422-6.3-2.777.473-5.899-.308-6.755-3.369C.42 10.04 0 4.615 0 3.883c0-3.67 3.217-2.517 5.202-1.026" />
73
+ </svg>
74
+ )
@@ -0,0 +1,107 @@
1
+ import {
2
+ Info,
3
+ Lightbulb,
4
+ AlertTriangle,
5
+ ShieldAlert,
6
+ Bookmark,
7
+ Zap,
8
+ Flame,
9
+ } from 'lucide-react'
10
+ import { cn } from '@client/utils/cn'
11
+ import { cva } from 'class-variance-authority'
12
+ import type { VariantProps } from 'class-variance-authority'
13
+
14
+ const ICON_MAP: Record<string, React.ReactNode> = {
15
+ note: <Bookmark size={18} />,
16
+ tip: <Lightbulb size={18} />,
17
+ info: <Info size={18} />,
18
+ warning: <AlertTriangle size={18} />,
19
+ danger: <ShieldAlert size={18} />,
20
+ important: <Flame size={18} />,
21
+ caution: <Zap size={18} />,
22
+ }
23
+
24
+ const LABEL_MAP: Record<string, string> = {
25
+ note: 'Note',
26
+ tip: 'Tip',
27
+ info: 'Info',
28
+ warning: 'Warning',
29
+ danger: 'Danger',
30
+ important: 'Important',
31
+ caution: 'Caution',
32
+ }
33
+
34
+ const admonitionVariants = cva('py-4 px-4 rounded-lg', {
35
+ variants: {
36
+ type: {
37
+ note: 'border-primary-400 bg-primary-500/5 text-primary-400',
38
+ tip: 'border-emerald-500 bg-emerald-500/5 text-emerald-500',
39
+ info: 'border-sky-500 bg-sky-500/5 text-sky-500',
40
+ warning: 'border-amber-500 bg-amber-500/5 text-amber-500',
41
+ danger: 'border-red-500 bg-red-500/5 text-red-500',
42
+ important: 'border-orange-500 bg-orange-500/5 text-orange-500',
43
+ caution: 'border-yellow-500 bg-yellow-500/5 text-yellow-500',
44
+ },
45
+ },
46
+ defaultVariants: {
47
+ type: 'note',
48
+ },
49
+ })
50
+ type AdmonitionVariants = VariantProps<typeof admonitionVariants>
51
+
52
+ export interface AdmonitionProps
53
+ extends React.HTMLAttributes<HTMLDivElement>,
54
+ AdmonitionVariants {
55
+ title?: string
56
+ children: React.ReactNode
57
+ }
58
+
59
+ export function Admonition({
60
+ type = 'note',
61
+ title,
62
+ children,
63
+ className = '',
64
+ ...rest
65
+ }: AdmonitionProps) {
66
+ return (
67
+ <div
68
+ className={cn(admonitionVariants({ type }), className)}
69
+ role={type === 'warning' || type === 'danger' ? 'alert' : 'note'}
70
+ {...rest}
71
+ >
72
+ <div className="flex items-center flex-row gap-2 mb-2">
73
+ <span className={cn('shrink-0', admonitionVariants({ type }))}>
74
+ {ICON_MAP[type as keyof typeof ICON_MAP]}
75
+ </span>
76
+ <span className="text-sm font-bold tracking-tight text-text-main">
77
+ {title || LABEL_MAP[type as keyof typeof LABEL_MAP]}
78
+ </span>
79
+ </div>
80
+ <div className="text-sm text-text-muted leading-relaxed [&>p]:m-0 [&>p]:mb-2 [&>p:last-child]:mb-0">
81
+ {children}
82
+ </div>
83
+ </div>
84
+ )
85
+ }
86
+
87
+ export const Note = (props: Omit<AdmonitionProps, 'type'>) => (
88
+ <Admonition type="note" {...props} />
89
+ )
90
+ export const Tip = (props: Omit<AdmonitionProps, 'type'>) => (
91
+ <Admonition type="tip" {...props} />
92
+ )
93
+ export const Warning = (props: Omit<AdmonitionProps, 'type'>) => (
94
+ <Admonition type="warning" {...props} />
95
+ )
96
+ export const Danger = (props: Omit<AdmonitionProps, 'type'>) => (
97
+ <Admonition type="danger" {...props} />
98
+ )
99
+ export const InfoBox = (props: Omit<AdmonitionProps, 'type'>) => (
100
+ <Admonition type="info" {...props} />
101
+ )
102
+ export const Important = (props: Omit<AdmonitionProps, 'type'>) => (
103
+ <Admonition type="important" {...props} />
104
+ )
105
+ export const Caution = (props: Omit<AdmonitionProps, 'type'>) => (
106
+ <Admonition type="caution" {...props} />
107
+ )
@@ -0,0 +1,41 @@
1
+ import { cn } from '@client/utils/cn'
2
+ import { cva } from 'class-variance-authority'
3
+ import type { VariantProps } from 'class-variance-authority'
4
+
5
+ const badgeVariants = cva(
6
+ 'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold tracking-tight',
7
+ {
8
+ variants: {
9
+ variant: {
10
+ default: 'bg-bg-surface text-text-muted border-border-subtle',
11
+ primary: 'bg-primary-500/15 text-primary-400 border-primary-500/20',
12
+ success: 'bg-emerald-500/15 text-emerald-400 border-emerald-500/20',
13
+ warning: 'bg-amber-500/15 text-amber-400 border-amber-500/20',
14
+ danger: 'bg-red-500/15 text-red-400 border-red-500/20',
15
+ info: 'bg-sky-500/15 text-sky-400 border-sky-500/20',
16
+ },
17
+ },
18
+ defaultVariants: {
19
+ variant: 'default',
20
+ },
21
+ },
22
+ )
23
+
24
+ export interface BadgeProps
25
+ extends React.HTMLAttributes<HTMLSpanElement>,
26
+ VariantProps<typeof badgeVariants> {
27
+ children: React.ReactNode
28
+ }
29
+
30
+ export function Badge({
31
+ variant = 'default',
32
+ children,
33
+ className = '',
34
+ ...rest
35
+ }: BadgeProps) {
36
+ return (
37
+ <span className={cn(badgeVariants({ variant }), className)} {...rest}>
38
+ {children}
39
+ </span>
40
+ )
41
+ }
@@ -0,0 +1,35 @@
1
+ import {
2
+ Button as ButtonPrimitive,
3
+ buttonVariants,
4
+ type ButtonProps,
5
+ } from '@components/primitives/button'
6
+ import { cn } from '@client/utils/cn'
7
+
8
+ export type { ButtonProps } from '@components/primitives/button'
9
+
10
+ export const Button = ({
11
+ className,
12
+ variant,
13
+ size,
14
+ rounded,
15
+ iconSize,
16
+ disabled,
17
+ ...props
18
+ }: ButtonProps) => {
19
+ return (
20
+ <ButtonPrimitive
21
+ className={cn(
22
+ 'group',
23
+ buttonVariants({
24
+ variant,
25
+ size,
26
+ rounded,
27
+ iconSize,
28
+ disabled,
29
+ className,
30
+ }),
31
+ )}
32
+ {...props}
33
+ />
34
+ )
35
+ }