@u-elements/u-tabs 0.0.5 → 0.0.6
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/dist/u-tabs.cjs +36 -18
- package/dist/u-tabs.d.cts +6 -4
- package/dist/u-tabs.d.ts +6 -4
- package/dist/u-tabs.js +36 -18
- package/dist/u-tabs.manifest.json +5 -0
- package/dist/u-tabs.vscode.json +1 -1
- package/package.json +23 -23
package/dist/u-tabs.cjs
CHANGED
|
@@ -3,17 +3,21 @@
|
|
|
3
3
|
// ../utils.ts
|
|
4
4
|
var IS_BROWSER = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.navigator !== "undefined";
|
|
5
5
|
var IS_ANDROID = IS_BROWSER && /android/i.test(navigator.userAgent);
|
|
6
|
+
IS_BROWSER && // @ts-expect-error Typescript has not implemented userAgentData yet https://stackoverflow.com/a/71392474
|
|
7
|
+
/^Mac/i.test(navigator.userAgentData?.platform || navigator.platform);
|
|
6
8
|
var SAFE_LABELLEDBY = `${IS_ANDROID ? "data" : "aria"}-labelledby`;
|
|
7
9
|
var DISPLAY_BLOCK = ":host(:not([hidden])) { display: block }";
|
|
8
10
|
var UHTMLElement = typeof HTMLElement === "undefined" ? class {
|
|
9
11
|
} : HTMLElement;
|
|
10
|
-
var events = (action, element, rest) =>
|
|
11
|
-
rest[0]
|
|
12
|
-
|
|
13
|
-
});
|
|
12
|
+
var events = (action, element, rest) => {
|
|
13
|
+
for (const type of rest[0].split(",")) {
|
|
14
|
+
rest[0] = type;
|
|
15
|
+
Element.prototype[`${action}EventListener`].apply(element, rest);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
14
18
|
var on = (element, ...rest) => events("add", element, rest);
|
|
15
19
|
var off = (element, ...rest) => events("remove", element, rest);
|
|
16
|
-
var attachStyle = (element, css) => element.attachShadow({ mode: "
|
|
20
|
+
var attachStyle = (element, css) => element.attachShadow({ mode: "open" }).append(
|
|
17
21
|
createElement("slot"),
|
|
18
22
|
// Unnamed slot does automatically render all top element nodes
|
|
19
23
|
createElement("style", { textContent: css })
|
|
@@ -26,7 +30,11 @@ var asButton = (event) => {
|
|
|
26
30
|
};
|
|
27
31
|
var getRoot = (node) => node.getRootNode();
|
|
28
32
|
var id = 0;
|
|
29
|
-
var useId = (el) =>
|
|
33
|
+
var useId = (el) => {
|
|
34
|
+
if (!el) return "";
|
|
35
|
+
if (!el.id) el.id = `:${el.nodeName.toLowerCase()}${(++id).toString(32)}`;
|
|
36
|
+
return el.id;
|
|
37
|
+
};
|
|
30
38
|
var createElement = (tagName, props) => Object.assign(document.createElement(tagName), props);
|
|
31
39
|
var customElements = {
|
|
32
40
|
define: (name, instance) => !IS_BROWSER || window.customElements.get(name) || window.customElements.define(name, instance)
|
|
@@ -111,7 +119,7 @@ var UHTMLTabElement = class extends UHTMLElement {
|
|
|
111
119
|
super();
|
|
112
120
|
attachStyle(
|
|
113
121
|
this,
|
|
114
|
-
|
|
122
|
+
":host(:not([hidden])) { cursor: pointer; display: inline-block }"
|
|
115
123
|
);
|
|
116
124
|
}
|
|
117
125
|
connectedCallback() {
|
|
@@ -127,16 +135,16 @@ var UHTMLTabElement = class extends UHTMLElement {
|
|
|
127
135
|
const nextPanel = getPanel(this);
|
|
128
136
|
const nextPanelId = useId(nextPanel);
|
|
129
137
|
if (name === "aria-selected" && this.tabList)
|
|
130
|
-
queryWithoutNested("u-tab", this.tabList)
|
|
138
|
+
for (const tab of queryWithoutNested("u-tab", this.tabList)) {
|
|
131
139
|
if (tab !== this && isSelected(tab)) {
|
|
132
140
|
getPanel(tab)?.setAttribute("hidden", "");
|
|
133
141
|
tab.ariaSelected = "false";
|
|
134
142
|
tab.tabIndex = -1;
|
|
135
143
|
}
|
|
136
|
-
}
|
|
144
|
+
}
|
|
137
145
|
if (name === ARIA_CONTROLS && prev)
|
|
138
146
|
getPanel(this, prev)?.setAttribute("hidden", "");
|
|
139
|
-
if (this.getAttribute(ARIA_CONTROLS) !== nextPanelId)
|
|
147
|
+
if (nextPanel && this.getAttribute(ARIA_CONTROLS) !== nextPanelId)
|
|
140
148
|
this.setAttribute(ARIA_CONTROLS, nextPanelId);
|
|
141
149
|
this.tabIndex = 0;
|
|
142
150
|
nextPanel?.setAttribute(SAFE_LABELLEDBY, useId(this));
|
|
@@ -172,6 +180,12 @@ var UHTMLTabPanelElement = class extends UHTMLElement {
|
|
|
172
180
|
connectedCallback() {
|
|
173
181
|
this.hidden = getSelectedIndex(this.tabs) === -1;
|
|
174
182
|
this.role = "tabpanel";
|
|
183
|
+
this.attributeChangedCallback();
|
|
184
|
+
}
|
|
185
|
+
attributeChangedCallback() {
|
|
186
|
+
if (this.hidden || isFocusable(this.firstElementChild))
|
|
187
|
+
this.removeAttribute("tabindex");
|
|
188
|
+
else this.tabIndex = 0;
|
|
175
189
|
}
|
|
176
190
|
get tabsElement() {
|
|
177
191
|
return this.closest("u-tabs");
|
|
@@ -182,16 +196,20 @@ var UHTMLTabPanelElement = class extends UHTMLElement {
|
|
|
182
196
|
return root.length ? root : document.querySelectorAll(css);
|
|
183
197
|
}
|
|
184
198
|
};
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
199
|
+
UHTMLTabPanelElement.observedAttributes = ["hidden"];
|
|
200
|
+
var queryWithoutNested = (tag, self) => self.querySelectorAll(
|
|
201
|
+
`${tag}:not(:scope ${self.nodeName}:not(:scope) ${tag})`
|
|
202
|
+
);
|
|
189
203
|
var isSelected = (tab) => tab.ariaSelected === "true";
|
|
190
204
|
var getSelectedIndex = (tabs) => [...tabs].findIndex(isSelected);
|
|
191
|
-
var
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
205
|
+
var isFocusable = (el) => el instanceof Element && el.matches(
|
|
206
|
+
`:is([contenteditable],[controls],[href],[tabindex],input:not([type="hidden"]),select,textarea,button,summary,iframe):not(:disabled,[tabindex^="-"])`
|
|
207
|
+
);
|
|
208
|
+
var getPanel = (tab, id2) => {
|
|
209
|
+
const panelId = id2 || tab.getAttribute(ARIA_CONTROLS);
|
|
210
|
+
const panelSelector = `u-tabpanel[id="${panelId}"]`;
|
|
211
|
+
const tabsElement = tab.closest("u-tabs");
|
|
212
|
+
return panelId && getRoot(tab).querySelector(panelSelector) || panelId && getRoot(tab).querySelector(panelSelector) || tabsElement && queryWithoutNested("u-tabpanel", tabsElement)[[...queryWithoutNested("u-tab", tabsElement)].indexOf(tab)] || null;
|
|
195
213
|
};
|
|
196
214
|
customElements.define("u-tabs", UHTMLTabsElement);
|
|
197
215
|
customElements.define("u-tablist", UHTMLTabListElement);
|
package/dist/u-tabs.d.cts
CHANGED
|
@@ -5,10 +5,10 @@ declare const UHTMLElement: {
|
|
|
5
5
|
|
|
6
6
|
declare global {
|
|
7
7
|
interface HTMLElementTagNameMap {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
"u-tabs": UHTMLTabsElement;
|
|
9
|
+
"u-tablist": UHTMLTabListElement;
|
|
10
|
+
"u-tab": UHTMLTabElement;
|
|
11
|
+
"u-tabpanel": UHTMLTabPanelElement;
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
@@ -59,8 +59,10 @@ declare class UHTMLTabElement extends UHTMLElement {
|
|
|
59
59
|
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tabpanel_role)
|
|
60
60
|
*/
|
|
61
61
|
declare class UHTMLTabPanelElement extends UHTMLElement {
|
|
62
|
+
static observedAttributes: string[];
|
|
62
63
|
constructor();
|
|
63
64
|
connectedCallback(): void;
|
|
65
|
+
attributeChangedCallback(): void;
|
|
64
66
|
get tabsElement(): UHTMLTabsElement | null;
|
|
65
67
|
get tabs(): NodeListOf<UHTMLTabElement>;
|
|
66
68
|
}
|
package/dist/u-tabs.d.ts
CHANGED
|
@@ -5,10 +5,10 @@ declare const UHTMLElement: {
|
|
|
5
5
|
|
|
6
6
|
declare global {
|
|
7
7
|
interface HTMLElementTagNameMap {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
"u-tabs": UHTMLTabsElement;
|
|
9
|
+
"u-tablist": UHTMLTabListElement;
|
|
10
|
+
"u-tab": UHTMLTabElement;
|
|
11
|
+
"u-tabpanel": UHTMLTabPanelElement;
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
@@ -59,8 +59,10 @@ declare class UHTMLTabElement extends UHTMLElement {
|
|
|
59
59
|
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tabpanel_role)
|
|
60
60
|
*/
|
|
61
61
|
declare class UHTMLTabPanelElement extends UHTMLElement {
|
|
62
|
+
static observedAttributes: string[];
|
|
62
63
|
constructor();
|
|
63
64
|
connectedCallback(): void;
|
|
65
|
+
attributeChangedCallback(): void;
|
|
64
66
|
get tabsElement(): UHTMLTabsElement | null;
|
|
65
67
|
get tabs(): NodeListOf<UHTMLTabElement>;
|
|
66
68
|
}
|
package/dist/u-tabs.js
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
// ../utils.ts
|
|
2
2
|
var IS_BROWSER = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.navigator !== "undefined";
|
|
3
3
|
var IS_ANDROID = IS_BROWSER && /android/i.test(navigator.userAgent);
|
|
4
|
+
IS_BROWSER && // @ts-expect-error Typescript has not implemented userAgentData yet https://stackoverflow.com/a/71392474
|
|
5
|
+
/^Mac/i.test(navigator.userAgentData?.platform || navigator.platform);
|
|
4
6
|
var SAFE_LABELLEDBY = `${IS_ANDROID ? "data" : "aria"}-labelledby`;
|
|
5
7
|
var DISPLAY_BLOCK = ":host(:not([hidden])) { display: block }";
|
|
6
8
|
var UHTMLElement = typeof HTMLElement === "undefined" ? class {
|
|
7
9
|
} : HTMLElement;
|
|
8
|
-
var events = (action, element, rest) =>
|
|
9
|
-
rest[0]
|
|
10
|
-
|
|
11
|
-
});
|
|
10
|
+
var events = (action, element, rest) => {
|
|
11
|
+
for (const type of rest[0].split(",")) {
|
|
12
|
+
rest[0] = type;
|
|
13
|
+
Element.prototype[`${action}EventListener`].apply(element, rest);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
12
16
|
var on = (element, ...rest) => events("add", element, rest);
|
|
13
17
|
var off = (element, ...rest) => events("remove", element, rest);
|
|
14
|
-
var attachStyle = (element, css) => element.attachShadow({ mode: "
|
|
18
|
+
var attachStyle = (element, css) => element.attachShadow({ mode: "open" }).append(
|
|
15
19
|
createElement("slot"),
|
|
16
20
|
// Unnamed slot does automatically render all top element nodes
|
|
17
21
|
createElement("style", { textContent: css })
|
|
@@ -24,7 +28,11 @@ var asButton = (event) => {
|
|
|
24
28
|
};
|
|
25
29
|
var getRoot = (node) => node.getRootNode();
|
|
26
30
|
var id = 0;
|
|
27
|
-
var useId = (el) =>
|
|
31
|
+
var useId = (el) => {
|
|
32
|
+
if (!el) return "";
|
|
33
|
+
if (!el.id) el.id = `:${el.nodeName.toLowerCase()}${(++id).toString(32)}`;
|
|
34
|
+
return el.id;
|
|
35
|
+
};
|
|
28
36
|
var createElement = (tagName, props) => Object.assign(document.createElement(tagName), props);
|
|
29
37
|
var customElements = {
|
|
30
38
|
define: (name, instance) => !IS_BROWSER || window.customElements.get(name) || window.customElements.define(name, instance)
|
|
@@ -109,7 +117,7 @@ var UHTMLTabElement = class extends UHTMLElement {
|
|
|
109
117
|
super();
|
|
110
118
|
attachStyle(
|
|
111
119
|
this,
|
|
112
|
-
|
|
120
|
+
":host(:not([hidden])) { cursor: pointer; display: inline-block }"
|
|
113
121
|
);
|
|
114
122
|
}
|
|
115
123
|
connectedCallback() {
|
|
@@ -125,16 +133,16 @@ var UHTMLTabElement = class extends UHTMLElement {
|
|
|
125
133
|
const nextPanel = getPanel(this);
|
|
126
134
|
const nextPanelId = useId(nextPanel);
|
|
127
135
|
if (name === "aria-selected" && this.tabList)
|
|
128
|
-
queryWithoutNested("u-tab", this.tabList)
|
|
136
|
+
for (const tab of queryWithoutNested("u-tab", this.tabList)) {
|
|
129
137
|
if (tab !== this && isSelected(tab)) {
|
|
130
138
|
getPanel(tab)?.setAttribute("hidden", "");
|
|
131
139
|
tab.ariaSelected = "false";
|
|
132
140
|
tab.tabIndex = -1;
|
|
133
141
|
}
|
|
134
|
-
}
|
|
142
|
+
}
|
|
135
143
|
if (name === ARIA_CONTROLS && prev)
|
|
136
144
|
getPanel(this, prev)?.setAttribute("hidden", "");
|
|
137
|
-
if (this.getAttribute(ARIA_CONTROLS) !== nextPanelId)
|
|
145
|
+
if (nextPanel && this.getAttribute(ARIA_CONTROLS) !== nextPanelId)
|
|
138
146
|
this.setAttribute(ARIA_CONTROLS, nextPanelId);
|
|
139
147
|
this.tabIndex = 0;
|
|
140
148
|
nextPanel?.setAttribute(SAFE_LABELLEDBY, useId(this));
|
|
@@ -170,6 +178,12 @@ var UHTMLTabPanelElement = class extends UHTMLElement {
|
|
|
170
178
|
connectedCallback() {
|
|
171
179
|
this.hidden = getSelectedIndex(this.tabs) === -1;
|
|
172
180
|
this.role = "tabpanel";
|
|
181
|
+
this.attributeChangedCallback();
|
|
182
|
+
}
|
|
183
|
+
attributeChangedCallback() {
|
|
184
|
+
if (this.hidden || isFocusable(this.firstElementChild))
|
|
185
|
+
this.removeAttribute("tabindex");
|
|
186
|
+
else this.tabIndex = 0;
|
|
173
187
|
}
|
|
174
188
|
get tabsElement() {
|
|
175
189
|
return this.closest("u-tabs");
|
|
@@ -180,16 +194,20 @@ var UHTMLTabPanelElement = class extends UHTMLElement {
|
|
|
180
194
|
return root.length ? root : document.querySelectorAll(css);
|
|
181
195
|
}
|
|
182
196
|
};
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
197
|
+
UHTMLTabPanelElement.observedAttributes = ["hidden"];
|
|
198
|
+
var queryWithoutNested = (tag, self) => self.querySelectorAll(
|
|
199
|
+
`${tag}:not(:scope ${self.nodeName}:not(:scope) ${tag})`
|
|
200
|
+
);
|
|
187
201
|
var isSelected = (tab) => tab.ariaSelected === "true";
|
|
188
202
|
var getSelectedIndex = (tabs) => [...tabs].findIndex(isSelected);
|
|
189
|
-
var
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
203
|
+
var isFocusable = (el) => el instanceof Element && el.matches(
|
|
204
|
+
`:is([contenteditable],[controls],[href],[tabindex],input:not([type="hidden"]),select,textarea,button,summary,iframe):not(:disabled,[tabindex^="-"])`
|
|
205
|
+
);
|
|
206
|
+
var getPanel = (tab, id2) => {
|
|
207
|
+
const panelId = id2 || tab.getAttribute(ARIA_CONTROLS);
|
|
208
|
+
const panelSelector = `u-tabpanel[id="${panelId}"]`;
|
|
209
|
+
const tabsElement = tab.closest("u-tabs");
|
|
210
|
+
return panelId && getRoot(tab).querySelector(panelSelector) || panelId && getRoot(tab).querySelector(panelSelector) || tabsElement && queryWithoutNested("u-tabpanel", tabsElement)[[...queryWithoutNested("u-tab", tabsElement)].indexOf(tab)] || null;
|
|
193
211
|
};
|
|
194
212
|
customElements.define("u-tabs", UHTMLTabsElement);
|
|
195
213
|
customElements.define("u-tablist", UHTMLTabListElement);
|
|
@@ -181,6 +181,11 @@
|
|
|
181
181
|
"readonly": true
|
|
182
182
|
}
|
|
183
183
|
],
|
|
184
|
+
"attributes": [
|
|
185
|
+
{
|
|
186
|
+
"name": "hidden"
|
|
187
|
+
}
|
|
188
|
+
],
|
|
184
189
|
"superclass": {
|
|
185
190
|
"name": "UHTMLElement",
|
|
186
191
|
"module": "//Users/eirikbacker/Library/Mobile%20Documents/com~apple~CloudDocs/5-capra/u-elements/packages/utils"
|
package/dist/u-tabs.vscode.json
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
{
|
|
27
27
|
"name": "u-tabpanel",
|
|
28
28
|
"description": "The `<u-tabpanel>` HTML element is a container for the resources of layered content associated with a `<u-tab>`.\n[MDN Reference](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tabpanel_role)\n---\n",
|
|
29
|
-
"attributes": [],
|
|
29
|
+
"attributes": [{ "name": "hidden", "values": [] }],
|
|
30
30
|
"references": []
|
|
31
31
|
}
|
|
32
32
|
]
|
package/package.json
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
2
|
+
"name": "@u-elements/u-tabs",
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "HTML tags, just truly accessible",
|
|
6
|
+
"homepage": "https://u-elements.github.io/u-elements/",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/u-tabs.cjs",
|
|
9
|
+
"module": "dist/u-tabs.js",
|
|
10
|
+
"types": "dist/u-tabs.d.ts",
|
|
11
|
+
"customElements": "dist/u-tabs.manifest.json",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/u-elements/u-elements.git"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/u-elements/u-elements/issues"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup --config ../../tsup.config.ts"
|
|
24
|
+
}
|
|
25
25
|
}
|