@lexibase/rdx-ui 3.0.0 → 3.2.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/THIRD_PARTY_NOTICES.md +3 -2
- package/package.json +4 -2
- package/src/components/docs-page-transition.tsx +178 -0
- package/src/components/docs-sidebar.tsx +105 -32
- package/src/components/docs-toc.tsx +6 -6
- package/src/components/kbd.tsx +8 -1
- package/src/components/mdx-code-block-view.tsx +133 -7
- package/src/components/mdx-code-block.tsx +83 -30
- package/src/components/mdx-components.tsx +6 -4
- package/src/components/mdx-folder-tree.tsx +58 -0
- package/src/components/mdx-keyboard-shortcut.tsx +74 -0
- package/src/components/mdx-mermaid.tsx +252 -0
- package/src/components/sheet.tsx +146 -0
- package/src/components/skip-link.tsx +10 -0
- package/src/components/tabs.tsx +6 -1
- package/src/lib/i18n.ts +48 -0
- package/src/lib/mermaid.ts +114 -0
- package/src/styles/globals.css +112 -14
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { Dialog as SheetPrimitive } from '@base-ui/react/dialog'
|
|
5
|
+
import { cn, mergeStateClassName } from '../lib/utils'
|
|
6
|
+
import { useMessages } from '../providers/locale-provider'
|
|
7
|
+
|
|
8
|
+
import { Button } from './button'
|
|
9
|
+
import { XIcon } from 'lucide-react'
|
|
10
|
+
|
|
11
|
+
function Sheet({ ...props }: SheetPrimitive.Root.Props) {
|
|
12
|
+
return <SheetPrimitive.Root data-slot="sheet" {...props} />
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function SheetTrigger({ ...props }: SheetPrimitive.Trigger.Props) {
|
|
16
|
+
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function SheetClose({ ...props }: SheetPrimitive.Close.Props) {
|
|
20
|
+
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function SheetPortal({ ...props }: SheetPrimitive.Portal.Props) {
|
|
24
|
+
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function SheetOverlay({ className, ...props }: SheetPrimitive.Backdrop.Props) {
|
|
28
|
+
return (
|
|
29
|
+
<SheetPrimitive.Backdrop
|
|
30
|
+
data-slot="sheet-overlay"
|
|
31
|
+
className={mergeStateClassName(
|
|
32
|
+
'fixed inset-0 z-50 bg-black/10 transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0 supports-backdrop-filter:backdrop-blur-xs motion-reduce:transition-none',
|
|
33
|
+
className
|
|
34
|
+
)}
|
|
35
|
+
{...props}
|
|
36
|
+
/>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function SheetContent({
|
|
41
|
+
className,
|
|
42
|
+
children,
|
|
43
|
+
side = 'right',
|
|
44
|
+
showCloseButton = true,
|
|
45
|
+
closeLabel,
|
|
46
|
+
portalProps,
|
|
47
|
+
...props
|
|
48
|
+
}: SheetPrimitive.Popup.Props & {
|
|
49
|
+
side?: 'top' | 'right' | 'bottom' | 'left'
|
|
50
|
+
showCloseButton?: boolean
|
|
51
|
+
closeLabel?: string
|
|
52
|
+
portalProps?: SheetPrimitive.Portal.Props
|
|
53
|
+
}) {
|
|
54
|
+
const messages = useMessages()
|
|
55
|
+
return (
|
|
56
|
+
<SheetPortal {...portalProps}>
|
|
57
|
+
<SheetOverlay />
|
|
58
|
+
<SheetPrimitive.Popup
|
|
59
|
+
data-slot="sheet-content"
|
|
60
|
+
data-side={side}
|
|
61
|
+
className={mergeStateClassName(
|
|
62
|
+
'fixed z-50 flex flex-col gap-4 bg-popover bg-clip-padding text-sm text-popover-foreground shadow-lg transition duration-200 ease-in-out data-ending-style:opacity-0 data-starting-style:opacity-0 data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=bottom]:data-ending-style:translate-y-[2.5rem] data-[side=bottom]:data-starting-style:translate-y-[2.5rem] data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=left]:data-ending-style:translate-x-[-2.5rem] data-[side=left]:data-starting-style:translate-x-[-2.5rem] data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=right]:data-ending-style:translate-x-[2.5rem] data-[side=right]:data-starting-style:translate-x-[2.5rem] data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=top]:data-ending-style:translate-y-[-2.5rem] data-[side=top]:data-starting-style:translate-y-[-2.5rem] data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm motion-reduce:transition-none',
|
|
63
|
+
className
|
|
64
|
+
)}
|
|
65
|
+
{...props}
|
|
66
|
+
>
|
|
67
|
+
{children}
|
|
68
|
+
{showCloseButton && (
|
|
69
|
+
<SheetPrimitive.Close
|
|
70
|
+
data-slot="sheet-close"
|
|
71
|
+
render={
|
|
72
|
+
<Button
|
|
73
|
+
variant="ghost"
|
|
74
|
+
className="absolute top-3 right-3"
|
|
75
|
+
size="icon-sm"
|
|
76
|
+
/>
|
|
77
|
+
}
|
|
78
|
+
>
|
|
79
|
+
<XIcon aria-hidden="true" />
|
|
80
|
+
<span className="sr-only">{closeLabel ?? messages.close}</span>
|
|
81
|
+
</SheetPrimitive.Close>
|
|
82
|
+
)}
|
|
83
|
+
</SheetPrimitive.Popup>
|
|
84
|
+
</SheetPortal>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function SheetHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
|
89
|
+
return (
|
|
90
|
+
<div
|
|
91
|
+
data-slot="sheet-header"
|
|
92
|
+
className={cn('flex flex-col gap-0.5 p-4', className)}
|
|
93
|
+
{...props}
|
|
94
|
+
/>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function SheetFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
|
99
|
+
return (
|
|
100
|
+
<div
|
|
101
|
+
data-slot="sheet-footer"
|
|
102
|
+
className={cn('mt-auto flex flex-col gap-2 p-4', className)}
|
|
103
|
+
{...props}
|
|
104
|
+
/>
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {
|
|
109
|
+
return (
|
|
110
|
+
<SheetPrimitive.Title
|
|
111
|
+
data-slot="sheet-title"
|
|
112
|
+
className={mergeStateClassName(
|
|
113
|
+
'cn-font-heading text-base font-medium text-foreground',
|
|
114
|
+
className
|
|
115
|
+
)}
|
|
116
|
+
{...props}
|
|
117
|
+
/>
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function SheetDescription({
|
|
122
|
+
className,
|
|
123
|
+
...props
|
|
124
|
+
}: SheetPrimitive.Description.Props) {
|
|
125
|
+
return (
|
|
126
|
+
<SheetPrimitive.Description
|
|
127
|
+
data-slot="sheet-description"
|
|
128
|
+
className={mergeStateClassName(
|
|
129
|
+
'text-sm text-muted-foreground',
|
|
130
|
+
className
|
|
131
|
+
)}
|
|
132
|
+
{...props}
|
|
133
|
+
/>
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export {
|
|
138
|
+
Sheet,
|
|
139
|
+
SheetTrigger,
|
|
140
|
+
SheetClose,
|
|
141
|
+
SheetContent,
|
|
142
|
+
SheetHeader,
|
|
143
|
+
SheetFooter,
|
|
144
|
+
SheetTitle,
|
|
145
|
+
SheetDescription,
|
|
146
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getMessages } from '../lib/i18n'
|
|
2
|
+
|
|
3
|
+
/** First keyboard stop, shared by the website and generated documentation. */
|
|
4
|
+
export function SkipLink({ lang }: { lang?: string }) {
|
|
5
|
+
return (
|
|
6
|
+
<a className="rdx-skip-link" href="#rdx-main">
|
|
7
|
+
{getMessages(lang).skipContent}
|
|
8
|
+
</a>
|
|
9
|
+
)
|
|
10
|
+
}
|
package/src/components/tabs.tsx
CHANGED
|
@@ -25,6 +25,7 @@ function panelText(node: Node): string {
|
|
|
25
25
|
)
|
|
26
26
|
)
|
|
27
27
|
return ''
|
|
28
|
+
if (node.dataset.rdxKbdValue !== undefined) return node.dataset.rdxKbdValue
|
|
28
29
|
if (node.matches('[data-rdx-code-block], [data-slot="code-block"]')) {
|
|
29
30
|
const pre = node.querySelector('pre')
|
|
30
31
|
const lines = pre?.querySelectorAll('[data-slot="code-block-line-content"]')
|
|
@@ -144,6 +145,7 @@ function Tabs({ className, ...props }: TabsPrimitive.Root.Props) {
|
|
|
144
145
|
}
|
|
145
146
|
|
|
146
147
|
function TabsList({ className, ...props }: TabsPrimitive.List.Props) {
|
|
148
|
+
const messages = useMessages()
|
|
147
149
|
return (
|
|
148
150
|
<div
|
|
149
151
|
data-slot="tabs-header"
|
|
@@ -151,6 +153,9 @@ function TabsList({ className, ...props }: TabsPrimitive.List.Props) {
|
|
|
151
153
|
>
|
|
152
154
|
<TabsPrimitive.List
|
|
153
155
|
data-slot="tabs-list"
|
|
156
|
+
aria-label={
|
|
157
|
+
props['aria-labelledby'] ? undefined : messages.documentationTabs
|
|
158
|
+
}
|
|
154
159
|
className={mergeStateClassName(
|
|
155
160
|
'flex min-w-0 flex-1 gap-0.5 overflow-x-auto p-1.5 data-[orientation=vertical]:flex-col',
|
|
156
161
|
className
|
|
@@ -167,7 +172,7 @@ function TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {
|
|
|
167
172
|
<TabsPrimitive.Tab
|
|
168
173
|
data-slot="tabs-trigger"
|
|
169
174
|
className={mergeStateClassName(
|
|
170
|
-
'relative shrink-0 rounded-md border border-transparent px-2.5 py-1 text-sm font-medium whitespace-nowrap text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring data-active:border-border data-active:bg-background data-active:text-
|
|
175
|
+
'relative shrink-0 rounded-md border border-transparent px-2.5 py-1 text-sm font-medium whitespace-nowrap text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring data-active:border-border data-active:bg-background data-active:text-rdx-selected data-active:shadow-xs data-disabled:cursor-not-allowed data-disabled:opacity-50 data-disabled:hover:bg-transparent data-disabled:hover:text-muted-foreground motion-reduce:transition-none',
|
|
171
176
|
className
|
|
172
177
|
)}
|
|
173
178
|
{...props}
|
package/src/lib/i18n.ts
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
/** Shared labels only: document content and author-provided names stay untouched. */
|
|
2
2
|
const en = {
|
|
3
|
+
keyboardJoiner: ' plus ',
|
|
4
|
+
keyboardControl: 'Control',
|
|
5
|
+
keyboardShift: 'Shift',
|
|
6
|
+
keyboardAlt: 'Alt',
|
|
7
|
+
keyboardCommand: 'Command',
|
|
8
|
+
keyboardOption: 'Option',
|
|
9
|
+
keyboardEscape: 'Escape',
|
|
10
|
+
keyboardEnter: 'Enter',
|
|
11
|
+
keyboardSpace: 'Space',
|
|
12
|
+
keyboardPlus: 'Plus',
|
|
13
|
+
keyboardArrowUp: 'Up arrow',
|
|
14
|
+
keyboardArrowDown: 'Down arrow',
|
|
15
|
+
keyboardArrowLeft: 'Left arrow',
|
|
16
|
+
keyboardArrowRight: 'Right arrow',
|
|
3
17
|
skipContent: 'Skip to content',
|
|
4
18
|
mainNavigation: 'Main navigation',
|
|
5
19
|
docs: 'Docs',
|
|
@@ -32,15 +46,25 @@ const en = {
|
|
|
32
46
|
'Press Escape or use the close button to return to the document.',
|
|
33
47
|
copyCode: 'Copy code',
|
|
34
48
|
wrapCode: 'Wrap lines',
|
|
49
|
+
showMore: 'Show more',
|
|
50
|
+
showLess: 'Show less',
|
|
35
51
|
codeCopied: 'Code copied to clipboard.',
|
|
36
52
|
copyCodeError: 'Could not copy. Select the code and copy it manually.',
|
|
37
53
|
copyRetry: 'Could not copy. Try again or copy manually.',
|
|
38
54
|
copied: 'Copied!',
|
|
39
55
|
copyTab: 'Copy active tab',
|
|
56
|
+
documentationTabs: 'Documentation tabs',
|
|
40
57
|
tabCopied: 'Tab content copied to clipboard.',
|
|
41
58
|
copyTabError: 'Could not copy. Select the tab content and copy it manually.',
|
|
42
59
|
code: 'Code',
|
|
43
60
|
folderTree: 'Folder',
|
|
61
|
+
diagram: 'Diagram',
|
|
62
|
+
showDiagram: 'Show diagram',
|
|
63
|
+
showDiagramSource: 'Show diagram source',
|
|
64
|
+
enlargeDiagram: 'Enlarge diagram',
|
|
65
|
+
diagramLoading: 'Rendering diagram…',
|
|
66
|
+
diagramError:
|
|
67
|
+
'Could not render this diagram. Check the Mermaid source below.',
|
|
44
68
|
table: 'Table',
|
|
45
69
|
current: 'Current',
|
|
46
70
|
version: 'Version {version}',
|
|
@@ -69,6 +93,20 @@ export type InterfaceMessages = { [Key in keyof typeof en]: string }
|
|
|
69
93
|
export type InterfaceLocale = 'en' | 'pt-BR'
|
|
70
94
|
|
|
71
95
|
const ptBR = {
|
|
96
|
+
keyboardJoiner: ' mais ',
|
|
97
|
+
keyboardControl: 'Control',
|
|
98
|
+
keyboardShift: 'Shift',
|
|
99
|
+
keyboardAlt: 'Alt',
|
|
100
|
+
keyboardCommand: 'Command',
|
|
101
|
+
keyboardOption: 'Option',
|
|
102
|
+
keyboardEscape: 'Escape',
|
|
103
|
+
keyboardEnter: 'Enter',
|
|
104
|
+
keyboardSpace: 'Espaço',
|
|
105
|
+
keyboardPlus: 'Sinal de mais',
|
|
106
|
+
keyboardArrowUp: 'Seta para cima',
|
|
107
|
+
keyboardArrowDown: 'Seta para baixo',
|
|
108
|
+
keyboardArrowLeft: 'Seta para a esquerda',
|
|
109
|
+
keyboardArrowRight: 'Seta para a direita',
|
|
72
110
|
skipContent: 'Ir para o conteúdo',
|
|
73
111
|
mainNavigation: 'Navegação principal',
|
|
74
112
|
docs: 'Docs',
|
|
@@ -101,17 +139,27 @@ const ptBR = {
|
|
|
101
139
|
'Pressione Escape ou use o botão de fechar para voltar ao documento.',
|
|
102
140
|
copyCode: 'Copiar código',
|
|
103
141
|
wrapCode: 'Quebrar linhas',
|
|
142
|
+
showMore: 'Mostrar mais',
|
|
143
|
+
showLess: 'Mostrar menos',
|
|
104
144
|
codeCopied: 'Código copiado para a área de transferência.',
|
|
105
145
|
copyCodeError:
|
|
106
146
|
'Não foi possível copiar. Selecione o código e copie manualmente.',
|
|
107
147
|
copyRetry: 'Não foi possível copiar. Tente novamente ou copie manualmente.',
|
|
108
148
|
copied: 'Copiado!',
|
|
109
149
|
copyTab: 'Copiar aba ativa',
|
|
150
|
+
documentationTabs: 'Abas da documentação',
|
|
110
151
|
tabCopied: 'Conteúdo da aba copiado para a área de transferência.',
|
|
111
152
|
copyTabError:
|
|
112
153
|
'Não foi possível copiar. Selecione o conteúdo da aba e copie manualmente.',
|
|
113
154
|
code: 'Código',
|
|
114
155
|
folderTree: 'Pastas',
|
|
156
|
+
diagram: 'Diagrama',
|
|
157
|
+
showDiagram: 'Mostrar diagrama',
|
|
158
|
+
showDiagramSource: 'Mostrar código do diagrama',
|
|
159
|
+
enlargeDiagram: 'Ampliar diagrama',
|
|
160
|
+
diagramLoading: 'Renderizando diagrama…',
|
|
161
|
+
diagramError:
|
|
162
|
+
'Não foi possível renderizar o diagrama. Confira o código Mermaid abaixo.',
|
|
115
163
|
table: 'Tabela',
|
|
116
164
|
current: 'Atual',
|
|
117
165
|
version: 'Versão {version}',
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
type Mermaid = (typeof import('mermaid'))['default']
|
|
2
|
+
|
|
3
|
+
let engine: Promise<Mermaid> | undefined
|
|
4
|
+
let queue: Promise<unknown> = Promise.resolve()
|
|
5
|
+
let serial = 0
|
|
6
|
+
|
|
7
|
+
function loadMermaid() {
|
|
8
|
+
engine ??= import('mermaid')
|
|
9
|
+
.then((module) => module.default)
|
|
10
|
+
.catch((error: unknown) => {
|
|
11
|
+
engine = undefined
|
|
12
|
+
throw error
|
|
13
|
+
})
|
|
14
|
+
return engine
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Mermaid owns global configuration: serialize theme setup and rendering. */
|
|
18
|
+
export function renderMermaid(
|
|
19
|
+
source: string,
|
|
20
|
+
dark: boolean,
|
|
21
|
+
active: () => boolean
|
|
22
|
+
): Promise<string | undefined> {
|
|
23
|
+
const task = queue.then(async () => {
|
|
24
|
+
if (!active()) return
|
|
25
|
+
if (source.length > 50_000)
|
|
26
|
+
throw new Error('Mermaid definition exceeds 50,000 characters.')
|
|
27
|
+
const mermaid = await loadMermaid()
|
|
28
|
+
if (!active()) return
|
|
29
|
+
const fontFamily = 'ui-sans-serif, system-ui, sans-serif'
|
|
30
|
+
mermaid.initialize({
|
|
31
|
+
startOnLoad: false,
|
|
32
|
+
securityLevel: 'strict',
|
|
33
|
+
suppressErrorRendering: true,
|
|
34
|
+
htmlLabels: false,
|
|
35
|
+
maxTextSize: 50_000,
|
|
36
|
+
maxEdges: 500,
|
|
37
|
+
theme: 'base',
|
|
38
|
+
fontFamily,
|
|
39
|
+
themeVariables: {
|
|
40
|
+
fontSize: '14px',
|
|
41
|
+
darkMode: dark,
|
|
42
|
+
background: 'transparent',
|
|
43
|
+
primaryColor: dark ? '#18181b' : '#f4f4f5',
|
|
44
|
+
primaryTextColor: dark ? '#fafafa' : '#18181b',
|
|
45
|
+
primaryBorderColor: dark ? '#52525b' : '#a1a1aa',
|
|
46
|
+
lineColor: dark ? '#a1a1aa' : '#52525b',
|
|
47
|
+
secondaryColor: dark ? '#27272a' : '#e4e4e7',
|
|
48
|
+
tertiaryColor: dark ? '#18181b' : '#fafafa',
|
|
49
|
+
fontFamily,
|
|
50
|
+
},
|
|
51
|
+
// Diagram directives cannot change the site's safety, theme or limits.
|
|
52
|
+
secure: [
|
|
53
|
+
...new Set([
|
|
54
|
+
'secure',
|
|
55
|
+
'securityLevel',
|
|
56
|
+
'startOnLoad',
|
|
57
|
+
'maxTextSize',
|
|
58
|
+
'maxEdges',
|
|
59
|
+
'suppressErrorRendering',
|
|
60
|
+
'theme',
|
|
61
|
+
'flowchart',
|
|
62
|
+
'htmlLabels',
|
|
63
|
+
'dompurifyConfig',
|
|
64
|
+
'themeCSS',
|
|
65
|
+
'themeVariables',
|
|
66
|
+
'fontFamily',
|
|
67
|
+
]),
|
|
68
|
+
],
|
|
69
|
+
})
|
|
70
|
+
const container = document.createElement('div')
|
|
71
|
+
container.setAttribute('aria-hidden', 'true')
|
|
72
|
+
container.inert = true
|
|
73
|
+
Object.assign(container.style, {
|
|
74
|
+
position: 'fixed',
|
|
75
|
+
left: '-100000px',
|
|
76
|
+
visibility: 'hidden',
|
|
77
|
+
})
|
|
78
|
+
document.body.append(container)
|
|
79
|
+
try {
|
|
80
|
+
const { svg } = await mermaid.render(
|
|
81
|
+
`rdx-mermaid-${++serial}`,
|
|
82
|
+
source,
|
|
83
|
+
container
|
|
84
|
+
)
|
|
85
|
+
if (!active()) return
|
|
86
|
+
// Mermaid's responsive width is intended for inline SVG. Give the image
|
|
87
|
+
// intrinsic dimensions so preview scaling and the expanded view stay crisp.
|
|
88
|
+
const document = new DOMParser().parseFromString(svg, 'image/svg+xml')
|
|
89
|
+
const element = document.documentElement
|
|
90
|
+
if (element.localName !== 'svg')
|
|
91
|
+
throw new Error('Mermaid returned invalid SVG.')
|
|
92
|
+
const viewBox = element
|
|
93
|
+
.getAttribute('viewBox')
|
|
94
|
+
?.split(/[\s,]+/)
|
|
95
|
+
.map(Number)
|
|
96
|
+
if (
|
|
97
|
+
viewBox?.length === 4 &&
|
|
98
|
+
viewBox.every(Number.isFinite) &&
|
|
99
|
+
viewBox[2]! > 0 &&
|
|
100
|
+
viewBox[3]! > 0
|
|
101
|
+
) {
|
|
102
|
+
element.setAttribute('width', String(viewBox[2]))
|
|
103
|
+
element.setAttribute('height', String(viewBox[3]))
|
|
104
|
+
element.style.removeProperty('max-width')
|
|
105
|
+
}
|
|
106
|
+
return new XMLSerializer().serializeToString(element)
|
|
107
|
+
} finally {
|
|
108
|
+
container.remove()
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
// A failed diagram must not block other diagrams on this or the next page.
|
|
112
|
+
queue = task.catch(() => undefined)
|
|
113
|
+
return task
|
|
114
|
+
}
|
package/src/styles/globals.css
CHANGED
|
@@ -6,6 +6,28 @@
|
|
|
6
6
|
|
|
7
7
|
@custom-variant dark (&:is(.dark *));
|
|
8
8
|
|
|
9
|
+
.rdx-skip-link {
|
|
10
|
+
position: fixed;
|
|
11
|
+
top: 1rem;
|
|
12
|
+
inset-inline-start: 1rem;
|
|
13
|
+
z-index: 100;
|
|
14
|
+
max-width: calc(100vw - 2rem);
|
|
15
|
+
transform: translateY(calc(-100% - 2rem));
|
|
16
|
+
padding: 0.5rem 0.75rem;
|
|
17
|
+
border: 1px solid var(--border);
|
|
18
|
+
border-radius: var(--radius);
|
|
19
|
+
background: var(--background);
|
|
20
|
+
color: var(--foreground);
|
|
21
|
+
font-size: 0.875rem;
|
|
22
|
+
font-weight: 500;
|
|
23
|
+
outline: 2px solid var(--ring);
|
|
24
|
+
outline-offset: 2px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.rdx-skip-link:focus {
|
|
28
|
+
transform: translateY(0);
|
|
29
|
+
}
|
|
30
|
+
|
|
9
31
|
:root {
|
|
10
32
|
--background: oklch(1 0 0);
|
|
11
33
|
--foreground: oklch(0.145 0 0);
|
|
@@ -19,13 +41,13 @@
|
|
|
19
41
|
--secondary-foreground: oklch(0.205 0 0);
|
|
20
42
|
--muted: oklch(0.97 0 0);
|
|
21
43
|
--muted-foreground: oklch(0.556 0 0);
|
|
22
|
-
--accent: oklch(0.97 0 0);
|
|
23
|
-
--accent-foreground: oklch(0.205 0 0);
|
|
44
|
+
--accent: var(--rdx-highlighting-soft, oklch(0.97 0 0));
|
|
45
|
+
--accent-foreground: var(--rdx-highlighting, oklch(0.205 0 0));
|
|
24
46
|
--destructive: oklch(0.577 0.245 27.325);
|
|
25
47
|
--destructive-foreground: oklch(0.577 0.245 27.325);
|
|
26
48
|
--border: oklch(0.922 0 0);
|
|
27
49
|
--input: oklch(0.922 0 0);
|
|
28
|
-
--ring: oklch(0.708 0 0);
|
|
50
|
+
--ring: var(--rdx-highlighting, oklch(0.708 0 0));
|
|
29
51
|
--chart-1: oklch(0.646 0.222 41.116);
|
|
30
52
|
--chart-2: oklch(0.6 0.118 184.704);
|
|
31
53
|
--chart-3: oklch(0.398 0.07 227.392);
|
|
@@ -34,12 +56,12 @@
|
|
|
34
56
|
--radius: 0.625rem;
|
|
35
57
|
--sidebar: oklch(0.985 0 0);
|
|
36
58
|
--sidebar-foreground: oklch(0.145 0 0);
|
|
37
|
-
--sidebar-primary: oklch(0.205 0 0);
|
|
59
|
+
--sidebar-primary: var(--rdx-highlighting, oklch(0.205 0 0));
|
|
38
60
|
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
39
|
-
--sidebar-accent: oklch(0.97 0 0);
|
|
40
|
-
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
61
|
+
--sidebar-accent: var(--rdx-highlighting-soft, oklch(0.97 0 0));
|
|
62
|
+
--sidebar-accent-foreground: var(--rdx-highlighting, oklch(0.205 0 0));
|
|
41
63
|
--sidebar-border: oklch(0.922 0 0);
|
|
42
|
-
--sidebar-ring: oklch(0.708 0 0);
|
|
64
|
+
--sidebar-ring: var(--rdx-highlighting, oklch(0.708 0 0));
|
|
43
65
|
}
|
|
44
66
|
|
|
45
67
|
.dark {
|
|
@@ -55,13 +77,13 @@
|
|
|
55
77
|
--secondary-foreground: oklch(0.985 0 0);
|
|
56
78
|
--muted: oklch(0.269 0 0);
|
|
57
79
|
--muted-foreground: oklch(0.708 0 0);
|
|
58
|
-
--accent: oklch(0.269 0 0);
|
|
59
|
-
--accent-foreground: oklch(0.985 0 0);
|
|
80
|
+
--accent: var(--rdx-highlighting-soft, oklch(0.269 0 0));
|
|
81
|
+
--accent-foreground: var(--rdx-highlighting, oklch(0.985 0 0));
|
|
60
82
|
--destructive: oklch(0.396 0.141 25.723);
|
|
61
83
|
--destructive-foreground: oklch(0.637 0.237 25.331);
|
|
62
84
|
--border: oklch(0.269 0 0);
|
|
63
85
|
--input: oklch(0.269 0 0);
|
|
64
|
-
--ring: oklch(0.556 0 0);
|
|
86
|
+
--ring: var(--rdx-highlighting, oklch(0.556 0 0));
|
|
65
87
|
--chart-1: oklch(0.488 0.243 264.376);
|
|
66
88
|
--chart-2: oklch(0.696 0.17 162.48);
|
|
67
89
|
--chart-3: oklch(0.769 0.188 70.08);
|
|
@@ -69,15 +91,27 @@
|
|
|
69
91
|
--chart-5: oklch(0.645 0.246 16.439);
|
|
70
92
|
--sidebar: oklch(0.205 0 0);
|
|
71
93
|
--sidebar-foreground: oklch(0.985 0 0);
|
|
72
|
-
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
94
|
+
--sidebar-primary: var(--rdx-highlighting, oklch(0.488 0.243 264.376));
|
|
73
95
|
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
74
|
-
--sidebar-accent: oklch(0.269 0 0);
|
|
75
|
-
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
96
|
+
--sidebar-accent: var(--rdx-highlighting-soft, oklch(0.269 0 0));
|
|
97
|
+
--sidebar-accent-foreground: var(--rdx-highlighting, oklch(0.985 0 0));
|
|
76
98
|
--sidebar-border: oklch(0.269 0 0);
|
|
77
|
-
--sidebar-ring: oklch(0.439 0 0);
|
|
99
|
+
--sidebar-ring: var(--rdx-highlighting, oklch(0.439 0 0));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
:root,
|
|
103
|
+
.dark {
|
|
104
|
+
/* Invalid without an override, allowing each existing token to keep its default. */
|
|
105
|
+
--rdx-highlighting-soft: color-mix(
|
|
106
|
+
in oklab,
|
|
107
|
+
var(--rdx-highlighting) 14%,
|
|
108
|
+
var(--background)
|
|
109
|
+
);
|
|
78
110
|
}
|
|
79
111
|
|
|
80
112
|
@theme inline {
|
|
113
|
+
--color-rdx-highlighting: var(--rdx-highlighting, var(--color-blue-500));
|
|
114
|
+
--color-rdx-selected: var(--rdx-highlighting, var(--foreground));
|
|
81
115
|
/* shadcn accordion animation, using the height measured by Base UI. */
|
|
82
116
|
--animate-accordion-down: accordion-down 0.2s ease-out;
|
|
83
117
|
--animate-accordion-up: accordion-up 0.2s ease-out;
|
|
@@ -141,6 +175,7 @@
|
|
|
141
175
|
@layer base {
|
|
142
176
|
* {
|
|
143
177
|
@apply border-border outline-ring/50;
|
|
178
|
+
scrollbar-width: thin;
|
|
144
179
|
}
|
|
145
180
|
body {
|
|
146
181
|
@apply bg-background text-foreground;
|
|
@@ -158,3 +193,66 @@
|
|
|
158
193
|
.dark [data-rdx-code-block] pre.shiki span {
|
|
159
194
|
color: var(--shiki-dark, inherit);
|
|
160
195
|
}
|
|
196
|
+
|
|
197
|
+
/* Only document navigation participates; desktop and reduced motion stay still. */
|
|
198
|
+
:root:active-view-transition-type(
|
|
199
|
+
rdx-doc-forward,
|
|
200
|
+
rdx-doc-back
|
|
201
|
+
)::view-transition {
|
|
202
|
+
pointer-events: none;
|
|
203
|
+
}
|
|
204
|
+
:root:active-view-transition-type(
|
|
205
|
+
rdx-doc-forward,
|
|
206
|
+
rdx-doc-back
|
|
207
|
+
)::view-transition-group(root) {
|
|
208
|
+
display: none;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
::view-transition-group(.rdx-doc-forward),
|
|
212
|
+
::view-transition-group(.rdx-doc-back),
|
|
213
|
+
::view-transition-old(.rdx-doc-forward),
|
|
214
|
+
::view-transition-new(.rdx-doc-forward),
|
|
215
|
+
::view-transition-old(.rdx-doc-back),
|
|
216
|
+
::view-transition-new(.rdx-doc-back) {
|
|
217
|
+
animation: none;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
@media (width < 768px) and (prefers-reduced-motion: no-preference) {
|
|
221
|
+
::view-transition-old(.rdx-doc-forward) {
|
|
222
|
+
--rdx-page-offset: -48px;
|
|
223
|
+
animation: rdx-page-exit 220ms ease-out both;
|
|
224
|
+
}
|
|
225
|
+
::view-transition-new(.rdx-doc-forward) {
|
|
226
|
+
--rdx-page-offset: 48px;
|
|
227
|
+
animation: rdx-page-enter 260ms cubic-bezier(0.22, 1, 0.36, 1) both;
|
|
228
|
+
}
|
|
229
|
+
::view-transition-old(.rdx-doc-back) {
|
|
230
|
+
--rdx-page-offset: 48px;
|
|
231
|
+
animation: rdx-page-exit 220ms ease-out both;
|
|
232
|
+
}
|
|
233
|
+
::view-transition-new(.rdx-doc-back) {
|
|
234
|
+
--rdx-page-offset: -48px;
|
|
235
|
+
animation: rdx-page-enter 260ms cubic-bezier(0.22, 1, 0.36, 1) both;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
@keyframes rdx-page-enter {
|
|
240
|
+
from {
|
|
241
|
+
opacity: 0;
|
|
242
|
+
transform: translateX(var(--rdx-page-offset));
|
|
243
|
+
}
|
|
244
|
+
to {
|
|
245
|
+
opacity: 1;
|
|
246
|
+
transform: translateX(0);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
@keyframes rdx-page-exit {
|
|
250
|
+
from {
|
|
251
|
+
opacity: 1;
|
|
252
|
+
transform: translateX(0);
|
|
253
|
+
}
|
|
254
|
+
to {
|
|
255
|
+
opacity: 0;
|
|
256
|
+
transform: translateX(var(--rdx-page-offset));
|
|
257
|
+
}
|
|
258
|
+
}
|