@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/connectors.js
CHANGED
|
@@ -2,6 +2,80 @@ import { hasDom, resolveHost, noop, bindOnce, byIdInHost, collectHosts } from '.
|
|
|
2
2
|
import { connectRects, arrowHead, dotMark } from '../connectors/index.js';
|
|
3
3
|
|
|
4
4
|
const SVGNS = 'http://www.w3.org/2000/svg';
|
|
5
|
+
const NORMALIZED_PATH_LENGTH = '1';
|
|
6
|
+
const END_DOT_RADIUS = 3;
|
|
7
|
+
const END_ARROW_SIZE = 8;
|
|
8
|
+
|
|
9
|
+
const snapshotAttrs = (el) =>
|
|
10
|
+
Array.from(el.attributes, ({ name, value }) => ({
|
|
11
|
+
name,
|
|
12
|
+
value,
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
const restoreAttrs = (el, attrs) => {
|
|
16
|
+
for (const { name } of Array.from(el.attributes)) el.removeAttribute(name);
|
|
17
|
+
for (const { name, value } of attrs) el.setAttribute(name, value);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const snapshotPart = (svg, selector) => {
|
|
21
|
+
const node = svg.querySelector(selector);
|
|
22
|
+
if (!node) return { node: null };
|
|
23
|
+
return {
|
|
24
|
+
node,
|
|
25
|
+
attrs: snapshotAttrs(node),
|
|
26
|
+
parent: node.parentNode,
|
|
27
|
+
nextSibling: node.nextSibling,
|
|
28
|
+
textContent: node.textContent,
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const restorePart = (svg, selector, state) => {
|
|
33
|
+
if (!state.node) {
|
|
34
|
+
svg.querySelector(selector)?.remove();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const parent = state.parent || svg;
|
|
39
|
+
if (state.node.parentNode !== parent) {
|
|
40
|
+
const before = state.nextSibling?.parentNode === parent ? state.nextSibling : null;
|
|
41
|
+
parent.insertBefore(state.node, before);
|
|
42
|
+
}
|
|
43
|
+
restoreAttrs(state.node, state.attrs);
|
|
44
|
+
state.node.textContent = state.textContent;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const upsertConnectorPart = (svg, selector, className) => {
|
|
48
|
+
let part = svg.querySelector(selector);
|
|
49
|
+
if (part) return part;
|
|
50
|
+
part = document.createElementNS(SVGNS, 'path');
|
|
51
|
+
part.setAttribute('class', className);
|
|
52
|
+
svg.appendChild(part);
|
|
53
|
+
return part;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const syncDrawPathLength = (svg, path) => {
|
|
57
|
+
// pathLength normalises the draw animation, but it would also reframe a
|
|
58
|
+
// dashed line's user-unit dasharray — so only set it for draw connectors.
|
|
59
|
+
if (svg.classList.contains('ui-connector--draw')) {
|
|
60
|
+
path.setAttribute('pathLength', NORMALIZED_PATH_LENGTH);
|
|
61
|
+
} else {
|
|
62
|
+
path.removeAttribute('pathLength');
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const syncConnectorEnd = (svg, end, angle) => {
|
|
67
|
+
const kind = svg.dataset.end || 'arrow';
|
|
68
|
+
const cap = svg.querySelector('.ui-connector__end');
|
|
69
|
+
if (kind === 'none') {
|
|
70
|
+
cap?.remove();
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const next = cap || upsertConnectorPart(svg, '.ui-connector__end', 'ui-connector__end');
|
|
74
|
+
next.setAttribute(
|
|
75
|
+
'd',
|
|
76
|
+
kind === 'dot' ? dotMark(end, END_DOT_RADIUS) : arrowHead(end, angle, END_ARROW_SIZE),
|
|
77
|
+
);
|
|
78
|
+
};
|
|
5
79
|
|
|
6
80
|
/**
|
|
7
81
|
* Draw + keep leader lines in sync. Each `[data-bronto-connector]` is an
|
|
@@ -22,58 +96,79 @@ export function initConnectors({ root } = {}) {
|
|
|
22
96
|
if (!hasDom()) return noop;
|
|
23
97
|
const host = resolveHost(root);
|
|
24
98
|
if (!host) return noop;
|
|
25
|
-
|
|
26
|
-
|
|
99
|
+
|
|
100
|
+
const fallbackRect = (svg, el) => {
|
|
101
|
+
const origin = svg.getBoundingClientRect();
|
|
102
|
+
const r = el.getBoundingClientRect();
|
|
103
|
+
const scaleX = origin.width ? (svg.clientWidth || origin.width) / origin.width : 1;
|
|
104
|
+
const scaleY = origin.height ? (svg.clientHeight || origin.height) / origin.height : 1;
|
|
105
|
+
return {
|
|
106
|
+
x: (r.left - origin.left) * scaleX,
|
|
107
|
+
y: (r.top - origin.top) * scaleY,
|
|
108
|
+
width: r.width * scaleX,
|
|
109
|
+
height: r.height * scaleY,
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const rectInSvg = (svg, el) => {
|
|
114
|
+
const r = el.getBoundingClientRect();
|
|
115
|
+
const matrix = svg.getScreenCTM?.();
|
|
116
|
+
const view = svg.ownerDocument?.defaultView;
|
|
117
|
+
const Point = view?.DOMPoint;
|
|
118
|
+
if (!matrix || !Point) return fallbackRect(svg, el);
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
const inverse = matrix.inverse();
|
|
122
|
+
const corners = [
|
|
123
|
+
new Point(r.left, r.top),
|
|
124
|
+
new Point(r.right, r.top),
|
|
125
|
+
new Point(r.right, r.bottom),
|
|
126
|
+
new Point(r.left, r.bottom),
|
|
127
|
+
].map((point) => point.matrixTransform(inverse));
|
|
128
|
+
const xs = corners.map((point) => point.x);
|
|
129
|
+
const ys = corners.map((point) => point.y);
|
|
130
|
+
const left = Math.min(...xs);
|
|
131
|
+
const right = Math.max(...xs);
|
|
132
|
+
const top = Math.min(...ys);
|
|
133
|
+
const bottom = Math.max(...ys);
|
|
134
|
+
return { x: left, y: top, width: right - left, height: bottom - top };
|
|
135
|
+
} catch {
|
|
136
|
+
return fallbackRect(svg, el);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
27
139
|
|
|
28
140
|
const draw = () => {
|
|
141
|
+
const connectors = collectHosts(host, '[data-bronto-connector]');
|
|
29
142
|
for (const svg of connectors) {
|
|
30
143
|
const from = byIdInHost(host, svg.dataset.from);
|
|
31
144
|
const to = byIdInHost(host, svg.dataset.to);
|
|
32
145
|
if (!from || !to) continue;
|
|
33
|
-
const o = svg.getBoundingClientRect();
|
|
34
|
-
const rel = (el) => {
|
|
35
|
-
const r = el.getBoundingClientRect();
|
|
36
|
-
return { x: r.left - o.left, y: r.top - o.top, width: r.width, height: r.height };
|
|
37
|
-
};
|
|
38
146
|
const {
|
|
39
147
|
d,
|
|
40
148
|
to: end,
|
|
41
149
|
angle,
|
|
42
150
|
} = connectRects({
|
|
43
|
-
fromRect:
|
|
44
|
-
toRect:
|
|
151
|
+
fromRect: rectInSvg(svg, from),
|
|
152
|
+
toRect: rectInSvg(svg, to),
|
|
45
153
|
shape: svg.dataset.shape || 'straight',
|
|
46
154
|
fromSide: svg.dataset.fromSide || undefined,
|
|
47
155
|
toSide: svg.dataset.toSide || undefined,
|
|
48
156
|
});
|
|
49
|
-
|
|
50
|
-
if (!path) {
|
|
51
|
-
path = document.createElementNS(SVGNS, 'path');
|
|
52
|
-
path.setAttribute('class', 'ui-connector__path');
|
|
53
|
-
svg.appendChild(path);
|
|
54
|
-
}
|
|
157
|
+
const path = upsertConnectorPart(svg, '.ui-connector__path', 'ui-connector__path');
|
|
55
158
|
path.setAttribute('d', d);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (svg.classList.contains('ui-connector--draw')) path.setAttribute('pathLength', '1');
|
|
59
|
-
else path.removeAttribute('pathLength');
|
|
60
|
-
|
|
61
|
-
const kind = svg.dataset.end || 'arrow';
|
|
62
|
-
let cap = svg.querySelector('.ui-connector__end');
|
|
63
|
-
if (kind === 'none') {
|
|
64
|
-
cap?.remove();
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
if (!cap) {
|
|
68
|
-
cap = document.createElementNS(SVGNS, 'path');
|
|
69
|
-
cap.setAttribute('class', 'ui-connector__end');
|
|
70
|
-
svg.appendChild(cap);
|
|
71
|
-
}
|
|
72
|
-
cap.setAttribute('d', kind === 'dot' ? dotMark(end, 3) : arrowHead(end, angle, 8));
|
|
159
|
+
syncDrawPathLength(svg, path);
|
|
160
|
+
syncConnectorEnd(svg, end, angle);
|
|
73
161
|
}
|
|
74
162
|
};
|
|
75
163
|
|
|
76
164
|
return bindOnce(host, 'connectors', () => {
|
|
165
|
+
const connectors = collectHosts(host, '[data-bronto-connector]');
|
|
166
|
+
if (!connectors.length) return noop;
|
|
167
|
+
const states = connectors.map((svg) => ({
|
|
168
|
+
svg,
|
|
169
|
+
path: snapshotPart(svg, '.ui-connector__path'),
|
|
170
|
+
end: snapshotPart(svg, '.ui-connector__end'),
|
|
171
|
+
}));
|
|
77
172
|
draw();
|
|
78
173
|
const view = host.defaultView || host.ownerDocument?.defaultView || null;
|
|
79
174
|
const RO = view?.ResizeObserver;
|
|
@@ -93,6 +188,10 @@ export function initConnectors({ root } = {}) {
|
|
|
93
188
|
ro?.disconnect();
|
|
94
189
|
view?.removeEventListener('resize', draw);
|
|
95
190
|
view?.removeEventListener('scroll', draw, true);
|
|
191
|
+
for (const state of states) {
|
|
192
|
+
restorePart(state.svg, '.ui-connector__path', state.path);
|
|
193
|
+
restorePart(state.svg, '.ui-connector__end', state.end);
|
|
194
|
+
}
|
|
96
195
|
};
|
|
97
196
|
});
|
|
98
197
|
}
|
|
@@ -1 +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,
|
|
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,CAiG3C;;;;;OApHa,MAAM;;;;OACN,MAAM;;;;QACN,MAAM;;;;QACN,MAAM"}
|
package/behaviors/crosshair.js
CHANGED
|
@@ -33,8 +33,49 @@ export function initCrosshair({ root } = {}) {
|
|
|
33
33
|
const cleanups = [];
|
|
34
34
|
for (const plot of plots) {
|
|
35
35
|
const overlay = plot.querySelector('.ui-crosshair');
|
|
36
|
-
|
|
36
|
+
let overlayState = null;
|
|
37
|
+
const rememberOverlay = () => {
|
|
38
|
+
if (!overlay || overlayState) return;
|
|
39
|
+
overlayState = {
|
|
40
|
+
active: overlay.classList.contains('is-active'),
|
|
41
|
+
x: {
|
|
42
|
+
value: overlay.style.getPropertyValue('--crosshair-x'),
|
|
43
|
+
priority: overlay.style.getPropertyPriority('--crosshair-x'),
|
|
44
|
+
},
|
|
45
|
+
y: {
|
|
46
|
+
value: overlay.style.getPropertyValue('--crosshair-y'),
|
|
47
|
+
priority: overlay.style.getPropertyPriority('--crosshair-y'),
|
|
48
|
+
},
|
|
49
|
+
inline: {
|
|
50
|
+
had: overlay.hasAttribute('data-readout-inline'),
|
|
51
|
+
value: overlay.getAttribute('data-readout-inline'),
|
|
52
|
+
},
|
|
53
|
+
block: {
|
|
54
|
+
had: overlay.hasAttribute('data-readout-block'),
|
|
55
|
+
value: overlay.getAttribute('data-readout-block'),
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
const restoreData = (name, state) => {
|
|
60
|
+
if (state.had) overlay.setAttribute(name, state.value);
|
|
61
|
+
else overlay.removeAttribute(name);
|
|
62
|
+
};
|
|
63
|
+
const restoreOverlay = () => {
|
|
64
|
+
if (!overlay || !overlayState) return;
|
|
65
|
+
overlay.classList.toggle('is-active', overlayState.active);
|
|
66
|
+
if (overlayState.x.value)
|
|
67
|
+
overlay.style.setProperty('--crosshair-x', overlayState.x.value, overlayState.x.priority);
|
|
68
|
+
else overlay.style.removeProperty('--crosshair-x');
|
|
69
|
+
if (overlayState.y.value)
|
|
70
|
+
overlay.style.setProperty('--crosshair-y', overlayState.y.value, overlayState.y.priority);
|
|
71
|
+
else overlay.style.removeProperty('--crosshair-y');
|
|
72
|
+
restoreData('data-readout-inline', overlayState.inline);
|
|
73
|
+
restoreData('data-readout-block', overlayState.block);
|
|
74
|
+
overlayState = null;
|
|
75
|
+
};
|
|
37
76
|
const onMove = (e) => {
|
|
77
|
+
if (!overlay) return;
|
|
78
|
+
rememberOverlay();
|
|
38
79
|
const r = plot.getBoundingClientRect();
|
|
39
80
|
if (!r.width || !r.height) return;
|
|
40
81
|
const x = e.clientX - r.left;
|
|
@@ -48,6 +89,8 @@ export function initCrosshair({ root } = {}) {
|
|
|
48
89
|
const rtl = getComputedStyle(plot).direction === 'rtl';
|
|
49
90
|
overlay.style.setProperty('--crosshair-x', `${rtl ? r.right - e.clientX : x}px`);
|
|
50
91
|
overlay.style.setProperty('--crosshair-y', `${y}px`);
|
|
92
|
+
overlay.dataset.readoutInline = x / r.width > 0.5 ? 'before' : 'after';
|
|
93
|
+
overlay.dataset.readoutBlock = y / r.height > 0.5 ? 'above' : 'below';
|
|
51
94
|
overlay.classList.add('is-active');
|
|
52
95
|
plot.dispatchEvent(
|
|
53
96
|
new CustomEvent('bronto:crosshair:move', {
|
|
@@ -57,16 +100,19 @@ export function initCrosshair({ root } = {}) {
|
|
|
57
100
|
);
|
|
58
101
|
};
|
|
59
102
|
const onLeave = () => {
|
|
103
|
+
if (!overlay) return;
|
|
60
104
|
overlay.classList.remove('is-active');
|
|
61
105
|
plot.dispatchEvent(new CustomEvent('bronto:crosshair:leave', { bubbles: true }));
|
|
62
106
|
};
|
|
63
107
|
cleanups.push(
|
|
64
108
|
bindOnce(plot, 'crosshair', () => {
|
|
109
|
+
if (!overlay) return noop;
|
|
65
110
|
plot.addEventListener('pointermove', onMove);
|
|
66
111
|
plot.addEventListener('pointerleave', onLeave);
|
|
67
112
|
return () => {
|
|
68
113
|
plot.removeEventListener('pointermove', onMove);
|
|
69
114
|
plot.removeEventListener('pointerleave', onLeave);
|
|
115
|
+
restoreOverlay();
|
|
70
116
|
};
|
|
71
117
|
}),
|
|
72
118
|
);
|
|
@@ -1 +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,
|
|
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,CA+E3C"}
|
package/behaviors/dialog.js
CHANGED
|
@@ -28,20 +28,32 @@ export function initDialog({ root } = {}) {
|
|
|
28
28
|
|
|
29
29
|
const openFrom = (opener) => {
|
|
30
30
|
const dlg = byIdInHost(host, opener.getAttribute('data-bronto-open'));
|
|
31
|
-
if (!dlg || typeof dlg.showModal !== 'function' || dlg.open) return;
|
|
32
|
-
|
|
31
|
+
if (!dlg || typeof dlg.showModal !== 'function' || dlg.open) return false;
|
|
32
|
+
const previous = focusRestorers.get(dlg);
|
|
33
|
+
if (previous) {
|
|
34
|
+
dlg.removeEventListener('close', previous);
|
|
35
|
+
focusRestorers.delete(dlg);
|
|
36
|
+
}
|
|
33
37
|
const restoreFocus = () => {
|
|
34
38
|
focusRestorers.delete(dlg);
|
|
35
39
|
if (opener.isConnected && typeof opener.focus === 'function') opener.focus();
|
|
36
40
|
};
|
|
41
|
+
try {
|
|
42
|
+
dlg.showModal();
|
|
43
|
+
} catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
managedDialogs.add(dlg);
|
|
37
47
|
focusRestorers.set(dlg, restoreFocus);
|
|
38
48
|
dlg.addEventListener('close', restoreFocus, { once: true });
|
|
39
|
-
|
|
49
|
+
return true;
|
|
40
50
|
};
|
|
41
51
|
|
|
42
52
|
const closeFrom = (closer) => {
|
|
43
53
|
const dlg = closer.closest('dialog');
|
|
44
|
-
if (dlg
|
|
54
|
+
if (!dlg || !dlg.open || !canManageDialog(dlg, closer)) return false;
|
|
55
|
+
dlg.close();
|
|
56
|
+
return true;
|
|
45
57
|
};
|
|
46
58
|
|
|
47
59
|
const lightDismiss = (dlg) => {
|
|
@@ -52,23 +64,26 @@ export function initDialog({ root } = {}) {
|
|
|
52
64
|
canManageDialog(dlg, dlg)
|
|
53
65
|
) {
|
|
54
66
|
dlg.close();
|
|
67
|
+
return true;
|
|
55
68
|
}
|
|
69
|
+
return false;
|
|
56
70
|
};
|
|
57
71
|
|
|
58
72
|
const onClick = (e) => {
|
|
59
|
-
const
|
|
73
|
+
const target = e.target;
|
|
74
|
+
const opener = target?.closest?.('[data-bronto-open]');
|
|
60
75
|
if (opener && host.contains(opener)) {
|
|
61
|
-
openFrom(opener);
|
|
76
|
+
if (openFrom(opener)) e.preventDefault();
|
|
62
77
|
return;
|
|
63
78
|
}
|
|
64
|
-
const closer =
|
|
79
|
+
const closer = target?.closest?.('[data-bronto-close]');
|
|
65
80
|
if (closer) {
|
|
66
|
-
closeFrom(closer);
|
|
81
|
+
if (closeFrom(closer)) e.preventDefault();
|
|
67
82
|
return;
|
|
68
83
|
}
|
|
69
84
|
// Light-dismiss: a click whose target is the <dialog> itself is the
|
|
70
85
|
// backdrop (content sits in child elements).
|
|
71
|
-
lightDismiss(e.
|
|
86
|
+
if (lightDismiss(target)) e.preventDefault();
|
|
72
87
|
};
|
|
73
88
|
return bindOnce(host, 'dialog', () => {
|
|
74
89
|
document.addEventListener('click', onClick);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"disclosure.d.ts","sourceRoot":"","sources":["disclosure.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"disclosure.d.ts","sourceRoot":"","sources":["disclosure.js"],"names":[],"mappings":"AAYA;;;;;;;GAOG;AACH,0CAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CAwC3C"}
|
package/behaviors/disclosure.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import { hasDom, resolveHost, noop, bindOnce, byIdInHost } from './internal.js';
|
|
1
|
+
import { hasDom, resolveHost, noop, bindOnce, byIdInHost, closestSafe } from './internal.js';
|
|
2
|
+
|
|
3
|
+
const snapshotAttr = (el, name) => ({
|
|
4
|
+
had: el.hasAttribute(name),
|
|
5
|
+
value: el.getAttribute(name),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
const restoreAttr = (el, name, state) => {
|
|
9
|
+
if (state.had) el.setAttribute(name, state.value);
|
|
10
|
+
else el.removeAttribute(name);
|
|
11
|
+
};
|
|
2
12
|
|
|
3
13
|
/**
|
|
4
14
|
* Disclosure: a `[data-bronto-disclosure]` trigger toggles the element
|
|
@@ -12,18 +22,38 @@ export function initDisclosure({ root } = {}) {
|
|
|
12
22
|
if (!hasDom()) return noop;
|
|
13
23
|
const host = resolveHost(root);
|
|
14
24
|
if (!host) return noop;
|
|
25
|
+
const triggerStates = new Map();
|
|
26
|
+
const panelStates = new Map();
|
|
27
|
+
|
|
28
|
+
const remember = (trigger, panel) => {
|
|
29
|
+
if (!triggerStates.has(trigger)) {
|
|
30
|
+
triggerStates.set(trigger, snapshotAttr(trigger, 'aria-expanded'));
|
|
31
|
+
}
|
|
32
|
+
if (!panelStates.has(panel)) {
|
|
33
|
+
panelStates.set(panel, snapshotAttr(panel, 'hidden'));
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
15
37
|
const onClick = (e) => {
|
|
16
|
-
const trigger = e.target
|
|
38
|
+
const trigger = closestSafe(e.target, '[data-bronto-disclosure]');
|
|
17
39
|
if (!trigger || !host.contains(trigger)) return;
|
|
18
40
|
const id = trigger.getAttribute('aria-controls');
|
|
19
41
|
const panel = byIdInHost(host, id);
|
|
20
42
|
if (!panel) return;
|
|
43
|
+
e.preventDefault();
|
|
44
|
+
remember(trigger, panel);
|
|
21
45
|
const open = trigger.getAttribute('aria-expanded') === 'true';
|
|
22
46
|
trigger.setAttribute('aria-expanded', String(!open));
|
|
23
47
|
panel.hidden = open;
|
|
24
48
|
};
|
|
25
49
|
return bindOnce(host, 'disclosure', () => {
|
|
26
50
|
host.addEventListener('click', onClick);
|
|
27
|
-
return () =>
|
|
51
|
+
return () => {
|
|
52
|
+
host.removeEventListener('click', onClick);
|
|
53
|
+
for (const [trigger, state] of triggerStates) restoreAttr(trigger, 'aria-expanded', state);
|
|
54
|
+
triggerStates.clear();
|
|
55
|
+
for (const [panel, state] of panelStates) restoreAttr(panel, 'hidden', state);
|
|
56
|
+
panelStates.clear();
|
|
57
|
+
};
|
|
28
58
|
});
|
|
29
59
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dismissible.d.ts","sourceRoot":"","sources":["dismissible.js"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,uCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"dismissible.d.ts","sourceRoot":"","sources":["dismissible.js"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,uCAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CAoB3C"}
|
package/behaviors/dismissible.js
CHANGED
|
@@ -13,11 +13,12 @@ export function dismissible({ root } = {}) {
|
|
|
13
13
|
const host = resolveHost(root);
|
|
14
14
|
if (!host) return noop;
|
|
15
15
|
const onClick = (e) => {
|
|
16
|
-
const btn = e.target
|
|
16
|
+
const btn = closestSafe(e.target, '[data-bronto-dismiss]');
|
|
17
17
|
if (!btn || !host.contains(btn)) return;
|
|
18
18
|
const sel = btn.getAttribute('data-bronto-dismiss');
|
|
19
|
-
const target = sel ? closestSafe(btn, sel) : btn
|
|
19
|
+
const target = sel ? closestSafe(btn, sel) : closestSafe(btn, '[data-bronto-dismissible]');
|
|
20
20
|
if (!target) return;
|
|
21
|
+
e.preventDefault();
|
|
21
22
|
const ev = new CustomEvent('bronto:dismiss', { bubbles: true, cancelable: true });
|
|
22
23
|
if (target.dispatchEvent(ev)) target.remove();
|
|
23
24
|
};
|
package/behaviors/forms.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forms.d.ts","sourceRoot":"","sources":["forms.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"forms.d.ts","sourceRoot":"","sources":["forms.js"],"names":[],"mappings":"AAiMA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,8CAHW,OAAO,eAAe,EAAE,YAAY,GAClC,OAAO,eAAe,EAAE,OAAO,CA2D3C"}
|