boltdocs 2.7.10 → 2.8.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.
- package/README.md +2 -2
- package/dist/banner-3N4Jd_L9.d.ts +100 -0
- package/dist/banner-MynZD_Ox.d.cts +100 -0
- package/dist/cache-BMUyNiiA.mjs +6 -0
- package/dist/cache-CKm45d2w.cjs +6 -0
- package/dist/client/index.cjs +2268 -1
- package/dist/client/index.d.cts +86 -110
- package/dist/client/index.d.ts +87 -111
- package/dist/client/index.js +2214 -1
- package/dist/client/mdx.cjs +12 -1
- package/dist/client/mdx.d.cts +39 -93
- package/dist/client/mdx.d.ts +38 -93
- package/dist/client/mdx.js +7 -1
- package/dist/client/primitives.cjs +60 -1
- package/dist/client/primitives.d.cts +411 -347
- package/dist/client/primitives.d.ts +411 -347
- package/dist/client/primitives.js +20 -1
- package/dist/docs-layout-CwCq42Zt.cjs +1348 -0
- package/dist/docs-layout-Dn6S5g59.js +1167 -0
- package/dist/doctor-BArviV8X.cjs +28 -0
- package/dist/doctor-CgLA7_Uv.mjs +28 -0
- package/dist/{doctor-CrytFkqW.cjs → doctor-DyNUVe96.cjs} +1 -1
- package/dist/{routes-DP1vmWRj.cjs → doctor-aN_leTbh.mjs} +1 -1
- package/dist/{generator-ClVanhvi.mjs → generator-BHCrLU6h.mjs} +2 -2
- package/dist/{generator-CHqxiQhF.cjs → generator-CC2yHzhZ.cjs} +2 -2
- package/dist/icons-dev-DvJ-hh9x.cjs +1209 -0
- package/dist/icons-dev-Oju24Wjp.js +845 -0
- package/dist/image-Ch4-GxdO.cjs +268 -0
- package/dist/image-Do8V9PCW.js +214 -0
- package/dist/mdx-D3A2_l7P.js +520 -0
- package/dist/mdx-PLhhPJRS.cjs +531 -0
- package/dist/node/cli-entry.cjs +3 -1
- package/dist/node/cli-entry.mjs +3 -1
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.d.cts +258 -152
- package/dist/node/index.d.mts +258 -150
- package/dist/node/index.mjs +1 -1
- package/dist/node/routes/worker.cjs +1 -1
- package/dist/node/routes/worker.mjs +1 -1
- package/dist/node-BmlP0eBP.cjs +159 -0
- package/dist/node-Y8_4ayje.mjs +159 -0
- package/dist/package-2nFy_NsW.cjs +6 -0
- package/dist/{package--0Yf0t1N.mjs → package-DAbtltXX.mjs} +1 -1
- package/dist/parser-B7-6PyQz.cjs +6 -0
- package/dist/{parser-Aq8LoH-0.cjs → parser-BzB-zCkF.cjs} +1 -1
- package/dist/parser-WGZdWs0X.mjs +6 -0
- package/dist/routes-BDDSxAl0.mjs +6 -0
- package/dist/routes-DJNJ-rTt.cjs +6 -0
- package/dist/routes-DiYC4nD2.cjs +6 -0
- package/dist/routes-_Bb2f4eI.mjs +6 -0
- package/dist/search-dialog-BXVoecTx.cjs +483 -0
- package/dist/search-dialog-BYhOov4S.cjs +331 -0
- package/dist/search-dialog-C09riYmx.js +313 -0
- package/dist/search-dialog-CUeAfy-8.cjs +8 -0
- package/dist/search-dialog-D8gLkhUV.js +453 -0
- package/dist/search-dialog-DHc_8FFX.js +8 -0
- package/dist/{sidebar-CcBkrm06.d.cts → sidebar-DNq4_ZAa.d.ts} +118 -52
- package/dist/{sidebar-CyZS9YOm.d.ts → sidebar-Dlkgbxs6.d.cts} +118 -52
- package/dist/utils-BYITg7T5.mjs +7 -0
- package/dist/utils-Cjmx1hhk.cjs +7 -0
- package/dist/worker-pool-CtqklOXq.cjs +6 -0
- package/dist/worker-pool-k0DY6k8T.mjs +6 -0
- package/package.json +5 -6
- package/src/shared/config-utils.ts +4 -0
- package/src/shared/types.ts +52 -6
- package/dist/cache-Ba-DZQNH.cjs +0 -6
- package/dist/cache-BuMZ58L5.mjs +0 -6
- package/dist/cards-BakZPTz9.d.ts +0 -30
- package/dist/cards-CQn9mXZS.d.cts +0 -30
- package/dist/docs-layout-KoWNZc8_.js +0 -6
- package/dist/docs-layout-x2yKt2cL.cjs +0 -6
- package/dist/doctor-Be7Ly1oM.mjs +0 -21
- package/dist/doctor-jMxWZyLJ.cjs +0 -21
- package/dist/icons-dev-B_RZIyxu.js +0 -6
- package/dist/icons-dev-BlV3wWFT.cjs +0 -6
- package/dist/image-BHhTvQzr.cjs +0 -6
- package/dist/image-CqKzYD8f.js +0 -6
- package/dist/mdx-DudBEac0.js +0 -7
- package/dist/mdx-r4cDQxWu.cjs +0 -7
- package/dist/node-DtEDyN1u.cjs +0 -111
- package/dist/node-_1jhMGYx.mjs +0 -111
- package/dist/package-DrwtlXfk.cjs +0 -6
- package/dist/parser-CdNbqN5y.cjs +0 -6
- package/dist/parser-nE792MLO.mjs +0 -6
- package/dist/rolldown-runtime-fkIsjY3S.mjs +0 -6
- package/dist/routes-2k3tbUmC.cjs +0 -6
- package/dist/routes-CpxZIsMM.mjs +0 -6
- package/dist/search-dialog-B584t9ZF.js +0 -6
- package/dist/search-dialog-BvBopRsZ.cjs +0 -6
- package/dist/search-dialog-ByvGScjt.js +0 -6
- package/dist/search-dialog-Cyko6TJm.cjs +0 -6
- package/dist/search-dialog-D6BNohIJ.js +0 -6
- package/dist/search-dialog-DuYTIefy.cjs +0 -6
- package/dist/utils-CG65J0Sc.mjs +0 -7
- package/dist/utils-CKunkU96.cjs +0 -7
- package/dist/worker-pool-CGn7DrLb.mjs +0 -6
- package/dist/worker-pool-Crbqgw5R.cjs +0 -6
- package/src/client/app/config-context.tsx +0 -51
- package/src/client/app/doc-page.tsx +0 -38
- package/src/client/app/docs-layout.tsx +0 -28
- package/src/client/app/head.tsx +0 -122
- package/src/client/app/helmet-compat.tsx +0 -36
- package/src/client/app/mdx-component.tsx +0 -8
- package/src/client/app/mdx-components-context.tsx +0 -72
- package/src/client/app/routes-context.tsx +0 -34
- package/src/client/app/scroll-handler.tsx +0 -74
- package/src/client/app/theme-context.tsx +0 -103
- package/src/client/app/ui-context.tsx +0 -42
- package/src/client/components/docs-layout-default.tsx +0 -85
- package/src/client/components/icons-dev.tsx +0 -282
- package/src/client/components/mdx/callout.tsx +0 -97
- package/src/client/components/mdx/card.tsx +0 -99
- package/src/client/components/mdx/cards.tsx +0 -27
- package/src/client/components/mdx/code-block.tsx +0 -184
- package/src/client/components/mdx/field.tsx +0 -33
- package/src/client/components/mdx/image.tsx +0 -44
- package/src/client/components/mdx/index.ts +0 -19
- package/src/client/components/mdx/table.tsx +0 -54
- package/src/client/components/mdx/typographics.tsx +0 -120
- package/src/client/components/mdx/use-code-block.ts +0 -34
- package/src/client/components/primitives/breadcrumbs.tsx +0 -54
- package/src/client/components/primitives/button-group.tsx +0 -54
- package/src/client/components/primitives/button.tsx +0 -6
- package/src/client/components/primitives/code-block.tsx +0 -120
- package/src/client/components/primitives/docs-layout.tsx +0 -125
- package/src/client/components/primitives/error-boundary.tsx +0 -107
- package/src/client/components/primitives/heading.tsx +0 -128
- package/src/client/components/primitives/helpers/observer.ts +0 -141
- package/src/client/components/primitives/image.tsx +0 -26
- package/src/client/components/primitives/link.tsx +0 -102
- package/src/client/components/primitives/menu.tsx +0 -137
- package/src/client/components/primitives/navbar.tsx +0 -466
- package/src/client/components/primitives/on-this-page.tsx +0 -430
- package/src/client/components/primitives/page-nav.tsx +0 -51
- package/src/client/components/primitives/popover.tsx +0 -28
- package/src/client/components/primitives/search-dialog.tsx +0 -193
- package/src/client/components/primitives/sidebar.tsx +0 -423
- package/src/client/components/primitives/skeleton.tsx +0 -26
- package/src/client/components/primitives/tabs.tsx +0 -70
- package/src/client/components/primitives/tooltip.tsx +0 -81
- package/src/client/components/primitives/types.ts +0 -11
- package/src/client/components/ui-base/banner.tsx +0 -66
- package/src/client/components/ui-base/breadcrumbs.tsx +0 -44
- package/src/client/components/ui-base/copy-markdown.tsx +0 -107
- package/src/client/components/ui-base/error-boundary.tsx +0 -15
- package/src/client/components/ui-base/github-stars.tsx +0 -29
- package/src/client/components/ui-base/icons.tsx +0 -240
- package/src/client/components/ui-base/index.ts +0 -16
- package/src/client/components/ui-base/last-updated.tsx +0 -27
- package/src/client/components/ui-base/navbar.tsx +0 -266
- package/src/client/components/ui-base/not-found.tsx +0 -26
- package/src/client/components/ui-base/on-this-page.tsx +0 -57
- package/src/client/components/ui-base/page-nav.tsx +0 -50
- package/src/client/components/ui-base/search-dialog.tsx +0 -163
- package/src/client/components/ui-base/search-highlight.tsx +0 -10
- package/src/client/components/ui-base/sidebar.tsx +0 -92
- package/src/client/components/ui-base/tabs.tsx +0 -83
- package/src/client/components/ui-base/theme-toggle.tsx +0 -130
- package/src/client/components/ui-base/version-i18n.tsx +0 -80
- package/src/client/hooks/index.ts +0 -13
- package/src/client/hooks/use-analytics.ts +0 -272
- package/src/client/hooks/use-breadcrumbs.ts +0 -22
- package/src/client/hooks/use-i18n.ts +0 -182
- package/src/client/hooks/use-localized-to.ts +0 -113
- package/src/client/hooks/use-location.ts +0 -5
- package/src/client/hooks/use-navbar.ts +0 -130
- package/src/client/hooks/use-page-nav.ts +0 -46
- package/src/client/hooks/use-routes.ts +0 -108
- package/src/client/hooks/use-search-highlight.ts +0 -185
- package/src/client/hooks/use-search.ts +0 -118
- package/src/client/hooks/use-sidebar.ts +0 -205
- package/src/client/hooks/use-tabs.ts +0 -46
- package/src/client/hooks/use-version.ts +0 -111
- package/src/client/index.ts +0 -31
- package/src/client/mdx.ts +0 -2
- package/src/client/primitives.ts +0 -19
- package/src/client/ssg/boltdocs-shell.tsx +0 -148
- package/src/client/ssg/create-routes.tsx +0 -473
- package/src/client/ssg/index.ts +0 -4
- package/src/client/ssg/mdx-page.tsx +0 -38
- package/src/client/store/boltdocs-context.tsx +0 -137
- package/src/client/theme/neutral.css +0 -141
- package/src/client/theme/reset.css +0 -189
- package/src/client/types.ts +0 -116
- package/src/client/utils/cn.ts +0 -6
- package/src/client/utils/copy-clipboard.ts +0 -22
- package/src/client/utils/get-base-file-path.ts +0 -21
- package/src/client/utils/github.ts +0 -121
- package/src/client/utils/i18n.ts +0 -23
- package/src/client/utils/path.ts +0 -9
- package/src/client/utils/react-to-text.ts +0 -34
- package/src/client/virtual.d.ts +0 -24
- /package/dist/{meta-loader-CWg2gnbY.mjs → meta-loader-DzwDFtdT.mjs} +0 -0
package/src/client/app/head.tsx
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react'
|
|
2
|
-
import { useLocation } from 'react-router-dom'
|
|
3
|
-
import { Helmet } from './helmet-compat'
|
|
4
|
-
import { useConfig } from './config-context'
|
|
5
|
-
import { getTranslated } from '../utils/i18n'
|
|
6
|
-
import { useRoutes } from '../hooks/use-routes'
|
|
7
|
-
|
|
8
|
-
interface HeadProps {
|
|
9
|
-
siteTitle?: string | Record<string, string>
|
|
10
|
-
siteDescription?: string | Record<string, string>
|
|
11
|
-
routes: Array<{
|
|
12
|
-
path: string
|
|
13
|
-
title: string
|
|
14
|
-
description?: string
|
|
15
|
-
seo?: Record<string, unknown>
|
|
16
|
-
}>
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function Head({ siteTitle, siteDescription, routes }: HeadProps) {
|
|
20
|
-
const location = useLocation()
|
|
21
|
-
const config = useConfig()
|
|
22
|
-
const { currentLocale } = useRoutes()
|
|
23
|
-
|
|
24
|
-
// Find the current route's metadata — memoized so the O(n) search only
|
|
25
|
-
// re-runs when the routes array or the current URL changes, not on every render.
|
|
26
|
-
const currentRoute = useMemo(
|
|
27
|
-
() => routes?.find?.((r) => r.path === location.pathname),
|
|
28
|
-
[routes, location.pathname],
|
|
29
|
-
)
|
|
30
|
-
const pageTitle = currentRoute?.title
|
|
31
|
-
const translatedSiteDescription = getTranslated(
|
|
32
|
-
siteDescription,
|
|
33
|
-
currentLocale,
|
|
34
|
-
)
|
|
35
|
-
const pageDescription =
|
|
36
|
-
currentRoute?.description || translatedSiteDescription || ''
|
|
37
|
-
|
|
38
|
-
const translatedSiteTitle = getTranslated(siteTitle, currentLocale)
|
|
39
|
-
const finalTitle = pageTitle
|
|
40
|
-
? `${pageTitle} | ${translatedSiteTitle}`
|
|
41
|
-
: translatedSiteTitle
|
|
42
|
-
|
|
43
|
-
const seo = currentRoute?.seo || {}
|
|
44
|
-
|
|
45
|
-
// Merge custom global metatags
|
|
46
|
-
const globalMetatags = config?.seo?.metatags || {}
|
|
47
|
-
|
|
48
|
-
// Calculate specific ones
|
|
49
|
-
const defaultOgImage = config?.seo?.thumbnails?.background
|
|
50
|
-
const ogImage = (seo['og:image'] || defaultOgImage) as string | undefined
|
|
51
|
-
|
|
52
|
-
return (
|
|
53
|
-
<Helmet>
|
|
54
|
-
<title>{finalTitle}</title>
|
|
55
|
-
<meta name="description" content={pageDescription} />
|
|
56
|
-
|
|
57
|
-
{/* Default OG Tags */}
|
|
58
|
-
<meta property="og:title" content={finalTitle} />
|
|
59
|
-
<meta property="og:description" content={pageDescription} />
|
|
60
|
-
<meta property="og:type" content="article" />
|
|
61
|
-
{/* Canonical URL for both <link> and og:url */}
|
|
62
|
-
{typeof window !== 'undefined' && (
|
|
63
|
-
<meta property="og:url" content={window.location.href} />
|
|
64
|
-
)}
|
|
65
|
-
{typeof window !== 'undefined' && (
|
|
66
|
-
<link
|
|
67
|
-
rel="canonical"
|
|
68
|
-
href={window.location.origin + location.pathname}
|
|
69
|
-
/>
|
|
70
|
-
)}
|
|
71
|
-
|
|
72
|
-
{/* Default Twitter Card */}
|
|
73
|
-
<meta name="twitter:card" content="summary" />
|
|
74
|
-
<meta name="twitter:title" content={finalTitle} />
|
|
75
|
-
<meta name="twitter:description" content={pageDescription} />
|
|
76
|
-
{ogImage && <meta name="twitter:image" content={ogImage} />}
|
|
77
|
-
{ogImage && <meta property="og:image" content={ogImage} />}
|
|
78
|
-
|
|
79
|
-
{/* Generator */}
|
|
80
|
-
<meta name="generator" content="Boltdocs" />
|
|
81
|
-
|
|
82
|
-
{/* User-defined global metatags */}
|
|
83
|
-
{Object.entries(globalMetatags).map(([key, value]) => {
|
|
84
|
-
const isProperty =
|
|
85
|
-
key.startsWith('og:') ||
|
|
86
|
-
key.startsWith('music:') ||
|
|
87
|
-
key.startsWith('video:') ||
|
|
88
|
-
key.startsWith('article:') ||
|
|
89
|
-
key.startsWith('book:') ||
|
|
90
|
-
key.startsWith('profile:')
|
|
91
|
-
return isProperty ? (
|
|
92
|
-
<meta key={key} property={key} content={value as string} />
|
|
93
|
-
) : (
|
|
94
|
-
<meta key={key} name={key} content={value as string} />
|
|
95
|
-
)
|
|
96
|
-
})}
|
|
97
|
-
|
|
98
|
-
{/* Page granular SEO tags (override global) */}
|
|
99
|
-
{Object.entries(seo).map(([key, value]) => {
|
|
100
|
-
if (key === 'noindex' && value === true)
|
|
101
|
-
return <meta key="noindex" name="robots" content="noindex" />
|
|
102
|
-
if (key === 'robots')
|
|
103
|
-
return <meta key="robots" name="robots" content={value as string} />
|
|
104
|
-
if (key === 'canonical')
|
|
105
|
-
return <link key="canonical" rel="canonical" href={value as string} />
|
|
106
|
-
|
|
107
|
-
const isProperty =
|
|
108
|
-
key.startsWith('og:') ||
|
|
109
|
-
key.startsWith('music:') ||
|
|
110
|
-
key.startsWith('video:') ||
|
|
111
|
-
key.startsWith('article:') ||
|
|
112
|
-
key.startsWith('book:') ||
|
|
113
|
-
key.startsWith('profile:')
|
|
114
|
-
return isProperty ? (
|
|
115
|
-
<meta key={key} property={key} content={value as string} />
|
|
116
|
-
) : (
|
|
117
|
-
<meta key={key} name={key} content={value as string} />
|
|
118
|
-
)
|
|
119
|
-
})}
|
|
120
|
-
</Helmet>
|
|
121
|
-
)
|
|
122
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared Helmet module compatibility helpers.
|
|
3
|
-
*
|
|
4
|
-
* react-helmet-async ships different module shapes depending on whether it is
|
|
5
|
-
* loaded via CJS or ESM. Instead of duplicating the same detection logic in
|
|
6
|
-
* every component that needs Helmet/HelmetProvider, we centralise it here.
|
|
7
|
-
*/
|
|
8
|
-
import type { ComponentType, ReactNode } from 'react'
|
|
9
|
-
import * as ReactHelmetAsync from 'react-helmet-async'
|
|
10
|
-
|
|
11
|
-
type HelmetModule = {
|
|
12
|
-
Helmet?: ComponentType<{ children?: ReactNode }>
|
|
13
|
-
HelmetProvider?: ComponentType<{ children?: ReactNode }>
|
|
14
|
-
default?: {
|
|
15
|
-
Helmet?: ComponentType<{ children?: ReactNode }>
|
|
16
|
-
HelmetProvider?: ComponentType<{ children?: ReactNode }>
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const mod = ReactHelmetAsync as unknown as HelmetModule
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* The `<Helmet>` component, resolved across CJS/ESM module shapes.
|
|
24
|
-
* Falls back to a transparent fragment wrapper if the module cannot be resolved.
|
|
25
|
-
*/
|
|
26
|
-
export const Helmet: ComponentType<{ children?: ReactNode }> =
|
|
27
|
-
mod.Helmet || mod.default?.Helmet || (({ children }) => <>{children}</>)
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* The `<HelmetProvider>` component, resolved across CJS/ESM module shapes.
|
|
31
|
-
* Falls back to a transparent fragment wrapper if the module cannot be resolved.
|
|
32
|
-
*/
|
|
33
|
-
export const HelmetProvider: ComponentType<{ children?: ReactNode }> =
|
|
34
|
-
mod.HelmetProvider ||
|
|
35
|
-
mod.default?.HelmetProvider ||
|
|
36
|
-
(({ children }) => <>{children}</>)
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { createContext, use, useMemo } from 'react'
|
|
2
|
-
import type { BoltdocsMdxComponents } from '../../shared/types'
|
|
3
|
-
|
|
4
|
-
export type MdxComponentsType = {
|
|
5
|
-
[key: string]: React.ComponentType<any>
|
|
6
|
-
} & {
|
|
7
|
-
Frontmatter?: Record<string, React.ComponentType<any>>
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const MDX_COMPONENTS_CONTEXT_SYMBOL = Symbol.for(
|
|
11
|
-
'__BDOCS_MDX_COMPONENTS_CONTEXT__',
|
|
12
|
-
)
|
|
13
|
-
const MDX_COMPONENTS_INSTANCE_SYMBOL = Symbol.for(
|
|
14
|
-
'__BDOCS_MDX_COMPONENTS_INSTANCE__',
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
const MdxComponentsContext =
|
|
18
|
-
(globalThis as any)[MDX_COMPONENTS_CONTEXT_SYMBOL] ||
|
|
19
|
-
((globalThis as any)[MDX_COMPONENTS_CONTEXT_SYMBOL] =
|
|
20
|
-
createContext<MdxComponentsType>({}))
|
|
21
|
-
|
|
22
|
-
export function useMdxComponents(): BoltdocsMdxComponents {
|
|
23
|
-
const context = use(MdxComponentsContext)
|
|
24
|
-
|
|
25
|
-
// Fallback to global registry for dual-package hazards
|
|
26
|
-
if (
|
|
27
|
-
(!context || Object.keys(context).length === 0) &&
|
|
28
|
-
(globalThis as any)[MDX_COMPONENTS_INSTANCE_SYMBOL]
|
|
29
|
-
) {
|
|
30
|
-
return (globalThis as any)[
|
|
31
|
-
MDX_COMPONENTS_INSTANCE_SYMBOL
|
|
32
|
-
] as BoltdocsMdxComponents
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return context as any as BoltdocsMdxComponents
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function MdxComponentsProvider({
|
|
39
|
-
components,
|
|
40
|
-
children,
|
|
41
|
-
}: {
|
|
42
|
-
components: Record<string, React.ComponentType<any>>
|
|
43
|
-
children: React.ReactNode
|
|
44
|
-
}) {
|
|
45
|
-
const processedComponents = useMemo(() => {
|
|
46
|
-
const processed: Record<string, any> = {}
|
|
47
|
-
const frontmatter: Record<string, React.ComponentType<any>> = {}
|
|
48
|
-
|
|
49
|
-
Object.entries(components).forEach(([key, value]) => {
|
|
50
|
-
if (key.startsWith('Frontmatter_')) {
|
|
51
|
-
const cleanKey = key.slice('Frontmatter_'.length)
|
|
52
|
-
frontmatter[cleanKey] = value
|
|
53
|
-
} else {
|
|
54
|
-
processed[key] = value
|
|
55
|
-
}
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
processed.Frontmatter = frontmatter
|
|
59
|
-
return processed as MdxComponentsType
|
|
60
|
-
}, [components])
|
|
61
|
-
|
|
62
|
-
// Sync with global registry
|
|
63
|
-
if (typeof globalThis !== 'undefined') {
|
|
64
|
-
;(globalThis as any)[MDX_COMPONENTS_INSTANCE_SYMBOL] = processedComponents
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return (
|
|
68
|
-
<MdxComponentsContext.Provider value={processedComponents}>
|
|
69
|
-
{children}
|
|
70
|
-
</MdxComponentsContext.Provider>
|
|
71
|
-
)
|
|
72
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { createContext, use } from 'react'
|
|
2
|
-
import type { ComponentRoute } from '../types'
|
|
3
|
-
|
|
4
|
-
interface RoutesContextType {
|
|
5
|
-
routes: ComponentRoute[]
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const RoutesContext = createContext<RoutesContextType>({
|
|
9
|
-
routes: [],
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Hook to access the processed routes list from the closest provider.
|
|
14
|
-
*/
|
|
15
|
-
export function useRoutesContext() {
|
|
16
|
-
return use(RoutesContext)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Provider component for the documentation routes.
|
|
21
|
-
*/
|
|
22
|
-
export function RoutesProvider({
|
|
23
|
-
routes,
|
|
24
|
-
children,
|
|
25
|
-
}: {
|
|
26
|
-
routes: ComponentRoute[]
|
|
27
|
-
children: React.ReactNode
|
|
28
|
-
}) {
|
|
29
|
-
return (
|
|
30
|
-
<RoutesContext.Provider value={{ routes }}>
|
|
31
|
-
{children}
|
|
32
|
-
</RoutesContext.Provider>
|
|
33
|
-
)
|
|
34
|
-
}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { useEffect, 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
|
-
// Helper to handle scroll logic
|
|
13
|
-
const handleScroll = (behavior: ScrollBehavior = 'auto') => {
|
|
14
|
-
const container = document.querySelector('.boltdocs-content') || window
|
|
15
|
-
|
|
16
|
-
const getScrollTop = () => {
|
|
17
|
-
if (container === window) return window.scrollY
|
|
18
|
-
return (container as HTMLElement).scrollTop
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const scrollTo = (top: number, scrollBehavior: ScrollBehavior) => {
|
|
22
|
-
if (container === window) {
|
|
23
|
-
window.scrollTo({ top, behavior: scrollBehavior })
|
|
24
|
-
} else {
|
|
25
|
-
;(container as HTMLElement).scrollTo({ top, behavior: scrollBehavior })
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (hash) {
|
|
30
|
-
const id = hash.replace('#', '')
|
|
31
|
-
const element = document.getElementById(id)
|
|
32
|
-
if (element) {
|
|
33
|
-
const offset = 80
|
|
34
|
-
const containerTop =
|
|
35
|
-
container === window
|
|
36
|
-
? 0
|
|
37
|
-
: (container as HTMLElement).getBoundingClientRect().top
|
|
38
|
-
const elementRect = element.getBoundingClientRect().top
|
|
39
|
-
const elementPosition = elementRect - containerTop
|
|
40
|
-
const offsetPosition = elementPosition - offset + getScrollTop()
|
|
41
|
-
|
|
42
|
-
scrollTo(offsetPosition, behavior)
|
|
43
|
-
return true
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
scrollTo(0, behavior)
|
|
48
|
-
return false
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// 1. Immediate sync scroll before paint
|
|
52
|
-
// biome-ignore lint/correctness/useExhaustiveDependencies: pathname is used as a trigger for scroll-to-top on navigation
|
|
53
|
-
useLayoutEffect(() => {
|
|
54
|
-
handleScroll('auto')
|
|
55
|
-
}, [pathname, hash])
|
|
56
|
-
|
|
57
|
-
// 2. Delayed async scroll as fallback/stabilizer after paint & passive effects
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
// Immediate run after paint (helps override old component unmount/revert side effects)
|
|
60
|
-
handleScroll('auto')
|
|
61
|
-
|
|
62
|
-
// Double-check inside requestAnimationFrame to catch concurrent renders or dynamic layout recalculations
|
|
63
|
-
const rafId = requestAnimationFrame(() => {
|
|
64
|
-
handleScroll('auto')
|
|
65
|
-
// Dispatch resize event so external components/scroll libraries (like GSAP ScrollTrigger) recalculate trigger offsets
|
|
66
|
-
window.dispatchEvent(new Event('resize'))
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
return () => cancelAnimationFrame(rafId)
|
|
70
|
-
}, [pathname, hash])
|
|
71
|
-
|
|
72
|
-
return null
|
|
73
|
-
}
|
|
74
|
-
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { createContext, use, useState, useEffect } from 'react'
|
|
2
|
-
|
|
3
|
-
export type Theme = 'light' | 'dark' | 'system'
|
|
4
|
-
export type ResolvedTheme = 'light' | 'dark'
|
|
5
|
-
|
|
6
|
-
interface ThemeContextType {
|
|
7
|
-
theme: Theme
|
|
8
|
-
resolvedTheme: ResolvedTheme
|
|
9
|
-
setTheme: (theme: Theme) => void
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const THEME_CONTEXT_SYMBOL = Symbol.for('__BDOCS_THEME_CONTEXT__')
|
|
13
|
-
const THEME_INSTANCE_SYMBOL = Symbol.for('__BDOCS_THEME_INSTANCE__')
|
|
14
|
-
const THEME_EVENT = 'boltdocs-theme-change'
|
|
15
|
-
|
|
16
|
-
const ThemeContext =
|
|
17
|
-
(globalThis as any)[THEME_CONTEXT_SYMBOL] ||
|
|
18
|
-
((globalThis as any)[THEME_CONTEXT_SYMBOL] = createContext<
|
|
19
|
-
ThemeContextType | undefined
|
|
20
|
-
>(undefined))
|
|
21
|
-
|
|
22
|
-
export function ThemeProvider({ children }: { children: React.ReactNode }) {
|
|
23
|
-
const [theme, setThemeState] = useState<Theme>('system')
|
|
24
|
-
const [resolvedTheme, setResolvedTheme] = useState<ResolvedTheme>('dark')
|
|
25
|
-
|
|
26
|
-
const applyTheme = (targetTheme: Theme) => {
|
|
27
|
-
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
|
28
|
-
const isDark =
|
|
29
|
-
targetTheme === 'dark' || (targetTheme === 'system' && mediaQuery.matches)
|
|
30
|
-
|
|
31
|
-
const root = window.document.documentElement
|
|
32
|
-
root.classList.toggle('dark', isDark)
|
|
33
|
-
root.dataset.theme = isDark ? 'dark' : 'light'
|
|
34
|
-
setResolvedTheme(isDark ? 'dark' : 'light')
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
const savedTheme = localStorage.getItem('boltdocs-theme') as Theme | null
|
|
39
|
-
if (savedTheme) {
|
|
40
|
-
setThemeState(savedTheme)
|
|
41
|
-
applyTheme(savedTheme)
|
|
42
|
-
} else {
|
|
43
|
-
applyTheme('system')
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
|
47
|
-
const listener = () => {
|
|
48
|
-
const current =
|
|
49
|
-
(localStorage.getItem('boltdocs-theme') as Theme) || 'system'
|
|
50
|
-
if (current === 'system') applyTheme('system')
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
mediaQuery.addEventListener('change', listener)
|
|
54
|
-
return () => mediaQuery.removeEventListener('change', listener)
|
|
55
|
-
}, [])
|
|
56
|
-
|
|
57
|
-
const setTheme = (newTheme: Theme) => {
|
|
58
|
-
setThemeState(newTheme)
|
|
59
|
-
localStorage.setItem('boltdocs-theme', newTheme)
|
|
60
|
-
applyTheme(newTheme)
|
|
61
|
-
|
|
62
|
-
// Notify external listeners (dual-package hazard)
|
|
63
|
-
if (typeof window !== 'undefined') {
|
|
64
|
-
window.dispatchEvent(new CustomEvent(THEME_EVENT, { detail: newTheme }))
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const value = { theme, resolvedTheme, setTheme }
|
|
69
|
-
|
|
70
|
-
// Sync with global registry
|
|
71
|
-
if (typeof globalThis !== 'undefined') {
|
|
72
|
-
;(globalThis as any)[THEME_INSTANCE_SYMBOL] = value
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function useTheme() {
|
|
79
|
-
const context = use(ThemeContext)
|
|
80
|
-
const [, forceUpdate] = useState({})
|
|
81
|
-
|
|
82
|
-
useEffect(() => {
|
|
83
|
-
if (context) return
|
|
84
|
-
|
|
85
|
-
const handler = () => forceUpdate({})
|
|
86
|
-
window.addEventListener(THEME_EVENT, handler)
|
|
87
|
-
return () => window.removeEventListener(THEME_EVENT, handler)
|
|
88
|
-
}, [context])
|
|
89
|
-
|
|
90
|
-
// Fallback to global registry for dual-package hazards
|
|
91
|
-
if (
|
|
92
|
-
!context &&
|
|
93
|
-
typeof globalThis !== 'undefined' &&
|
|
94
|
-
(globalThis as any)[THEME_INSTANCE_SYMBOL]
|
|
95
|
-
) {
|
|
96
|
-
return (globalThis as any)[THEME_INSTANCE_SYMBOL] as ThemeContextType
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (context === undefined) {
|
|
100
|
-
throw new Error('useTheme must be used within a ThemeProvider')
|
|
101
|
-
}
|
|
102
|
-
return context as ThemeContextType
|
|
103
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext, useState, useEffect } from 'react'
|
|
2
|
-
import { useLocation } from 'react-router-dom'
|
|
3
|
-
|
|
4
|
-
interface UIContextType {
|
|
5
|
-
isSidebarOpen: boolean
|
|
6
|
-
toggleSidebar: () => void
|
|
7
|
-
closeSidebar: () => void
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const UIContext = createContext<UIContextType | undefined>(undefined)
|
|
11
|
-
|
|
12
|
-
export function UIProvider({ children }: { children: React.ReactNode }) {
|
|
13
|
-
const [isSidebarOpen, setIsSidebarOpen] = useState(false)
|
|
14
|
-
const location = useLocation()
|
|
15
|
-
|
|
16
|
-
const toggleSidebar = () => setIsSidebarOpen((prev) => !prev)
|
|
17
|
-
const closeSidebar = () => setIsSidebarOpen(false)
|
|
18
|
-
|
|
19
|
-
// Close sidebar on navigation
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
setIsSidebarOpen(false)
|
|
22
|
-
}, [location.pathname])
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<UIContext.Provider value={{ isSidebarOpen, toggleSidebar, closeSidebar }}>
|
|
26
|
-
{children}
|
|
27
|
-
</UIContext.Provider>
|
|
28
|
-
)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function useUI() {
|
|
32
|
-
const context = useContext(UIContext)
|
|
33
|
-
if (context === undefined) {
|
|
34
|
-
// Safe fallback for split bundles, independent component renders, or during SSR
|
|
35
|
-
return {
|
|
36
|
-
isSidebarOpen: false,
|
|
37
|
-
toggleSidebar: () => {},
|
|
38
|
-
closeSidebar: () => {},
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return context
|
|
42
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { DocsLayout as DocsLayoutPrimitive } from './primitives/docs-layout'
|
|
2
|
-
import { Navbar } from './ui-base/navbar'
|
|
3
|
-
import { Sidebar } from './ui-base/sidebar'
|
|
4
|
-
import { OnThisPage } from './ui-base/on-this-page'
|
|
5
|
-
import { Breadcrumbs } from './ui-base/breadcrumbs'
|
|
6
|
-
import { PageNav } from './ui-base/page-nav'
|
|
7
|
-
import { ErrorBoundary } from './ui-base/error-boundary'
|
|
8
|
-
import { CopyMarkdown } from './ui-base/copy-markdown'
|
|
9
|
-
import { useRoutes } from '../hooks/use-routes'
|
|
10
|
-
import { useConfig } from '../app/config-context'
|
|
11
|
-
|
|
12
|
-
interface DocsLayoutThemeProps {
|
|
13
|
-
children?: React.ReactNode
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Pre-assembled high-fidelity documentation layout component.
|
|
18
|
-
* Fully styled and optimized to adapt seamlessly to our custom Parchment/Slate theme.
|
|
19
|
-
*/
|
|
20
|
-
function DocsLayoutComponent({ children }: DocsLayoutThemeProps) {
|
|
21
|
-
const { routes: filteredRoutes, currentRoute } = useRoutes()
|
|
22
|
-
const config = useConfig()
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<DocsLayoutPrimitive className="selection:bg-primary-500/10 selection:text-primary-500">
|
|
26
|
-
<Navbar />
|
|
27
|
-
<DocsLayoutPrimitive.Body className="bg-main">
|
|
28
|
-
<Sidebar routes={filteredRoutes || []} config={config} />
|
|
29
|
-
<DocsLayoutPrimitive.Content className="animate-in fade-in duration-500 scroll-smooth">
|
|
30
|
-
<DocsLayoutPrimitive.ContentMdx className="max-w-3xl sm:max-w-4xl lg:max-w-4xl px-2 pt-8 pb-24">
|
|
31
|
-
<DocsLayoutPrimitive.Header>
|
|
32
|
-
<div className="mb-4 border-b border-subtle pb-4 flex flex-wrap items-center justify-between gap-3">
|
|
33
|
-
<Breadcrumbs />
|
|
34
|
-
<CopyMarkdown
|
|
35
|
-
mdxRaw={currentRoute?._rawContent}
|
|
36
|
-
route={currentRoute}
|
|
37
|
-
/>
|
|
38
|
-
</div>
|
|
39
|
-
|
|
40
|
-
{/* Inject Main Page Heading automatically */}
|
|
41
|
-
{currentRoute?.title && (
|
|
42
|
-
<h1 className="text-4xl font-bold tracking-tight text-default mb-3">
|
|
43
|
-
{currentRoute.title}
|
|
44
|
-
</h1>
|
|
45
|
-
)}
|
|
46
|
-
{currentRoute?.description && (
|
|
47
|
-
<p className="text-lg text-muted-foreground mb-6 leading-relaxed">
|
|
48
|
-
{currentRoute.description}
|
|
49
|
-
</p>
|
|
50
|
-
)}
|
|
51
|
-
</DocsLayoutPrimitive.Header>
|
|
52
|
-
|
|
53
|
-
<ErrorBoundary>
|
|
54
|
-
<div className="prose prose-neutral dark:prose-invert max-w-none">
|
|
55
|
-
{children}
|
|
56
|
-
</div>
|
|
57
|
-
</ErrorBoundary>
|
|
58
|
-
|
|
59
|
-
<DocsLayoutPrimitive.Footer>
|
|
60
|
-
<PageNav />
|
|
61
|
-
</DocsLayoutPrimitive.Footer>
|
|
62
|
-
</DocsLayoutPrimitive.ContentMdx>
|
|
63
|
-
</DocsLayoutPrimitive.Content>
|
|
64
|
-
<OnThisPage
|
|
65
|
-
headings={currentRoute?.headings}
|
|
66
|
-
editLink={config.theme?.editLink}
|
|
67
|
-
communityHelp={config.theme?.communityHelp}
|
|
68
|
-
filePath={currentRoute?.filePath}
|
|
69
|
-
/>
|
|
70
|
-
</DocsLayoutPrimitive.Body>
|
|
71
|
-
</DocsLayoutPrimitive>
|
|
72
|
-
)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Expose the primitive sub-components directly on the Default DocsLayout
|
|
76
|
-
// to maintain complete backward-compatibility for custom theme assemblies.
|
|
77
|
-
export const DocsLayout = Object.assign(DocsLayoutComponent, {
|
|
78
|
-
Body: DocsLayoutPrimitive.Body,
|
|
79
|
-
Content: DocsLayoutPrimitive.Content,
|
|
80
|
-
ContentMdx: DocsLayoutPrimitive.ContentMdx,
|
|
81
|
-
Header: DocsLayoutPrimitive.Header,
|
|
82
|
-
Footer: DocsLayoutPrimitive.Footer,
|
|
83
|
-
}) as any
|
|
84
|
-
|
|
85
|
-
export default DocsLayout
|