boltdocs 2.5.6 → 2.6.1
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/bin/boltdocs.js +2 -2
- package/dist/client/index.cjs +6 -0
- package/dist/client/{index.d.mts → index.d.cts} +135 -265
- package/dist/client/index.d.ts +136 -266
- package/dist/client/index.js +1 -1
- package/dist/client/theme/neutral.css +90 -50
- package/dist/node/cli-entry.cjs +2 -2
- package/dist/node/cli-entry.mjs +2 -2
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.d.cts +168 -205
- package/dist/node/index.d.mts +168 -205
- package/dist/node/index.mjs +1 -1
- package/dist/node-CWN8U_p8.mjs +88 -0
- package/dist/node-D5iosYXv.cjs +88 -0
- package/dist/{package-OFZf0s2j.mjs → package-DukYeKmD.mjs} +1 -1
- package/dist/{package-BY8Jd2j4.cjs → package-c99Cs7mD.cjs} +1 -1
- package/dist/search-dialog-3lvKsbVG.js +6 -0
- package/dist/search-dialog-DMK5OpgH.cjs +6 -0
- package/dist/use-search-C9bxCqfF.js +6 -0
- package/dist/use-search-DcfZSunO.cjs +6 -0
- package/package.json +21 -23
- package/src/client/app/config-context.tsx +38 -5
- package/src/client/app/doc-page.tsx +34 -0
- package/src/client/app/mdx-component.tsx +2 -3
- package/src/client/app/mdx-components-context.tsx +27 -2
- package/src/client/app/routes-context.tsx +34 -0
- package/src/client/app/scroll-handler.tsx +7 -4
- package/src/client/app/theme-context.tsx +71 -67
- package/src/client/components/docs-layout.tsx +1 -2
- package/src/client/components/icons-dev.tsx +36 -5
- package/src/client/components/mdx/admonition.tsx +11 -27
- package/src/client/components/mdx/badge.tsx +1 -1
- package/src/client/components/mdx/button.tsx +3 -3
- package/src/client/components/mdx/card.tsx +1 -1
- package/src/client/components/mdx/code-block.tsx +90 -80
- package/src/client/components/mdx/component-preview.tsx +1 -5
- package/src/client/components/mdx/component-props.tsx +1 -1
- package/src/client/components/mdx/field.tsx +4 -5
- package/src/client/components/mdx/file-tree.tsx +6 -3
- package/src/client/components/mdx/hooks/use-code-block.ts +2 -2
- package/src/client/components/mdx/image.tsx +1 -1
- package/src/client/components/mdx/link.tsx +2 -2
- package/src/client/components/mdx/list.tsx +1 -1
- package/src/client/components/mdx/table.tsx +1 -1
- package/src/client/components/mdx/tabs.tsx +1 -1
- package/src/client/components/primitives/breadcrumbs.tsx +1 -7
- package/src/client/components/primitives/button-group.tsx +1 -1
- package/src/client/components/primitives/button.tsx +1 -1
- package/src/client/components/primitives/code-block.tsx +113 -0
- package/src/client/components/primitives/link.tsx +23 -41
- package/src/client/components/primitives/menu.tsx +5 -6
- package/src/client/components/primitives/navbar.tsx +6 -18
- package/src/client/components/primitives/navigation-menu.tsx +4 -4
- package/src/client/components/primitives/on-this-page.tsx +6 -10
- package/src/client/components/primitives/page-nav.tsx +4 -9
- package/src/client/components/primitives/popover.tsx +1 -1
- package/src/client/components/primitives/search-dialog.tsx +3 -6
- package/src/client/components/primitives/sidebar.tsx +80 -22
- package/src/client/components/primitives/skeleton.tsx +1 -1
- package/src/client/components/primitives/tabs.tsx +4 -11
- package/src/client/components/primitives/tooltip.tsx +3 -3
- package/src/client/components/ui-base/breadcrumbs.tsx +4 -6
- package/src/client/components/ui-base/copy-markdown.tsx +2 -7
- package/src/client/components/ui-base/github-stars.tsx +2 -2
- package/src/client/components/ui-base/head.tsx +58 -51
- package/src/client/components/ui-base/loading.tsx +2 -2
- package/src/client/components/ui-base/navbar.tsx +12 -14
- package/src/client/components/ui-base/not-found.tsx +1 -1
- package/src/client/components/ui-base/on-this-page.tsx +6 -6
- package/src/client/components/ui-base/page-nav.tsx +4 -8
- package/src/client/components/ui-base/search-dialog.tsx +10 -8
- package/src/client/components/ui-base/sidebar.tsx +76 -23
- package/src/client/components/ui-base/tabs.tsx +9 -8
- package/src/client/components/ui-base/theme-toggle.tsx +2 -2
- package/src/client/hooks/use-i18n.ts +3 -3
- package/src/client/hooks/use-localized-to.ts +1 -1
- package/src/client/hooks/use-navbar.ts +8 -6
- package/src/client/hooks/use-routes.ts +19 -11
- package/src/client/hooks/use-search.ts +1 -1
- package/src/client/hooks/use-sidebar.ts +48 -2
- package/src/client/hooks/use-tabs.ts +6 -2
- package/src/client/hooks/use-version.ts +3 -3
- package/src/client/index.ts +20 -22
- package/src/client/ssg/boltdocs-shell.tsx +127 -0
- package/src/client/ssg/create-routes.tsx +179 -0
- package/src/client/ssg/index.ts +3 -0
- package/src/client/ssg/mdx-page.tsx +37 -0
- package/src/client/store/boltdocs-context.tsx +46 -99
- package/src/client/theme/neutral.css +90 -50
- package/src/client/types.ts +5 -33
- package/src/client/utils/react-to-text.ts +34 -0
- package/src/shared/config-utils.ts +12 -0
- package/src/shared/types.ts +171 -0
- package/dist/cache-Cr8W2zgZ.cjs +0 -6
- package/dist/cache-DFdakSmR.mjs +0 -6
- package/dist/client/index.mjs +0 -6
- package/dist/client/ssr.cjs +0 -6
- package/dist/client/ssr.d.cts +0 -80
- package/dist/client/ssr.d.mts +0 -80
- package/dist/client/ssr.mjs +0 -6
- package/dist/node-CWXme96p.mjs +0 -73
- package/dist/node-VYfhzGrh.cjs +0 -73
- package/dist/search-dialog-BeNyI_KQ.mjs +0 -6
- package/dist/search-dialog-dYsCAk5S.js +0 -6
- package/dist/use-search-D25n0PrV.mjs +0 -6
- package/dist/use-search-WuzdH1cJ.js +0 -6
- package/src/client/app/index.tsx +0 -348
- package/src/client/app/mdx-page.tsx +0 -15
- package/src/client/app/preload.tsx +0 -66
- package/src/client/app/router.tsx +0 -30
- package/src/client/components/default-layout.tsx +0 -90
- package/src/client/integrations/codesandbox.ts +0 -179
- package/src/client/integrations/index.ts +0 -1
- package/src/client/ssr.tsx +0 -65
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
AnchorProvider,
|
|
4
4
|
ScrollProvider,
|
|
5
5
|
useActiveAnchor,
|
|
6
|
-
} from '
|
|
7
|
-
import
|
|
8
|
-
import { useOnThisPage } from '
|
|
9
|
-
import type { OnThisPageProps } from '
|
|
6
|
+
} from '../primitives/on-this-page'
|
|
7
|
+
import { useRef, useEffect, useState, useCallback, useMemo } from 'react'
|
|
8
|
+
import { useOnThisPage } from '../../hooks/use-onthispage'
|
|
9
|
+
import type { OnThisPageProps } from '../../types'
|
|
10
10
|
import { Pencil, CircleHelp, TextAlignStart } from 'lucide-react'
|
|
11
11
|
|
|
12
12
|
export function OnThisPage({
|
|
@@ -17,7 +17,7 @@ export function OnThisPage({
|
|
|
17
17
|
}: OnThisPageProps) {
|
|
18
18
|
const { headings } = useOnThisPage(rawHeadings)
|
|
19
19
|
|
|
20
|
-
const toc =
|
|
20
|
+
const toc = useMemo(
|
|
21
21
|
() =>
|
|
22
22
|
headings.map((h) => ({ title: h.text, url: `#${h.id}`, depth: h.level })),
|
|
23
23
|
[headings],
|
|
@@ -115,7 +115,7 @@ function OnThisPageInner({
|
|
|
115
115
|
|
|
116
116
|
{(editLink || communityHelp) && (
|
|
117
117
|
<div className="mt-8 pt-8 border-t border-border-subtle space-y-4">
|
|
118
|
-
<p className="text-xs font-bold uppercase
|
|
118
|
+
<p className="text-xs font-bold uppercase text-text-main">
|
|
119
119
|
Need help?
|
|
120
120
|
</p>
|
|
121
121
|
<ul className="space-y-3">
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { usePageNav } from '
|
|
2
|
-
import { PageNav as PageNavPrimitive } from '
|
|
1
|
+
import { usePageNav } from '../../hooks/use-page-nav'
|
|
2
|
+
import { PageNav as PageNavPrimitive } from '../primitives/page-nav'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Component to display the previous and next page navigation buttons.
|
|
@@ -14,9 +14,7 @@ export function PageNav() {
|
|
|
14
14
|
<PageNavPrimitive.Root className="animate-in fade-in slide-in-from-bottom-4 duration-700">
|
|
15
15
|
{prevPage ? (
|
|
16
16
|
<PageNavPrimitive.Link to={prevPage.path} direction="prev">
|
|
17
|
-
<PageNavPrimitive.Title>
|
|
18
|
-
Previous
|
|
19
|
-
</PageNavPrimitive.Title>
|
|
17
|
+
<PageNavPrimitive.Title>Previous</PageNavPrimitive.Title>
|
|
20
18
|
<PageNavPrimitive.Description>
|
|
21
19
|
{prevPage.title}
|
|
22
20
|
</PageNavPrimitive.Description>
|
|
@@ -27,9 +25,7 @@ export function PageNav() {
|
|
|
27
25
|
|
|
28
26
|
{nextPage && (
|
|
29
27
|
<PageNavPrimitive.Link to={nextPage.path} direction="next">
|
|
30
|
-
<PageNavPrimitive.Title>
|
|
31
|
-
Next
|
|
32
|
-
</PageNavPrimitive.Title>
|
|
28
|
+
<PageNavPrimitive.Title>Next</PageNavPrimitive.Title>
|
|
33
29
|
<PageNavPrimitive.Description>
|
|
34
30
|
{nextPage.title}
|
|
35
31
|
</PageNavPrimitive.Description>
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { useEffect, useCallback } from 'react'
|
|
2
|
-
import { useSearch } from '
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
} from '@components/primitives/search-dialog'
|
|
6
|
-
import Navbar from '@components/primitives/navbar'
|
|
2
|
+
import { useSearch } from '../../hooks/use-search'
|
|
3
|
+
import { SearchDialog as SearchDialogPrimitive } from '../primitives/search-dialog'
|
|
4
|
+
import Navbar from '../primitives/navbar'
|
|
7
5
|
import { useNavigate } from 'react-router-dom'
|
|
8
|
-
import type { ComponentRoute } from '
|
|
6
|
+
import type { ComponentRoute } from '../../types'
|
|
9
7
|
interface SearchResult {
|
|
10
8
|
id: string
|
|
11
9
|
title: string
|
|
@@ -73,8 +71,12 @@ export function SearchDialog({ routes }: { routes: ComponentRoute[] }) {
|
|
|
73
71
|
>
|
|
74
72
|
<SearchDialogPrimitive.Item.Icon isHeading={item.isHeading} />
|
|
75
73
|
<div className="flex flex-col justify-center gap-0.5">
|
|
76
|
-
<SearchDialogPrimitive.Item.Title>
|
|
77
|
-
|
|
74
|
+
<SearchDialogPrimitive.Item.Title>
|
|
75
|
+
{item.title}
|
|
76
|
+
</SearchDialogPrimitive.Item.Title>
|
|
77
|
+
<SearchDialogPrimitive.Item.Bio>
|
|
78
|
+
{item.bio}
|
|
79
|
+
</SearchDialogPrimitive.Item.Bio>
|
|
78
80
|
</div>
|
|
79
81
|
</SearchDialogPrimitive.Item>
|
|
80
82
|
)}
|
|
@@ -1,52 +1,105 @@
|
|
|
1
1
|
import { useState, useEffect, useMemo } from 'react'
|
|
2
|
-
import { useSidebar } from '
|
|
3
|
-
import { Sidebar as SidebarPrimitive } from '
|
|
2
|
+
import { useSidebar } from '../../hooks/use-sidebar'
|
|
3
|
+
import { Sidebar as SidebarPrimitive } from '../primitives/sidebar'
|
|
4
4
|
import { PoweredBy } from './powered-by'
|
|
5
5
|
import * as LucideIcons from 'lucide-react'
|
|
6
|
-
import
|
|
7
|
-
import type {
|
|
6
|
+
import virtualIcons from 'virtual:boltdocs-icons'
|
|
7
|
+
import type { ComponentRoute } from '../../types'
|
|
8
|
+
import type { BoltdocsConfig } from '../../../shared/types'
|
|
8
9
|
|
|
9
10
|
function getIcon(iconName?: string): React.ElementType | undefined {
|
|
10
11
|
if (!iconName) return undefined
|
|
11
|
-
const icons = LucideIcons as unknown as Record<
|
|
12
|
-
|
|
12
|
+
const icons = { ...LucideIcons, ...virtualIcons } as unknown as Record<
|
|
13
|
+
string,
|
|
14
|
+
React.ElementType
|
|
15
|
+
>
|
|
16
|
+
const IconComponent = icons[iconName] || icons[iconName + 'Icon']
|
|
13
17
|
return IconComponent || undefined
|
|
14
18
|
}
|
|
15
19
|
|
|
16
|
-
function
|
|
17
|
-
|
|
20
|
+
function SidebarSubRouteGroup({
|
|
21
|
+
route,
|
|
18
22
|
activePath,
|
|
19
23
|
getIcon,
|
|
20
24
|
}: {
|
|
21
|
-
|
|
22
|
-
slug: string
|
|
23
|
-
title: string
|
|
24
|
-
routes: ComponentRoute[]
|
|
25
|
-
icon?: string
|
|
26
|
-
}
|
|
25
|
+
route: ComponentRoute
|
|
27
26
|
activePath: string
|
|
28
27
|
getIcon: (iconName?: string) => React.ElementType | undefined
|
|
29
28
|
}) {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
const isCurrent =
|
|
30
|
+
activePath ===
|
|
31
|
+
(route.path.endsWith('/') ? route.path.slice(0, -1) : route.path)
|
|
32
|
+
|
|
33
|
+
const hasActiveSubRoute = useMemo(
|
|
34
|
+
() => route.subRoutes?.some((r) => r.path === activePath),
|
|
35
|
+
[route.subRoutes, activePath],
|
|
33
36
|
)
|
|
34
37
|
|
|
35
|
-
const [isOpen, setIsOpen] = useState(
|
|
38
|
+
const [isOpen, setIsOpen] = useState(hasActiveSubRoute || isCurrent)
|
|
36
39
|
|
|
37
40
|
useEffect(() => {
|
|
38
|
-
if (
|
|
41
|
+
if (hasActiveSubRoute || isCurrent) {
|
|
39
42
|
setIsOpen(true)
|
|
40
43
|
}
|
|
41
|
-
}, [
|
|
44
|
+
}, [hasActiveSubRoute, isCurrent])
|
|
42
45
|
|
|
43
46
|
return (
|
|
44
|
-
<SidebarPrimitive.
|
|
45
|
-
|
|
47
|
+
<SidebarPrimitive.SubGroup
|
|
48
|
+
label={route.title}
|
|
49
|
+
href={route.path}
|
|
50
|
+
active={isCurrent}
|
|
51
|
+
icon={getIcon(route.icon)}
|
|
52
|
+
badge={route.badge}
|
|
46
53
|
isOpen={isOpen}
|
|
47
54
|
onToggle={() => setIsOpen(!isOpen)}
|
|
48
55
|
>
|
|
56
|
+
{route.subRoutes?.map((subRoute: ComponentRoute) => {
|
|
57
|
+
const isSubCurrent =
|
|
58
|
+
activePath ===
|
|
59
|
+
(subRoute.path.endsWith('/') ? subRoute.path.slice(0, -1) : subRoute.path)
|
|
60
|
+
return (
|
|
61
|
+
<SidebarPrimitive.Link
|
|
62
|
+
key={subRoute.path}
|
|
63
|
+
label={subRoute.title}
|
|
64
|
+
href={subRoute.path}
|
|
65
|
+
active={isSubCurrent}
|
|
66
|
+
icon={getIcon(subRoute.icon)}
|
|
67
|
+
badge={subRoute.badge}
|
|
68
|
+
/>
|
|
69
|
+
)
|
|
70
|
+
})}
|
|
71
|
+
</SidebarPrimitive.SubGroup>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function SidebarGroupSection({
|
|
76
|
+
group,
|
|
77
|
+
activePath,
|
|
78
|
+
getIcon,
|
|
79
|
+
}: {
|
|
80
|
+
group: {
|
|
81
|
+
slug: string
|
|
82
|
+
title: string
|
|
83
|
+
routes: ComponentRoute[]
|
|
84
|
+
icon?: string
|
|
85
|
+
}
|
|
86
|
+
activePath: string
|
|
87
|
+
getIcon: (iconName?: string) => React.ElementType | undefined
|
|
88
|
+
}) {
|
|
89
|
+
return (
|
|
90
|
+
<SidebarPrimitive.Group title={group.title} icon={getIcon(group.icon)}>
|
|
49
91
|
{group.routes.map((route: ComponentRoute) => {
|
|
92
|
+
if (route.subRoutes && route.subRoutes.length > 0) {
|
|
93
|
+
return (
|
|
94
|
+
<SidebarSubRouteGroup
|
|
95
|
+
key={route.path}
|
|
96
|
+
route={route}
|
|
97
|
+
activePath={activePath}
|
|
98
|
+
getIcon={getIcon}
|
|
99
|
+
/>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
50
103
|
const isCurrent =
|
|
51
104
|
activePath ===
|
|
52
105
|
(route.path.endsWith('/') ? route.path.slice(0, -1) : route.path)
|
|
@@ -98,7 +151,7 @@ export function Sidebar({
|
|
|
98
151
|
)}
|
|
99
152
|
|
|
100
153
|
{groups.map((group) => (
|
|
101
|
-
<
|
|
154
|
+
<SidebarGroupSection
|
|
102
155
|
key={group.slug}
|
|
103
156
|
group={group}
|
|
104
157
|
activePath={activePath}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { useTabs as useTabsHook } from '
|
|
2
|
-
import { Tabs as T } from '
|
|
3
|
-
import { Link } from '
|
|
4
|
-
import type { BoltdocsTab, ComponentRoute } from '
|
|
1
|
+
import { useTabs as useTabsHook } from '../../hooks/use-tabs'
|
|
2
|
+
import { Tabs as T } from '../primitives/tabs'
|
|
3
|
+
import { Link } from '../primitives/link'
|
|
4
|
+
import type { BoltdocsTab, ComponentRoute } from '../../types'
|
|
5
5
|
import * as Icons from 'lucide-react'
|
|
6
|
-
import { getTranslated } from '
|
|
7
|
-
import { useRoutes } from '
|
|
6
|
+
import { getTranslated } from '../../utils/i18n'
|
|
7
|
+
import { useRoutes } from '../../hooks/use-routes'
|
|
8
8
|
|
|
9
9
|
export function Tabs({
|
|
10
10
|
tabs,
|
|
@@ -50,10 +50,11 @@ export function Tabs({
|
|
|
50
50
|
ref={(el: HTMLAnchorElement | null) => {
|
|
51
51
|
tabRefs.current[index] = el
|
|
52
52
|
}}
|
|
53
|
-
className={`relative flex items-center gap-2 px-4 py-3 text-sm font-medium transition-colors outline-none ${
|
|
53
|
+
className={`relative flex items-center gap-2 px-4 py-3 text-sm font-medium transition-colors outline-none ${
|
|
54
|
+
isActive
|
|
54
55
|
? 'text-primary-500'
|
|
55
56
|
: 'text-text-muted hover:text-text-main'
|
|
56
|
-
|
|
57
|
+
}`}
|
|
57
58
|
>
|
|
58
59
|
{renderTabIcon(tab.icon)}
|
|
59
60
|
<span>{getTranslated(tab.text, currentLocale)}</span>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react'
|
|
2
2
|
import { Sun, Moon, Monitor } from 'lucide-react'
|
|
3
|
-
import { useTheme } from '
|
|
3
|
+
import { useTheme } from '../../app/theme-context'
|
|
4
4
|
import { Button } from 'react-aria-components'
|
|
5
|
-
import { Menu } from '
|
|
5
|
+
import { Menu } from '../primitives/menu'
|
|
6
6
|
|
|
7
7
|
export function ThemeToggle() {
|
|
8
8
|
const { theme, setTheme } = useTheme()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useNavigate } from 'react-router-dom'
|
|
2
|
-
import { getBaseFilePath } from '
|
|
2
|
+
import { getBaseFilePath } from '../utils/get-base-file-path'
|
|
3
3
|
import { useRoutes } from './use-routes'
|
|
4
|
-
import {
|
|
4
|
+
import { useBoltdocsContext } from '../store/boltdocs-context'
|
|
5
5
|
|
|
6
6
|
export interface LocaleOption {
|
|
7
7
|
key: string
|
|
@@ -25,7 +25,7 @@ export function useI18n(): UseI18nReturn {
|
|
|
25
25
|
const routeContext = useRoutes()
|
|
26
26
|
const { allRoutes, currentRoute, currentLocale, config } = routeContext
|
|
27
27
|
const i18n = config.i18n
|
|
28
|
-
const setLocale =
|
|
28
|
+
const { setLocale } = useBoltdocsContext()
|
|
29
29
|
|
|
30
30
|
const handleLocaleChange = (locale: string) => {
|
|
31
31
|
if (!i18n || locale === currentLocale) return
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { useLocation } from 'react-router-dom'
|
|
2
|
-
import { useConfig } from '
|
|
3
|
-
import { useTheme } from '
|
|
4
|
-
import type { NavbarLink } from '
|
|
5
|
-
import { getTranslated } from '
|
|
2
|
+
import { useConfig } from '../app/config-context'
|
|
3
|
+
import { useTheme } from '../app/theme-context'
|
|
4
|
+
import type { NavbarLink } from '../types'
|
|
5
|
+
import { getTranslated } from '../utils/i18n'
|
|
6
6
|
import { useRoutes } from './use-routes'
|
|
7
7
|
|
|
8
8
|
export function useNavbar() {
|
|
9
9
|
const config = useConfig()
|
|
10
|
-
const { theme } = useTheme()
|
|
10
|
+
const { theme, resolvedTheme } = useTheme()
|
|
11
11
|
const location = useLocation()
|
|
12
12
|
const { currentLocale } = useRoutes()
|
|
13
13
|
|
|
@@ -67,11 +67,13 @@ export function useNavbar() {
|
|
|
67
67
|
})
|
|
68
68
|
|
|
69
69
|
const logo = themeConfig.logo
|
|
70
|
+
// Use resolvedTheme so 'system' correctly maps to 'dark' or 'light'
|
|
71
|
+
// based on the OS preference, instead of always falling back to 'light'.
|
|
70
72
|
const logoSrc = !logo
|
|
71
73
|
? null
|
|
72
74
|
: typeof logo === 'string'
|
|
73
75
|
? logo
|
|
74
|
-
:
|
|
76
|
+
: resolvedTheme === 'dark'
|
|
75
77
|
? (logo as any).dark
|
|
76
78
|
: (logo as any).light
|
|
77
79
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useLocation } from 'react-router-dom'
|
|
2
|
-
import { useConfig } from '
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { useConfig } from '../app/config-context'
|
|
3
|
+
import { useRoutesContext } from '../app/routes-context'
|
|
4
|
+
import { useBoltdocsContext } from '../store/boltdocs-context'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Hook to access the framework's routing state.
|
|
@@ -9,17 +9,25 @@ import { useBoltdocsStore } from '../store/boltdocs-context'
|
|
|
9
9
|
* version and locale.
|
|
10
10
|
*/
|
|
11
11
|
export function useRoutes() {
|
|
12
|
-
const { routes: allRoutes } =
|
|
12
|
+
const { routes: allRoutes } = useRoutesContext()
|
|
13
13
|
const config = useConfig()
|
|
14
14
|
const location = useLocation()
|
|
15
15
|
|
|
16
16
|
// Use Zustand store for active state
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
const {
|
|
18
|
+
hasHydrated,
|
|
19
|
+
currentLocale: currentLocaleStore,
|
|
20
|
+
currentVersion: currentVersionStore,
|
|
21
|
+
} = useBoltdocsContext()
|
|
22
|
+
|
|
23
|
+
const normalize = (p: string) =>
|
|
24
|
+
p.endsWith('/') && p.length > 1 ? p.slice(0, -1) : p
|
|
25
|
+
const currentPath = normalize(location.pathname)
|
|
20
26
|
|
|
21
27
|
// Find the current route matching the pathname
|
|
22
|
-
const currentRoute = allRoutes
|
|
28
|
+
const currentRoute = allRoutes?.find?.(
|
|
29
|
+
(r) => normalize(r.path) === currentPath,
|
|
30
|
+
)
|
|
23
31
|
|
|
24
32
|
// Derive current locale and version
|
|
25
33
|
// Priority: URL (currentRoute) > Zustand Store (Persistence) > Config Default
|
|
@@ -36,7 +44,7 @@ export function useRoutes() {
|
|
|
36
44
|
: undefined
|
|
37
45
|
|
|
38
46
|
// Filter routes to those matching the current version and locale
|
|
39
|
-
const routes = allRoutes
|
|
47
|
+
const routes = allRoutes?.filter?.((r) => {
|
|
40
48
|
const localeMatch = config.i18n
|
|
41
49
|
? (r.locale || config.i18n.defaultLocale) === currentLocale
|
|
42
50
|
: true
|
|
@@ -53,7 +61,7 @@ export function useRoutes() {
|
|
|
53
61
|
const isCurrentRoutePrefixed = !!currentRoute?.locale
|
|
54
62
|
const isRoutePrefixed = !!r.locale
|
|
55
63
|
|
|
56
|
-
const hasAlternate = allRoutes
|
|
64
|
+
const hasAlternate = allRoutes?.some?.(
|
|
57
65
|
(alt) =>
|
|
58
66
|
alt !== r &&
|
|
59
67
|
alt.filePath === r.filePath &&
|
|
@@ -78,7 +86,7 @@ export function useRoutes() {
|
|
|
78
86
|
config.i18n?.locales[currentLocale as string] ||
|
|
79
87
|
currentLocale
|
|
80
88
|
|
|
81
|
-
const currentVersionConfig = config.versions?.versions
|
|
89
|
+
const currentVersionConfig = config.versions?.versions?.find?.(
|
|
82
90
|
(v) => v.path === currentVersion,
|
|
83
91
|
)
|
|
84
92
|
const currentVersionLabel = currentVersionConfig?.label || currentVersion
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useState, useMemo, useEffect } from 'react'
|
|
2
2
|
import { Index } from 'flexsearch'
|
|
3
3
|
import { useRoutes } from './use-routes'
|
|
4
|
-
import type { ComponentRoute } from '
|
|
4
|
+
import type { ComponentRoute } from '../types'
|
|
5
5
|
// @ts-ignore
|
|
6
6
|
import searchData from 'virtual:boltdocs-search'
|
|
7
7
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useLocation } from 'react-router-dom'
|
|
2
|
-
import { useConfig } from '
|
|
2
|
+
import { useConfig } from '../app/config-context'
|
|
3
3
|
import type { ComponentRoute } from '../types'
|
|
4
4
|
|
|
5
5
|
export function useSidebar(routes: ComponentRoute[]) {
|
|
@@ -41,7 +41,53 @@ export function useSidebar(routes: ComponentRoute[]) {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const groups = Array.from(groupsMap.values())
|
|
44
|
+
const groups = Array.from(groupsMap.values()).map((group) => {
|
|
45
|
+
const subRouteParents = new Map<string, ComponentRoute>()
|
|
46
|
+
const subRouteChildren = new Map<string, ComponentRoute[]>()
|
|
47
|
+
|
|
48
|
+
// First pass: Categorize as parent or child
|
|
49
|
+
for (const route of group.routes) {
|
|
50
|
+
if (route.subRouteGroup) {
|
|
51
|
+
const isParent =
|
|
52
|
+
route.path.endsWith(`/${route.subRouteGroup}`) ||
|
|
53
|
+
route.path.endsWith(`/${route.subRouteGroup}/`)
|
|
54
|
+
|
|
55
|
+
if (isParent && !subRouteParents.has(route.subRouteGroup)) {
|
|
56
|
+
subRouteParents.set(route.subRouteGroup, route)
|
|
57
|
+
} else {
|
|
58
|
+
if (!subRouteChildren.has(route.subRouteGroup)) {
|
|
59
|
+
subRouteChildren.set(route.subRouteGroup, [])
|
|
60
|
+
}
|
|
61
|
+
subRouteChildren.get(route.subRouteGroup)!.push(route)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const finalRoutes: ComponentRoute[] = []
|
|
67
|
+
const seenSubGroups = new Set<string>()
|
|
68
|
+
|
|
69
|
+
// Second pass: Assemble maintaining mostly original order
|
|
70
|
+
for (const route of group.routes) {
|
|
71
|
+
if (route.subRouteGroup) {
|
|
72
|
+
if (!seenSubGroups.has(route.subRouteGroup)) {
|
|
73
|
+
seenSubGroups.add(route.subRouteGroup)
|
|
74
|
+
const parent = subRouteParents.get(route.subRouteGroup)
|
|
75
|
+
const children = subRouteChildren.get(route.subRouteGroup) || []
|
|
76
|
+
|
|
77
|
+
if (parent) {
|
|
78
|
+
finalRoutes.push({ ...parent, subRoutes: children })
|
|
79
|
+
} else {
|
|
80
|
+
// Fallback
|
|
81
|
+
finalRoutes.push(...children)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
finalRoutes.push(route)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return { ...group, routes: finalRoutes }
|
|
90
|
+
})
|
|
45
91
|
|
|
46
92
|
return {
|
|
47
93
|
groups,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useLocation } from 'react-router-dom'
|
|
2
2
|
import { useEffect, useState, useRef } from 'react'
|
|
3
|
-
import type { ComponentRoute, BoltdocsTab } from '
|
|
3
|
+
import type { ComponentRoute, BoltdocsTab } from '../types'
|
|
4
4
|
|
|
5
5
|
export function useTabs(
|
|
6
6
|
tabs: BoltdocsTab[] = [],
|
|
@@ -14,7 +14,11 @@ export function useTabs(
|
|
|
14
14
|
width: 0,
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
-
const
|
|
17
|
+
const normalize = (p: string) =>
|
|
18
|
+
p.endsWith('/') && p.length > 1 ? p.slice(0, -1) : p
|
|
19
|
+
const currentPath = normalize(location.pathname)
|
|
20
|
+
|
|
21
|
+
const activeRoute = routes.find((r) => normalize(r.path) === currentPath)
|
|
18
22
|
const activeTabId = activeRoute?.tab?.toLowerCase()
|
|
19
23
|
const activeIndex = tabs.findIndex(
|
|
20
24
|
(tab) => tab.id.toLowerCase() === activeTabId,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useNavigate } from 'react-router-dom'
|
|
2
|
-
import { getBaseFilePath } from '
|
|
2
|
+
import { getBaseFilePath } from '../utils/get-base-file-path'
|
|
3
3
|
import { useRoutes } from './use-routes'
|
|
4
|
-
import {
|
|
4
|
+
import { useBoltdocsContext } from '../store/boltdocs-context'
|
|
5
5
|
|
|
6
6
|
export interface VersionOption {
|
|
7
7
|
key: string
|
|
@@ -26,7 +26,7 @@ export function useVersion(): UseVersionReturn {
|
|
|
26
26
|
const { allRoutes, currentRoute, currentVersion, currentLocale, config } =
|
|
27
27
|
routeContext
|
|
28
28
|
const versions = config.versions
|
|
29
|
-
const setVersion =
|
|
29
|
+
const { setVersion } = useBoltdocsContext()
|
|
30
30
|
|
|
31
31
|
const handleVersionChange = (version: string) => {
|
|
32
32
|
if (!versions || version === currentVersion) return
|
package/src/client/index.ts
CHANGED
|
@@ -1,35 +1,32 @@
|
|
|
1
|
-
export type { BoltdocsConfig, BoltdocsThemeConfig } from '../node/config'
|
|
2
1
|
export type {
|
|
3
2
|
ComponentRoute,
|
|
4
|
-
CreateBoltdocsAppOptions,
|
|
5
3
|
LayoutProps,
|
|
6
4
|
} from './types'
|
|
7
|
-
export
|
|
8
|
-
export { useConfig } from '
|
|
9
|
-
export { useTheme } from '
|
|
10
|
-
export { useRoutes } from '
|
|
11
|
-
export { useMdxComponents } from '
|
|
5
|
+
export * from './ssg'
|
|
6
|
+
export { useConfig } from './app/config-context'
|
|
7
|
+
export { useTheme } from './app/theme-context'
|
|
8
|
+
export { useRoutes } from './hooks/use-routes'
|
|
9
|
+
export { useMdxComponents } from './app/mdx-components-context'
|
|
12
10
|
|
|
13
11
|
// Hooks
|
|
14
|
-
export * from '
|
|
12
|
+
export * from './hooks/index'
|
|
15
13
|
// Composable layout building blocks
|
|
16
|
-
export { DocsLayout } from '
|
|
17
|
-
export { DefaultLayout } from '@components/default-layout'
|
|
14
|
+
export { DocsLayout } from './components/docs-layout'
|
|
18
15
|
|
|
19
16
|
// Default UI components (for use in custom layout.tsx)
|
|
20
|
-
export { Navbar } from '
|
|
21
|
-
export { Sidebar } from '
|
|
22
|
-
export { OnThisPage } from '
|
|
23
|
-
export { Head } from '
|
|
24
|
-
export { Breadcrumbs } from '
|
|
25
|
-
export { PageNav } from '
|
|
26
|
-
export { ErrorBoundary } from '
|
|
27
|
-
export { CopyMarkdown } from '
|
|
17
|
+
export { Navbar } from './components/ui-base/navbar'
|
|
18
|
+
export { Sidebar } from './components/ui-base/sidebar'
|
|
19
|
+
export { OnThisPage } from './components/ui-base/on-this-page'
|
|
20
|
+
export { Head } from './components/ui-base/head'
|
|
21
|
+
export { Breadcrumbs } from './components/ui-base/breadcrumbs'
|
|
22
|
+
export { PageNav } from './components/ui-base/page-nav'
|
|
23
|
+
export { ErrorBoundary } from './components/ui-base/error-boundary'
|
|
24
|
+
export { CopyMarkdown } from './components/ui-base/copy-markdown'
|
|
28
25
|
|
|
29
|
-
export { NotFound } from '
|
|
30
|
-
export { Loading } from '
|
|
31
|
-
export { CodeBlock } from '
|
|
32
|
-
export { Video } from '
|
|
26
|
+
export { NotFound } from './components/ui-base/not-found'
|
|
27
|
+
export { Loading } from './components/ui-base/loading'
|
|
28
|
+
export { CodeBlock } from './components/mdx/code-block'
|
|
29
|
+
export { Video } from './components/mdx/video'
|
|
33
30
|
|
|
34
31
|
// MDX Components
|
|
35
32
|
export {
|
|
@@ -104,3 +101,4 @@ export { Skeleton as PrimitiveSkeleton } from './components/primitives/skeleton'
|
|
|
104
101
|
|
|
105
102
|
// Utilities
|
|
106
103
|
export { cn } from './utils/cn'
|
|
104
|
+
export { getTranslated } from './utils/i18n'
|