@u-elements/u-tabs 0.0.2 → 0.0.4
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 +71 -67
- package/dist/u-tabs.d.cts +77 -45
- package/dist/u-tabs.d.ts +77 -45
- package/dist/u-tabs.js +71 -67
- package/dist/u-tabs.manifest.json +15 -5
- package/dist/u-tabs.vscode.json +1 -1
- package/package.json +1 -1
package/dist/u-tabs.cjs
CHANGED
|
@@ -20,10 +20,8 @@ var attachStyle = (element, css) => element.attachShadow({ mode: "closed" }).app
|
|
|
20
20
|
);
|
|
21
21
|
var asButton = (event) => {
|
|
22
22
|
const isClick = "key" in event && (event.key === " " || event.key === "Enter");
|
|
23
|
-
if (isClick)
|
|
24
|
-
|
|
25
|
-
if (isClick && event.target instanceof HTMLElement)
|
|
26
|
-
event.target.click();
|
|
23
|
+
if (isClick) event.preventDefault();
|
|
24
|
+
if (isClick && event.target instanceof HTMLElement) event.target.click();
|
|
27
25
|
return isClick;
|
|
28
26
|
};
|
|
29
27
|
var getRoot = (node) => node.getRootNode();
|
|
@@ -45,10 +43,10 @@ var UHTMLTabsElement = class extends UHTMLElement {
|
|
|
45
43
|
return queryWithoutNested("u-tablist", this)[0] || null;
|
|
46
44
|
}
|
|
47
45
|
get selectedIndex() {
|
|
48
|
-
return
|
|
46
|
+
return getSelectedIndex(this.tabs);
|
|
49
47
|
}
|
|
50
48
|
set selectedIndex(index) {
|
|
51
|
-
this.tabs[index].ariaSelected = "true";
|
|
49
|
+
if (this.tabs[index]) this.tabs[index].ariaSelected = "true";
|
|
52
50
|
}
|
|
53
51
|
get tabs() {
|
|
54
52
|
return queryWithoutNested("u-tab", this);
|
|
@@ -72,31 +70,42 @@ var UHTMLTabListElement = class extends UHTMLElement {
|
|
|
72
70
|
handleEvent(event) {
|
|
73
71
|
const { key } = event;
|
|
74
72
|
const tabs = [...this.getElementsByTagName("u-tab")];
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (event.type === "click")
|
|
79
|
-
tabs[index].selected = true;
|
|
73
|
+
const prev = tabs.findIndex((tab) => tab.contains(event.target));
|
|
74
|
+
let next = prev;
|
|
75
|
+
if (event.defaultPrevented || prev === -1) return;
|
|
76
|
+
if (event.type === "click") tabs[prev].selected = true;
|
|
80
77
|
if (event.type === "keydown" && !asButton(event)) {
|
|
81
78
|
if (key === "ArrowDown" || key === "ArrowRight")
|
|
82
|
-
|
|
79
|
+
next = (prev + 1) % tabs.length;
|
|
83
80
|
else if (key === "ArrowUp" || key === "ArrowLeft")
|
|
84
|
-
|
|
85
|
-
else if (key === "End")
|
|
86
|
-
|
|
87
|
-
else if (key === "
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
81
|
+
next = (prev || tabs.length) - 1;
|
|
82
|
+
else if (key === "End") next = tabs.length - 1;
|
|
83
|
+
else if (key === "Home") next = 0;
|
|
84
|
+
else if (key === "Tab") next = getSelectedIndex(tabs);
|
|
85
|
+
else return;
|
|
86
|
+
setTimeout(() => {
|
|
87
|
+
tabs[prev].tabIndex = -1;
|
|
88
|
+
tabs[next].tabIndex = 0;
|
|
89
|
+
});
|
|
90
|
+
if (key !== "Tab") {
|
|
91
|
+
event.preventDefault();
|
|
92
|
+
tabs[next].focus();
|
|
93
|
+
}
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
96
|
get tabsElement() {
|
|
96
97
|
return this.closest("u-tabs");
|
|
97
98
|
}
|
|
99
|
+
get tabs() {
|
|
100
|
+
return queryWithoutNested("u-tab", this);
|
|
101
|
+
}
|
|
102
|
+
get selectedIndex() {
|
|
103
|
+
return getSelectedIndex(this.tabs);
|
|
104
|
+
}
|
|
105
|
+
set selectedIndex(index) {
|
|
106
|
+
if (this.tabs[index]) this.tabs[index].ariaSelected = "true";
|
|
107
|
+
}
|
|
98
108
|
};
|
|
99
|
-
var SKIP_ATTR_CHANGE = false;
|
|
100
109
|
var UHTMLTabElement = class extends UHTMLElement {
|
|
101
110
|
constructor() {
|
|
102
111
|
super();
|
|
@@ -106,33 +115,33 @@ var UHTMLTabElement = class extends UHTMLElement {
|
|
|
106
115
|
);
|
|
107
116
|
}
|
|
108
117
|
connectedCallback() {
|
|
109
|
-
this.selected
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
panel?.setAttribute(
|
|
130
|
-
SAFE_LABELLEDBY,
|
|
131
|
-
useId(selectedPanel === panel ? selected : tab)
|
|
132
|
-
);
|
|
118
|
+
const selected = this.selected || [...queryWithoutNested("u-tab", this.tabList || this)].every(
|
|
119
|
+
(tab) => tab.ariaSelected !== "true"
|
|
120
|
+
);
|
|
121
|
+
this.role = "tab";
|
|
122
|
+
this.tabIndex = selected ? 0 : -1;
|
|
123
|
+
this.ariaSelected = `${selected}`;
|
|
124
|
+
}
|
|
125
|
+
attributeChangedCallback(name, prev) {
|
|
126
|
+
if (!this.selected) return;
|
|
127
|
+
const nextPanel = getPanel(this);
|
|
128
|
+
const nextPanelId = useId(nextPanel);
|
|
129
|
+
if (this.tabList)
|
|
130
|
+
queryWithoutNested("u-tab", this.tabList).forEach((tab) => {
|
|
131
|
+
const isUnselect = tab !== this && tab.ariaSelected === "true";
|
|
132
|
+
const prevPanel = isUnselect && getPanel(tab);
|
|
133
|
+
if (prevPanel && prevPanel !== nextPanel) prevPanel.hidden = true;
|
|
134
|
+
if (isUnselect) {
|
|
135
|
+
tab.ariaSelected = "false";
|
|
136
|
+
tab.tabIndex = -1;
|
|
137
|
+
}
|
|
133
138
|
});
|
|
134
|
-
|
|
135
|
-
|
|
139
|
+
if (name === ARIA_CONTROLS) getPanel(this, prev)?.setAttribute("hidden", "");
|
|
140
|
+
if (this.getAttribute(ARIA_CONTROLS) !== nextPanelId)
|
|
141
|
+
this.setAttribute(ARIA_CONTROLS, nextPanelId);
|
|
142
|
+
this.tabIndex = 0;
|
|
143
|
+
nextPanel?.setAttribute(SAFE_LABELLEDBY, useId(this));
|
|
144
|
+
nextPanel?.removeAttribute("hidden");
|
|
136
145
|
}
|
|
137
146
|
get tabsElement() {
|
|
138
147
|
return this.closest("u-tabs");
|
|
@@ -144,11 +153,12 @@ var UHTMLTabElement = class extends UHTMLElement {
|
|
|
144
153
|
return this.ariaSelected === "true";
|
|
145
154
|
}
|
|
146
155
|
set selected(value) {
|
|
147
|
-
this.ariaSelected = `${value}`;
|
|
156
|
+
this.ariaSelected = `${!!value}`;
|
|
148
157
|
}
|
|
149
158
|
/** Retrieves the ordinal position of an tab in a tablist. */
|
|
150
159
|
get index() {
|
|
151
|
-
|
|
160
|
+
const tabList = this.tabList;
|
|
161
|
+
return tabList ? [...queryWithoutNested("u-tab", tabList)].indexOf(this) : 0;
|
|
152
162
|
}
|
|
153
163
|
get panel() {
|
|
154
164
|
return getPanel(this);
|
|
@@ -161,33 +171,27 @@ var UHTMLTabPanelElement = class extends UHTMLElement {
|
|
|
161
171
|
attachStyle(this, DISPLAY_BLOCK);
|
|
162
172
|
}
|
|
163
173
|
connectedCallback() {
|
|
174
|
+
this.hidden = [...this.tabs].every((tab) => tab.ariaSelected !== "true");
|
|
164
175
|
this.role = "tabpanel";
|
|
165
|
-
this.hidden = Array.from(this.tabs).every((tab) => !tab.selected);
|
|
166
|
-
}
|
|
167
|
-
attributeChangedCallback(_name, prev, next) {
|
|
168
|
-
if (SKIP_ATTR_CHANGE || prev === next)
|
|
169
|
-
return;
|
|
170
|
-
getTabs(this, prev).forEach((tab) => tab.setAttribute(ARIA_CONTROLS, next));
|
|
171
176
|
}
|
|
172
177
|
get tabsElement() {
|
|
173
178
|
return this.closest("u-tabs");
|
|
174
179
|
}
|
|
175
180
|
get tabs() {
|
|
176
|
-
|
|
181
|
+
const css = `u-tab[${ARIA_CONTROLS}="${this.id}"]`;
|
|
182
|
+
const root = getRoot(this).querySelectorAll(css);
|
|
183
|
+
return root.length ? root : document.querySelectorAll(css);
|
|
177
184
|
}
|
|
178
185
|
};
|
|
179
|
-
UHTMLTabPanelElement.observedAttributes = ["id"];
|
|
180
186
|
var queryWithoutNested = (tag, self) => {
|
|
181
|
-
const
|
|
182
|
-
return self.querySelectorAll(
|
|
183
|
-
};
|
|
184
|
-
var getPanel = (self) => {
|
|
185
|
-
const css = `u-tabpanel[id="${self.getAttribute(ARIA_CONTROLS)}"]`;
|
|
186
|
-
return getRoot(self).querySelector(css) || document.querySelector(css);
|
|
187
|
+
const css = `${tag}:not(:scope ${self.nodeName}:not(:scope) ${tag})`;
|
|
188
|
+
return self.querySelectorAll(css);
|
|
187
189
|
};
|
|
188
|
-
var
|
|
189
|
-
|
|
190
|
-
|
|
190
|
+
var getSelectedIndex = (tabs) => [...tabs].findIndex((tab) => tab.ariaSelected === "true");
|
|
191
|
+
var getPanel = (self, id2) => {
|
|
192
|
+
const css = `u-tabpanel[id="${id2 || self.getAttribute(ARIA_CONTROLS)}"]`;
|
|
193
|
+
const tabsElement = self.closest("u-tabs");
|
|
194
|
+
return getRoot(self).querySelector(css) || document.querySelector(css) || tabsElement && queryWithoutNested("u-tabpanel", tabsElement)[[...queryWithoutNested("u-tab", tabsElement)].indexOf(self)] || null;
|
|
191
195
|
};
|
|
192
196
|
customElements.define("u-tabs", UHTMLTabsElement);
|
|
193
197
|
customElements.define("u-tablist", UHTMLTabListElement);
|
package/dist/u-tabs.d.cts
CHANGED
|
@@ -33,6 +33,9 @@ declare class UHTMLTabListElement extends UHTMLElement {
|
|
|
33
33
|
disconnectedCallback(): void;
|
|
34
34
|
handleEvent(event: Event): void;
|
|
35
35
|
get tabsElement(): UHTMLTabsElement | null;
|
|
36
|
+
get tabs(): NodeListOf<UHTMLTabElement>;
|
|
37
|
+
get selectedIndex(): number;
|
|
38
|
+
set selectedIndex(index: number);
|
|
36
39
|
}
|
|
37
40
|
/**
|
|
38
41
|
* The `<u-tab>` HTML element is an interactive element inside a `<u-tablist>` that, when activated, displays its associated `<u-tabpanel>`.
|
|
@@ -42,7 +45,7 @@ declare class UHTMLTabElement extends UHTMLElement {
|
|
|
42
45
|
static observedAttributes: string[];
|
|
43
46
|
constructor();
|
|
44
47
|
connectedCallback(): void;
|
|
45
|
-
attributeChangedCallback(
|
|
48
|
+
attributeChangedCallback(name: string, prev: string): void;
|
|
46
49
|
get tabsElement(): UHTMLTabsElement | null;
|
|
47
50
|
get tabList(): UHTMLTabListElement | null;
|
|
48
51
|
get selected(): boolean;
|
|
@@ -56,66 +59,95 @@ declare class UHTMLTabElement extends UHTMLElement {
|
|
|
56
59
|
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tabpanel_role)
|
|
57
60
|
*/
|
|
58
61
|
declare class UHTMLTabPanelElement extends UHTMLElement {
|
|
59
|
-
static observedAttributes: string[];
|
|
60
62
|
constructor();
|
|
61
63
|
connectedCallback(): void;
|
|
62
|
-
attributeChangedCallback(_name: string, prev: string, next: string): void;
|
|
63
64
|
get tabsElement(): UHTMLTabsElement | null;
|
|
64
65
|
get tabs(): NodeListOf<UHTMLTabElement>;
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
export { UHTMLTabElement, UHTMLTabListElement, UHTMLTabPanelElement, UHTMLTabsElement };
|
|
69
|
+
|
|
70
|
+
import type * as PreactTypes from 'preact'
|
|
71
|
+
import type * as ReactTypes from 'react'
|
|
72
|
+
import type * as SvelteTypes from 'svelte/elements'
|
|
68
73
|
import type * as VueJSX from '@vue/runtime-dom'
|
|
69
74
|
import type { JSX as QwikJSX } from '@builder.io/qwik/jsx-runtime'
|
|
70
|
-
import type { JSX as ReactJSX } from 'react'
|
|
71
75
|
import type { JSX as SolidJSX } from 'solid-js'
|
|
72
|
-
import type { SvelteHTMLElements } from 'svelte/elements'
|
|
73
76
|
|
|
74
|
-
|
|
75
|
-
export type
|
|
76
|
-
export type
|
|
77
|
-
export type
|
|
78
|
-
export type
|
|
77
|
+
|
|
78
|
+
export type PreactUtabs = PreactTypes.JSX.HTMLAttributes<UHTMLTagsElement> & { }
|
|
79
|
+
export type ReactUtabs = ReactTypes.DetailedHTMLProps<ReactTypes.HTMLAttributes<UHTMLTabsElement>, UHTMLTabsElement> & { class?: string }
|
|
80
|
+
export type QwikUtabs = QwikJSX.IntrinsicElements['div']
|
|
81
|
+
export type VueUtabs = VueJSX.HTMLAttributes
|
|
82
|
+
export type SvelteUtabs = SvelteTypes.HTMLAttributes<UHTMLTabsElement> & { }
|
|
83
|
+
export type SolidUtabs = SolidJSX.HTMLAttributes<UHTMLTabsElement>
|
|
79
84
|
|
|
80
85
|
// Augmenting @vue/runtime-dom instead of vue directly to avoid interfering with React JSX
|
|
81
|
-
declare
|
|
82
|
-
declare
|
|
83
|
-
declare
|
|
84
|
-
declare module '
|
|
85
|
-
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tabs':
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
declare global { namespace React.JSX { interface IntrinsicElements { 'u-tabs': ReactUtabs } } }
|
|
87
|
+
declare global { namespace preact.JSX { interface IntrinsicElements { 'u-tabs': PreactUtabs } } }
|
|
88
|
+
declare module '@builder.io/qwik/jsx-runtime' { export namespace JSX { export interface IntrinsicElements { 'u-tabs': QwikUtabs } } }
|
|
89
|
+
declare module '@vue/runtime-dom' { export interface GlobalComponents { 'u-tabs': VueUtabs } }
|
|
90
|
+
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tabs': SvelteUtabs } }
|
|
91
|
+
declare module 'solid-js' {
|
|
92
|
+
namespace JSX {
|
|
93
|
+
interface IntrinsicElements { 'u-tabs': SolidUtabs }
|
|
94
|
+
interface CustomEvents { }
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export type PreactUtablist = PreactTypes.JSX.HTMLAttributes<UHTMLTagsElement> & { }
|
|
98
|
+
export type ReactUtablist = ReactTypes.DetailedHTMLProps<ReactTypes.HTMLAttributes<UHTMLTabListElement>, UHTMLTabListElement> & { class?: string }
|
|
99
|
+
export type QwikUtablist = QwikJSX.IntrinsicElements['div']
|
|
100
|
+
export type VueUtablist = VueJSX.HTMLAttributes
|
|
101
|
+
export type SvelteUtablist = SvelteTypes.HTMLAttributes<UHTMLTabListElement> & { }
|
|
102
|
+
export type SolidUtablist = SolidJSX.HTMLAttributes<UHTMLTabListElement>
|
|
91
103
|
|
|
92
104
|
// Augmenting @vue/runtime-dom instead of vue directly to avoid interfering with React JSX
|
|
93
|
-
declare
|
|
94
|
-
declare
|
|
95
|
-
declare
|
|
96
|
-
declare module '
|
|
97
|
-
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tablist':
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
declare global { namespace React.JSX { interface IntrinsicElements { 'u-tablist': ReactUtablist } } }
|
|
106
|
+
declare global { namespace preact.JSX { interface IntrinsicElements { 'u-tablist': PreactUtablist } } }
|
|
107
|
+
declare module '@builder.io/qwik/jsx-runtime' { export namespace JSX { export interface IntrinsicElements { 'u-tablist': QwikUtablist } } }
|
|
108
|
+
declare module '@vue/runtime-dom' { export interface GlobalComponents { 'u-tablist': VueUtablist } }
|
|
109
|
+
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tablist': SvelteUtablist } }
|
|
110
|
+
declare module 'solid-js' {
|
|
111
|
+
namespace JSX {
|
|
112
|
+
interface IntrinsicElements { 'u-tablist': SolidUtablist }
|
|
113
|
+
interface CustomEvents { }
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export type PreactUtab = PreactTypes.JSX.HTMLAttributes<UHTMLTagsElement> & { }
|
|
117
|
+
export type ReactUtab = ReactTypes.DetailedHTMLProps<ReactTypes.HTMLAttributes<UHTMLTabElement>, UHTMLTabElement> & { class?: string }
|
|
118
|
+
export type QwikUtab = QwikJSX.IntrinsicElements['div']
|
|
119
|
+
export type VueUtab = VueJSX.HTMLAttributes
|
|
120
|
+
export type SvelteUtab = SvelteTypes.HTMLAttributes<UHTMLTabElement> & { }
|
|
121
|
+
export type SolidUtab = SolidJSX.HTMLAttributes<UHTMLTabElement>
|
|
103
122
|
|
|
104
123
|
// Augmenting @vue/runtime-dom instead of vue directly to avoid interfering with React JSX
|
|
105
|
-
declare
|
|
106
|
-
declare
|
|
107
|
-
declare
|
|
108
|
-
declare module '
|
|
109
|
-
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tab':
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
124
|
+
declare global { namespace React.JSX { interface IntrinsicElements { 'u-tab': ReactUtab } } }
|
|
125
|
+
declare global { namespace preact.JSX { interface IntrinsicElements { 'u-tab': PreactUtab } } }
|
|
126
|
+
declare module '@builder.io/qwik/jsx-runtime' { export namespace JSX { export interface IntrinsicElements { 'u-tab': QwikUtab } } }
|
|
127
|
+
declare module '@vue/runtime-dom' { export interface GlobalComponents { 'u-tab': VueUtab } }
|
|
128
|
+
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tab': SvelteUtab } }
|
|
129
|
+
declare module 'solid-js' {
|
|
130
|
+
namespace JSX {
|
|
131
|
+
interface IntrinsicElements { 'u-tab': SolidUtab }
|
|
132
|
+
interface CustomEvents { }
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
export type PreactUtabpanel = PreactTypes.JSX.HTMLAttributes<UHTMLTagsElement> & { }
|
|
136
|
+
export type ReactUtabpanel = ReactTypes.DetailedHTMLProps<ReactTypes.HTMLAttributes<UHTMLTabPanelElement>, UHTMLTabPanelElement> & { class?: string }
|
|
137
|
+
export type QwikUtabpanel = QwikJSX.IntrinsicElements['div']
|
|
138
|
+
export type VueUtabpanel = VueJSX.HTMLAttributes
|
|
139
|
+
export type SvelteUtabpanel = SvelteTypes.HTMLAttributes<UHTMLTabPanelElement> & { }
|
|
140
|
+
export type SolidUtabpanel = SolidJSX.HTMLAttributes<UHTMLTabPanelElement>
|
|
115
141
|
|
|
116
142
|
// Augmenting @vue/runtime-dom instead of vue directly to avoid interfering with React JSX
|
|
117
|
-
declare
|
|
118
|
-
declare
|
|
119
|
-
declare
|
|
120
|
-
declare module '
|
|
121
|
-
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tabpanel':
|
|
143
|
+
declare global { namespace React.JSX { interface IntrinsicElements { 'u-tabpanel': ReactUtabpanel } } }
|
|
144
|
+
declare global { namespace preact.JSX { interface IntrinsicElements { 'u-tabpanel': PreactUtabpanel } } }
|
|
145
|
+
declare module '@builder.io/qwik/jsx-runtime' { export namespace JSX { export interface IntrinsicElements { 'u-tabpanel': QwikUtabpanel } } }
|
|
146
|
+
declare module '@vue/runtime-dom' { export interface GlobalComponents { 'u-tabpanel': VueUtabpanel } }
|
|
147
|
+
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tabpanel': SvelteUtabpanel } }
|
|
148
|
+
declare module 'solid-js' {
|
|
149
|
+
namespace JSX {
|
|
150
|
+
interface IntrinsicElements { 'u-tabpanel': SolidUtabpanel }
|
|
151
|
+
interface CustomEvents { }
|
|
152
|
+
}
|
|
153
|
+
}
|
package/dist/u-tabs.d.ts
CHANGED
|
@@ -33,6 +33,9 @@ declare class UHTMLTabListElement extends UHTMLElement {
|
|
|
33
33
|
disconnectedCallback(): void;
|
|
34
34
|
handleEvent(event: Event): void;
|
|
35
35
|
get tabsElement(): UHTMLTabsElement | null;
|
|
36
|
+
get tabs(): NodeListOf<UHTMLTabElement>;
|
|
37
|
+
get selectedIndex(): number;
|
|
38
|
+
set selectedIndex(index: number);
|
|
36
39
|
}
|
|
37
40
|
/**
|
|
38
41
|
* The `<u-tab>` HTML element is an interactive element inside a `<u-tablist>` that, when activated, displays its associated `<u-tabpanel>`.
|
|
@@ -42,7 +45,7 @@ declare class UHTMLTabElement extends UHTMLElement {
|
|
|
42
45
|
static observedAttributes: string[];
|
|
43
46
|
constructor();
|
|
44
47
|
connectedCallback(): void;
|
|
45
|
-
attributeChangedCallback(
|
|
48
|
+
attributeChangedCallback(name: string, prev: string): void;
|
|
46
49
|
get tabsElement(): UHTMLTabsElement | null;
|
|
47
50
|
get tabList(): UHTMLTabListElement | null;
|
|
48
51
|
get selected(): boolean;
|
|
@@ -56,66 +59,95 @@ declare class UHTMLTabElement extends UHTMLElement {
|
|
|
56
59
|
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tabpanel_role)
|
|
57
60
|
*/
|
|
58
61
|
declare class UHTMLTabPanelElement extends UHTMLElement {
|
|
59
|
-
static observedAttributes: string[];
|
|
60
62
|
constructor();
|
|
61
63
|
connectedCallback(): void;
|
|
62
|
-
attributeChangedCallback(_name: string, prev: string, next: string): void;
|
|
63
64
|
get tabsElement(): UHTMLTabsElement | null;
|
|
64
65
|
get tabs(): NodeListOf<UHTMLTabElement>;
|
|
65
66
|
}
|
|
66
67
|
|
|
67
68
|
export { UHTMLTabElement, UHTMLTabListElement, UHTMLTabPanelElement, UHTMLTabsElement };
|
|
69
|
+
|
|
70
|
+
import type * as PreactTypes from 'preact'
|
|
71
|
+
import type * as ReactTypes from 'react'
|
|
72
|
+
import type * as SvelteTypes from 'svelte/elements'
|
|
68
73
|
import type * as VueJSX from '@vue/runtime-dom'
|
|
69
74
|
import type { JSX as QwikJSX } from '@builder.io/qwik/jsx-runtime'
|
|
70
|
-
import type { JSX as ReactJSX } from 'react'
|
|
71
75
|
import type { JSX as SolidJSX } from 'solid-js'
|
|
72
|
-
import type { SvelteHTMLElements } from 'svelte/elements'
|
|
73
76
|
|
|
74
|
-
|
|
75
|
-
export type
|
|
76
|
-
export type
|
|
77
|
-
export type
|
|
78
|
-
export type
|
|
77
|
+
|
|
78
|
+
export type PreactUtabs = PreactTypes.JSX.HTMLAttributes<UHTMLTagsElement> & { }
|
|
79
|
+
export type ReactUtabs = ReactTypes.DetailedHTMLProps<ReactTypes.HTMLAttributes<UHTMLTabsElement>, UHTMLTabsElement> & { class?: string }
|
|
80
|
+
export type QwikUtabs = QwikJSX.IntrinsicElements['div']
|
|
81
|
+
export type VueUtabs = VueJSX.HTMLAttributes
|
|
82
|
+
export type SvelteUtabs = SvelteTypes.HTMLAttributes<UHTMLTabsElement> & { }
|
|
83
|
+
export type SolidUtabs = SolidJSX.HTMLAttributes<UHTMLTabsElement>
|
|
79
84
|
|
|
80
85
|
// Augmenting @vue/runtime-dom instead of vue directly to avoid interfering with React JSX
|
|
81
|
-
declare
|
|
82
|
-
declare
|
|
83
|
-
declare
|
|
84
|
-
declare module '
|
|
85
|
-
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tabs':
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
declare global { namespace React.JSX { interface IntrinsicElements { 'u-tabs': ReactUtabs } } }
|
|
87
|
+
declare global { namespace preact.JSX { interface IntrinsicElements { 'u-tabs': PreactUtabs } } }
|
|
88
|
+
declare module '@builder.io/qwik/jsx-runtime' { export namespace JSX { export interface IntrinsicElements { 'u-tabs': QwikUtabs } } }
|
|
89
|
+
declare module '@vue/runtime-dom' { export interface GlobalComponents { 'u-tabs': VueUtabs } }
|
|
90
|
+
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tabs': SvelteUtabs } }
|
|
91
|
+
declare module 'solid-js' {
|
|
92
|
+
namespace JSX {
|
|
93
|
+
interface IntrinsicElements { 'u-tabs': SolidUtabs }
|
|
94
|
+
interface CustomEvents { }
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export type PreactUtablist = PreactTypes.JSX.HTMLAttributes<UHTMLTagsElement> & { }
|
|
98
|
+
export type ReactUtablist = ReactTypes.DetailedHTMLProps<ReactTypes.HTMLAttributes<UHTMLTabListElement>, UHTMLTabListElement> & { class?: string }
|
|
99
|
+
export type QwikUtablist = QwikJSX.IntrinsicElements['div']
|
|
100
|
+
export type VueUtablist = VueJSX.HTMLAttributes
|
|
101
|
+
export type SvelteUtablist = SvelteTypes.HTMLAttributes<UHTMLTabListElement> & { }
|
|
102
|
+
export type SolidUtablist = SolidJSX.HTMLAttributes<UHTMLTabListElement>
|
|
91
103
|
|
|
92
104
|
// Augmenting @vue/runtime-dom instead of vue directly to avoid interfering with React JSX
|
|
93
|
-
declare
|
|
94
|
-
declare
|
|
95
|
-
declare
|
|
96
|
-
declare module '
|
|
97
|
-
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tablist':
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
declare global { namespace React.JSX { interface IntrinsicElements { 'u-tablist': ReactUtablist } } }
|
|
106
|
+
declare global { namespace preact.JSX { interface IntrinsicElements { 'u-tablist': PreactUtablist } } }
|
|
107
|
+
declare module '@builder.io/qwik/jsx-runtime' { export namespace JSX { export interface IntrinsicElements { 'u-tablist': QwikUtablist } } }
|
|
108
|
+
declare module '@vue/runtime-dom' { export interface GlobalComponents { 'u-tablist': VueUtablist } }
|
|
109
|
+
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tablist': SvelteUtablist } }
|
|
110
|
+
declare module 'solid-js' {
|
|
111
|
+
namespace JSX {
|
|
112
|
+
interface IntrinsicElements { 'u-tablist': SolidUtablist }
|
|
113
|
+
interface CustomEvents { }
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export type PreactUtab = PreactTypes.JSX.HTMLAttributes<UHTMLTagsElement> & { }
|
|
117
|
+
export type ReactUtab = ReactTypes.DetailedHTMLProps<ReactTypes.HTMLAttributes<UHTMLTabElement>, UHTMLTabElement> & { class?: string }
|
|
118
|
+
export type QwikUtab = QwikJSX.IntrinsicElements['div']
|
|
119
|
+
export type VueUtab = VueJSX.HTMLAttributes
|
|
120
|
+
export type SvelteUtab = SvelteTypes.HTMLAttributes<UHTMLTabElement> & { }
|
|
121
|
+
export type SolidUtab = SolidJSX.HTMLAttributes<UHTMLTabElement>
|
|
103
122
|
|
|
104
123
|
// Augmenting @vue/runtime-dom instead of vue directly to avoid interfering with React JSX
|
|
105
|
-
declare
|
|
106
|
-
declare
|
|
107
|
-
declare
|
|
108
|
-
declare module '
|
|
109
|
-
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tab':
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
124
|
+
declare global { namespace React.JSX { interface IntrinsicElements { 'u-tab': ReactUtab } } }
|
|
125
|
+
declare global { namespace preact.JSX { interface IntrinsicElements { 'u-tab': PreactUtab } } }
|
|
126
|
+
declare module '@builder.io/qwik/jsx-runtime' { export namespace JSX { export interface IntrinsicElements { 'u-tab': QwikUtab } } }
|
|
127
|
+
declare module '@vue/runtime-dom' { export interface GlobalComponents { 'u-tab': VueUtab } }
|
|
128
|
+
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tab': SvelteUtab } }
|
|
129
|
+
declare module 'solid-js' {
|
|
130
|
+
namespace JSX {
|
|
131
|
+
interface IntrinsicElements { 'u-tab': SolidUtab }
|
|
132
|
+
interface CustomEvents { }
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
export type PreactUtabpanel = PreactTypes.JSX.HTMLAttributes<UHTMLTagsElement> & { }
|
|
136
|
+
export type ReactUtabpanel = ReactTypes.DetailedHTMLProps<ReactTypes.HTMLAttributes<UHTMLTabPanelElement>, UHTMLTabPanelElement> & { class?: string }
|
|
137
|
+
export type QwikUtabpanel = QwikJSX.IntrinsicElements['div']
|
|
138
|
+
export type VueUtabpanel = VueJSX.HTMLAttributes
|
|
139
|
+
export type SvelteUtabpanel = SvelteTypes.HTMLAttributes<UHTMLTabPanelElement> & { }
|
|
140
|
+
export type SolidUtabpanel = SolidJSX.HTMLAttributes<UHTMLTabPanelElement>
|
|
115
141
|
|
|
116
142
|
// Augmenting @vue/runtime-dom instead of vue directly to avoid interfering with React JSX
|
|
117
|
-
declare
|
|
118
|
-
declare
|
|
119
|
-
declare
|
|
120
|
-
declare module '
|
|
121
|
-
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tabpanel':
|
|
143
|
+
declare global { namespace React.JSX { interface IntrinsicElements { 'u-tabpanel': ReactUtabpanel } } }
|
|
144
|
+
declare global { namespace preact.JSX { interface IntrinsicElements { 'u-tabpanel': PreactUtabpanel } } }
|
|
145
|
+
declare module '@builder.io/qwik/jsx-runtime' { export namespace JSX { export interface IntrinsicElements { 'u-tabpanel': QwikUtabpanel } } }
|
|
146
|
+
declare module '@vue/runtime-dom' { export interface GlobalComponents { 'u-tabpanel': VueUtabpanel } }
|
|
147
|
+
declare module 'svelte/elements' { interface SvelteHTMLElements { 'u-tabpanel': SvelteUtabpanel } }
|
|
148
|
+
declare module 'solid-js' {
|
|
149
|
+
namespace JSX {
|
|
150
|
+
interface IntrinsicElements { 'u-tabpanel': SolidUtabpanel }
|
|
151
|
+
interface CustomEvents { }
|
|
152
|
+
}
|
|
153
|
+
}
|
package/dist/u-tabs.js
CHANGED
|
@@ -18,10 +18,8 @@ var attachStyle = (element, css) => element.attachShadow({ mode: "closed" }).app
|
|
|
18
18
|
);
|
|
19
19
|
var asButton = (event) => {
|
|
20
20
|
const isClick = "key" in event && (event.key === " " || event.key === "Enter");
|
|
21
|
-
if (isClick)
|
|
22
|
-
|
|
23
|
-
if (isClick && event.target instanceof HTMLElement)
|
|
24
|
-
event.target.click();
|
|
21
|
+
if (isClick) event.preventDefault();
|
|
22
|
+
if (isClick && event.target instanceof HTMLElement) event.target.click();
|
|
25
23
|
return isClick;
|
|
26
24
|
};
|
|
27
25
|
var getRoot = (node) => node.getRootNode();
|
|
@@ -43,10 +41,10 @@ var UHTMLTabsElement = class extends UHTMLElement {
|
|
|
43
41
|
return queryWithoutNested("u-tablist", this)[0] || null;
|
|
44
42
|
}
|
|
45
43
|
get selectedIndex() {
|
|
46
|
-
return
|
|
44
|
+
return getSelectedIndex(this.tabs);
|
|
47
45
|
}
|
|
48
46
|
set selectedIndex(index) {
|
|
49
|
-
this.tabs[index].ariaSelected = "true";
|
|
47
|
+
if (this.tabs[index]) this.tabs[index].ariaSelected = "true";
|
|
50
48
|
}
|
|
51
49
|
get tabs() {
|
|
52
50
|
return queryWithoutNested("u-tab", this);
|
|
@@ -70,31 +68,42 @@ var UHTMLTabListElement = class extends UHTMLElement {
|
|
|
70
68
|
handleEvent(event) {
|
|
71
69
|
const { key } = event;
|
|
72
70
|
const tabs = [...this.getElementsByTagName("u-tab")];
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (event.type === "click")
|
|
77
|
-
tabs[index].selected = true;
|
|
71
|
+
const prev = tabs.findIndex((tab) => tab.contains(event.target));
|
|
72
|
+
let next = prev;
|
|
73
|
+
if (event.defaultPrevented || prev === -1) return;
|
|
74
|
+
if (event.type === "click") tabs[prev].selected = true;
|
|
78
75
|
if (event.type === "keydown" && !asButton(event)) {
|
|
79
76
|
if (key === "ArrowDown" || key === "ArrowRight")
|
|
80
|
-
|
|
77
|
+
next = (prev + 1) % tabs.length;
|
|
81
78
|
else if (key === "ArrowUp" || key === "ArrowLeft")
|
|
82
|
-
|
|
83
|
-
else if (key === "End")
|
|
84
|
-
|
|
85
|
-
else if (key === "
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
79
|
+
next = (prev || tabs.length) - 1;
|
|
80
|
+
else if (key === "End") next = tabs.length - 1;
|
|
81
|
+
else if (key === "Home") next = 0;
|
|
82
|
+
else if (key === "Tab") next = getSelectedIndex(tabs);
|
|
83
|
+
else return;
|
|
84
|
+
setTimeout(() => {
|
|
85
|
+
tabs[prev].tabIndex = -1;
|
|
86
|
+
tabs[next].tabIndex = 0;
|
|
87
|
+
});
|
|
88
|
+
if (key !== "Tab") {
|
|
89
|
+
event.preventDefault();
|
|
90
|
+
tabs[next].focus();
|
|
91
|
+
}
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
get tabsElement() {
|
|
94
95
|
return this.closest("u-tabs");
|
|
95
96
|
}
|
|
97
|
+
get tabs() {
|
|
98
|
+
return queryWithoutNested("u-tab", this);
|
|
99
|
+
}
|
|
100
|
+
get selectedIndex() {
|
|
101
|
+
return getSelectedIndex(this.tabs);
|
|
102
|
+
}
|
|
103
|
+
set selectedIndex(index) {
|
|
104
|
+
if (this.tabs[index]) this.tabs[index].ariaSelected = "true";
|
|
105
|
+
}
|
|
96
106
|
};
|
|
97
|
-
var SKIP_ATTR_CHANGE = false;
|
|
98
107
|
var UHTMLTabElement = class extends UHTMLElement {
|
|
99
108
|
constructor() {
|
|
100
109
|
super();
|
|
@@ -104,33 +113,33 @@ var UHTMLTabElement = class extends UHTMLElement {
|
|
|
104
113
|
);
|
|
105
114
|
}
|
|
106
115
|
connectedCallback() {
|
|
107
|
-
this.selected
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
panel?.setAttribute(
|
|
128
|
-
SAFE_LABELLEDBY,
|
|
129
|
-
useId(selectedPanel === panel ? selected : tab)
|
|
130
|
-
);
|
|
116
|
+
const selected = this.selected || [...queryWithoutNested("u-tab", this.tabList || this)].every(
|
|
117
|
+
(tab) => tab.ariaSelected !== "true"
|
|
118
|
+
);
|
|
119
|
+
this.role = "tab";
|
|
120
|
+
this.tabIndex = selected ? 0 : -1;
|
|
121
|
+
this.ariaSelected = `${selected}`;
|
|
122
|
+
}
|
|
123
|
+
attributeChangedCallback(name, prev) {
|
|
124
|
+
if (!this.selected) return;
|
|
125
|
+
const nextPanel = getPanel(this);
|
|
126
|
+
const nextPanelId = useId(nextPanel);
|
|
127
|
+
if (this.tabList)
|
|
128
|
+
queryWithoutNested("u-tab", this.tabList).forEach((tab) => {
|
|
129
|
+
const isUnselect = tab !== this && tab.ariaSelected === "true";
|
|
130
|
+
const prevPanel = isUnselect && getPanel(tab);
|
|
131
|
+
if (prevPanel && prevPanel !== nextPanel) prevPanel.hidden = true;
|
|
132
|
+
if (isUnselect) {
|
|
133
|
+
tab.ariaSelected = "false";
|
|
134
|
+
tab.tabIndex = -1;
|
|
135
|
+
}
|
|
131
136
|
});
|
|
132
|
-
|
|
133
|
-
|
|
137
|
+
if (name === ARIA_CONTROLS) getPanel(this, prev)?.setAttribute("hidden", "");
|
|
138
|
+
if (this.getAttribute(ARIA_CONTROLS) !== nextPanelId)
|
|
139
|
+
this.setAttribute(ARIA_CONTROLS, nextPanelId);
|
|
140
|
+
this.tabIndex = 0;
|
|
141
|
+
nextPanel?.setAttribute(SAFE_LABELLEDBY, useId(this));
|
|
142
|
+
nextPanel?.removeAttribute("hidden");
|
|
134
143
|
}
|
|
135
144
|
get tabsElement() {
|
|
136
145
|
return this.closest("u-tabs");
|
|
@@ -142,11 +151,12 @@ var UHTMLTabElement = class extends UHTMLElement {
|
|
|
142
151
|
return this.ariaSelected === "true";
|
|
143
152
|
}
|
|
144
153
|
set selected(value) {
|
|
145
|
-
this.ariaSelected = `${value}`;
|
|
154
|
+
this.ariaSelected = `${!!value}`;
|
|
146
155
|
}
|
|
147
156
|
/** Retrieves the ordinal position of an tab in a tablist. */
|
|
148
157
|
get index() {
|
|
149
|
-
|
|
158
|
+
const tabList = this.tabList;
|
|
159
|
+
return tabList ? [...queryWithoutNested("u-tab", tabList)].indexOf(this) : 0;
|
|
150
160
|
}
|
|
151
161
|
get panel() {
|
|
152
162
|
return getPanel(this);
|
|
@@ -159,33 +169,27 @@ var UHTMLTabPanelElement = class extends UHTMLElement {
|
|
|
159
169
|
attachStyle(this, DISPLAY_BLOCK);
|
|
160
170
|
}
|
|
161
171
|
connectedCallback() {
|
|
172
|
+
this.hidden = [...this.tabs].every((tab) => tab.ariaSelected !== "true");
|
|
162
173
|
this.role = "tabpanel";
|
|
163
|
-
this.hidden = Array.from(this.tabs).every((tab) => !tab.selected);
|
|
164
|
-
}
|
|
165
|
-
attributeChangedCallback(_name, prev, next) {
|
|
166
|
-
if (SKIP_ATTR_CHANGE || prev === next)
|
|
167
|
-
return;
|
|
168
|
-
getTabs(this, prev).forEach((tab) => tab.setAttribute(ARIA_CONTROLS, next));
|
|
169
174
|
}
|
|
170
175
|
get tabsElement() {
|
|
171
176
|
return this.closest("u-tabs");
|
|
172
177
|
}
|
|
173
178
|
get tabs() {
|
|
174
|
-
|
|
179
|
+
const css = `u-tab[${ARIA_CONTROLS}="${this.id}"]`;
|
|
180
|
+
const root = getRoot(this).querySelectorAll(css);
|
|
181
|
+
return root.length ? root : document.querySelectorAll(css);
|
|
175
182
|
}
|
|
176
183
|
};
|
|
177
|
-
UHTMLTabPanelElement.observedAttributes = ["id"];
|
|
178
184
|
var queryWithoutNested = (tag, self) => {
|
|
179
|
-
const
|
|
180
|
-
return self.querySelectorAll(
|
|
181
|
-
};
|
|
182
|
-
var getPanel = (self) => {
|
|
183
|
-
const css = `u-tabpanel[id="${self.getAttribute(ARIA_CONTROLS)}"]`;
|
|
184
|
-
return getRoot(self).querySelector(css) || document.querySelector(css);
|
|
185
|
+
const css = `${tag}:not(:scope ${self.nodeName}:not(:scope) ${tag})`;
|
|
186
|
+
return self.querySelectorAll(css);
|
|
185
187
|
};
|
|
186
|
-
var
|
|
187
|
-
|
|
188
|
-
|
|
188
|
+
var getSelectedIndex = (tabs) => [...tabs].findIndex((tab) => tab.ariaSelected === "true");
|
|
189
|
+
var getPanel = (self, id2) => {
|
|
190
|
+
const css = `u-tabpanel[id="${id2 || self.getAttribute(ARIA_CONTROLS)}"]`;
|
|
191
|
+
const tabsElement = self.closest("u-tabs");
|
|
192
|
+
return getRoot(self).querySelector(css) || document.querySelector(css) || tabsElement && queryWithoutNested("u-tabpanel", tabsElement)[[...queryWithoutNested("u-tab", tabsElement)].indexOf(self)] || null;
|
|
189
193
|
};
|
|
190
194
|
customElements.define("u-tabs", UHTMLTabsElement);
|
|
191
195
|
customElements.define("u-tablist", UHTMLTabListElement);
|
|
@@ -74,6 +74,21 @@
|
|
|
74
74
|
"text": "UHTMLTabsElement | null"
|
|
75
75
|
},
|
|
76
76
|
"readonly": true
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"kind": "field",
|
|
80
|
+
"name": "tabs",
|
|
81
|
+
"type": {
|
|
82
|
+
"text": "NodeListOf<UHTMLTabElement>"
|
|
83
|
+
},
|
|
84
|
+
"readonly": true
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"kind": "field",
|
|
88
|
+
"name": "selectedIndex",
|
|
89
|
+
"type": {
|
|
90
|
+
"text": "number"
|
|
91
|
+
}
|
|
77
92
|
}
|
|
78
93
|
],
|
|
79
94
|
"superclass": {
|
|
@@ -166,11 +181,6 @@
|
|
|
166
181
|
"readonly": true
|
|
167
182
|
}
|
|
168
183
|
],
|
|
169
|
-
"attributes": [
|
|
170
|
-
{
|
|
171
|
-
"name": "id"
|
|
172
|
-
}
|
|
173
|
-
],
|
|
174
184
|
"superclass": {
|
|
175
185
|
"name": "UHTMLElement",
|
|
176
186
|
"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": [],
|
|
30
30
|
"references": []
|
|
31
31
|
}
|
|
32
32
|
]
|