@smwb/ui-solid 1.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -0
- package/dist/assets/styles/less/components/appBar/appBar.entry.css +1 -1
- package/dist/assets/styles/less/components/avatar/avatar.entry.css +1 -1
- package/dist/assets/styles/less/components/badge/badge.entry.css +1 -1
- package/dist/assets/styles/less/components/breadcrumbs/breadcrumbs.entry.css +1 -1
- package/dist/assets/styles/less/components/button/button.entry.css +1 -1
- package/dist/assets/styles/less/components/buttonGroup/buttonGroup.entry.css +1 -1
- package/dist/assets/styles/less/components/dagView/dagView.entry.css +1 -1
- package/dist/assets/styles/less/components/meter/meter.entry.css +1 -1
- package/dist/assets/styles/less/components/screenDivider/screenDivider.entry.css +1 -1
- package/dist/assets/styles/less/components/sheet/sheet.entry.css +1 -1
- package/dist/assets/styles/less/components/statusDot/statusDot.entry.css +1 -1
- package/dist/assets/styles/less/components/tabGroups/tabGroups.entry.css +1 -1
- package/dist/assets/styles/less/components/tabs/tab/tab.entry.css +1 -1
- package/dist/assets/styles/less/components/toggle/toggle.entry.css +1 -1
- package/dist/assets/styles/less/components/treeView/treeView.entry.css +1 -1
- package/dist/assets/styles/less/tokens.entry.css +1 -1
- package/dist/components/dataDisplay/avatar/avatar.d.ts +5 -2
- package/dist/components/dataDisplay/avatar/avatar.js +9 -9
- package/dist/components/dataDisplay/avatar/avatar.js.map +1 -1
- package/dist/components/dataDisplay/badge/badge.d.ts +2 -1
- package/dist/components/dataDisplay/badge/badge.js.map +1 -1
- package/dist/components/dataDisplay/chart/chart.d.ts +16 -8
- package/dist/components/dataDisplay/chart/chartFull.d.ts +14 -0
- package/dist/components/dataDisplay/chart/core.d.ts +19 -0
- package/dist/components/dataDisplay/chart/index.d.ts +1 -1
- package/dist/components/dataDisplay/dagView/dagView.d.ts +4 -0
- package/dist/components/dataDisplay/dagView/dagView.js +124 -123
- package/dist/components/dataDisplay/dagView/dagView.js.map +1 -1
- package/dist/components/dataDisplay/dagView/index.d.ts +1 -1
- package/dist/components/dataDisplay/meter/index.d.ts +1 -1
- package/dist/components/dataDisplay/meter/meter.d.ts +14 -0
- package/dist/components/dataDisplay/meter/meter.js +32 -30
- package/dist/components/dataDisplay/meter/meter.js.map +1 -1
- package/dist/components/dataDisplay/statusDot/index.d.ts +1 -1
- package/dist/components/dataDisplay/statusDot/statusDot.d.ts +10 -1
- package/dist/components/dataDisplay/statusDot/statusDot.js +20 -11
- package/dist/components/dataDisplay/statusDot/statusDot.js.map +1 -1
- package/dist/components/dataDisplay/treeView/treeView.d.ts +18 -2
- package/dist/components/dataDisplay/treeView/treeView.js +140 -121
- package/dist/components/dataDisplay/treeView/treeView.js.map +1 -1
- package/dist/components/inputs/button/button.d.ts +7 -0
- package/dist/components/inputs/button/button.js +57 -51
- package/dist/components/inputs/button/button.js.map +1 -1
- package/dist/components/inputs/toggle/toggle.d.ts +6 -0
- package/dist/components/inputs/toggle/toggle.js +23 -23
- package/dist/components/inputs/toggle/toggle.js.map +1 -1
- package/dist/components/layout/appLayout/appLayout.d.ts +6 -1
- package/dist/components/layout/appLayout/appLayout.js +49 -42
- package/dist/components/layout/appLayout/appLayout.js.map +1 -1
- package/dist/components/layout/screenDivider/screenDivider.d.ts +12 -0
- package/dist/components/layout/screenDivider/screenDivider.js +87 -46
- package/dist/components/layout/screenDivider/screenDivider.js.map +1 -1
- package/dist/components/layout/sheet/sheet.d.ts +11 -0
- package/dist/components/layout/sheet/sheet.js +122 -102
- package/dist/components/layout/sheet/sheet.js.map +1 -1
- package/dist/components/layout/tabGroups/index.d.ts +1 -1
- package/dist/components/layout/tabGroups/tabGroups.d.ts +44 -1
- package/dist/components/layout/tabGroups/tabGroups.js +500 -460
- package/dist/components/layout/tabGroups/tabGroups.js.map +1 -1
- package/dist/components/layout/tabGroups/tabGroupsFocus.d.ts +16 -0
- package/dist/components/layout/tabGroups/tabGroupsFocus.js +102 -70
- package/dist/components/layout/tabGroups/tabGroupsFocus.js.map +1 -1
- package/dist/components/navigation/appBar/appBar.d.ts +12 -0
- package/dist/components/navigation/appBar/appBar.js.map +1 -1
- package/dist/components/navigation/breadcrumbs/breadcrumbs.d.ts +9 -0
- package/dist/components/navigation/breadcrumbs/breadcrumbs.js +47 -31
- package/dist/components/navigation/breadcrumbs/breadcrumbs.js.map +1 -1
- package/dist/components/navigation/tabs/tab/tab.js +71 -68
- package/dist/components/navigation/tabs/tab/tab.js.map +1 -1
- package/dist/components/navigation/tabs/tabs.d.ts +15 -1
- package/dist/components/navigation/tabs/tabs.js +19 -16
- package/dist/components/navigation/tabs/tabs.js.map +1 -1
- package/dist/components/navigation/tabs/tabsContext.d.ts +2 -0
- package/dist/components/navigation/tabs/tabsContext.js.map +1 -1
- package/dist/headless/components/dataDisplay/avatar/avatar.js +9 -9
- package/dist/headless/components/dataDisplay/avatar/avatar.js.map +1 -1
- package/dist/headless/components/dataDisplay/badge/badge.js.map +1 -1
- package/dist/headless/components/dataDisplay/dagView/dagView.js +133 -132
- package/dist/headless/components/dataDisplay/dagView/dagView.js.map +1 -1
- package/dist/headless/components/dataDisplay/meter/meter.js +32 -30
- package/dist/headless/components/dataDisplay/meter/meter.js.map +1 -1
- package/dist/headless/components/dataDisplay/statusDot/statusDot.js +19 -10
- package/dist/headless/components/dataDisplay/statusDot/statusDot.js.map +1 -1
- package/dist/headless/components/dataDisplay/treeView/treeView.js +139 -120
- package/dist/headless/components/dataDisplay/treeView/treeView.js.map +1 -1
- package/dist/headless/components/inputs/button/button.js +57 -51
- package/dist/headless/components/inputs/button/button.js.map +1 -1
- package/dist/headless/components/inputs/toggle/toggle.js +23 -23
- package/dist/headless/components/inputs/toggle/toggle.js.map +1 -1
- package/dist/headless/components/layout/appLayout/appLayout.js +52 -45
- package/dist/headless/components/layout/appLayout/appLayout.js.map +1 -1
- package/dist/headless/components/layout/screenDivider/screenDivider.js +88 -47
- package/dist/headless/components/layout/screenDivider/screenDivider.js.map +1 -1
- package/dist/headless/components/layout/sheet/sheet.js +124 -104
- package/dist/headless/components/layout/sheet/sheet.js.map +1 -1
- package/dist/headless/components/layout/tabGroups/tabGroups.js +500 -460
- package/dist/headless/components/layout/tabGroups/tabGroups.js.map +1 -1
- package/dist/headless/components/layout/tabGroups/tabGroupsFocus.js +102 -70
- package/dist/headless/components/layout/tabGroups/tabGroupsFocus.js.map +1 -1
- package/dist/headless/components/navigation/appBar/appBar.js.map +1 -1
- package/dist/headless/components/navigation/breadcrumbs/breadcrumbs.js +46 -30
- package/dist/headless/components/navigation/breadcrumbs/breadcrumbs.js.map +1 -1
- package/dist/headless/components/navigation/tabs/tab/tab.js +70 -67
- package/dist/headless/components/navigation/tabs/tab/tab.js.map +1 -1
- package/dist/headless/components/navigation/tabs/tabs.js +19 -16
- package/dist/headless/components/navigation/tabs/tabs.js.map +1 -1
- package/dist/headless/components/navigation/tabs/tabsContext.js.map +1 -1
- package/dist/headless/primitives/publishHeaderOffset.js +19 -0
- package/dist/headless/primitives/publishHeaderOffset.js.map +1 -0
- package/dist/headless/source/components/dataDisplay/avatar/avatar.jsx +1 -0
- package/dist/headless/source/components/dataDisplay/avatar/avatar.jsx.map +1 -1
- package/dist/headless/source/components/dataDisplay/badge/badge.jsx.map +1 -1
- package/dist/headless/source/components/dataDisplay/chart/chart.jsx +14 -12
- package/dist/headless/source/components/dataDisplay/chart/chart.jsx.map +1 -1
- package/dist/headless/source/components/dataDisplay/chart/chartFull.js +12 -0
- package/dist/headless/source/components/dataDisplay/chart/chartFull.js.map +7 -0
- package/dist/headless/source/components/dataDisplay/chart/core.js +11 -0
- package/dist/headless/source/components/dataDisplay/chart/core.js.map +7 -0
- package/dist/headless/source/components/dataDisplay/chart/index.js +1 -1
- package/dist/headless/source/components/dataDisplay/chart/index.js.map +1 -1
- package/dist/headless/source/components/dataDisplay/dagView/dagView.jsx +2 -1
- package/dist/headless/source/components/dataDisplay/dagView/dagView.jsx.map +1 -1
- package/dist/headless/source/components/dataDisplay/dagView/index.js.map +2 -2
- package/dist/headless/source/components/dataDisplay/meter/index.js.map +1 -1
- package/dist/headless/source/components/dataDisplay/meter/meter.jsx +14 -2
- package/dist/headless/source/components/dataDisplay/meter/meter.jsx.map +1 -1
- package/dist/headless/source/components/dataDisplay/statusDot/index.js.map +1 -1
- package/dist/headless/source/components/dataDisplay/statusDot/statusDot.jsx +13 -1
- package/dist/headless/source/components/dataDisplay/statusDot/statusDot.jsx.map +1 -1
- package/dist/headless/source/components/dataDisplay/treeView/treeView.jsx +16 -3
- package/dist/headless/source/components/dataDisplay/treeView/treeView.jsx.map +1 -1
- package/dist/headless/source/components/inputs/button/button.jsx +26 -1
- package/dist/headless/source/components/inputs/button/button.jsx.map +1 -1
- package/dist/headless/source/components/inputs/toggle/toggle.jsx +9 -2
- package/dist/headless/source/components/inputs/toggle/toggle.jsx.map +1 -1
- package/dist/headless/source/components/layout/appLayout/appLayout.jsx +14 -2
- package/dist/headless/source/components/layout/appLayout/appLayout.jsx.map +1 -1
- package/dist/headless/source/components/layout/screenDivider/screenDivider.jsx +102 -18
- package/dist/headless/source/components/layout/screenDivider/screenDivider.jsx.map +1 -1
- package/dist/headless/source/components/layout/sheet/sheet.jsx +14 -1
- package/dist/headless/source/components/layout/sheet/sheet.jsx.map +1 -1
- package/dist/headless/source/components/layout/tabGroups/index.js.map +1 -1
- package/dist/headless/source/components/layout/tabGroups/tabGroups.jsx +55 -1
- package/dist/headless/source/components/layout/tabGroups/tabGroups.jsx.map +1 -1
- package/dist/headless/source/components/layout/tabGroups/tabGroupsFocus.js +42 -0
- package/dist/headless/source/components/layout/tabGroups/tabGroupsFocus.js.map +2 -2
- package/dist/headless/source/components/navigation/appBar/appBar.jsx.map +1 -1
- package/dist/headless/source/components/navigation/breadcrumbs/breadcrumbs.jsx +39 -4
- package/dist/headless/source/components/navigation/breadcrumbs/breadcrumbs.jsx.map +1 -1
- package/dist/headless/source/components/navigation/tabs/tab/tab.jsx +7 -1
- package/dist/headless/source/components/navigation/tabs/tab/tab.jsx.map +1 -1
- package/dist/headless/source/components/navigation/tabs/tabs.jsx +5 -1
- package/dist/headless/source/components/navigation/tabs/tabs.jsx.map +1 -1
- package/dist/headless/source/components/navigation/tabs/tabsContext.js.map +2 -2
- package/dist/headless/source/index.js +8 -1
- package/dist/headless/source/index.js.map +2 -2
- package/dist/headless/source/primitives/publishHeaderOffset.js +34 -0
- package/dist/headless/source/primitives/publishHeaderOffset.js.map +7 -0
- package/dist/index.d.ts +5 -5
- package/dist/primitives/publishHeaderOffset.d.ts +7 -0
- package/dist/primitives/publishHeaderOffset.js +19 -0
- package/dist/primitives/publishHeaderOffset.js.map +1 -0
- package/dist/source/components/dataDisplay/avatar/avatar.jsx +1 -0
- package/dist/source/components/dataDisplay/avatar/avatar.jsx.map +1 -1
- package/dist/source/components/dataDisplay/badge/badge.jsx.map +1 -1
- package/dist/source/components/dataDisplay/chart/chart.jsx +14 -12
- package/dist/source/components/dataDisplay/chart/chart.jsx.map +1 -1
- package/dist/source/components/dataDisplay/chart/chartFull.js +12 -0
- package/dist/source/components/dataDisplay/chart/chartFull.js.map +7 -0
- package/dist/source/components/dataDisplay/chart/core.js +11 -0
- package/dist/source/components/dataDisplay/chart/core.js.map +7 -0
- package/dist/source/components/dataDisplay/chart/index.js +1 -1
- package/dist/source/components/dataDisplay/chart/index.js.map +1 -1
- package/dist/source/components/dataDisplay/dagView/dagView.jsx +2 -1
- package/dist/source/components/dataDisplay/dagView/dagView.jsx.map +1 -1
- package/dist/source/components/dataDisplay/dagView/index.js.map +2 -2
- package/dist/source/components/dataDisplay/meter/index.js.map +1 -1
- package/dist/source/components/dataDisplay/meter/meter.jsx +14 -2
- package/dist/source/components/dataDisplay/meter/meter.jsx.map +1 -1
- package/dist/source/components/dataDisplay/statusDot/index.js.map +1 -1
- package/dist/source/components/dataDisplay/statusDot/statusDot.jsx +13 -1
- package/dist/source/components/dataDisplay/statusDot/statusDot.jsx.map +1 -1
- package/dist/source/components/dataDisplay/treeView/treeView.jsx +16 -3
- package/dist/source/components/dataDisplay/treeView/treeView.jsx.map +1 -1
- package/dist/source/components/inputs/button/button.jsx +26 -1
- package/dist/source/components/inputs/button/button.jsx.map +1 -1
- package/dist/source/components/inputs/toggle/toggle.jsx +9 -2
- package/dist/source/components/inputs/toggle/toggle.jsx.map +1 -1
- package/dist/source/components/layout/appLayout/appLayout.jsx +14 -2
- package/dist/source/components/layout/appLayout/appLayout.jsx.map +1 -1
- package/dist/source/components/layout/screenDivider/screenDivider.jsx +102 -18
- package/dist/source/components/layout/screenDivider/screenDivider.jsx.map +1 -1
- package/dist/source/components/layout/sheet/sheet.jsx +14 -1
- package/dist/source/components/layout/sheet/sheet.jsx.map +1 -1
- package/dist/source/components/layout/tabGroups/index.js.map +1 -1
- package/dist/source/components/layout/tabGroups/tabGroups.jsx +55 -1
- package/dist/source/components/layout/tabGroups/tabGroups.jsx.map +1 -1
- package/dist/source/components/layout/tabGroups/tabGroupsFocus.js +42 -0
- package/dist/source/components/layout/tabGroups/tabGroupsFocus.js.map +2 -2
- package/dist/source/components/navigation/appBar/appBar.jsx.map +1 -1
- package/dist/source/components/navigation/breadcrumbs/breadcrumbs.jsx +39 -4
- package/dist/source/components/navigation/breadcrumbs/breadcrumbs.jsx.map +1 -1
- package/dist/source/components/navigation/tabs/tab/tab.jsx +7 -1
- package/dist/source/components/navigation/tabs/tab/tab.jsx.map +1 -1
- package/dist/source/components/navigation/tabs/tabs.jsx +5 -1
- package/dist/source/components/navigation/tabs/tabs.jsx.map +1 -1
- package/dist/source/components/navigation/tabs/tabsContext.js.map +2 -2
- package/dist/source/index.js +8 -1
- package/dist/source/index.js.map +2 -2
- package/dist/source/primitives/publishHeaderOffset.js +34 -0
- package/dist/source/primitives/publishHeaderOffset.js.map +7 -0
- package/package.json +9 -3
|
@@ -53,3 +53,19 @@ export declare function focusFromEnd(element: HTMLElement): void;
|
|
|
53
53
|
* Null when the browser's move was right.
|
|
54
54
|
*/
|
|
55
55
|
export declare function frameExitTarget(root: HTMLElement, frame: Element, landed: Element): HTMLElement | null;
|
|
56
|
+
/** A control of a group's `stripActions` slot that has the focus: its group and its place among the slot's stops. */
|
|
57
|
+
export interface TabGroupsSlotFocus {
|
|
58
|
+
element: HTMLElement;
|
|
59
|
+
group: string;
|
|
60
|
+
index: number;
|
|
61
|
+
}
|
|
62
|
+
/** Where a focused element is in a `stripActions` slot of this root, or null when it is in none. */
|
|
63
|
+
export declare function slotFocusOf(root: HTMLElement, element: HTMLElement): TabGroupsSlotFocus | null;
|
|
64
|
+
/**
|
|
65
|
+
* Where the focus goes when the slot control that had it has left the document — a split or a
|
|
66
|
+
* close from the slot takes the slot away with its group, or to the group the user works in now:
|
|
67
|
+
* the stop at the same place (or the last one, when there are fewer) in the slot of the control's
|
|
68
|
+
* own group while that still draws one, else in the slot of the group in use, else that group's
|
|
69
|
+
* selected tab.
|
|
70
|
+
*/
|
|
71
|
+
export declare function slotFocusHeir(root: HTMLElement, lost: TabGroupsSlotFocus, activeGroup: string): HTMLElement | null;
|
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
const
|
|
2
|
-
function
|
|
1
|
+
const L = "smwb-tab-groups", N = ":scope > .smwb-tab-groups__focus-guard", C = ":scope > .smwb-tab-groups__panel-end", I = ".smwb-tab-groups__header, .smwb-tab-groups__panel, .smwb-tab-groups__separator", y = 'a[href], area[href], button, input, select, textarea, iframe, summary, audio[controls], video[controls], [contenteditable]:not([contenteditable="false"]), [tabindex]';
|
|
2
|
+
function s(t) {
|
|
3
3
|
if (t.parentElement) return t.parentElement;
|
|
4
4
|
const n = t.parentNode;
|
|
5
5
|
return n?.nodeType === 11 && n.host ? n.host : null;
|
|
6
6
|
}
|
|
7
|
-
function
|
|
8
|
-
return t ? t.nodeType === 1 ? t :
|
|
7
|
+
function w(t) {
|
|
8
|
+
return t ? t.nodeType === 1 ? t : s(t) : null;
|
|
9
9
|
}
|
|
10
|
-
function
|
|
11
|
-
for (let e = n; e; e =
|
|
10
|
+
function S(t, n) {
|
|
11
|
+
for (let e = n; e; e = s(e))
|
|
12
12
|
if (e === t) return !0;
|
|
13
13
|
return !1;
|
|
14
14
|
}
|
|
15
|
-
function
|
|
15
|
+
function V(t) {
|
|
16
16
|
let n = t.activeElement;
|
|
17
17
|
for (; n?.shadowRoot?.activeElement; ) n = n.shadowRoot.activeElement;
|
|
18
18
|
return n;
|
|
19
19
|
}
|
|
20
|
-
function
|
|
21
|
-
for (let n =
|
|
22
|
-
if (n.classList.contains(
|
|
20
|
+
function k(t) {
|
|
21
|
+
for (let n = w(t); n; n = s(n))
|
|
22
|
+
if (n.classList.contains(L)) return n;
|
|
23
23
|
return null;
|
|
24
24
|
}
|
|
25
|
-
function
|
|
26
|
-
let e =
|
|
27
|
-
for (; e &&
|
|
25
|
+
function l(t, n) {
|
|
26
|
+
let e = w(n);
|
|
27
|
+
for (; e && s(e) !== t; ) e = s(e);
|
|
28
28
|
return e;
|
|
29
29
|
}
|
|
30
|
-
function
|
|
31
|
-
return
|
|
30
|
+
function W(t, n) {
|
|
31
|
+
return l(t, n)?.getAttribute("data-group-id") ?? null;
|
|
32
32
|
}
|
|
33
|
-
function
|
|
34
|
-
return t.querySelector(
|
|
33
|
+
function E(t) {
|
|
34
|
+
return t.querySelector(N);
|
|
35
35
|
}
|
|
36
36
|
function a(t) {
|
|
37
37
|
const n = t.ownerDocument;
|
|
38
38
|
return (t.getAttribute("aria-owns") ?? "").split(/\s+/).flatMap((e) => {
|
|
39
39
|
const r = e ? n.getElementById(e) : null;
|
|
40
|
-
return r && r.parentElement === t && !r.hidden && r.matches(
|
|
40
|
+
return r && r.parentElement === t && !r.hidden && r.matches(I) ? [r] : [];
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
|
-
function
|
|
43
|
+
function T(t) {
|
|
44
44
|
return typeof t.checkVisibility != "function" || t.checkVisibility({ visibilityProperty: !0 });
|
|
45
45
|
}
|
|
46
|
-
function
|
|
46
|
+
function O(t) {
|
|
47
47
|
const n = t.tabIndex;
|
|
48
48
|
return typeof n == "number" ? n : -1;
|
|
49
49
|
}
|
|
50
|
-
function
|
|
50
|
+
function q(t) {
|
|
51
51
|
if (t.scrollHeight <= t.clientHeight && t.scrollWidth <= t.clientWidth) return !1;
|
|
52
52
|
const n = t.ownerDocument.defaultView?.getComputedStyle(t), e = (r) => r === "auto" || r === "scroll";
|
|
53
|
-
return !!(n && (e(n.overflowY) || e(n.overflowX)) && !t.querySelector(
|
|
53
|
+
return !!(n && (e(n.overflowY) || e(n.overflowX)) && !t.querySelector(y));
|
|
54
54
|
}
|
|
55
|
-
function
|
|
56
|
-
return t.matches(
|
|
55
|
+
function F(t) {
|
|
56
|
+
return t.matches(y) ? O(t) !== 0 || t.matches(":disabled") || t.localName === "input" && t.type === "hidden" ? !1 : T(t) : q(t);
|
|
57
57
|
}
|
|
58
|
-
function
|
|
58
|
+
function h(t) {
|
|
59
59
|
return t.localName === "input" && t.type === "radio";
|
|
60
60
|
}
|
|
61
|
-
function
|
|
61
|
+
function A(t, n) {
|
|
62
62
|
return t === n || t.name !== "" && t.name === n.name && t.form === n.form && t.getRootNode() === n.getRootNode();
|
|
63
63
|
}
|
|
64
|
-
function
|
|
64
|
+
function H(t) {
|
|
65
65
|
if (t.checked) return t;
|
|
66
66
|
if (t.name === "") return null;
|
|
67
67
|
const n = t.form ?? t.getRootNode();
|
|
68
68
|
return (t.form ? Array.from(t.form.elements) : Array.from(n.querySelectorAll("input"))).find(
|
|
69
|
-
(r) =>
|
|
69
|
+
(r) => h(r) && r.checked && A(t, r)
|
|
70
70
|
) ?? null;
|
|
71
71
|
}
|
|
72
|
-
function
|
|
73
|
-
if (n &&
|
|
74
|
-
const e =
|
|
72
|
+
function P(t, n) {
|
|
73
|
+
if (n && h(n) && A(n, t)) return !1;
|
|
74
|
+
const e = H(t);
|
|
75
75
|
return e === null || e === t;
|
|
76
76
|
}
|
|
77
|
-
function
|
|
77
|
+
function B(t) {
|
|
78
78
|
if (t.shadowRoot) return Array.from(t.shadowRoot.children);
|
|
79
79
|
if (t.localName === "slot") {
|
|
80
80
|
const n = t, e = typeof n.assignedElements == "function" ? n.assignedElements() : [];
|
|
@@ -82,23 +82,23 @@ function T(t) {
|
|
|
82
82
|
}
|
|
83
83
|
return Array.from(t.children);
|
|
84
84
|
}
|
|
85
|
-
function*
|
|
85
|
+
function* d(t) {
|
|
86
86
|
yield t;
|
|
87
|
-
for (const n of
|
|
88
|
-
n.matches("[hidden], [inert]") || (yield*
|
|
87
|
+
for (const n of B(t))
|
|
88
|
+
n.matches("[hidden], [inert]") || (yield* d(n));
|
|
89
89
|
}
|
|
90
|
-
function
|
|
91
|
-
return
|
|
90
|
+
function g(t, n) {
|
|
91
|
+
return F(t) && (!h(t) || P(t, n));
|
|
92
92
|
}
|
|
93
|
-
function
|
|
93
|
+
function p(t, n, e, r = !1) {
|
|
94
94
|
let o, i = !1;
|
|
95
|
-
for (const u of
|
|
95
|
+
for (const u of d(t)) {
|
|
96
96
|
if (u === n) {
|
|
97
97
|
if (e < 0) return o;
|
|
98
98
|
i = !0;
|
|
99
99
|
continue;
|
|
100
100
|
}
|
|
101
|
-
if (!(i && r &&
|
|
101
|
+
if (!(i && r && S(n, u)) && g(u, n)) {
|
|
102
102
|
if (i) return u;
|
|
103
103
|
o = u;
|
|
104
104
|
}
|
|
@@ -106,8 +106,8 @@ function d(t, n, e, r = !1) {
|
|
|
106
106
|
}
|
|
107
107
|
function m(t, n, e) {
|
|
108
108
|
let r;
|
|
109
|
-
for (const o of
|
|
110
|
-
if (
|
|
109
|
+
for (const o of d(t))
|
|
110
|
+
if (g(o, e)) {
|
|
111
111
|
if (n > 0) return o;
|
|
112
112
|
r = o;
|
|
113
113
|
}
|
|
@@ -117,27 +117,27 @@ function f(t, n, e, r) {
|
|
|
117
117
|
for (let o = n; o >= 0 && o < t.length; o += e) {
|
|
118
118
|
const i = t[o], u = i ? m(i, e, r) : void 0;
|
|
119
119
|
if (!i || !u) continue;
|
|
120
|
-
const c = u.localName === "iframe" ? i.querySelector(
|
|
120
|
+
const c = u.localName === "iframe" ? i.querySelector(C) : null;
|
|
121
121
|
return c ? { element: c, prevent: !1 } : { element: u, prevent: !0 };
|
|
122
122
|
}
|
|
123
123
|
return null;
|
|
124
124
|
}
|
|
125
|
-
function
|
|
126
|
-
const r =
|
|
125
|
+
function U(t, n, e) {
|
|
126
|
+
const r = E(t), o = a(t);
|
|
127
127
|
if (n === r) return e < 0 ? f(o, o.length - 1, -1, n) : null;
|
|
128
|
-
const i =
|
|
129
|
-
if (!i || u < 0 ||
|
|
128
|
+
const i = l(t, n), u = i ? o.indexOf(i) : -1;
|
|
129
|
+
if (!i || u < 0 || O(n) > 0 || p(i, n, e)) return null;
|
|
130
130
|
const c = f(o, u + e, e, n);
|
|
131
131
|
return c || (e > 0 && r ? { element: r, prevent: !1 } : null);
|
|
132
132
|
}
|
|
133
|
-
function
|
|
133
|
+
function X(t) {
|
|
134
134
|
const n = a(t);
|
|
135
135
|
for (let e = n.length - 1; e >= 0; e -= 1) {
|
|
136
136
|
const r = n[e], o = r ? m(r, -1, null) : void 0;
|
|
137
137
|
if (o) return o;
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
-
function
|
|
140
|
+
function G(t) {
|
|
141
141
|
if (t.localName === "iframe") {
|
|
142
142
|
let n;
|
|
143
143
|
try {
|
|
@@ -147,46 +147,78 @@ function q(t) {
|
|
|
147
147
|
}
|
|
148
148
|
const e = n ? m(n, -1, null) : void 0;
|
|
149
149
|
if (e) {
|
|
150
|
-
|
|
150
|
+
G(e);
|
|
151
151
|
return;
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
t.focus();
|
|
155
155
|
}
|
|
156
|
-
function
|
|
157
|
-
const n =
|
|
156
|
+
function _(t) {
|
|
157
|
+
const n = k(s(t));
|
|
158
158
|
if (!n) {
|
|
159
159
|
const i = t.ownerDocument.body;
|
|
160
|
-
return i ?
|
|
160
|
+
return i ? p(i, t, 1, !0) : void 0;
|
|
161
161
|
}
|
|
162
|
-
const e =
|
|
162
|
+
const e = l(n, t), r = a(n), o = e ? r.indexOf(e) : -1;
|
|
163
163
|
if (e && o >= 0) {
|
|
164
|
-
const i =
|
|
164
|
+
const i = p(e, t, 1, !0);
|
|
165
165
|
if (i) return i;
|
|
166
166
|
const u = f(r, o + 1, 1, null);
|
|
167
167
|
if (u) return u.element;
|
|
168
168
|
}
|
|
169
|
-
return
|
|
169
|
+
return _(n);
|
|
170
170
|
}
|
|
171
|
-
function
|
|
172
|
-
const r =
|
|
173
|
-
if (!o || e !== r &&
|
|
171
|
+
function Y(t, n, e) {
|
|
172
|
+
const r = E(t), o = l(t, n);
|
|
173
|
+
if (!o || e !== r && l(t, e) === o || e !== r && !(n.compareDocumentPosition(e) & 4)) return null;
|
|
174
174
|
const i = a(t), u = i.indexOf(o);
|
|
175
175
|
if (u < 0) return null;
|
|
176
|
-
const c = f(i, u + 1, 1, null)?.element ??
|
|
176
|
+
const c = f(i, u + 1, 1, null)?.element ?? _(t) ?? r;
|
|
177
177
|
return c === e && e !== r ? null : c;
|
|
178
178
|
}
|
|
179
|
+
const v = "smwb-tab-groups__header", M = "smwb-tab-groups__strip-actions";
|
|
180
|
+
function b(t, n) {
|
|
181
|
+
for (const e of Array.from(t.children))
|
|
182
|
+
if (e.classList.contains(v) && e.getAttribute("data-group-id") === n)
|
|
183
|
+
return e;
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
function R(t) {
|
|
187
|
+
return Array.from(t.children).find((n) => n.classList.contains(M));
|
|
188
|
+
}
|
|
189
|
+
function x(t) {
|
|
190
|
+
const n = R(t), e = [];
|
|
191
|
+
if (!n) return e;
|
|
192
|
+
for (const r of d(n))
|
|
193
|
+
r !== n && g(r, null) && e.push(r);
|
|
194
|
+
return e;
|
|
195
|
+
}
|
|
196
|
+
function j(t, n) {
|
|
197
|
+
const e = l(t, n), r = e?.classList.contains(v) ? e.getAttribute("data-group-id") : null, o = e ? R(e) : void 0;
|
|
198
|
+
if (!e || r === null || r === void 0 || !o || !S(o, n)) return null;
|
|
199
|
+
const i = x(e), u = i.indexOf(n), c = u >= 0 ? u : i.filter((D) => (D.compareDocumentPosition(n) & 4) !== 0).length;
|
|
200
|
+
return { element: n, group: r, index: c };
|
|
201
|
+
}
|
|
202
|
+
function z(t, n, e) {
|
|
203
|
+
for (const r of [n.group, e]) {
|
|
204
|
+
const o = b(t, r), i = o ? x(o) : [];
|
|
205
|
+
if (i.length > 0) return i[Math.min(n.index, i.length - 1)] ?? null;
|
|
206
|
+
}
|
|
207
|
+
return b(t, e)?.querySelector('[role="tab"][aria-selected="true"]') ?? null;
|
|
208
|
+
}
|
|
179
209
|
export {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
210
|
+
S as containsDeep,
|
|
211
|
+
V as deepActiveElement,
|
|
212
|
+
G as focusFromEnd,
|
|
213
|
+
Y as frameExitTarget,
|
|
214
|
+
E as guardOf,
|
|
215
|
+
X as lastStopOf,
|
|
216
|
+
W as ownGroupIdOf,
|
|
217
|
+
k as ownerRootOf,
|
|
188
218
|
a as readingChildren,
|
|
189
|
-
|
|
190
|
-
|
|
219
|
+
l as rootChildOf,
|
|
220
|
+
z as slotFocusHeir,
|
|
221
|
+
j as slotFocusOf,
|
|
222
|
+
U as tabMove
|
|
191
223
|
};
|
|
192
224
|
//# sourceMappingURL=tabGroupsFocus.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabGroupsFocus.js","sources":["../../../../src/components/layout/tabGroups/tabGroupsFocus.ts"],"sourcesContent":["/**\n * The Tab order of `TabGroups`, read from the DOM alone: no framework here, and the file is a\n * byte-identical copy in ui-react and ui-solid.\n *\n * The root keeps its panels in the DOM in the order they first appeared, so the DOM order of its\n * children is not the reading order; the root's `aria-owns` lists them in reading order. Inside one\n * child — a header, a panel, a separator — DOM order is reading order, so there the browser moves\n * the focus itself, with every rule of its own (a radio group is one stop, a frame is entered at\n * its first or its last stop, a shadow tree is walked in place). Only a press that would leave a\n * child is taken over: it goes to the next child in reading order, to the stop the browser would\n * pick there by the same rules. A `TabGroups` nested in a panel is that panel's content: its own\n * root answers for the moves inside it, first.\n */\n\nconst ROOT_CLASS = \"smwb-tab-groups\";\nconst GUARD_SELECTOR = \":scope > .smwb-tab-groups__focus-guard\";\nconst PANEL_END_SELECTOR = \":scope > .smwb-tab-groups__panel-end\";\nconst READING_CHILD = \".smwb-tab-groups__header, .smwb-tab-groups__panel, .smwb-tab-groups__separator\";\n\n/** What can take focus from the Tab key, as a browser decides it. */\nconst FOCUSABLE =\n 'a[href], area[href], button, input, select, textarea, iframe, summary, audio[controls], video[controls], [contenteditable]:not([contenteditable=\"false\"]), [tabindex]';\n\n/** A browser's move of the Tab key, taken over: focus `element`, then stop there (`prevent`) or let the browser go on from it. */\nexport interface TabGroupsTabMove {\n element: HTMLElement;\n prevent: boolean;\n}\n\n/** The parent of a node across a shadow root's boundary: the host. */\nfunction parentOf(node: Node): Element | null {\n if (node.parentElement) return node.parentElement;\n const parent = node.parentNode as (Node & { host?: Element }) | null;\n return parent?.nodeType === 11 && parent.host ? parent.host : null;\n}\n\nfunction elementOf(node: Node | null): Element | null {\n if (!node) return null;\n return node.nodeType === 1 ? (node as Element) : parentOf(node);\n}\n\n/** Whether `node` is `ancestor` or inside it, shadow trees included. */\nexport function containsDeep(ancestor: Node, node: Node | null): boolean {\n for (let current: Node | null = node; current; current = parentOf(current)) {\n if (current === ancestor) return true;\n }\n return false;\n}\n\n/** The element that has the focus, inside shadow trees too: where the browser's Tab starts from. */\nexport function deepActiveElement(doc: Document): Element | null {\n let active = doc.activeElement;\n while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;\n return active;\n}\n\n/** The `TabGroups` root a node is in: the nearest one around it, or the node itself when it is one. */\nexport function ownerRootOf(node: Node | null): HTMLElement | null {\n for (let current = elementOf(node); current; current = parentOf(current)) {\n if (current.classList.contains(ROOT_CLASS)) return current as HTMLElement;\n }\n return null;\n}\n\n/** The child of `root` a node is in — a header, a panel, a separator, the guard — or null. */\nexport function rootChildOf(root: Element, node: Node | null): HTMLElement | null {\n let current = elementOf(node);\n while (current && parentOf(current) !== root) current = parentOf(current);\n return current as HTMLElement | null;\n}\n\n/** The group a node is in, told by the root's own child: a nested `TabGroups`' groups are not this root's. */\nexport function ownGroupIdOf(root: Element, node: Node | null): string | null {\n return rootChildOf(root, node)?.getAttribute(\"data-group-id\") ?? null;\n}\n\n/** The root's guard, its last Tab stop, which only holds the focus on its way in or out. */\nexport function guardOf(root: HTMLElement): HTMLElement | null {\n return root.querySelector<HTMLElement>(GUARD_SELECTOR);\n}\n\n/** The root's headers, shown panels and separators in reading order, as its `aria-owns` lists them. */\nexport function readingChildren(root: HTMLElement): HTMLElement[] {\n const doc = root.ownerDocument;\n return (root.getAttribute(\"aria-owns\") ?? \"\").split(/\\s+/).flatMap((id) => {\n const element = id ? doc.getElementById(id) : null;\n return element && element.parentElement === root && !element.hidden && element.matches(READING_CHILD)\n ? [element]\n : [];\n });\n}\n\n/** Whether an element is drawn: a browser skips what is not (`display: none` from a stylesheet); jsdom draws nothing. */\nfunction isDrawn(element: Element): boolean {\n return typeof element.checkVisibility !== \"function\" || element.checkVisibility({ visibilityProperty: true });\n}\n\nfunction tabIndexOf(element: Element): number {\n const value = (element as Partial<HTMLElement>).tabIndex;\n return typeof value === \"number\" ? value : -1;\n}\n\n/** A scroller is a Tab stop of its own in Chromium when nothing inside it takes the focus. */\nfunction isScrollerStop(element: Element): boolean {\n if (element.scrollHeight <= element.clientHeight && element.scrollWidth <= element.clientWidth) return false;\n const style = element.ownerDocument.defaultView?.getComputedStyle(element);\n const scrolls = (value: string | undefined): boolean => value === \"auto\" || value === \"scroll\";\n return Boolean(style && (scrolls(style.overflowY) || scrolls(style.overflowX)) && !element.querySelector(FOCUSABLE));\n}\n\n/**\n * Whether the Tab key stops at an element, radio groups aside: focusable, in the sequence of\n * `tabindex` 0 (-1 is out of it, and above 0 the browser visits before everything else), enabled\n * and drawn — or a scroller with nothing focusable inside.\n */\nfunction isStop(element: Element): element is HTMLElement {\n if (element.matches(FOCUSABLE)) {\n if (tabIndexOf(element) !== 0 || element.matches(\":disabled\")) return false;\n if (element.localName === \"input\" && (element as HTMLInputElement).type === \"hidden\") return false;\n return isDrawn(element);\n }\n return isScrollerStop(element);\n}\n\nfunction isRadio(element: Element): element is HTMLInputElement {\n return element.localName === \"input\" && (element as HTMLInputElement).type === \"radio\";\n}\n\n/** Radios of one group: the same name (an unnamed radio is a group of its own), the same form, the same tree. */\nfunction sameGroup(a: HTMLInputElement, b: HTMLInputElement): boolean {\n return a === b || (a.name !== \"\" && a.name === b.name && a.form === b.form && a.getRootNode() === b.getRootNode());\n}\n\n/** The checked radio of a radio's group, wherever it is drawn, or null. */\nfunction checkedOf(radio: HTMLInputElement): HTMLInputElement | null {\n if (radio.checked) return radio;\n if (radio.name === \"\") return null;\n const scope = radio.form ?? (radio.getRootNode() as Document | ShadowRoot);\n const members: Element[] = radio.form ? Array.from(radio.form.elements) : Array.from(scope.querySelectorAll(\"input\"));\n return (\n members.find(\n (member): member is HTMLInputElement => isRadio(member) && member.checked && sameGroup(radio, member)\n ) ?? null\n );\n}\n\n/**\n * A radio group is one stop: its checked radio, or with none checked every radio of it (so the\n * first one going forwards, the last one going backwards), and none of the group the focus is in.\n */\nfunction isRadioStop(radio: HTMLInputElement, focused: Element | null): boolean {\n if (focused && isRadio(focused) && sameGroup(focused, radio)) return false;\n const checked = checkedOf(radio);\n return checked === null || checked === radio;\n}\n\n/** The element children a walk in the flat tree visits: a shadow root's instead of its host's, a slot's assigned ones. */\nfunction childrenOf(element: Element): Element[] {\n if (element.shadowRoot) return Array.from(element.shadowRoot.children);\n if (element.localName === \"slot\") {\n const slot = element as HTMLSlotElement;\n const assigned = typeof slot.assignedElements === \"function\" ? slot.assignedElements() : [];\n if (assigned.length > 0) return assigned;\n }\n return Array.from(element.children);\n}\n\n/** An element and everything under it in flat-tree order, without what is `hidden` or `inert`. */\nfunction* walk(element: Element): Generator<Element> {\n yield element;\n for (const child of childrenOf(element)) {\n if (!child.matches(\"[hidden], [inert]\")) yield* walk(child);\n }\n}\n\nfunction isStopFrom(element: Element, focused: Element | null): element is HTMLElement {\n return isStop(element) && (!isRadio(element) || isRadioStop(element, focused));\n}\n\n/**\n * The stop the Tab key goes to from `from` without leaving `container`, or undefined when it\n * would leave it. `past` starts after everything inside `from`, as from a nested root as a whole.\n */\nfunction stepWithin(container: Element, from: Element, step: 1 | -1, past = false): HTMLElement | undefined {\n let before: HTMLElement | undefined;\n let passed = false;\n for (const element of walk(container)) {\n if (element === from) {\n if (step < 0) return before;\n passed = true;\n continue;\n }\n if (passed && past && containsDeep(from, element)) continue;\n if (!isStopFrom(element, from)) continue;\n if (passed) return element;\n before = element;\n }\n return undefined;\n}\n\n/** The first stop inside a container (step 1) or the last one (step -1), the container itself included. */\nfunction edgeStop(container: Element, step: 1 | -1, focused: Element | null): HTMLElement | undefined {\n let last: HTMLElement | undefined;\n for (const element of walk(container)) {\n if (!isStopFrom(element, focused)) continue;\n if (step > 0) return element;\n last = element;\n }\n return last;\n}\n\n/**\n * Into the reading-order children from `index` on: the first stop of the first one that has one,\n * or going backwards the last stop. A frame that ends a panel is entered by the browser itself,\n * which lands on the frame's own last stop (whatever its origin): its panel's end marker takes the\n * focus, and the browser's move goes on from there.\n */\nfunction enter(children: HTMLElement[], index: number, step: 1 | -1, focused: Element | null): TabGroupsTabMove | null {\n for (let at = index; at >= 0 && at < children.length; at += step) {\n const child = children[at];\n const stop = child ? edgeStop(child, step, focused) : undefined;\n if (!child || !stop) continue;\n const end = stop.localName === \"iframe\" ? child.querySelector<HTMLElement>(PANEL_END_SELECTOR) : null;\n return end ? { element: end, prevent: false } : { element: stop, prevent: true };\n }\n return null;\n}\n\n/**\n * What the Tab key (step 1) or Shift+Tab (step -1) does from `from`, the focused element in\n * `root`: null when the browser's own move is right — inside a child, or out of the root before\n * its first stop. At the end of the reading order the focus leaves through the guard, and the\n * browser moves on past the root from there.\n */\nexport function tabMove(root: HTMLElement, from: Element, step: 1 | -1): TabGroupsTabMove | null {\n const guard = guardOf(root);\n const children = readingChildren(root);\n // The guard holds the focus (nothing followed a frame at the end): Shift+Tab goes back in.\n if (from === guard) return step < 0 ? enter(children, children.length - 1, -1, from) : null;\n const child = rootChildOf(root, from);\n const index = child ? children.indexOf(child) : -1;\n if (!child || index < 0 || tabIndexOf(from) > 0) return null;\n if (stepWithin(child, from, step)) return null;\n const entered = enter(children, index + step, step, from);\n if (entered) return entered;\n return step > 0 && guard ? { element: guard, prevent: false } : null;\n}\n\n/** The last stop of the reading order, where Shift+Tab from after the root goes. */\nexport function lastStopOf(root: HTMLElement): HTMLElement | undefined {\n const children = readingChildren(root);\n for (let at = children.length - 1; at >= 0; at -= 1) {\n const child = children[at];\n const stop = child ? edgeStop(child, -1, null) : undefined;\n if (stop) return stop;\n }\n return undefined;\n}\n\n/**\n * Focuses a stop that is reached backwards: a frame whose document can be read (the same origin)\n * at its own last stop, as the browser's Shift+Tab would; another frame as a whole.\n */\nexport function focusFromEnd(element: HTMLElement): void {\n if (element.localName === \"iframe\") {\n let body: HTMLElement | null | undefined;\n try {\n body = (element as HTMLIFrameElement).contentDocument?.body;\n } catch {\n body = null;\n }\n const last = body ? edgeStop(body, -1, null) : undefined;\n if (last) {\n focusFromEnd(last);\n return;\n }\n }\n element.focus();\n}\n\n/** The first stop after a whole root: on in the root around it, or in the page. */\nfunction stopAfter(root: HTMLElement): HTMLElement | undefined {\n const outer = ownerRootOf(parentOf(root));\n if (!outer) {\n const body = root.ownerDocument.body;\n return body ? stepWithin(body, root, 1, true) : undefined;\n }\n const child = rootChildOf(outer, root);\n const children = readingChildren(outer);\n const index = child ? children.indexOf(child) : -1;\n if (child && index >= 0) {\n const inside = stepWithin(child, root, 1, true);\n if (inside) return inside;\n const entered = enter(children, index + 1, 1, null);\n if (entered) return entered.element;\n }\n return stopAfter(outer);\n}\n\n/**\n * Where the focus belongs after the browser's Tab took it out of `frame`, an iframe of this root,\n * onto `landed`. Inside a frame the keys are its own, so the browser left it by DOM order: to\n * another child of the root, or to the guard, when the frame ended its child. The next child in\n * reading order takes the focus instead, or after the last one whatever follows the root; with\n * nothing there the guard holds the focus (it is returned), and the next Tab leaves the page.\n * Null when the browser's move was right.\n */\nexport function frameExitTarget(root: HTMLElement, frame: Element, landed: Element): HTMLElement | null {\n const guard = guardOf(root);\n const child = rootChildOf(root, frame);\n if (!child || (landed !== guard && rootChildOf(root, landed) === child)) return null;\n // Out of a frame backwards the browser stays in its child: the child itself is a stop before it.\n if (landed !== guard && !(frame.compareDocumentPosition(landed) & 4)) return null;\n const children = readingChildren(root);\n const index = children.indexOf(child);\n if (index < 0) return null;\n const wanted = enter(children, index + 1, 1, null)?.element ?? stopAfter(root) ?? guard;\n return wanted === landed && landed !== guard ? null : wanted;\n}\n"],"names":["ROOT_CLASS","GUARD_SELECTOR","PANEL_END_SELECTOR","READING_CHILD","FOCUSABLE","parentOf","node","parent","elementOf","containsDeep","ancestor","current","deepActiveElement","doc","active","ownerRootOf","rootChildOf","root","ownGroupIdOf","guardOf","readingChildren","id","element","isDrawn","tabIndexOf","value","isScrollerStop","style","scrolls","isStop","isRadio","sameGroup","a","b","checkedOf","radio","scope","member","isRadioStop","focused","checked","childrenOf","slot","assigned","walk","child","isStopFrom","stepWithin","container","from","step","past","before","passed","edgeStop","last","enter","children","index","at","stop","end","tabMove","guard","entered","lastStopOf","focusFromEnd","body","stopAfter","outer","inside","frameExitTarget","frame","landed","wanted"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tabGroupsFocus.js","sources":["../../../../src/components/layout/tabGroups/tabGroupsFocus.ts"],"sourcesContent":["/**\n * The Tab order of `TabGroups`, read from the DOM alone: no framework here, and the file is a\n * byte-identical copy in ui-react and ui-solid.\n *\n * The root keeps its panels in the DOM in the order they first appeared, so the DOM order of its\n * children is not the reading order; the root's `aria-owns` lists them in reading order. Inside one\n * child — a header, a panel, a separator — DOM order is reading order, so there the browser moves\n * the focus itself, with every rule of its own (a radio group is one stop, a frame is entered at\n * its first or its last stop, a shadow tree is walked in place). Only a press that would leave a\n * child is taken over: it goes to the next child in reading order, to the stop the browser would\n * pick there by the same rules. A `TabGroups` nested in a panel is that panel's content: its own\n * root answers for the moves inside it, first.\n */\n\nconst ROOT_CLASS = \"smwb-tab-groups\";\nconst GUARD_SELECTOR = \":scope > .smwb-tab-groups__focus-guard\";\nconst PANEL_END_SELECTOR = \":scope > .smwb-tab-groups__panel-end\";\nconst READING_CHILD = \".smwb-tab-groups__header, .smwb-tab-groups__panel, .smwb-tab-groups__separator\";\n\n/** What can take focus from the Tab key, as a browser decides it. */\nconst FOCUSABLE =\n 'a[href], area[href], button, input, select, textarea, iframe, summary, audio[controls], video[controls], [contenteditable]:not([contenteditable=\"false\"]), [tabindex]';\n\n/** A browser's move of the Tab key, taken over: focus `element`, then stop there (`prevent`) or let the browser go on from it. */\nexport interface TabGroupsTabMove {\n element: HTMLElement;\n prevent: boolean;\n}\n\n/** The parent of a node across a shadow root's boundary: the host. */\nfunction parentOf(node: Node): Element | null {\n if (node.parentElement) return node.parentElement;\n const parent = node.parentNode as (Node & { host?: Element }) | null;\n return parent?.nodeType === 11 && parent.host ? parent.host : null;\n}\n\nfunction elementOf(node: Node | null): Element | null {\n if (!node) return null;\n return node.nodeType === 1 ? (node as Element) : parentOf(node);\n}\n\n/** Whether `node` is `ancestor` or inside it, shadow trees included. */\nexport function containsDeep(ancestor: Node, node: Node | null): boolean {\n for (let current: Node | null = node; current; current = parentOf(current)) {\n if (current === ancestor) return true;\n }\n return false;\n}\n\n/** The element that has the focus, inside shadow trees too: where the browser's Tab starts from. */\nexport function deepActiveElement(doc: Document): Element | null {\n let active = doc.activeElement;\n while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;\n return active;\n}\n\n/** The `TabGroups` root a node is in: the nearest one around it, or the node itself when it is one. */\nexport function ownerRootOf(node: Node | null): HTMLElement | null {\n for (let current = elementOf(node); current; current = parentOf(current)) {\n if (current.classList.contains(ROOT_CLASS)) return current as HTMLElement;\n }\n return null;\n}\n\n/** The child of `root` a node is in — a header, a panel, a separator, the guard — or null. */\nexport function rootChildOf(root: Element, node: Node | null): HTMLElement | null {\n let current = elementOf(node);\n while (current && parentOf(current) !== root) current = parentOf(current);\n return current as HTMLElement | null;\n}\n\n/** The group a node is in, told by the root's own child: a nested `TabGroups`' groups are not this root's. */\nexport function ownGroupIdOf(root: Element, node: Node | null): string | null {\n return rootChildOf(root, node)?.getAttribute(\"data-group-id\") ?? null;\n}\n\n/** The root's guard, its last Tab stop, which only holds the focus on its way in or out. */\nexport function guardOf(root: HTMLElement): HTMLElement | null {\n return root.querySelector<HTMLElement>(GUARD_SELECTOR);\n}\n\n/** The root's headers, shown panels and separators in reading order, as its `aria-owns` lists them. */\nexport function readingChildren(root: HTMLElement): HTMLElement[] {\n const doc = root.ownerDocument;\n return (root.getAttribute(\"aria-owns\") ?? \"\").split(/\\s+/).flatMap((id) => {\n const element = id ? doc.getElementById(id) : null;\n return element && element.parentElement === root && !element.hidden && element.matches(READING_CHILD)\n ? [element]\n : [];\n });\n}\n\n/** Whether an element is drawn: a browser skips what is not (`display: none` from a stylesheet); jsdom draws nothing. */\nfunction isDrawn(element: Element): boolean {\n return typeof element.checkVisibility !== \"function\" || element.checkVisibility({ visibilityProperty: true });\n}\n\nfunction tabIndexOf(element: Element): number {\n const value = (element as Partial<HTMLElement>).tabIndex;\n return typeof value === \"number\" ? value : -1;\n}\n\n/** A scroller is a Tab stop of its own in Chromium when nothing inside it takes the focus. */\nfunction isScrollerStop(element: Element): boolean {\n if (element.scrollHeight <= element.clientHeight && element.scrollWidth <= element.clientWidth) return false;\n const style = element.ownerDocument.defaultView?.getComputedStyle(element);\n const scrolls = (value: string | undefined): boolean => value === \"auto\" || value === \"scroll\";\n return Boolean(style && (scrolls(style.overflowY) || scrolls(style.overflowX)) && !element.querySelector(FOCUSABLE));\n}\n\n/**\n * Whether the Tab key stops at an element, radio groups aside: focusable, in the sequence of\n * `tabindex` 0 (-1 is out of it, and above 0 the browser visits before everything else), enabled\n * and drawn — or a scroller with nothing focusable inside.\n */\nfunction isStop(element: Element): element is HTMLElement {\n if (element.matches(FOCUSABLE)) {\n if (tabIndexOf(element) !== 0 || element.matches(\":disabled\")) return false;\n if (element.localName === \"input\" && (element as HTMLInputElement).type === \"hidden\") return false;\n return isDrawn(element);\n }\n return isScrollerStop(element);\n}\n\nfunction isRadio(element: Element): element is HTMLInputElement {\n return element.localName === \"input\" && (element as HTMLInputElement).type === \"radio\";\n}\n\n/** Radios of one group: the same name (an unnamed radio is a group of its own), the same form, the same tree. */\nfunction sameGroup(a: HTMLInputElement, b: HTMLInputElement): boolean {\n return a === b || (a.name !== \"\" && a.name === b.name && a.form === b.form && a.getRootNode() === b.getRootNode());\n}\n\n/** The checked radio of a radio's group, wherever it is drawn, or null. */\nfunction checkedOf(radio: HTMLInputElement): HTMLInputElement | null {\n if (radio.checked) return radio;\n if (radio.name === \"\") return null;\n const scope = radio.form ?? (radio.getRootNode() as Document | ShadowRoot);\n const members: Element[] = radio.form ? Array.from(radio.form.elements) : Array.from(scope.querySelectorAll(\"input\"));\n return (\n members.find(\n (member): member is HTMLInputElement => isRadio(member) && member.checked && sameGroup(radio, member)\n ) ?? null\n );\n}\n\n/**\n * A radio group is one stop: its checked radio, or with none checked every radio of it (so the\n * first one going forwards, the last one going backwards), and none of the group the focus is in.\n */\nfunction isRadioStop(radio: HTMLInputElement, focused: Element | null): boolean {\n if (focused && isRadio(focused) && sameGroup(focused, radio)) return false;\n const checked = checkedOf(radio);\n return checked === null || checked === radio;\n}\n\n/** The element children a walk in the flat tree visits: a shadow root's instead of its host's, a slot's assigned ones. */\nfunction childrenOf(element: Element): Element[] {\n if (element.shadowRoot) return Array.from(element.shadowRoot.children);\n if (element.localName === \"slot\") {\n const slot = element as HTMLSlotElement;\n const assigned = typeof slot.assignedElements === \"function\" ? slot.assignedElements() : [];\n if (assigned.length > 0) return assigned;\n }\n return Array.from(element.children);\n}\n\n/** An element and everything under it in flat-tree order, without what is `hidden` or `inert`. */\nfunction* walk(element: Element): Generator<Element> {\n yield element;\n for (const child of childrenOf(element)) {\n if (!child.matches(\"[hidden], [inert]\")) yield* walk(child);\n }\n}\n\nfunction isStopFrom(element: Element, focused: Element | null): element is HTMLElement {\n return isStop(element) && (!isRadio(element) || isRadioStop(element, focused));\n}\n\n/**\n * The stop the Tab key goes to from `from` without leaving `container`, or undefined when it\n * would leave it. `past` starts after everything inside `from`, as from a nested root as a whole.\n */\nfunction stepWithin(container: Element, from: Element, step: 1 | -1, past = false): HTMLElement | undefined {\n let before: HTMLElement | undefined;\n let passed = false;\n for (const element of walk(container)) {\n if (element === from) {\n if (step < 0) return before;\n passed = true;\n continue;\n }\n if (passed && past && containsDeep(from, element)) continue;\n if (!isStopFrom(element, from)) continue;\n if (passed) return element;\n before = element;\n }\n return undefined;\n}\n\n/** The first stop inside a container (step 1) or the last one (step -1), the container itself included. */\nfunction edgeStop(container: Element, step: 1 | -1, focused: Element | null): HTMLElement | undefined {\n let last: HTMLElement | undefined;\n for (const element of walk(container)) {\n if (!isStopFrom(element, focused)) continue;\n if (step > 0) return element;\n last = element;\n }\n return last;\n}\n\n/**\n * Into the reading-order children from `index` on: the first stop of the first one that has one,\n * or going backwards the last stop. A frame that ends a panel is entered by the browser itself,\n * which lands on the frame's own last stop (whatever its origin): its panel's end marker takes the\n * focus, and the browser's move goes on from there.\n */\nfunction enter(children: HTMLElement[], index: number, step: 1 | -1, focused: Element | null): TabGroupsTabMove | null {\n for (let at = index; at >= 0 && at < children.length; at += step) {\n const child = children[at];\n const stop = child ? edgeStop(child, step, focused) : undefined;\n if (!child || !stop) continue;\n const end = stop.localName === \"iframe\" ? child.querySelector<HTMLElement>(PANEL_END_SELECTOR) : null;\n return end ? { element: end, prevent: false } : { element: stop, prevent: true };\n }\n return null;\n}\n\n/**\n * What the Tab key (step 1) or Shift+Tab (step -1) does from `from`, the focused element in\n * `root`: null when the browser's own move is right — inside a child, or out of the root before\n * its first stop. At the end of the reading order the focus leaves through the guard, and the\n * browser moves on past the root from there.\n */\nexport function tabMove(root: HTMLElement, from: Element, step: 1 | -1): TabGroupsTabMove | null {\n const guard = guardOf(root);\n const children = readingChildren(root);\n // The guard holds the focus (nothing followed a frame at the end): Shift+Tab goes back in.\n if (from === guard) return step < 0 ? enter(children, children.length - 1, -1, from) : null;\n const child = rootChildOf(root, from);\n const index = child ? children.indexOf(child) : -1;\n if (!child || index < 0 || tabIndexOf(from) > 0) return null;\n if (stepWithin(child, from, step)) return null;\n const entered = enter(children, index + step, step, from);\n if (entered) return entered;\n return step > 0 && guard ? { element: guard, prevent: false } : null;\n}\n\n/** The last stop of the reading order, where Shift+Tab from after the root goes. */\nexport function lastStopOf(root: HTMLElement): HTMLElement | undefined {\n const children = readingChildren(root);\n for (let at = children.length - 1; at >= 0; at -= 1) {\n const child = children[at];\n const stop = child ? edgeStop(child, -1, null) : undefined;\n if (stop) return stop;\n }\n return undefined;\n}\n\n/**\n * Focuses a stop that is reached backwards: a frame whose document can be read (the same origin)\n * at its own last stop, as the browser's Shift+Tab would; another frame as a whole.\n */\nexport function focusFromEnd(element: HTMLElement): void {\n if (element.localName === \"iframe\") {\n let body: HTMLElement | null | undefined;\n try {\n body = (element as HTMLIFrameElement).contentDocument?.body;\n } catch {\n body = null;\n }\n const last = body ? edgeStop(body, -1, null) : undefined;\n if (last) {\n focusFromEnd(last);\n return;\n }\n }\n element.focus();\n}\n\n/** The first stop after a whole root: on in the root around it, or in the page. */\nfunction stopAfter(root: HTMLElement): HTMLElement | undefined {\n const outer = ownerRootOf(parentOf(root));\n if (!outer) {\n const body = root.ownerDocument.body;\n return body ? stepWithin(body, root, 1, true) : undefined;\n }\n const child = rootChildOf(outer, root);\n const children = readingChildren(outer);\n const index = child ? children.indexOf(child) : -1;\n if (child && index >= 0) {\n const inside = stepWithin(child, root, 1, true);\n if (inside) return inside;\n const entered = enter(children, index + 1, 1, null);\n if (entered) return entered.element;\n }\n return stopAfter(outer);\n}\n\n/**\n * Where the focus belongs after the browser's Tab took it out of `frame`, an iframe of this root,\n * onto `landed`. Inside a frame the keys are its own, so the browser left it by DOM order: to\n * another child of the root, or to the guard, when the frame ended its child. The next child in\n * reading order takes the focus instead, or after the last one whatever follows the root; with\n * nothing there the guard holds the focus (it is returned), and the next Tab leaves the page.\n * Null when the browser's move was right.\n */\nexport function frameExitTarget(root: HTMLElement, frame: Element, landed: Element): HTMLElement | null {\n const guard = guardOf(root);\n const child = rootChildOf(root, frame);\n if (!child || (landed !== guard && rootChildOf(root, landed) === child)) return null;\n // Out of a frame backwards the browser stays in its child: the child itself is a stop before it.\n if (landed !== guard && !(frame.compareDocumentPosition(landed) & 4)) return null;\n const children = readingChildren(root);\n const index = children.indexOf(child);\n if (index < 0) return null;\n const wanted = enter(children, index + 1, 1, null)?.element ?? stopAfter(root) ?? guard;\n return wanted === landed && landed !== guard ? null : wanted;\n}\n\nconst HEADER_CLASS = \"smwb-tab-groups__header\";\nconst STRIP_CLASS = \"smwb-tab-groups__strip-actions\";\n\n/** A control of a group's `stripActions` slot that has the focus: its group and its place among the slot's stops. */\nexport interface TabGroupsSlotFocus {\n element: HTMLElement;\n group: string;\n index: number;\n}\n\n/** The root's header of a group, walked rather than selected: ids need no escaping. */\nfunction headerOf(root: HTMLElement, groupId: string): HTMLElement | null {\n for (const child of Array.from(root.children)) {\n if (child.classList.contains(HEADER_CLASS) && child.getAttribute(\"data-group-id\") === groupId) {\n return child as HTMLElement;\n }\n }\n return null;\n}\n\n/** A header's `stripActions` wrapper, one of its own children (walked too: `:scope` breaks on some ids in jsdom). */\nfunction slotOf(header: Element): Element | undefined {\n return Array.from(header.children).find((child) => child.classList.contains(STRIP_CLASS));\n}\n\n/** The Tab stops of a header's `stripActions` slot in order; none when it draws no slot. */\nfunction slotStops(header: HTMLElement): HTMLElement[] {\n const slot = slotOf(header);\n const stops: HTMLElement[] = [];\n if (!slot) return stops;\n for (const element of walk(slot)) {\n if (element !== slot && isStopFrom(element, null)) stops.push(element);\n }\n return stops;\n}\n\n/** Where a focused element is in a `stripActions` slot of this root, or null when it is in none. */\nexport function slotFocusOf(root: HTMLElement, element: HTMLElement): TabGroupsSlotFocus | null {\n const header = rootChildOf(root, element);\n const group = header?.classList.contains(HEADER_CLASS) ? header.getAttribute(\"data-group-id\") : null;\n const slot = header ? slotOf(header) : undefined;\n if (!header || group === null || group === undefined || !slot || !containsDeep(slot, element)) return null;\n const stops = slotStops(header);\n const at = stops.indexOf(element);\n // Not a stop itself (`tabindex=\"-1\"`): its place is after the stops before it.\n const index = at >= 0 ? at : stops.filter((stop) => (stop.compareDocumentPosition(element) & 4) !== 0).length;\n return { element, group, index };\n}\n\n/**\n * Where the focus goes when the slot control that had it has left the document — a split or a\n * close from the slot takes the slot away with its group, or to the group the user works in now:\n * the stop at the same place (or the last one, when there are fewer) in the slot of the control's\n * own group while that still draws one, else in the slot of the group in use, else that group's\n * selected tab.\n */\nexport function slotFocusHeir(root: HTMLElement, lost: TabGroupsSlotFocus, activeGroup: string): HTMLElement | null {\n for (const groupId of [lost.group, activeGroup]) {\n const header = headerOf(root, groupId);\n const stops = header ? slotStops(header) : [];\n if (stops.length > 0) return stops[Math.min(lost.index, stops.length - 1)] ?? null;\n }\n return headerOf(root, activeGroup)?.querySelector<HTMLElement>('[role=\"tab\"][aria-selected=\"true\"]') ?? null;\n}\n"],"names":["ROOT_CLASS","GUARD_SELECTOR","PANEL_END_SELECTOR","READING_CHILD","FOCUSABLE","parentOf","node","parent","elementOf","containsDeep","ancestor","current","deepActiveElement","doc","active","ownerRootOf","rootChildOf","root","ownGroupIdOf","guardOf","readingChildren","id","element","isDrawn","tabIndexOf","value","isScrollerStop","style","scrolls","isStop","isRadio","sameGroup","a","b","checkedOf","radio","scope","member","isRadioStop","focused","checked","childrenOf","slot","assigned","walk","child","isStopFrom","stepWithin","container","from","step","past","before","passed","edgeStop","last","enter","children","index","at","stop","end","tabMove","guard","entered","lastStopOf","focusFromEnd","body","stopAfter","outer","inside","frameExitTarget","frame","landed","wanted","HEADER_CLASS","STRIP_CLASS","headerOf","groupId","slotOf","header","slotStops","stops","slotFocusOf","group","slotFocusHeir","lost","activeGroup"],"mappings":"AAcA,MAAMA,IAAa,mBACbC,IAAiB,0CACjBC,IAAqB,wCACrBC,IAAgB,kFAGhBC,IACJ;AASF,SAASC,EAASC,GAA4B;AAC5C,MAAIA,EAAK,cAAe,QAAOA,EAAK;AACpC,QAAMC,IAASD,EAAK;AACpB,SAAOC,GAAQ,aAAa,MAAMA,EAAO,OAAOA,EAAO,OAAO;AAChE;AAEA,SAASC,EAAUF,GAAmC;AACpD,SAAKA,IACEA,EAAK,aAAa,IAAKA,IAAmBD,EAASC,CAAI,IAD5C;AAEpB;AAGO,SAASG,EAAaC,GAAgBJ,GAA4B;AACvE,WAASK,IAAuBL,GAAMK,GAASA,IAAUN,EAASM,CAAO;AACvE,QAAIA,MAAYD,EAAU,QAAO;AAEnC,SAAO;AACT;AAGO,SAASE,EAAkBC,GAA+B;AAC/D,MAAIC,IAASD,EAAI;AACjB,SAAOC,GAAQ,YAAY,gBAAe,CAAAA,IAASA,EAAO,WAAW;AACrE,SAAOA;AACT;AAGO,SAASC,EAAYT,GAAuC;AACjE,WAASK,IAAUH,EAAUF,CAAI,GAAGK,GAASA,IAAUN,EAASM,CAAO;AACrE,QAAIA,EAAQ,UAAU,SAASX,CAAU,EAAG,QAAOW;AAErD,SAAO;AACT;AAGO,SAASK,EAAYC,GAAeX,GAAuC;AAChF,MAAIK,IAAUH,EAAUF,CAAI;AAC5B,SAAOK,KAAWN,EAASM,CAAO,MAAMM,IAAM,CAAAN,IAAUN,EAASM,CAAO;AACxE,SAAOA;AACT;AAGO,SAASO,EAAaD,GAAeX,GAAkC;AAC5E,SAAOU,EAAYC,GAAMX,CAAI,GAAG,aAAa,eAAe,KAAK;AACnE;AAGO,SAASa,EAAQF,GAAuC;AAC7D,SAAOA,EAAK,cAA2BhB,CAAc;AACvD;AAGO,SAASmB,EAAgBH,GAAkC;AAChE,QAAMJ,IAAMI,EAAK;AACjB,UAAQA,EAAK,aAAa,WAAW,KAAK,IAAI,MAAM,KAAK,EAAE,QAAQ,CAACI,MAAO;AACzE,UAAMC,IAAUD,IAAKR,EAAI,eAAeQ,CAAE,IAAI;AAC9C,WAAOC,KAAWA,EAAQ,kBAAkBL,KAAQ,CAACK,EAAQ,UAAUA,EAAQ,QAAQnB,CAAa,IAChG,CAACmB,CAAO,IACR,CAAA;AAAA,EACN,CAAC;AACH;AAGA,SAASC,EAAQD,GAA2B;AAC1C,SAAO,OAAOA,EAAQ,mBAAoB,cAAcA,EAAQ,gBAAgB,EAAE,oBAAoB,IAAM;AAC9G;AAEA,SAASE,EAAWF,GAA0B;AAC5C,QAAMG,IAASH,EAAiC;AAChD,SAAO,OAAOG,KAAU,WAAWA,IAAQ;AAC7C;AAGA,SAASC,EAAeJ,GAA2B;AACjD,MAAIA,EAAQ,gBAAgBA,EAAQ,gBAAgBA,EAAQ,eAAeA,EAAQ,YAAa,QAAO;AACvG,QAAMK,IAAQL,EAAQ,cAAc,aAAa,iBAAiBA,CAAO,GACnEM,IAAU,CAACH,MAAuCA,MAAU,UAAUA,MAAU;AACtF,SAAO,GAAQE,MAAUC,EAAQD,EAAM,SAAS,KAAKC,EAAQD,EAAM,SAAS,MAAM,CAACL,EAAQ,cAAclB,CAAS;AACpH;AAOA,SAASyB,EAAOP,GAA0C;AACxD,SAAIA,EAAQ,QAAQlB,CAAS,IACvBoB,EAAWF,CAAO,MAAM,KAAKA,EAAQ,QAAQ,WAAW,KACxDA,EAAQ,cAAc,WAAYA,EAA6B,SAAS,WAAiB,KACtFC,EAAQD,CAAO,IAEjBI,EAAeJ,CAAO;AAC/B;AAEA,SAASQ,EAAQR,GAA+C;AAC9D,SAAOA,EAAQ,cAAc,WAAYA,EAA6B,SAAS;AACjF;AAGA,SAASS,EAAUC,GAAqBC,GAA8B;AACpE,SAAOD,MAAMC,KAAMD,EAAE,SAAS,MAAMA,EAAE,SAASC,EAAE,QAAQD,EAAE,SAASC,EAAE,QAAQD,EAAE,YAAA,MAAkBC,EAAE,YAAA;AACtG;AAGA,SAASC,EAAUC,GAAkD;AACnE,MAAIA,EAAM,QAAS,QAAOA;AAC1B,MAAIA,EAAM,SAAS,GAAI,QAAO;AAC9B,QAAMC,IAAQD,EAAM,QAASA,EAAM,YAAA;AAEnC,UAD2BA,EAAM,OAAO,MAAM,KAAKA,EAAM,KAAK,QAAQ,IAAI,MAAM,KAAKC,EAAM,iBAAiB,OAAO,CAAC,GAE1G;AAAA,IACN,CAACC,MAAuCP,EAAQO,CAAM,KAAKA,EAAO,WAAWN,EAAUI,GAAOE,CAAM;AAAA,EAAA,KACjG;AAET;AAMA,SAASC,EAAYH,GAAyBI,GAAkC;AAC9E,MAAIA,KAAWT,EAAQS,CAAO,KAAKR,EAAUQ,GAASJ,CAAK,EAAG,QAAO;AACrE,QAAMK,IAAUN,EAAUC,CAAK;AAC/B,SAAOK,MAAY,QAAQA,MAAYL;AACzC;AAGA,SAASM,EAAWnB,GAA6B;AAC/C,MAAIA,EAAQ,WAAY,QAAO,MAAM,KAAKA,EAAQ,WAAW,QAAQ;AACrE,MAAIA,EAAQ,cAAc,QAAQ;AAChC,UAAMoB,IAAOpB,GACPqB,IAAW,OAAOD,EAAK,oBAAqB,aAAaA,EAAK,iBAAA,IAAqB,CAAA;AACzF,QAAIC,EAAS,SAAS,EAAG,QAAOA;AAAA,EAClC;AACA,SAAO,MAAM,KAAKrB,EAAQ,QAAQ;AACpC;AAGA,UAAUsB,EAAKtB,GAAsC;AACnD,QAAMA;AACN,aAAWuB,KAASJ,EAAWnB,CAAO;AACpC,IAAKuB,EAAM,QAAQ,mBAAmB,MAAG,OAAOD,EAAKC,CAAK;AAE9D;AAEA,SAASC,EAAWxB,GAAkBiB,GAAiD;AACrF,SAAOV,EAAOP,CAAO,MAAM,CAACQ,EAAQR,CAAO,KAAKgB,EAAYhB,GAASiB,CAAO;AAC9E;AAMA,SAASQ,EAAWC,GAAoBC,GAAeC,GAAcC,IAAO,IAAgC;AAC1G,MAAIC,GACAC,IAAS;AACb,aAAW/B,KAAWsB,EAAKI,CAAS,GAAG;AACrC,QAAI1B,MAAY2B,GAAM;AACpB,UAAIC,IAAO,EAAG,QAAOE;AACrB,MAAAC,IAAS;AACT;AAAA,IACF;AACA,QAAI,EAAAA,KAAUF,KAAQ1C,EAAawC,GAAM3B,CAAO,MAC3CwB,EAAWxB,GAAS2B,CAAI,GAC7B;AAAA,UAAII,EAAQ,QAAO/B;AACnB,MAAA8B,IAAS9B;AAAA;AAAA,EACX;AAEF;AAGA,SAASgC,EAASN,GAAoBE,GAAcX,GAAkD;AACpG,MAAIgB;AACJ,aAAWjC,KAAWsB,EAAKI,CAAS;AAClC,QAAKF,EAAWxB,GAASiB,CAAO,GAChC;AAAA,UAAIW,IAAO,EAAG,QAAO5B;AACrB,MAAAiC,IAAOjC;AAAA;AAET,SAAOiC;AACT;AAQA,SAASC,EAAMC,GAAyBC,GAAeR,GAAcX,GAAkD;AACrH,WAASoB,IAAKD,GAAOC,KAAM,KAAKA,IAAKF,EAAS,QAAQE,KAAMT,GAAM;AAChE,UAAML,IAAQY,EAASE,CAAE,GACnBC,IAAOf,IAAQS,EAAST,GAAOK,GAAMX,CAAO,IAAI;AACtD,QAAI,CAACM,KAAS,CAACe,EAAM;AACrB,UAAMC,IAAMD,EAAK,cAAc,WAAWf,EAAM,cAA2B3C,CAAkB,IAAI;AACjG,WAAO2D,IAAM,EAAE,SAASA,GAAK,SAAS,GAAA,IAAU,EAAE,SAASD,GAAM,SAAS,GAAA;AAAA,EAC5E;AACA,SAAO;AACT;AAQO,SAASE,EAAQ7C,GAAmBgC,GAAeC,GAAuC;AAC/F,QAAMa,IAAQ5C,EAAQF,CAAI,GACpBwC,IAAWrC,EAAgBH,CAAI;AAErC,MAAIgC,MAASc,EAAO,QAAOb,IAAO,IAAIM,EAAMC,GAAUA,EAAS,SAAS,GAAG,IAAIR,CAAI,IAAI;AACvF,QAAMJ,IAAQ7B,EAAYC,GAAMgC,CAAI,GAC9BS,IAAQb,IAAQY,EAAS,QAAQZ,CAAK,IAAI;AAEhD,MADI,CAACA,KAASa,IAAQ,KAAKlC,EAAWyB,CAAI,IAAI,KAC1CF,EAAWF,GAAOI,GAAMC,CAAI,EAAG,QAAO;AAC1C,QAAMc,IAAUR,EAAMC,GAAUC,IAAQR,GAAMA,GAAMD,CAAI;AACxD,SAAIe,MACGd,IAAO,KAAKa,IAAQ,EAAE,SAASA,GAAO,SAAS,OAAU;AAClE;AAGO,SAASE,EAAWhD,GAA4C;AACrE,QAAMwC,IAAWrC,EAAgBH,CAAI;AACrC,WAAS0C,IAAKF,EAAS,SAAS,GAAGE,KAAM,GAAGA,KAAM,GAAG;AACnD,UAAMd,IAAQY,EAASE,CAAE,GACnBC,IAAOf,IAAQS,EAAST,GAAO,IAAI,IAAI,IAAI;AACjD,QAAIe,EAAM,QAAOA;AAAA,EACnB;AAEF;AAMO,SAASM,EAAa5C,GAA4B;AACvD,MAAIA,EAAQ,cAAc,UAAU;AAClC,QAAI6C;AACJ,QAAI;AACF,MAAAA,IAAQ7C,EAA8B,iBAAiB;AAAA,IACzD,QAAQ;AACN,MAAA6C,IAAO;AAAA,IACT;AACA,UAAMZ,IAAOY,IAAOb,EAASa,GAAM,IAAI,IAAI,IAAI;AAC/C,QAAIZ,GAAM;AACR,MAAAW,EAAaX,CAAI;AACjB;AAAA,IACF;AAAA,EACF;AACA,EAAAjC,EAAQ,MAAA;AACV;AAGA,SAAS8C,EAAUnD,GAA4C;AAC7D,QAAMoD,IAAQtD,EAAYV,EAASY,CAAI,CAAC;AACxC,MAAI,CAACoD,GAAO;AACV,UAAMF,IAAOlD,EAAK,cAAc;AAChC,WAAOkD,IAAOpB,EAAWoB,GAAMlD,GAAM,GAAG,EAAI,IAAI;AAAA,EAClD;AACA,QAAM4B,IAAQ7B,EAAYqD,GAAOpD,CAAI,GAC/BwC,IAAWrC,EAAgBiD,CAAK,GAChCX,IAAQb,IAAQY,EAAS,QAAQZ,CAAK,IAAI;AAChD,MAAIA,KAASa,KAAS,GAAG;AACvB,UAAMY,IAASvB,EAAWF,GAAO5B,GAAM,GAAG,EAAI;AAC9C,QAAIqD,EAAQ,QAAOA;AACnB,UAAMN,IAAUR,EAAMC,GAAUC,IAAQ,GAAG,GAAG,IAAI;AAClD,QAAIM,UAAgBA,EAAQ;AAAA,EAC9B;AACA,SAAOI,EAAUC,CAAK;AACxB;AAUO,SAASE,EAAgBtD,GAAmBuD,GAAgBC,GAAqC;AACtG,QAAMV,IAAQ5C,EAAQF,CAAI,GACpB4B,IAAQ7B,EAAYC,GAAMuD,CAAK;AAGrC,MAFI,CAAC3B,KAAU4B,MAAWV,KAAS/C,EAAYC,GAAMwD,CAAM,MAAM5B,KAE7D4B,MAAWV,KAAS,EAAES,EAAM,wBAAwBC,CAAM,IAAI,GAAI,QAAO;AAC7E,QAAMhB,IAAWrC,EAAgBH,CAAI,GAC/ByC,IAAQD,EAAS,QAAQZ,CAAK;AACpC,MAAIa,IAAQ,EAAG,QAAO;AACtB,QAAMgB,IAASlB,EAAMC,GAAUC,IAAQ,GAAG,GAAG,IAAI,GAAG,WAAWU,EAAUnD,CAAI,KAAK8C;AAClF,SAAOW,MAAWD,KAAUA,MAAWV,IAAQ,OAAOW;AACxD;AAEA,MAAMC,IAAe,2BACfC,IAAc;AAUpB,SAASC,EAAS5D,GAAmB6D,GAAqC;AACxE,aAAWjC,KAAS,MAAM,KAAK5B,EAAK,QAAQ;AAC1C,QAAI4B,EAAM,UAAU,SAAS8B,CAAY,KAAK9B,EAAM,aAAa,eAAe,MAAMiC;AACpF,aAAOjC;AAGX,SAAO;AACT;AAGA,SAASkC,EAAOC,GAAsC;AACpD,SAAO,MAAM,KAAKA,EAAO,QAAQ,EAAE,KAAK,CAACnC,MAAUA,EAAM,UAAU,SAAS+B,CAAW,CAAC;AAC1F;AAGA,SAASK,EAAUD,GAAoC;AACrD,QAAMtC,IAAOqC,EAAOC,CAAM,GACpBE,IAAuB,CAAA;AAC7B,MAAI,CAACxC,EAAM,QAAOwC;AAClB,aAAW5D,KAAWsB,EAAKF,CAAI;AAC7B,IAAIpB,MAAYoB,KAAQI,EAAWxB,GAAS,IAAI,KAAG4D,EAAM,KAAK5D,CAAO;AAEvE,SAAO4D;AACT;AAGO,SAASC,EAAYlE,GAAmBK,GAAiD;AAC9F,QAAM0D,IAAShE,EAAYC,GAAMK,CAAO,GAClC8D,IAAQJ,GAAQ,UAAU,SAASL,CAAY,IAAIK,EAAO,aAAa,eAAe,IAAI,MAC1FtC,IAAOsC,IAASD,EAAOC,CAAM,IAAI;AACvC,MAAI,CAACA,KAAUI,MAAU,QAAQA,MAAU,UAAa,CAAC1C,KAAQ,CAACjC,EAAaiC,GAAMpB,CAAO,EAAG,QAAO;AACtG,QAAM4D,IAAQD,EAAUD,CAAM,GACxBrB,IAAKuB,EAAM,QAAQ5D,CAAO,GAE1BoC,IAAQC,KAAM,IAAIA,IAAKuB,EAAM,OAAO,CAACtB,OAAUA,EAAK,wBAAwBtC,CAAO,IAAI,OAAO,CAAC,EAAE;AACvG,SAAO,EAAE,SAAAA,GAAS,OAAA8D,GAAO,OAAA1B,EAAA;AAC3B;AASO,SAAS2B,EAAcpE,GAAmBqE,GAA0BC,GAAyC;AAClH,aAAWT,KAAW,CAACQ,EAAK,OAAOC,CAAW,GAAG;AAC/C,UAAMP,IAASH,EAAS5D,GAAM6D,CAAO,GAC/BI,IAAQF,IAASC,EAAUD,CAAM,IAAI,CAAA;AAC3C,QAAIE,EAAM,SAAS,EAAG,QAAOA,EAAM,KAAK,IAAII,EAAK,OAAOJ,EAAM,SAAS,CAAC,CAAC,KAAK;AAAA,EAChF;AACA,SAAOL,EAAS5D,GAAMsE,CAAW,GAAG,cAA2B,oCAAoC,KAAK;AAC1G;"}
|
|
@@ -6,8 +6,20 @@ export interface AppBarProps extends Omit<JSX.HTMLAttributes<HTMLElement>, "titl
|
|
|
6
6
|
position?: "relative" | "static" | "absolute" | "sticky" | "fixed";
|
|
7
7
|
placement?: "top" | "bottom";
|
|
8
8
|
leftContent?: JSX.Element;
|
|
9
|
+
/**
|
|
10
|
+
* Content of the middle area, e.g. a search field. The area takes only the room the title and the right group leave
|
|
11
|
+
* free (`flex: 1 1 0`), so it is the first to narrow when the bar does. A direct child narrows with it (`max-width: 100%`)
|
|
12
|
+
* only as far as its own content can: a control with a minimum width, or a nowrap row of buttons or tabs, keeps it and
|
|
13
|
+
* runs under the right group when the title takes the whole bar, so give such content `min-width: 0` or let it shrink.
|
|
14
|
+
*/
|
|
9
15
|
midContent?: JSX.Element;
|
|
10
16
|
rightContent?: JSX.Element;
|
|
17
|
+
/**
|
|
18
|
+
* Title in the left group. It keeps its content size while the middle area has room to give up; when the bar is
|
|
19
|
+
* narrower than the title and the right group together, a text title is cut with an ellipsis and the right group stays
|
|
20
|
+
* inside the bar. The cut leaves a margin for a focus ring (`overflow: clip`), so a link or a button in the title keeps
|
|
21
|
+
* its ring.
|
|
22
|
+
*/
|
|
11
23
|
title?: JSX.Element | string;
|
|
12
24
|
/**
|
|
13
25
|
* Tag the `title` is rendered in: a `div` (default) or a heading, `h1`–`h6`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appBar.js","sources":["../../../../src/components/navigation/appBar/appBar.tsx"],"sourcesContent":["import { type JSX, type ParentProps, Show, children, mergeProps, splitProps } from \"solid-js\";\nimport { Dynamic } from \"solid-js/web\";\nimport cn from \"clsx\";\nimport { mergeRefs, type Ref } from \"../../../primitives/mergeRefs\";\n\nexport type AppBarColor = \"default\" | \"primary\" | \"secondary\" | \"error\" | \"success\" | \"warning\" | \"info\";\n\nexport interface AppBarProps extends Omit<JSX.HTMLAttributes<HTMLElement>, \"title\"> {\n dense?: boolean;\n position?: \"relative\" | \"static\" | \"absolute\" | \"sticky\" | \"fixed\";\n placement?: \"top\" | \"bottom\";\n leftContent?: JSX.Element;\n midContent?: JSX.Element;\n rightContent?: JSX.Element;\n title?: JSX.Element | string;\n /**\n * Tag the `title` is rendered in: a `div` (default) or a heading, `h1`–`h6`,\n * for the page's main heading. Only the tag changes — a heading is drawn with\n * the bar's own font size, weight and no margins, so it looks exactly like the\n * div. The heading's text is the `title` itself, so pass a string or plain\n * markup rather than a `Typography` heading.\n */\n titleAs?: \"div\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\";\n midContentAlign?: \"middle\" | \"left\" | \"right\";\n /**\n * `window`: the bar is the title bar of a desktop app window (Electron, Tauri, an installed PWA with Window\n * Controls Overlay). The bar drags the window; buttons, links, fields and other controls in it stay clickable,\n * and room is left for the OS window buttons (`windowControls`). In a plain browser tab it looks like `default`.\n */\n variant?: \"default\" | \"window\";\n /**\n * With `variant=\"window\"`: where the OS window buttons are, so the bar's content keeps clear of them.\n * `auto` (default) takes the area from the shell's `env(titlebar-area-*)` (Window Controls Overlay, Electron\n * `titleBarOverlay`) and reserves nothing without it; `left` is macOS (traffic lights, `titleBarStyle: \"hiddenInset\"`),\n * `right` is Windows/Linux caption buttons drawn by the OS; `none` reserves nothing. The reserved width is\n * the `--smui-appBarWindowControlsWidth` custom property (64px on the left, 138px on the right by default).\n */\n windowControls?: \"auto\" | \"left\" | \"right\" | \"none\";\n /** Semantic background color. */\n color?: AppBarColor;\n /** Test id of the root (`<header>`, or `<footer>` at the bottom); `app-bar` unless given. */\n \"data-testid\"?: string | undefined;\n ref?: Ref<HTMLElement>;\n}\n\nexport function AppBar(props: ParentProps<AppBarProps>): JSX.Element {\n const merged = mergeProps(\n {\n position: \"static\" as const,\n placement: \"top\" as const,\n midContentAlign: \"middle\" as const,\n variant: \"default\" as const,\n windowControls: \"auto\" as const,\n color: \"default\" as AppBarColor,\n },\n props\n );\n const [local, rest] = splitProps(merged, [\n \"class\",\n \"children\",\n \"dense\",\n \"position\",\n \"placement\",\n \"leftContent\",\n \"midContent\",\n \"midContentAlign\",\n \"variant\",\n \"windowControls\",\n \"rightContent\",\n \"title\",\n \"titleAs\",\n \"color\",\n \"ref\",\n \"data-testid\",\n ]);\n\n // Read each slot once: markup passed as a prop is created anew on every read,\n // and during hydration a copy the server never rendered has no DOM node.\n const content = children(() => local.children);\n // The title is drawn only without children, so it is read only then.\n const title = children(() => (content() ? undefined : local.title));\n\n return (\n <Dynamic\n component={local.placement === \"top\" ? \"header\" : \"footer\"}\n {...rest}\n ref={mergeRefs(local.ref)}\n data-testid={local[\"data-testid\"] ?? \"app-bar\"}\n class={cn(\n \"smwb-appbar\",\n local.class,\n `smwb-${local.position}`,\n `smwb-${local.placement}`,\n { \"smwb-dense\": local.dense },\n local.color !== \"default\" && `smwb-appbar_color-${local.color}`,\n local.variant === \"window\" && \"smwb-appbar_variant-window\",\n local.variant === \"window\" &&\n local.windowControls !== \"auto\" &&\n `smwb-appbar_window-controls-${local.windowControls}`\n )}\n >\n <Show\n when={content()}\n fallback={\n <div class=\"smwb-appbar__inner\">\n <div class=\"smwb-appbar__left\">\n <Show keyed when={title() && (local.titleAs ?? \"div\")}>\n {(tag) => {\n // Headings go through literal templates too: `Dynamic` would add a hydration level to the\n // default `div` and a trailing space to the class on the server.\n switch (tag) {\n case \"h1\":\n return <h1 class=\"smwb-appbar__left__title\">{title()}</h1>;\n case \"h2\":\n return <h2 class=\"smwb-appbar__left__title\">{title()}</h2>;\n case \"h3\":\n return <h3 class=\"smwb-appbar__left__title\">{title()}</h3>;\n case \"h4\":\n return <h4 class=\"smwb-appbar__left__title\">{title()}</h4>;\n case \"h5\":\n return <h5 class=\"smwb-appbar__left__title\">{title()}</h5>;\n case \"h6\":\n return <h6 class=\"smwb-appbar__left__title\">{title()}</h6>;\n default:\n return <div class=\"smwb-appbar__left__title\">{title()}</div>;\n }\n }}\n </Show>\n {local.leftContent}\n </div>\n <div class={cn(\"smwb-appbar__mid\", `smwb-${local.midContentAlign}`)}>{local.midContent}</div>\n <div class=\"smwb-appbar__right\">{local.rightContent}</div>\n </div>\n }\n >\n {content()}\n </Show>\n </Dynamic>\n );\n}\n\nexport default AppBar;\n"],"names":["AppBar","props","merged","mergeProps","position","placement","midContentAlign","variant","windowControls","color","local","rest","splitProps","content","children","title","undefined","_$createComponent","Dynamic","_$mergeProps","component","ref","r$","_ref$","mergeRefs","cn","class","dense","Show","when","fallback","_el$","_tmpl$","_el$2","firstChild","_el$3","nextSibling","_el$4","_$insert","keyed","_$memo","titleAs","tag","_el$5","_tmpl$2","_el$6","_tmpl$3","_el$7","_tmpl$4","_el$8","_tmpl$5","_el$9","_tmpl$6","_el$0","_tmpl$7","_el$1","_tmpl$8","leftContent","midContent","rightContent","_$effect","_$className"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"appBar.js","sources":["../../../../src/components/navigation/appBar/appBar.tsx"],"sourcesContent":["import { type JSX, type ParentProps, Show, children, mergeProps, splitProps } from \"solid-js\";\nimport { Dynamic } from \"solid-js/web\";\nimport cn from \"clsx\";\nimport { mergeRefs, type Ref } from \"../../../primitives/mergeRefs\";\n\nexport type AppBarColor = \"default\" | \"primary\" | \"secondary\" | \"error\" | \"success\" | \"warning\" | \"info\";\n\nexport interface AppBarProps extends Omit<JSX.HTMLAttributes<HTMLElement>, \"title\"> {\n dense?: boolean;\n position?: \"relative\" | \"static\" | \"absolute\" | \"sticky\" | \"fixed\";\n placement?: \"top\" | \"bottom\";\n leftContent?: JSX.Element;\n /**\n * Content of the middle area, e.g. a search field. The area takes only the room the title and the right group leave\n * free (`flex: 1 1 0`), so it is the first to narrow when the bar does. A direct child narrows with it (`max-width: 100%`)\n * only as far as its own content can: a control with a minimum width, or a nowrap row of buttons or tabs, keeps it and\n * runs under the right group when the title takes the whole bar, so give such content `min-width: 0` or let it shrink.\n */\n midContent?: JSX.Element;\n rightContent?: JSX.Element;\n /**\n * Title in the left group. It keeps its content size while the middle area has room to give up; when the bar is\n * narrower than the title and the right group together, a text title is cut with an ellipsis and the right group stays\n * inside the bar. The cut leaves a margin for a focus ring (`overflow: clip`), so a link or a button in the title keeps\n * its ring.\n */\n title?: JSX.Element | string;\n /**\n * Tag the `title` is rendered in: a `div` (default) or a heading, `h1`–`h6`,\n * for the page's main heading. Only the tag changes — a heading is drawn with\n * the bar's own font size, weight and no margins, so it looks exactly like the\n * div. The heading's text is the `title` itself, so pass a string or plain\n * markup rather than a `Typography` heading.\n */\n titleAs?: \"div\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\";\n midContentAlign?: \"middle\" | \"left\" | \"right\";\n /**\n * `window`: the bar is the title bar of a desktop app window (Electron, Tauri, an installed PWA with Window\n * Controls Overlay). The bar drags the window; buttons, links, fields and other controls in it stay clickable,\n * and room is left for the OS window buttons (`windowControls`). In a plain browser tab it looks like `default`.\n */\n variant?: \"default\" | \"window\";\n /**\n * With `variant=\"window\"`: where the OS window buttons are, so the bar's content keeps clear of them.\n * `auto` (default) takes the area from the shell's `env(titlebar-area-*)` (Window Controls Overlay, Electron\n * `titleBarOverlay`) and reserves nothing without it; `left` is macOS (traffic lights, `titleBarStyle: \"hiddenInset\"`),\n * `right` is Windows/Linux caption buttons drawn by the OS; `none` reserves nothing. The reserved width is\n * the `--smui-appBarWindowControlsWidth` custom property (64px on the left, 138px on the right by default).\n */\n windowControls?: \"auto\" | \"left\" | \"right\" | \"none\";\n /** Semantic background color. */\n color?: AppBarColor;\n /** Test id of the root (`<header>`, or `<footer>` at the bottom); `app-bar` unless given. */\n \"data-testid\"?: string | undefined;\n ref?: Ref<HTMLElement>;\n}\n\nexport function AppBar(props: ParentProps<AppBarProps>): JSX.Element {\n const merged = mergeProps(\n {\n position: \"static\" as const,\n placement: \"top\" as const,\n midContentAlign: \"middle\" as const,\n variant: \"default\" as const,\n windowControls: \"auto\" as const,\n color: \"default\" as AppBarColor,\n },\n props\n );\n const [local, rest] = splitProps(merged, [\n \"class\",\n \"children\",\n \"dense\",\n \"position\",\n \"placement\",\n \"leftContent\",\n \"midContent\",\n \"midContentAlign\",\n \"variant\",\n \"windowControls\",\n \"rightContent\",\n \"title\",\n \"titleAs\",\n \"color\",\n \"ref\",\n \"data-testid\",\n ]);\n\n // Read each slot once: markup passed as a prop is created anew on every read,\n // and during hydration a copy the server never rendered has no DOM node.\n const content = children(() => local.children);\n // The title is drawn only without children, so it is read only then.\n const title = children(() => (content() ? undefined : local.title));\n\n return (\n <Dynamic\n component={local.placement === \"top\" ? \"header\" : \"footer\"}\n {...rest}\n ref={mergeRefs(local.ref)}\n data-testid={local[\"data-testid\"] ?? \"app-bar\"}\n class={cn(\n \"smwb-appbar\",\n local.class,\n `smwb-${local.position}`,\n `smwb-${local.placement}`,\n { \"smwb-dense\": local.dense },\n local.color !== \"default\" && `smwb-appbar_color-${local.color}`,\n local.variant === \"window\" && \"smwb-appbar_variant-window\",\n local.variant === \"window\" &&\n local.windowControls !== \"auto\" &&\n `smwb-appbar_window-controls-${local.windowControls}`\n )}\n >\n <Show\n when={content()}\n fallback={\n <div class=\"smwb-appbar__inner\">\n <div class=\"smwb-appbar__left\">\n <Show keyed when={title() && (local.titleAs ?? \"div\")}>\n {(tag) => {\n // Headings go through literal templates too: `Dynamic` would add a hydration level to the\n // default `div` and a trailing space to the class on the server.\n switch (tag) {\n case \"h1\":\n return <h1 class=\"smwb-appbar__left__title\">{title()}</h1>;\n case \"h2\":\n return <h2 class=\"smwb-appbar__left__title\">{title()}</h2>;\n case \"h3\":\n return <h3 class=\"smwb-appbar__left__title\">{title()}</h3>;\n case \"h4\":\n return <h4 class=\"smwb-appbar__left__title\">{title()}</h4>;\n case \"h5\":\n return <h5 class=\"smwb-appbar__left__title\">{title()}</h5>;\n case \"h6\":\n return <h6 class=\"smwb-appbar__left__title\">{title()}</h6>;\n default:\n return <div class=\"smwb-appbar__left__title\">{title()}</div>;\n }\n }}\n </Show>\n {local.leftContent}\n </div>\n <div class={cn(\"smwb-appbar__mid\", `smwb-${local.midContentAlign}`)}>{local.midContent}</div>\n <div class=\"smwb-appbar__right\">{local.rightContent}</div>\n </div>\n }\n >\n {content()}\n </Show>\n </Dynamic>\n );\n}\n\nexport default AppBar;\n"],"names":["AppBar","props","merged","mergeProps","position","placement","midContentAlign","variant","windowControls","color","local","rest","splitProps","content","children","title","undefined","_$createComponent","Dynamic","_$mergeProps","component","ref","r$","_ref$","mergeRefs","cn","class","dense","Show","when","fallback","_el$","_tmpl$","_el$2","firstChild","_el$3","nextSibling","_el$4","_$insert","keyed","_$memo","titleAs","tag","_el$5","_tmpl$2","_el$6","_tmpl$3","_el$7","_tmpl$4","_el$8","_tmpl$5","_el$9","_tmpl$6","_el$0","_tmpl$7","_el$1","_tmpl$8","leftContent","midContent","rightContent","_$effect","_$className"],"mappings":"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"}
|
|
@@ -15,6 +15,15 @@ export interface BreadcrumbsProps extends JSX.HTMLAttributes<HTMLElement> {
|
|
|
15
15
|
onExpand?: () => void;
|
|
16
16
|
/** Accessible label for the expand button. */
|
|
17
17
|
expandLabel?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Keep the trail on one line: the crumbs do not wrap, they shrink and cut their text with an ellipsis, the last one
|
|
20
|
+
* giving way last, and a cut crumb shows its full text as a `title` on hover. Plain text and a block child (a heading,
|
|
21
|
+
* `Typography`) are cut with an ellipsis; a crumb laid out as a row (an icon with a label, say) is clipped as far as
|
|
22
|
+
* its own layout allows. A leading crumb is never narrower than `@breadcrumbsLeadingMinWidth`, so a one- or
|
|
23
|
+
* two-letter one takes that width even when everything fits, and the last one is never narrower than
|
|
24
|
+
* `@breadcrumbsLastMinWidth`: in a box smaller than those floors the trail runs past it instead of shrinking further.
|
|
25
|
+
*/
|
|
26
|
+
noWrap?: boolean;
|
|
18
27
|
/** Test id of the root `<nav>`; `breadcrumbs` unless given. */
|
|
19
28
|
"data-testid"?: string | undefined;
|
|
20
29
|
ref?: Ref<HTMLElement>;
|