boltdocs 2.5.6 → 2.6.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 +2 -2
- package/dist/client/index.cjs +6 -0
- package/dist/client/{index.d.mts → index.d.cts} +134 -252
- package/dist/client/index.d.ts +135 -253
- 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 +150 -205
- package/dist/node/index.d.mts +150 -205
- package/dist/node/index.mjs +1 -1
- package/dist/node-BgvNl2Ay.mjs +89 -0
- package/dist/node-vkbb0MK7.cjs +89 -0
- package/dist/{package-OFZf0s2j.mjs → package-CR0HF9x3.mjs} +1 -1
- package/dist/{package-BY8Jd2j4.cjs → package-Dgmsc_l5.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 +19 -22
- 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/default-layout.tsx +13 -14
- 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 +22 -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/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/integrations/codesandbox.ts +0 -179
- package/src/client/integrations/index.ts +0 -1
- package/src/client/ssr.tsx +0 -65
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
Button as ButtonPrimitive,
|
|
3
3
|
buttonVariants,
|
|
4
4
|
type ButtonProps,
|
|
5
|
-
} from '
|
|
6
|
-
import { cn } from '
|
|
5
|
+
} from '../primitives/button'
|
|
6
|
+
import { cn } from '../../utils/cn'
|
|
7
7
|
|
|
8
|
-
export type { ButtonProps } from '
|
|
8
|
+
export type { ButtonProps } from '../primitives/button'
|
|
9
9
|
|
|
10
10
|
export const Button = ({
|
|
11
11
|
className,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MouseEvent as ReactMouseEvent } from 'react'
|
|
2
2
|
import { useCallback, useRef } from 'react'
|
|
3
3
|
import * as RAC from 'react-aria-components'
|
|
4
|
-
import { cn } from '
|
|
4
|
+
import { cn } from '../../utils/cn'
|
|
5
5
|
import { cva } from 'class-variance-authority'
|
|
6
6
|
import type { VariantProps } from 'class-variance-authority'
|
|
7
7
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Button } from 'react-aria-components'
|
|
2
2
|
import { Copy, Check, File } from 'lucide-react'
|
|
3
|
-
import { cn } from '
|
|
3
|
+
import { cn } from '../../utils/cn'
|
|
4
|
+
import { reactToText } from '../../utils/react-to-text'
|
|
4
5
|
import { useCodeBlock } from './hooks/use-code-block'
|
|
5
|
-
import
|
|
6
|
+
import * as CodePrimitive from '../primitives/code-block'
|
|
6
7
|
import {
|
|
7
8
|
TypeScript,
|
|
8
9
|
JavaScript,
|
|
@@ -13,8 +14,10 @@ import {
|
|
|
13
14
|
Markdown,
|
|
14
15
|
Shell,
|
|
15
16
|
Yaml,
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
Rust,
|
|
18
|
+
BracketsRed,
|
|
19
|
+
} from '../icons-dev'
|
|
20
|
+
import { Tooltip } from '../primitives/tooltip'
|
|
18
21
|
|
|
19
22
|
const langIconMap: Record<string, React.ComponentType<{ size?: number }>> = {
|
|
20
23
|
ts: TypeScript,
|
|
@@ -30,6 +33,9 @@ const langIconMap: Record<string, React.ComponentType<{ size?: number }>> = {
|
|
|
30
33
|
sh: Shell,
|
|
31
34
|
yaml: Yaml,
|
|
32
35
|
yml: Yaml,
|
|
36
|
+
rs: Rust,
|
|
37
|
+
rust: Rust,
|
|
38
|
+
toml: BracketsRed
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
export interface CodeBlockProps {
|
|
@@ -40,10 +46,32 @@ export interface CodeBlockProps {
|
|
|
40
46
|
lang?: string
|
|
41
47
|
highlightedHtml?: string
|
|
42
48
|
'data-lang'?: string
|
|
49
|
+
'data-title'?: string
|
|
43
50
|
plain?: boolean
|
|
44
51
|
[key: string]: any
|
|
45
52
|
}
|
|
46
53
|
|
|
54
|
+
const CopyButton = ({ copied, handleCopy }: { copied: boolean; handleCopy: () => void }) => {
|
|
55
|
+
return (
|
|
56
|
+
<Tooltip content={copied ? 'Copied!' : 'Copy code'}>
|
|
57
|
+
{/* @ts-ignore */}
|
|
58
|
+
<Button
|
|
59
|
+
onPress={handleCopy}
|
|
60
|
+
className={cn(
|
|
61
|
+
'grid place-items-center size-8 bg-transparent outline-none cursor-pointer transition-all duration-200 hover:scale-110 active:scale-95 [&>svg]:size-4 [&>svg]:stroke-2',
|
|
62
|
+
copied
|
|
63
|
+
? 'text-emerald-400'
|
|
64
|
+
: 'text-text-muted hover:text-text-main',
|
|
65
|
+
)}
|
|
66
|
+
aria-label="Copy code"
|
|
67
|
+
>
|
|
68
|
+
{/* @ts-ignore */}
|
|
69
|
+
{copied ? <Check size={20} /> : <Copy size={20} />}
|
|
70
|
+
</Button>
|
|
71
|
+
</Tooltip>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
47
75
|
export function CodeBlock(props: CodeBlockProps) {
|
|
48
76
|
const {
|
|
49
77
|
children,
|
|
@@ -51,13 +79,16 @@ export function CodeBlock(props: CodeBlockProps) {
|
|
|
51
79
|
highlightedHtml,
|
|
52
80
|
'data-highlighted-html': dataHighlightedHtml,
|
|
53
81
|
title,
|
|
82
|
+
'data-title': dataTitle,
|
|
54
83
|
'data-lang': dataLang,
|
|
55
84
|
plain = false,
|
|
56
85
|
...rest
|
|
57
86
|
} = props
|
|
87
|
+
|
|
58
88
|
const effectiveHighlightedHtml = highlightedHtml || dataHighlightedHtml
|
|
59
|
-
const
|
|
89
|
+
const effectiveTitle = title || dataTitle
|
|
60
90
|
const lang = props.lang || dataLang || ''
|
|
91
|
+
|
|
61
92
|
const {
|
|
62
93
|
copied,
|
|
63
94
|
isExpanded,
|
|
@@ -71,84 +102,63 @@ export function CodeBlock(props: CodeBlockProps) {
|
|
|
71
102
|
const LangIcon = langIconMap[lang]
|
|
72
103
|
|
|
73
104
|
return (
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
)}
|
|
93
|
-
<span>{title}</span>
|
|
94
|
-
</div>
|
|
105
|
+
<CodePrimitive.CodeBlock plain={plain} className={props.className}>
|
|
106
|
+
{(effectiveTitle || !hideCopy) && (
|
|
107
|
+
<CodePrimitive.CodeBlockHeader>
|
|
108
|
+
<CodePrimitive.CodeBlockGroup>
|
|
109
|
+
{effectiveTitle && (
|
|
110
|
+
<>
|
|
111
|
+
{LangIcon ? (
|
|
112
|
+
<LangIcon size={14} />
|
|
113
|
+
) : (
|
|
114
|
+
// @ts-ignore
|
|
115
|
+
<File size={14} className="opacity-60" />
|
|
116
|
+
)}
|
|
117
|
+
<span>{effectiveTitle}</span>
|
|
118
|
+
</>
|
|
119
|
+
)}
|
|
120
|
+
</CodePrimitive.CodeBlockGroup>
|
|
121
|
+
{!hideCopy && <CopyButton copied={copied} handleCopy={handleCopy} />}
|
|
122
|
+
</CodePrimitive.CodeBlockHeader>
|
|
95
123
|
)}
|
|
96
124
|
|
|
97
|
-
{
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
</Tooltip>
|
|
125
|
+
<CodePrimitive.CodeBlockContent shouldTruncate={shouldTruncate}>
|
|
126
|
+
{effectiveHighlightedHtml ? (
|
|
127
|
+
<div
|
|
128
|
+
// @ts-ignore
|
|
129
|
+
ref={preRef}
|
|
130
|
+
className="shiki-wrapper [&>pre]:m-0! [&>pre]:rounded-none! [&>pre]:border-none! [&>pre]:bg-inherit! [&>pre>code]:grid! [&>pre>code]:p-5! [&>.shiki.shiki-themes]:bg-transparent!"
|
|
131
|
+
dangerouslySetInnerHTML={{ __html: effectiveHighlightedHtml }}
|
|
132
|
+
/>
|
|
133
|
+
) : (
|
|
134
|
+
<pre
|
|
135
|
+
ref={preRef}
|
|
136
|
+
className="m-0! p-5! rounded-none! border-none! bg-inherit! font-mono text-[0.8125rem] leading-[1.7] overflow-x-auto"
|
|
137
|
+
{...rest}
|
|
138
|
+
>
|
|
139
|
+
{reactToText(children)}
|
|
140
|
+
</pre>
|
|
114
141
|
)}
|
|
115
|
-
</div>
|
|
116
|
-
|
|
117
|
-
{/* Code Content */}
|
|
118
|
-
{effectiveHighlightedHtml ? (
|
|
119
|
-
<div
|
|
120
|
-
// @ts-ignore
|
|
121
|
-
ref={preRef}
|
|
122
|
-
className="shiki-wrapper [&>pre]:m-0! [&>pre]:rounded-none! [&>pre]:border-none! [&>pre]:bg-inherit! [&>pre>code]:grid! [&>pre>code]:p-5! [&>.shiki.shiki-themes]:bg-transparent!"
|
|
123
|
-
dangerouslySetInnerHTML={{ __html: effectiveHighlightedHtml }}
|
|
124
|
-
/>
|
|
125
|
-
) : (
|
|
126
|
-
<pre
|
|
127
|
-
ref={preRef}
|
|
128
|
-
className="m-0! rounded-none! border-none! bg-inherit! font-mono text-[0.8125rem] leading-[1.7]"
|
|
129
|
-
{...rest}
|
|
130
|
-
>
|
|
131
|
-
{children}
|
|
132
|
-
</pre>
|
|
133
|
-
)}
|
|
134
142
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
>
|
|
144
|
-
<RAC.Button
|
|
145
|
-
onPress={() => setIsExpanded(!isExpanded)}
|
|
146
|
-
className="rounded-full bg-bg-surface border border-border-subtle px-5 py-2 text-[0.8125rem] font-medium text-text-main outline-none cursor-pointer transition-all hover:bg-border-subtle hover:-translate-y-px backdrop-blur-md"
|
|
143
|
+
{/* Expand/Collapse Trigger */}
|
|
144
|
+
{isExpandable && (
|
|
145
|
+
<div
|
|
146
|
+
className={cn(
|
|
147
|
+
shouldTruncate
|
|
148
|
+
? 'absolute bottom-0 inset-x-0 h-24 bg-linear-to-t from-(--color-code-bg) to-transparent flex items-end justify-center pb-4 z-10'
|
|
149
|
+
: 'relative flex justify-center py-4',
|
|
150
|
+
)}
|
|
147
151
|
>
|
|
148
|
-
{
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
152
|
+
{/* @ts-ignore */}
|
|
153
|
+
<Button
|
|
154
|
+
onPress={() => setIsExpanded(!isExpanded)}
|
|
155
|
+
className="rounded-full bg-bg-surface border border-border-subtle px-5 py-2 text-[0.8125rem] font-medium text-text-main outline-none cursor-pointer transition-all hover:bg-border-subtle hover:-translate-y-px backdrop-blur-md"
|
|
156
|
+
>
|
|
157
|
+
{isExpanded ? 'Show less' : 'Expand code'}
|
|
158
|
+
</Button>
|
|
159
|
+
</div>
|
|
160
|
+
)}
|
|
161
|
+
</CodePrimitive.CodeBlockContent>
|
|
162
|
+
</CodePrimitive.CodeBlock>
|
|
153
163
|
)
|
|
154
164
|
}
|
|
@@ -11,11 +11,7 @@ export interface ComponentPreviewProps {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export function ComponentPreview(props: ComponentPreviewProps) {
|
|
14
|
-
const {
|
|
15
|
-
highlightedHtml,
|
|
16
|
-
hideCode = false,
|
|
17
|
-
hideCopy = false,
|
|
18
|
-
} = props
|
|
14
|
+
const { highlightedHtml, hideCode = false, hideCopy = false } = props
|
|
19
15
|
const { initialCode, previewElement } = useComponentPreview(props)
|
|
20
16
|
|
|
21
17
|
return (
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { cn } from '
|
|
1
|
+
import { cn } from '../../utils/cn'
|
|
2
2
|
|
|
3
3
|
export interface FieldProps {
|
|
4
4
|
name: string
|
|
@@ -23,23 +23,22 @@ export function Field({
|
|
|
23
23
|
<article
|
|
24
24
|
className={cn(
|
|
25
25
|
'group relative my-6 rounded-xl border border-border-subtle bg-bg-surface p-5 transition-all duration-300',
|
|
26
|
-
'hover:border-primary-500/30 hover:shadow-lg hover:shadow-primary-500/5',
|
|
27
26
|
className,
|
|
28
27
|
)}
|
|
29
28
|
id={id}
|
|
30
29
|
>
|
|
31
30
|
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between mb-4">
|
|
32
31
|
<div className="flex flex-wrap items-center gap-2.5">
|
|
33
|
-
<code className="inline-flex items-center rounded-md bg-primary-500/10 px-2.5 py-1 font-mono text-sm font-bold text-primary-400 border border-primary-500/20 shadow-sm transition-colors
|
|
32
|
+
<code className="inline-flex items-center rounded-md bg-primary-500/10 px-2.5 py-1 font-mono text-sm font-bold text-primary-400 border border-primary-500/20 shadow-sm transition-colors">
|
|
34
33
|
{name}
|
|
35
34
|
</code>
|
|
36
35
|
{type && (
|
|
37
|
-
<span className="rounded-md bg-bg-muted/80 border border-border-subtle px-2 py-0.5 text-[11px] font-semibold text-text-muted uppercase
|
|
36
|
+
<span className="rounded-md bg-bg-muted/80 border border-border-subtle px-2 py-0.5 text-[11px] font-semibold text-text-muted uppercase shadow-sm">
|
|
38
37
|
{type}
|
|
39
38
|
</span>
|
|
40
39
|
)}
|
|
41
40
|
{required && (
|
|
42
|
-
<div className="flex items-center gap-1.5 rounded-full bg-red-500/10 px-2.5 py-0.5 text-[10px] font-bold uppercase
|
|
41
|
+
<div className="flex items-center gap-1.5 rounded-full bg-red-500/10 px-2.5 py-0.5 text-[10px] font-bold uppercase text-red-400 border border-red-500/20 shadow-sm">
|
|
43
42
|
<span className="h-1 w-1 rounded-full bg-red-400 animate-pulse" />
|
|
44
43
|
Required
|
|
45
44
|
</div>
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
FileImage,
|
|
9
9
|
ChevronRight,
|
|
10
10
|
} from 'lucide-react'
|
|
11
|
-
import { cn } from '
|
|
11
|
+
import { cn } from '../../utils/cn'
|
|
12
12
|
|
|
13
13
|
import {
|
|
14
14
|
TypeScript,
|
|
@@ -20,14 +20,17 @@ import {
|
|
|
20
20
|
Markdown,
|
|
21
21
|
Shell,
|
|
22
22
|
Yaml,
|
|
23
|
-
} from '
|
|
23
|
+
} from '../icons-dev'
|
|
24
24
|
|
|
25
25
|
// --- Constants & Types ---
|
|
26
26
|
|
|
27
27
|
const ICON_SIZE = 16
|
|
28
28
|
const STROKE_WIDTH = 2
|
|
29
29
|
|
|
30
|
-
const FILE_EXTENSION_MAP: Record<
|
|
30
|
+
const FILE_EXTENSION_MAP: Record<
|
|
31
|
+
string,
|
|
32
|
+
React.ComponentType<{ size?: number }>
|
|
33
|
+
> = {
|
|
31
34
|
ts: TypeScript,
|
|
32
35
|
tsx: ReactIcon,
|
|
33
36
|
js: JavaScript,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useConfig } from '
|
|
2
|
-
import { copyToClipboard } from '
|
|
1
|
+
import { useConfig } from '../../../app/config-context'
|
|
2
|
+
import { copyToClipboard } from '../../../utils/copy-clipboard'
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
|
4
4
|
import type { CodeBlockProps } from '../code-block'
|
|
5
5
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Link as LinkPrimitive,
|
|
3
3
|
type LinkProps as LinkPrimitiveProps,
|
|
4
|
-
} from '
|
|
5
|
-
import { cn } from '
|
|
4
|
+
} from '../primitives/link'
|
|
5
|
+
import { cn } from '../../utils/cn'
|
|
6
6
|
|
|
7
7
|
export type LinkProps = LinkPrimitiveProps & {
|
|
8
8
|
to: string
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
type ComponentPropsWithoutRef,
|
|
7
7
|
} from 'react'
|
|
8
8
|
import { Check, ChevronRight, Circle } from 'lucide-react'
|
|
9
|
-
import { cn } from '
|
|
9
|
+
import { cn } from '../../utils/cn'
|
|
10
10
|
import { cva, type VariantProps } from 'class-variance-authority'
|
|
11
11
|
|
|
12
12
|
const listVariants = cva('my-6 transition-all duration-200', {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Children, isValidElement, useMemo } from 'react'
|
|
2
2
|
import * as RAC from 'react-aria-components'
|
|
3
3
|
import { useTabs } from './hooks/useTabs'
|
|
4
|
-
import { cn } from '
|
|
4
|
+
import { cn } from '../../utils/cn'
|
|
5
5
|
import { CodeBlock } from './code-block'
|
|
6
6
|
import { cva } from 'class-variance-authority'
|
|
7
7
|
|
|
@@ -26,11 +26,7 @@ export const Breadcrumbs = ({
|
|
|
26
26
|
)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
const BreadcrumbsItem = ({
|
|
30
|
-
children,
|
|
31
|
-
className,
|
|
32
|
-
...props
|
|
33
|
-
}: ComponentBase) => {
|
|
29
|
+
const BreadcrumbsItem = ({ children, className, ...props }: ComponentBase) => {
|
|
34
30
|
return (
|
|
35
31
|
<Breadcrumb
|
|
36
32
|
className={cn('flex items-center mb-0 gap-1.5', className)}
|
|
@@ -71,8 +67,6 @@ const BreadcrumbsSeparator = ({ className }: ComponentBase) => {
|
|
|
71
67
|
)
|
|
72
68
|
}
|
|
73
69
|
|
|
74
|
-
|
|
75
|
-
|
|
76
70
|
Breadcrumbs.Root = Breadcrumbs
|
|
77
71
|
Breadcrumbs.Item = BreadcrumbsItem
|
|
78
72
|
Breadcrumbs.Link = BreadcrumbsLink
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { ComponentProps } from "react";
|
|
2
|
+
import { cn } from "../../utils/cn";
|
|
3
|
+
|
|
4
|
+
interface CodeBlockRootProps extends ComponentProps<"div"> {
|
|
5
|
+
/**
|
|
6
|
+
* Whether the code block is in plain mode (no borders/padding)
|
|
7
|
+
* @default false
|
|
8
|
+
*/
|
|
9
|
+
plain?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const CodeBlock = ({
|
|
13
|
+
children,
|
|
14
|
+
className,
|
|
15
|
+
plain = false,
|
|
16
|
+
...props
|
|
17
|
+
}: CodeBlockRootProps) => {
|
|
18
|
+
return (
|
|
19
|
+
<div
|
|
20
|
+
className={cn(
|
|
21
|
+
"not-prose boltdocs-code-block",
|
|
22
|
+
'group relative overflow-hidden bg-(--color-code-bg)',
|
|
23
|
+
'contain-layout contain-paint',
|
|
24
|
+
{
|
|
25
|
+
'my-6 rounded-lg border border-border-subtle': !plain,
|
|
26
|
+
},
|
|
27
|
+
className,
|
|
28
|
+
)}
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
{children}
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
type CodeBlockHeaderProps = ComponentProps<"div">;
|
|
37
|
+
|
|
38
|
+
const CodeBlockHeader = ({
|
|
39
|
+
children,
|
|
40
|
+
className,
|
|
41
|
+
...props
|
|
42
|
+
}: CodeBlockHeaderProps) => {
|
|
43
|
+
return (
|
|
44
|
+
<div
|
|
45
|
+
className={cn(
|
|
46
|
+
"flex h-9 items-center justify-between px-4 py-1.5",
|
|
47
|
+
"border-b border-border-subtle bg-bg-surface/50",
|
|
48
|
+
"text-[13px] font-medium text-text-muted",
|
|
49
|
+
className,
|
|
50
|
+
)}
|
|
51
|
+
{...props}
|
|
52
|
+
>
|
|
53
|
+
{children}
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
type CodeBlockGroupProps = ComponentProps<"div">;
|
|
59
|
+
|
|
60
|
+
const CodeBlockGroup = ({
|
|
61
|
+
children,
|
|
62
|
+
className,
|
|
63
|
+
...props
|
|
64
|
+
}: CodeBlockGroupProps) => {
|
|
65
|
+
return (
|
|
66
|
+
<div
|
|
67
|
+
className={cn(
|
|
68
|
+
"flex items-center space-x-2",
|
|
69
|
+
className,
|
|
70
|
+
)}
|
|
71
|
+
{...props}
|
|
72
|
+
>
|
|
73
|
+
{children}
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
interface CodeBlockContentProps extends ComponentProps<"div"> {
|
|
79
|
+
/**
|
|
80
|
+
* Whether the code should be truncated with an expand button
|
|
81
|
+
* @default false
|
|
82
|
+
*/
|
|
83
|
+
shouldTruncate?: boolean;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const CodeBlockContent = ({
|
|
87
|
+
className,
|
|
88
|
+
children,
|
|
89
|
+
shouldTruncate = false,
|
|
90
|
+
...props
|
|
91
|
+
}: CodeBlockContentProps) => {
|
|
92
|
+
return (
|
|
93
|
+
<div
|
|
94
|
+
className={cn(
|
|
95
|
+
"relative",
|
|
96
|
+
{
|
|
97
|
+
'[&>pre]:max-h-62.5 [&>pre]:overflow-hidden': shouldTruncate,
|
|
98
|
+
},
|
|
99
|
+
className,
|
|
100
|
+
)}
|
|
101
|
+
{...props}
|
|
102
|
+
>
|
|
103
|
+
{children}
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export {
|
|
109
|
+
CodeBlock,
|
|
110
|
+
CodeBlockHeader,
|
|
111
|
+
CodeBlockGroup,
|
|
112
|
+
CodeBlockContent,
|
|
113
|
+
};
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
1
|
import {
|
|
3
2
|
Link as RACLink,
|
|
4
3
|
type LinkProps as RACLinkProps,
|
|
5
4
|
} from 'react-aria-components'
|
|
6
5
|
import { useLocation } from 'react-router-dom'
|
|
7
|
-
import { useLocalizedTo } from '
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
6
|
+
import { useLocalizedTo } from '../../hooks/use-localized-to'
|
|
7
|
+
import { cn } from '../../utils/cn'
|
|
8
|
+
import { forwardRef } from 'react'
|
|
10
9
|
|
|
11
10
|
export interface LinkProps extends RACLinkProps {
|
|
12
11
|
/** Should prefetch the page on hover? Default 'hover' */
|
|
@@ -20,46 +19,29 @@ export interface LinkProps extends RACLinkProps {
|
|
|
20
19
|
* It uses the global navigation configuration from BoltdocsRouterProvider
|
|
21
20
|
* to handle seamless client-side transitions.
|
|
22
21
|
*/
|
|
23
|
-
export const Link =
|
|
24
|
-
|
|
25
|
-
const { href, prefetch = 'hover', onMouseEnter, onFocus, ...rest } = props
|
|
22
|
+
export const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
|
|
23
|
+
const { href, prefetch = 'hover', onMouseEnter, onFocus, ...rest } = props
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
const { preload } = usePreload()
|
|
25
|
+
const localizedHref = useLocalizedTo(href ?? '')
|
|
29
26
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
prefetch === 'hover' &&
|
|
34
|
-
typeof localizedHref === 'string' &&
|
|
35
|
-
localizedHref.startsWith('/')
|
|
36
|
-
) {
|
|
37
|
-
preload(localizedHref)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
27
|
+
const handleMouseEnter = (e: React.MouseEvent<HTMLAnchorElement>) => {
|
|
28
|
+
onMouseEnter?.(e)
|
|
29
|
+
}
|
|
40
30
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
prefetch === 'hover' &&
|
|
45
|
-
typeof localizedHref === 'string' &&
|
|
46
|
-
localizedHref.startsWith('/')
|
|
47
|
-
) {
|
|
48
|
-
preload(localizedHref)
|
|
49
|
-
}
|
|
50
|
-
}
|
|
31
|
+
const handleFocus = (e: React.FocusEvent) => {
|
|
32
|
+
onFocus?.(e as any)
|
|
33
|
+
}
|
|
51
34
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
)
|
|
35
|
+
return (
|
|
36
|
+
<RACLink
|
|
37
|
+
{...rest}
|
|
38
|
+
ref={ref}
|
|
39
|
+
href={localizedHref as string}
|
|
40
|
+
onMouseEnter={handleMouseEnter}
|
|
41
|
+
onFocus={handleFocus as any}
|
|
42
|
+
/>
|
|
43
|
+
)
|
|
44
|
+
})
|
|
63
45
|
Link.displayName = 'Link'
|
|
64
46
|
|
|
65
47
|
/**
|
|
@@ -90,7 +72,7 @@ export interface NavLinkProps
|
|
|
90
72
|
* It combines the Link primitive with path matching logic to determine
|
|
91
73
|
* if the link is currently active based on the browser's location.
|
|
92
74
|
*/
|
|
93
|
-
export const NavLink =
|
|
75
|
+
export const NavLink = forwardRef<HTMLAnchorElement, NavLinkProps>(
|
|
94
76
|
(props, ref) => {
|
|
95
77
|
const { href, end = false, className, children, ...rest } = props
|
|
96
78
|
const location = useLocation()
|