@api-client/ui 0.3.1 → 0.3.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/build/src/elements/environment/EnvironmentEditor.d.ts.map +1 -1
- package/build/src/elements/environment/EnvironmentEditor.js +8 -6
- package/build/src/elements/environment/EnvironmentEditor.js.map +1 -1
- package/build/src/elements/har/HarViewer.d.ts.map +1 -1
- package/build/src/elements/har/HarViewer.js +13 -15
- package/build/src/elements/har/HarViewer.js.map +1 -1
- package/build/src/elements/http/RequestEditor.d.ts +2 -1
- package/build/src/elements/http/RequestEditor.d.ts.map +1 -1
- package/build/src/elements/http/RequestEditor.js +17 -12
- package/build/src/elements/http/RequestEditor.js.map +1 -1
- package/build/src/elements/http/RequestLog.d.ts.map +1 -1
- package/build/src/elements/http/RequestLog.js +34 -8
- package/build/src/elements/http/RequestLog.js.map +1 -1
- package/build/src/md/button/internals/button.styles.js +4 -4
- package/build/src/md/button/internals/button.styles.js.map +1 -1
- package/build/src/md/motion/animation.d.ts +5 -3
- package/build/src/md/motion/animation.d.ts.map +1 -1
- package/build/src/md/motion/animation.js +4 -2
- package/build/src/md/motion/animation.js.map +1 -1
- package/build/src/md/ripple/internals/ripple.styles.d.ts.map +1 -1
- package/build/src/md/ripple/internals/ripple.styles.js +20 -8
- package/build/src/md/ripple/internals/ripple.styles.js.map +1 -1
- package/build/src/md/tabs/internals/Tab.d.ts +25 -9
- package/build/src/md/tabs/internals/Tab.d.ts.map +1 -1
- package/build/src/md/tabs/internals/Tab.js +122 -53
- package/build/src/md/tabs/internals/Tab.js.map +1 -1
- package/build/src/md/tabs/internals/Tab.styles.d.ts.map +1 -1
- package/build/src/md/tabs/internals/Tab.styles.js +69 -64
- package/build/src/md/tabs/internals/Tab.styles.js.map +1 -1
- package/build/src/md/tabs/internals/Tabs.d.ts +52 -54
- package/build/src/md/tabs/internals/Tabs.d.ts.map +1 -1
- package/build/src/md/tabs/internals/Tabs.js +270 -330
- package/build/src/md/tabs/internals/Tabs.js.map +1 -1
- package/build/src/md/tabs/internals/Tabs.styles.d.ts.map +1 -1
- package/build/src/md/tabs/internals/Tabs.styles.js +13 -17
- package/build/src/md/tabs/internals/Tabs.styles.js.map +1 -1
- package/build/src/md/text-field/internals/common.styles.d.ts.map +1 -1
- package/build/src/md/text-field/internals/common.styles.js +0 -3
- package/build/src/md/text-field/internals/common.styles.js.map +1 -1
- package/build/src/styles/m3/native.css +270 -0
- package/build/src/styles/m3/theme.css +155 -0
- package/build/src/styles/m3/tokens.css +512 -0
- package/demo/md/tabs/tabs.html +19 -0
- package/demo/md/tabs/tabs.ts +133 -83
- package/package.json +20 -4
- package/scripts/copy-assets.js +21 -0
- package/src/elements/environment/EnvironmentEditor.ts +8 -6
- package/src/elements/har/HarViewer.ts +13 -15
- package/src/elements/http/RequestEditor.ts +18 -13
- package/src/elements/http/RequestLog.ts +34 -8
- package/src/md/button/internals/button.styles.ts +4 -4
- package/src/md/motion/animation.ts +4 -2
- package/src/md/ripple/internals/ripple.styles.ts +20 -8
- package/src/md/tabs/internals/Tab.styles.ts +69 -64
- package/src/md/tabs/internals/Tab.ts +126 -43
- package/src/md/tabs/internals/Tabs.styles.ts +13 -17
- package/src/md/tabs/internals/Tabs.ts +259 -305
- package/src/md/text-field/internals/common.styles.ts +0 -3
- package/test/elements/har/HarViewerElement.test.ts +1 -55
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { __esDecorate, __runInitializers } from "tslib";
|
|
2
|
-
import { html, LitElement
|
|
2
|
+
import { html, LitElement } from 'lit';
|
|
3
3
|
import { property, query, queryAssignedElements, state } from 'lit/decorators.js';
|
|
4
4
|
import { classMap } from 'lit/directives/class-map.js';
|
|
5
5
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
6
6
|
import { Easing } from '../../motion/animation.js';
|
|
7
|
+
import UiTab from './Tab.js';
|
|
7
8
|
import '../../icon-button/ui-icon-button.js';
|
|
8
9
|
import '../../divider/ui-divider.js';
|
|
9
10
|
import '../../icons/ui-icon.js';
|
|
@@ -18,27 +19,21 @@ export function calcPercent(w, w0) {
|
|
|
18
19
|
}
|
|
19
20
|
let UiTabs = (() => {
|
|
20
21
|
let _classSuper = LitElement;
|
|
21
|
-
let
|
|
22
|
-
let
|
|
23
|
-
let
|
|
22
|
+
let _tabs_decorators;
|
|
23
|
+
let _tabs_initializers = [];
|
|
24
|
+
let _tabs_extraInitializers = [];
|
|
25
|
+
let _tabsScrollerElement_decorators;
|
|
26
|
+
let _tabsScrollerElement_initializers = [];
|
|
27
|
+
let _tabsScrollerElement_extraInitializers = [];
|
|
28
|
+
let _slotElement_decorators;
|
|
29
|
+
let _slotElement_initializers = [];
|
|
30
|
+
let _slotElement_extraInitializers = [];
|
|
24
31
|
let _pointer_decorators;
|
|
25
32
|
let _pointer_initializers = [];
|
|
26
33
|
let _pointer_extraInitializers = [];
|
|
27
|
-
let _content_decorators;
|
|
28
|
-
let _content_initializers = [];
|
|
29
|
-
let _content_extraInitializers = [];
|
|
30
34
|
let _priority_decorators;
|
|
31
35
|
let _priority_initializers = [];
|
|
32
36
|
let _priority_extraInitializers = [];
|
|
33
|
-
let _scrollable_decorators;
|
|
34
|
-
let _scrollable_initializers = [];
|
|
35
|
-
let _scrollable_extraInitializers = [];
|
|
36
|
-
let _selected_decorators;
|
|
37
|
-
let _selected_initializers = [];
|
|
38
|
-
let _selected_extraInitializers = [];
|
|
39
|
-
let _selectedAttribute_decorators;
|
|
40
|
-
let _selectedAttribute_initializers = [];
|
|
41
|
-
let _selectedAttribute_extraInitializers = [];
|
|
42
37
|
let _pointerStyles_decorators;
|
|
43
38
|
let _pointerStyles_initializers = [];
|
|
44
39
|
let _pointerStyles_extraInitializers = [];
|
|
@@ -48,87 +43,112 @@ let UiTabs = (() => {
|
|
|
48
43
|
let _isVisible_decorators;
|
|
49
44
|
let _isVisible_initializers = [];
|
|
50
45
|
let _isVisible_extraInitializers = [];
|
|
46
|
+
let _autoActivate_decorators;
|
|
47
|
+
let _autoActivate_initializers = [];
|
|
48
|
+
let _autoActivate_extraInitializers = [];
|
|
51
49
|
return class UiTabs extends _classSuper {
|
|
52
50
|
static {
|
|
53
51
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
54
|
-
|
|
52
|
+
_tabs_decorators = [queryAssignedElements({ flatten: true, selector: 'ui-tab' })];
|
|
53
|
+
_tabsScrollerElement_decorators = [query('.tabs')];
|
|
54
|
+
_slotElement_decorators = [query('slot')];
|
|
55
55
|
_pointer_decorators = [query('.pointer')];
|
|
56
|
-
_content_decorators = [query('.content')];
|
|
57
56
|
_priority_decorators = [property({ type: String, reflect: true })];
|
|
58
|
-
_scrollable_decorators = [property({ type: Boolean })];
|
|
59
|
-
_selected_decorators = [property({ type: String })];
|
|
60
|
-
_selectedAttribute_decorators = [property({ type: String })];
|
|
61
57
|
_pointerStyles_decorators = [state()];
|
|
62
58
|
_indicated_decorators = [state()];
|
|
63
59
|
_isVisible_decorators = [state()];
|
|
64
|
-
|
|
60
|
+
_autoActivate_decorators = [property({ type: Boolean })];
|
|
61
|
+
__esDecorate(this, null, _tabs_decorators, { kind: "accessor", name: "tabs", static: false, private: false, access: { has: obj => "tabs" in obj, get: obj => obj.tabs, set: (obj, value) => { obj.tabs = value; } }, metadata: _metadata }, _tabs_initializers, _tabs_extraInitializers);
|
|
62
|
+
__esDecorate(this, null, _tabsScrollerElement_decorators, { kind: "accessor", name: "tabsScrollerElement", static: false, private: false, access: { has: obj => "tabsScrollerElement" in obj, get: obj => obj.tabsScrollerElement, set: (obj, value) => { obj.tabsScrollerElement = value; } }, metadata: _metadata }, _tabsScrollerElement_initializers, _tabsScrollerElement_extraInitializers);
|
|
63
|
+
__esDecorate(this, null, _slotElement_decorators, { kind: "accessor", name: "slotElement", static: false, private: false, access: { has: obj => "slotElement" in obj, get: obj => obj.slotElement, set: (obj, value) => { obj.slotElement = value; } }, metadata: _metadata }, _slotElement_initializers, _slotElement_extraInitializers);
|
|
65
64
|
__esDecorate(this, null, _pointer_decorators, { kind: "accessor", name: "pointer", static: false, private: false, access: { has: obj => "pointer" in obj, get: obj => obj.pointer, set: (obj, value) => { obj.pointer = value; } }, metadata: _metadata }, _pointer_initializers, _pointer_extraInitializers);
|
|
66
|
-
__esDecorate(this, null, _content_decorators, { kind: "accessor", name: "content", static: false, private: false, access: { has: obj => "content" in obj, get: obj => obj.content, set: (obj, value) => { obj.content = value; } }, metadata: _metadata }, _content_initializers, _content_extraInitializers);
|
|
67
65
|
__esDecorate(this, null, _priority_decorators, { kind: "accessor", name: "priority", static: false, private: false, access: { has: obj => "priority" in obj, get: obj => obj.priority, set: (obj, value) => { obj.priority = value; } }, metadata: _metadata }, _priority_initializers, _priority_extraInitializers);
|
|
68
|
-
__esDecorate(this, null, _scrollable_decorators, { kind: "accessor", name: "scrollable", static: false, private: false, access: { has: obj => "scrollable" in obj, get: obj => obj.scrollable, set: (obj, value) => { obj.scrollable = value; } }, metadata: _metadata }, _scrollable_initializers, _scrollable_extraInitializers);
|
|
69
|
-
__esDecorate(this, null, _selected_decorators, { kind: "accessor", name: "selected", static: false, private: false, access: { has: obj => "selected" in obj, get: obj => obj.selected, set: (obj, value) => { obj.selected = value; } }, metadata: _metadata }, _selected_initializers, _selected_extraInitializers);
|
|
70
|
-
__esDecorate(this, null, _selectedAttribute_decorators, { kind: "accessor", name: "selectedAttribute", static: false, private: false, access: { has: obj => "selectedAttribute" in obj, get: obj => obj.selectedAttribute, set: (obj, value) => { obj.selectedAttribute = value; } }, metadata: _metadata }, _selectedAttribute_initializers, _selectedAttribute_extraInitializers);
|
|
71
66
|
__esDecorate(this, null, _pointerStyles_decorators, { kind: "accessor", name: "pointerStyles", static: false, private: false, access: { has: obj => "pointerStyles" in obj, get: obj => obj.pointerStyles, set: (obj, value) => { obj.pointerStyles = value; } }, metadata: _metadata }, _pointerStyles_initializers, _pointerStyles_extraInitializers);
|
|
72
67
|
__esDecorate(this, null, _indicated_decorators, { kind: "accessor", name: "indicated", static: false, private: false, access: { has: obj => "indicated" in obj, get: obj => obj.indicated, set: (obj, value) => { obj.indicated = value; } }, metadata: _metadata }, _indicated_initializers, _indicated_extraInitializers);
|
|
73
68
|
__esDecorate(this, null, _isVisible_decorators, { kind: "accessor", name: "isVisible", static: false, private: false, access: { has: obj => "isVisible" in obj, get: obj => obj.isVisible, set: (obj, value) => { obj.isVisible = value; } }, metadata: _metadata }, _isVisible_initializers, _isVisible_extraInitializers);
|
|
69
|
+
__esDecorate(this, null, _autoActivate_decorators, { kind: "accessor", name: "autoActivate", static: false, private: false, access: { has: obj => "autoActivate" in obj, get: obj => obj.autoActivate, set: (obj, value) => { obj.autoActivate = value; } }, metadata: _metadata }, _autoActivate_initializers, _autoActivate_extraInitializers);
|
|
74
70
|
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
75
71
|
}
|
|
76
|
-
items = [];
|
|
77
72
|
activeItem = null;
|
|
78
73
|
previousItem = null;
|
|
79
|
-
#assignedElements_accessor_storage = __runInitializers(this, _assignedElements_initializers, void 0);
|
|
80
|
-
get assignedElements() { return this.#assignedElements_accessor_storage; }
|
|
81
|
-
set assignedElements(value) { this.#assignedElements_accessor_storage = value; }
|
|
82
|
-
#pointer_accessor_storage = (__runInitializers(this, _assignedElements_extraInitializers), __runInitializers(this, _pointer_initializers, void 0));
|
|
83
|
-
get pointer() { return this.#pointer_accessor_storage; }
|
|
84
|
-
set pointer(value) { this.#pointer_accessor_storage = value; }
|
|
85
|
-
#content_accessor_storage = (__runInitializers(this, _pointer_extraInitializers), __runInitializers(this, _content_initializers, void 0));
|
|
86
|
-
get content() { return this.#content_accessor_storage; }
|
|
87
|
-
set content(value) { this.#content_accessor_storage = value; }
|
|
88
|
-
#priority_accessor_storage = (__runInitializers(this, _content_extraInitializers), __runInitializers(this, _priority_initializers, 'primary'
|
|
89
74
|
/**
|
|
90
|
-
*
|
|
91
|
-
* @attribute
|
|
75
|
+
* The currently selected tab, `null` only when there are no tab children.
|
|
92
76
|
*/
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
77
|
+
get activeTab() {
|
|
78
|
+
return this.tabs.find((tab) => tab.selected) ?? null;
|
|
79
|
+
}
|
|
80
|
+
set activeTab(tab) {
|
|
81
|
+
// Ignore setting activeTab to null. As long as there are children, one tab
|
|
82
|
+
// must be selected.
|
|
83
|
+
if (tab) {
|
|
84
|
+
this.activateTab(tab);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
103
87
|
/**
|
|
104
|
-
*
|
|
105
|
-
* @attribute
|
|
88
|
+
* The index of the currently selected tab.
|
|
106
89
|
*/
|
|
107
|
-
get
|
|
108
|
-
|
|
109
|
-
|
|
90
|
+
get activeTabIndex() {
|
|
91
|
+
return this.tabs.findIndex((tab) => tab.selected);
|
|
92
|
+
}
|
|
110
93
|
/**
|
|
111
|
-
*
|
|
112
|
-
* This is matched with the `aria-controls` of the tab.
|
|
113
|
-
* @attribute
|
|
94
|
+
* Sets the active tab by index.
|
|
114
95
|
*/
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
96
|
+
set activeTabIndex(index) {
|
|
97
|
+
const activateTabAtIndex = () => {
|
|
98
|
+
const tab = this.tabs[index];
|
|
99
|
+
// Ignore out-of-bound indices.
|
|
100
|
+
if (tab) {
|
|
101
|
+
this.activateTab(tab);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
if (!this.slotElement) {
|
|
105
|
+
// This is needed to support setting the activeTabIndex via a lit property
|
|
106
|
+
// binding.
|
|
107
|
+
//
|
|
108
|
+
// ```ts
|
|
109
|
+
// html`
|
|
110
|
+
// <md-tabs .activeTabIndex=${1}>
|
|
111
|
+
// <md-tab>First</md-tab>
|
|
112
|
+
// <md-tab>Second</md-tab>
|
|
113
|
+
// </md-tabs>
|
|
114
|
+
// `;
|
|
115
|
+
// ```
|
|
116
|
+
//
|
|
117
|
+
// It's needed since lit's rendering lifecycle is asynchronous, and the
|
|
118
|
+
// `<slot>` element hasn't rendered, so `tabs` is empty.
|
|
119
|
+
this.updateComplete.then(activateTabAtIndex);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
activateTabAtIndex();
|
|
123
|
+
}
|
|
124
|
+
get focusedTab() {
|
|
125
|
+
return this.tabs.find((tab) => tab.matches(':focus-within'));
|
|
126
|
+
}
|
|
127
|
+
#tabs_accessor_storage = __runInitializers(this, _tabs_initializers, void 0);
|
|
128
|
+
get tabs() { return this.#tabs_accessor_storage; }
|
|
129
|
+
set tabs(value) { this.#tabs_accessor_storage = value; }
|
|
130
|
+
#tabsScrollerElement_accessor_storage = (__runInitializers(this, _tabs_extraInitializers), __runInitializers(this, _tabsScrollerElement_initializers, void 0));
|
|
131
|
+
get tabsScrollerElement() { return this.#tabsScrollerElement_accessor_storage; }
|
|
132
|
+
set tabsScrollerElement(value) { this.#tabsScrollerElement_accessor_storage = value; }
|
|
133
|
+
#slotElement_accessor_storage = (__runInitializers(this, _tabsScrollerElement_extraInitializers), __runInitializers(this, _slotElement_initializers, void 0));
|
|
134
|
+
get slotElement() { return this.#slotElement_accessor_storage; }
|
|
135
|
+
set slotElement(value) { this.#slotElement_accessor_storage = value; }
|
|
136
|
+
#pointer_accessor_storage = (__runInitializers(this, _slotElement_extraInitializers), __runInitializers(this, _pointer_initializers, void 0));
|
|
137
|
+
get pointer() { return this.#pointer_accessor_storage; }
|
|
138
|
+
set pointer(value) { this.#pointer_accessor_storage = value; }
|
|
139
|
+
#priority_accessor_storage = (__runInitializers(this, _pointer_extraInitializers), __runInitializers(this, _priority_initializers, 'primary'));
|
|
118
140
|
/**
|
|
119
|
-
* The
|
|
120
|
-
* corresponds to which tab.
|
|
141
|
+
* The priority of the tabs.
|
|
121
142
|
*
|
|
122
|
-
* @default
|
|
143
|
+
* @default primary
|
|
123
144
|
* @attribute
|
|
124
145
|
*/
|
|
125
|
-
get
|
|
126
|
-
set
|
|
127
|
-
#pointerStyles_accessor_storage = (__runInitializers(this,
|
|
146
|
+
get priority() { return this.#priority_accessor_storage; }
|
|
147
|
+
set priority(value) { this.#priority_accessor_storage = value; }
|
|
148
|
+
#pointerStyles_accessor_storage = (__runInitializers(this, _priority_extraInitializers), __runInitializers(this, _pointerStyles_initializers, void 0));
|
|
128
149
|
get pointerStyles() { return this.#pointerStyles_accessor_storage; }
|
|
129
150
|
set pointerStyles(value) { this.#pointerStyles_accessor_storage = value; }
|
|
130
|
-
|
|
131
|
-
#indicated_accessor_storage = __runInitializers(this, _indicated_initializers, false);
|
|
151
|
+
#indicated_accessor_storage = (__runInitializers(this, _pointerStyles_extraInitializers), __runInitializers(this, _indicated_initializers, false));
|
|
132
152
|
get indicated() { return this.#indicated_accessor_storage; }
|
|
133
153
|
set indicated(value) { this.#indicated_accessor_storage = value; }
|
|
134
154
|
observer = __runInitializers(this, _indicated_extraInitializers);
|
|
@@ -139,12 +159,23 @@ let UiTabs = (() => {
|
|
|
139
159
|
*/
|
|
140
160
|
get isVisible() { return this.#isVisible_accessor_storage; }
|
|
141
161
|
set isVisible(value) { this.#isVisible_accessor_storage = value; }
|
|
162
|
+
#autoActivate_accessor_storage = (__runInitializers(this, _isVisible_extraInitializers), __runInitializers(this, _autoActivate_initializers, false));
|
|
163
|
+
/**
|
|
164
|
+
* Whether or not to automatically select a tab when it is focused.
|
|
165
|
+
*/
|
|
166
|
+
get autoActivate() { return this.#autoActivate_accessor_storage; }
|
|
167
|
+
set autoActivate(value) { this.#autoActivate_accessor_storage = value; }
|
|
168
|
+
internals = (__runInitializers(this, _autoActivate_extraInitializers), this.attachInternals());
|
|
142
169
|
constructor() {
|
|
143
170
|
super();
|
|
171
|
+
this.internals.role = 'tablist';
|
|
144
172
|
this.observer = new IntersectionObserver(this.intersectionCallback.bind(this), {
|
|
145
173
|
threshold: 1.0,
|
|
146
174
|
rootMargin: '0px',
|
|
147
175
|
});
|
|
176
|
+
this.addEventListener('keydown', this.handleKeydown.bind(this));
|
|
177
|
+
this.addEventListener('keyup', this.handleKeyup.bind(this));
|
|
178
|
+
this.addEventListener('focusout', this.handleFocusout.bind(this));
|
|
148
179
|
}
|
|
149
180
|
willUpdate(cp) {
|
|
150
181
|
if (cp.has('isVisible')) {
|
|
@@ -154,10 +185,10 @@ let UiTabs = (() => {
|
|
|
154
185
|
}
|
|
155
186
|
connectedCallback() {
|
|
156
187
|
super.connectedCallback();
|
|
188
|
+
this.observer.observe(this);
|
|
157
189
|
if (!this.hasAttribute('role')) {
|
|
158
190
|
this.setAttribute('role', 'tablist');
|
|
159
191
|
}
|
|
160
|
-
this.observer.observe(this);
|
|
161
192
|
}
|
|
162
193
|
disconnectedCallback() {
|
|
163
194
|
super.disconnectedCallback();
|
|
@@ -167,97 +198,28 @@ let UiTabs = (() => {
|
|
|
167
198
|
const [entry] = entries;
|
|
168
199
|
this.isVisible = entry.isIntersecting;
|
|
169
200
|
}
|
|
170
|
-
async updateItems() {
|
|
171
|
-
const elements = this.assignedElements || [];
|
|
172
|
-
const items = elements.filter(this.isTabItem, this);
|
|
173
|
-
this.items = items;
|
|
174
|
-
if (this.activeItem && !items.includes(this.activeItem)) {
|
|
175
|
-
this.activeItem = null;
|
|
176
|
-
}
|
|
177
|
-
await this.updateComplete;
|
|
178
|
-
this.ensureSelection();
|
|
179
|
-
}
|
|
180
201
|
/**
|
|
181
|
-
*
|
|
202
|
+
* Scrolls the toolbar, if overflowing, to the active tab, or the provided
|
|
203
|
+
* tab.
|
|
204
|
+
*
|
|
205
|
+
* @param tabToScrollTo The tab that should be scrolled to. Defaults to the
|
|
206
|
+
* active tab.
|
|
207
|
+
* @return A Promise that resolves after the tab has been scrolled to.
|
|
182
208
|
*/
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
isSelectable(element) {
|
|
190
|
-
if (element.disabled) {
|
|
191
|
-
return false;
|
|
192
|
-
}
|
|
193
|
-
if (element.hidden && element.hasAttribute('hidden')) {
|
|
194
|
-
return false;
|
|
195
|
-
}
|
|
196
|
-
return true;
|
|
197
|
-
}
|
|
198
|
-
ensureSelection() {
|
|
199
|
-
const { selected, selectedAttribute, activeItem, items } = this;
|
|
200
|
-
if (!selectedAttribute) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
const item = items.find((i) => i.getAttribute(selectedAttribute) === selected);
|
|
204
|
-
if (item && item === activeItem) {
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
this.makeSelection(item);
|
|
208
|
-
}
|
|
209
|
-
makeSelection(tab, focus = false) {
|
|
210
|
-
const { activeItem } = this;
|
|
211
|
-
if (activeItem === tab) {
|
|
212
|
-
tab.highlight();
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
this.previousItem = activeItem;
|
|
216
|
-
if (activeItem) {
|
|
217
|
-
this.deselectItem(activeItem);
|
|
218
|
-
}
|
|
219
|
-
if (tab) {
|
|
220
|
-
this.selectItem(tab, focus);
|
|
221
|
-
this.positionPointer(tab, activeItem);
|
|
222
|
-
if (this.activeItem) {
|
|
223
|
-
// we set this here so we won't notify selection when initializing.
|
|
224
|
-
this.notifySelect(tab);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
notifySelect(item) {
|
|
229
|
-
const index = this.items.indexOf(item);
|
|
230
|
-
if (index === -1) {
|
|
209
|
+
async scrollToTab(tabToScrollTo) {
|
|
210
|
+
await this.updateComplete;
|
|
211
|
+
const { tabs } = this;
|
|
212
|
+
tabToScrollTo ??= this.activeTab;
|
|
213
|
+
if (!tabToScrollTo || !tabs.includes(tabToScrollTo) || !this.tabsScrollerElement) {
|
|
231
214
|
return;
|
|
232
215
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}));
|
|
241
|
-
}
|
|
242
|
-
selectItem(tab, focus = false) {
|
|
243
|
-
this.activeItem = tab;
|
|
244
|
-
if (this.hasAttribute('tabindex')) {
|
|
245
|
-
this.removeAttribute('tabindex');
|
|
246
|
-
}
|
|
247
|
-
tab.setAttribute('aria-selected', 'true');
|
|
248
|
-
tab.setAttribute('tabindex', '0');
|
|
249
|
-
tab.selected = true;
|
|
250
|
-
tab.priority = this.priority;
|
|
251
|
-
tab.scrollIntoView({ inline: 'nearest', behavior: 'auto', block: 'nearest' });
|
|
252
|
-
if (focus) {
|
|
253
|
-
tab.focus();
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
deselectItem(tab) {
|
|
257
|
-
tab.setAttribute('aria-selected', 'false');
|
|
258
|
-
tab.setAttribute('tabindex', '-1');
|
|
259
|
-
tab.selected = false;
|
|
260
|
-
tab.indicated = false;
|
|
216
|
+
// wait for tabs to render.
|
|
217
|
+
await Promise.all(tabs.map((tab) => tab.updateComplete));
|
|
218
|
+
tabToScrollTo.scrollIntoView({
|
|
219
|
+
block: 'nearest',
|
|
220
|
+
inline: 'nearest',
|
|
221
|
+
behavior: !this.focusedTab ? 'instant' : 'auto',
|
|
222
|
+
});
|
|
261
223
|
}
|
|
262
224
|
handleVisibility() {
|
|
263
225
|
const { previousItem, activeItem } = this;
|
|
@@ -267,11 +229,12 @@ let UiTabs = (() => {
|
|
|
267
229
|
this.positionPointer(activeItem, previousItem);
|
|
268
230
|
}
|
|
269
231
|
async positionPointer(tab, old) {
|
|
270
|
-
const {
|
|
232
|
+
const { pointer, isVisible } = this;
|
|
271
233
|
if (!isVisible) {
|
|
234
|
+
tab.indicated = true;
|
|
272
235
|
return;
|
|
273
236
|
}
|
|
274
|
-
const index =
|
|
237
|
+
const index = this.tabs.indexOf(tab);
|
|
275
238
|
if (index < 0 || !pointer) {
|
|
276
239
|
this.pointerStyles = undefined;
|
|
277
240
|
return;
|
|
@@ -282,27 +245,29 @@ let UiTabs = (() => {
|
|
|
282
245
|
return;
|
|
283
246
|
}
|
|
284
247
|
const isPrimary = this.priority === 'primary';
|
|
285
|
-
const final =
|
|
286
|
-
if (this.pointerStyles && this.pointerStyles.left === `${final}px`) {
|
|
248
|
+
const final = this.getTabSizing(tab);
|
|
249
|
+
if (this.pointerStyles && this.pointerStyles.left === `${final.left}px`) {
|
|
250
|
+
tab.indicated = true;
|
|
287
251
|
return;
|
|
288
252
|
}
|
|
289
253
|
// first position this indicator in the place of the old one.
|
|
290
254
|
// update the view and then run the animation.
|
|
291
255
|
this.indicated = true;
|
|
292
|
-
const
|
|
293
|
-
this.pointerStyles = { left };
|
|
256
|
+
const starting = this.getTabSizing(old);
|
|
257
|
+
this.pointerStyles = { left: `${starting.left}px`, width: `${starting.width}px` };
|
|
294
258
|
await this.updateComplete;
|
|
295
|
-
const frames = isPrimary ? this.getPrimaryKeyframes(
|
|
259
|
+
const frames = isPrimary ? this.getPrimaryKeyframes(starting, final) : this.getSecondaryKeyframes(starting, final);
|
|
296
260
|
if (this.moveAnimation) {
|
|
297
261
|
this.moveAnimation.cancel();
|
|
298
262
|
}
|
|
299
263
|
const moveAnimation = pointer.animate(frames, {
|
|
300
|
-
duration:
|
|
264
|
+
duration: 200,
|
|
301
265
|
iterations: 1,
|
|
302
|
-
easing: Easing.
|
|
266
|
+
easing: Easing.EMPHASIZED_DECELERATE,
|
|
303
267
|
});
|
|
304
268
|
const finalStyles = {
|
|
305
|
-
left: `${final}px`,
|
|
269
|
+
left: `${final.left}px`,
|
|
270
|
+
width: `${final.width}px`,
|
|
306
271
|
};
|
|
307
272
|
moveAnimation.addEventListener('finish', () => {
|
|
308
273
|
this.pointerStyles = finalStyles;
|
|
@@ -315,186 +280,180 @@ let UiTabs = (() => {
|
|
|
315
280
|
});
|
|
316
281
|
this.moveAnimation = moveAnimation;
|
|
317
282
|
}
|
|
318
|
-
moveAnimation
|
|
319
|
-
|
|
320
|
-
const contentBox = this.
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
const left = leftFromParent + tabRect.width / 2 - 20 + offset;
|
|
325
|
-
return `${left}px`;
|
|
326
|
-
}
|
|
327
|
-
getSecondaryLeft(tab) {
|
|
328
|
-
const contentBox = this.content.getBoundingClientRect();
|
|
329
|
-
const tabRect = tab.getBoundingClientRect();
|
|
330
|
-
const offset = this.scrollable ? 48 : 0; // left button
|
|
331
|
-
const leftFromParent = tabRect.x - contentBox.x + offset;
|
|
332
|
-
return `${leftFromParent}px`;
|
|
283
|
+
moveAnimation;
|
|
284
|
+
getTabSizing(tab) {
|
|
285
|
+
const contentBox = this.tabsScrollerElement.getBoundingClientRect();
|
|
286
|
+
const sizing = tab.getIndicatorSizing();
|
|
287
|
+
sizing.left = sizing.left - contentBox.x;
|
|
288
|
+
return sizing;
|
|
333
289
|
}
|
|
334
290
|
getPrimaryKeyframes(start, final) {
|
|
335
291
|
return [
|
|
336
292
|
{
|
|
337
|
-
left: start
|
|
338
|
-
width:
|
|
339
|
-
},
|
|
340
|
-
{
|
|
341
|
-
width: `80px`,
|
|
293
|
+
left: `${start.left}px`,
|
|
294
|
+
width: `${start.width}px`,
|
|
342
295
|
},
|
|
343
296
|
{
|
|
344
|
-
left: final
|
|
345
|
-
width:
|
|
297
|
+
left: `${final.left}px`,
|
|
298
|
+
width: `${final.width}px`,
|
|
346
299
|
},
|
|
347
300
|
];
|
|
348
301
|
}
|
|
349
302
|
getSecondaryKeyframes(start, final) {
|
|
350
303
|
return [
|
|
351
304
|
{
|
|
352
|
-
left: start
|
|
305
|
+
left: `${start.left}px`,
|
|
306
|
+
width: `${start.width}px`,
|
|
353
307
|
},
|
|
354
308
|
{
|
|
355
|
-
left: final
|
|
309
|
+
left: `${final.left}px`,
|
|
310
|
+
width: `${final.width}px`,
|
|
356
311
|
},
|
|
357
312
|
];
|
|
358
313
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
if (
|
|
364
|
-
|
|
314
|
+
async handleTabClick(e) {
|
|
315
|
+
const tab = e.composedPath().find((el) => isTab(el));
|
|
316
|
+
// Allow event to bubble
|
|
317
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
318
|
+
if (e.defaultPrevented || !tab || tab.selected) {
|
|
319
|
+
return;
|
|
365
320
|
}
|
|
321
|
+
this.activateTab(tab);
|
|
366
322
|
}
|
|
367
|
-
|
|
368
|
-
const {
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
if (!next) {
|
|
374
|
-
break;
|
|
375
|
-
}
|
|
376
|
-
if (items.includes(next)) {
|
|
377
|
-
item = next;
|
|
378
|
-
}
|
|
323
|
+
activateTab(activeTab) {
|
|
324
|
+
const { tabs } = this;
|
|
325
|
+
const previousTab = this.activeTab;
|
|
326
|
+
if (!tabs.includes(activeTab) || previousTab === activeTab) {
|
|
327
|
+
// Ignore setting activeTab to a tab element that is not a child.
|
|
328
|
+
return;
|
|
379
329
|
}
|
|
380
|
-
|
|
330
|
+
for (const tab of tabs) {
|
|
331
|
+
tab.selected = tab === activeTab;
|
|
332
|
+
}
|
|
333
|
+
if (previousTab) {
|
|
334
|
+
// Don't dispatch a change event if activating a tab when no previous tabs
|
|
335
|
+
// were selected, such as when md-tabs auto-selects the first tab.
|
|
336
|
+
const detail = {
|
|
337
|
+
item: activeTab,
|
|
338
|
+
index: this.tabs.indexOf(activeTab),
|
|
339
|
+
};
|
|
340
|
+
const defaultPrevented = !this.dispatchEvent(new CustomEvent('change', { detail, bubbles: false, cancelable: true }));
|
|
341
|
+
if (defaultPrevented) {
|
|
342
|
+
for (const tab of tabs) {
|
|
343
|
+
tab.selected = tab === previousTab;
|
|
344
|
+
}
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
previousTab.indicated = false;
|
|
348
|
+
}
|
|
349
|
+
activeTab.indicated = false;
|
|
350
|
+
this.positionPointer(activeTab, previousTab);
|
|
351
|
+
this.updateFocusableTab(activeTab);
|
|
352
|
+
this.scrollToTab(activeTab);
|
|
353
|
+
}
|
|
354
|
+
updateFocusableTab(focusableTab) {
|
|
355
|
+
for (const tab of this.tabs) {
|
|
356
|
+
tab.tabIndex = tab === focusableTab ? 0 : -1;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
async handleKeydown(event) {
|
|
360
|
+
// Allow event to bubble.
|
|
361
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
362
|
+
const isLeft = event.key === 'ArrowLeft';
|
|
363
|
+
const isRight = event.key === 'ArrowRight';
|
|
364
|
+
const isHome = event.key === 'Home';
|
|
365
|
+
const isEnd = event.key === 'End';
|
|
366
|
+
// Ignore non-navigation keys
|
|
367
|
+
if (event.defaultPrevented || (!isLeft && !isRight && !isHome && !isEnd)) {
|
|
381
368
|
return;
|
|
382
369
|
}
|
|
383
|
-
this
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
const { contentScroll = 0, content } = this;
|
|
387
|
-
if (contentScroll === 0) {
|
|
370
|
+
const { tabs } = this;
|
|
371
|
+
// Don't try to select another tab if there aren't any.
|
|
372
|
+
if (tabs.length < 2) {
|
|
388
373
|
return;
|
|
389
374
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
375
|
+
// Prevent default interactions, such as scrolling.
|
|
376
|
+
event.preventDefault();
|
|
377
|
+
let indexToFocus;
|
|
378
|
+
if (isHome || isEnd) {
|
|
379
|
+
indexToFocus = isHome ? 0 : tabs.length - 1;
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
// Check if moving forwards or backwards
|
|
383
|
+
const isRtl = getComputedStyle(this).direction === 'rtl';
|
|
384
|
+
const forwards = isRtl ? isLeft : isRight;
|
|
385
|
+
const { focusedTab } = this;
|
|
386
|
+
if (!focusedTab) {
|
|
387
|
+
// If there is not already a tab focused, select the first or last tab
|
|
388
|
+
// based on the direction we're traveling.
|
|
389
|
+
indexToFocus = forwards ? 0 : tabs.length - 1;
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
const focusedIndex = this.tabs.indexOf(focusedTab);
|
|
393
|
+
indexToFocus = forwards ? focusedIndex + 1 : focusedIndex - 1;
|
|
394
|
+
if (indexToFocus >= tabs.length) {
|
|
395
|
+
// Return to start if moving past the last item.
|
|
396
|
+
indexToFocus = 0;
|
|
397
|
+
}
|
|
398
|
+
else if (indexToFocus < 0) {
|
|
399
|
+
// Go to end if moving before the first item.
|
|
400
|
+
indexToFocus = tabs.length - 1;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
const tabToFocus = tabs[indexToFocus];
|
|
405
|
+
tabToFocus.focus();
|
|
406
|
+
if (this.autoActivate) {
|
|
407
|
+
this.activateTab(tabToFocus);
|
|
393
408
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
behavior: 'smooth',
|
|
397
|
-
left,
|
|
398
|
-
});
|
|
399
|
-
}
|
|
400
|
-
handleScrollRight() {
|
|
401
|
-
const { contentScroll = 0, content } = this;
|
|
402
|
-
let left = contentScroll + 80;
|
|
403
|
-
if (left + content.clientWidth > content.scrollWidth) {
|
|
404
|
-
left = content.scrollWidth - content.clientWidth;
|
|
409
|
+
else {
|
|
410
|
+
this.updateFocusableTab(tabToFocus);
|
|
405
411
|
}
|
|
406
|
-
this.contentScroll = left;
|
|
407
|
-
content.scrollTo({
|
|
408
|
-
behavior: 'smooth',
|
|
409
|
-
left,
|
|
410
|
-
});
|
|
411
412
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
this.
|
|
413
|
+
// scroll to item on keyup.
|
|
414
|
+
handleKeyup() {
|
|
415
|
+
this.scrollToTab(this.focusedTab ?? this.activeTab);
|
|
415
416
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
this.makeSelection(tab, true);
|
|
417
|
+
handleFocusout() {
|
|
418
|
+
// restore focus to selected item when blurring the tab bar.
|
|
419
|
+
if (this.matches(':focus-within')) {
|
|
420
|
+
return;
|
|
421
421
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
this.makeSelection(tab, true);
|
|
422
|
+
const { activeTab } = this;
|
|
423
|
+
if (activeTab) {
|
|
424
|
+
this.updateFocusableTab(activeTab);
|
|
426
425
|
}
|
|
427
426
|
}
|
|
428
|
-
|
|
429
|
-
const
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
}
|
|
434
|
-
let i = curIndex;
|
|
435
|
-
let result;
|
|
436
|
-
do {
|
|
437
|
-
i--;
|
|
438
|
-
if (i === curIndex) {
|
|
439
|
-
// looped back from the end, no active element to find.
|
|
440
|
-
return item;
|
|
441
|
-
}
|
|
442
|
-
const tmp = items[i];
|
|
443
|
-
if (!tmp) {
|
|
444
|
-
i = items.length;
|
|
445
|
-
continue;
|
|
446
|
-
}
|
|
447
|
-
if (this.isSelectable(tmp)) {
|
|
448
|
-
result = tmp;
|
|
427
|
+
handleSlotChange() {
|
|
428
|
+
for (const tab of this.tabs) {
|
|
429
|
+
tab.priority = this.priority;
|
|
430
|
+
if (tab.selected) {
|
|
431
|
+
tab.indicated = true;
|
|
449
432
|
}
|
|
450
|
-
} while (!result);
|
|
451
|
-
return result || item;
|
|
452
|
-
}
|
|
453
|
-
getNextItem(item) {
|
|
454
|
-
const { items } = this;
|
|
455
|
-
const curIndex = items.indexOf(item);
|
|
456
|
-
if (curIndex < 0) {
|
|
457
|
-
return item;
|
|
458
433
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
if (this.isSelectable(tmp)) {
|
|
473
|
-
next = tmp;
|
|
474
|
-
}
|
|
475
|
-
} while (!next);
|
|
476
|
-
return next || item;
|
|
434
|
+
const firstTab = this.tabs[0];
|
|
435
|
+
if (!this.activeTab && firstTab) {
|
|
436
|
+
// If the active tab was removed, auto-select the first one. There should
|
|
437
|
+
// always be a selected tab while the bar has children.
|
|
438
|
+
this.activateTab(firstTab);
|
|
439
|
+
}
|
|
440
|
+
// When children shift, ensure the active tab is visible. For example, if
|
|
441
|
+
// many children are added before the active tab, it'd be pushed off screen.
|
|
442
|
+
// This ensures it stays visible.
|
|
443
|
+
this.scrollToTab(this.activeTab);
|
|
444
|
+
if (this.activeTab) {
|
|
445
|
+
this.updateFocusableTab(this.activeTab);
|
|
446
|
+
}
|
|
477
447
|
}
|
|
478
448
|
render() {
|
|
479
|
-
const classes = {
|
|
480
|
-
surface: true,
|
|
481
|
-
scrollable: !!this.scrollable,
|
|
482
|
-
};
|
|
483
449
|
return html `
|
|
484
|
-
<div class="
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
${this.rightScrollControl()} ${this.renderIndicator()}
|
|
488
|
-
<div class="divider"></div>
|
|
489
|
-
</div>
|
|
450
|
+
<div class="tabs">${this.renderSlot()}</div>
|
|
451
|
+
${this.renderIndicator()}
|
|
452
|
+
<ui-divider class="divider"></ui-divider>
|
|
490
453
|
`;
|
|
491
454
|
}
|
|
492
455
|
renderSlot() {
|
|
493
|
-
return html `<slot
|
|
494
|
-
@slotchange="${this.updateItems}"
|
|
495
|
-
@click="${this.contentClickHandler}"
|
|
496
|
-
@keydown="${this.contentKeyDownHandler}"
|
|
497
|
-
></slot>`;
|
|
456
|
+
return html `<slot @slotchange="${this.handleSlotChange}" @click="${this.handleTabClick}"></slot>`;
|
|
498
457
|
}
|
|
499
458
|
renderIndicator() {
|
|
500
459
|
const classes = {
|
|
@@ -509,34 +468,15 @@ let UiTabs = (() => {
|
|
|
509
468
|
</div>
|
|
510
469
|
`;
|
|
511
470
|
}
|
|
512
|
-
renderLeftScrollControl() {
|
|
513
|
-
if (!this.scrollable) {
|
|
514
|
-
return nothing;
|
|
515
|
-
}
|
|
516
|
-
return html ` <div class="scroll-control left">
|
|
517
|
-
<ui-icon-button aria-label="Scroll tabs left" title="Scroll tabs left" @click="${this.handleScrollLeft}">
|
|
518
|
-
<ui-icon icon="chevronLeft"></ui-icon>
|
|
519
|
-
</ui-icon-button>
|
|
520
|
-
</div>`;
|
|
521
|
-
}
|
|
522
|
-
rightScrollControl() {
|
|
523
|
-
if (!this.scrollable) {
|
|
524
|
-
return nothing;
|
|
525
|
-
}
|
|
526
|
-
return html `<div class="scroll-control right">
|
|
527
|
-
<ui-icon-button aria-label="Scroll tabs right" title="Scroll tabs right" @click="${this.handleScrollRight}">
|
|
528
|
-
<ui-icon icon="chevronRight"></ui-icon>
|
|
529
|
-
</ui-icon-button>
|
|
530
|
-
</div>`;
|
|
531
|
-
}
|
|
532
471
|
};
|
|
533
472
|
})();
|
|
534
473
|
/**
|
|
535
474
|
* A container for tabs.
|
|
536
475
|
*
|
|
537
|
-
* @fires
|
|
538
|
-
* The `event.detail` object contains the `item` and `index` properties.
|
|
539
|
-
* It also has the `select` property with the value of the `selectedAttribute` on the tab.
|
|
476
|
+
* @fires change - A non bubbling event when selection change through user interaction.
|
|
540
477
|
*/
|
|
541
478
|
export default UiTabs;
|
|
479
|
+
function isTab(element) {
|
|
480
|
+
return element instanceof UiTab;
|
|
481
|
+
}
|
|
542
482
|
//# sourceMappingURL=Tabs.js.map
|