@ponchia/ui 0.5.0 → 0.6.3
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 +386 -4
- package/MIGRATIONS.json +14 -0
- package/README.md +29 -6
- package/annotations/index.d.ts +398 -276
- package/annotations/index.d.ts.map +1 -0
- package/annotations/index.js +350 -77
- package/behaviors/carousel.d.ts +28 -0
- package/behaviors/carousel.d.ts.map +1 -0
- package/behaviors/carousel.js +20 -16
- package/behaviors/combobox.d.ts +40 -0
- package/behaviors/combobox.d.ts.map +1 -0
- package/behaviors/combobox.js +111 -29
- package/behaviors/command.d.ts +41 -0
- package/behaviors/command.d.ts.map +1 -0
- package/behaviors/command.js +27 -15
- package/behaviors/connectors.d.ts +17 -0
- package/behaviors/connectors.d.ts.map +1 -0
- package/behaviors/connectors.js +7 -5
- package/behaviors/crosshair.d.ts +42 -0
- package/behaviors/crosshair.d.ts.map +1 -0
- package/behaviors/crosshair.js +23 -6
- package/behaviors/dialog.d.ts +20 -0
- package/behaviors/dialog.d.ts.map +1 -0
- package/behaviors/dialog.js +6 -2
- package/behaviors/disclosure.d.ts +10 -0
- package/behaviors/disclosure.d.ts.map +1 -0
- package/behaviors/disclosure.js +6 -2
- package/behaviors/dismissible.d.ts +10 -0
- package/behaviors/dismissible.d.ts.map +1 -0
- package/behaviors/dismissible.js +6 -2
- package/behaviors/forms.d.ts +27 -0
- package/behaviors/forms.d.ts.map +1 -0
- package/behaviors/forms.js +54 -13
- package/behaviors/glyph.d.ts +14 -0
- package/behaviors/glyph.d.ts.map +1 -0
- package/behaviors/glyph.js +28 -5
- package/behaviors/index.d.ts +31 -237
- package/behaviors/index.d.ts.map +1 -0
- package/behaviors/index.js +17 -0
- package/behaviors/inert.d.ts +20 -0
- package/behaviors/inert.d.ts.map +1 -0
- package/behaviors/inert.js +46 -0
- package/behaviors/internal.d.ts +25 -0
- package/behaviors/internal.d.ts.map +1 -0
- package/behaviors/internal.js +77 -1
- package/behaviors/legend.d.ts +35 -0
- package/behaviors/legend.d.ts.map +1 -0
- package/behaviors/legend.js +32 -2
- package/behaviors/menu.d.ts +16 -0
- package/behaviors/menu.d.ts.map +1 -0
- package/behaviors/menu.js +6 -2
- package/behaviors/modal.d.ts +41 -0
- package/behaviors/modal.d.ts.map +1 -0
- package/behaviors/modal.js +124 -0
- package/behaviors/popover.d.ts +28 -0
- package/behaviors/popover.d.ts.map +1 -0
- package/behaviors/popover.js +78 -7
- package/behaviors/spotlight.d.ts +17 -0
- package/behaviors/spotlight.d.ts.map +1 -0
- package/behaviors/spotlight.js +7 -5
- package/behaviors/table.d.ts +36 -0
- package/behaviors/table.d.ts.map +1 -0
- package/behaviors/table.js +84 -17
- package/behaviors/tabs.d.ts +20 -0
- package/behaviors/tabs.d.ts.map +1 -0
- package/behaviors/tabs.js +17 -14
- package/behaviors/theme.d.ts +54 -0
- package/behaviors/theme.d.ts.map +1 -0
- package/behaviors/theme.js +22 -3
- package/behaviors/toast.d.ts +49 -0
- package/behaviors/toast.d.ts.map +1 -0
- package/behaviors/toast.js +47 -3
- package/classes/classes.json +2527 -0
- package/classes/index.d.ts +134 -15
- package/classes/index.js +280 -80
- package/classes/vscode.css-custom-data.json +12 -0
- package/connectors/index.d.ts +201 -69
- package/connectors/index.d.ts.map +1 -0
- package/connectors/index.js +142 -25
- package/css/app.css +69 -13
- package/css/base.css +15 -10
- package/css/bullet.css +108 -0
- package/css/code.css +98 -0
- package/css/connectors.css +17 -0
- package/css/content.css +22 -3
- package/css/crosshair.css +7 -7
- package/css/dataviz.css +5 -1
- package/css/diff.css +153 -0
- package/css/disclosure.css +53 -7
- package/css/dots.css +94 -7
- package/css/feedback.css +97 -7
- package/css/forms.css +113 -4
- package/css/legend.css +16 -9
- package/css/marks.css +38 -8
- package/css/motion.css +98 -53
- package/css/navigation.css +7 -0
- package/css/overlay.css +90 -3
- package/css/primitives.css +158 -13
- package/css/report.css +73 -56
- package/css/sidenote.css +67 -0
- package/css/site.css +16 -2
- package/css/sources.css +43 -1
- package/css/spark.css +62 -0
- package/css/spotlight.css +1 -1
- package/css/table.css +9 -2
- package/css/term.css +110 -0
- package/css/textref.css +63 -0
- package/css/toc.css +91 -0
- package/css/tokens.css +49 -1
- package/css/tree.css +134 -0
- package/css/workbench.css +1 -1
- package/dist/bronto.css +1 -1
- package/dist/css/analytical.css +1 -1
- package/dist/css/app.css +1 -1
- package/dist/css/base.css +1 -1
- package/dist/css/bullet.css +1 -0
- package/dist/css/code.css +1 -0
- package/dist/css/connectors.css +1 -1
- package/dist/css/content.css +1 -1
- package/dist/css/crosshair.css +1 -1
- package/dist/css/diff.css +1 -0
- package/dist/css/disclosure.css +1 -1
- package/dist/css/dots.css +1 -1
- package/dist/css/feedback.css +1 -1
- package/dist/css/forms.css +1 -1
- package/dist/css/legend.css +1 -1
- package/dist/css/marks.css +1 -1
- package/dist/css/motion.css +1 -1
- package/dist/css/navigation.css +1 -1
- package/dist/css/overlay.css +1 -1
- package/dist/css/primitives.css +1 -1
- package/dist/css/report.css +1 -1
- package/dist/css/sidenote.css +1 -0
- package/dist/css/site.css +1 -1
- package/dist/css/sources.css +1 -1
- package/dist/css/spark.css +1 -0
- package/dist/css/spotlight.css +1 -1
- package/dist/css/table.css +1 -1
- package/dist/css/term.css +1 -0
- package/dist/css/textref.css +1 -0
- package/dist/css/toc.css +1 -0
- package/dist/css/tokens.css +1 -1
- package/dist/css/tree.css +1 -0
- package/dist/css/workbench.css +1 -1
- package/docs/adr/0003-theme-model.md +1 -1
- package/docs/annotations.md +133 -14
- package/docs/architecture.md +49 -6
- package/docs/bullet.md +78 -0
- package/docs/code.md +76 -0
- package/docs/contrast.md +116 -92
- package/docs/d2.md +196 -0
- package/docs/diff.md +146 -0
- package/docs/legends.md +23 -3
- package/docs/marks.md +9 -2
- package/docs/mermaid.md +169 -0
- package/docs/reference.md +201 -26
- package/docs/reporting.md +416 -57
- package/docs/sidenote.md +64 -0
- package/docs/sources.md +27 -0
- package/docs/spark.md +78 -0
- package/docs/stability.md +10 -2
- package/docs/term.md +81 -0
- package/docs/textref.md +78 -0
- package/docs/theming.md +44 -5
- package/docs/toc.md +83 -0
- package/docs/tree.md +74 -0
- package/docs/usage.md +354 -16
- package/docs/vega.md +244 -0
- package/docs/workbench.md +7 -1
- package/glyphs/glyphs.js +13 -5
- package/llms.txt +285 -14
- package/package.json +95 -17
- package/qwik/index.d.ts +44 -59
- package/qwik/index.d.ts.map +1 -0
- package/qwik/index.js +65 -3
- package/react/index.d.ts +41 -61
- package/react/index.d.ts.map +1 -0
- package/react/index.js +63 -3
- package/solid/index.d.ts +68 -61
- package/solid/index.d.ts.map +1 -0
- package/solid/index.js +66 -3
- package/tokens/d2.d.ts +38 -0
- package/tokens/d2.js +71 -0
- package/tokens/d2.json +43 -0
- package/tokens/index.d.ts +5 -5
- package/tokens/index.js +15 -1
- package/tokens/index.json +9 -0
- package/tokens/mermaid.d.ts +23 -0
- package/tokens/mermaid.js +181 -0
- package/tokens/mermaid.json +163 -0
- package/tokens/resolved.json +45 -1
- package/tokens/skins.js +3 -2
- package/tokens/tokens.dtcg.json +26 -0
- package/tokens/vega.d.ts +34 -0
- package/tokens/vega.js +155 -0
- package/tokens/vega.json +179 -0
package/behaviors/carousel.js
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
hasDom,
|
|
3
|
+
resolveHost,
|
|
4
|
+
noop,
|
|
5
|
+
bindOnce,
|
|
6
|
+
scrollIntoViewSafe,
|
|
7
|
+
collectHosts,
|
|
8
|
+
} from './internal.js';
|
|
2
9
|
|
|
3
10
|
/**
|
|
4
11
|
* Image carousel / gallery, built on CSS scroll-snap so touch + trackpad
|
|
@@ -22,13 +29,15 @@ import { hasDom, noop, bindOnce } from './internal.js';
|
|
|
22
29
|
* Emits `bronto:change` ({ detail: { index } }) on every index change
|
|
23
30
|
* (button, key, thumbnail, or swipe). SSR-safe, idempotent per carousel;
|
|
24
31
|
* returns a cleanup function.
|
|
32
|
+
*
|
|
33
|
+
* @param {import('./internal.js').DelegateOpts} [opts]
|
|
34
|
+
* @returns {import('./internal.js').Cleanup}
|
|
25
35
|
*/
|
|
26
36
|
export function initCarousel({ root } = {}) {
|
|
27
37
|
if (!hasDom()) return noop;
|
|
28
|
-
const host = root
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
boxes.push(...(host.querySelectorAll?.('[data-bronto-carousel]') ?? []));
|
|
38
|
+
const host = resolveHost(root);
|
|
39
|
+
if (!host) return noop;
|
|
40
|
+
const boxes = collectHosts(host, '[data-bronto-carousel]');
|
|
32
41
|
const cleanups = [];
|
|
33
42
|
|
|
34
43
|
for (const box of boxes) {
|
|
@@ -103,16 +112,7 @@ export function initCarousel({ root } = {}) {
|
|
|
103
112
|
const emit = () =>
|
|
104
113
|
box.dispatchEvent(new CustomEvent('bronto:change', { detail: { index }, bubbles: true }));
|
|
105
114
|
|
|
106
|
-
|
|
107
|
-
// affordance, so never let it break index/aria sync — same guard as
|
|
108
|
-
// initCombobox.
|
|
109
|
-
const reveal = (el) => {
|
|
110
|
-
try {
|
|
111
|
-
el?.scrollIntoView({ block: 'nearest', inline: 'center' });
|
|
112
|
-
} catch {
|
|
113
|
-
/* no layout — ignore */
|
|
114
|
-
}
|
|
115
|
-
};
|
|
115
|
+
const reveal = (el) => scrollIntoViewSafe(el, { block: 'nearest', inline: 'center' });
|
|
116
116
|
|
|
117
117
|
const goTo = (i, { emitChange = true } = {}) => {
|
|
118
118
|
const next = loop ? (i + n) % n : Math.max(0, Math.min(n - 1, i));
|
|
@@ -176,13 +176,17 @@ export function initCarousel({ root } = {}) {
|
|
|
176
176
|
},
|
|
177
177
|
{ root: viewport, threshold: 0.6 },
|
|
178
178
|
);
|
|
179
|
-
slides.forEach((s) => io.observe(s));
|
|
180
179
|
}
|
|
181
180
|
|
|
182
181
|
render();
|
|
183
182
|
const bound = bindOnce(box, 'carousel', () => {
|
|
184
183
|
viewport.addEventListener('keydown', onKey);
|
|
185
184
|
box.addEventListener('click', onClick);
|
|
185
|
+
// Observe inside the add callback so observe/disconnect pair with the
|
|
186
|
+
// binding lifecycle: a re-init tears down the prior binding (which
|
|
187
|
+
// disconnects the old observer) before this starts, so two observers
|
|
188
|
+
// never watch the same slides — even for one tick.
|
|
189
|
+
slides.forEach((s) => io?.observe(s));
|
|
186
190
|
return () => {
|
|
187
191
|
viewport.removeEventListener('keydown', onKey);
|
|
188
192
|
box.removeEventListener('click', onClick);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Editable combobox with a filtered listbox popup, implementing the
|
|
3
|
+
* WAI-ARIA APG combobox pattern (the widget the framework most lacked
|
|
4
|
+
* and consumers most often build badly). Dependency-free, no
|
|
5
|
+
* positioning library — the list is CSS-anchored under the input.
|
|
6
|
+
*
|
|
7
|
+
* The input MUST have an accessible name — a `<label>`, `aria-label`, or
|
|
8
|
+
* `aria-labelledby` (a placeholder does not count). A nameless `role="combobox"`
|
|
9
|
+
* is a silent screen-reader failure, so the behavior warns at dev time when it
|
|
10
|
+
* finds one, and mirrors the input's name onto the listbox.
|
|
11
|
+
*
|
|
12
|
+
* Markup: `[data-bronto-combobox]` wrapping an `<input role="combobox">`
|
|
13
|
+
* (`.ui-combobox__input`) and a `<ul role="listbox">`
|
|
14
|
+
* (`.ui-combobox__list`) of `<li role="option">` (`.ui-combobox__option`,
|
|
15
|
+
* optional `data-value`). An optional `.ui-combobox__empty` (hidden at rest)
|
|
16
|
+
* shows when nothing matches. The behavior owns ids, `aria-expanded`,
|
|
17
|
+
* `aria-controls`, `aria-activedescendant`, roving active option,
|
|
18
|
+
* type-to-filter, full keyboard (Down/Up/Home/End/Enter/Escape/Tab),
|
|
19
|
+
* pointer select, and outside-click close. On select the **visible input shows
|
|
20
|
+
* the option's text label**, while the emitted `bronto:change` CustomEvent
|
|
21
|
+
* carries the option's `data-value` code: `{ detail: { value, label } }` (value
|
|
22
|
+
* falls back to the label when there is no `data-value`). SSR-safe, idempotent
|
|
23
|
+
* per instance; returns a cleanup function.
|
|
24
|
+
*
|
|
25
|
+
* Single-select APG deviations (intentional, for a filtering text combobox):
|
|
26
|
+
* ArrowDown on a CLOSED list opens + filters rather than pre-activating the
|
|
27
|
+
* first option, and Tab closes the list without committing the merely-highlighted
|
|
28
|
+
* option (only Enter/click commits). Both are safe for single-select.
|
|
29
|
+
*
|
|
30
|
+
* Options are read from the DOM at init; if you replace the listbox contents
|
|
31
|
+
* (e.g. async/remote results), either re-run initCombobox, or add
|
|
32
|
+
* `data-bronto-combobox-live` to the `[data-bronto-combobox]` host so a
|
|
33
|
+
* MutationObserver re-reads the options in place (opt-in — off by default so
|
|
34
|
+
* the common static case stays observer-free).
|
|
35
|
+
*
|
|
36
|
+
* @param {import('./internal.js').DelegateOpts} [opts]
|
|
37
|
+
* @returns {import('./internal.js').Cleanup}
|
|
38
|
+
*/
|
|
39
|
+
export function initCombobox({ root }?: import("./internal.js").DelegateOpts): import("./internal.js").Cleanup;
|
|
40
|
+
//# sourceMappingURL=combobox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["combobox.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CAqO3C"}
|
package/behaviors/combobox.js
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
hasDom,
|
|
3
|
+
resolveHost,
|
|
4
|
+
noop,
|
|
5
|
+
bindOnce,
|
|
6
|
+
nextFieldUid,
|
|
7
|
+
scrollIntoViewSafe,
|
|
8
|
+
wrapIndex,
|
|
9
|
+
collectHosts,
|
|
10
|
+
} from './internal.js';
|
|
2
11
|
|
|
3
12
|
/**
|
|
4
13
|
* Editable combobox with a filtered listbox popup, implementing the
|
|
@@ -6,23 +15,43 @@ import { hasDom, noop, bindOnce, nextFieldUid } from './internal.js';
|
|
|
6
15
|
* and consumers most often build badly). Dependency-free, no
|
|
7
16
|
* positioning library — the list is CSS-anchored under the input.
|
|
8
17
|
*
|
|
18
|
+
* The input MUST have an accessible name — a `<label>`, `aria-label`, or
|
|
19
|
+
* `aria-labelledby` (a placeholder does not count). A nameless `role="combobox"`
|
|
20
|
+
* is a silent screen-reader failure, so the behavior warns at dev time when it
|
|
21
|
+
* finds one, and mirrors the input's name onto the listbox.
|
|
22
|
+
*
|
|
9
23
|
* Markup: `[data-bronto-combobox]` wrapping an `<input role="combobox">`
|
|
10
24
|
* (`.ui-combobox__input`) and a `<ul role="listbox">`
|
|
11
25
|
* (`.ui-combobox__list`) of `<li role="option">` (`.ui-combobox__option`,
|
|
12
|
-
* optional `data-value`). An optional `.ui-combobox__empty`
|
|
13
|
-
* nothing matches. The behavior owns ids, `aria-expanded`,
|
|
26
|
+
* optional `data-value`). An optional `.ui-combobox__empty` (hidden at rest)
|
|
27
|
+
* shows when nothing matches. The behavior owns ids, `aria-expanded`,
|
|
14
28
|
* `aria-controls`, `aria-activedescendant`, roving active option,
|
|
15
29
|
* type-to-filter, full keyboard (Down/Up/Home/End/Enter/Escape/Tab),
|
|
16
|
-
* pointer select, and outside-click close
|
|
17
|
-
*
|
|
18
|
-
*
|
|
30
|
+
* pointer select, and outside-click close. On select the **visible input shows
|
|
31
|
+
* the option's text label**, while the emitted `bronto:change` CustomEvent
|
|
32
|
+
* carries the option's `data-value` code: `{ detail: { value, label } }` (value
|
|
33
|
+
* falls back to the label when there is no `data-value`). SSR-safe, idempotent
|
|
34
|
+
* per instance; returns a cleanup function.
|
|
35
|
+
*
|
|
36
|
+
* Single-select APG deviations (intentional, for a filtering text combobox):
|
|
37
|
+
* ArrowDown on a CLOSED list opens + filters rather than pre-activating the
|
|
38
|
+
* first option, and Tab closes the list without committing the merely-highlighted
|
|
39
|
+
* option (only Enter/click commits). Both are safe for single-select.
|
|
40
|
+
*
|
|
41
|
+
* Options are read from the DOM at init; if you replace the listbox contents
|
|
42
|
+
* (e.g. async/remote results), either re-run initCombobox, or add
|
|
43
|
+
* `data-bronto-combobox-live` to the `[data-bronto-combobox]` host so a
|
|
44
|
+
* MutationObserver re-reads the options in place (opt-in — off by default so
|
|
45
|
+
* the common static case stays observer-free).
|
|
46
|
+
*
|
|
47
|
+
* @param {import('./internal.js').DelegateOpts} [opts]
|
|
48
|
+
* @returns {import('./internal.js').Cleanup}
|
|
19
49
|
*/
|
|
20
50
|
export function initCombobox({ root } = {}) {
|
|
21
51
|
if (!hasDom()) return noop;
|
|
22
|
-
const host = root
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
boxes.push(...(host.querySelectorAll?.('[data-bronto-combobox]') ?? []));
|
|
52
|
+
const host = resolveHost(root);
|
|
53
|
+
if (!host) return noop;
|
|
54
|
+
const boxes = collectHosts(host, '[data-bronto-combobox]');
|
|
26
55
|
const cleanups = [];
|
|
27
56
|
|
|
28
57
|
for (const box of boxes) {
|
|
@@ -30,20 +59,59 @@ export function initCombobox({ root } = {}) {
|
|
|
30
59
|
const list = box.querySelector('[role="listbox"], .ui-combobox__list');
|
|
31
60
|
if (!input || !list) continue;
|
|
32
61
|
const empty = box.querySelector('.ui-combobox__empty');
|
|
33
|
-
const options = [...list.querySelectorAll('[role="option"], .ui-combobox__option')];
|
|
34
|
-
|
|
35
62
|
const listId = list.id || (list.id = `bronto-cb-list-${nextFieldUid()}`);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
63
|
+
// Re-readable so the opt-in MutationObserver (`data-bronto-combobox-live`)
|
|
64
|
+
// can pick up async/replaced option nodes without a full re-init. `visible`,
|
|
65
|
+
// `filter`, `move`, etc. close over this binding, so reassigning it is enough.
|
|
66
|
+
let options = [];
|
|
67
|
+
const syncOptions = () => {
|
|
68
|
+
options = [...list.querySelectorAll('[role="option"], .ui-combobox__option')];
|
|
69
|
+
options.forEach((o, i) => {
|
|
70
|
+
if (!o.id) o.id = `${listId}-opt-${i}`;
|
|
71
|
+
o.setAttribute('role', 'option');
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
syncOptions();
|
|
40
75
|
list.setAttribute('role', 'listbox');
|
|
76
|
+
// Give the listbox its own accessible name (a bare role=listbox is unnamed
|
|
77
|
+
// to a screen reader) by mirroring the input's REAL name. (a11y review C30.)
|
|
78
|
+
// The placeholder is deliberately NOT in this chain: the input warning below
|
|
79
|
+
// already rejects a placeholder as an inadequate name, so papering the
|
|
80
|
+
// listbox over with it would contradict that — if there's no real name the
|
|
81
|
+
// listbox stays unnamed and the warning is the signal. (component audit C28.)
|
|
82
|
+
if (!list.hasAttribute('aria-label') && !list.hasAttribute('aria-labelledby')) {
|
|
83
|
+
const name = input.getAttribute('aria-label') || input.labels?.[0]?.textContent?.trim();
|
|
84
|
+
if (name) list.setAttribute('aria-label', name);
|
|
85
|
+
}
|
|
86
|
+
// A `role="combobox"` with no accessible name is a silent AT failure. A
|
|
87
|
+
// placeholder is not a robust name (it can vanish and is ignored by some
|
|
88
|
+
// AT), so warn unless there is a real label/aria-label/aria-labelledby/title
|
|
89
|
+
// (C7). We can't invent a good name, hence a dev-time warning, not a guess.
|
|
90
|
+
const inputNamed =
|
|
91
|
+
input.hasAttribute('aria-label') ||
|
|
92
|
+
input.hasAttribute('aria-labelledby') ||
|
|
93
|
+
!!input.labels?.length ||
|
|
94
|
+
input.hasAttribute('title');
|
|
95
|
+
if (!inputNamed && typeof console !== 'undefined') {
|
|
96
|
+
console.warn(
|
|
97
|
+
'[bronto] initCombobox(): the combobox input has no accessible name — add a <label>, aria-label, or aria-labelledby (a placeholder is not enough).',
|
|
98
|
+
);
|
|
99
|
+
}
|
|
41
100
|
input.setAttribute('role', 'combobox');
|
|
42
101
|
input.setAttribute('aria-controls', listId);
|
|
43
102
|
input.setAttribute('aria-autocomplete', 'list');
|
|
44
103
|
input.setAttribute('aria-expanded', 'false');
|
|
45
104
|
input.setAttribute('autocomplete', 'off');
|
|
46
105
|
list.hidden = true;
|
|
106
|
+
// Hide the empty-state at rest: it must only appear once a filter yields no
|
|
107
|
+
// matches, never on an idle combobox. Without this an author who omits
|
|
108
|
+
// `hidden` on `.ui-combobox__empty` ships a box that reads "No matches"
|
|
109
|
+
// before the user has typed anything. (component audit C10.) Make it a
|
|
110
|
+
// status live region so its appearance is announced. (component audit C38.)
|
|
111
|
+
if (empty) {
|
|
112
|
+
empty.hidden = true;
|
|
113
|
+
if (!empty.hasAttribute('role')) empty.setAttribute('role', 'status');
|
|
114
|
+
}
|
|
47
115
|
|
|
48
116
|
let active = -1;
|
|
49
117
|
const visible = () => options.filter((o) => !o.hidden);
|
|
@@ -53,13 +121,7 @@ export function initCombobox({ root } = {}) {
|
|
|
53
121
|
if (opt) {
|
|
54
122
|
opt.classList.add('is-active');
|
|
55
123
|
input.setAttribute('aria-activedescendant', opt.id);
|
|
56
|
-
|
|
57
|
-
// pure affordance, so never let it break keyboard nav.
|
|
58
|
-
try {
|
|
59
|
-
opt.scrollIntoView({ block: 'nearest' });
|
|
60
|
-
} catch {
|
|
61
|
-
/* non-DOM/headless environment — ignore */
|
|
62
|
-
}
|
|
124
|
+
scrollIntoViewSafe(opt);
|
|
63
125
|
} else {
|
|
64
126
|
input.removeAttribute('aria-activedescendant');
|
|
65
127
|
}
|
|
@@ -96,13 +158,19 @@ export function initCombobox({ root } = {}) {
|
|
|
96
158
|
};
|
|
97
159
|
|
|
98
160
|
const select = (opt) => {
|
|
99
|
-
input
|
|
161
|
+
// Show the human LABEL in the input; emit the `data-value` CODE in the
|
|
162
|
+
// event. The natural pattern is code in `data-value`, label in the text —
|
|
163
|
+
// putting the code in the visible input silently shows the user a raw code.
|
|
164
|
+
// (component audit C10.)
|
|
165
|
+
const label = opt.textContent.trim();
|
|
166
|
+
const value = opt.dataset.value ?? label;
|
|
167
|
+
input.value = label;
|
|
100
168
|
options.forEach((o) => o.setAttribute('aria-selected', String(o === opt)));
|
|
101
169
|
close();
|
|
102
170
|
input.focus();
|
|
103
171
|
box.dispatchEvent(
|
|
104
172
|
new CustomEvent('bronto:change', {
|
|
105
|
-
detail: { value
|
|
173
|
+
detail: { value, label },
|
|
106
174
|
bubbles: true,
|
|
107
175
|
}),
|
|
108
176
|
);
|
|
@@ -112,10 +180,7 @@ export function initCombobox({ root } = {}) {
|
|
|
112
180
|
const vis = visible();
|
|
113
181
|
if (!vis.length) return;
|
|
114
182
|
open();
|
|
115
|
-
const
|
|
116
|
-
let next = curIdx + delta;
|
|
117
|
-
if (next < 0) next = vis.length - 1;
|
|
118
|
-
if (next >= vis.length) next = 0;
|
|
183
|
+
const next = wrapIndex(vis.indexOf(options[active]), delta, vis.length);
|
|
119
184
|
active = options.indexOf(vis[next]);
|
|
120
185
|
setActive(options[active]);
|
|
121
186
|
};
|
|
@@ -138,6 +203,15 @@ export function initCombobox({ root } = {}) {
|
|
|
138
203
|
return true;
|
|
139
204
|
};
|
|
140
205
|
|
|
206
|
+
// Live re-sync after the option nodes change under us. The active option may
|
|
207
|
+
// be gone, so drop it; re-filter against the current input only while open.
|
|
208
|
+
const relist = () => {
|
|
209
|
+
syncOptions();
|
|
210
|
+
active = -1;
|
|
211
|
+
setActive(null);
|
|
212
|
+
if (!list.hidden) filter();
|
|
213
|
+
};
|
|
214
|
+
|
|
141
215
|
const onInput = () => filter();
|
|
142
216
|
const onKey = (e) => {
|
|
143
217
|
switch (e.key) {
|
|
@@ -181,7 +255,15 @@ export function initCombobox({ root } = {}) {
|
|
|
181
255
|
input.addEventListener('keydown', onKey);
|
|
182
256
|
list.addEventListener('click', onOptionClick);
|
|
183
257
|
document.addEventListener('click', onDocClick);
|
|
258
|
+
// Opt-in: keep options in sync with a list mutated after init (async /
|
|
259
|
+
// remote results). Off by default so the common static case stays free.
|
|
260
|
+
const observer =
|
|
261
|
+
box.hasAttribute('data-bronto-combobox-live') && typeof MutationObserver === 'function'
|
|
262
|
+
? new MutationObserver(relist)
|
|
263
|
+
: null;
|
|
264
|
+
observer?.observe(list, { childList: true, subtree: true });
|
|
184
265
|
return () => {
|
|
266
|
+
observer?.disconnect();
|
|
185
267
|
input.removeEventListener('input', onInput);
|
|
186
268
|
input.removeEventListener('keydown', onKey);
|
|
187
269
|
list.removeEventListener('click', onOptionClick);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} CommandSelectDetail
|
|
3
|
+
* @property {string} value The chosen command's value.
|
|
4
|
+
* @property {string} label The chosen command's visible label.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Command palette — filter + keyboard-navigate a DOM-authored command list.
|
|
8
|
+
* The CSS shell (`.ui-command`) is opt-in; this wires the listbox behavior the
|
|
9
|
+
* shell needs. Bronto filters and navigates; the HOST owns the action registry,
|
|
10
|
+
* permission checks, routing, async effects, and command execution (it listens
|
|
11
|
+
* for `bronto:command:select`). There is no global Cmd/Ctrl+K — open the palette
|
|
12
|
+
* yourself (e.g. a `<dialog>` via `initDialog`).
|
|
13
|
+
*
|
|
14
|
+
* Markup: `[data-bronto-command]` wrapping an `<input>` (`.ui-command__input`)
|
|
15
|
+
* and a list (`.ui-command__list`) of `.ui-command__item` rows (optional
|
|
16
|
+
* `data-value`), interleaved with `.ui-command__group` labels and an optional
|
|
17
|
+
* `.ui-command__empty`. The behavior owns ids, `role=combobox/listbox/option`,
|
|
18
|
+
* `aria-activedescendant`, a roving active item, substring filtering (hiding
|
|
19
|
+
* empty groups), full keyboard (Down/Up/Home/End/Enter/Escape), and pointer
|
|
20
|
+
* select. It emits `bronto:command:select` ({ detail: { value, label } }) on
|
|
21
|
+
* choose and `bronto:command:close` on Escape. SSR-safe, idempotent per
|
|
22
|
+
* instance; returns a cleanup function.
|
|
23
|
+
*
|
|
24
|
+
* Items are read from the DOM at init; re-run initCommand after replacing the
|
|
25
|
+
* command list so filtering/navigation see the current nodes.
|
|
26
|
+
*
|
|
27
|
+
* @param {import('./internal.js').DelegateOpts} [opts]
|
|
28
|
+
* @returns {import('./internal.js').Cleanup}
|
|
29
|
+
*/
|
|
30
|
+
export function initCommand({ root }?: import("./internal.js").DelegateOpts): import("./internal.js").Cleanup;
|
|
31
|
+
export type CommandSelectDetail = {
|
|
32
|
+
/**
|
|
33
|
+
* The chosen command's value.
|
|
34
|
+
*/
|
|
35
|
+
value: string;
|
|
36
|
+
/**
|
|
37
|
+
* The chosen command's visible label.
|
|
38
|
+
*/
|
|
39
|
+
label: string;
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["command.js"],"names":[],"mappings":"AAWA;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,uCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CA+J3C;;;;;WAzLa,MAAM;;;;WACN,MAAM"}
|
package/behaviors/command.js
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
hasDom,
|
|
3
|
+
resolveHost,
|
|
4
|
+
noop,
|
|
5
|
+
bindOnce,
|
|
6
|
+
nextFieldUid,
|
|
7
|
+
collectHosts,
|
|
8
|
+
scrollIntoViewSafe,
|
|
9
|
+
wrapIndex,
|
|
10
|
+
} from './internal.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {object} CommandSelectDetail
|
|
14
|
+
* @property {string} value The chosen command's value.
|
|
15
|
+
* @property {string} label The chosen command's visible label.
|
|
16
|
+
*/
|
|
2
17
|
|
|
3
18
|
/**
|
|
4
19
|
* Command palette — filter + keyboard-navigate a DOM-authored command list.
|
|
@@ -17,13 +32,18 @@ import { hasDom, noop, bindOnce, nextFieldUid } from './internal.js';
|
|
|
17
32
|
* select. It emits `bronto:command:select` ({ detail: { value, label } }) on
|
|
18
33
|
* choose and `bronto:command:close` on Escape. SSR-safe, idempotent per
|
|
19
34
|
* instance; returns a cleanup function.
|
|
35
|
+
*
|
|
36
|
+
* Items are read from the DOM at init; re-run initCommand after replacing the
|
|
37
|
+
* command list so filtering/navigation see the current nodes.
|
|
38
|
+
*
|
|
39
|
+
* @param {import('./internal.js').DelegateOpts} [opts]
|
|
40
|
+
* @returns {import('./internal.js').Cleanup}
|
|
20
41
|
*/
|
|
21
42
|
export function initCommand({ root } = {}) {
|
|
22
43
|
if (!hasDom()) return noop;
|
|
23
|
-
const host = root
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
palettes.push(...(host.querySelectorAll?.('[data-bronto-command]') ?? []));
|
|
44
|
+
const host = resolveHost(root);
|
|
45
|
+
if (!host) return noop;
|
|
46
|
+
const palettes = collectHosts(host, '[data-bronto-command]');
|
|
27
47
|
const cleanups = [];
|
|
28
48
|
|
|
29
49
|
for (const box of palettes) {
|
|
@@ -58,11 +78,7 @@ export function initCommand({ root } = {}) {
|
|
|
58
78
|
if (item) {
|
|
59
79
|
active = items.indexOf(item);
|
|
60
80
|
input.setAttribute('aria-activedescendant', item.id);
|
|
61
|
-
|
|
62
|
-
item.scrollIntoView({ block: 'nearest' });
|
|
63
|
-
} catch {
|
|
64
|
-
/* headless — scrollIntoView is a pure affordance */
|
|
65
|
-
}
|
|
81
|
+
scrollIntoViewSafe(item);
|
|
66
82
|
} else {
|
|
67
83
|
active = -1;
|
|
68
84
|
input.removeAttribute('aria-activedescendant');
|
|
@@ -101,11 +117,7 @@ export function initCommand({ root } = {}) {
|
|
|
101
117
|
const move = (delta) => {
|
|
102
118
|
const vis = visible();
|
|
103
119
|
if (!vis.length) return;
|
|
104
|
-
|
|
105
|
-
let next = cur + delta;
|
|
106
|
-
if (next < 0) next = vis.length - 1;
|
|
107
|
-
if (next >= vis.length) next = 0;
|
|
108
|
-
setActive(vis[next]);
|
|
120
|
+
setActive(vis[wrapIndex(vis.indexOf(items[active]), delta, vis.length)]);
|
|
109
121
|
};
|
|
110
122
|
|
|
111
123
|
const choose = (item) => {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Draw + keep leader lines in sync. Each `[data-bronto-connector]` is an
|
|
3
|
+
* `.ui-connector` SVG overlaying a positioned container; `data-from`/`data-to`
|
|
4
|
+
* are the ids of the elements to connect. Optional `data-shape`
|
|
5
|
+
* (`straight`|`elbow`|`curve`), `data-from-side`/`data-to-side`
|
|
6
|
+
* (`top`|`right`|`bottom`|`left`|`center`), and `data-end` (`arrow`|`dot`|`none`).
|
|
7
|
+
*
|
|
8
|
+
* Bronto computes the geometry (the pure `@ponchia/ui/connectors` helpers) and
|
|
9
|
+
* sets the path; it owns no layout. Redraws on resize/scroll via a
|
|
10
|
+
* ResizeObserver + listeners. SSR-safe, idempotent per host; returns a cleanup
|
|
11
|
+
* that disconnects everything. Re-run after adding/removing connectors.
|
|
12
|
+
*
|
|
13
|
+
* @param {import('./internal.js').DelegateOpts} [opts]
|
|
14
|
+
* @returns {import('./internal.js').Cleanup}
|
|
15
|
+
*/
|
|
16
|
+
export function initConnectors({ root }?: import("./internal.js").DelegateOpts): import("./internal.js").Cleanup;
|
|
17
|
+
//# sourceMappingURL=connectors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectors.d.ts","sourceRoot":"","sources":["connectors.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AACH,0CAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CA+E3C"}
|
package/behaviors/connectors.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { hasDom, noop, bindOnce, byIdInHost } from './internal.js';
|
|
1
|
+
import { hasDom, resolveHost, noop, bindOnce, byIdInHost, collectHosts } from './internal.js';
|
|
2
2
|
import { connectRects, arrowHead, dotMark } from '../connectors/index.js';
|
|
3
3
|
|
|
4
4
|
const SVGNS = 'http://www.w3.org/2000/svg';
|
|
@@ -14,13 +14,15 @@ const SVGNS = 'http://www.w3.org/2000/svg';
|
|
|
14
14
|
* sets the path; it owns no layout. Redraws on resize/scroll via a
|
|
15
15
|
* ResizeObserver + listeners. SSR-safe, idempotent per host; returns a cleanup
|
|
16
16
|
* that disconnects everything. Re-run after adding/removing connectors.
|
|
17
|
+
*
|
|
18
|
+
* @param {import('./internal.js').DelegateOpts} [opts]
|
|
19
|
+
* @returns {import('./internal.js').Cleanup}
|
|
17
20
|
*/
|
|
18
21
|
export function initConnectors({ root } = {}) {
|
|
19
22
|
if (!hasDom()) return noop;
|
|
20
|
-
const host = root
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
connectors.push(...host.querySelectorAll('[data-bronto-connector]'));
|
|
23
|
+
const host = resolveHost(root);
|
|
24
|
+
if (!host) return noop;
|
|
25
|
+
const connectors = collectHosts(host, '[data-bronto-connector]');
|
|
24
26
|
if (!connectors.length) return noop;
|
|
25
27
|
|
|
26
28
|
const draw = () => {
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} CrosshairMoveDetail
|
|
3
|
+
* @property {number} x Pointer x within the plot, in pixels.
|
|
4
|
+
* @property {number} y Pointer y within the plot, in pixels.
|
|
5
|
+
* @property {number} fx Pointer x as a 0..1 fraction of the plot width.
|
|
6
|
+
* @property {number} fy Pointer y as a 0..1 fraction of the plot height.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Track the pointer over a plot and drive a crosshair. Each
|
|
10
|
+
* `[data-bronto-crosshair]` is the plot; it contains a `.ui-crosshair` overlay.
|
|
11
|
+
* On pointer move the behavior sets `--crosshair-x/y` (pixels within the plot)
|
|
12
|
+
* on the overlay, marks it `.is-active`, and dispatches
|
|
13
|
+
* `bronto:crosshair:move` with `{ x, y, fx, fy }` (px + 0..1 fractions);
|
|
14
|
+
* `bronto:crosshair:leave` on exit.
|
|
15
|
+
*
|
|
16
|
+
* Bronto reports WHERE the pointer is — it does not find the nearest datum or
|
|
17
|
+
* map pixels to data values (that needs the host's scales). SSR-safe,
|
|
18
|
+
* idempotent per plot; returns a cleanup function.
|
|
19
|
+
*
|
|
20
|
+
* @param {import('./internal.js').DelegateOpts} [opts]
|
|
21
|
+
* @returns {import('./internal.js').Cleanup}
|
|
22
|
+
*/
|
|
23
|
+
export function initCrosshair({ root }?: import("./internal.js").DelegateOpts): import("./internal.js").Cleanup;
|
|
24
|
+
export type CrosshairMoveDetail = {
|
|
25
|
+
/**
|
|
26
|
+
* Pointer x within the plot, in pixels.
|
|
27
|
+
*/
|
|
28
|
+
x: number;
|
|
29
|
+
/**
|
|
30
|
+
* Pointer y within the plot, in pixels.
|
|
31
|
+
*/
|
|
32
|
+
y: number;
|
|
33
|
+
/**
|
|
34
|
+
* Pointer x as a 0..1 fraction of the plot width.
|
|
35
|
+
*/
|
|
36
|
+
fx: number;
|
|
37
|
+
/**
|
|
38
|
+
* Pointer y as a 0..1 fraction of the plot height.
|
|
39
|
+
*/
|
|
40
|
+
fy: number;
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=crosshair.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crosshair.d.ts","sourceRoot":"","sources":["crosshair.js"],"names":[],"mappings":"AAEA;;;;;;GAMG;AAEH;;;;;;;;;;;;;;GAcG;AACH,yCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CAmD3C;;;;;OAtEa,MAAM;;;;OACN,MAAM;;;;QACN,MAAM;;;;QACN,MAAM"}
|
package/behaviors/crosshair.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import { hasDom, noop, bindOnce } from './internal.js';
|
|
1
|
+
import { hasDom, resolveHost, noop, bindOnce, collectHosts } from './internal.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {object} CrosshairMoveDetail
|
|
5
|
+
* @property {number} x Pointer x within the plot, in pixels.
|
|
6
|
+
* @property {number} y Pointer y within the plot, in pixels.
|
|
7
|
+
* @property {number} fx Pointer x as a 0..1 fraction of the plot width.
|
|
8
|
+
* @property {number} fy Pointer y as a 0..1 fraction of the plot height.
|
|
9
|
+
*/
|
|
2
10
|
|
|
3
11
|
/**
|
|
4
12
|
* Track the pointer over a plot and drive a crosshair. Each
|
|
@@ -11,13 +19,15 @@ import { hasDom, noop, bindOnce } from './internal.js';
|
|
|
11
19
|
* Bronto reports WHERE the pointer is — it does not find the nearest datum or
|
|
12
20
|
* map pixels to data values (that needs the host's scales). SSR-safe,
|
|
13
21
|
* idempotent per plot; returns a cleanup function.
|
|
22
|
+
*
|
|
23
|
+
* @param {import('./internal.js').DelegateOpts} [opts]
|
|
24
|
+
* @returns {import('./internal.js').Cleanup}
|
|
14
25
|
*/
|
|
15
26
|
export function initCrosshair({ root } = {}) {
|
|
16
27
|
if (!hasDom()) return noop;
|
|
17
|
-
const host = root
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
plots.push(...host.querySelectorAll('[data-bronto-crosshair]'));
|
|
28
|
+
const host = resolveHost(root);
|
|
29
|
+
if (!host) return noop;
|
|
30
|
+
const plots = collectHosts(host, '[data-bronto-crosshair]');
|
|
21
31
|
if (!plots.length) return noop;
|
|
22
32
|
|
|
23
33
|
const cleanups = [];
|
|
@@ -29,7 +39,14 @@ export function initCrosshair({ root } = {}) {
|
|
|
29
39
|
if (!r.width || !r.height) return;
|
|
30
40
|
const x = e.clientX - r.left;
|
|
31
41
|
const y = e.clientY - r.top;
|
|
32
|
-
|
|
42
|
+
// The CSS positions the vertical rule / readout with a *logical* inset
|
|
43
|
+
// (inset-inline-start), so --crosshair-x must be the distance from the
|
|
44
|
+
// inline-start edge — the physical left in LTR, the physical right in RTL.
|
|
45
|
+
// Emitting the physical x instead made the RTL rule land off-plot. The
|
|
46
|
+
// public `detail.x`/`fx` stay physical-from-left so host scale-mapping
|
|
47
|
+
// keeps one stable coordinate space regardless of direction.
|
|
48
|
+
const rtl = getComputedStyle(plot).direction === 'rtl';
|
|
49
|
+
overlay.style.setProperty('--crosshair-x', `${rtl ? r.right - e.clientX : x}px`);
|
|
33
50
|
overlay.style.setProperty('--crosshair-y', `${y}px`);
|
|
34
51
|
overlay.classList.add('is-active');
|
|
35
52
|
plot.dispatchEvent(
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire native <dialog> open/close glue (the one bit <dialog> can't do
|
|
3
|
+
* declaratively). Click `[data-bronto-open="dialogId"]` calls
|
|
4
|
+
* `showModal()` on `#dialogId`; click `[data-bronto-close]` closes the
|
|
5
|
+
* nearest enclosing <dialog>. Clicking the backdrop of a dialog that has
|
|
6
|
+
* `[data-bronto-dialog-light]` closes it too. On open the trigger is
|
|
7
|
+
* remembered and focus is returned to it on *every* close path (Esc,
|
|
8
|
+
* close button, backdrop light-dismiss, programmatic) via the native
|
|
9
|
+
* `close` event, so keyboard/SR users are never dropped at `<body>`.
|
|
10
|
+
* SSR-safe and idempotent; returns cleanup.
|
|
11
|
+
*
|
|
12
|
+
* `root` scopes delegated triggers (default `document`). Controlled targets are
|
|
13
|
+
* resolved root-first, then document-wide, so scoped islands win duplicate-id
|
|
14
|
+
* conflicts without breaking body/portal-mounted overlays.
|
|
15
|
+
*
|
|
16
|
+
* @param {import('./internal.js').DelegateOpts} [opts]
|
|
17
|
+
* @returns {import('./internal.js').Cleanup}
|
|
18
|
+
*/
|
|
19
|
+
export function initDialog({ root }?: import("./internal.js").DelegateOpts): import("./internal.js").Cleanup;
|
|
20
|
+
//# sourceMappingURL=dialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["dialog.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,sCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CA0D3C"}
|
package/behaviors/dialog.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { hasDom, noop, bindOnce, byIdInHost } from './internal.js';
|
|
1
|
+
import { hasDom, resolveHost, noop, bindOnce, byIdInHost } from './internal.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Wire native <dialog> open/close glue (the one bit <dialog> can't do
|
|
@@ -14,10 +14,14 @@ import { hasDom, noop, bindOnce, byIdInHost } from './internal.js';
|
|
|
14
14
|
* `root` scopes delegated triggers (default `document`). Controlled targets are
|
|
15
15
|
* resolved root-first, then document-wide, so scoped islands win duplicate-id
|
|
16
16
|
* conflicts without breaking body/portal-mounted overlays.
|
|
17
|
+
*
|
|
18
|
+
* @param {import('./internal.js').DelegateOpts} [opts]
|
|
19
|
+
* @returns {import('./internal.js').Cleanup}
|
|
17
20
|
*/
|
|
18
21
|
export function initDialog({ root } = {}) {
|
|
19
22
|
if (!hasDom()) return noop;
|
|
20
|
-
const host = root
|
|
23
|
+
const host = resolveHost(root);
|
|
24
|
+
if (!host) return noop;
|
|
21
25
|
const managedDialogs = new WeakSet();
|
|
22
26
|
const canManageDialog = (dlg, origin) => host.contains(origin) || managedDialogs.has(dlg);
|
|
23
27
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disclosure: a `[data-bronto-disclosure]` trigger toggles the element
|
|
3
|
+
* referenced by its `aria-controls` id, keeping `aria-expanded` and the
|
|
4
|
+
* panel's `hidden` attribute in sync.
|
|
5
|
+
*
|
|
6
|
+
* @param {import('./internal.js').DelegateOpts} [opts]
|
|
7
|
+
* @returns {import('./internal.js').Cleanup}
|
|
8
|
+
*/
|
|
9
|
+
export function initDisclosure({ root }?: import("./internal.js").DelegateOpts): import("./internal.js").Cleanup;
|
|
10
|
+
//# sourceMappingURL=disclosure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disclosure.d.ts","sourceRoot":"","sources":["disclosure.js"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,0CAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CAoB3C"}
|