@u-elements/u-tabs 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/u-tabs.cjs +46 -68
- package/dist/u-tabs.d.cts +7 -10
- package/dist/u-tabs.d.ts +7 -10
- package/dist/u-tabs.js +46 -68
- package/dist/u-tabs.manifest.json +16 -13
- package/dist/u-tabs.vscode.json +4 -1
- package/package.json +1 -1
package/dist/u-tabs.cjs
CHANGED
|
@@ -2,53 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
// ../utils.ts
|
|
4
4
|
var IS_BROWSER = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.navigator !== "undefined";
|
|
5
|
-
var IS_ANDROID = IS_BROWSER && /android/i.test(
|
|
6
|
-
var
|
|
7
|
-
var ARIA_LABELLEDBY = IS_ANDROID ? "data-labelledby" : "aria-labelledby";
|
|
8
|
-
var ARIA_SELECTED = "aria-selected";
|
|
5
|
+
var IS_ANDROID = IS_BROWSER && /android/i.test(navigator.userAgent);
|
|
6
|
+
var SAFE_LABELLEDBY = `${IS_ANDROID ? "data" : "aria"}-labelledby`;
|
|
9
7
|
var DISPLAY_BLOCK = ":host(:not([hidden])) { display: block }";
|
|
10
8
|
var UHTMLElement = typeof HTMLElement === "undefined" ? class {
|
|
11
9
|
} : HTMLElement;
|
|
12
|
-
var
|
|
10
|
+
var events = (action, element, rest) => rest[0].split(",").forEach((type) => {
|
|
13
11
|
rest[0] = type;
|
|
14
12
|
Element.prototype[`${action}EventListener`].apply(element, rest);
|
|
15
13
|
});
|
|
16
|
-
var on = (element, ...rest) =>
|
|
17
|
-
var off = (element, ...rest) =>
|
|
14
|
+
var on = (element, ...rest) => events("add", element, rest);
|
|
15
|
+
var off = (element, ...rest) => events("remove", element, rest);
|
|
18
16
|
var attachStyle = (element, css) => element.attachShadow({ mode: "closed" }).append(
|
|
19
17
|
createElement("slot"),
|
|
20
18
|
// Unnamed slot does automatically render all top element nodes
|
|
21
19
|
createElement("style", { textContent: css })
|
|
22
20
|
);
|
|
23
|
-
function attr(element, name, value) {
|
|
24
|
-
if (element instanceof Element) {
|
|
25
|
-
if (typeof name === "object")
|
|
26
|
-
Object.entries(name).map(([name2, value2]) => attr(element, name2, value2));
|
|
27
|
-
else if (value === void 0)
|
|
28
|
-
return element.getAttribute(name);
|
|
29
|
-
else if (value === null)
|
|
30
|
-
element.removeAttribute(name);
|
|
31
|
-
else if (element.getAttribute(name) !== `${value}`)
|
|
32
|
-
element.setAttribute(name, `${value}`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
21
|
var asButton = (event) => {
|
|
36
22
|
const isClick = "key" in event && (event.key === " " || event.key === "Enter");
|
|
37
|
-
if (isClick)
|
|
38
|
-
|
|
39
|
-
if (isClick && event.target instanceof HTMLElement)
|
|
40
|
-
event.target.click();
|
|
23
|
+
if (isClick) event.preventDefault();
|
|
24
|
+
if (isClick && event.target instanceof HTMLElement) event.target.click();
|
|
41
25
|
return isClick;
|
|
42
26
|
};
|
|
43
27
|
var getRoot = (node) => node.getRootNode();
|
|
44
28
|
var id = 0;
|
|
45
|
-
var useId = (el) => el ? el.id || (el.id = `:${el.nodeName.toLowerCase()}${(++id).toString(32)}`) :
|
|
29
|
+
var useId = (el) => el ? el.id || (el.id = `:${el.nodeName.toLowerCase()}${(++id).toString(32)}`) : "";
|
|
46
30
|
var createElement = (tagName, props) => Object.assign(document.createElement(tagName), props);
|
|
47
31
|
var customElements = {
|
|
48
32
|
define: (name, instance) => !IS_BROWSER || window.customElements.get(name) || window.customElements.define(name, instance)
|
|
49
33
|
};
|
|
50
34
|
|
|
51
35
|
// u-tabs.ts
|
|
36
|
+
var ARIA_CONTROLS = "aria-controls";
|
|
52
37
|
var UHTMLTabsElement = class extends UHTMLElement {
|
|
53
38
|
constructor() {
|
|
54
39
|
super();
|
|
@@ -58,10 +43,10 @@ var UHTMLTabsElement = class extends UHTMLElement {
|
|
|
58
43
|
return queryWithoutNested("u-tablist", this)[0] || null;
|
|
59
44
|
}
|
|
60
45
|
get selectedIndex() {
|
|
61
|
-
return [...this.tabs].findIndex((tab) =>
|
|
46
|
+
return [...this.tabs].findIndex((tab) => tab.ariaSelected === "true");
|
|
62
47
|
}
|
|
63
48
|
set selectedIndex(index) {
|
|
64
|
-
|
|
49
|
+
if (this.tabs[index]) this.tabs[index].ariaSelected = "true";
|
|
65
50
|
}
|
|
66
51
|
get tabs() {
|
|
67
52
|
return queryWithoutNested("u-tab", this);
|
|
@@ -76,7 +61,7 @@ var UHTMLTabListElement = class extends UHTMLElement {
|
|
|
76
61
|
attachStyle(this, DISPLAY_BLOCK);
|
|
77
62
|
}
|
|
78
63
|
connectedCallback() {
|
|
79
|
-
|
|
64
|
+
this.role = "tablist";
|
|
80
65
|
on(this, "click,keydown", this);
|
|
81
66
|
}
|
|
82
67
|
disconnectedCallback() {
|
|
@@ -86,21 +71,16 @@ var UHTMLTabListElement = class extends UHTMLElement {
|
|
|
86
71
|
const { key } = event;
|
|
87
72
|
const tabs = [...this.getElementsByTagName("u-tab")];
|
|
88
73
|
let index = tabs.findIndex((tab) => tab.contains(event.target));
|
|
89
|
-
if (event.defaultPrevented || index === -1)
|
|
90
|
-
|
|
91
|
-
if (event.type === "click")
|
|
92
|
-
tabs[index].selected = true;
|
|
74
|
+
if (event.defaultPrevented || index === -1) return;
|
|
75
|
+
if (event.type === "click") tabs[index].selected = true;
|
|
93
76
|
if (event.type === "keydown" && !asButton(event)) {
|
|
94
77
|
if (key === "ArrowDown" || key === "ArrowRight")
|
|
95
78
|
index = ++index % tabs.length;
|
|
96
79
|
else if (key === "ArrowUp" || key === "ArrowLeft")
|
|
97
80
|
index = (index || tabs.length) - 1;
|
|
98
|
-
else if (key === "End")
|
|
99
|
-
|
|
100
|
-
else
|
|
101
|
-
index = 0;
|
|
102
|
-
else
|
|
103
|
-
return;
|
|
81
|
+
else if (key === "End") index = tabs.length - 1;
|
|
82
|
+
else if (key === "Home") index = 0;
|
|
83
|
+
else return;
|
|
104
84
|
event.preventDefault();
|
|
105
85
|
tabs[index].focus();
|
|
106
86
|
}
|
|
@@ -109,41 +89,41 @@ var UHTMLTabListElement = class extends UHTMLElement {
|
|
|
109
89
|
return this.closest("u-tabs");
|
|
110
90
|
}
|
|
111
91
|
};
|
|
112
|
-
var
|
|
92
|
+
var SKIP_ATTR_CHANGE = false;
|
|
113
93
|
var UHTMLTabElement = class extends UHTMLElement {
|
|
114
|
-
static get observedAttributes() {
|
|
115
|
-
return ["id", ARIA_SELECTED, ARIA_CONTROLS];
|
|
116
|
-
}
|
|
117
94
|
constructor() {
|
|
118
95
|
super();
|
|
119
|
-
attachStyle(
|
|
96
|
+
attachStyle(
|
|
97
|
+
this,
|
|
98
|
+
`:host(:not([hidden])) { cursor: pointer; display: inline-block }`
|
|
99
|
+
);
|
|
120
100
|
}
|
|
121
101
|
connectedCallback() {
|
|
122
102
|
this.selected = !!this.selected;
|
|
123
103
|
}
|
|
124
104
|
attributeChangedCallback(_name, prev, next) {
|
|
125
|
-
if (!
|
|
105
|
+
if (!SKIP_ATTR_CHANGE && prev !== next && (SKIP_ATTR_CHANGE = true)) {
|
|
126
106
|
const { tabs = [], panels = [], selectedIndex } = this.tabsElement || {};
|
|
127
107
|
const selected = this.selected ? this : tabs[selectedIndex || 0] || this;
|
|
128
108
|
let selectedPanel;
|
|
129
|
-
panels.forEach((panel) =>
|
|
109
|
+
panels.forEach((panel) => {
|
|
110
|
+
panel.removeAttribute(SAFE_LABELLEDBY);
|
|
111
|
+
panel.hidden = true;
|
|
112
|
+
});
|
|
130
113
|
tabs.forEach((tab, index) => {
|
|
131
|
-
const tabindex = selected === tab ? 0 : -1;
|
|
132
114
|
const panel = getPanel(tab) || panels[index] || null;
|
|
133
|
-
if (
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
hidden: selectedPanel === panel ? null : ""
|
|
144
|
-
});
|
|
115
|
+
if (selected === tab && panel) selectedPanel = panel;
|
|
116
|
+
tab.role = "tab";
|
|
117
|
+
tab.tabIndex = selected === tab ? 0 : -1;
|
|
118
|
+
tab.ariaSelected = `${selected === tab}`;
|
|
119
|
+
tab.setAttribute(ARIA_CONTROLS, useId(panel));
|
|
120
|
+
panel?.toggleAttribute("hidden", selectedPanel !== panel);
|
|
121
|
+
panel?.setAttribute(
|
|
122
|
+
SAFE_LABELLEDBY,
|
|
123
|
+
useId(selectedPanel === panel ? selected : tab)
|
|
124
|
+
);
|
|
145
125
|
});
|
|
146
|
-
|
|
126
|
+
SKIP_ATTR_CHANGE = false;
|
|
147
127
|
}
|
|
148
128
|
}
|
|
149
129
|
get tabsElement() {
|
|
@@ -153,10 +133,10 @@ var UHTMLTabElement = class extends UHTMLElement {
|
|
|
153
133
|
return this.closest("u-tablist");
|
|
154
134
|
}
|
|
155
135
|
get selected() {
|
|
156
|
-
return
|
|
136
|
+
return this.ariaSelected === "true";
|
|
157
137
|
}
|
|
158
138
|
set selected(value) {
|
|
159
|
-
|
|
139
|
+
this.ariaSelected = `${value}`;
|
|
160
140
|
}
|
|
161
141
|
/** Retrieves the ordinal position of an tab in a tablist. */
|
|
162
142
|
get index() {
|
|
@@ -166,22 +146,19 @@ var UHTMLTabElement = class extends UHTMLElement {
|
|
|
166
146
|
return getPanel(this);
|
|
167
147
|
}
|
|
168
148
|
};
|
|
149
|
+
UHTMLTabElement.observedAttributes = ["id", "aria-selected", ARIA_CONTROLS];
|
|
169
150
|
var UHTMLTabPanelElement = class extends UHTMLElement {
|
|
170
|
-
static get observedAttributes() {
|
|
171
|
-
return ["id"];
|
|
172
|
-
}
|
|
173
151
|
constructor() {
|
|
174
152
|
super();
|
|
175
153
|
attachStyle(this, DISPLAY_BLOCK);
|
|
176
154
|
}
|
|
177
155
|
connectedCallback() {
|
|
178
|
-
|
|
156
|
+
this.role = "tabpanel";
|
|
179
157
|
this.hidden = Array.from(this.tabs).every((tab) => !tab.selected);
|
|
180
158
|
}
|
|
181
159
|
attributeChangedCallback(_name, prev, next) {
|
|
182
|
-
if (
|
|
183
|
-
|
|
184
|
-
}
|
|
160
|
+
if (SKIP_ATTR_CHANGE || prev === next) return;
|
|
161
|
+
getTabs(this, prev).forEach((tab) => tab.setAttribute(ARIA_CONTROLS, next));
|
|
185
162
|
}
|
|
186
163
|
get tabsElement() {
|
|
187
164
|
return this.closest("u-tabs");
|
|
@@ -190,12 +167,13 @@ var UHTMLTabPanelElement = class extends UHTMLElement {
|
|
|
190
167
|
return getTabs(this, this.id);
|
|
191
168
|
}
|
|
192
169
|
};
|
|
170
|
+
UHTMLTabPanelElement.observedAttributes = ["id"];
|
|
193
171
|
var queryWithoutNested = (tag, self) => {
|
|
194
172
|
const selector = `${tag}:not(:scope ${self.nodeName}:not(:scope) ${tag})`;
|
|
195
173
|
return self.querySelectorAll(selector);
|
|
196
174
|
};
|
|
197
175
|
var getPanel = (self) => {
|
|
198
|
-
const css = `u-tabpanel[id="${
|
|
176
|
+
const css = `u-tabpanel[id="${self.getAttribute(ARIA_CONTROLS)}"]`;
|
|
199
177
|
return getRoot(self).querySelector(css) || document.querySelector(css);
|
|
200
178
|
};
|
|
201
179
|
var getTabs = (self, id2) => {
|
package/dist/u-tabs.d.cts
CHANGED
|
@@ -39,7 +39,7 @@ declare class UHTMLTabListElement extends UHTMLElement {
|
|
|
39
39
|
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tab_role)
|
|
40
40
|
*/
|
|
41
41
|
declare class UHTMLTabElement extends UHTMLElement {
|
|
42
|
-
static
|
|
42
|
+
static observedAttributes: string[];
|
|
43
43
|
constructor();
|
|
44
44
|
connectedCallback(): void;
|
|
45
45
|
attributeChangedCallback(_name: string, prev: string, next: string): void;
|
|
@@ -56,7 +56,7 @@ declare class UHTMLTabElement extends UHTMLElement {
|
|
|
56
56
|
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tabpanel_role)
|
|
57
57
|
*/
|
|
58
58
|
declare class UHTMLTabPanelElement extends UHTMLElement {
|
|
59
|
-
static
|
|
59
|
+
static observedAttributes: string[];
|
|
60
60
|
constructor();
|
|
61
61
|
connectedCallback(): void;
|
|
62
62
|
attributeChangedCallback(_name: string, prev: string, next: string): void;
|
|
@@ -65,15 +65,15 @@ declare class UHTMLTabPanelElement extends UHTMLElement {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
export { UHTMLTabElement, UHTMLTabListElement, UHTMLTabPanelElement, UHTMLTabsElement };
|
|
68
|
-
|
|
69
68
|
import type * as VueJSX from '@vue/runtime-dom'
|
|
70
69
|
import type { JSX as QwikJSX } from '@builder.io/qwik/jsx-runtime'
|
|
71
70
|
import type { JSX as ReactJSX } from 'react'
|
|
72
71
|
import type { JSX as SolidJSX } from 'solid-js'
|
|
73
72
|
import type { SvelteHTMLElements } from 'svelte/elements'
|
|
73
|
+
|
|
74
74
|
export type VueTabs = VueJSX.IntrinsicElementAttributes['div']
|
|
75
75
|
export type QwikTabs = QwikJSX.IntrinsicElements['div']
|
|
76
|
-
export type ReactTabs = ReactJSX.IntrinsicElements['div']
|
|
76
|
+
export type ReactTabs = ReactJSX.IntrinsicElements['div'] & { class?: string }
|
|
77
77
|
export type SolidJSTabs = SolidJSX.HTMLElementTags['div']
|
|
78
78
|
export type SvelteTabs = SvelteHTMLElements['div']
|
|
79
79
|
|
|
@@ -83,10 +83,9 @@ declare module '@builder.io/qwik/jsx-runtime' { export namespace JSX { export in
|
|
|
83
83
|
declare global { namespace React.JSX { interface IntrinsicElements { 'u-tabs': ReactTabs } } }
|
|
84
84
|
declare module 'solid-js' { namespace JSX { interface IntrinsicElements { 'u-tabs': SolidJSTabs } } }
|
|
85
85
|
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tabs': SvelteTabs } }
|
|
86
|
-
|
|
87
86
|
export type VueTablist = VueJSX.IntrinsicElementAttributes['div']
|
|
88
87
|
export type QwikTablist = QwikJSX.IntrinsicElements['div']
|
|
89
|
-
export type ReactTablist = ReactJSX.IntrinsicElements['div']
|
|
88
|
+
export type ReactTablist = ReactJSX.IntrinsicElements['div'] & { class?: string }
|
|
90
89
|
export type SolidJSTablist = SolidJSX.HTMLElementTags['div']
|
|
91
90
|
export type SvelteTablist = SvelteHTMLElements['div']
|
|
92
91
|
|
|
@@ -96,10 +95,9 @@ declare module '@builder.io/qwik/jsx-runtime' { export namespace JSX { export in
|
|
|
96
95
|
declare global { namespace React.JSX { interface IntrinsicElements { 'u-tablist': ReactTablist } } }
|
|
97
96
|
declare module 'solid-js' { namespace JSX { interface IntrinsicElements { 'u-tablist': SolidJSTablist } } }
|
|
98
97
|
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tablist': SvelteTablist } }
|
|
99
|
-
|
|
100
98
|
export type VueTab = VueJSX.IntrinsicElementAttributes['div']
|
|
101
99
|
export type QwikTab = QwikJSX.IntrinsicElements['div']
|
|
102
|
-
export type ReactTab = ReactJSX.IntrinsicElements['div']
|
|
100
|
+
export type ReactTab = ReactJSX.IntrinsicElements['div'] & { class?: string }
|
|
103
101
|
export type SolidJSTab = SolidJSX.HTMLElementTags['div']
|
|
104
102
|
export type SvelteTab = SvelteHTMLElements['div']
|
|
105
103
|
|
|
@@ -109,10 +107,9 @@ declare module '@builder.io/qwik/jsx-runtime' { export namespace JSX { export in
|
|
|
109
107
|
declare global { namespace React.JSX { interface IntrinsicElements { 'u-tab': ReactTab } } }
|
|
110
108
|
declare module 'solid-js' { namespace JSX { interface IntrinsicElements { 'u-tab': SolidJSTab } } }
|
|
111
109
|
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tab': SvelteTab } }
|
|
112
|
-
|
|
113
110
|
export type VueTabpanel = VueJSX.IntrinsicElementAttributes['div']
|
|
114
111
|
export type QwikTabpanel = QwikJSX.IntrinsicElements['div']
|
|
115
|
-
export type ReactTabpanel = ReactJSX.IntrinsicElements['div']
|
|
112
|
+
export type ReactTabpanel = ReactJSX.IntrinsicElements['div'] & { class?: string }
|
|
116
113
|
export type SolidJSTabpanel = SolidJSX.HTMLElementTags['div']
|
|
117
114
|
export type SvelteTabpanel = SvelteHTMLElements['div']
|
|
118
115
|
|
package/dist/u-tabs.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ declare class UHTMLTabListElement extends UHTMLElement {
|
|
|
39
39
|
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tab_role)
|
|
40
40
|
*/
|
|
41
41
|
declare class UHTMLTabElement extends UHTMLElement {
|
|
42
|
-
static
|
|
42
|
+
static observedAttributes: string[];
|
|
43
43
|
constructor();
|
|
44
44
|
connectedCallback(): void;
|
|
45
45
|
attributeChangedCallback(_name: string, prev: string, next: string): void;
|
|
@@ -56,7 +56,7 @@ declare class UHTMLTabElement extends UHTMLElement {
|
|
|
56
56
|
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tabpanel_role)
|
|
57
57
|
*/
|
|
58
58
|
declare class UHTMLTabPanelElement extends UHTMLElement {
|
|
59
|
-
static
|
|
59
|
+
static observedAttributes: string[];
|
|
60
60
|
constructor();
|
|
61
61
|
connectedCallback(): void;
|
|
62
62
|
attributeChangedCallback(_name: string, prev: string, next: string): void;
|
|
@@ -65,15 +65,15 @@ declare class UHTMLTabPanelElement extends UHTMLElement {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
export { UHTMLTabElement, UHTMLTabListElement, UHTMLTabPanelElement, UHTMLTabsElement };
|
|
68
|
-
|
|
69
68
|
import type * as VueJSX from '@vue/runtime-dom'
|
|
70
69
|
import type { JSX as QwikJSX } from '@builder.io/qwik/jsx-runtime'
|
|
71
70
|
import type { JSX as ReactJSX } from 'react'
|
|
72
71
|
import type { JSX as SolidJSX } from 'solid-js'
|
|
73
72
|
import type { SvelteHTMLElements } from 'svelte/elements'
|
|
73
|
+
|
|
74
74
|
export type VueTabs = VueJSX.IntrinsicElementAttributes['div']
|
|
75
75
|
export type QwikTabs = QwikJSX.IntrinsicElements['div']
|
|
76
|
-
export type ReactTabs = ReactJSX.IntrinsicElements['div']
|
|
76
|
+
export type ReactTabs = ReactJSX.IntrinsicElements['div'] & { class?: string }
|
|
77
77
|
export type SolidJSTabs = SolidJSX.HTMLElementTags['div']
|
|
78
78
|
export type SvelteTabs = SvelteHTMLElements['div']
|
|
79
79
|
|
|
@@ -83,10 +83,9 @@ declare module '@builder.io/qwik/jsx-runtime' { export namespace JSX { export in
|
|
|
83
83
|
declare global { namespace React.JSX { interface IntrinsicElements { 'u-tabs': ReactTabs } } }
|
|
84
84
|
declare module 'solid-js' { namespace JSX { interface IntrinsicElements { 'u-tabs': SolidJSTabs } } }
|
|
85
85
|
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tabs': SvelteTabs } }
|
|
86
|
-
|
|
87
86
|
export type VueTablist = VueJSX.IntrinsicElementAttributes['div']
|
|
88
87
|
export type QwikTablist = QwikJSX.IntrinsicElements['div']
|
|
89
|
-
export type ReactTablist = ReactJSX.IntrinsicElements['div']
|
|
88
|
+
export type ReactTablist = ReactJSX.IntrinsicElements['div'] & { class?: string }
|
|
90
89
|
export type SolidJSTablist = SolidJSX.HTMLElementTags['div']
|
|
91
90
|
export type SvelteTablist = SvelteHTMLElements['div']
|
|
92
91
|
|
|
@@ -96,10 +95,9 @@ declare module '@builder.io/qwik/jsx-runtime' { export namespace JSX { export in
|
|
|
96
95
|
declare global { namespace React.JSX { interface IntrinsicElements { 'u-tablist': ReactTablist } } }
|
|
97
96
|
declare module 'solid-js' { namespace JSX { interface IntrinsicElements { 'u-tablist': SolidJSTablist } } }
|
|
98
97
|
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tablist': SvelteTablist } }
|
|
99
|
-
|
|
100
98
|
export type VueTab = VueJSX.IntrinsicElementAttributes['div']
|
|
101
99
|
export type QwikTab = QwikJSX.IntrinsicElements['div']
|
|
102
|
-
export type ReactTab = ReactJSX.IntrinsicElements['div']
|
|
100
|
+
export type ReactTab = ReactJSX.IntrinsicElements['div'] & { class?: string }
|
|
103
101
|
export type SolidJSTab = SolidJSX.HTMLElementTags['div']
|
|
104
102
|
export type SvelteTab = SvelteHTMLElements['div']
|
|
105
103
|
|
|
@@ -109,10 +107,9 @@ declare module '@builder.io/qwik/jsx-runtime' { export namespace JSX { export in
|
|
|
109
107
|
declare global { namespace React.JSX { interface IntrinsicElements { 'u-tab': ReactTab } } }
|
|
110
108
|
declare module 'solid-js' { namespace JSX { interface IntrinsicElements { 'u-tab': SolidJSTab } } }
|
|
111
109
|
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tab': SvelteTab } }
|
|
112
|
-
|
|
113
110
|
export type VueTabpanel = VueJSX.IntrinsicElementAttributes['div']
|
|
114
111
|
export type QwikTabpanel = QwikJSX.IntrinsicElements['div']
|
|
115
|
-
export type ReactTabpanel = ReactJSX.IntrinsicElements['div']
|
|
112
|
+
export type ReactTabpanel = ReactJSX.IntrinsicElements['div'] & { class?: string }
|
|
116
113
|
export type SolidJSTabpanel = SolidJSX.HTMLElementTags['div']
|
|
117
114
|
export type SvelteTabpanel = SvelteHTMLElements['div']
|
|
118
115
|
|
package/dist/u-tabs.js
CHANGED
|
@@ -1,52 +1,37 @@
|
|
|
1
1
|
// ../utils.ts
|
|
2
2
|
var IS_BROWSER = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.navigator !== "undefined";
|
|
3
|
-
var IS_ANDROID = IS_BROWSER && /android/i.test(
|
|
4
|
-
var
|
|
5
|
-
var ARIA_LABELLEDBY = IS_ANDROID ? "data-labelledby" : "aria-labelledby";
|
|
6
|
-
var ARIA_SELECTED = "aria-selected";
|
|
3
|
+
var IS_ANDROID = IS_BROWSER && /android/i.test(navigator.userAgent);
|
|
4
|
+
var SAFE_LABELLEDBY = `${IS_ANDROID ? "data" : "aria"}-labelledby`;
|
|
7
5
|
var DISPLAY_BLOCK = ":host(:not([hidden])) { display: block }";
|
|
8
6
|
var UHTMLElement = typeof HTMLElement === "undefined" ? class {
|
|
9
7
|
} : HTMLElement;
|
|
10
|
-
var
|
|
8
|
+
var events = (action, element, rest) => rest[0].split(",").forEach((type) => {
|
|
11
9
|
rest[0] = type;
|
|
12
10
|
Element.prototype[`${action}EventListener`].apply(element, rest);
|
|
13
11
|
});
|
|
14
|
-
var on = (element, ...rest) =>
|
|
15
|
-
var off = (element, ...rest) =>
|
|
12
|
+
var on = (element, ...rest) => events("add", element, rest);
|
|
13
|
+
var off = (element, ...rest) => events("remove", element, rest);
|
|
16
14
|
var attachStyle = (element, css) => element.attachShadow({ mode: "closed" }).append(
|
|
17
15
|
createElement("slot"),
|
|
18
16
|
// Unnamed slot does automatically render all top element nodes
|
|
19
17
|
createElement("style", { textContent: css })
|
|
20
18
|
);
|
|
21
|
-
function attr(element, name, value) {
|
|
22
|
-
if (element instanceof Element) {
|
|
23
|
-
if (typeof name === "object")
|
|
24
|
-
Object.entries(name).map(([name2, value2]) => attr(element, name2, value2));
|
|
25
|
-
else if (value === void 0)
|
|
26
|
-
return element.getAttribute(name);
|
|
27
|
-
else if (value === null)
|
|
28
|
-
element.removeAttribute(name);
|
|
29
|
-
else if (element.getAttribute(name) !== `${value}`)
|
|
30
|
-
element.setAttribute(name, `${value}`);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
19
|
var asButton = (event) => {
|
|
34
20
|
const isClick = "key" in event && (event.key === " " || event.key === "Enter");
|
|
35
|
-
if (isClick)
|
|
36
|
-
|
|
37
|
-
if (isClick && event.target instanceof HTMLElement)
|
|
38
|
-
event.target.click();
|
|
21
|
+
if (isClick) event.preventDefault();
|
|
22
|
+
if (isClick && event.target instanceof HTMLElement) event.target.click();
|
|
39
23
|
return isClick;
|
|
40
24
|
};
|
|
41
25
|
var getRoot = (node) => node.getRootNode();
|
|
42
26
|
var id = 0;
|
|
43
|
-
var useId = (el) => el ? el.id || (el.id = `:${el.nodeName.toLowerCase()}${(++id).toString(32)}`) :
|
|
27
|
+
var useId = (el) => el ? el.id || (el.id = `:${el.nodeName.toLowerCase()}${(++id).toString(32)}`) : "";
|
|
44
28
|
var createElement = (tagName, props) => Object.assign(document.createElement(tagName), props);
|
|
45
29
|
var customElements = {
|
|
46
30
|
define: (name, instance) => !IS_BROWSER || window.customElements.get(name) || window.customElements.define(name, instance)
|
|
47
31
|
};
|
|
48
32
|
|
|
49
33
|
// u-tabs.ts
|
|
34
|
+
var ARIA_CONTROLS = "aria-controls";
|
|
50
35
|
var UHTMLTabsElement = class extends UHTMLElement {
|
|
51
36
|
constructor() {
|
|
52
37
|
super();
|
|
@@ -56,10 +41,10 @@ var UHTMLTabsElement = class extends UHTMLElement {
|
|
|
56
41
|
return queryWithoutNested("u-tablist", this)[0] || null;
|
|
57
42
|
}
|
|
58
43
|
get selectedIndex() {
|
|
59
|
-
return [...this.tabs].findIndex((tab) =>
|
|
44
|
+
return [...this.tabs].findIndex((tab) => tab.ariaSelected === "true");
|
|
60
45
|
}
|
|
61
46
|
set selectedIndex(index) {
|
|
62
|
-
|
|
47
|
+
if (this.tabs[index]) this.tabs[index].ariaSelected = "true";
|
|
63
48
|
}
|
|
64
49
|
get tabs() {
|
|
65
50
|
return queryWithoutNested("u-tab", this);
|
|
@@ -74,7 +59,7 @@ var UHTMLTabListElement = class extends UHTMLElement {
|
|
|
74
59
|
attachStyle(this, DISPLAY_BLOCK);
|
|
75
60
|
}
|
|
76
61
|
connectedCallback() {
|
|
77
|
-
|
|
62
|
+
this.role = "tablist";
|
|
78
63
|
on(this, "click,keydown", this);
|
|
79
64
|
}
|
|
80
65
|
disconnectedCallback() {
|
|
@@ -84,21 +69,16 @@ var UHTMLTabListElement = class extends UHTMLElement {
|
|
|
84
69
|
const { key } = event;
|
|
85
70
|
const tabs = [...this.getElementsByTagName("u-tab")];
|
|
86
71
|
let index = tabs.findIndex((tab) => tab.contains(event.target));
|
|
87
|
-
if (event.defaultPrevented || index === -1)
|
|
88
|
-
|
|
89
|
-
if (event.type === "click")
|
|
90
|
-
tabs[index].selected = true;
|
|
72
|
+
if (event.defaultPrevented || index === -1) return;
|
|
73
|
+
if (event.type === "click") tabs[index].selected = true;
|
|
91
74
|
if (event.type === "keydown" && !asButton(event)) {
|
|
92
75
|
if (key === "ArrowDown" || key === "ArrowRight")
|
|
93
76
|
index = ++index % tabs.length;
|
|
94
77
|
else if (key === "ArrowUp" || key === "ArrowLeft")
|
|
95
78
|
index = (index || tabs.length) - 1;
|
|
96
|
-
else if (key === "End")
|
|
97
|
-
|
|
98
|
-
else
|
|
99
|
-
index = 0;
|
|
100
|
-
else
|
|
101
|
-
return;
|
|
79
|
+
else if (key === "End") index = tabs.length - 1;
|
|
80
|
+
else if (key === "Home") index = 0;
|
|
81
|
+
else return;
|
|
102
82
|
event.preventDefault();
|
|
103
83
|
tabs[index].focus();
|
|
104
84
|
}
|
|
@@ -107,41 +87,41 @@ var UHTMLTabListElement = class extends UHTMLElement {
|
|
|
107
87
|
return this.closest("u-tabs");
|
|
108
88
|
}
|
|
109
89
|
};
|
|
110
|
-
var
|
|
90
|
+
var SKIP_ATTR_CHANGE = false;
|
|
111
91
|
var UHTMLTabElement = class extends UHTMLElement {
|
|
112
|
-
static get observedAttributes() {
|
|
113
|
-
return ["id", ARIA_SELECTED, ARIA_CONTROLS];
|
|
114
|
-
}
|
|
115
92
|
constructor() {
|
|
116
93
|
super();
|
|
117
|
-
attachStyle(
|
|
94
|
+
attachStyle(
|
|
95
|
+
this,
|
|
96
|
+
`:host(:not([hidden])) { cursor: pointer; display: inline-block }`
|
|
97
|
+
);
|
|
118
98
|
}
|
|
119
99
|
connectedCallback() {
|
|
120
100
|
this.selected = !!this.selected;
|
|
121
101
|
}
|
|
122
102
|
attributeChangedCallback(_name, prev, next) {
|
|
123
|
-
if (!
|
|
103
|
+
if (!SKIP_ATTR_CHANGE && prev !== next && (SKIP_ATTR_CHANGE = true)) {
|
|
124
104
|
const { tabs = [], panels = [], selectedIndex } = this.tabsElement || {};
|
|
125
105
|
const selected = this.selected ? this : tabs[selectedIndex || 0] || this;
|
|
126
106
|
let selectedPanel;
|
|
127
|
-
panels.forEach((panel) =>
|
|
107
|
+
panels.forEach((panel) => {
|
|
108
|
+
panel.removeAttribute(SAFE_LABELLEDBY);
|
|
109
|
+
panel.hidden = true;
|
|
110
|
+
});
|
|
128
111
|
tabs.forEach((tab, index) => {
|
|
129
|
-
const tabindex = selected === tab ? 0 : -1;
|
|
130
112
|
const panel = getPanel(tab) || panels[index] || null;
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
hidden: selectedPanel === panel ? null : ""
|
|
142
|
-
});
|
|
113
|
+
if (selected === tab && panel) selectedPanel = panel;
|
|
114
|
+
tab.role = "tab";
|
|
115
|
+
tab.tabIndex = selected === tab ? 0 : -1;
|
|
116
|
+
tab.ariaSelected = `${selected === tab}`;
|
|
117
|
+
tab.setAttribute(ARIA_CONTROLS, useId(panel));
|
|
118
|
+
panel?.toggleAttribute("hidden", selectedPanel !== panel);
|
|
119
|
+
panel?.setAttribute(
|
|
120
|
+
SAFE_LABELLEDBY,
|
|
121
|
+
useId(selectedPanel === panel ? selected : tab)
|
|
122
|
+
);
|
|
143
123
|
});
|
|
144
|
-
|
|
124
|
+
SKIP_ATTR_CHANGE = false;
|
|
145
125
|
}
|
|
146
126
|
}
|
|
147
127
|
get tabsElement() {
|
|
@@ -151,10 +131,10 @@ var UHTMLTabElement = class extends UHTMLElement {
|
|
|
151
131
|
return this.closest("u-tablist");
|
|
152
132
|
}
|
|
153
133
|
get selected() {
|
|
154
|
-
return
|
|
134
|
+
return this.ariaSelected === "true";
|
|
155
135
|
}
|
|
156
136
|
set selected(value) {
|
|
157
|
-
|
|
137
|
+
this.ariaSelected = `${value}`;
|
|
158
138
|
}
|
|
159
139
|
/** Retrieves the ordinal position of an tab in a tablist. */
|
|
160
140
|
get index() {
|
|
@@ -164,22 +144,19 @@ var UHTMLTabElement = class extends UHTMLElement {
|
|
|
164
144
|
return getPanel(this);
|
|
165
145
|
}
|
|
166
146
|
};
|
|
147
|
+
UHTMLTabElement.observedAttributes = ["id", "aria-selected", ARIA_CONTROLS];
|
|
167
148
|
var UHTMLTabPanelElement = class extends UHTMLElement {
|
|
168
|
-
static get observedAttributes() {
|
|
169
|
-
return ["id"];
|
|
170
|
-
}
|
|
171
149
|
constructor() {
|
|
172
150
|
super();
|
|
173
151
|
attachStyle(this, DISPLAY_BLOCK);
|
|
174
152
|
}
|
|
175
153
|
connectedCallback() {
|
|
176
|
-
|
|
154
|
+
this.role = "tabpanel";
|
|
177
155
|
this.hidden = Array.from(this.tabs).every((tab) => !tab.selected);
|
|
178
156
|
}
|
|
179
157
|
attributeChangedCallback(_name, prev, next) {
|
|
180
|
-
if (
|
|
181
|
-
|
|
182
|
-
}
|
|
158
|
+
if (SKIP_ATTR_CHANGE || prev === next) return;
|
|
159
|
+
getTabs(this, prev).forEach((tab) => tab.setAttribute(ARIA_CONTROLS, next));
|
|
183
160
|
}
|
|
184
161
|
get tabsElement() {
|
|
185
162
|
return this.closest("u-tabs");
|
|
@@ -188,12 +165,13 @@ var UHTMLTabPanelElement = class extends UHTMLElement {
|
|
|
188
165
|
return getTabs(this, this.id);
|
|
189
166
|
}
|
|
190
167
|
};
|
|
168
|
+
UHTMLTabPanelElement.observedAttributes = ["id"];
|
|
191
169
|
var queryWithoutNested = (tag, self) => {
|
|
192
170
|
const selector = `${tag}:not(:scope ${self.nodeName}:not(:scope) ${tag})`;
|
|
193
171
|
return self.querySelectorAll(selector);
|
|
194
172
|
};
|
|
195
173
|
var getPanel = (self) => {
|
|
196
|
-
const css = `u-tabpanel[id="${
|
|
174
|
+
const css = `u-tabpanel[id="${self.getAttribute(ARIA_CONTROLS)}"]`;
|
|
197
175
|
return getRoot(self).querySelector(css) || document.querySelector(css);
|
|
198
176
|
};
|
|
199
177
|
var getTabs = (self, id2) => {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"modules": [
|
|
5
5
|
{
|
|
6
6
|
"kind": "javascript-module",
|
|
7
|
-
"path": "u-tabs.ts",
|
|
7
|
+
"path": "/Users/eirikbacker/Library/Mobile Documents/com~apple~CloudDocs/5-capra/u-elements/packages/u-tabs/u-tabs.ts",
|
|
8
8
|
"declarations": [
|
|
9
9
|
{
|
|
10
10
|
"kind": "class",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
],
|
|
46
46
|
"superclass": {
|
|
47
47
|
"name": "UHTMLElement",
|
|
48
|
-
"module": "/utils"
|
|
48
|
+
"module": "//Users/eirikbacker/Library/Mobile%20Documents/com~apple~CloudDocs/5-capra/u-elements/packages/utils"
|
|
49
49
|
},
|
|
50
50
|
"tagName": "u-tabs",
|
|
51
51
|
"customElement": true
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
],
|
|
79
79
|
"superclass": {
|
|
80
80
|
"name": "UHTMLElement",
|
|
81
|
-
"module": "/utils"
|
|
81
|
+
"module": "//Users/eirikbacker/Library/Mobile%20Documents/com~apple~CloudDocs/5-capra/u-elements/packages/utils"
|
|
82
82
|
},
|
|
83
83
|
"tagName": "u-tablist",
|
|
84
84
|
"customElement": true
|
|
@@ -132,11 +132,14 @@
|
|
|
132
132
|
"attributes": [
|
|
133
133
|
{
|
|
134
134
|
"name": "id"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"name": "aria-selected"
|
|
135
138
|
}
|
|
136
139
|
],
|
|
137
140
|
"superclass": {
|
|
138
141
|
"name": "UHTMLElement",
|
|
139
|
-
"module": "/utils"
|
|
142
|
+
"module": "//Users/eirikbacker/Library/Mobile%20Documents/com~apple~CloudDocs/5-capra/u-elements/packages/utils"
|
|
140
143
|
},
|
|
141
144
|
"tagName": "u-tab",
|
|
142
145
|
"customElement": true
|
|
@@ -170,7 +173,7 @@
|
|
|
170
173
|
],
|
|
171
174
|
"superclass": {
|
|
172
175
|
"name": "UHTMLElement",
|
|
173
|
-
"module": "/utils"
|
|
176
|
+
"module": "//Users/eirikbacker/Library/Mobile%20Documents/com~apple~CloudDocs/5-capra/u-elements/packages/utils"
|
|
174
177
|
},
|
|
175
178
|
"tagName": "u-tabpanel",
|
|
176
179
|
"customElement": true
|
|
@@ -182,7 +185,7 @@
|
|
|
182
185
|
"name": "UHTMLTabsElement",
|
|
183
186
|
"declaration": {
|
|
184
187
|
"name": "UHTMLTabsElement",
|
|
185
|
-
"module": "u-tabs.ts"
|
|
188
|
+
"module": "/Users/eirikbacker/Library/Mobile Documents/com~apple~CloudDocs/5-capra/u-elements/packages/u-tabs/u-tabs.ts"
|
|
186
189
|
}
|
|
187
190
|
},
|
|
188
191
|
{
|
|
@@ -190,7 +193,7 @@
|
|
|
190
193
|
"name": "UHTMLTabListElement",
|
|
191
194
|
"declaration": {
|
|
192
195
|
"name": "UHTMLTabListElement",
|
|
193
|
-
"module": "u-tabs.ts"
|
|
196
|
+
"module": "/Users/eirikbacker/Library/Mobile Documents/com~apple~CloudDocs/5-capra/u-elements/packages/u-tabs/u-tabs.ts"
|
|
194
197
|
}
|
|
195
198
|
},
|
|
196
199
|
{
|
|
@@ -198,7 +201,7 @@
|
|
|
198
201
|
"name": "UHTMLTabElement",
|
|
199
202
|
"declaration": {
|
|
200
203
|
"name": "UHTMLTabElement",
|
|
201
|
-
"module": "u-tabs.ts"
|
|
204
|
+
"module": "/Users/eirikbacker/Library/Mobile Documents/com~apple~CloudDocs/5-capra/u-elements/packages/u-tabs/u-tabs.ts"
|
|
202
205
|
}
|
|
203
206
|
},
|
|
204
207
|
{
|
|
@@ -206,7 +209,7 @@
|
|
|
206
209
|
"name": "UHTMLTabPanelElement",
|
|
207
210
|
"declaration": {
|
|
208
211
|
"name": "UHTMLTabPanelElement",
|
|
209
|
-
"module": "u-tabs.ts"
|
|
212
|
+
"module": "/Users/eirikbacker/Library/Mobile Documents/com~apple~CloudDocs/5-capra/u-elements/packages/u-tabs/u-tabs.ts"
|
|
210
213
|
}
|
|
211
214
|
},
|
|
212
215
|
{
|
|
@@ -214,7 +217,7 @@
|
|
|
214
217
|
"name": "u-tabs",
|
|
215
218
|
"declaration": {
|
|
216
219
|
"name": "UHTMLTabsElement",
|
|
217
|
-
"module": "u-tabs.ts"
|
|
220
|
+
"module": "/Users/eirikbacker/Library/Mobile Documents/com~apple~CloudDocs/5-capra/u-elements/packages/u-tabs/u-tabs.ts"
|
|
218
221
|
}
|
|
219
222
|
},
|
|
220
223
|
{
|
|
@@ -222,7 +225,7 @@
|
|
|
222
225
|
"name": "u-tablist",
|
|
223
226
|
"declaration": {
|
|
224
227
|
"name": "UHTMLTabListElement",
|
|
225
|
-
"module": "u-tabs.ts"
|
|
228
|
+
"module": "/Users/eirikbacker/Library/Mobile Documents/com~apple~CloudDocs/5-capra/u-elements/packages/u-tabs/u-tabs.ts"
|
|
226
229
|
}
|
|
227
230
|
},
|
|
228
231
|
{
|
|
@@ -230,7 +233,7 @@
|
|
|
230
233
|
"name": "u-tab",
|
|
231
234
|
"declaration": {
|
|
232
235
|
"name": "UHTMLTabElement",
|
|
233
|
-
"module": "u-tabs.ts"
|
|
236
|
+
"module": "/Users/eirikbacker/Library/Mobile Documents/com~apple~CloudDocs/5-capra/u-elements/packages/u-tabs/u-tabs.ts"
|
|
234
237
|
}
|
|
235
238
|
},
|
|
236
239
|
{
|
|
@@ -238,7 +241,7 @@
|
|
|
238
241
|
"name": "u-tabpanel",
|
|
239
242
|
"declaration": {
|
|
240
243
|
"name": "UHTMLTabPanelElement",
|
|
241
|
-
"module": "u-tabs.ts"
|
|
244
|
+
"module": "/Users/eirikbacker/Library/Mobile Documents/com~apple~CloudDocs/5-capra/u-elements/packages/u-tabs/u-tabs.ts"
|
|
242
245
|
}
|
|
243
246
|
}
|
|
244
247
|
]
|
package/dist/u-tabs.vscode.json
CHANGED
|
@@ -17,7 +17,10 @@
|
|
|
17
17
|
{
|
|
18
18
|
"name": "u-tab",
|
|
19
19
|
"description": "The `<u-tab>` HTML element is an interactive element inside a `<u-tablist>` that, when activated, displays its associated `<u-tabpanel>`.\n[MDN Reference](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tab_role)\n---\n",
|
|
20
|
-
"attributes": [
|
|
20
|
+
"attributes": [
|
|
21
|
+
{ "name": "id", "values": [] },
|
|
22
|
+
{ "name": "aria-selected", "values": [] }
|
|
23
|
+
],
|
|
21
24
|
"references": []
|
|
22
25
|
},
|
|
23
26
|
{
|