boltdocs 2.6.2 → 2.7.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/bin/boltdocs.js +0 -1
- package/dist/cache-CQKlT4fI.mjs +6 -0
- package/dist/cache-DorPMFgW.cjs +6 -0
- package/dist/cards-BLoSiRuL.d.ts +30 -0
- package/dist/cards-CQn9mXZS.d.cts +30 -0
- package/dist/chunk-Ds5LZdWN.cjs +6 -0
- package/dist/client/index.cjs +1 -1
- package/dist/client/index.d.cts +167 -1338
- package/dist/client/index.d.ts +166 -1337
- package/dist/client/index.js +1 -1
- package/dist/{package-CFP44vfn.cjs → client/mdx.cjs} +1 -1
- package/dist/client/mdx.d.cts +128 -0
- package/dist/client/mdx.d.ts +129 -0
- package/dist/client/mdx.js +6 -0
- package/dist/client/primitives.cjs +6 -0
- package/dist/client/primitives.d.cts +818 -0
- package/dist/client/primitives.d.ts +818 -0
- package/dist/client/primitives.js +6 -0
- package/dist/client/theme/neutral.css +74 -361
- package/dist/client/theme/reset.css +189 -0
- package/dist/docs-layout-BlDhcQRv.cjs +6 -0
- package/dist/docs-layout-BvAOWEJw.js +6 -0
- package/dist/doctor-BQiQhCTl.cjs +6 -0
- package/dist/doctor-COpf35L2.cjs +20 -0
- package/dist/doctor-Dh1XP7Pz.mjs +20 -0
- package/dist/generator-DGW6pkCC.cjs +22 -0
- package/dist/generator-Dv3wEmhZ.mjs +22 -0
- package/dist/icons-dev-CrQLjoQp.js +6 -0
- package/dist/icons-dev-rzdz6Lf3.cjs +6 -0
- package/dist/image-BkIfa9oo.js +6 -0
- package/dist/image-DIGjCPe6.cjs +6 -0
- package/dist/mdx-K0WYBAJ3.js +7 -0
- package/dist/mdx-hpErbRUe.cjs +7 -0
- package/dist/meta-loader-0gJ4PtBC.cjs +6 -0
- package/dist/meta-loader-9IpAHWDS.mjs +6 -0
- package/dist/node/cli-entry.cjs +1 -2
- package/dist/node/cli-entry.mjs +1 -2
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.d.cts +55 -11
- package/dist/node/index.d.mts +55 -12
- package/dist/node/index.mjs +1 -1
- package/dist/node/routes/worker.cjs +6 -0
- package/dist/node/routes/worker.d.cts +2 -0
- package/dist/node/routes/worker.d.mts +2 -0
- package/dist/node/routes/worker.mjs +6 -0
- package/dist/node-C2nWXElP.mjs +112 -0
- package/dist/node-CinkUtxV.cjs +112 -0
- package/dist/package-BMYLDBBP.cjs +6 -0
- package/dist/{package-Bqbn1AYK.mjs → package-HegMOTL_.mjs} +1 -1
- package/dist/parser-Bh11BsdA.cjs +6 -0
- package/dist/parser-D8eQvE7N.mjs +6 -0
- package/dist/parser-DYRzXWmA.cjs +6 -0
- package/dist/routes-CHf76Ye4.cjs +6 -0
- package/dist/routes-CMUZGI6T.mjs +6 -0
- package/dist/routes-Co1mRM58.cjs +6 -0
- package/dist/search-dialog-BACuzoVX.cjs +6 -0
- package/dist/search-dialog-BKagVT17.js +6 -0
- package/dist/search-dialog-C8w12eUx.js +6 -0
- package/dist/search-dialog-CGyrozZE.cjs +6 -0
- package/dist/search-dialog-D26rUnJ_.cjs +6 -0
- package/dist/sidebar-DKvg6KOc.d.cts +491 -0
- package/dist/sidebar-Dr1TiRIy.d.ts +491 -0
- package/dist/utils-BxNAXhZZ.mjs +7 -0
- package/dist/utils-Clzu7jvb.cjs +7 -0
- package/dist/worker-pool-Bd8Y9KDv.mjs +6 -0
- package/dist/worker-pool-BwU8ckrg.cjs +6 -0
- package/package.json +27 -8
- package/src/client/app/doc-page.tsx +9 -5
- package/src/client/app/docs-layout.tsx +17 -3
- package/src/client/app/head.tsx +122 -0
- package/src/client/app/helmet-compat.tsx +36 -0
- package/src/client/app/mdx-component.tsx +5 -52
- package/src/client/app/mdx-components-context.tsx +32 -8
- package/src/client/app/routes-context.tsx +2 -2
- package/src/client/app/scroll-handler.tsx +1 -1
- package/src/client/app/theme-context.tsx +5 -5
- package/src/client/app/ui-context.tsx +42 -0
- package/src/client/components/docs-layout-default.tsx +85 -0
- package/src/client/components/icons-dev.tsx +38 -15
- package/src/client/components/mdx/callout.tsx +97 -0
- package/src/client/components/mdx/card.tsx +73 -98
- package/src/client/components/mdx/cards.tsx +27 -0
- package/src/client/components/mdx/code-block.tsx +37 -17
- package/src/client/components/mdx/field.tsx +24 -56
- package/src/client/components/mdx/image.tsx +36 -15
- package/src/client/components/mdx/index.ts +19 -53
- package/src/client/components/mdx/table.tsx +46 -148
- package/src/client/components/mdx/typographics.tsx +120 -0
- package/src/client/components/mdx/{hooks/use-code-block.ts → use-code-block.ts} +5 -7
- package/src/client/components/primitives/breadcrumbs.tsx +5 -24
- package/src/client/components/primitives/button.tsx +3 -142
- package/src/client/components/primitives/code-block.tsx +104 -97
- package/src/client/components/{docs-layout.tsx → primitives/docs-layout.tsx} +15 -24
- package/src/client/components/primitives/error-boundary.tsx +107 -0
- package/src/client/components/primitives/heading.tsx +128 -0
- package/src/client/components/primitives/helpers/observer.ts +62 -32
- package/src/client/components/primitives/image.tsx +26 -0
- package/src/client/components/primitives/link.tsx +50 -52
- package/src/client/components/primitives/menu.tsx +25 -49
- package/src/client/components/primitives/navbar.tsx +234 -59
- package/src/client/components/primitives/on-this-page.tsx +169 -40
- package/src/client/components/primitives/page-nav.tsx +11 -39
- package/src/client/components/primitives/popover.tsx +12 -30
- package/src/client/components/primitives/search-dialog.tsx +77 -71
- package/src/client/components/primitives/sidebar.tsx +312 -119
- package/src/client/components/primitives/skeleton.tsx +1 -1
- package/src/client/components/primitives/tabs.tsx +5 -16
- package/src/client/components/primitives/tooltip.tsx +1 -1
- package/src/client/components/ui-base/banner.tsx +66 -0
- package/src/client/components/ui-base/breadcrumbs.tsx +26 -20
- package/src/client/components/ui-base/copy-markdown.tsx +43 -35
- package/src/client/components/ui-base/error-boundary.tsx +9 -46
- package/src/client/components/ui-base/github-stars.tsx +5 -3
- package/src/client/components/ui-base/index.ts +3 -3
- package/src/client/components/ui-base/last-updated.tsx +27 -0
- package/src/client/components/ui-base/navbar.tsx +183 -89
- package/src/client/components/ui-base/not-found.tsx +11 -9
- package/src/client/components/ui-base/on-this-page.tsx +8 -104
- package/src/client/components/ui-base/page-nav.tsx +23 -9
- package/src/client/components/ui-base/search-dialog.tsx +111 -36
- package/src/client/components/ui-base/search-highlight.tsx +10 -0
- package/src/client/components/ui-base/sidebar.tsx +77 -154
- package/src/client/components/ui-base/tabs.tsx +20 -7
- package/src/client/components/ui-base/theme-toggle.tsx +88 -10
- package/src/client/components/ui-base/version-i18n.tsx +80 -0
- package/src/client/hooks/index.ts +2 -1
- package/src/client/hooks/use-analytics.ts +272 -0
- package/src/client/hooks/use-i18n.ts +116 -50
- package/src/client/hooks/use-localized-to.ts +70 -27
- package/src/client/hooks/use-navbar.ts +69 -39
- package/src/client/hooks/use-page-nav.ts +28 -25
- package/src/client/hooks/use-routes.ts +63 -80
- package/src/client/hooks/use-search-highlight.ts +185 -0
- package/src/client/hooks/use-search.ts +12 -3
- package/src/client/hooks/use-sidebar.ts +183 -80
- package/src/client/hooks/use-tabs.ts +3 -4
- package/src/client/hooks/use-version.ts +44 -29
- package/src/client/index.ts +13 -87
- package/src/client/mdx.ts +2 -0
- package/src/client/primitives.ts +19 -0
- package/src/client/ssg/boltdocs-shell.tsx +68 -79
- package/src/client/ssg/create-routes.tsx +268 -72
- package/src/client/ssg/mdx-page.tsx +2 -1
- package/src/client/store/boltdocs-context.tsx +72 -20
- package/src/client/theme/neutral.css +74 -361
- package/src/client/theme/reset.css +189 -0
- package/src/client/types.ts +10 -2
- package/src/client/utils/path.ts +9 -0
- package/src/client/utils/react-to-text.ts +24 -24
- package/src/client/virtual.d.ts +1 -1
- package/src/shared/types.ts +82 -22
- package/dist/node-Bogvkxao.mjs +0 -101
- package/dist/node-CXaog6St.cjs +0 -101
- package/dist/search-dialog-CV3eJzMm.cjs +0 -6
- package/dist/search-dialog-DNTomKgu.js +0 -6
- package/dist/use-search-CS3gH19M.js +0 -6
- package/dist/use-search-DBpJZQuw.cjs +0 -6
- package/src/client/components/mdx/admonition.tsx +0 -91
- package/src/client/components/mdx/badge.tsx +0 -41
- package/src/client/components/mdx/button.tsx +0 -35
- package/src/client/components/mdx/component-preview.tsx +0 -37
- package/src/client/components/mdx/component-props.tsx +0 -83
- package/src/client/components/mdx/file-tree.tsx +0 -325
- package/src/client/components/mdx/hooks/use-component-preview.ts +0 -16
- package/src/client/components/mdx/hooks/useTable.ts +0 -74
- package/src/client/components/mdx/hooks/useTabs.ts +0 -68
- package/src/client/components/mdx/link.tsx +0 -38
- package/src/client/components/mdx/list.tsx +0 -192
- package/src/client/components/mdx/tabs.tsx +0 -135
- package/src/client/components/mdx/video.tsx +0 -68
- package/src/client/components/primitives/index.ts +0 -19
- package/src/client/components/primitives/navigation-menu.tsx +0 -114
- package/src/client/components/ui-base/head.tsx +0 -83
- package/src/client/components/ui-base/loading.tsx +0 -57
- package/src/client/components/ui-base/powered-by.tsx +0 -25
- package/src/client/hooks/use-onthispage.ts +0 -23
- package/src/client/utils/use-on-change.ts +0 -15
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
} from 'react'
|
|
12
12
|
import scrollIntoView from 'scroll-into-view-if-needed'
|
|
13
13
|
import { cn } from '../../utils/cn'
|
|
14
|
-
import { useOnChange } from '../../utils/use-on-change'
|
|
15
14
|
import type { ComponentBase } from './types'
|
|
16
15
|
import { getItemId, Observer } from './helpers/observer'
|
|
17
16
|
|
|
@@ -41,6 +40,10 @@ export interface AnchorProviderProps {
|
|
|
41
40
|
* @defaultValue false
|
|
42
41
|
*/
|
|
43
42
|
single?: boolean
|
|
43
|
+
/**
|
|
44
|
+
* Custom IntersectionObserver options
|
|
45
|
+
*/
|
|
46
|
+
observerOptions?: IntersectionObserverInit
|
|
44
47
|
children?: ReactNode
|
|
45
48
|
}
|
|
46
49
|
|
|
@@ -123,6 +126,7 @@ export function ScrollProvider({
|
|
|
123
126
|
export function AnchorProvider({
|
|
124
127
|
toc,
|
|
125
128
|
single = false,
|
|
129
|
+
observerOptions,
|
|
126
130
|
children,
|
|
127
131
|
}: AnchorProviderProps) {
|
|
128
132
|
const observer = useMemo(() => new Observer(), [])
|
|
@@ -136,10 +140,16 @@ export function AnchorProvider({
|
|
|
136
140
|
useEffect(() => {
|
|
137
141
|
// We use a rootMargin that acts as an activation "line" near the top.
|
|
138
142
|
// headings are "intersecting" (active=true) when they are BELOW this line.
|
|
139
|
-
|
|
140
|
-
|
|
143
|
+
// Default to a more permissive margin for detecting visible headings
|
|
144
|
+
const defaultOptions = {
|
|
145
|
+
rootMargin: '-80px 0% -60% 0%',
|
|
141
146
|
threshold: 0,
|
|
142
|
-
}
|
|
147
|
+
}
|
|
148
|
+
const options = observerOptions
|
|
149
|
+
? { ...defaultOptions, ...observerOptions }
|
|
150
|
+
: defaultOptions
|
|
151
|
+
|
|
152
|
+
observer.watch(options)
|
|
143
153
|
observer.onChange = () => setItems([...observer.items])
|
|
144
154
|
|
|
145
155
|
return () => {
|
|
@@ -156,7 +166,7 @@ export const OnThisPage = ({ children, className }: ComponentBase) => {
|
|
|
156
166
|
className={cn(
|
|
157
167
|
'sticky top-navbar hidden xl:flex flex-col shrink-0',
|
|
158
168
|
'w-toc',
|
|
159
|
-
'py-
|
|
169
|
+
'py-4 pl-6 pr-4',
|
|
160
170
|
className,
|
|
161
171
|
)}
|
|
162
172
|
>
|
|
@@ -168,10 +178,7 @@ export const OnThisPage = ({ children, className }: ComponentBase) => {
|
|
|
168
178
|
const OnThisPageHeader = ({ children, className, ...props }: ComponentBase) => {
|
|
169
179
|
return (
|
|
170
180
|
<div
|
|
171
|
-
className={cn(
|
|
172
|
-
'mb-4 text-xs font-bold text-text-main',
|
|
173
|
-
className,
|
|
174
|
-
)}
|
|
181
|
+
className={cn('mb-4 text-xs font-bold text-body', className)}
|
|
175
182
|
{...props}
|
|
176
183
|
>
|
|
177
184
|
{children}
|
|
@@ -192,7 +199,16 @@ const OnThisPageContent = ({
|
|
|
192
199
|
return (
|
|
193
200
|
<div
|
|
194
201
|
ref={internalRef}
|
|
195
|
-
className={cn(
|
|
202
|
+
className={cn(
|
|
203
|
+
'relative overflow-y-auto boltdocs-otp-content pb-12',
|
|
204
|
+
'max-h-[70%]',
|
|
205
|
+
className,
|
|
206
|
+
)}
|
|
207
|
+
style={{
|
|
208
|
+
maskImage: 'linear-gradient(to bottom, black 90%, transparent 100%)',
|
|
209
|
+
WebkitMaskImage:
|
|
210
|
+
'linear-gradient(to bottom, black 90%, transparent 100%)',
|
|
211
|
+
}}
|
|
196
212
|
{...props}
|
|
197
213
|
>
|
|
198
214
|
{children}
|
|
@@ -206,7 +222,7 @@ const OnThisPageList = ({ children, className }: ComponentBase) => {
|
|
|
206
222
|
return (
|
|
207
223
|
<ul
|
|
208
224
|
className={cn(
|
|
209
|
-
'relative space-y-
|
|
225
|
+
'relative space-y-0.5 text-sm border-l border-subtle',
|
|
210
226
|
className,
|
|
211
227
|
)}
|
|
212
228
|
>
|
|
@@ -234,41 +250,49 @@ const OnThisPageLink = ({
|
|
|
234
250
|
const containerRef = use(ScrollContext)
|
|
235
251
|
const id = href ? getItemId(href) : null
|
|
236
252
|
const anchorRef = useRef<HTMLAnchorElement>(null)
|
|
237
|
-
const [internalActive, setInternalActive] = useState(active)
|
|
238
|
-
|
|
239
|
-
useOnChange(
|
|
240
|
-
id && items ? items.find((i) => i.id === id)?.active : null,
|
|
241
|
-
(newActive) => {
|
|
242
|
-
if (newActive !== null && newActive !== internalActive) {
|
|
243
|
-
setInternalActive(!!newActive)
|
|
244
|
-
|
|
245
|
-
if (newActive && anchorRef.current && containerRef?.current) {
|
|
246
|
-
scrollIntoView(anchorRef.current, {
|
|
247
|
-
behavior: 'smooth',
|
|
248
|
-
block: 'center',
|
|
249
|
-
inline: 'center',
|
|
250
|
-
scrollMode: 'if-needed',
|
|
251
|
-
boundary: containerRef.current,
|
|
252
|
-
})
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
},
|
|
256
|
-
)
|
|
257
253
|
|
|
258
|
-
|
|
254
|
+
const computedActive =
|
|
255
|
+
active !== undefined
|
|
256
|
+
? active
|
|
257
|
+
: id && items
|
|
258
|
+
? !!items.find((i) => i.id === id)?.active
|
|
259
|
+
: false
|
|
260
|
+
|
|
259
261
|
useEffect(() => {
|
|
260
|
-
if (
|
|
261
|
-
|
|
262
|
+
if (computedActive && anchorRef.current && containerRef?.current) {
|
|
263
|
+
scrollIntoView(anchorRef.current, {
|
|
264
|
+
behavior: 'smooth',
|
|
265
|
+
block: 'center',
|
|
266
|
+
inline: 'center',
|
|
267
|
+
scrollMode: 'if-needed',
|
|
268
|
+
boundary: containerRef.current,
|
|
269
|
+
})
|
|
270
|
+
}
|
|
271
|
+
}, [computedActive, containerRef])
|
|
272
|
+
|
|
273
|
+
const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
|
|
274
|
+
if (onClick) {
|
|
275
|
+
onClick(e)
|
|
276
|
+
} else if (href && href.startsWith('#')) {
|
|
277
|
+
e.preventDefault()
|
|
278
|
+
const elementId = href.slice(1)
|
|
279
|
+
const el = document.getElementById(elementId)
|
|
280
|
+
if (el) {
|
|
281
|
+
el.scrollIntoView({ behavior: 'smooth' })
|
|
282
|
+
window.history.pushState(null, '', href)
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
262
286
|
|
|
263
287
|
return (
|
|
264
288
|
<a
|
|
265
289
|
ref={anchorRef}
|
|
266
290
|
href={href}
|
|
267
|
-
onClick={
|
|
268
|
-
data-active={
|
|
291
|
+
onClick={handleClick}
|
|
292
|
+
data-active={computedActive}
|
|
269
293
|
className={cn(
|
|
270
|
-
'block py-
|
|
271
|
-
|
|
294
|
+
'block py-0.5 pl-4 text-[13px] outline-none transition-colors',
|
|
295
|
+
computedActive ? 'text-primary-500' : 'text-muted hover:text-body',
|
|
272
296
|
className,
|
|
273
297
|
)}
|
|
274
298
|
>
|
|
@@ -281,17 +305,118 @@ const OnThisPageIndicator = ({
|
|
|
281
305
|
style,
|
|
282
306
|
className,
|
|
283
307
|
}: OnThisPageIndicatorProps) => {
|
|
308
|
+
const containerRef = useRef<HTMLDivElement>(null)
|
|
309
|
+
const [internalStyle, setInternalStyle] = useState<React.CSSProperties>({
|
|
310
|
+
opacity: 0,
|
|
311
|
+
...style,
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
const items = useItems()
|
|
315
|
+
|
|
316
|
+
useEffect(() => {
|
|
317
|
+
const parent = containerRef.current?.parentElement
|
|
318
|
+
if (!parent) return
|
|
319
|
+
|
|
320
|
+
const activeLinks = parent.querySelectorAll('a[data-active="true"]')
|
|
321
|
+
|
|
322
|
+
if (activeLinks.length > 0) {
|
|
323
|
+
const firstActiveLink = activeLinks[0] as HTMLElement
|
|
324
|
+
const lastActiveLink = activeLinks[activeLinks.length - 1] as HTMLElement
|
|
325
|
+
|
|
326
|
+
const firstRect = firstActiveLink.getBoundingClientRect()
|
|
327
|
+
const lastRect = lastActiveLink.getBoundingClientRect()
|
|
328
|
+
const parentRect = parent.getBoundingClientRect()
|
|
329
|
+
|
|
330
|
+
const offsetTop = firstRect.top - parentRect.top
|
|
331
|
+
const height = lastRect.bottom - firstRect.top
|
|
332
|
+
|
|
333
|
+
setInternalStyle({
|
|
334
|
+
transform: `translateY(${offsetTop}px)`,
|
|
335
|
+
height: `${height}px`,
|
|
336
|
+
opacity: 1,
|
|
337
|
+
...style,
|
|
338
|
+
})
|
|
339
|
+
} else {
|
|
340
|
+
setInternalStyle({
|
|
341
|
+
opacity: 0,
|
|
342
|
+
...style,
|
|
343
|
+
})
|
|
344
|
+
}
|
|
345
|
+
}, [items, style])
|
|
346
|
+
|
|
284
347
|
return (
|
|
285
348
|
<div
|
|
349
|
+
ref={containerRef}
|
|
286
350
|
className={cn(
|
|
287
|
-
'absolute -left-px w-0.5 rounded-full bg-primary-500
|
|
351
|
+
'absolute -left-px w-0.5 rounded-full bg-primary-500',
|
|
288
352
|
className,
|
|
289
353
|
)}
|
|
290
|
-
style={
|
|
354
|
+
style={{
|
|
355
|
+
transition:
|
|
356
|
+
'transform 180ms cubic-bezier(0.2, 0.8, 0.2, 1), height 180ms cubic-bezier(0.2, 0.8, 0.2, 1), opacity 150ms',
|
|
357
|
+
...internalStyle,
|
|
358
|
+
}}
|
|
291
359
|
/>
|
|
292
360
|
)
|
|
293
361
|
}
|
|
294
362
|
|
|
363
|
+
/**
|
|
364
|
+
* High-level automated list of toc items
|
|
365
|
+
*/
|
|
366
|
+
export function OnThisPageItems({
|
|
367
|
+
headings = [],
|
|
368
|
+
className,
|
|
369
|
+
}: {
|
|
370
|
+
headings: { level: number; text: string; id: string }[]
|
|
371
|
+
} & ComponentBase) {
|
|
372
|
+
const activeIds = useActiveAnchors()
|
|
373
|
+
|
|
374
|
+
if (headings.length === 0) return null
|
|
375
|
+
|
|
376
|
+
return (
|
|
377
|
+
<OnThisPageList className={className}>
|
|
378
|
+
<OnThisPageIndicator />
|
|
379
|
+
{headings.map((h) => (
|
|
380
|
+
<OnThisPageItem key={h.id} level={h.level}>
|
|
381
|
+
<OnThisPageLink href={`#${h.id}`} active={activeIds.includes(h.id)}>
|
|
382
|
+
{h.text}
|
|
383
|
+
</OnThisPageLink>
|
|
384
|
+
</OnThisPageItem>
|
|
385
|
+
))}
|
|
386
|
+
</OnThisPageList>
|
|
387
|
+
)
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* High-level automated Table of Contents tree
|
|
392
|
+
*/
|
|
393
|
+
export function OnThisPageTree({
|
|
394
|
+
headings = [],
|
|
395
|
+
className,
|
|
396
|
+
}: {
|
|
397
|
+
headings: { level: number; text: string; id: string }[]
|
|
398
|
+
} & ComponentBase) {
|
|
399
|
+
const toc = useMemo(
|
|
400
|
+
() =>
|
|
401
|
+
headings.map((h) => ({ title: h.text, url: `#${h.id}`, depth: h.level })),
|
|
402
|
+
[headings],
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
const scrollContainerRef = useRef<HTMLDivElement>(null)
|
|
406
|
+
|
|
407
|
+
if (headings.length === 0) return null
|
|
408
|
+
|
|
409
|
+
return (
|
|
410
|
+
<AnchorProvider toc={toc} single={false}>
|
|
411
|
+
<ScrollProvider containerRef={scrollContainerRef}>
|
|
412
|
+
<OnThisPageContent ref={scrollContainerRef}>
|
|
413
|
+
<OnThisPageItems headings={headings} className={className} />
|
|
414
|
+
</OnThisPageContent>
|
|
415
|
+
</ScrollProvider>
|
|
416
|
+
</AnchorProvider>
|
|
417
|
+
)
|
|
418
|
+
}
|
|
419
|
+
|
|
295
420
|
OnThisPage.Root = OnThisPage
|
|
296
421
|
OnThisPage.Header = OnThisPageHeader
|
|
297
422
|
OnThisPage.Content = OnThisPageContent
|
|
@@ -299,3 +424,7 @@ OnThisPage.List = OnThisPageList
|
|
|
299
424
|
OnThisPage.Item = OnThisPageItem
|
|
300
425
|
OnThisPage.Link = OnThisPageLink
|
|
301
426
|
OnThisPage.Indicator = OnThisPageIndicator
|
|
427
|
+
OnThisPage.Items = OnThisPageItems
|
|
428
|
+
OnThisPage.Tree = OnThisPageTree
|
|
429
|
+
|
|
430
|
+
export default OnThisPage
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Link } from './link'
|
|
2
2
|
import { ChevronLeft, ChevronRight } from 'lucide-react'
|
|
3
3
|
import { cn } from '../../utils/cn'
|
|
4
4
|
import type { ComponentBase } from './types'
|
|
@@ -10,62 +10,34 @@ export interface PageNavProps extends ComponentBase {
|
|
|
10
10
|
|
|
11
11
|
export const PageNav = ({ children, className }: ComponentBase) => {
|
|
12
12
|
return (
|
|
13
|
-
<nav
|
|
14
|
-
className={cn(
|
|
15
|
-
'grid grid-cols-1 sm:grid-cols-2 gap-4 mt-12 pt-8 border-t border-border-subtle',
|
|
16
|
-
className,
|
|
17
|
-
)}
|
|
18
|
-
>
|
|
19
|
-
{children}
|
|
20
|
-
</nav>
|
|
13
|
+
<nav className={cn('grid sm:grid-cols-2 gap-4', className)}>{children}</nav>
|
|
21
14
|
)
|
|
22
15
|
}
|
|
23
16
|
|
|
24
17
|
const PageNavLink = ({ children, to, direction, className }: PageNavProps) => {
|
|
25
18
|
const isNext = direction === 'next'
|
|
26
19
|
return (
|
|
27
|
-
<
|
|
20
|
+
<Link
|
|
28
21
|
href={to}
|
|
29
22
|
className={cn(
|
|
30
|
-
'flex
|
|
31
|
-
'
|
|
32
|
-
'focus-visible:ring-2 focus-visible:ring-primary-500/30',
|
|
33
|
-
isNext ? 'text-right justify-end' : 'text-left justify-start',
|
|
23
|
+
'flex items-center outline-none no-underline',
|
|
24
|
+
isNext ? 'justify-end' : 'justify-start',
|
|
34
25
|
className,
|
|
35
26
|
)}
|
|
36
27
|
>
|
|
37
|
-
{!isNext &&
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
{isNext && (
|
|
42
|
-
<ChevronRight className="ml-3 h-5 w-5 text-text-muted group-hover:text-primary-500 transition-transform group-hover:translate-x-1" />
|
|
43
|
-
)}
|
|
44
|
-
</RAC.Link>
|
|
28
|
+
{!isNext && <ChevronLeft className="shrink-0" />}
|
|
29
|
+
<div className="flex flex-col flex-1">{children}</div>
|
|
30
|
+
{isNext && <ChevronRight className="shrink-0" />}
|
|
31
|
+
</Link>
|
|
45
32
|
)
|
|
46
33
|
}
|
|
47
34
|
|
|
48
35
|
const PageNavTitle = ({ children, className }: ComponentBase) => {
|
|
49
|
-
return (
|
|
50
|
-
<span
|
|
51
|
-
className={cn(
|
|
52
|
-
'text-xs font-medium uppercase text-text-muted',
|
|
53
|
-
className,
|
|
54
|
-
)}
|
|
55
|
-
>
|
|
56
|
-
{children}
|
|
57
|
-
</span>
|
|
58
|
-
)
|
|
36
|
+
return <span className={cn(className)}>{children}</span>
|
|
59
37
|
}
|
|
60
38
|
|
|
61
39
|
const PageNavDescription = ({ children, className }: ComponentBase) => {
|
|
62
|
-
return (
|
|
63
|
-
<span
|
|
64
|
-
className={cn('text-base font-bold text-text-main truncate', className)}
|
|
65
|
-
>
|
|
66
|
-
{children}
|
|
67
|
-
</span>
|
|
68
|
-
)
|
|
40
|
+
return <span className={cn('truncate', className)}>{children}</span>
|
|
69
41
|
}
|
|
70
42
|
|
|
71
43
|
const PageNavIcon = ({ children }: ComponentBase) => {
|
|
@@ -1,46 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
Popover as RACPopover,
|
|
3
|
+
type PopoverProps as RACPopoverProps,
|
|
4
|
+
} from 'react-aria-components'
|
|
4
5
|
import { cn } from '../../utils/cn'
|
|
5
6
|
|
|
6
|
-
export interface PopoverProps extends Omit<
|
|
7
|
+
export interface PopoverProps extends Omit<RACPopoverProps, 'children'> {
|
|
7
8
|
children: React.ReactNode
|
|
8
9
|
className?: string
|
|
9
|
-
showArrow?: boolean
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* A reusable Popover primitive with premium glassmorphism styling and smooth animations.
|
|
14
14
|
*/
|
|
15
|
-
export const Popover = ({
|
|
16
|
-
children,
|
|
17
|
-
className,
|
|
18
|
-
showArrow,
|
|
19
|
-
...props
|
|
20
|
-
}: PopoverProps) => {
|
|
15
|
+
export const Popover = ({ children, className, ...props }: PopoverProps) => {
|
|
21
16
|
return (
|
|
22
|
-
<
|
|
17
|
+
<RACPopover
|
|
23
18
|
offset={8}
|
|
24
|
-
{
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
'z-50 overflow-auto rounded-xl border border-border-subtle bg-bg-surface/80 shadow-xl backdrop-blur-md outline-none transition-none',
|
|
28
|
-
className,
|
|
29
|
-
),
|
|
19
|
+
className={cn(
|
|
20
|
+
'z-50 overflow-auto outline-none transition-none',
|
|
21
|
+
className,
|
|
30
22
|
)}
|
|
23
|
+
{...props}
|
|
31
24
|
>
|
|
32
|
-
{showArrow && (
|
|
33
|
-
<RAC.OverlayArrow className="group">
|
|
34
|
-
<svg
|
|
35
|
-
viewBox="0 0 12 12"
|
|
36
|
-
className="block h-3 w-3 fill-bg-surface/80 stroke-border-subtle group-placement-bottom:rotate-180 group-placement-left:-rotate-90 group-placement-right:rotate-90"
|
|
37
|
-
aria-hidden="true"
|
|
38
|
-
>
|
|
39
|
-
<path d="M0 0 L6 6 L12 0" />
|
|
40
|
-
</svg>
|
|
41
|
-
</RAC.OverlayArrow>
|
|
42
|
-
)}
|
|
43
25
|
{children as any}
|
|
44
|
-
</
|
|
26
|
+
</RACPopover>
|
|
45
27
|
)
|
|
46
28
|
}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
1
3
|
import * as RAC from 'react-aria-components'
|
|
2
|
-
import {
|
|
4
|
+
import { Hash, FileText, CornerDownLeft } from 'lucide-react'
|
|
3
5
|
import { cn } from '../../utils/cn'
|
|
4
6
|
import type { ComponentBase } from './types'
|
|
5
7
|
|
|
6
|
-
export interface SearchDialogProps extends ComponentBase {
|
|
7
|
-
isOpen?: boolean
|
|
8
|
-
onOpenChange?: (isOpen: boolean) => void
|
|
9
|
-
}
|
|
10
|
-
|
|
11
8
|
export interface SearchDialogItemProps
|
|
12
9
|
extends Omit<RAC.ListBoxItemProps, 'children'> {
|
|
13
10
|
className?: string
|
|
@@ -19,37 +16,66 @@ export interface SearchDialogItemIconProps {
|
|
|
19
16
|
className?: string
|
|
20
17
|
}
|
|
21
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Pure, unstyled SearchDialog Overlay (maps to RAC.ModalOverlay)
|
|
21
|
+
*/
|
|
22
22
|
export const SearchDialog = ({
|
|
23
|
-
children,
|
|
24
|
-
isOpen,
|
|
25
|
-
onOpenChange,
|
|
26
23
|
className,
|
|
27
|
-
|
|
24
|
+
...props
|
|
25
|
+
}: RAC.ModalOverlayProps) => {
|
|
28
26
|
return (
|
|
29
27
|
<RAC.ModalOverlay
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
className={cn(
|
|
34
|
-
'fixed inset-0 z-100 bg-black/40 backdrop-blur-sm px-4 py-4 sm:py-20',
|
|
35
|
-
'entering:animate-in entering:fade-in exiting:animate-out exiting:fade-out',
|
|
36
|
-
)}
|
|
37
|
-
>
|
|
38
|
-
<RAC.Modal
|
|
39
|
-
className={cn(
|
|
40
|
-
'mx-auto w-full max-w-2xl overflow-hidden rounded-xl border border-border-subtle bg-bg-surface shadow-2xl ring-1 ring-black/5 outline-none',
|
|
41
|
-
'entering:animate-in entering:fade-in entering:zoom-in-95 exiting:animate-out exiting:fade-out exiting:zoom-out-95',
|
|
42
|
-
className,
|
|
43
|
-
)}
|
|
44
|
-
>
|
|
45
|
-
<RAC.Dialog className="flex flex-col max-h-[70vh] focus:outline-none">
|
|
46
|
-
{children as any}
|
|
47
|
-
</RAC.Dialog>
|
|
48
|
-
</RAC.Modal>
|
|
49
|
-
</RAC.ModalOverlay>
|
|
28
|
+
className={cn('fixed inset-0 z-100', className)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
50
31
|
)
|
|
51
32
|
}
|
|
52
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Pure, unstyled SearchDialog Content (maps to RAC.Modal)
|
|
36
|
+
*/
|
|
37
|
+
const SearchDialogContent = ({
|
|
38
|
+
className,
|
|
39
|
+
...props
|
|
40
|
+
}: RAC.ModalOverlayProps) => <RAC.Modal className={cn(className)} {...props} />
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Pure, unstyled SearchDialog Dialog (maps to RAC.Dialog)
|
|
44
|
+
*/
|
|
45
|
+
const SearchDialogDialog = ({ className, ...props }: RAC.DialogProps) => (
|
|
46
|
+
<RAC.Dialog
|
|
47
|
+
className={cn('flex flex-col focus:outline-none', className)}
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Pure, unstyled SearchDialog Input Field (maps to RAC.SearchField)
|
|
54
|
+
*/
|
|
55
|
+
const SearchDialogField = ({ className, ...props }: RAC.SearchFieldProps) => (
|
|
56
|
+
<RAC.SearchField className={cn('flex items-center', className)} {...props} />
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Pure, unstyled SearchInput (maps to RAC.Input)
|
|
61
|
+
*/
|
|
62
|
+
const SearchDialogSearchInput = ({ className, ...props }: RAC.InputProps) => (
|
|
63
|
+
<RAC.Input
|
|
64
|
+
className={cn('w-full bg-transparent outline-none border-none', className)}
|
|
65
|
+
{...props}
|
|
66
|
+
/>
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Pure, unstyled Clear Button (maps to RAC.Button with slot="clear")
|
|
71
|
+
*/
|
|
72
|
+
const SearchDialogClearButton = ({ className, ...props }: RAC.ButtonProps) => (
|
|
73
|
+
<RAC.Button slot="clear" className={cn(className)} {...props} />
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Pure, unstyled Autocomplete container (maps to RAC.Autocomplete)
|
|
78
|
+
*/
|
|
53
79
|
const SearchDialogAutocomplete = <T extends object>({
|
|
54
80
|
children,
|
|
55
81
|
className,
|
|
@@ -61,7 +87,7 @@ const SearchDialogAutocomplete = <T extends object>({
|
|
|
61
87
|
}) => {
|
|
62
88
|
const Autocomplete = RAC.Autocomplete as any
|
|
63
89
|
return (
|
|
64
|
-
<div className={className}>
|
|
90
|
+
<div className={cn('flex-1 min-h-0', className)}>
|
|
65
91
|
<Autocomplete
|
|
66
92
|
{...props}
|
|
67
93
|
onSelectionChange={onSelectionChange}
|
|
@@ -73,31 +99,9 @@ const SearchDialogAutocomplete = <T extends object>({
|
|
|
73
99
|
)
|
|
74
100
|
}
|
|
75
101
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}: RAC.InputProps & { className?: string }) => {
|
|
80
|
-
return (
|
|
81
|
-
<RAC.SearchField
|
|
82
|
-
className="flex items-center gap-3 border-b border-border-subtle px-4 py-4"
|
|
83
|
-
autoFocus
|
|
84
|
-
>
|
|
85
|
-
<Search className="h-5 w-5 text-text-muted" />
|
|
86
|
-
<RAC.Input
|
|
87
|
-
{...props}
|
|
88
|
-
className={cn(
|
|
89
|
-
'w-full bg-transparent text-lg text-text-main placeholder-text-muted outline-none',
|
|
90
|
-
className,
|
|
91
|
-
)}
|
|
92
|
-
placeholder="Search documentation..."
|
|
93
|
-
/>
|
|
94
|
-
<div className="flex items-center gap-1.5 rounded-md border border-border-subtle bg-bg-main px-1.5 py-1 text-[10px] font-medium text-text-muted">
|
|
95
|
-
<kbd className="font-sans">ESC</kbd>
|
|
96
|
-
</div>
|
|
97
|
-
</RAC.SearchField>
|
|
98
|
-
)
|
|
99
|
-
}
|
|
100
|
-
|
|
102
|
+
/**
|
|
103
|
+
* Pure, unstyled List Box (maps to RAC.ListBox)
|
|
104
|
+
*/
|
|
101
105
|
const SearchDialogList = <T extends object>({
|
|
102
106
|
children,
|
|
103
107
|
className,
|
|
@@ -106,13 +110,16 @@ const SearchDialogList = <T extends object>({
|
|
|
106
110
|
return (
|
|
107
111
|
<RAC.ListBox
|
|
108
112
|
{...props}
|
|
109
|
-
className={cn('flex-1 overflow-y-auto
|
|
113
|
+
className={cn('flex-1 overflow-y-auto outline-none min-h-0', className)}
|
|
110
114
|
>
|
|
111
115
|
{children as any}
|
|
112
116
|
</RAC.ListBox>
|
|
113
117
|
)
|
|
114
118
|
}
|
|
115
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Pure, unstyled List Box Item (maps to RAC.ListBoxItem)
|
|
122
|
+
*/
|
|
116
123
|
const SearchDialogItemRoot = ({
|
|
117
124
|
children,
|
|
118
125
|
className,
|
|
@@ -122,8 +129,7 @@ const SearchDialogItemRoot = ({
|
|
|
122
129
|
<RAC.ListBoxItem
|
|
123
130
|
{...props}
|
|
124
131
|
className={cn(
|
|
125
|
-
'group flex items-center
|
|
126
|
-
'text-text-muted hover:bg-bg-main hover:text-text-main focus:bg-primary-500 focus:text-white selected:bg-primary-500 selected:text-white',
|
|
132
|
+
'group flex items-center outline-none cursor-pointer',
|
|
127
133
|
className,
|
|
128
134
|
)}
|
|
129
135
|
>
|
|
@@ -155,31 +161,31 @@ const SearchDialogItemIcon = ({
|
|
|
155
161
|
|
|
156
162
|
const SearchDialogItemTitle = ({ children, className }: ComponentBase) => {
|
|
157
163
|
return (
|
|
158
|
-
<span
|
|
159
|
-
className={cn('block font-medium truncate flex-1 text-sm', className)}
|
|
160
|
-
>
|
|
161
|
-
{children}
|
|
162
|
-
</span>
|
|
164
|
+
<span className={cn('block truncate flex-1', className)}>{children}</span>
|
|
163
165
|
)
|
|
164
166
|
}
|
|
165
167
|
|
|
166
168
|
const SearchDialogItemBio = ({ children, className }: ComponentBase) => {
|
|
167
169
|
return (
|
|
168
|
-
<span
|
|
169
|
-
className={cn(
|
|
170
|
-
'ml-2 text-xs opacity-70 truncate hidden sm:inline group-focus:opacity-100',
|
|
171
|
-
className,
|
|
172
|
-
)}
|
|
173
|
-
>
|
|
170
|
+
<span className={cn('ml-2 truncate hidden sm:inline', className)}>
|
|
174
171
|
{children}
|
|
175
172
|
</span>
|
|
176
173
|
)
|
|
177
174
|
}
|
|
178
175
|
|
|
176
|
+
// Compound API wiring
|
|
179
177
|
SearchDialog.Root = SearchDialog
|
|
178
|
+
SearchDialog.Overlay = SearchDialog
|
|
179
|
+
SearchDialog.Content = SearchDialogContent
|
|
180
|
+
SearchDialog.Dialog = SearchDialogDialog
|
|
180
181
|
SearchDialog.Autocomplete = SearchDialogAutocomplete
|
|
181
|
-
SearchDialog.Input = SearchDialogInput
|
|
182
182
|
SearchDialog.List = SearchDialogList
|
|
183
|
+
|
|
184
|
+
SearchDialog.Input = Object.assign(SearchDialogField, {
|
|
185
|
+
SearchInput: SearchDialogSearchInput,
|
|
186
|
+
Button: SearchDialogClearButton,
|
|
187
|
+
})
|
|
188
|
+
|
|
183
189
|
SearchDialog.Item = Object.assign(SearchDialogItemRoot, {
|
|
184
190
|
Icon: SearchDialogItemIcon,
|
|
185
191
|
Title: SearchDialogItemTitle,
|