@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/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
+ }
@@ -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
+ }