@lexibase/rdx-ui 2.0.0 → 3.1.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 +8 -2
- package/package.json +8 -3
- package/src/components/button.tsx +2 -0
- package/src/components/code-block.tsx +274 -46
- package/src/components/copy-code-button.tsx +1 -79
- package/src/components/dialog.tsx +123 -36
- package/src/components/docs-page-transition.tsx +178 -0
- package/src/components/docs-search-dialog.tsx +6 -1
- package/src/components/docs-sidebar.tsx +103 -30
- package/src/components/docs-toc.tsx +6 -6
- package/src/components/mdx-code-block-view.tsx +203 -0
- package/src/components/mdx-code-block.tsx +161 -0
- package/src/components/mdx-components.tsx +47 -16
- package/src/components/mdx-folder-tree.tsx +58 -0
- package/src/components/mdx-image.tsx +73 -0
- package/src/components/mdx-mermaid.tsx +252 -0
- package/src/components/sheet.tsx +146 -0
- package/src/components/tabs.tsx +12 -3
- package/src/hooks/use-highlighted-code.ts +75 -0
- package/src/lib/highlighter.tsx +124 -0
- package/src/lib/i18n.ts +32 -0
- package/src/lib/mermaid.ts +114 -0
- package/src/styles/globals.css +91 -14
- package/src/styles/shadcn.css +650 -0
package/src/lib/i18n.ts
CHANGED
|
@@ -26,15 +26,31 @@ const en = {
|
|
|
26
26
|
open: 'Open',
|
|
27
27
|
close: 'Close',
|
|
28
28
|
closeSearch: 'Close search',
|
|
29
|
+
enlargeImage: 'Enlarge image: {alt}',
|
|
30
|
+
closeImage: 'Close image',
|
|
31
|
+
imagePreviewDescription:
|
|
32
|
+
'Press Escape or use the close button to return to the document.',
|
|
29
33
|
copyCode: 'Copy code',
|
|
34
|
+
wrapCode: 'Wrap lines',
|
|
35
|
+
showMore: 'Show more',
|
|
36
|
+
showLess: 'Show less',
|
|
30
37
|
codeCopied: 'Code copied to clipboard.',
|
|
31
38
|
copyCodeError: 'Could not copy. Select the code and copy it manually.',
|
|
32
39
|
copyRetry: 'Could not copy. Try again or copy manually.',
|
|
33
40
|
copied: 'Copied!',
|
|
34
41
|
copyTab: 'Copy active tab',
|
|
42
|
+
documentationTabs: 'Documentation tabs',
|
|
35
43
|
tabCopied: 'Tab content copied to clipboard.',
|
|
36
44
|
copyTabError: 'Could not copy. Select the tab content and copy it manually.',
|
|
37
45
|
code: 'Code',
|
|
46
|
+
folderTree: 'Folder',
|
|
47
|
+
diagram: 'Diagram',
|
|
48
|
+
showDiagram: 'Show diagram',
|
|
49
|
+
showDiagramSource: 'Show diagram source',
|
|
50
|
+
enlargeDiagram: 'Enlarge diagram',
|
|
51
|
+
diagramLoading: 'Rendering diagram…',
|
|
52
|
+
diagramError:
|
|
53
|
+
'Could not render this diagram. Check the Mermaid source below.',
|
|
38
54
|
table: 'Table',
|
|
39
55
|
current: 'Current',
|
|
40
56
|
version: 'Version {version}',
|
|
@@ -89,17 +105,33 @@ const ptBR = {
|
|
|
89
105
|
open: 'Abrir',
|
|
90
106
|
close: 'Fechar',
|
|
91
107
|
closeSearch: 'Fechar busca',
|
|
108
|
+
enlargeImage: 'Ampliar imagem: {alt}',
|
|
109
|
+
closeImage: 'Fechar imagem',
|
|
110
|
+
imagePreviewDescription:
|
|
111
|
+
'Pressione Escape ou use o botão de fechar para voltar ao documento.',
|
|
92
112
|
copyCode: 'Copiar código',
|
|
113
|
+
wrapCode: 'Quebrar linhas',
|
|
114
|
+
showMore: 'Mostrar mais',
|
|
115
|
+
showLess: 'Mostrar menos',
|
|
93
116
|
codeCopied: 'Código copiado para a área de transferência.',
|
|
94
117
|
copyCodeError:
|
|
95
118
|
'Não foi possível copiar. Selecione o código e copie manualmente.',
|
|
96
119
|
copyRetry: 'Não foi possível copiar. Tente novamente ou copie manualmente.',
|
|
97
120
|
copied: 'Copiado!',
|
|
98
121
|
copyTab: 'Copiar aba ativa',
|
|
122
|
+
documentationTabs: 'Abas da documentação',
|
|
99
123
|
tabCopied: 'Conteúdo da aba copiado para a área de transferência.',
|
|
100
124
|
copyTabError:
|
|
101
125
|
'Não foi possível copiar. Selecione o conteúdo da aba e copie manualmente.',
|
|
102
126
|
code: 'Código',
|
|
127
|
+
folderTree: 'Pastas',
|
|
128
|
+
diagram: 'Diagrama',
|
|
129
|
+
showDiagram: 'Mostrar diagrama',
|
|
130
|
+
showDiagramSource: 'Mostrar código do diagrama',
|
|
131
|
+
enlargeDiagram: 'Ampliar diagrama',
|
|
132
|
+
diagramLoading: 'Renderizando diagrama…',
|
|
133
|
+
diagramError:
|
|
134
|
+
'Não foi possível renderizar o diagrama. Confira o código Mermaid abaixo.',
|
|
103
135
|
table: 'Tabela',
|
|
104
136
|
current: 'Atual',
|
|
105
137
|
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
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
@source "../**/*.{ts,tsx}";
|
|
3
3
|
|
|
4
4
|
@import 'tw-animate-css';
|
|
5
|
+
@import './shadcn.css';
|
|
5
6
|
|
|
6
7
|
@custom-variant dark (&:is(.dark *));
|
|
7
8
|
|
|
@@ -18,13 +19,13 @@
|
|
|
18
19
|
--secondary-foreground: oklch(0.205 0 0);
|
|
19
20
|
--muted: oklch(0.97 0 0);
|
|
20
21
|
--muted-foreground: oklch(0.556 0 0);
|
|
21
|
-
--accent: oklch(0.97 0 0);
|
|
22
|
-
--accent-foreground: oklch(0.205 0 0);
|
|
22
|
+
--accent: var(--rdx-highlighting-soft, oklch(0.97 0 0));
|
|
23
|
+
--accent-foreground: var(--rdx-highlighting, oklch(0.205 0 0));
|
|
23
24
|
--destructive: oklch(0.577 0.245 27.325);
|
|
24
25
|
--destructive-foreground: oklch(0.577 0.245 27.325);
|
|
25
26
|
--border: oklch(0.922 0 0);
|
|
26
27
|
--input: oklch(0.922 0 0);
|
|
27
|
-
--ring: oklch(0.708 0 0);
|
|
28
|
+
--ring: var(--rdx-highlighting, oklch(0.708 0 0));
|
|
28
29
|
--chart-1: oklch(0.646 0.222 41.116);
|
|
29
30
|
--chart-2: oklch(0.6 0.118 184.704);
|
|
30
31
|
--chart-3: oklch(0.398 0.07 227.392);
|
|
@@ -33,12 +34,12 @@
|
|
|
33
34
|
--radius: 0.625rem;
|
|
34
35
|
--sidebar: oklch(0.985 0 0);
|
|
35
36
|
--sidebar-foreground: oklch(0.145 0 0);
|
|
36
|
-
--sidebar-primary: oklch(0.205 0 0);
|
|
37
|
+
--sidebar-primary: var(--rdx-highlighting, oklch(0.205 0 0));
|
|
37
38
|
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
38
|
-
--sidebar-accent: oklch(0.97 0 0);
|
|
39
|
-
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
39
|
+
--sidebar-accent: var(--rdx-highlighting-soft, oklch(0.97 0 0));
|
|
40
|
+
--sidebar-accent-foreground: var(--rdx-highlighting, oklch(0.205 0 0));
|
|
40
41
|
--sidebar-border: oklch(0.922 0 0);
|
|
41
|
-
--sidebar-ring: oklch(0.708 0 0);
|
|
42
|
+
--sidebar-ring: var(--rdx-highlighting, oklch(0.708 0 0));
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
.dark {
|
|
@@ -54,13 +55,13 @@
|
|
|
54
55
|
--secondary-foreground: oklch(0.985 0 0);
|
|
55
56
|
--muted: oklch(0.269 0 0);
|
|
56
57
|
--muted-foreground: oklch(0.708 0 0);
|
|
57
|
-
--accent: oklch(0.269 0 0);
|
|
58
|
-
--accent-foreground: oklch(0.985 0 0);
|
|
58
|
+
--accent: var(--rdx-highlighting-soft, oklch(0.269 0 0));
|
|
59
|
+
--accent-foreground: var(--rdx-highlighting, oklch(0.985 0 0));
|
|
59
60
|
--destructive: oklch(0.396 0.141 25.723);
|
|
60
61
|
--destructive-foreground: oklch(0.637 0.237 25.331);
|
|
61
62
|
--border: oklch(0.269 0 0);
|
|
62
63
|
--input: oklch(0.269 0 0);
|
|
63
|
-
--ring: oklch(0.556 0 0);
|
|
64
|
+
--ring: var(--rdx-highlighting, oklch(0.556 0 0));
|
|
64
65
|
--chart-1: oklch(0.488 0.243 264.376);
|
|
65
66
|
--chart-2: oklch(0.696 0.17 162.48);
|
|
66
67
|
--chart-3: oklch(0.769 0.188 70.08);
|
|
@@ -68,15 +69,27 @@
|
|
|
68
69
|
--chart-5: oklch(0.645 0.246 16.439);
|
|
69
70
|
--sidebar: oklch(0.205 0 0);
|
|
70
71
|
--sidebar-foreground: oklch(0.985 0 0);
|
|
71
|
-
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
72
|
+
--sidebar-primary: var(--rdx-highlighting, oklch(0.488 0.243 264.376));
|
|
72
73
|
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
73
|
-
--sidebar-accent: oklch(0.269 0 0);
|
|
74
|
-
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
74
|
+
--sidebar-accent: var(--rdx-highlighting-soft, oklch(0.269 0 0));
|
|
75
|
+
--sidebar-accent-foreground: var(--rdx-highlighting, oklch(0.985 0 0));
|
|
75
76
|
--sidebar-border: oklch(0.269 0 0);
|
|
76
|
-
--sidebar-ring: oklch(0.439 0 0);
|
|
77
|
+
--sidebar-ring: var(--rdx-highlighting, oklch(0.439 0 0));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
:root,
|
|
81
|
+
.dark {
|
|
82
|
+
/* Invalid without an override, allowing each existing token to keep its default. */
|
|
83
|
+
--rdx-highlighting-soft: color-mix(
|
|
84
|
+
in oklab,
|
|
85
|
+
var(--rdx-highlighting) 14%,
|
|
86
|
+
var(--background)
|
|
87
|
+
);
|
|
77
88
|
}
|
|
78
89
|
|
|
79
90
|
@theme inline {
|
|
91
|
+
--color-rdx-highlighting: var(--rdx-highlighting, var(--color-blue-500));
|
|
92
|
+
--color-rdx-selected: var(--rdx-highlighting, var(--foreground));
|
|
80
93
|
/* shadcn accordion animation, using the height measured by Base UI. */
|
|
81
94
|
--animate-accordion-down: accordion-down 0.2s ease-out;
|
|
82
95
|
--animate-accordion-up: accordion-up 0.2s ease-out;
|
|
@@ -140,6 +153,7 @@
|
|
|
140
153
|
@layer base {
|
|
141
154
|
* {
|
|
142
155
|
@apply border-border outline-ring/50;
|
|
156
|
+
scrollbar-width: thin;
|
|
143
157
|
}
|
|
144
158
|
body {
|
|
145
159
|
@apply bg-background text-foreground;
|
|
@@ -157,3 +171,66 @@
|
|
|
157
171
|
.dark [data-rdx-code-block] pre.shiki span {
|
|
158
172
|
color: var(--shiki-dark, inherit);
|
|
159
173
|
}
|
|
174
|
+
|
|
175
|
+
/* Only document navigation participates; desktop and reduced motion stay still. */
|
|
176
|
+
:root:active-view-transition-type(
|
|
177
|
+
rdx-doc-forward,
|
|
178
|
+
rdx-doc-back
|
|
179
|
+
)::view-transition {
|
|
180
|
+
pointer-events: none;
|
|
181
|
+
}
|
|
182
|
+
:root:active-view-transition-type(
|
|
183
|
+
rdx-doc-forward,
|
|
184
|
+
rdx-doc-back
|
|
185
|
+
)::view-transition-group(root) {
|
|
186
|
+
display: none;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
::view-transition-group(.rdx-doc-forward),
|
|
190
|
+
::view-transition-group(.rdx-doc-back),
|
|
191
|
+
::view-transition-old(.rdx-doc-forward),
|
|
192
|
+
::view-transition-new(.rdx-doc-forward),
|
|
193
|
+
::view-transition-old(.rdx-doc-back),
|
|
194
|
+
::view-transition-new(.rdx-doc-back) {
|
|
195
|
+
animation: none;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
@media (width < 768px) and (prefers-reduced-motion: no-preference) {
|
|
199
|
+
::view-transition-old(.rdx-doc-forward) {
|
|
200
|
+
--rdx-page-offset: -48px;
|
|
201
|
+
animation: rdx-page-exit 220ms ease-out both;
|
|
202
|
+
}
|
|
203
|
+
::view-transition-new(.rdx-doc-forward) {
|
|
204
|
+
--rdx-page-offset: 48px;
|
|
205
|
+
animation: rdx-page-enter 260ms cubic-bezier(0.22, 1, 0.36, 1) both;
|
|
206
|
+
}
|
|
207
|
+
::view-transition-old(.rdx-doc-back) {
|
|
208
|
+
--rdx-page-offset: 48px;
|
|
209
|
+
animation: rdx-page-exit 220ms ease-out both;
|
|
210
|
+
}
|
|
211
|
+
::view-transition-new(.rdx-doc-back) {
|
|
212
|
+
--rdx-page-offset: -48px;
|
|
213
|
+
animation: rdx-page-enter 260ms cubic-bezier(0.22, 1, 0.36, 1) both;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
@keyframes rdx-page-enter {
|
|
218
|
+
from {
|
|
219
|
+
opacity: 0;
|
|
220
|
+
transform: translateX(var(--rdx-page-offset));
|
|
221
|
+
}
|
|
222
|
+
to {
|
|
223
|
+
opacity: 1;
|
|
224
|
+
transform: translateX(0);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
@keyframes rdx-page-exit {
|
|
228
|
+
from {
|
|
229
|
+
opacity: 1;
|
|
230
|
+
transform: translateX(0);
|
|
231
|
+
}
|
|
232
|
+
to {
|
|
233
|
+
opacity: 0;
|
|
234
|
+
transform: translateX(var(--rdx-page-offset));
|
|
235
|
+
}
|
|
236
|
+
}
|