boltdocs 2.7.10 → 2.7.11
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/dist/client/index.cjs +1929 -1
- package/dist/client/index.js +1880 -1
- package/dist/client/mdx.cjs +7 -1
- package/dist/client/mdx.js +7 -1
- package/dist/client/primitives.cjs +60 -1
- package/dist/client/primitives.js +20 -1
- package/dist/docs-layout-BXHV0xw_.cjs +1431 -0
- package/dist/docs-layout-DwFndmj5.js +1231 -0
- package/dist/icons-dev-3cZMyt8r.cjs +1204 -0
- package/dist/icons-dev-Df8OQ481.js +839 -0
- package/dist/image-DtrI2cw3.cjs +268 -0
- package/dist/image-jxPb-2iV.js +214 -0
- package/dist/mdx-BdWkJTeB.cjs +523 -0
- package/dist/mdx-UTTLFWJq.js +494 -0
- package/dist/node/cli-entry.cjs +1 -1
- package/dist/node/cli-entry.mjs +1 -1
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.mjs +1 -1
- package/dist/{node-DtEDyN1u.cjs → node-BSM4qcDK.cjs} +1 -1
- package/dist/{node-_1jhMGYx.mjs → node-BspZN3R2.mjs} +1 -1
- package/dist/{package-DrwtlXfk.cjs → package-DIIrjuWI.cjs} +1 -1
- package/dist/{package--0Yf0t1N.mjs → package-K0zsjGIz.mjs} +1 -1
- package/dist/{search-dialog-ByvGScjt.js → search-dialog-BHuIiUC6.js} +3 -1
- package/dist/search-dialog-BNF10tDl.js +375 -0
- package/dist/search-dialog-BwkDuI9R.cjs +220 -0
- package/dist/search-dialog-C7xuvyNk.cjs +386 -0
- package/dist/search-dialog-CIQg6k8c.cjs +8 -0
- package/dist/search-dialog-D-DDN7zJ.js +208 -0
- package/package.json +3 -4
- package/dist/docs-layout-KoWNZc8_.js +0 -6
- package/dist/docs-layout-x2yKt2cL.cjs +0 -6
- 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/search-dialog-B584t9ZF.js +0 -6
- package/dist/search-dialog-BvBopRsZ.cjs +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/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
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
import { Suspense, lazy, useState } from 'react'
|
|
2
|
-
import { cn } from '../../utils/cn'
|
|
3
|
-
import { useNavbar } from '../../hooks/use-navbar'
|
|
4
|
-
import { useRoutes } from '../../hooks/use-routes'
|
|
5
|
-
import NavbarPrimitive from '../primitives/navbar'
|
|
6
|
-
import { ThemeToggle } from './theme-toggle'
|
|
7
|
-
import { GithubStars } from './github-stars'
|
|
8
|
-
import { Tabs } from './tabs'
|
|
9
|
-
import { useLocation } from 'react-router-dom'
|
|
10
|
-
import type { BoltdocsSocialLink } from '../../../shared/types'
|
|
11
|
-
import { Button } from '../primitives/button'
|
|
12
|
-
import { Menu as MenuIcon, X } from './icons'
|
|
13
|
-
import { useLocalizedTo } from '../../hooks/use-localized-to'
|
|
14
|
-
import type { NavbarLink as NavbarLinkType } from '../../types'
|
|
15
|
-
import { useUI } from '../../app/ui-context'
|
|
16
|
-
import { VersionSelector, I18nSelector } from './version-i18n'
|
|
17
|
-
|
|
18
|
-
const SearchDialog = lazy(() =>
|
|
19
|
-
import('./search-dialog').then((m) => ({
|
|
20
|
-
default: m.SearchDialog,
|
|
21
|
-
})),
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
export function Navbar() {
|
|
25
|
-
const { links, title, logo, logoProps, github, social, config } = useNavbar()
|
|
26
|
-
const { routes, allRoutes, currentRoute, currentVersion, currentLocale } = useRoutes()
|
|
27
|
-
const { pathname } = useLocation()
|
|
28
|
-
const { isSidebarOpen, toggleSidebar } = useUI()
|
|
29
|
-
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
|
|
30
|
-
|
|
31
|
-
const themeConfig = config.theme || {}
|
|
32
|
-
const isDocs = !!currentRoute?.filePath
|
|
33
|
-
const hasTabs = themeConfig?.tabs && themeConfig.tabs.length > 0
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<NavbarPrimitive.Root
|
|
37
|
-
className={cn(
|
|
38
|
-
'border-b border-subtle bg-main/80 backdrop-blur-md',
|
|
39
|
-
hasTabs && 'border-b-0',
|
|
40
|
-
)}
|
|
41
|
-
>
|
|
42
|
-
<NavbarPrimitive.Content>
|
|
43
|
-
<NavbarPrimitive.Left>
|
|
44
|
-
{isDocs && (
|
|
45
|
-
<Button
|
|
46
|
-
onPress={toggleSidebar}
|
|
47
|
-
className="mr-2 lg:hidden p-1.5 h-8 w-8 flex items-center justify-center bg-transparent border-none outline-none select-none cursor-pointer rounded-xl hover:bg-primary-50/50 transition-colors"
|
|
48
|
-
aria-label={isSidebarOpen ? 'Close sidebar' : 'Open sidebar'}
|
|
49
|
-
>
|
|
50
|
-
{isSidebarOpen ? (
|
|
51
|
-
<X className="w-5 h-5 text-body" />
|
|
52
|
-
) : (
|
|
53
|
-
<MenuIcon className="w-5 h-5 text-body" />
|
|
54
|
-
)}
|
|
55
|
-
</Button>
|
|
56
|
-
)}
|
|
57
|
-
{logo && (
|
|
58
|
-
<NavbarPrimitive.Logo
|
|
59
|
-
src={logo}
|
|
60
|
-
alt={logoProps?.alt || title}
|
|
61
|
-
width={logoProps?.width ?? 24}
|
|
62
|
-
height={logoProps?.height ?? 24}
|
|
63
|
-
href="site:/"
|
|
64
|
-
/>
|
|
65
|
-
)}
|
|
66
|
-
<NavbarPrimitive.Title href="site:/">{title}</NavbarPrimitive.Title>
|
|
67
|
-
|
|
68
|
-
<div className="hidden sm:block">
|
|
69
|
-
{config.versions && currentVersion && <VersionSelector />}
|
|
70
|
-
</div>
|
|
71
|
-
</NavbarPrimitive.Left>
|
|
72
|
-
<NavbarPrimitive.Center>
|
|
73
|
-
<Suspense
|
|
74
|
-
fallback={
|
|
75
|
-
<div className="h-9 w-32 animate-pulse rounded-md bg-surface" />
|
|
76
|
-
}
|
|
77
|
-
>
|
|
78
|
-
<SearchDialog routes={routes || []} />
|
|
79
|
-
</Suspense>
|
|
80
|
-
</NavbarPrimitive.Center>
|
|
81
|
-
<NavbarPrimitive.Right>
|
|
82
|
-
<Suspense fallback={null}>
|
|
83
|
-
<div className="lg:hidden">
|
|
84
|
-
<SearchDialog routes={routes || []} />
|
|
85
|
-
</div>
|
|
86
|
-
</Suspense>
|
|
87
|
-
<NavbarPrimitive.Links>
|
|
88
|
-
{links.map((link) => (
|
|
89
|
-
<NavbarLinkItem key={link.href} link={link} />
|
|
90
|
-
))}
|
|
91
|
-
</NavbarPrimitive.Links>
|
|
92
|
-
|
|
93
|
-
<div className="hidden sm:flex items-center gap-2">
|
|
94
|
-
{config.i18n && currentLocale && <I18nSelector />}
|
|
95
|
-
<NavbarPrimitive.Split className="bg-subtle" />
|
|
96
|
-
</div>
|
|
97
|
-
|
|
98
|
-
<div className="hidden md:block">
|
|
99
|
-
<ThemeToggle />
|
|
100
|
-
</div>
|
|
101
|
-
|
|
102
|
-
{github && (
|
|
103
|
-
<div className="hidden md:block">
|
|
104
|
-
<GithubStars repo={themeConfig?.githubRepo ?? ''} />
|
|
105
|
-
</div>
|
|
106
|
-
)}
|
|
107
|
-
{social.length > 0 && (
|
|
108
|
-
<div className="hidden md:block">
|
|
109
|
-
<NavbarPrimitive.Split className="bg-subtle" />
|
|
110
|
-
</div>
|
|
111
|
-
)}
|
|
112
|
-
<div className="hidden md:flex items-center gap-1">
|
|
113
|
-
{social.map(({ icon, link }: BoltdocsSocialLink) => (
|
|
114
|
-
<NavbarPrimitive.Socials
|
|
115
|
-
key={link}
|
|
116
|
-
icon={icon}
|
|
117
|
-
link={link}
|
|
118
|
-
className="p-1.5 text-muted hover:text-body hover:bg-surface rounded-md transition-all focus-visible:ring-2 focus-visible:ring-primary-500/30"
|
|
119
|
-
/>
|
|
120
|
-
))}
|
|
121
|
-
</div>
|
|
122
|
-
|
|
123
|
-
<NavbarPrimitive.More
|
|
124
|
-
onPress={() => setIsMobileMenuOpen(true)}
|
|
125
|
-
className="text-muted hover:text-body active:scale-90 transition-all focus-visible:ring-2 focus-visible:ring-primary-500/30"
|
|
126
|
-
/>
|
|
127
|
-
</NavbarPrimitive.Right>
|
|
128
|
-
</NavbarPrimitive.Content>
|
|
129
|
-
|
|
130
|
-
<NavbarPrimitive.MobileMenu
|
|
131
|
-
isOpen={isMobileMenuOpen}
|
|
132
|
-
onClose={() => setIsMobileMenuOpen(false)}
|
|
133
|
-
className="bg-main/98 backdrop-blur-2xl"
|
|
134
|
-
>
|
|
135
|
-
<div className="flex flex-col gap-1">
|
|
136
|
-
{links.map((link) => (
|
|
137
|
-
<NavbarMobileLinkItem
|
|
138
|
-
key={link.href}
|
|
139
|
-
link={link}
|
|
140
|
-
onClose={() => setIsMobileMenuOpen(false)}
|
|
141
|
-
/>
|
|
142
|
-
))}
|
|
143
|
-
</div>
|
|
144
|
-
|
|
145
|
-
{social.length > 0 && (
|
|
146
|
-
<div className="mt-6">
|
|
147
|
-
<div className="px-4 mb-4 text-xs font-bold uppercase tracking-widest text-muted/50">
|
|
148
|
-
Connect
|
|
149
|
-
</div>
|
|
150
|
-
<div className="flex flex-wrap gap-2 px-2">
|
|
151
|
-
{social.map(({ icon, link }: BoltdocsSocialLink) => (
|
|
152
|
-
<NavbarPrimitive.Socials
|
|
153
|
-
key={link}
|
|
154
|
-
icon={icon}
|
|
155
|
-
link={link}
|
|
156
|
-
className="p-3 bg-surface border border-subtle rounded-xl flex-1 justify-center"
|
|
157
|
-
/>
|
|
158
|
-
))}
|
|
159
|
-
</div>
|
|
160
|
-
</div>
|
|
161
|
-
)}
|
|
162
|
-
</NavbarPrimitive.MobileMenu>
|
|
163
|
-
|
|
164
|
-
{isDocs && hasTabs && themeConfig?.tabs && (
|
|
165
|
-
<div className="w-full border-b border-subtle bg-main">
|
|
166
|
-
<Tabs tabs={themeConfig.tabs} routes={allRoutes || routes || []} />
|
|
167
|
-
</div>
|
|
168
|
-
)}
|
|
169
|
-
</NavbarPrimitive.Root>
|
|
170
|
-
)
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function NavbarLinkItem({ link }: { link: NavbarLinkType }) {
|
|
174
|
-
const localizedHref = useLocalizedTo(link.href || '')
|
|
175
|
-
const { pathname } = useLocation()
|
|
176
|
-
const active =
|
|
177
|
-
pathname === localizedHref || pathname.startsWith(localizedHref + '/')
|
|
178
|
-
const hasItems = link.items && link.items.length > 0
|
|
179
|
-
|
|
180
|
-
if (hasItems) {
|
|
181
|
-
return (
|
|
182
|
-
<NavbarPrimitive.Dropdown
|
|
183
|
-
label={
|
|
184
|
-
<span
|
|
185
|
-
className={cn(
|
|
186
|
-
'transition-colors outline-none font-medium focus-visible:ring-2 focus-visible:ring-primary-500/30 rounded-sm px-2 py-1',
|
|
187
|
-
active ? 'text-primary-500' : 'text-muted hover:text-body',
|
|
188
|
-
)}
|
|
189
|
-
>
|
|
190
|
-
{link.label as any}
|
|
191
|
-
</span>
|
|
192
|
-
}
|
|
193
|
-
>
|
|
194
|
-
{link.items?.map((item) => (
|
|
195
|
-
<NavbarPrimitive.DropdownItem
|
|
196
|
-
key={item.href}
|
|
197
|
-
href={useLocalizedTo(item.href || '')}
|
|
198
|
-
label={item.label as any}
|
|
199
|
-
/>
|
|
200
|
-
))}
|
|
201
|
-
</NavbarPrimitive.Dropdown>
|
|
202
|
-
)
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return (
|
|
206
|
-
<NavbarPrimitive.Link
|
|
207
|
-
{...(link as any)}
|
|
208
|
-
href={localizedHref}
|
|
209
|
-
active={active}
|
|
210
|
-
className={cn(
|
|
211
|
-
'transition-colors outline-none font-medium focus-visible:ring-2 focus-visible:ring-primary-500/30 rounded-sm',
|
|
212
|
-
active ? 'text-primary-500' : 'text-muted hover:text-body',
|
|
213
|
-
)}
|
|
214
|
-
/>
|
|
215
|
-
)
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
function NavbarMobileLinkItem({
|
|
219
|
-
link,
|
|
220
|
-
onClose,
|
|
221
|
-
}: {
|
|
222
|
-
link: NavbarLinkType
|
|
223
|
-
onClose: () => void
|
|
224
|
-
}) {
|
|
225
|
-
const localizedHref = useLocalizedTo(link.href || '')
|
|
226
|
-
const { pathname } = useLocation()
|
|
227
|
-
const active = pathname === localizedHref
|
|
228
|
-
const hasItems = link.items && link.items.length > 0
|
|
229
|
-
|
|
230
|
-
if (hasItems) {
|
|
231
|
-
return (
|
|
232
|
-
<div className="flex flex-col gap-1">
|
|
233
|
-
<div
|
|
234
|
-
className={cn(
|
|
235
|
-
'px-3 py-2 text-sm transition-all',
|
|
236
|
-
active ? 'text-body' : 'text-muted/80 hover:text-body',
|
|
237
|
-
)}
|
|
238
|
-
>
|
|
239
|
-
{link.label as any}
|
|
240
|
-
</div>
|
|
241
|
-
<div className="flex flex-col gap-1 pl-4">
|
|
242
|
-
{link.items?.map((item) => (
|
|
243
|
-
<NavbarMobileLinkItem
|
|
244
|
-
key={item.href}
|
|
245
|
-
link={item}
|
|
246
|
-
onClose={onClose}
|
|
247
|
-
/>
|
|
248
|
-
))}
|
|
249
|
-
</div>
|
|
250
|
-
</div>
|
|
251
|
-
)
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return (
|
|
255
|
-
<NavbarPrimitive.MobileLink
|
|
256
|
-
{...(link as any)}
|
|
257
|
-
href={localizedHref}
|
|
258
|
-
active={active}
|
|
259
|
-
onPress={onClose}
|
|
260
|
-
className={cn(
|
|
261
|
-
'transition-all',
|
|
262
|
-
active ? 'text-body' : 'text-muted/80 hover:text-body',
|
|
263
|
-
)}
|
|
264
|
-
/>
|
|
265
|
-
)
|
|
266
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { ArrowLeft } from './icons'
|
|
2
|
-
import { Link } from '../primitives/link'
|
|
3
|
-
|
|
4
|
-
export function NotFound() {
|
|
5
|
-
return (
|
|
6
|
-
<div className="flex items-center justify-center min-h-[65vh] text-center px-4">
|
|
7
|
-
<div className="space-y-6 max-w-md mx-auto p-8 border border-subtle bg-surface rounded-2xl shadow-xs">
|
|
8
|
-
<span className="block text-7xl font-extrabold tracking-tight text-primary-500">
|
|
9
|
-
404
|
|
10
|
-
</span>
|
|
11
|
-
<div className="space-y-2">
|
|
12
|
-
<h1 className="text-xl font-bold text-body">Page Not Found</h1>
|
|
13
|
-
<p className="text-sm text-muted leading-relaxed">
|
|
14
|
-
The page you're looking for doesn't exist or has been moved.
|
|
15
|
-
</p>
|
|
16
|
-
</div>
|
|
17
|
-
<Link
|
|
18
|
-
href="/"
|
|
19
|
-
className="inline-flex items-center gap-2 rounded-xl border border-subtle bg-main px-6 py-2.5 text-xs font-semibold text-body hover:bg-primary-50/50 hover:border-primary-500/50 transition-all duration-300 outline-none select-none"
|
|
20
|
-
>
|
|
21
|
-
<ArrowLeft size={14} /> Go to Home
|
|
22
|
-
</Link>
|
|
23
|
-
</div>
|
|
24
|
-
</div>
|
|
25
|
-
)
|
|
26
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { OnThisPage as OTP } from '../primitives/on-this-page'
|
|
2
|
-
import type { OnThisPageProps } from '../../types'
|
|
3
|
-
import { Pencil, CircleHelp, TextAlignStart } from './icons'
|
|
4
|
-
|
|
5
|
-
export function OnThisPage({
|
|
6
|
-
headings = [],
|
|
7
|
-
editLink,
|
|
8
|
-
communityHelp,
|
|
9
|
-
filePath,
|
|
10
|
-
}: OnThisPageProps) {
|
|
11
|
-
if (headings.length === 0) return null
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<OTP.Root>
|
|
15
|
-
<OTP.Header className="flex flex-row gap-x-2">
|
|
16
|
-
<TextAlignStart size={16} />
|
|
17
|
-
On this page
|
|
18
|
-
</OTP.Header>
|
|
19
|
-
|
|
20
|
-
<OTP.Tree headings={headings} />
|
|
21
|
-
|
|
22
|
-
{(editLink || communityHelp) && (
|
|
23
|
-
<div className="mt-8 pt-8 border-t border-subtle space-y-4">
|
|
24
|
-
<p className="text-xs font-bold text-body">Need help?</p>
|
|
25
|
-
<ul className="space-y-3">
|
|
26
|
-
{editLink && filePath && (
|
|
27
|
-
<li>
|
|
28
|
-
<a
|
|
29
|
-
href={editLink.replace(':path', filePath)}
|
|
30
|
-
target="_blank"
|
|
31
|
-
rel="noopener noreferrer"
|
|
32
|
-
className="flex items-center gap-2 text-sm text-muted hover:text-body transition-colors"
|
|
33
|
-
>
|
|
34
|
-
<Pencil size={16} />
|
|
35
|
-
Edit this page
|
|
36
|
-
</a>
|
|
37
|
-
</li>
|
|
38
|
-
)}
|
|
39
|
-
{communityHelp && (
|
|
40
|
-
<li>
|
|
41
|
-
<a
|
|
42
|
-
href={communityHelp}
|
|
43
|
-
target="_blank"
|
|
44
|
-
rel="noopener noreferrer"
|
|
45
|
-
className="flex items-center gap-2 text-sm text-muted hover:text-body transition-colors"
|
|
46
|
-
>
|
|
47
|
-
<CircleHelp size={16} />
|
|
48
|
-
Community help
|
|
49
|
-
</a>
|
|
50
|
-
</li>
|
|
51
|
-
)}
|
|
52
|
-
</ul>
|
|
53
|
-
</div>
|
|
54
|
-
)}
|
|
55
|
-
</OTP.Root>
|
|
56
|
-
)
|
|
57
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { usePageNav } from '../../hooks/use-page-nav'
|
|
2
|
-
import { PageNav as PageNavPrimitive } from '../primitives/page-nav'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Component to display the previous and next page navigation buttons.
|
|
6
|
-
* Enhanced with subtle entrance animations, modern card layout, and hover highlights.
|
|
7
|
-
*/
|
|
8
|
-
export function PageNav() {
|
|
9
|
-
const { prevPage, nextPage } = usePageNav()
|
|
10
|
-
|
|
11
|
-
if (!prevPage && !nextPage) return null
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<PageNavPrimitive.Root className="pt-8 border-t border-subtle grid sm:grid-cols-2 gap-4 animate-in fade-in slide-in-from-bottom-4 duration-700 select-none">
|
|
15
|
-
{prevPage ? (
|
|
16
|
-
<PageNavPrimitive.Link
|
|
17
|
-
to={prevPage.path}
|
|
18
|
-
direction="prev"
|
|
19
|
-
className="group border border-subtle bg-surface p-5 rounded-2xl transition-all duration-300 hover:border-primary-500/50 hover:bg-primary-50/20"
|
|
20
|
-
>
|
|
21
|
-
<PageNavPrimitive.Title className="text-xs font-bold uppercase tracking-wider text-muted/60 mb-1">
|
|
22
|
-
Previous
|
|
23
|
-
</PageNavPrimitive.Title>
|
|
24
|
-
<PageNavPrimitive.Description className="text-sm sm:text-base font-bold text-body group-hover:text-primary-500 transition-colors">
|
|
25
|
-
{prevPage.title}
|
|
26
|
-
</PageNavPrimitive.Description>
|
|
27
|
-
</PageNavPrimitive.Link>
|
|
28
|
-
) : (
|
|
29
|
-
<div />
|
|
30
|
-
)}
|
|
31
|
-
|
|
32
|
-
{nextPage ? (
|
|
33
|
-
<PageNavPrimitive.Link
|
|
34
|
-
to={nextPage.path}
|
|
35
|
-
direction="next"
|
|
36
|
-
className="group border border-subtle bg-surface p-5 rounded-2xl transition-all duration-300 hover:border-primary-500/50 hover:bg-primary-50/20"
|
|
37
|
-
>
|
|
38
|
-
<PageNavPrimitive.Title className="text-xs font-bold uppercase tracking-wider text-muted/60 mb-1">
|
|
39
|
-
Next
|
|
40
|
-
</PageNavPrimitive.Title>
|
|
41
|
-
<PageNavPrimitive.Description className="text-sm sm:text-base font-bold text-body group-hover:text-primary-500 transition-colors">
|
|
42
|
-
{nextPage.title}
|
|
43
|
-
</PageNavPrimitive.Description>
|
|
44
|
-
</PageNavPrimitive.Link>
|
|
45
|
-
) : (
|
|
46
|
-
<div />
|
|
47
|
-
)}
|
|
48
|
-
</PageNavPrimitive.Root>
|
|
49
|
-
)
|
|
50
|
-
}
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { useEffect, useCallback } from 'react'
|
|
2
|
-
import { Search } from './icons'
|
|
3
|
-
import { useSearch } from '../../hooks/use-search'
|
|
4
|
-
import { SearchDialog as SearchDialogPrimitive } from '../primitives/search-dialog'
|
|
5
|
-
import Navbar from '../primitives/navbar'
|
|
6
|
-
import { useNavigate } from 'react-router-dom'
|
|
7
|
-
import type { ComponentRoute } from '../../types'
|
|
8
|
-
|
|
9
|
-
interface SearchResult {
|
|
10
|
-
id: string
|
|
11
|
-
title: string
|
|
12
|
-
path: string
|
|
13
|
-
bio: string
|
|
14
|
-
groupTitle?: string
|
|
15
|
-
isHeading?: boolean
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function Highlight({ text, query }: { text: string; query: string }) {
|
|
19
|
-
if (!query || !text) return <>{text}</>
|
|
20
|
-
const escapedQuery = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
21
|
-
const regex = new RegExp(`(${escapedQuery})`, 'gi')
|
|
22
|
-
const parts = text.split(regex)
|
|
23
|
-
return (
|
|
24
|
-
<>
|
|
25
|
-
{parts.map((part, i) =>
|
|
26
|
-
regex.test(part) ? (
|
|
27
|
-
<mark
|
|
28
|
-
key={i}
|
|
29
|
-
className="bg-primary-500/20 text-primary-600 dark:text-primary-400 font-bold px-0.5 rounded-sm"
|
|
30
|
-
>
|
|
31
|
-
{part}
|
|
32
|
-
</mark>
|
|
33
|
-
) : (
|
|
34
|
-
part
|
|
35
|
-
),
|
|
36
|
-
)}
|
|
37
|
-
</>
|
|
38
|
-
)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function SearchDialog({ routes }: { routes: ComponentRoute[] }) {
|
|
42
|
-
const { isOpen, setIsOpen, query, setQuery, list } = useSearch(routes)
|
|
43
|
-
const navigate = useNavigate()
|
|
44
|
-
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
const handleKeyDown = (e: KeyboardEvent) => {
|
|
47
|
-
const isMac = /Mac/.test(navigator.userAgent)
|
|
48
|
-
const isMeta = isMac ? e.metaKey : e.ctrlKey
|
|
49
|
-
|
|
50
|
-
if (isMeta && (e.key === 'k' || e.key === 'j')) {
|
|
51
|
-
e.preventDefault()
|
|
52
|
-
setIsOpen((prev) => !prev)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
window.addEventListener('keydown', handleKeyDown)
|
|
56
|
-
return () => window.removeEventListener('keydown', handleKeyDown)
|
|
57
|
-
}, [setIsOpen])
|
|
58
|
-
|
|
59
|
-
const handleSelect = useCallback(
|
|
60
|
-
(key: React.Key) => {
|
|
61
|
-
const path = String(key)
|
|
62
|
-
setIsOpen(false)
|
|
63
|
-
|
|
64
|
-
const [baseUrl, hash] = path.split('#')
|
|
65
|
-
const search = query ? `?hl=${encodeURIComponent(query)}` : ''
|
|
66
|
-
const finalPath = `${baseUrl}${search}${hash ? `#${hash}` : ''}`
|
|
67
|
-
|
|
68
|
-
navigate(finalPath)
|
|
69
|
-
|
|
70
|
-
if (hash) {
|
|
71
|
-
setTimeout(() => {
|
|
72
|
-
const el = document.getElementById(hash)
|
|
73
|
-
if (el) el.scrollIntoView({ behavior: 'smooth' })
|
|
74
|
-
}, 100)
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
[navigate, setIsOpen, query],
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
return (
|
|
81
|
-
<>
|
|
82
|
-
<Navbar.SearchTrigger.Desktop
|
|
83
|
-
onPress={() => setIsOpen(true)}
|
|
84
|
-
className="rounded-xl border border-subtle bg-surface text-muted transition-all duration-200 hover:border-primary-500/50 hover:text-body hover:bg-soft/50 hover:shadow-sm active:scale-[0.98] focus-visible:ring-2 focus-visible:ring-primary-500/30"
|
|
85
|
-
>
|
|
86
|
-
<div className="flex items-center gap-2">
|
|
87
|
-
<Search size={16} />
|
|
88
|
-
<span className="hidden sm:inline-block">Search docs...</span>
|
|
89
|
-
</div>
|
|
90
|
-
<Navbar.SearchTrigger.Kbd className="[&_kbd]:bg-main [&_kbd]:border [&_kbd]:border-subtle [&_kbd]:rounded [&_kbd]:px-1.5 [&_kbd]:h-5 [&_kbd]:w-5" />
|
|
91
|
-
</Navbar.SearchTrigger.Desktop>
|
|
92
|
-
|
|
93
|
-
<Navbar.SearchTrigger.Mobile
|
|
94
|
-
onPress={() => setIsOpen(true)}
|
|
95
|
-
className="rounded-xl text-muted transition-all duration-200 hover:text-body active:scale-95 focus-visible:ring-2 focus-visible:ring-primary-500/30"
|
|
96
|
-
>
|
|
97
|
-
<Search size={20} />
|
|
98
|
-
</Navbar.SearchTrigger.Mobile>
|
|
99
|
-
|
|
100
|
-
<SearchDialogPrimitive.Overlay
|
|
101
|
-
isOpen={isOpen}
|
|
102
|
-
isDismissable
|
|
103
|
-
onOpenChange={() => setIsOpen(false)}
|
|
104
|
-
className="fixed inset-0 z-100 flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs animate-fade-in"
|
|
105
|
-
>
|
|
106
|
-
<SearchDialogPrimitive.Content className="w-full max-w-lg bg-main border border-subtle shadow-md rounded-2xl overflow-hidden p-6">
|
|
107
|
-
<SearchDialogPrimitive.Dialog
|
|
108
|
-
aria-label="Search documentation"
|
|
109
|
-
className="flex flex-col min-h-0 h-[450px]"
|
|
110
|
-
>
|
|
111
|
-
<SearchDialogPrimitive.Autocomplete
|
|
112
|
-
onSelectionChange={handleSelect}
|
|
113
|
-
className="flex flex-col min-h-0"
|
|
114
|
-
>
|
|
115
|
-
<SearchDialogPrimitive.Input
|
|
116
|
-
value={query}
|
|
117
|
-
onChange={setQuery}
|
|
118
|
-
className="flex items-center gap-2 border border-subtle bg-surface px-4 py-2.5 rounded-xl focus-within:border-primary-500 mb-4"
|
|
119
|
-
>
|
|
120
|
-
<SearchDialogPrimitive.Input.SearchInput
|
|
121
|
-
placeholder="Search documentation..."
|
|
122
|
-
className="w-full bg-transparent outline-none text-body text-sm"
|
|
123
|
-
/>
|
|
124
|
-
{query && (
|
|
125
|
-
<SearchDialogPrimitive.Input.Button
|
|
126
|
-
onPress={() => setQuery('')}
|
|
127
|
-
className="text-muted hover:text-body text-xs cursor-pointer select-none"
|
|
128
|
-
>
|
|
129
|
-
✕
|
|
130
|
-
</SearchDialogPrimitive.Input.Button>
|
|
131
|
-
)}
|
|
132
|
-
</SearchDialogPrimitive.Input>
|
|
133
|
-
|
|
134
|
-
<SearchDialogPrimitive.List items={list as SearchResult[]}>
|
|
135
|
-
{(item: SearchResult) => (
|
|
136
|
-
<SearchDialogPrimitive.Item
|
|
137
|
-
key={item.id}
|
|
138
|
-
onPress={() => handleSelect(item.id)}
|
|
139
|
-
textValue={item.title}
|
|
140
|
-
className="flex items-center gap-3 px-4 py-2 rounded-xl group dark:hover:bg-primary-300/40 hover:bg-primary-200/50 transition-colors duration-100"
|
|
141
|
-
>
|
|
142
|
-
<SearchDialogPrimitive.Item.Icon
|
|
143
|
-
isHeading={item.isHeading}
|
|
144
|
-
className="text-muted group-hover:text-primary-500 group-focus:text-primary-500"
|
|
145
|
-
/>
|
|
146
|
-
<div className="flex flex-col justify-center min-w-0">
|
|
147
|
-
<SearchDialogPrimitive.Item.Title className="text-sm font-medium text-body truncate dark:group-hover:text-primary-100">
|
|
148
|
-
<Highlight text={item.title} query={query} />
|
|
149
|
-
</SearchDialogPrimitive.Item.Title>
|
|
150
|
-
<SearchDialogPrimitive.Item.Bio className="text-xs text-muted truncate">
|
|
151
|
-
<Highlight text={item.bio} query={query} />
|
|
152
|
-
</SearchDialogPrimitive.Item.Bio>
|
|
153
|
-
</div>
|
|
154
|
-
</SearchDialogPrimitive.Item>
|
|
155
|
-
)}
|
|
156
|
-
</SearchDialogPrimitive.List>
|
|
157
|
-
</SearchDialogPrimitive.Autocomplete>
|
|
158
|
-
</SearchDialogPrimitive.Dialog>
|
|
159
|
-
</SearchDialogPrimitive.Content>
|
|
160
|
-
</SearchDialogPrimitive.Overlay>
|
|
161
|
-
</>
|
|
162
|
-
)
|
|
163
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { useSearchHighlight } from '../../hooks/use-search-highlight'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Component that enables search term highlighting on the page.
|
|
5
|
-
* It doesn't render anything visible.
|
|
6
|
-
*/
|
|
7
|
-
export function SearchHighlight() {
|
|
8
|
-
useSearchHighlight('.boltdocs-page')
|
|
9
|
-
return null
|
|
10
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { Sidebar as SidebarPrimitive } from '../primitives/sidebar'
|
|
2
|
-
import { X } from './icons'
|
|
3
|
-
import type { ComponentRoute } from '../../types'
|
|
4
|
-
import type { BoltdocsConfig } from '../../../shared/types'
|
|
5
|
-
import { VersionSelector, I18nSelector } from './version-i18n'
|
|
6
|
-
import { ThemeSwitcher } from './theme-toggle'
|
|
7
|
-
import { useNavbar } from '../../hooks/use-navbar'
|
|
8
|
-
import { useUI } from '../../app/ui-context'
|
|
9
|
-
import { Button } from '../primitives/button'
|
|
10
|
-
|
|
11
|
-
interface SidebarProps {
|
|
12
|
-
routes: ComponentRoute[]
|
|
13
|
-
config: BoltdocsConfig
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function SidebarMain({ routes, config }: SidebarProps) {
|
|
17
|
-
const { logo, title, logoProps } = useNavbar()
|
|
18
|
-
const { closeSidebar } = useUI()
|
|
19
|
-
|
|
20
|
-
const SidebarLogo = logo ? (
|
|
21
|
-
<img
|
|
22
|
-
src={logo}
|
|
23
|
-
alt={logoProps?.alt || title}
|
|
24
|
-
width={24}
|
|
25
|
-
height={24}
|
|
26
|
-
className="rounded-xl"
|
|
27
|
-
/>
|
|
28
|
-
) : null
|
|
29
|
-
|
|
30
|
-
const hasUtilities = config.versions || config.i18n
|
|
31
|
-
|
|
32
|
-
return (
|
|
33
|
-
<>
|
|
34
|
-
{/* Desktop Version */}
|
|
35
|
-
<SidebarPrimitive.Root>
|
|
36
|
-
<SidebarPrimitive.Content>
|
|
37
|
-
<SidebarPrimitive.Items routes={routes} />
|
|
38
|
-
</SidebarPrimitive.Content>
|
|
39
|
-
</SidebarPrimitive.Root>
|
|
40
|
-
|
|
41
|
-
{/* Mobile Version */}
|
|
42
|
-
<SidebarPrimitive.Mobile>
|
|
43
|
-
<SidebarPrimitive.Header>
|
|
44
|
-
<div className="flex items-center gap-3">
|
|
45
|
-
{SidebarLogo}
|
|
46
|
-
<span className="font-bold text-lg tracking-tight text-body truncate max-w-[120px]">
|
|
47
|
-
{title}
|
|
48
|
-
</span>
|
|
49
|
-
</div>
|
|
50
|
-
<div className="flex items-center gap-2">
|
|
51
|
-
<ThemeSwitcher className="w-24 h-9 rounded-xl" />
|
|
52
|
-
<Button
|
|
53
|
-
onPress={closeSidebar}
|
|
54
|
-
className="h-9 w-9 flex items-center justify-center bg-transparent border-none outline-none select-none cursor-pointer rounded-xl hover:bg-primary-50/50 text-muted hover:text-body transition-colors"
|
|
55
|
-
aria-label="Close sidebar"
|
|
56
|
-
>
|
|
57
|
-
<X size={20} />
|
|
58
|
-
</Button>
|
|
59
|
-
</div>
|
|
60
|
-
</SidebarPrimitive.Header>
|
|
61
|
-
<SidebarPrimitive.Content>
|
|
62
|
-
{hasUtilities && (
|
|
63
|
-
<div className="flex flex-col gap-4 mb-10">
|
|
64
|
-
<div className="flex gap-3">
|
|
65
|
-
{config.versions && (
|
|
66
|
-
<VersionSelector className="flex-1 justify-between h-10 bg-surface border-subtle rounded-xl" />
|
|
67
|
-
)}
|
|
68
|
-
{config.i18n && (
|
|
69
|
-
<I18nSelector className="flex-1 justify-between h-10 bg-surface border-subtle rounded-xl" />
|
|
70
|
-
)}
|
|
71
|
-
</div>
|
|
72
|
-
<div className="mt-2 border-b border-subtle" />
|
|
73
|
-
</div>
|
|
74
|
-
)}
|
|
75
|
-
<SidebarPrimitive.Items routes={routes} />
|
|
76
|
-
</SidebarPrimitive.Content>
|
|
77
|
-
</SidebarPrimitive.Mobile>
|
|
78
|
-
</>
|
|
79
|
-
)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export const Sidebar = Object.assign(SidebarMain, {
|
|
83
|
-
Root: SidebarPrimitive.Root,
|
|
84
|
-
Mobile: SidebarPrimitive.Mobile,
|
|
85
|
-
Header: SidebarPrimitive.Header,
|
|
86
|
-
Content: SidebarPrimitive.Content,
|
|
87
|
-
Group: SidebarPrimitive.Group,
|
|
88
|
-
Link: SidebarPrimitive.Link,
|
|
89
|
-
SubGroup: SidebarPrimitive.SubGroup,
|
|
90
|
-
Item: SidebarPrimitive.Item,
|
|
91
|
-
Items: SidebarPrimitive.Items,
|
|
92
|
-
})
|