@ponchia/ui 0.6.10 → 0.6.11
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/CHANGELOG.md +72 -0
- package/README.md +38 -25
- package/annotations/index.d.ts +15 -15
- package/annotations/index.d.ts.map +1 -1
- package/annotations/index.js +52 -34
- package/behaviors/carousel.d.ts +7 -3
- package/behaviors/carousel.d.ts.map +1 -1
- package/behaviors/carousel.js +157 -27
- package/behaviors/combobox.d.ts +1 -1
- package/behaviors/combobox.d.ts.map +1 -1
- package/behaviors/combobox.js +46 -23
- package/behaviors/command.d.ts +1 -1
- package/behaviors/command.d.ts.map +1 -1
- package/behaviors/command.js +63 -23
- package/behaviors/connectors.d.ts.map +1 -1
- package/behaviors/connectors.js +126 -19
- package/behaviors/crosshair.d.ts.map +1 -1
- package/behaviors/crosshair.js +71 -8
- package/behaviors/dialog.d.ts.map +1 -1
- package/behaviors/dialog.js +20 -3
- package/behaviors/disclosure.d.ts.map +1 -1
- package/behaviors/disclosure.js +35 -6
- package/behaviors/dismissible.js +1 -1
- package/behaviors/forms.d.ts +23 -2
- package/behaviors/forms.d.ts.map +1 -1
- package/behaviors/forms.js +97 -9
- package/behaviors/glyph.d.ts.map +1 -1
- package/behaviors/glyph.js +56 -5
- package/behaviors/internal.d.ts.map +1 -1
- package/behaviors/internal.js +52 -5
- package/behaviors/menu.d.ts.map +1 -1
- package/behaviors/menu.js +2 -1
- package/behaviors/modal.d.ts.map +1 -1
- package/behaviors/modal.js +25 -9
- package/behaviors/popover.d.ts.map +1 -1
- package/behaviors/popover.js +8 -6
- package/behaviors/sources.d.ts.map +1 -1
- package/behaviors/sources.js +24 -3
- package/behaviors/splitter.d.ts.map +1 -1
- package/behaviors/splitter.js +27 -6
- package/behaviors/table.d.ts.map +1 -1
- package/behaviors/table.js +44 -7
- package/behaviors/tabs.d.ts.map +1 -1
- package/behaviors/tabs.js +51 -14
- package/behaviors/theme.d.ts.map +1 -1
- package/behaviors/theme.js +64 -4
- package/behaviors/toast.d.ts +6 -1
- package/behaviors/toast.d.ts.map +1 -1
- package/behaviors/toast.js +48 -12
- package/classes/classes.json +24 -0
- package/classes/index.d.ts +3 -2
- package/classes/index.js +77 -39
- package/connectors/index.d.ts +4 -4
- package/connectors/index.d.ts.map +1 -1
- package/connectors/index.js +14 -12
- package/css/annotations.css +1 -0
- package/css/app.css +7 -0
- package/css/base.css +3 -0
- package/css/bullet.css +41 -7
- package/css/code.css +14 -0
- package/css/command.css +10 -0
- package/css/dataviz.css +27 -0
- package/css/diff.css +2 -0
- package/css/disclosure.css +8 -0
- package/css/dots.css +1 -1
- package/css/feedback.css +9 -0
- package/css/interval.css +20 -2
- package/css/legend.css +10 -9
- package/css/marks.css +1 -0
- package/css/motion.css +2 -0
- package/css/overlay.css +14 -2
- package/css/primitives.css +1 -1
- package/css/report.css +3 -0
- package/css/sources.css +4 -4
- package/css/spotlight.css +6 -0
- package/css/table.css +19 -0
- package/css/term.css +4 -1
- package/css/tokens.css +8 -13
- package/dist/bronto.css +1 -1
- package/dist/css/analytical.css +1 -1
- package/dist/css/app.css +1 -1
- package/dist/css/bullet.css +1 -1
- package/dist/css/code.css +1 -1
- package/dist/css/command.css +1 -1
- package/dist/css/dataviz.css +1 -1
- package/dist/css/diff.css +1 -1
- package/dist/css/disclosure.css +1 -1
- package/dist/css/dots.css +1 -1
- package/dist/css/feedback.css +1 -1
- package/dist/css/interval.css +1 -1
- package/dist/css/legend.css +1 -1
- package/dist/css/marks.css +1 -1
- package/dist/css/overlay.css +1 -1
- package/dist/css/primitives.css +1 -1
- package/dist/css/report-kit.css +1 -1
- package/dist/css/sources.css +1 -1
- package/dist/css/spotlight.css +1 -1
- package/dist/css/table.css +1 -1
- package/dist/css/term.css +1 -1
- package/dist/css/tokens.css +1 -1
- package/docs/architecture.md +5 -3
- package/docs/bullet.md +6 -1
- package/docs/clamp.md +5 -0
- package/docs/command.md +3 -2
- package/docs/contrast.md +3 -3
- package/docs/crosshair.md +6 -0
- package/docs/dots.md +10 -3
- package/docs/figure.md +7 -0
- package/docs/glyphs.md +14 -2
- package/docs/highlights.md +9 -0
- package/docs/interval.md +6 -0
- package/docs/mermaid.md +5 -3
- package/docs/package-contract.md +24 -1
- package/docs/reporting.md +8 -8
- package/docs/selection.md +9 -0
- package/docs/sources.md +5 -0
- package/docs/state.md +6 -0
- package/docs/textref.md +18 -13
- package/docs/theming.md +18 -8
- package/docs/toc.md +6 -0
- package/docs/tree.md +9 -2
- package/docs/usage.md +2 -2
- package/docs/vega.md +5 -3
- package/glyphs/glyphs.js +62 -8
- package/index.d.ts +1 -0
- package/llms.txt +18 -14
- package/package.json +98 -6
- package/qwik/index.d.ts +4 -3
- package/qwik/index.d.ts.map +1 -1
- package/qwik/index.js +7 -5
- package/react/index.d.ts +4 -3
- package/react/index.d.ts.map +1 -1
- package/react/index.js +3 -2
- package/solid/index.d.ts +7 -5
- package/solid/index.d.ts.map +1 -1
- package/solid/index.js +11 -7
- package/tokens/vega.d.ts +1 -1
- package/tokens/vega.js +3 -2
- package/vue/index.d.ts.map +1 -1
- package/vue/index.js +37 -3
package/behaviors/theme.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["theme.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["theme.js"],"names":[],"mappings":"AAuBA;;;;;;;;;GASG;AAEH;;;;;;;GAOG;AACH,wDAHW,cAAc,GACZ,IAAI,CAahB;AAED;;;;;;;;;;;;;;GAcG;AACH,uDAHW,gBAAgB,GAAG,OAAO,eAAe,EAAE,YAAY,GACrD,OAAO,eAAe,EAAE,OAAO,CAgH3C;;;;;;;;;;6BAzJY,gBAAgB,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE;;;;;WAIpC,OAAO,GAAG,MAAM"}
|
package/behaviors/theme.js
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
import { hasDom, resolveHost, noop, bindOnce, collectHosts, closestSafe } from './internal.js';
|
|
2
2
|
|
|
3
3
|
const THEMES = ['light', 'dark'];
|
|
4
|
+
const DARK_SCHEME_QUERY = '(prefers-color-scheme: dark)';
|
|
5
|
+
|
|
6
|
+
const colorSchemeQuery = () =>
|
|
7
|
+
typeof matchMedia === 'function' ? matchMedia(DARK_SCHEME_QUERY) : null;
|
|
8
|
+
|
|
9
|
+
function onColorSchemeChange(query, listener) {
|
|
10
|
+
if (
|
|
11
|
+
typeof query?.addEventListener === 'function' &&
|
|
12
|
+
typeof query.removeEventListener === 'function'
|
|
13
|
+
) {
|
|
14
|
+
query.addEventListener('change', listener);
|
|
15
|
+
return () => query.removeEventListener('change', listener);
|
|
16
|
+
}
|
|
17
|
+
if (typeof query?.addListener === 'function' && typeof query.removeListener === 'function') {
|
|
18
|
+
query.addListener(listener);
|
|
19
|
+
return () => query.removeListener(listener);
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
4
23
|
|
|
5
24
|
/**
|
|
6
25
|
* @typedef {object} ThemeStorageOpts
|
|
@@ -66,8 +85,12 @@ export function initThemeToggle({ storageKey = 'bronto-theme', root } = {}) {
|
|
|
66
85
|
}
|
|
67
86
|
};
|
|
68
87
|
|
|
69
|
-
|
|
70
|
-
|
|
88
|
+
let schemeQuery = null;
|
|
89
|
+
let removeSchemeListener = noop;
|
|
90
|
+
|
|
91
|
+
const hasExplicitTheme = () => THEMES.includes(docEl.getAttribute('data-theme'));
|
|
92
|
+
|
|
93
|
+
const prefersDark = () => (schemeQuery || colorSchemeQuery())?.matches === true;
|
|
71
94
|
|
|
72
95
|
const current = () => {
|
|
73
96
|
const attr = docEl.getAttribute('data-theme');
|
|
@@ -87,6 +110,38 @@ export function initThemeToggle({ storageKey = 'bronto-theme', root } = {}) {
|
|
|
87
110
|
});
|
|
88
111
|
};
|
|
89
112
|
|
|
113
|
+
const clearSchemeListener = () => {
|
|
114
|
+
removeSchemeListener();
|
|
115
|
+
removeSchemeListener = noop;
|
|
116
|
+
schemeQuery = null;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const syncSchemeListener = () => {
|
|
120
|
+
if (hasExplicitTheme()) {
|
|
121
|
+
clearSchemeListener();
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (schemeQuery) return;
|
|
125
|
+
const query = colorSchemeQuery();
|
|
126
|
+
const cleanup = onColorSchemeChange(query, onSchemeChange);
|
|
127
|
+
if (!cleanup) return;
|
|
128
|
+
schemeQuery = query;
|
|
129
|
+
removeSchemeListener = cleanup;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
function onSchemeChange() {
|
|
133
|
+
if (hasExplicitTheme()) {
|
|
134
|
+
clearSchemeListener();
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
reflect();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const onThemeChange = () => {
|
|
141
|
+
reflect();
|
|
142
|
+
syncSchemeListener();
|
|
143
|
+
};
|
|
144
|
+
|
|
90
145
|
const onClick = (e) => {
|
|
91
146
|
const trigger = closestSafe(e.target, '[data-bronto-theme-toggle]');
|
|
92
147
|
if (!trigger || !host.contains(trigger)) return;
|
|
@@ -94,6 +149,7 @@ export function initThemeToggle({ storageKey = 'bronto-theme', root } = {}) {
|
|
|
94
149
|
const forced = trigger.getAttribute('data-bronto-theme-toggle');
|
|
95
150
|
const next = THEMES.includes(forced) ? forced : current() === 'dark' ? 'light' : 'dark';
|
|
96
151
|
docEl.setAttribute('data-theme', next);
|
|
152
|
+
clearSchemeListener();
|
|
97
153
|
try {
|
|
98
154
|
localStorage.setItem(storageKey, next);
|
|
99
155
|
} catch {
|
|
@@ -105,12 +161,16 @@ export function initThemeToggle({ storageKey = 'bronto-theme', root } = {}) {
|
|
|
105
161
|
);
|
|
106
162
|
};
|
|
107
163
|
|
|
108
|
-
applyStoredTheme({ storageKey, root: docEl });
|
|
109
|
-
reflect();
|
|
110
164
|
return bindOnce(host, 'themeToggle', () => {
|
|
165
|
+
applyStoredTheme({ storageKey, root: docEl });
|
|
166
|
+
reflect();
|
|
167
|
+
syncSchemeListener();
|
|
168
|
+
docEl.addEventListener('bronto:themechange', onThemeChange);
|
|
111
169
|
host.addEventListener('click', onClick);
|
|
112
170
|
return () => {
|
|
171
|
+
docEl.removeEventListener('bronto:themechange', onThemeChange);
|
|
113
172
|
host.removeEventListener('click', onClick);
|
|
173
|
+
clearSchemeListener();
|
|
114
174
|
for (const [el, state] of toggleStates) {
|
|
115
175
|
if (state.had) el.setAttribute('aria-pressed', state.value);
|
|
116
176
|
else el.removeAttribute('aria-pressed');
|
package/behaviors/toast.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* @property {number} [duration] Auto-dismiss delay in ms. `0` keeps it until dismissed. Default: `4000`.
|
|
6
6
|
* @property {boolean} [assertive] Route to the assertive live region so AT interrupts immediately. Defaults to `true` when `tone === 'danger'`.
|
|
7
7
|
* @property {boolean} [closable] Render a dismiss button on the toast.
|
|
8
|
+
* @property {string} [dismissLabel] Accessible label for the generated dismiss button. Default: `Dismiss`.
|
|
8
9
|
*/
|
|
9
10
|
/**
|
|
10
11
|
* Push a transient toast into a shared, screen-anchored stack. The stack
|
|
@@ -23,7 +24,7 @@
|
|
|
23
24
|
* @param {ToastOpts} [opts]
|
|
24
25
|
* @returns {import('./internal.js').Cleanup}
|
|
25
26
|
*/
|
|
26
|
-
export function toast(message: string, { tone, title, duration, assertive, closable }?: ToastOpts): import("./internal.js").Cleanup;
|
|
27
|
+
export function toast(message: string, { tone, title, duration, assertive, closable, dismissLabel }?: ToastOpts): import("./internal.js").Cleanup;
|
|
27
28
|
export type ToastOpts = {
|
|
28
29
|
/**
|
|
29
30
|
* Status tone — maps to `ui-toast--<tone>`.
|
|
@@ -45,5 +46,9 @@ export type ToastOpts = {
|
|
|
45
46
|
* Render a dismiss button on the toast.
|
|
46
47
|
*/
|
|
47
48
|
closable?: boolean | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Accessible label for the generated dismiss button. Default: `Dismiss`.
|
|
51
|
+
*/
|
|
52
|
+
dismissLabel?: string | undefined;
|
|
48
53
|
};
|
|
49
54
|
//# sourceMappingURL=toast.d.ts.map
|
package/behaviors/toast.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["toast.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["toast.js"],"names":[],"mappings":"AAwJA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH,+BAJW,MAAM,iEACN,SAAS,GACP,OAAO,eAAe,EAAE,OAAO,CAsD3C"}
|
package/behaviors/toast.js
CHANGED
|
@@ -27,10 +27,10 @@ function toastStack(isAssertive) {
|
|
|
27
27
|
stack.setAttribute('aria-live', isAssertive ? 'assertive' : 'polite');
|
|
28
28
|
if (isAssertive) {
|
|
29
29
|
stack.setAttribute('role', 'alert');
|
|
30
|
-
// The assertive
|
|
31
|
-
//
|
|
32
|
-
// the
|
|
33
|
-
stack.setAttribute('aria-atomic', '
|
|
30
|
+
// The assertive stack may hold more than one sticky danger toast. Keep the
|
|
31
|
+
// container non-atomic so adding a new toast announces that toast only,
|
|
32
|
+
// while the per-toast aria-atomic below still reads its title + message.
|
|
33
|
+
stack.setAttribute('aria-atomic', 'false');
|
|
34
34
|
}
|
|
35
35
|
document.body.appendChild(stack);
|
|
36
36
|
}
|
|
@@ -102,25 +102,54 @@ function removeToast(el) {
|
|
|
102
102
|
}
|
|
103
103
|
el.classList.add('is-leaving');
|
|
104
104
|
let done = false;
|
|
105
|
+
let timer;
|
|
105
106
|
const finish = () => {
|
|
106
107
|
if (done) return;
|
|
107
108
|
done = true;
|
|
109
|
+
el.removeEventListener('transitionend', finish);
|
|
110
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
108
111
|
el.remove();
|
|
109
112
|
};
|
|
110
|
-
el.addEventListener('transitionend', finish
|
|
111
|
-
|
|
113
|
+
el.addEventListener('transitionend', finish);
|
|
114
|
+
timer = setTimeout(finish, dur * 1000 + 120);
|
|
112
115
|
timer?.unref?.(); // don't keep a Node test process alive
|
|
113
116
|
}
|
|
114
117
|
|
|
115
|
-
function addToastClose(el, dismiss) {
|
|
118
|
+
function addToastClose(el, dismiss, label = 'Dismiss') {
|
|
116
119
|
const close = document.createElement('button');
|
|
117
120
|
close.type = 'button';
|
|
118
121
|
close.className = 'ui-toast__close';
|
|
119
|
-
close.setAttribute('aria-label',
|
|
122
|
+
close.setAttribute('aria-label', label);
|
|
120
123
|
close.addEventListener('click', dismiss);
|
|
121
124
|
el.appendChild(close);
|
|
122
125
|
}
|
|
123
126
|
|
|
127
|
+
function normalizeToastDuration(duration) {
|
|
128
|
+
let value;
|
|
129
|
+
try {
|
|
130
|
+
value = Number(duration);
|
|
131
|
+
} catch {
|
|
132
|
+
value = NaN;
|
|
133
|
+
}
|
|
134
|
+
if (Number.isFinite(value) && value >= 0) return value;
|
|
135
|
+
if (typeof console !== 'undefined') {
|
|
136
|
+
console.warn(
|
|
137
|
+
'[bronto] toast(): duration must be a finite non-negative number. Rendering a sticky, closable toast instead.',
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
return 0;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function toastDismissLabel(stack, dismissLabel) {
|
|
144
|
+
return (
|
|
145
|
+
(typeof dismissLabel === 'string' && dismissLabel.trim()) ||
|
|
146
|
+
stack.getAttribute('data-bronto-toast-dismiss-label')?.trim() ||
|
|
147
|
+
document.body?.getAttribute('data-bronto-toast-dismiss-label')?.trim() ||
|
|
148
|
+
document.documentElement?.getAttribute('data-bronto-toast-dismiss-label')?.trim() ||
|
|
149
|
+
'Dismiss'
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
124
153
|
/**
|
|
125
154
|
* @typedef {object} ToastOpts
|
|
126
155
|
* @property {'accent' | 'success' | 'warning' | 'danger' | 'info'} [tone] Status tone — maps to `ui-toast--<tone>`.
|
|
@@ -128,6 +157,7 @@ function addToastClose(el, dismiss) {
|
|
|
128
157
|
* @property {number} [duration] Auto-dismiss delay in ms. `0` keeps it until dismissed. Default: `4000`.
|
|
129
158
|
* @property {boolean} [assertive] Route to the assertive live region so AT interrupts immediately. Defaults to `true` when `tone === 'danger'`.
|
|
130
159
|
* @property {boolean} [closable] Render a dismiss button on the toast.
|
|
160
|
+
* @property {string} [dismissLabel] Accessible label for the generated dismiss button. Default: `Dismiss`.
|
|
131
161
|
*/
|
|
132
162
|
|
|
133
163
|
/**
|
|
@@ -147,7 +177,10 @@ function addToastClose(el, dismiss) {
|
|
|
147
177
|
* @param {ToastOpts} [opts]
|
|
148
178
|
* @returns {import('./internal.js').Cleanup}
|
|
149
179
|
*/
|
|
150
|
-
export function toast(
|
|
180
|
+
export function toast(
|
|
181
|
+
message,
|
|
182
|
+
{ tone, title, duration = 4000, assertive, closable, dismissLabel } = {},
|
|
183
|
+
) {
|
|
151
184
|
if (!hasDom()) return noop;
|
|
152
185
|
// Errors must interrupt: danger toasts (or an explicit `assertive`)
|
|
153
186
|
// go to a SEPARATE assertive region so they announce immediately,
|
|
@@ -157,6 +190,7 @@ export function toast(message, { tone, title, duration = 4000, assertive, closab
|
|
|
157
190
|
const isAssertive = assertive ?? tone === 'danger';
|
|
158
191
|
const { stack, fresh: freshStack } = toastStack(isAssertive);
|
|
159
192
|
const el = toastElement(message, { tone, title });
|
|
193
|
+
const normalizedDuration = normalizeToastDuration(duration);
|
|
160
194
|
// Append after a frame the *first* time so the empty live region is
|
|
161
195
|
// observed by AT before its first child arrives; once the region has
|
|
162
196
|
// been observed, later toasts append synchronously.
|
|
@@ -185,12 +219,14 @@ export function toast(message, { tone, title, duration = 4000, assertive, closab
|
|
|
185
219
|
// Explicitly opting OUT of the close button on a sticky toast strands it with
|
|
186
220
|
// no in-UI dismissal; warn that the caller must retain and call the returned
|
|
187
221
|
// dismiss function.
|
|
188
|
-
if (
|
|
222
|
+
if (normalizedDuration === 0 && closable === false && typeof console !== 'undefined') {
|
|
189
223
|
console.warn(
|
|
190
224
|
'[bronto] toast(): duration:0 + closable:false has no in-UI dismissal — keep the returned dismiss() and call it yourself, or set closable:true.',
|
|
191
225
|
);
|
|
192
226
|
}
|
|
193
|
-
if (closable ??
|
|
194
|
-
|
|
227
|
+
if (closable ?? normalizedDuration === 0) {
|
|
228
|
+
addToastClose(el, dismiss, toastDismissLabel(stack, dismissLabel));
|
|
229
|
+
}
|
|
230
|
+
if (normalizedDuration > 0) timer = setTimeout(dismiss, normalizedDuration);
|
|
195
231
|
return dismiss;
|
|
196
232
|
}
|
package/classes/classes.json
CHANGED
|
@@ -2754,6 +2754,30 @@
|
|
|
2754
2754
|
"behavior": "initCommand",
|
|
2755
2755
|
"note": "wires the filter input + active-option keyboard model"
|
|
2756
2756
|
},
|
|
2757
|
+
{
|
|
2758
|
+
"name": "data-bronto-carousel-roledescription",
|
|
2759
|
+
"on": "a .ui-carousel host",
|
|
2760
|
+
"behavior": "initCarousel",
|
|
2761
|
+
"note": "localized override for the carousel aria-roledescription; the behavior applies its English default only when this attribute and any authored aria-roledescription are absent."
|
|
2762
|
+
},
|
|
2763
|
+
{
|
|
2764
|
+
"name": "data-bronto-carousel-slide-roledescription",
|
|
2765
|
+
"on": "a .ui-carousel host (applies to each slide)",
|
|
2766
|
+
"behavior": "initCarousel",
|
|
2767
|
+
"note": "localized override for the per-slide aria-roledescription; an authored slide aria-roledescription is preserved and the English \"slide\" default applies only when both are absent."
|
|
2768
|
+
},
|
|
2769
|
+
{
|
|
2770
|
+
"name": "data-bronto-error-summary-title",
|
|
2771
|
+
"on": "a form/error-summary host enhanced by initFormValidation",
|
|
2772
|
+
"behavior": "initFormValidation",
|
|
2773
|
+
"note": "localized heading for the generated validation error summary; an authored title or this attribute is preserved, English is only the fallback."
|
|
2774
|
+
},
|
|
2775
|
+
{
|
|
2776
|
+
"name": "data-bronto-toast-dismiss-label",
|
|
2777
|
+
"on": "the toast host (or via toast() options)",
|
|
2778
|
+
"behavior": "toast",
|
|
2779
|
+
"note": "localized aria-label for the generated toast dismiss button; defaults to the English 'Dismiss' only when absent."
|
|
2780
|
+
},
|
|
2757
2781
|
{
|
|
2758
2782
|
"name": "data-bronto-sources",
|
|
2759
2783
|
"on": "a source/citation island",
|
package/classes/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export type ClassValue =
|
|
|
10
10
|
| boolean
|
|
11
11
|
| null
|
|
12
12
|
| undefined
|
|
13
|
-
| ClassValue[];
|
|
13
|
+
| readonly ClassValue[];
|
|
14
14
|
|
|
15
15
|
/** The flat registry of every class @ponchia/ui defines (literal). */
|
|
16
16
|
export declare const cls: {
|
|
@@ -661,7 +661,7 @@ export declare const cls: {
|
|
|
661
661
|
};
|
|
662
662
|
|
|
663
663
|
/** classnames-style joiner: skips falsy, flattens arrays. */
|
|
664
|
-
export declare function cx(...parts: ClassValue[]): string;
|
|
664
|
+
export declare function cx(...parts: readonly ClassValue[]): string;
|
|
665
665
|
|
|
666
666
|
export interface ButtonOpts {
|
|
667
667
|
variant?: 'ghost' | 'subtle' | 'danger';
|
|
@@ -715,6 +715,7 @@ export interface DotgridOpts {
|
|
|
715
715
|
export interface TableOpts {
|
|
716
716
|
density?: 'dense' | 'comfortable';
|
|
717
717
|
lined?: boolean;
|
|
718
|
+
breakAnywhere?: boolean;
|
|
718
719
|
}
|
|
719
720
|
export interface EyebrowOpts {
|
|
720
721
|
muted?: boolean;
|
package/classes/index.js
CHANGED
|
@@ -703,50 +703,70 @@ export const cls = Object.freeze({
|
|
|
703
703
|
themetoggleThumb: 'ui-themetoggle__thumb',
|
|
704
704
|
});
|
|
705
705
|
|
|
706
|
-
/**
|
|
706
|
+
/**
|
|
707
|
+
* Mirrors clsx's permissive input: `number`/`boolean` accepted so guarded class
|
|
708
|
+
* expressions type-check; readonly arrays/tuples flatten the same as mutable ones.
|
|
709
|
+
* @typedef {string | number | boolean | null | undefined | ReadonlyArray<ClassValue>} ClassValue
|
|
710
|
+
*/
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* classnames-style joiner: skips falsy, flattens nested arrays of any depth.
|
|
714
|
+
* @param {...ClassValue} parts
|
|
715
|
+
* @returns {string}
|
|
716
|
+
*/
|
|
707
717
|
export function cx(...parts) {
|
|
708
718
|
const out = [];
|
|
709
|
-
for (const p of parts.flat(Infinity)) if (p) out.push(p);
|
|
719
|
+
for (const p of parts.flat(Infinity)) if (p && typeof p !== 'boolean') out.push(p);
|
|
710
720
|
return out.join(' ');
|
|
711
721
|
}
|
|
712
722
|
|
|
713
723
|
const j = (...p) => p.filter(Boolean).join(' ');
|
|
724
|
+
const valueClass = (map, value) => (value == null || !Object.hasOwn(map, value) ? '' : map[value]);
|
|
714
725
|
|
|
715
726
|
// Lifecycle state → canonical tone class.
|
|
716
727
|
const stateTone = (state) =>
|
|
717
|
-
(
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
728
|
+
valueClass(
|
|
729
|
+
{
|
|
730
|
+
saving: cls.stateSaving,
|
|
731
|
+
saved: cls.stateSaved,
|
|
732
|
+
queued: cls.stateQueued,
|
|
733
|
+
offline: cls.stateOffline,
|
|
734
|
+
stale: cls.stateStale,
|
|
735
|
+
conflict: cls.stateConflict,
|
|
736
|
+
error: cls.stateError,
|
|
737
|
+
locked: cls.stateLocked,
|
|
738
|
+
reviewed: cls.stateReviewed,
|
|
739
|
+
'needs-review': cls.stateNeedsReview,
|
|
740
|
+
},
|
|
741
|
+
state,
|
|
742
|
+
);
|
|
729
743
|
|
|
730
744
|
const jobTone = (state) =>
|
|
731
|
-
(
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
745
|
+
valueClass(
|
|
746
|
+
{
|
|
747
|
+
queued: cls.jobQueued,
|
|
748
|
+
running: cls.jobRunning,
|
|
749
|
+
blocked: cls.jobBlocked,
|
|
750
|
+
failed: cls.jobFailed,
|
|
751
|
+
complete: cls.jobComplete,
|
|
752
|
+
},
|
|
753
|
+
state,
|
|
754
|
+
);
|
|
738
755
|
|
|
739
756
|
// Trust-state → tone class, shared by the source/citation/provenance recipes.
|
|
740
|
-
//
|
|
757
|
+
// Own-property object-literal lookup to match stateTone above.
|
|
741
758
|
const srcTone = (state) =>
|
|
742
|
-
(
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
759
|
+
valueClass(
|
|
760
|
+
{
|
|
761
|
+
verified: cls.srcVerified,
|
|
762
|
+
unverified: cls.srcUnverified,
|
|
763
|
+
generated: cls.srcGenerated,
|
|
764
|
+
reviewed: cls.srcReviewed,
|
|
765
|
+
stale: cls.srcStale,
|
|
766
|
+
conflict: cls.srcConflict,
|
|
767
|
+
},
|
|
768
|
+
state,
|
|
769
|
+
);
|
|
750
770
|
|
|
751
771
|
// Component tone → modifier class. Same object-literal idiom as srcTone/stateTone
|
|
752
772
|
// while keeping modifier classes grep-friendly.
|
|
@@ -759,13 +779,13 @@ const srcTone = (state) =>
|
|
|
759
779
|
// is fine and returns no modifier.
|
|
760
780
|
const toneClass = (component, map, tone) => {
|
|
761
781
|
if (tone == null) return '';
|
|
762
|
-
const hit = map
|
|
782
|
+
const hit = valueClass(map, tone);
|
|
763
783
|
if (!hit && typeof console !== 'undefined') {
|
|
764
784
|
console.warn(
|
|
765
785
|
`[bronto] ui.${component}(): "${tone}" is not a ${component} tone (use one of: ${Object.keys(map).join(', ')}).`,
|
|
766
786
|
);
|
|
767
787
|
}
|
|
768
|
-
return hit
|
|
788
|
+
return hit;
|
|
769
789
|
};
|
|
770
790
|
|
|
771
791
|
const badgeTone = (tone) =>
|
|
@@ -862,8 +882,6 @@ const claimStatus = (status) =>
|
|
|
862
882
|
status,
|
|
863
883
|
);
|
|
864
884
|
|
|
865
|
-
const valueClass = (map, value) => (value == null ? '' : map[value] || '');
|
|
866
|
-
|
|
867
885
|
const annotationVariants = Object.freeze({
|
|
868
886
|
label: cls.annotationLabelVariant,
|
|
869
887
|
callout: cls.annotationCallout,
|
|
@@ -899,6 +917,13 @@ const annotationMotions = Object.freeze({
|
|
|
899
917
|
focus: cls.annotationFocus,
|
|
900
918
|
});
|
|
901
919
|
|
|
920
|
+
/**
|
|
921
|
+
* @typedef {object} TableOpts
|
|
922
|
+
* @property {'dense' | 'comfortable'} [density] Density modifier.
|
|
923
|
+
* @property {boolean} [lined] Add row separator lines.
|
|
924
|
+
* @property {boolean} [breakAnywhere] Allow long unspaced cell content to wrap instead of overflowing.
|
|
925
|
+
*/
|
|
926
|
+
|
|
902
927
|
export const ui = {
|
|
903
928
|
button: ({ variant, icon, size } = {}) =>
|
|
904
929
|
j(
|
|
@@ -930,6 +955,7 @@ export const ui = {
|
|
|
930
955
|
dot: ({ tone, live } = {}) => j(cls.dot, dotTone(tone), live && cls.dotLive),
|
|
931
956
|
dotgrid: ({ accent, dense } = {}) =>
|
|
932
957
|
j(cls.dotgrid, accent && cls.dotgridAccent, dense && cls.dotgridDense),
|
|
958
|
+
/** @type {(opts?: TableOpts) => string} */
|
|
933
959
|
table: ({ density, lined, breakAnywhere } = {}) =>
|
|
934
960
|
j(
|
|
935
961
|
cls.table,
|
|
@@ -1078,9 +1104,19 @@ export const ui = {
|
|
|
1078
1104
|
// unknown; a meter is never indeterminate so it passes false. (Kept a boolean
|
|
1079
1105
|
// flag rather than testing the role string, so check:recipe-types doesn't read it
|
|
1080
1106
|
// as a recipe option literal.)
|
|
1081
|
-
const valueAttrs = (role, value, min, max, busyWhenIndeterminate) => {
|
|
1107
|
+
const valueAttrs = (component, role, value, min, max, busyWhenIndeterminate) => {
|
|
1082
1108
|
const lo = Number(min);
|
|
1083
1109
|
const hi = Number(max);
|
|
1110
|
+
const validRange = Number.isFinite(lo) && Number.isFinite(hi) && hi > lo;
|
|
1111
|
+
if (!validRange) {
|
|
1112
|
+
if (typeof console !== 'undefined') {
|
|
1113
|
+
console.warn(
|
|
1114
|
+
`[bronto] attrs.${component}(): invalid range (expected finite min/max with max > min); omitting value ARIA.`,
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
return busyWhenIndeterminate ? { role, 'aria-busy': 'true' } : { role };
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1084
1120
|
const raw = Number(value);
|
|
1085
1121
|
// Indeterminate: an omitted/unknown value (attrs.progress() with no argument).
|
|
1086
1122
|
// ARIA requires aria-valuenow be OMITTED here — emitting 0 announces "0%",
|
|
@@ -1093,7 +1129,7 @@ const valueAttrs = (role, value, min, max, busyWhenIndeterminate) => {
|
|
|
1093
1129
|
return busyWhenIndeterminate ? { role, 'aria-busy': 'true' } : { role };
|
|
1094
1130
|
}
|
|
1095
1131
|
const now = Math.min(hi, Math.max(lo, raw));
|
|
1096
|
-
const pct =
|
|
1132
|
+
const pct = ((now - lo) / (hi - lo)) * 100;
|
|
1097
1133
|
return {
|
|
1098
1134
|
role,
|
|
1099
1135
|
'aria-valuenow': now,
|
|
@@ -1119,10 +1155,12 @@ const valueAttrs = (role, value, min, max, busyWhenIndeterminate) => {
|
|
|
1119
1155
|
* call with no value for the indeterminate sweep.
|
|
1120
1156
|
*/
|
|
1121
1157
|
export const attrs = Object.freeze({
|
|
1122
|
-
meter: (value, { min = 0, max = 100 } = {}) =>
|
|
1158
|
+
meter: (value, { min = 0, max = 100 } = {}) =>
|
|
1159
|
+
valueAttrs('meter', 'meter', value, min, max, false),
|
|
1123
1160
|
progress: (value, { min = 0, max = 100 } = {}) =>
|
|
1124
|
-
valueAttrs('progressbar', value, min, max, true),
|
|
1125
|
-
dotbar: (value, { min = 0, max = 100 } = {}) =>
|
|
1161
|
+
valueAttrs('progress', 'progressbar', value, min, max, true),
|
|
1162
|
+
dotbar: (value, { min = 0, max = 100 } = {}) =>
|
|
1163
|
+
valueAttrs('dotbar', 'progressbar', value, min, max, true),
|
|
1126
1164
|
});
|
|
1127
1165
|
|
|
1128
1166
|
export default ui;
|
package/connectors/index.d.ts
CHANGED
|
@@ -80,10 +80,10 @@ export function curvePath(from: Point, to: Point, opts?: {
|
|
|
80
80
|
}): string;
|
|
81
81
|
/**
|
|
82
82
|
* Build a path between two points by `shape` (`straight` | `elbow` | `curve`).
|
|
83
|
-
* @param {ConnectorPathOptions}
|
|
83
|
+
* @param {ConnectorPathOptions} opts
|
|
84
84
|
* @returns {string}
|
|
85
85
|
*/
|
|
86
|
-
export function connectorPath(opts
|
|
86
|
+
export function connectorPath(opts: ConnectorPathOptions): string;
|
|
87
87
|
/**
|
|
88
88
|
* A filled triangle arrowhead at `p`, pointing along `angle` (radians).
|
|
89
89
|
* @param {Point} p
|
|
@@ -136,10 +136,10 @@ export function endTangentAngle(from: Point, to: Point, shape?: ConnectorShape):
|
|
|
136
136
|
* Connect two rects. Resolves anchor points (explicit `fromSide`/`toSide`, else
|
|
137
137
|
* auto), builds the path, and returns `{ d, from, to, angle }` so the caller can
|
|
138
138
|
* place an arrowhead/dot at `to` rotated by `angle`.
|
|
139
|
-
* @param {ConnectRectsOptions}
|
|
139
|
+
* @param {ConnectRectsOptions} opts
|
|
140
140
|
* @returns {ConnectRectsResult}
|
|
141
141
|
*/
|
|
142
|
-
export function connectRects(opts
|
|
142
|
+
export function connectRects(opts: ConnectRectsOptions): ConnectRectsResult;
|
|
143
143
|
/**
|
|
144
144
|
* @ponchia/ui/connectors — dependency-free SVG geometry for connecting two
|
|
145
145
|
* elements (or two points) with a leader line.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":"AAiDA;;;;;;GAMG;AACH,6BALW,MAAM,SACN,MAAM,GAAG,IAAI,GAAG,SAAS,aACzB,MAAM,GAAG,IAAI,GAAG,SAAS,GACvB,MAAM,CAMlB;AAED;;;;;;GAMG;AACH,gCALW,MAAM,SACN,MAAM,GAAG,IAAI,GAAG,SAAS,aACzB,MAAM,GAAG,IAAI,GAAG,SAAS,GACvB,MAAM,CAMlB;AAID;;;GAGG;AACH,mCAHW,MAAM,GACJ,MAAM,CAKlB;AAED;;;GAGG;AACH,2BAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,yBAJW,MAAM,KACN,MAAM,GACJ,MAAM,CAIlB;AAGD;;;;;GAKG;AACH,6BALW,MAAM,OACN,MAAM,OACN,MAAM,GACJ,MAAM,CAKlB;AAqBD;;;;;GAKG;AACH,kCAJW,IAAI,SACJ,IAAI,GACF,KAAK,CAoBjB;AAED;;;;;GAKG;AACH,mCAJW,KAAK,MACL,KAAK,GACH,MAAM,CAOlB;AAED;;;;;GAKG;AACH,mCAJW,KAAK,MACL,KAAK,GACH,MAAM,CAOlB;AAED;;;;;;GAMG;AACH,gCALW,KAAK,MACL,KAAK,SACL;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACd,MAAM,CAgBlB;AAED;;;;;;GAMG;AACH,gCALW,KAAK,MACL,KAAK,SACL;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACpB,MAAM,CAclB;AAED;;;;GAIG;AACH,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":"AAiDA;;;;;;GAMG;AACH,6BALW,MAAM,SACN,MAAM,GAAG,IAAI,GAAG,SAAS,aACzB,MAAM,GAAG,IAAI,GAAG,SAAS,GACvB,MAAM,CAMlB;AAED;;;;;;GAMG;AACH,gCALW,MAAM,SACN,MAAM,GAAG,IAAI,GAAG,SAAS,aACzB,MAAM,GAAG,IAAI,GAAG,SAAS,GACvB,MAAM,CAMlB;AAID;;;GAGG;AACH,mCAHW,MAAM,GACJ,MAAM,CAKlB;AAED;;;GAGG;AACH,2BAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,yBAJW,MAAM,KACN,MAAM,GACJ,MAAM,CAIlB;AAGD;;;;;GAKG;AACH,6BALW,MAAM,OACN,MAAM,OACN,MAAM,GACJ,MAAM,CAKlB;AAqBD;;;;;GAKG;AACH,kCAJW,IAAI,SACJ,IAAI,GACF,KAAK,CAoBjB;AAED;;;;;GAKG;AACH,mCAJW,KAAK,MACL,KAAK,GACH,MAAM,CAOlB;AAED;;;;;GAKG;AACH,mCAJW,KAAK,MACL,KAAK,GACH,MAAM,CAOlB;AAED;;;;;;GAMG;AACH,gCALW,KAAK,MACL,KAAK,SACL;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACd,MAAM,CAgBlB;AAED;;;;;;GAMG;AACH,gCALW,KAAK,MACL,KAAK,SACL;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACpB,MAAM,CAclB;AAED;;;;GAIG;AACH,oCAHW,oBAAoB,GAClB,MAAM,CASlB;AAED;;;;;;;;GAQG;AACH,6BAPW,KAAK,SACL,MAAM,SACN,MAAM,WACN,MAAM,GAEJ,MAAM,CAalB;AAED;;;;;GAKG;AACH,2BAJW,KAAK,WACL,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;;;GASG;AACH,+BANW,MAAM,OACN,MAAM,SACN,MAAM,UACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;GAKG;AACH,oCAJW,IAAI,UACJ,IAAI,GACF;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,IAAI,CAAA;CAAE,CAWpC;AAED;;;;;;;;GAQG;AACH,sCALW,KAAK,MACL,KAAK,UACL,cAAc,GACZ,MAAM,CASlB;AAED;;;;;;GAMG;AACH,mCAHW,mBAAmB,GACjB,kBAAkB,CAgB9B;AAhWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAKH,wBAAyB,IAAI,CAAC;oBA/BjB;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE;mBACxB;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;mBACvD,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ;6BAC9C,UAAU,GAAG,OAAO,GAAG,OAAO;;UAG7B,KAAK;QACL,KAAK;;;;;;;;;;;;cAML,IAAI;YACJ,IAAI;;;;;;;;;;;;;;OAQJ,MAAM;UACN,KAAK;QACL,KAAK;;;;WACL,MAAM"}
|
package/connectors/index.js
CHANGED
|
@@ -230,14 +230,15 @@ export function curvePath(from, to, opts = {}) {
|
|
|
230
230
|
|
|
231
231
|
/**
|
|
232
232
|
* Build a path between two points by `shape` (`straight` | `elbow` | `curve`).
|
|
233
|
-
* @param {ConnectorPathOptions}
|
|
233
|
+
* @param {ConnectorPathOptions} opts
|
|
234
234
|
* @returns {string}
|
|
235
235
|
*/
|
|
236
|
-
export function connectorPath(opts
|
|
237
|
-
const
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
if (shape === '
|
|
236
|
+
export function connectorPath(opts) {
|
|
237
|
+
const options = opts ?? {};
|
|
238
|
+
const { from, to } = options;
|
|
239
|
+
const shape = connectorShape(options.shape);
|
|
240
|
+
if (shape === 'elbow') return elbowPath(from, to, options);
|
|
241
|
+
if (shape === 'curve') return curvePath(from, to, options);
|
|
241
242
|
return straightPath(from, to);
|
|
242
243
|
}
|
|
243
244
|
|
|
@@ -332,17 +333,18 @@ export function endTangentAngle(from, to, shape = 'straight') {
|
|
|
332
333
|
* Connect two rects. Resolves anchor points (explicit `fromSide`/`toSide`, else
|
|
333
334
|
* auto), builds the path, and returns `{ d, from, to, angle }` so the caller can
|
|
334
335
|
* place an arrowhead/dot at `to` rotated by `angle`.
|
|
335
|
-
* @param {ConnectRectsOptions}
|
|
336
|
+
* @param {ConnectRectsOptions} opts
|
|
336
337
|
* @returns {ConnectRectsResult}
|
|
337
338
|
*/
|
|
338
|
-
export function connectRects(opts
|
|
339
|
-
const
|
|
340
|
-
const
|
|
339
|
+
export function connectRects(opts) {
|
|
340
|
+
const options = opts ?? {};
|
|
341
|
+
const { fromRect, toRect, curvature, mid } = options;
|
|
342
|
+
const shape = connectorShape(options.shape);
|
|
341
343
|
// Honor each side override independently; auto-pick whichever is unset.
|
|
342
344
|
const auto = autoSides(fromRect, toRect);
|
|
343
345
|
const sides = {
|
|
344
|
-
from:
|
|
345
|
-
to:
|
|
346
|
+
from: options.fromSide == null ? auto.from : sideValue(options.fromSide),
|
|
347
|
+
to: options.toSide == null ? auto.to : sideValue(options.toSide),
|
|
346
348
|
};
|
|
347
349
|
const from = anchorPoint(fromRect, sides.from);
|
|
348
350
|
const to = anchorPoint(toRect, sides.to);
|
package/css/annotations.css
CHANGED
package/css/app.css
CHANGED
|
@@ -184,6 +184,13 @@
|
|
|
184
184
|
z-index: var(--z-raised);
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
+
@media (prefers-reduced-transparency: reduce) {
|
|
188
|
+
.ui-app-topbar {
|
|
189
|
+
backdrop-filter: none;
|
|
190
|
+
background: var(--surface-1);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
187
194
|
.ui-app-topbar__title {
|
|
188
195
|
color: var(--text);
|
|
189
196
|
font-family: var(--display);
|
package/css/base.css
CHANGED
|
@@ -267,6 +267,7 @@ textarea:focus-visible,
|
|
|
267
267
|
.ui-dotloader,
|
|
268
268
|
.ui-dotspinner,
|
|
269
269
|
dialog.ui-modal::backdrop {
|
|
270
|
+
/* Intentional !important: print chrome must stay hidden across component display rules. */
|
|
270
271
|
display: none !important;
|
|
271
272
|
}
|
|
272
273
|
|
|
@@ -274,6 +275,7 @@ textarea:focus-visible,
|
|
|
274
275
|
*,
|
|
275
276
|
*::before,
|
|
276
277
|
*::after {
|
|
278
|
+
/* Intentional !important: print output drops decorative shadows globally. */
|
|
277
279
|
box-shadow: none !important;
|
|
278
280
|
text-shadow: none !important;
|
|
279
281
|
}
|
|
@@ -291,6 +293,7 @@ textarea:focus-visible,
|
|
|
291
293
|
.ui-prose table,
|
|
292
294
|
.ui-tabs__list,
|
|
293
295
|
pre {
|
|
296
|
+
/* Intentional !important: print must spill scroll containers even if component rules clip. */
|
|
294
297
|
overflow: visible !important;
|
|
295
298
|
}
|
|
296
299
|
|