@ponchia/ui 0.6.7 → 0.6.9
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 +129 -4
- package/README.md +4 -4
- package/annotations/index.d.ts.map +1 -1
- package/annotations/index.js +26 -9
- package/behaviors/carousel.d.ts.map +1 -1
- package/behaviors/carousel.js +145 -49
- package/behaviors/combobox.d.ts.map +1 -1
- package/behaviors/combobox.js +220 -92
- package/behaviors/command.d.ts.map +1 -1
- package/behaviors/command.js +74 -14
- package/behaviors/connectors.d.ts.map +1 -1
- package/behaviors/connectors.js +131 -32
- package/behaviors/crosshair.d.ts.map +1 -1
- package/behaviors/crosshair.js +47 -1
- package/behaviors/dialog.d.ts.map +1 -1
- package/behaviors/dialog.js +24 -9
- package/behaviors/disclosure.d.ts.map +1 -1
- package/behaviors/disclosure.js +33 -3
- package/behaviors/dismissible.d.ts.map +1 -1
- package/behaviors/dismissible.js +3 -2
- package/behaviors/forms.d.ts.map +1 -1
- package/behaviors/forms.js +211 -140
- package/behaviors/glyph.d.ts.map +1 -1
- package/behaviors/glyph.js +172 -132
- package/behaviors/inert.d.ts +1 -1
- package/behaviors/inert.d.ts.map +1 -1
- package/behaviors/inert.js +4 -3
- package/behaviors/internal.d.ts.map +1 -1
- package/behaviors/internal.js +4 -3
- package/behaviors/legend.d.ts +0 -5
- package/behaviors/legend.d.ts.map +1 -1
- package/behaviors/legend.js +45 -13
- package/behaviors/menu.d.ts.map +1 -1
- package/behaviors/menu.js +13 -8
- package/behaviors/modal.d.ts.map +1 -1
- package/behaviors/modal.js +77 -19
- package/behaviors/popover.d.ts +4 -3
- package/behaviors/popover.d.ts.map +1 -1
- package/behaviors/popover.js +94 -14
- package/behaviors/sources.d.ts.map +1 -1
- package/behaviors/sources.js +14 -2
- package/behaviors/splitter.d.ts.map +1 -1
- package/behaviors/splitter.js +149 -110
- package/behaviors/spotlight.d.ts.map +1 -1
- package/behaviors/spotlight.js +28 -2
- package/behaviors/table.d.ts +1 -1
- package/behaviors/table.d.ts.map +1 -1
- package/behaviors/table.js +108 -17
- package/behaviors/tabs.d.ts.map +1 -1
- package/behaviors/tabs.js +84 -20
- package/behaviors/theme.d.ts.map +1 -1
- package/behaviors/theme.js +25 -5
- package/behaviors/toast.js +5 -5
- package/classes/index.d.ts +15 -2
- package/classes/index.js +48 -35
- package/connectors/index.d.ts +41 -8
- package/connectors/index.d.ts.map +1 -1
- package/connectors/index.js +74 -19
- package/css/annotations.css +12 -0
- package/css/app.css +3 -4
- package/css/base.css +1 -1
- package/css/content.css +3 -3
- package/css/crosshair.css +27 -2
- package/css/disclosure.css +3 -3
- package/css/dots.css +4 -4
- package/css/feedback.css +8 -37
- package/css/forms.css +9 -12
- package/css/legend.css +1 -1
- package/css/marks.css +1 -1
- package/css/motion.css +6 -6
- package/css/navigation.css +12 -0
- package/css/overlay.css +5 -7
- package/css/primitives.css +14 -16
- package/css/sidenote.css +2 -2
- package/css/table.css +2 -2
- package/css/tokens.css +16 -0
- package/dist/bronto.css +1 -1
- package/dist/css/analytical.css +1 -1
- package/dist/css/annotations.css +1 -1
- package/dist/css/crosshair.css +1 -1
- package/dist/css/feedback.css +1 -1
- package/dist/css/navigation.css +1 -1
- package/dist/css/report-kit.css +1 -1
- package/dist/css/tokens.css +1 -1
- package/docs/adr/0001-color-system.md +3 -2
- package/docs/annotations.md +21 -1
- package/docs/architecture.md +74 -13
- package/docs/command.md +4 -1
- package/docs/connectors.md +16 -0
- package/docs/crosshair.md +1 -1
- package/docs/dots.md +4 -1
- package/docs/glyphs.md +11 -0
- package/docs/interop/react-flow.md +89 -0
- package/docs/migrations/0.2-to-0.3.md +1 -1
- package/docs/package-contract.md +7 -5
- package/docs/reporting.md +23 -12
- package/docs/stability.md +85 -9
- package/docs/theming.md +2 -2
- package/docs/usage.md +16 -2
- package/docs/vega.md +4 -4
- package/glyphs/glyphs.js +43 -33
- package/llms.txt +19 -8
- package/package.json +23 -4
- package/schemas/report-claims.v1.schema.json +1 -1
- package/svelte/index.d.ts +71 -45
- package/svelte/index.d.ts.map +1 -1
- package/svelte/index.js +29 -2
- package/tokens/index.js +2 -2
- package/vue/index.d.ts +42 -5
- package/vue/index.d.ts.map +1 -1
- package/vue/index.js +32 -1
package/behaviors/tabs.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
hasDom,
|
|
3
|
+
resolveHost,
|
|
4
|
+
noop,
|
|
5
|
+
bindOnce,
|
|
6
|
+
nextFieldUid,
|
|
7
|
+
collectHosts,
|
|
8
|
+
closestSafe,
|
|
9
|
+
} from './internal.js';
|
|
2
10
|
|
|
3
11
|
/**
|
|
4
12
|
* Wire `[data-bronto-tabs]` groups for full keyboard a11y. The framework
|
|
@@ -24,6 +32,23 @@ export function initTabs({ root } = {}) {
|
|
|
24
32
|
if (!host) return noop;
|
|
25
33
|
const cleanups = [];
|
|
26
34
|
const groups = collectHosts(host, '[data-bronto-tabs]');
|
|
35
|
+
const snapshotAttrs = (el, names) => {
|
|
36
|
+
const out = {};
|
|
37
|
+
for (const name of names) {
|
|
38
|
+
out[name] = {
|
|
39
|
+
had: el.hasAttribute(name),
|
|
40
|
+
value: el.getAttribute(name),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
};
|
|
45
|
+
const restoreAttrs = (el, attrs) => {
|
|
46
|
+
for (const [name, attr] of Object.entries(attrs)) {
|
|
47
|
+
if (attr.had) el.setAttribute(name, attr.value);
|
|
48
|
+
else el.removeAttribute(name);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
27
52
|
for (const group of groups) {
|
|
28
53
|
// Own group only — a tab/panel inside a nested [data-bronto-tabs]
|
|
29
54
|
// belongs to that inner group, not this one.
|
|
@@ -31,20 +56,43 @@ export function initTabs({ root } = {}) {
|
|
|
31
56
|
const tabs = [...group.querySelectorAll('.ui-tab')].filter(owned);
|
|
32
57
|
const panels = [...group.querySelectorAll('.ui-tabs__panel')].filter(owned);
|
|
33
58
|
if (!tabs.length) continue;
|
|
34
|
-
const list = group.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
59
|
+
const list = [...group.querySelectorAll('.ui-tabs__list')].find(owned);
|
|
60
|
+
const rememberState = () => ({
|
|
61
|
+
list: list ? snapshotAttrs(list, ['role']) : null,
|
|
62
|
+
tabs: new Map(
|
|
63
|
+
tabs.map((tab) => [
|
|
64
|
+
tab,
|
|
65
|
+
{
|
|
66
|
+
active: tab.classList.contains('is-active'),
|
|
67
|
+
attrs: snapshotAttrs(tab, ['id', 'role', 'aria-selected', 'aria-controls', 'tabindex']),
|
|
68
|
+
},
|
|
69
|
+
]),
|
|
70
|
+
),
|
|
71
|
+
panels: new Map(
|
|
72
|
+
panels.map((panel) => [
|
|
73
|
+
panel,
|
|
74
|
+
{
|
|
75
|
+
hidden: panel.hidden,
|
|
76
|
+
attrs: snapshotAttrs(panel, ['id', 'role', 'aria-labelledby', 'tabindex']),
|
|
77
|
+
},
|
|
78
|
+
]),
|
|
79
|
+
),
|
|
80
|
+
});
|
|
81
|
+
const restoreState = (state) => {
|
|
82
|
+
if (list && state.list) restoreAttrs(list, state.list);
|
|
83
|
+
for (const tab of tabs) {
|
|
84
|
+
const tabState = state.tabs.get(tab);
|
|
85
|
+
if (!tabState) continue;
|
|
86
|
+
tab.classList.toggle('is-active', tabState.active);
|
|
87
|
+
restoreAttrs(tab, tabState.attrs);
|
|
88
|
+
}
|
|
89
|
+
for (const panel of panels) {
|
|
90
|
+
const panelState = state.panels.get(panel);
|
|
91
|
+
if (!panelState) continue;
|
|
92
|
+
panel.hidden = panelState.hidden;
|
|
93
|
+
restoreAttrs(panel, panelState.attrs);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
48
96
|
|
|
49
97
|
const select = (tab) => {
|
|
50
98
|
for (const t of tabs) {
|
|
@@ -55,14 +103,14 @@ export function initTabs({ root } = {}) {
|
|
|
55
103
|
t.tabIndex = on ? 0 : -1;
|
|
56
104
|
}
|
|
57
105
|
// Only retarget panels when this tab actually controls one. A panel-less
|
|
58
|
-
// tab must
|
|
106
|
+
// tab must not hide every panel; leave the prior panel visible.
|
|
59
107
|
if (!panels.some((p) => p.dataset.panel === tab.dataset.tab)) return;
|
|
60
108
|
for (const p of panels) {
|
|
61
109
|
p.setAttribute('role', 'tabpanel');
|
|
62
110
|
const shown = p.dataset.panel === tab.dataset.tab;
|
|
63
111
|
p.hidden = !shown;
|
|
64
112
|
// APG: a tabpanel is focusable so keyboard users can reach a text-only
|
|
65
|
-
// panel; hidden panels drop out of the tab order
|
|
113
|
+
// panel; hidden panels drop out of the tab order.
|
|
66
114
|
if (shown) p.tabIndex = 0;
|
|
67
115
|
else p.removeAttribute('tabindex');
|
|
68
116
|
}
|
|
@@ -70,14 +118,15 @@ export function initTabs({ root } = {}) {
|
|
|
70
118
|
const onClick = (e) => {
|
|
71
119
|
// `tabs` is filtered to this group, so membership (not mere DOM
|
|
72
120
|
// containment) is what isolates nested [data-bronto-tabs] groups.
|
|
73
|
-
const tab = e.target
|
|
121
|
+
const tab = closestSafe(e.target, '.ui-tab');
|
|
74
122
|
if (tab && tabs.includes(tab)) {
|
|
123
|
+
e.preventDefault();
|
|
75
124
|
select(tab);
|
|
76
125
|
tab.focus();
|
|
77
126
|
}
|
|
78
127
|
};
|
|
79
128
|
const onKey = (e) => {
|
|
80
|
-
const i = tabs.indexOf(e.target
|
|
129
|
+
const i = tabs.indexOf(closestSafe(e.target, '.ui-tab'));
|
|
81
130
|
if (i < 0) return;
|
|
82
131
|
let n = i;
|
|
83
132
|
if (e.key === 'ArrowRight' || e.key === 'ArrowDown') n = (i + 1) % tabs.length;
|
|
@@ -90,14 +139,29 @@ export function initTabs({ root } = {}) {
|
|
|
90
139
|
select(tabs[n]);
|
|
91
140
|
tabs[n].focus();
|
|
92
141
|
};
|
|
93
|
-
select(tabs.find((t) => t.classList.contains('is-active')) || tabs[0]);
|
|
94
142
|
cleanups.push(
|
|
95
143
|
bindOnce(group, 'tabs', () => {
|
|
144
|
+
const state = rememberState();
|
|
145
|
+
if (list) list.setAttribute('role', 'tablist');
|
|
146
|
+
|
|
147
|
+
// APG: bind each tab to its panel (aria-controls) and back
|
|
148
|
+
// (aria-labelledby), minting stable ids only where absent.
|
|
149
|
+
for (const t of tabs) {
|
|
150
|
+
const p = panels.find((x) => x.dataset.panel === t.dataset.tab);
|
|
151
|
+
if (!p) continue;
|
|
152
|
+
const n = nextFieldUid();
|
|
153
|
+
if (!t.id) t.id = `bronto-tab-${n}`;
|
|
154
|
+
if (!p.id) p.id = `bronto-tabpanel-${n}`;
|
|
155
|
+
t.setAttribute('aria-controls', p.id);
|
|
156
|
+
p.setAttribute('aria-labelledby', t.id);
|
|
157
|
+
}
|
|
158
|
+
select(tabs.find((t) => t.classList.contains('is-active')) || tabs[0]);
|
|
96
159
|
group.addEventListener('click', onClick);
|
|
97
160
|
group.addEventListener('keydown', onKey);
|
|
98
161
|
return () => {
|
|
99
162
|
group.removeEventListener('click', onClick);
|
|
100
163
|
group.removeEventListener('keydown', onKey);
|
|
164
|
+
restoreState(state);
|
|
101
165
|
};
|
|
102
166
|
}),
|
|
103
167
|
);
|
package/behaviors/theme.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["theme.js"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH;;;;;;;GAOG;AACH,wDAHW,cAAc,GACZ,IAAI,CAahB;AAED;;;;;;;;;;;;;;GAcG;AACH,uDAHW,gBAAgB,GAAG,OAAO,eAAe,EAAE,YAAY,GACrD,OAAO,eAAe,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["theme.js"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH;;;;;;;GAOG;AACH,wDAHW,cAAc,GACZ,IAAI,CAahB;AAED;;;;;;;;;;;;;;GAcG;AACH,uDAHW,gBAAgB,GAAG,OAAO,eAAe,EAAE,YAAY,GACrD,OAAO,eAAe,EAAE,OAAO,CAuE3C;;;;;;;;;;6BAhHY,gBAAgB,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE;;;;;WAIpC,OAAO,GAAG,MAAM"}
|
package/behaviors/theme.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { hasDom, resolveHost, noop, bindOnce, collectHosts } from './internal.js';
|
|
1
|
+
import { hasDom, resolveHost, noop, bindOnce, collectHosts, closestSafe } from './internal.js';
|
|
2
2
|
|
|
3
3
|
const THEMES = ['light', 'dark'];
|
|
4
4
|
|
|
@@ -53,7 +53,18 @@ export function initThemeToggle({ storageKey = 'bronto-theme', root } = {}) {
|
|
|
53
53
|
if (!hasDom()) return noop;
|
|
54
54
|
const host = resolveHost(root);
|
|
55
55
|
if (!host) return noop;
|
|
56
|
-
const
|
|
56
|
+
const doc = host.nodeType === 9 ? host : host.ownerDocument || document;
|
|
57
|
+
const docEl = doc.documentElement;
|
|
58
|
+
const toggleStates = new Map();
|
|
59
|
+
|
|
60
|
+
const rememberToggle = (el) => {
|
|
61
|
+
if (!toggleStates.has(el)) {
|
|
62
|
+
toggleStates.set(el, {
|
|
63
|
+
had: el.hasAttribute('aria-pressed'),
|
|
64
|
+
value: el.getAttribute('aria-pressed'),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
};
|
|
57
68
|
|
|
58
69
|
const prefersDark = () =>
|
|
59
70
|
typeof matchMedia === 'function' && matchMedia('(prefers-color-scheme: dark)').matches;
|
|
@@ -67,6 +78,7 @@ export function initThemeToggle({ storageKey = 'bronto-theme', root } = {}) {
|
|
|
67
78
|
const reflect = () => {
|
|
68
79
|
const c = current();
|
|
69
80
|
collectHosts(host, '[data-bronto-theme-toggle]').forEach((el) => {
|
|
81
|
+
rememberToggle(el);
|
|
70
82
|
const forced = el.getAttribute('data-bronto-theme-toggle');
|
|
71
83
|
// A forced control is "pressed" when its theme is the active one;
|
|
72
84
|
// a plain toggle reflects whether dark is active.
|
|
@@ -76,8 +88,9 @@ export function initThemeToggle({ storageKey = 'bronto-theme', root } = {}) {
|
|
|
76
88
|
};
|
|
77
89
|
|
|
78
90
|
const onClick = (e) => {
|
|
79
|
-
const trigger = e.target
|
|
91
|
+
const trigger = closestSafe(e.target, '[data-bronto-theme-toggle]');
|
|
80
92
|
if (!trigger || !host.contains(trigger)) return;
|
|
93
|
+
e.preventDefault();
|
|
81
94
|
const forced = trigger.getAttribute('data-bronto-theme-toggle');
|
|
82
95
|
const next = THEMES.includes(forced) ? forced : current() === 'dark' ? 'light' : 'dark';
|
|
83
96
|
docEl.setAttribute('data-theme', next);
|
|
@@ -92,10 +105,17 @@ export function initThemeToggle({ storageKey = 'bronto-theme', root } = {}) {
|
|
|
92
105
|
);
|
|
93
106
|
};
|
|
94
107
|
|
|
95
|
-
applyStoredTheme({ storageKey });
|
|
108
|
+
applyStoredTheme({ storageKey, root: docEl });
|
|
96
109
|
reflect();
|
|
97
110
|
return bindOnce(host, 'themeToggle', () => {
|
|
98
111
|
host.addEventListener('click', onClick);
|
|
99
|
-
return () =>
|
|
112
|
+
return () => {
|
|
113
|
+
host.removeEventListener('click', onClick);
|
|
114
|
+
for (const [el, state] of toggleStates) {
|
|
115
|
+
if (state.had) el.setAttribute('aria-pressed', state.value);
|
|
116
|
+
else el.removeAttribute('aria-pressed');
|
|
117
|
+
}
|
|
118
|
+
toggleStates.clear();
|
|
119
|
+
};
|
|
100
120
|
});
|
|
101
121
|
}
|
package/behaviors/toast.js
CHANGED
|
@@ -3,7 +3,7 @@ import { hasDom, noop } from './internal.js';
|
|
|
3
3
|
// The tones that have a `.ui-toast--*` rule. The TS type already unions these,
|
|
4
4
|
// but a plain-JS / LLM caller can pass any string — and an unknown tone built a
|
|
5
5
|
// `.ui-toast--error` class that matches no CSS, yielding a silent neutral toast.
|
|
6
|
-
// Validate so an unknown tone degrades to neutral *and warns*, never lies.
|
|
6
|
+
// Validate so an unknown tone degrades to neutral *and warns*, never lies.
|
|
7
7
|
const TOAST_TONES = new Set(['accent', 'success', 'warning', 'danger', 'info']);
|
|
8
8
|
|
|
9
9
|
// First-toast deferral queue. The very first toast on a brand-new stack
|
|
@@ -29,7 +29,7 @@ function toastStack(isAssertive) {
|
|
|
29
29
|
stack.setAttribute('role', 'alert');
|
|
30
30
|
// The assertive region carries one error at a time and must be read whole;
|
|
31
31
|
// aria-atomic ensures the full toast (title + message) announces, not just
|
|
32
|
-
// the
|
|
32
|
+
// the changed fragment.
|
|
33
33
|
stack.setAttribute('aria-atomic', 'true');
|
|
34
34
|
}
|
|
35
35
|
document.body.appendChild(stack);
|
|
@@ -67,7 +67,7 @@ function toastElement(message, { tone, title }) {
|
|
|
67
67
|
// aria-atomic so a *titled* toast announces title + message as one unit, not
|
|
68
68
|
// disjointly — and unlike aria-atomic on the polite STACK (which would re-read
|
|
69
69
|
// every resident toast on each new one), scoping it to the toast keeps sibling
|
|
70
|
-
// toasts out of the announcement.
|
|
70
|
+
// toasts out of the announcement.
|
|
71
71
|
el.setAttribute('aria-atomic', 'true');
|
|
72
72
|
if (title) {
|
|
73
73
|
const t = document.createElement('p');
|
|
@@ -183,8 +183,8 @@ export function toast(message, { tone, title, duration = 4000, assertive, closab
|
|
|
183
183
|
// `closable`. The button carries no text node (glyph is a CSS
|
|
184
184
|
// ::before) so the toast's announced/textContent stays the message.
|
|
185
185
|
// Explicitly opting OUT of the close button on a sticky toast strands it with
|
|
186
|
-
// no in-UI dismissal
|
|
187
|
-
// dismiss
|
|
186
|
+
// no in-UI dismissal; warn that the caller must retain and call the returned
|
|
187
|
+
// dismiss function.
|
|
188
188
|
if (duration === 0 && closable === false && typeof console !== 'undefined') {
|
|
189
189
|
console.warn(
|
|
190
190
|
'[bronto] toast(): duration:0 + closable:false has no in-UI dismissal — keep the returned dismiss() and call it yourself, or set closable:true.',
|
package/classes/index.d.ts
CHANGED
|
@@ -959,9 +959,22 @@ export interface ValueAttrs {
|
|
|
959
959
|
'aria-valuemax': number;
|
|
960
960
|
style: { '--value': number };
|
|
961
961
|
}
|
|
962
|
+
export interface MeterValueAttrs extends ValueAttrs {
|
|
963
|
+
role: 'meter';
|
|
964
|
+
}
|
|
965
|
+
export interface ProgressValueAttrs extends ValueAttrs {
|
|
966
|
+
role: 'progressbar';
|
|
967
|
+
}
|
|
968
|
+
export interface IndeterminateProgressAttrs {
|
|
969
|
+
role: 'progressbar';
|
|
970
|
+
'aria-busy': 'true';
|
|
971
|
+
}
|
|
962
972
|
export interface Attrs {
|
|
963
|
-
meter(value: number, opts?: ValueRangeOpts):
|
|
964
|
-
progress(value: number, opts?: ValueRangeOpts):
|
|
973
|
+
meter(value: number, opts?: ValueRangeOpts): MeterValueAttrs;
|
|
974
|
+
progress(value: number, opts?: ValueRangeOpts): ProgressValueAttrs;
|
|
975
|
+
progress(value?: undefined, opts?: ValueRangeOpts): IndeterminateProgressAttrs;
|
|
976
|
+
dotbar(value: number, opts?: ValueRangeOpts): ProgressValueAttrs;
|
|
977
|
+
dotbar(value?: undefined, opts?: ValueRangeOpts): IndeterminateProgressAttrs;
|
|
965
978
|
}
|
|
966
979
|
/** Set the painted value AND its ARIA together so they cannot drift. */
|
|
967
980
|
export declare const attrs: Attrs;
|
package/classes/index.js
CHANGED
|
@@ -212,7 +212,7 @@ export const cls = Object.freeze({
|
|
|
212
212
|
tableLined: 'ui-table--lined',
|
|
213
213
|
tableBreakAnywhere: 'ui-table--break-anywhere',
|
|
214
214
|
tableWrap: 'ui-table-wrap',
|
|
215
|
-
// Loading state goes on the
|
|
215
|
+
// Loading state goes on the wrap, so the modifier is named for the wrap.
|
|
216
216
|
tableLoading: 'ui-table-wrap--loading',
|
|
217
217
|
tableEmpty: 'ui-table__empty',
|
|
218
218
|
tableSort: 'ui-table__sort',
|
|
@@ -467,7 +467,6 @@ export const cls = Object.freeze({
|
|
|
467
467
|
crosshairLineX: 'ui-crosshair__line--x',
|
|
468
468
|
crosshairLineY: 'ui-crosshair__line--y',
|
|
469
469
|
crosshairBadge: 'ui-crosshair__badge',
|
|
470
|
-
readout: 'ui-readout',
|
|
471
470
|
// selection-state vocabulary (cross-cutting — css/selection.css)
|
|
472
471
|
sel: 'ui-sel',
|
|
473
472
|
selOn: 'ui-sel--on',
|
|
@@ -740,14 +739,14 @@ const srcTone = (state) =>
|
|
|
740
739
|
})[state] || '';
|
|
741
740
|
|
|
742
741
|
// Component tone → modifier class. Same object-literal idiom as srcTone/stateTone
|
|
743
|
-
//
|
|
742
|
+
// while keeping modifier classes grep-friendly.
|
|
744
743
|
//
|
|
745
744
|
// The set differs PER COMPONENT on purpose — `muted` is a badge/num tone, not an
|
|
746
745
|
// alert/toast/meter/dot one — so a caller extrapolating a universal tone (e.g.
|
|
747
746
|
// `ui.alert({ tone: 'muted' })`) used to get a silent no-op: a bare, untoned
|
|
748
747
|
// element with no signal that the tone was dropped. Warn at dev time instead, so
|
|
749
748
|
// that "validates-but-no-ops" trap is loud rather than invisible. An omitted tone
|
|
750
|
-
// is fine
|
|
749
|
+
// is fine and returns no modifier.
|
|
751
750
|
const toneClass = (component, map, tone) => {
|
|
752
751
|
if (tone == null) return '';
|
|
753
752
|
const hit = map[tone];
|
|
@@ -853,6 +852,43 @@ const claimStatus = (status) =>
|
|
|
853
852
|
status,
|
|
854
853
|
);
|
|
855
854
|
|
|
855
|
+
const valueClass = (map, value) => (value == null ? '' : map[value] || '');
|
|
856
|
+
|
|
857
|
+
const annotationVariants = Object.freeze({
|
|
858
|
+
label: cls.annotationLabelVariant,
|
|
859
|
+
callout: cls.annotationCallout,
|
|
860
|
+
elbow: cls.annotationElbow,
|
|
861
|
+
curve: cls.annotationCurve,
|
|
862
|
+
circle: cls.annotationCircle,
|
|
863
|
+
rect: cls.annotationRect,
|
|
864
|
+
threshold: cls.annotationThreshold,
|
|
865
|
+
badge: cls.annotationBadgeVariant,
|
|
866
|
+
bracket: cls.annotationBracket,
|
|
867
|
+
band: cls.annotationBand,
|
|
868
|
+
slope: cls.annotationSlope,
|
|
869
|
+
compare: cls.annotationCompare,
|
|
870
|
+
cluster: cls.annotationCluster,
|
|
871
|
+
axis: cls.annotationAxis,
|
|
872
|
+
timeline: cls.annotationTimeline,
|
|
873
|
+
evidence: cls.annotationEvidence,
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
const annotationTones = Object.freeze({
|
|
877
|
+
accent: cls.annotationAccent,
|
|
878
|
+
muted: cls.annotationMuted,
|
|
879
|
+
success: cls.annotationSuccess,
|
|
880
|
+
warning: cls.annotationWarning,
|
|
881
|
+
danger: cls.annotationDanger,
|
|
882
|
+
info: cls.annotationInfo,
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
const annotationMotions = Object.freeze({
|
|
886
|
+
draw: cls.annotationDraw,
|
|
887
|
+
pulse: cls.annotationPulse,
|
|
888
|
+
reveal: cls.annotationReveal,
|
|
889
|
+
focus: cls.annotationFocus,
|
|
890
|
+
});
|
|
891
|
+
|
|
856
892
|
export const ui = {
|
|
857
893
|
button: ({ variant, icon, size } = {}) =>
|
|
858
894
|
j(
|
|
@@ -928,7 +964,7 @@ export const ui = {
|
|
|
928
964
|
j(
|
|
929
965
|
cls.legendSwatch,
|
|
930
966
|
// Series 1–8 map to ui-legend__swatch--N; the explicit bounds-check keeps a
|
|
931
|
-
// 0/9/non-integer from coining a class the stylesheet never defines.
|
|
967
|
+
// 0/9/non-integer from coining a class the stylesheet never defines.
|
|
932
968
|
Number.isInteger(series) && series >= 1 && series <= 8 && cls[`legendSwatch${series}`],
|
|
933
969
|
shape === 'circle' && cls.legendSwatchCircle,
|
|
934
970
|
shape === 'line' && cls.legendSwatchLine,
|
|
@@ -936,32 +972,9 @@ export const ui = {
|
|
|
936
972
|
annotation: ({ variant = 'callout', tone = 'accent', motion } = {}) =>
|
|
937
973
|
j(
|
|
938
974
|
cls.annotation,
|
|
939
|
-
variant
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
variant === 'curve' && cls.annotationCurve,
|
|
943
|
-
variant === 'circle' && cls.annotationCircle,
|
|
944
|
-
variant === 'rect' && cls.annotationRect,
|
|
945
|
-
variant === 'threshold' && cls.annotationThreshold,
|
|
946
|
-
variant === 'badge' && cls.annotationBadgeVariant,
|
|
947
|
-
variant === 'bracket' && cls.annotationBracket,
|
|
948
|
-
variant === 'band' && cls.annotationBand,
|
|
949
|
-
variant === 'slope' && cls.annotationSlope,
|
|
950
|
-
variant === 'compare' && cls.annotationCompare,
|
|
951
|
-
variant === 'cluster' && cls.annotationCluster,
|
|
952
|
-
variant === 'axis' && cls.annotationAxis,
|
|
953
|
-
variant === 'timeline' && cls.annotationTimeline,
|
|
954
|
-
variant === 'evidence' && cls.annotationEvidence,
|
|
955
|
-
tone === 'accent' && cls.annotationAccent,
|
|
956
|
-
tone === 'muted' && cls.annotationMuted,
|
|
957
|
-
tone === 'success' && cls.annotationSuccess,
|
|
958
|
-
tone === 'warning' && cls.annotationWarning,
|
|
959
|
-
tone === 'danger' && cls.annotationDanger,
|
|
960
|
-
tone === 'info' && cls.annotationInfo,
|
|
961
|
-
motion === 'draw' && cls.annotationDraw,
|
|
962
|
-
motion === 'pulse' && cls.annotationPulse,
|
|
963
|
-
motion === 'reveal' && cls.annotationReveal,
|
|
964
|
-
motion === 'focus' && cls.annotationFocus,
|
|
975
|
+
valueClass(annotationVariants, variant),
|
|
976
|
+
valueClass(annotationTones, tone),
|
|
977
|
+
valueClass(annotationMotions, motion),
|
|
965
978
|
),
|
|
966
979
|
mark: ({ style, tone, motion } = {}) =>
|
|
967
980
|
j(
|
|
@@ -1050,7 +1063,7 @@ export const ui = {
|
|
|
1050
1063
|
// UNITLESS `--value` (0–100) and AT needs role + aria-valuenow/min/max. This sets
|
|
1051
1064
|
// the painted value and its announced value together so they can't drift, and
|
|
1052
1065
|
// normalizes an arbitrary {min,max} to the 0–100 `--value` the CSS expects while
|
|
1053
|
-
// keeping aria-valuenow in the caller's real units.
|
|
1066
|
+
// keeping aria-valuenow in the caller's real units.
|
|
1054
1067
|
// `busyWhenIndeterminate` — a progressbar advertises aria-busy when its value is
|
|
1055
1068
|
// unknown; a meter is never indeterminate so it passes false. (Kept a boolean
|
|
1056
1069
|
// flag rather than testing the role string, so check:recipe-types doesn't read it
|
|
@@ -1065,7 +1078,7 @@ const valueAttrs = (role, value, min, max, busyWhenIndeterminate) => {
|
|
|
1065
1078
|
// advertises aria-busy; a meter has no indeterminate state, so a non-finite
|
|
1066
1079
|
// value there is a caller error we still fail safe on by omitting the
|
|
1067
1080
|
// misleading 0. Pair with `ui.progress({ indeterminate: true })` for the CSS
|
|
1068
|
-
// sweep.
|
|
1081
|
+
// sweep.
|
|
1069
1082
|
if (!Number.isFinite(raw)) {
|
|
1070
1083
|
return busyWhenIndeterminate ? { role, 'aria-busy': 'true' } : { role };
|
|
1071
1084
|
}
|
|
@@ -1087,13 +1100,13 @@ const valueAttrs = (role, value, min, max, busyWhenIndeterminate) => {
|
|
|
1087
1100
|
* </div>
|
|
1088
1101
|
* `value` is in your own units; pass `{ min, max }` (default 0–100) and the
|
|
1089
1102
|
* `--value` width is normalized for you. Call `attrs.progress()` with no value
|
|
1090
|
-
* for an indeterminate bar (omits aria-valuenow, sets aria-busy).
|
|
1103
|
+
* for an indeterminate bar (omits aria-valuenow, sets aria-busy).
|
|
1091
1104
|
*
|
|
1092
1105
|
* `attrs.dotbar(value)` is the segmented analogue of `attrs.progress`: a
|
|
1093
1106
|
* determinate `.ui-dotbar` carries the same progress data as `.ui-progress` but,
|
|
1094
1107
|
* without this, was eight empty `<span>`s to AT (the segments are decorative —
|
|
1095
1108
|
* mark them `aria-hidden`). Same progressbar role + aria-valuenow/min/max;
|
|
1096
|
-
* call with no value for the indeterminate sweep.
|
|
1109
|
+
* call with no value for the indeterminate sweep.
|
|
1097
1110
|
*/
|
|
1098
1111
|
export const attrs = Object.freeze({
|
|
1099
1112
|
meter: (value, { min = 0, max = 100 } = {}) => valueAttrs('meter', value, min, max, false),
|
package/connectors/index.d.ts
CHANGED
|
@@ -1,9 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a numeric option with an optional fallback.
|
|
3
|
+
* @param {string} name
|
|
4
|
+
* @param {number | null | undefined} value
|
|
5
|
+
* @param {number | null | undefined} [fallback]
|
|
6
|
+
* @returns {number}
|
|
7
|
+
*/
|
|
8
|
+
export function finite(name: string, value: number | null | undefined, fallback?: number | null | undefined): number;
|
|
9
|
+
/**
|
|
10
|
+
* Resolve a non-negative numeric option with an optional fallback.
|
|
11
|
+
* @param {string} name
|
|
12
|
+
* @param {number | null | undefined} value
|
|
13
|
+
* @param {number | null | undefined} [fallback]
|
|
14
|
+
* @returns {number}
|
|
15
|
+
*/
|
|
16
|
+
export function dimension(name: string, value: number | null | undefined, fallback?: number | null | undefined): number;
|
|
17
|
+
/**
|
|
18
|
+
* @param {number} value
|
|
19
|
+
* @returns {number}
|
|
20
|
+
*/
|
|
21
|
+
export function roundNumber(value: number): number;
|
|
22
|
+
/**
|
|
23
|
+
* @param {number} value
|
|
24
|
+
* @returns {string}
|
|
25
|
+
*/
|
|
26
|
+
export function fmt(value: number): string;
|
|
27
|
+
/**
|
|
28
|
+
* @param {number} x
|
|
29
|
+
* @param {number} y
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
export function point(x: number, y: number): string;
|
|
33
|
+
/**
|
|
34
|
+
* @param {number} value
|
|
35
|
+
* @param {number} min
|
|
36
|
+
* @param {number} max
|
|
37
|
+
* @returns {number}
|
|
38
|
+
*/
|
|
39
|
+
export function clamp(value: number, min: number, max: number): number;
|
|
7
40
|
/**
|
|
8
41
|
* A point on a rect's edge (or centre). `rect` is `{ x, y, width, height }`.
|
|
9
42
|
* @param {Rect} rect
|
|
@@ -70,8 +103,8 @@ export function arrowHead(p: Point, angle: number, size?: number, spread?: numbe
|
|
|
70
103
|
export function dotMark(p: Point, radius?: number): string;
|
|
71
104
|
/**
|
|
72
105
|
* An axis-aligned rectangle path from its corners (callers derive the corners
|
|
73
|
-
* from a centre or a top-left as they need). Shared by
|
|
74
|
-
*
|
|
106
|
+
* from a centre or a top-left as they need). Shared by annotation rect/band
|
|
107
|
+
* and evidence-marker subjects.
|
|
75
108
|
* @param {number} left
|
|
76
109
|
* @param {number} top
|
|
77
110
|
* @param {number} right
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":"
|
|
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,qCAHW,oBAAoB,GAClB,MAAM,CAQlB;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,oCAHW,mBAAmB,GACjB,kBAAkB,CAe9B;AA9VD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
|