@lexibase/rdx-ui 3.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.
@@ -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
+ }
@@ -19,13 +19,13 @@
19
19
  --secondary-foreground: oklch(0.205 0 0);
20
20
  --muted: oklch(0.97 0 0);
21
21
  --muted-foreground: oklch(0.556 0 0);
22
- --accent: oklch(0.97 0 0);
23
- --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));
24
24
  --destructive: oklch(0.577 0.245 27.325);
25
25
  --destructive-foreground: oklch(0.577 0.245 27.325);
26
26
  --border: oklch(0.922 0 0);
27
27
  --input: oklch(0.922 0 0);
28
- --ring: oklch(0.708 0 0);
28
+ --ring: var(--rdx-highlighting, oklch(0.708 0 0));
29
29
  --chart-1: oklch(0.646 0.222 41.116);
30
30
  --chart-2: oklch(0.6 0.118 184.704);
31
31
  --chart-3: oklch(0.398 0.07 227.392);
@@ -34,12 +34,12 @@
34
34
  --radius: 0.625rem;
35
35
  --sidebar: oklch(0.985 0 0);
36
36
  --sidebar-foreground: oklch(0.145 0 0);
37
- --sidebar-primary: oklch(0.205 0 0);
37
+ --sidebar-primary: var(--rdx-highlighting, oklch(0.205 0 0));
38
38
  --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);
39
+ --sidebar-accent: var(--rdx-highlighting-soft, oklch(0.97 0 0));
40
+ --sidebar-accent-foreground: var(--rdx-highlighting, oklch(0.205 0 0));
41
41
  --sidebar-border: oklch(0.922 0 0);
42
- --sidebar-ring: oklch(0.708 0 0);
42
+ --sidebar-ring: var(--rdx-highlighting, oklch(0.708 0 0));
43
43
  }
44
44
 
45
45
  .dark {
@@ -55,13 +55,13 @@
55
55
  --secondary-foreground: oklch(0.985 0 0);
56
56
  --muted: oklch(0.269 0 0);
57
57
  --muted-foreground: oklch(0.708 0 0);
58
- --accent: oklch(0.269 0 0);
59
- --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));
60
60
  --destructive: oklch(0.396 0.141 25.723);
61
61
  --destructive-foreground: oklch(0.637 0.237 25.331);
62
62
  --border: oklch(0.269 0 0);
63
63
  --input: oklch(0.269 0 0);
64
- --ring: oklch(0.556 0 0);
64
+ --ring: var(--rdx-highlighting, oklch(0.556 0 0));
65
65
  --chart-1: oklch(0.488 0.243 264.376);
66
66
  --chart-2: oklch(0.696 0.17 162.48);
67
67
  --chart-3: oklch(0.769 0.188 70.08);
@@ -69,15 +69,27 @@
69
69
  --chart-5: oklch(0.645 0.246 16.439);
70
70
  --sidebar: oklch(0.205 0 0);
71
71
  --sidebar-foreground: oklch(0.985 0 0);
72
- --sidebar-primary: oklch(0.488 0.243 264.376);
72
+ --sidebar-primary: var(--rdx-highlighting, oklch(0.488 0.243 264.376));
73
73
  --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);
74
+ --sidebar-accent: var(--rdx-highlighting-soft, oklch(0.269 0 0));
75
+ --sidebar-accent-foreground: var(--rdx-highlighting, oklch(0.985 0 0));
76
76
  --sidebar-border: oklch(0.269 0 0);
77
- --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
+ );
78
88
  }
79
89
 
80
90
  @theme inline {
91
+ --color-rdx-highlighting: var(--rdx-highlighting, var(--color-blue-500));
92
+ --color-rdx-selected: var(--rdx-highlighting, var(--foreground));
81
93
  /* shadcn accordion animation, using the height measured by Base UI. */
82
94
  --animate-accordion-down: accordion-down 0.2s ease-out;
83
95
  --animate-accordion-up: accordion-up 0.2s ease-out;
@@ -141,6 +153,7 @@
141
153
  @layer base {
142
154
  * {
143
155
  @apply border-border outline-ring/50;
156
+ scrollbar-width: thin;
144
157
  }
145
158
  body {
146
159
  @apply bg-background text-foreground;
@@ -158,3 +171,66 @@
158
171
  .dark [data-rdx-code-block] pre.shiki span {
159
172
  color: var(--shiki-dark, inherit);
160
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
+ }