@brightspace-ui/core 3.316.0 → 3.317.1
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/components/tabs/README.md +0 -5
- package/components/tabs/tab-panel-mixin.js +0 -40
- package/components/tabs/tabs.js +315 -650
- package/custom-elements.json +1 -111
- package/package.json +1 -1
- package/components/tabs/tab-internal.js +0 -144
package/components/tabs/tabs.js
CHANGED
|
@@ -1,24 +1,17 @@
|
|
|
1
1
|
import '../colors/colors.js';
|
|
2
2
|
import '../icons/icon.js';
|
|
3
|
-
import '
|
|
4
|
-
import { css, html, LitElement, nothing, unsafeCSS } from 'lit';
|
|
3
|
+
import { css, html, LitElement, unsafeCSS } from 'lit';
|
|
5
4
|
import { findComposedAncestor, getOffsetParent, isVisible } from '../../helpers/dom.js';
|
|
6
5
|
import { getFocusPseudoClass, getFocusRingStyles } from '../../helpers/focus.js';
|
|
7
6
|
import { ArrowKeysMixin } from '../../mixins/arrow-keys/arrow-keys-mixin.js';
|
|
8
7
|
import { bodyCompactStyles } from '../typography/styles.js';
|
|
9
8
|
import { classMap } from 'lit/directives/class-map.js';
|
|
10
|
-
import { getFlag } from '../../helpers/flags.js';
|
|
11
9
|
import { getOverflowDeclarations } from '../../helpers/overflow.js';
|
|
12
10
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
13
11
|
import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
|
|
14
|
-
import { repeat } from 'lit/directives/repeat.js';
|
|
15
12
|
import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
|
|
16
13
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
17
14
|
|
|
18
|
-
export function getUseNewTabsStructureFlag() {
|
|
19
|
-
return getFlag('GAUD-8299-core-tabs-use-new-structure', true);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
15
|
const reduceMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
23
16
|
|
|
24
17
|
const scrollButtonWidth = 56;
|
|
@@ -30,7 +23,6 @@ function getOffsetLeft(tab, tabRect) {
|
|
|
30
23
|
|
|
31
24
|
/**
|
|
32
25
|
* A component for tabbed content. It supports the "d2l-tab" component and "TabMixin" consumers for tabs, the "d2l-tab-panel" component for the tab content, renders tabs responsively, and provides virtual scrolling for large tab lists.
|
|
33
|
-
* @slot - DEPRECATED: Contains the tab panels (e.g., "d2l-tab-panel" components)
|
|
34
26
|
* @slot ext - Additional content (e.g., a button) positioned at right
|
|
35
27
|
* @slot tabs - Contains the tabs (e.g., "d2l-tab" components or custom components that use `TabMixin`)
|
|
36
28
|
* @slot panels - Contains the tab panels (e.g., "d2l-tab-panel" components)
|
|
@@ -50,11 +42,9 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
50
42
|
text: { type: String },
|
|
51
43
|
_allowScrollNext: { type: Boolean },
|
|
52
44
|
_allowScrollPrevious: { type: Boolean },
|
|
53
|
-
_defaultSlotBehavior: { state: true },
|
|
54
45
|
_maxWidth: { type: Number },
|
|
55
46
|
_scrollCollapsed: { type: Boolean },
|
|
56
47
|
_state: { type: String },
|
|
57
|
-
_tabInfos: { type: Array },
|
|
58
48
|
_translationValue: {}
|
|
59
49
|
};
|
|
60
50
|
|
|
@@ -169,12 +159,10 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
169
159
|
transition: margin-top 200ms ease-out;
|
|
170
160
|
}
|
|
171
161
|
|
|
172
|
-
|
|
162
|
+
::slotted([role="tab"]) {
|
|
173
163
|
-webkit-transition: max-width 200ms ease-out, opacity 200ms ease-out, transform 200ms ease-out;
|
|
174
164
|
transition: max-width 200ms ease-out, opacity 200ms ease-out, transform 200ms ease-out;
|
|
175
165
|
}
|
|
176
|
-
d2l-tab-internal[data-state="adding"],
|
|
177
|
-
d2l-tab-internal[data-state="removing"],
|
|
178
166
|
::slotted([role="tab"][data-state="adding"]),
|
|
179
167
|
::slotted([role="tab"][data-state="removing"]) {
|
|
180
168
|
max-width: 0;
|
|
@@ -200,7 +188,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
200
188
|
-webkit-transition: none;
|
|
201
189
|
transition: none;
|
|
202
190
|
}
|
|
203
|
-
|
|
191
|
+
::slotted([role="tab"]) {
|
|
204
192
|
-webkit-transition: none;
|
|
205
193
|
transition: none;
|
|
206
194
|
}
|
|
@@ -229,21 +217,13 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
229
217
|
this.maxToShow = -1;
|
|
230
218
|
this._allowScrollNext = false;
|
|
231
219
|
this._allowScrollPrevious = false;
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
* Remove this._defaultSlotBehavior and related code with GAUD-8299-core-tabs-use-new-structure flag clean up
|
|
235
|
-
* NOTE: remove the TRUE case of _defaultSlotBehavior
|
|
236
|
-
*/
|
|
237
|
-
this._defaultSlotBehavior = !this.#newTabsPanelStructure;
|
|
238
|
-
|
|
239
|
-
this._loadingCompleteResolve = undefined;
|
|
240
|
-
this._loadingCompletePromise = new Promise(resolve => this._loadingCompleteResolve = resolve);
|
|
220
|
+
this.#loadingCompleteResolve = undefined;
|
|
221
|
+
this.#loadingCompletePromise = new Promise(resolve => this.#loadingCompleteResolve = resolve);
|
|
241
222
|
this._maxWidth = null;
|
|
242
223
|
this._scrollCollapsed = false;
|
|
243
224
|
this._state = 'shown';
|
|
244
|
-
this
|
|
245
|
-
this
|
|
246
|
-
if (this._defaultSlotBehavior) this._tabInfos = [];
|
|
225
|
+
this.#tabIds = {};
|
|
226
|
+
this.#tabs = [];
|
|
247
227
|
this._translationValue = 0;
|
|
248
228
|
}
|
|
249
229
|
|
|
@@ -251,7 +231,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
251
231
|
super.connectedCallback();
|
|
252
232
|
|
|
253
233
|
queueMicrotask(() => {
|
|
254
|
-
const bgColor = this
|
|
234
|
+
const bgColor = this.#getComputedBackgroundColor();
|
|
255
235
|
if (bgColor && bgColor !== 'rgb(255, 255, 255)' && bgColor !== 'rgba(255, 255, 255, 1)') {
|
|
256
236
|
this.style.setProperty('--d2l-tabs-background-color', bgColor);
|
|
257
237
|
}
|
|
@@ -261,75 +241,45 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
261
241
|
|
|
262
242
|
disconnectedCallback() {
|
|
263
243
|
super.disconnectedCallback();
|
|
264
|
-
if (this
|
|
244
|
+
if (this.#resizeObserver) this.#resizeObserver.disconnect();
|
|
265
245
|
}
|
|
266
246
|
|
|
267
247
|
firstUpdated(changedProperties) {
|
|
268
248
|
super.firstUpdated(changedProperties);
|
|
269
249
|
|
|
270
250
|
this.arrowKeysFocusablesProvider = async() => {
|
|
271
|
-
return this
|
|
251
|
+
return this.#tabs;
|
|
272
252
|
};
|
|
273
253
|
|
|
274
254
|
this.arrowKeysOnBeforeFocus = async(tab) => {
|
|
275
|
-
|
|
276
|
-
// remove this section with GAUD-8299-core-tabs-use-new-structure flag clean up
|
|
277
|
-
const tabInfo = this._getTabInfo(tab.controlsPanel);
|
|
278
|
-
this._setFocusableDefaultSlotBehavior(tabInfo);
|
|
255
|
+
this.#setFocusable(tab);
|
|
279
256
|
|
|
280
|
-
|
|
281
|
-
|
|
257
|
+
this.requestUpdate();
|
|
258
|
+
await this.updateComplete;
|
|
282
259
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
} else {
|
|
286
|
-
const measures = this._getMeasures();
|
|
287
|
-
const newTranslationValue = this._calculateScrollPositionDefaultSlotBehavior(tabInfo, measures);
|
|
288
|
-
|
|
289
|
-
if (!this.#isRTL()) {
|
|
290
|
-
if (newTranslationValue >= 0) return;
|
|
291
|
-
} else {
|
|
292
|
-
if (newTranslationValue <= 0) return;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const expanded = await this._tryExpandTabsContainer(measures);
|
|
296
|
-
if (expanded) {
|
|
297
|
-
return;
|
|
298
|
-
} else {
|
|
299
|
-
return this._updateScrollPositionDefaultSlotBehavior(tabInfo);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
260
|
+
if (!this._scrollCollapsed) {
|
|
261
|
+
return this.#updateScrollPosition(tab);
|
|
302
262
|
} else {
|
|
303
|
-
this
|
|
263
|
+
const measures = this.#getMeasures();
|
|
264
|
+
const newTranslationValue = this.#calculateScrollPosition(tab, measures);
|
|
304
265
|
|
|
305
|
-
this
|
|
306
|
-
|
|
266
|
+
if (!this.#isRTL()) {
|
|
267
|
+
if (newTranslationValue >= 0) return;
|
|
268
|
+
} else {
|
|
269
|
+
if (newTranslationValue <= 0) return;
|
|
270
|
+
}
|
|
307
271
|
|
|
308
|
-
|
|
309
|
-
|
|
272
|
+
const expanded = await this.#tryExpandTabsContainer(measures);
|
|
273
|
+
if (expanded) {
|
|
274
|
+
return;
|
|
310
275
|
} else {
|
|
311
|
-
|
|
312
|
-
const newTranslationValue = this._calculateScrollPosition(tab, measures);
|
|
313
|
-
|
|
314
|
-
if (!this.#isRTL()) {
|
|
315
|
-
if (newTranslationValue >= 0) return;
|
|
316
|
-
} else {
|
|
317
|
-
if (newTranslationValue <= 0) return;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
const expanded = await this._tryExpandTabsContainer(measures);
|
|
321
|
-
if (expanded) {
|
|
322
|
-
return;
|
|
323
|
-
} else {
|
|
324
|
-
return this._updateScrollPosition(tab);
|
|
325
|
-
}
|
|
276
|
+
return this.#updateScrollPosition(tab);
|
|
326
277
|
}
|
|
327
278
|
}
|
|
328
279
|
};
|
|
329
280
|
|
|
330
|
-
this
|
|
331
|
-
this.
|
|
332
|
-
this._resizeObserver.observe(this.shadowRoot.querySelector('.d2l-tabs-container-list'));
|
|
281
|
+
this.#resizeObserver = new ResizeObserver(this.#handleResize);
|
|
282
|
+
this.#resizeObserver.observe(this.shadowRoot.querySelector('.d2l-tabs-container-list'));
|
|
333
283
|
|
|
334
284
|
}
|
|
335
285
|
|
|
@@ -362,36 +312,27 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
362
312
|
style="${styleMap(tabsContainerStyles)}">
|
|
363
313
|
<div class="d2l-tabs-scroll-previous-container">
|
|
364
314
|
<button class="d2l-tabs-scroll-button"
|
|
365
|
-
@click="${this
|
|
315
|
+
@click="${this.#handleScrollPrevious}"
|
|
366
316
|
title="${this.localize('components.tabs.previous')}">
|
|
367
317
|
<d2l-icon icon="tier1:chevron-left"></d2l-icon>
|
|
368
318
|
</button>
|
|
369
319
|
</div>
|
|
370
320
|
${this.arrowKeysContainer(html`
|
|
371
321
|
<div class="d2l-tabs-container-list"
|
|
372
|
-
@d2l-tab-content-change="${this
|
|
322
|
+
@d2l-tab-content-change="${this.#handleTabContentChange}"
|
|
373
323
|
@d2l-tab-hidden-change="${this.#handleTabHiddenChange}"
|
|
374
|
-
@d2l-tab-selected="${this
|
|
324
|
+
@d2l-tab-selected="${this.#handleTabSelected}"
|
|
375
325
|
@d2l-tab-deselected="${this.#handleTabDeselected}"
|
|
376
|
-
@focusout="${this
|
|
326
|
+
@focusout="${this.#handleFocusOut}"
|
|
377
327
|
aria-label="${ifDefined(this.text)}"
|
|
378
328
|
role="tablist"
|
|
379
329
|
style="${styleMap(tabsContainerListStyles)}">
|
|
380
|
-
${
|
|
381
|
-
<d2l-tab-internal aria-selected="${tabInfo.selected ? 'true' : 'false'}"
|
|
382
|
-
.controlsPanel="${tabInfo.id}"
|
|
383
|
-
data-state="${tabInfo.state}"
|
|
384
|
-
?skeleton="${this.skeleton}"
|
|
385
|
-
tabindex="${tabInfo.activeFocusable ? 0 : -1}"
|
|
386
|
-
text="${tabInfo.text}">
|
|
387
|
-
</d2l-tab-internal>
|
|
388
|
-
`) : nothing}
|
|
389
|
-
<slot name="tabs" @slotchange="${this._handleTabsSlotChange}"></slot>
|
|
330
|
+
<slot name="tabs" @slotchange="${this.#handleTabsSlotChange}"></slot>
|
|
390
331
|
</div>
|
|
391
332
|
`)}
|
|
392
333
|
<div class="d2l-tabs-scroll-next-container">
|
|
393
334
|
<button class="d2l-tabs-scroll-button"
|
|
394
|
-
@click="${this
|
|
335
|
+
@click="${this.#handleScrollNext}"
|
|
395
336
|
title="${this.localize('components.tabs.next')}">
|
|
396
337
|
<d2l-icon icon="tier1:chevron-right"></d2l-icon>
|
|
397
338
|
</button>
|
|
@@ -399,21 +340,18 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
399
340
|
</div>
|
|
400
341
|
<div class="d2l-tabs-container-ext"><slot name="ext"></slot></div>
|
|
401
342
|
</div>
|
|
402
|
-
<div class="${classMap(panelContainerClasses)}"
|
|
403
|
-
@
|
|
404
|
-
@d2l-tab-panel-text-changed="${ifDefined(!this.#newTabsPanelStructure ? this._handlePanelTextChange : undefined)}">
|
|
405
|
-
${!this.#newTabsPanelStructure ? html`<slot @slotchange="${this._handleDefaultSlotChange}"></slot>` : nothing}
|
|
406
|
-
<slot name="panels" @slotchange="${this._handlePanelsSlotChange}"></slot>
|
|
343
|
+
<div class="${classMap(panelContainerClasses)}">
|
|
344
|
+
<slot name="panels" @slotchange="${this.#handlePanelsSlotChange}"></slot>
|
|
407
345
|
</div>
|
|
408
346
|
`;
|
|
409
347
|
}
|
|
410
348
|
|
|
411
349
|
focus() {
|
|
412
|
-
return this
|
|
350
|
+
return this.#focusSelected();
|
|
413
351
|
}
|
|
414
352
|
|
|
415
353
|
async getLoadingComplete() {
|
|
416
|
-
return this
|
|
354
|
+
return this.#loadingCompletePromise;
|
|
417
355
|
}
|
|
418
356
|
|
|
419
357
|
getTabListRect() {
|
|
@@ -423,15 +361,28 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
423
361
|
|
|
424
362
|
hideTab(tab) {
|
|
425
363
|
tab.setAttribute('data-state', 'removing');
|
|
426
|
-
return (Object.keys(this
|
|
364
|
+
return (Object.keys(this.#tabIds).length > 1 && !reduceMotion) ? this.#animateTabRemoval(tab) : Promise.resolve();
|
|
427
365
|
}
|
|
428
366
|
|
|
429
367
|
#checkTabPanelMatchRequested;
|
|
430
|
-
#
|
|
368
|
+
#initialized;
|
|
369
|
+
#loadingCompletePromise;
|
|
370
|
+
#loadingCompleteResolve;
|
|
371
|
+
#measures;
|
|
431
372
|
#panels;
|
|
373
|
+
#resizeObserver;
|
|
374
|
+
#tabIds;
|
|
375
|
+
#tabs;
|
|
432
376
|
#updateAriaControlsRequested;
|
|
433
377
|
|
|
434
|
-
|
|
378
|
+
#handleResize = (entries) => {
|
|
379
|
+
const measures = this.#getMeasures();
|
|
380
|
+
if (entries.length === 1 && entries[0].contentRect.width === measures.tabsContainerListRect.width) return;
|
|
381
|
+
this.#updateMeasures();
|
|
382
|
+
this.#updateScrollVisibility(this.#getMeasures());
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
#animateTabAddition(tab) {
|
|
435
386
|
if (!tab || reduceMotion) {
|
|
436
387
|
return new Promise((resolve) => {
|
|
437
388
|
tab.setAttribute('data-state', '');
|
|
@@ -452,25 +403,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
452
403
|
});
|
|
453
404
|
}
|
|
454
405
|
|
|
455
|
-
|
|
456
|
-
_animateTabAdditionDefaultSlotBehavior(tabInfo) {
|
|
457
|
-
const tab = this.shadowRoot
|
|
458
|
-
&& this.shadowRoot.querySelector(`d2l-tab-internal[controls-panel="${CSS.escape(tabInfo.id)}"]`);
|
|
459
|
-
if (!tab) Promise.resolve();
|
|
460
|
-
|
|
461
|
-
return new Promise((resolve) => {
|
|
462
|
-
const handleTransitionEnd = (e) => {
|
|
463
|
-
if (e.propertyName !== 'max-width') return;
|
|
464
|
-
tab.removeEventListener('transitionend', handleTransitionEnd);
|
|
465
|
-
resolve();
|
|
466
|
-
};
|
|
467
|
-
tab.addEventListener('transitionend', handleTransitionEnd);
|
|
468
|
-
tabInfo.state = '';
|
|
469
|
-
this.requestUpdate();
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
_animateTabRemoval(tab) {
|
|
406
|
+
#animateTabRemoval(tab) {
|
|
474
407
|
if (!tab || reduceMotion) return Promise.resolve();
|
|
475
408
|
|
|
476
409
|
return new Promise((resolve) => {
|
|
@@ -484,62 +417,120 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
484
417
|
});
|
|
485
418
|
}
|
|
486
419
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
const tab = this.shadowRoot &&
|
|
490
|
-
this.shadowRoot.querySelector(`d2l-tab-internal[controls-panel="${CSS.escape(tabInfo.id)}"]`);
|
|
491
|
-
if (!tab) Promise.resolve();
|
|
492
|
-
|
|
493
|
-
return new Promise((resolve) => {
|
|
494
|
-
const handleTransitionEnd = (e) => {
|
|
495
|
-
if (e.propertyName !== 'max-width') return;
|
|
496
|
-
tab.removeEventListener('transitionend', handleTransitionEnd);
|
|
497
|
-
this._tabInfos.splice(this._tabInfos.findIndex(info => info.id === tabInfo.id), 1);
|
|
498
|
-
this.requestUpdate();
|
|
499
|
-
resolve();
|
|
500
|
-
};
|
|
501
|
-
tab.addEventListener('transitionend', handleTransitionEnd);
|
|
502
|
-
});
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
_calculateScrollPosition(selectedTab, measures) {
|
|
506
|
-
const tabs = this._tabs;
|
|
420
|
+
#calculateScrollPosition(selectedTab, measures) {
|
|
421
|
+
const tabs = this.#tabs;
|
|
507
422
|
const selectedTabIndex = tabs.indexOf(selectedTab);
|
|
508
423
|
return this.#calculateScrollPositionLogic(tabs, selectedTabIndex, measures);
|
|
509
424
|
}
|
|
510
425
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
426
|
+
#calculateScrollPositionLogic(tabsDataStructure, selectedTabIndex, measures) {
|
|
427
|
+
if (!measures.tabRects[selectedTabIndex]) return 0;
|
|
428
|
+
|
|
429
|
+
const selectedTabMeasures = measures.tabRects[selectedTabIndex];
|
|
430
|
+
|
|
431
|
+
const isOverflowingLeft = (selectedTabMeasures.offsetLeft + this._translationValue < 0);
|
|
432
|
+
const isOverflowingRight = (selectedTabMeasures.offsetLeft + selectedTabMeasures.rect.width + this._translationValue > measures.tabsContainerRect.width);
|
|
433
|
+
|
|
434
|
+
const isRTL = this.#isRTL();
|
|
435
|
+
|
|
436
|
+
let getNewTranslationValue;
|
|
437
|
+
if (!isRTL) {
|
|
438
|
+
getNewTranslationValue = () => {
|
|
439
|
+
if (selectedTabIndex === 0) {
|
|
440
|
+
// position selected tab at beginning
|
|
441
|
+
return 0;
|
|
442
|
+
} else if (selectedTabIndex === (tabsDataStructure.length - 1)) {
|
|
443
|
+
// position selected tab at end
|
|
444
|
+
return -1 * (selectedTabMeasures.offsetLeft - measures.tabsContainerRect.width + selectedTabMeasures.rect.width);
|
|
445
|
+
} else {
|
|
446
|
+
// position selected tab in middle
|
|
447
|
+
return -1 * (selectedTabMeasures.offsetLeft - (measures.tabsContainerRect.width / 2) + (selectedTabMeasures.rect.width / 2));
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
} else {
|
|
451
|
+
getNewTranslationValue = () => {
|
|
452
|
+
if (selectedTabIndex === 0) {
|
|
453
|
+
// position selected tab at beginning
|
|
454
|
+
return 0;
|
|
455
|
+
} else if (selectedTabIndex === (tabsDataStructure.length - 1)) {
|
|
456
|
+
// position selected tab at end
|
|
457
|
+
return -1 * selectedTabMeasures.offsetLeft;
|
|
458
|
+
} else {
|
|
459
|
+
// position selected tab in middle
|
|
460
|
+
return (measures.tabsContainerRect.width / 2) - (selectedTabMeasures.offsetLeft + selectedTabMeasures.rect.width / 2) + (selectedTabMeasures.rect.width / 2);
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
}
|
|
516
464
|
|
|
517
|
-
|
|
518
|
-
if (
|
|
519
|
-
|
|
520
|
-
return;
|
|
465
|
+
let newTranslationValue = this._translationValue;
|
|
466
|
+
if (isOverflowingLeft || isOverflowingRight) {
|
|
467
|
+
newTranslationValue = getNewTranslationValue();
|
|
521
468
|
}
|
|
522
469
|
|
|
523
|
-
|
|
524
|
-
|
|
470
|
+
let expectedPosition;
|
|
471
|
+
|
|
472
|
+
// make sure the new position will not place selected tab behind left scroll button
|
|
473
|
+
if (!isRTL) {
|
|
474
|
+
expectedPosition = selectedTabMeasures.offsetLeft + newTranslationValue;
|
|
475
|
+
if (newTranslationValue < 0 && this.#isPositionInLeftScrollArea(expectedPosition)) {
|
|
476
|
+
newTranslationValue = getNewTranslationValue();
|
|
477
|
+
}
|
|
478
|
+
} else {
|
|
479
|
+
expectedPosition = selectedTabMeasures.offsetLeft + selectedTabMeasures.rect.width + newTranslationValue;
|
|
480
|
+
if (newTranslationValue > 0 && this.#isPositionInRightScrollArea(expectedPosition, measures)) {
|
|
481
|
+
newTranslationValue = getNewTranslationValue();
|
|
482
|
+
}
|
|
483
|
+
}
|
|
525
484
|
|
|
526
|
-
|
|
485
|
+
if (!isRTL) {
|
|
486
|
+
// make sure there will not be any empty space between left side of container and first tab
|
|
487
|
+
if (newTranslationValue > 0) newTranslationValue = 0;
|
|
488
|
+
} else {
|
|
489
|
+
// make sure there will not be any empty space between right side of container and first tab
|
|
490
|
+
if (newTranslationValue < 0) newTranslationValue = 0;
|
|
491
|
+
}
|
|
527
492
|
|
|
528
|
-
|
|
493
|
+
// make sure the new position will not place selected tab behind the right scroll button
|
|
494
|
+
if (!isRTL) {
|
|
495
|
+
expectedPosition = selectedTabMeasures.offsetLeft + selectedTabMeasures.rect.width + newTranslationValue;
|
|
496
|
+
if ((selectedTabIndex < tabsDataStructure.length - 1) && this.#isPositionInRightScrollArea(expectedPosition, measures)) {
|
|
497
|
+
newTranslationValue = getNewTranslationValue();
|
|
498
|
+
}
|
|
499
|
+
} else {
|
|
500
|
+
expectedPosition = selectedTabMeasures.offsetLeft + newTranslationValue;
|
|
501
|
+
if ((selectedTabIndex < tabsDataStructure.length - 1) && this.#isPositionInLeftScrollArea(expectedPosition)) {
|
|
502
|
+
newTranslationValue = getNewTranslationValue();
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
return newTranslationValue;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
#checkTabPanelMatch() {
|
|
510
|
+
// debounce so only runs once when tabs/panels slots changing
|
|
511
|
+
if (this.#checkTabPanelMatchRequested) return;
|
|
512
|
+
|
|
513
|
+
this.#checkTabPanelMatchRequested = true;
|
|
514
|
+
setTimeout(() => {
|
|
515
|
+
if ((this.#tabs && !this.#panels) || (this.#panels && !this.#tabs)) {
|
|
516
|
+
console.warn('d2l-tabs: tabs and panels are not in sync');
|
|
517
|
+
} else if (this.#tabs.length !== this.#panels.length) {
|
|
518
|
+
console.warn('d2l-tabs: number of tabs and panels does not match');
|
|
519
|
+
}
|
|
520
|
+
this.#checkTabPanelMatchRequested = false;
|
|
521
|
+
}, 0);
|
|
529
522
|
}
|
|
530
523
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
const selectedTab = this.shadowRoot && this.shadowRoot.querySelector('d2l-tab-internal[aria-selected="true"]');
|
|
524
|
+
async #focusSelected() {
|
|
525
|
+
const selectedTab = this.#tabs.find(ti => ti.selected);
|
|
534
526
|
if (!selectedTab) return;
|
|
535
527
|
|
|
536
|
-
|
|
537
|
-
await this._updateScrollPositionDefaultSlotBehavior(selectedTabInfo);
|
|
528
|
+
await this.#updateScrollPosition(selectedTab);
|
|
538
529
|
|
|
539
530
|
selectedTab.focus();
|
|
540
531
|
}
|
|
541
532
|
|
|
542
|
-
|
|
533
|
+
#getComputedBackgroundColor() {
|
|
543
534
|
let bgColor = null;
|
|
544
535
|
|
|
545
536
|
findComposedAncestor(this, (node) => {
|
|
@@ -553,177 +544,33 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
553
544
|
return bgColor;
|
|
554
545
|
}
|
|
555
546
|
|
|
556
|
-
|
|
557
|
-
if (!this
|
|
558
|
-
return this
|
|
547
|
+
#getMeasures() {
|
|
548
|
+
if (!this.#measures) this.#updateMeasures();
|
|
549
|
+
return this.#measures;
|
|
559
550
|
}
|
|
560
551
|
|
|
561
|
-
|
|
562
|
-
if (this._defaultSlotBehavior) return this._getPanelDefaultSlotBehavior(id);
|
|
563
|
-
|
|
552
|
+
#getPanel(id) {
|
|
564
553
|
if (!this.#panels) return;
|
|
565
554
|
return this.#panels.find(panel => panel.labelledBy === id);
|
|
566
555
|
}
|
|
567
556
|
|
|
568
|
-
|
|
569
|
-
_getPanelDefaultSlotBehavior(id) {
|
|
570
|
-
if (!this.shadowRoot) return;
|
|
571
|
-
// use simple selector for slot (Edge)
|
|
572
|
-
const slot = this.shadowRoot.querySelector('.d2l-panels-container').querySelector('slot');
|
|
573
|
-
const panels = this._getPanelsDefaultSlotBehavior(slot);
|
|
574
|
-
for (let i = 0; i < panels.length; i++) {
|
|
575
|
-
if (panels[i].nodeType === Node.ELEMENT_NODE && panels[i].role === 'tabpanel' && panels[i].id === id) {
|
|
576
|
-
return panels[i];
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// rremove with GAUD-8299-core-tabs-use-new-structure flag clean up
|
|
582
|
-
_getPanelsDefaultSlotBehavior(slot) {
|
|
583
|
-
if (!slot) return;
|
|
584
|
-
return slot.assignedElements({ flatten: true }).filter((node) => node.role === 'tabpanel');
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
// remove with GAUD-8299-core-tabs-use-new-structure flag clean up
|
|
588
|
-
_getTabInfo(id) {
|
|
589
|
-
return this._tabInfos.find((t) => t.id === id);
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
// remove with GAUD-8299-core-tabs-use-new-structure flag clean up
|
|
593
|
-
async _handleDefaultSlotChange(e) {
|
|
594
|
-
if (!this._defaultSlotBehavior) return;
|
|
595
|
-
|
|
596
|
-
const panels = this._getPanelsDefaultSlotBehavior(e.target);
|
|
597
|
-
|
|
598
|
-
// handle case where there are less than two tabs initially
|
|
599
|
-
this._updateTabListVisibility(panels);
|
|
600
|
-
|
|
601
|
-
if (!this._initialized && panels.length === 0) return;
|
|
602
|
-
|
|
603
|
-
let selectedTabInfo = null;
|
|
604
|
-
|
|
605
|
-
const newTabInfos = panels.map((panel) => {
|
|
606
|
-
let state = '';
|
|
607
|
-
if (this._initialized && !reduceMotion && panels.length !== this._tabInfos.length) {
|
|
608
|
-
// if it's a new tab, update state to animate addition
|
|
609
|
-
if (this._tabInfos.findIndex(info => info.id === panel.id) === -1) {
|
|
610
|
-
state = 'adding';
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
const tabInfo = {
|
|
614
|
-
id: panel.id,
|
|
615
|
-
text: panel.text,
|
|
616
|
-
selected: panel.selected,
|
|
617
|
-
state: state
|
|
618
|
-
};
|
|
619
|
-
if (tabInfo.selected) {
|
|
620
|
-
selectedTabInfo = tabInfo;
|
|
621
|
-
this._setFocusableDefaultSlotBehavior(tabInfo);
|
|
622
|
-
}
|
|
623
|
-
return tabInfo;
|
|
624
|
-
});
|
|
625
|
-
|
|
626
|
-
if (this._initialized && !reduceMotion && this._tabInfos.length !== newTabInfos.length) {
|
|
627
|
-
this._tabInfos.forEach((info, index) => {
|
|
628
|
-
// if a tab was removed, include old info to animate it away
|
|
629
|
-
if (newTabInfos.findIndex(newInfo => newInfo.id === info.id) === -1) {
|
|
630
|
-
info.state = 'removing';
|
|
631
|
-
info.selected = false;
|
|
632
|
-
newTabInfos.splice(index, 0, info);
|
|
633
|
-
}
|
|
634
|
-
});
|
|
635
|
-
}
|
|
636
|
-
this._tabInfos = newTabInfos;
|
|
637
|
-
|
|
638
|
-
if (this._tabInfos.length > 0 && !selectedTabInfo) {
|
|
639
|
-
selectedTabInfo = this._tabInfos.find(tabInfo => tabInfo.state !== 'removing');
|
|
640
|
-
if (selectedTabInfo) {
|
|
641
|
-
selectedTabInfo.activeFocusable = true;
|
|
642
|
-
selectedTabInfo.selected = true;
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
await this.updateComplete;
|
|
647
|
-
|
|
648
|
-
const animPromises = [];
|
|
649
|
-
if (!this._initialized && this._tabInfos.length > 0) {
|
|
650
|
-
|
|
651
|
-
this._initialized = true;
|
|
652
|
-
await this._updateTabsContainerWidthDefaultSlotBehavior(selectedTabInfo);
|
|
653
|
-
|
|
654
|
-
} else {
|
|
655
|
-
|
|
656
|
-
if (this._tabInfos.length > 1) {
|
|
657
|
-
this._tabInfos.forEach((info) => {
|
|
658
|
-
if (info.state === 'adding') animPromises.push(this._animateTabAdditionDefaultSlotBehavior(info));
|
|
659
|
-
else if (info.state === 'removing') animPromises.push(this._animateTabRemovalDefaultSlotBehavior(info));
|
|
660
|
-
});
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
// required for animation
|
|
664
|
-
this._updateMeasures();
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
if (selectedTabInfo) {
|
|
668
|
-
Promise.all(animPromises).then(() => {
|
|
669
|
-
this._updateMeasures();
|
|
670
|
-
return this._updateScrollPositionDefaultSlotBehavior(selectedTabInfo);
|
|
671
|
-
});
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
_handleFocusOut(e) {
|
|
557
|
+
#handleFocusOut(e) {
|
|
677
558
|
if (e.relatedTarget && e.relatedTarget.role === 'tab') return;
|
|
678
|
-
this
|
|
559
|
+
this.#resetFocusables();
|
|
679
560
|
}
|
|
680
561
|
|
|
681
|
-
|
|
682
|
-
_handlePanelSelected(e) {
|
|
683
|
-
if (!this._defaultSlotBehavior) return;
|
|
684
|
-
|
|
685
|
-
const tabInfo = this._getTabInfo(e.target.id);
|
|
686
|
-
// event could be from nested tabs
|
|
687
|
-
if (!tabInfo) return;
|
|
688
|
-
|
|
689
|
-
this._setFocusableDefaultSlotBehavior(tabInfo);
|
|
690
|
-
tabInfo.selected = true;
|
|
691
|
-
this.requestUpdate();
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
_handlePanelsSlotChange(e) {
|
|
695
|
-
if (this._defaultSlotBehavior) return;
|
|
696
|
-
|
|
562
|
+
#handlePanelsSlotChange(e) {
|
|
697
563
|
this.#panels = e.target.assignedElements({ flatten: true }).filter((node) => node.role === 'tabpanel');
|
|
698
564
|
this.#checkTabPanelMatch();
|
|
699
565
|
this.#setAriaControls();
|
|
700
566
|
}
|
|
701
567
|
|
|
702
|
-
|
|
703
|
-
async _handlePanelTextChange(e) {
|
|
704
|
-
const tabInfo = this._getTabInfo(e.target.id);
|
|
705
|
-
// event could be from nested tabs
|
|
706
|
-
if (!tabInfo) return;
|
|
707
|
-
tabInfo.text = e.target.text;
|
|
708
|
-
this.requestUpdate();
|
|
709
|
-
await this.updateComplete;
|
|
710
|
-
this._updateMeasures();
|
|
711
|
-
await this._updateScrollVisibility(this._getMeasures());
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
_handleResize(entries) {
|
|
715
|
-
const measures = this._getMeasures();
|
|
716
|
-
if (entries.length === 1 && entries[0].contentRect.width === measures.tabsContainerListRect.width) return;
|
|
717
|
-
this._updateMeasures();
|
|
718
|
-
this._updateScrollVisibility(this._getMeasures());
|
|
719
|
-
}
|
|
568
|
+
async #handleScrollNext() {
|
|
720
569
|
|
|
721
|
-
|
|
570
|
+
const measures = this.#getMeasures();
|
|
722
571
|
|
|
723
|
-
const
|
|
724
|
-
|
|
725
|
-
const expanded = await this._tryExpandTabsContainer(measures);
|
|
726
|
-
const newMeasures = expanded ? this._getMeasures() : measures;
|
|
572
|
+
const expanded = await this.#tryExpandTabsContainer(measures);
|
|
573
|
+
const newMeasures = expanded ? this.#getMeasures() : measures;
|
|
727
574
|
|
|
728
575
|
let newTranslationValue;
|
|
729
576
|
const lastTabMeasures = measures.tabRects[measures.tabRects.length - 1];
|
|
@@ -753,8 +600,8 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
753
600
|
|
|
754
601
|
}
|
|
755
602
|
|
|
756
|
-
await this
|
|
757
|
-
await this
|
|
603
|
+
await this.#scrollToPosition(newTranslationValue);
|
|
604
|
+
await this.#updateScrollVisibility(newMeasures);
|
|
758
605
|
|
|
759
606
|
if (!isOverflowingNext && this.shadowRoot) {
|
|
760
607
|
this.shadowRoot.querySelector('.d2l-tabs-scroll-previous-container button').focus();
|
|
@@ -762,12 +609,12 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
762
609
|
|
|
763
610
|
}
|
|
764
611
|
|
|
765
|
-
async
|
|
612
|
+
async #handleScrollPrevious() {
|
|
766
613
|
|
|
767
|
-
const measures = this
|
|
614
|
+
const measures = this.#getMeasures();
|
|
768
615
|
|
|
769
|
-
const expanded = await this
|
|
770
|
-
const newMeasures = expanded ? this
|
|
616
|
+
const expanded = await this.#tryExpandTabsContainer(measures);
|
|
617
|
+
const newMeasures = expanded ? this.#getMeasures() : measures;
|
|
771
618
|
|
|
772
619
|
let newTranslationValue;
|
|
773
620
|
let isOverflowingPrevious;
|
|
@@ -786,8 +633,8 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
786
633
|
|
|
787
634
|
}
|
|
788
635
|
|
|
789
|
-
await this
|
|
790
|
-
await this
|
|
636
|
+
await this.#scrollToPosition(newTranslationValue);
|
|
637
|
+
await this.#updateScrollVisibility(newMeasures);
|
|
791
638
|
|
|
792
639
|
if (!isOverflowingPrevious && this.shadowRoot) {
|
|
793
640
|
this.shadowRoot.querySelector('.d2l-tabs-scroll-next-container button').focus();
|
|
@@ -795,68 +642,50 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
795
642
|
|
|
796
643
|
}
|
|
797
644
|
|
|
798
|
-
async
|
|
799
|
-
this
|
|
800
|
-
await this
|
|
645
|
+
async #handleTabContentChange() {
|
|
646
|
+
this.#updateMeasures();
|
|
647
|
+
await this.#updateScrollVisibility(this.#getMeasures());
|
|
801
648
|
}
|
|
802
649
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
return;
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
const selectedTab = e.target;
|
|
810
|
-
this.#updateSelectedTab(selectedTab);
|
|
811
|
-
await this.updateComplete;
|
|
812
|
-
this._updateScrollPosition(selectedTab);
|
|
650
|
+
#handleTabDeselected(e) {
|
|
651
|
+
const panel = this.#getPanel(e.target.id);
|
|
652
|
+
if (panel) panel._selected = false;
|
|
813
653
|
}
|
|
814
654
|
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
e.stopPropagation();
|
|
818
|
-
|
|
819
|
-
const selectedTab = e.target;
|
|
820
|
-
const selectedPanel = this._getPanel(selectedTab.controlsPanel);
|
|
821
|
-
const selectedTabInfo = this._getTabInfo(selectedTab.controlsPanel);
|
|
822
|
-
selectedTabInfo.activeFocusable = true;
|
|
655
|
+
#handleTabHiddenChange() {
|
|
656
|
+
if (!this.#tabs || this.#tabs.length <= 1) return;
|
|
823
657
|
|
|
824
|
-
|
|
825
|
-
this.
|
|
826
|
-
|
|
827
|
-
selectedPanel.selected = true;
|
|
828
|
-
this._tabInfos.forEach((tabInfo) => {
|
|
829
|
-
if (tabInfo.id !== selectedTab.controlsPanel) {
|
|
830
|
-
if (tabInfo.selected) {
|
|
831
|
-
tabInfo.selected = false;
|
|
832
|
-
const panel = this._getPanel(tabInfo.id);
|
|
833
|
-
// panel may not exist if it's being removed
|
|
834
|
-
if (panel) panel.selected = false;
|
|
835
|
-
}
|
|
836
|
-
if (tabInfo.activeFocusable) tabInfo.activeFocusable = false;
|
|
837
|
-
}
|
|
658
|
+
let visibleTabCount = 0;
|
|
659
|
+
this.#tabs.forEach((tab) => {
|
|
660
|
+
if (!tab.hidden) visibleTabCount++;
|
|
838
661
|
});
|
|
839
662
|
|
|
840
|
-
this.
|
|
663
|
+
if (visibleTabCount > 1 && this._state === 'hidden') this.#showTabsList();
|
|
664
|
+
else if (visibleTabCount <= 1 && this._state === 'shown') this.#hideTabsList();
|
|
841
665
|
}
|
|
842
666
|
|
|
843
|
-
async
|
|
844
|
-
|
|
667
|
+
async #handleTabSelected(e) {
|
|
668
|
+
const selectedTab = e.target;
|
|
669
|
+
this.#updateSelectedTab(selectedTab);
|
|
670
|
+
await this.updateComplete;
|
|
671
|
+
this.#updateScrollPosition(selectedTab);
|
|
672
|
+
}
|
|
845
673
|
|
|
846
|
-
|
|
674
|
+
async #handleTabsSlotChange(e) {
|
|
675
|
+
this.#tabs = e.target.assignedElements({ flatten: true }).filter((node) => node.role === 'tab');
|
|
847
676
|
|
|
848
677
|
// handle case where there are less than two tabs initially
|
|
849
|
-
this
|
|
678
|
+
this.#updateTabListVisibility(this.#tabs);
|
|
850
679
|
|
|
851
|
-
if (!this
|
|
680
|
+
if (!this.#initialized && this.#tabs.length === 0) return;
|
|
852
681
|
|
|
853
682
|
let selectedTab = null;
|
|
854
683
|
const newTabIds = {};
|
|
855
|
-
this
|
|
856
|
-
const isNew = this
|
|
857
|
-
if (isNew && !reduceMotion && this.
|
|
684
|
+
this.#tabs?.forEach((tab) => {
|
|
685
|
+
const isNew = this.#initialized && !this.#tabIds[tab.id];
|
|
686
|
+
if (isNew && !reduceMotion && this.#tabs.length !== Object.keys(this.#tabIds).length) {
|
|
858
687
|
// if it's a new tab, update state to animate addition
|
|
859
|
-
this
|
|
688
|
+
this.#tabIds[tab.id] = true;
|
|
860
689
|
tab.setAttribute('data-state', 'adding');
|
|
861
690
|
}
|
|
862
691
|
if (tab.selected && tab.getAttribute('data-state') !== 'removing') {
|
|
@@ -866,10 +695,10 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
866
695
|
newTabIds[tab.id] = true;
|
|
867
696
|
});
|
|
868
697
|
|
|
869
|
-
this
|
|
698
|
+
this.#tabIds = newTabIds;
|
|
870
699
|
|
|
871
700
|
if (!selectedTab) {
|
|
872
|
-
selectedTab = this.
|
|
701
|
+
selectedTab = this.#tabs.find((tab) => tab.getAttribute('data-state') !== 'removing');
|
|
873
702
|
if (selectedTab) selectedTab.selected = true;
|
|
874
703
|
}
|
|
875
704
|
if (selectedTab) {
|
|
@@ -882,47 +711,62 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
882
711
|
|
|
883
712
|
const animPromises = [];
|
|
884
713
|
|
|
885
|
-
if (!this
|
|
886
|
-
this
|
|
887
|
-
await this
|
|
714
|
+
if (!this.#initialized && this.#tabs.length > 0) {
|
|
715
|
+
this.#initialized = true;
|
|
716
|
+
await this.#updateTabsContainerWidth(selectedTab);
|
|
888
717
|
} else {
|
|
889
|
-
if (this.
|
|
890
|
-
this.
|
|
891
|
-
if (tab.getAttribute('data-state') === 'adding') animPromises.push(this
|
|
718
|
+
if (this.#tabs.length > 1) {
|
|
719
|
+
this.#tabs.forEach((tab) => {
|
|
720
|
+
if (tab.getAttribute('data-state') === 'adding') animPromises.push(this.#animateTabAddition(tab));
|
|
892
721
|
});
|
|
893
722
|
}
|
|
894
|
-
this
|
|
723
|
+
this.#updateMeasures();
|
|
895
724
|
}
|
|
896
725
|
|
|
897
726
|
if (selectedTab) {
|
|
898
727
|
Promise.all(animPromises).then(async() => {
|
|
899
728
|
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
900
|
-
this
|
|
901
|
-
this
|
|
729
|
+
this.#updateMeasures();
|
|
730
|
+
this.#updateScrollPosition(selectedTab);
|
|
902
731
|
});
|
|
903
732
|
}
|
|
904
733
|
}
|
|
905
734
|
|
|
906
|
-
|
|
735
|
+
#hideTabsList() {
|
|
736
|
+
// don't animate the tabs list visibility if it's the inital render
|
|
737
|
+
if (reduceMotion || !this.#initialized || !isVisible(this)) {
|
|
738
|
+
this._state = 'hidden';
|
|
739
|
+
} else if (this.shadowRoot) {
|
|
740
|
+
const layout = this.shadowRoot.querySelector('.d2l-tabs-layout');
|
|
741
|
+
const handleTransitionEnd = (e) => {
|
|
742
|
+
if (e.propertyName !== 'max-height') return;
|
|
743
|
+
layout.removeEventListener('transitionend', handleTransitionEnd);
|
|
744
|
+
this._state = 'hidden';
|
|
745
|
+
};
|
|
746
|
+
layout.addEventListener('transitionend', handleTransitionEnd);
|
|
747
|
+
this._state = 'anim';
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
#isPositionInLeftScrollArea(position) {
|
|
907
752
|
return position > 0 && position < scrollButtonWidth;
|
|
908
753
|
}
|
|
909
754
|
|
|
910
|
-
|
|
755
|
+
#isPositionInRightScrollArea(position, measures) {
|
|
911
756
|
return (position > measures.tabsContainerRect.width - scrollButtonWidth) && (position < measures.tabsContainerRect.width);
|
|
912
757
|
}
|
|
913
758
|
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
}
|
|
759
|
+
#isRTL() {
|
|
760
|
+
return document.documentElement.getAttribute('dir') === 'rtl';
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
#resetFocusables() {
|
|
764
|
+
const selectedTab = this.#tabs.find(ti => ti.selected);
|
|
765
|
+
if (selectedTab) this.#setFocusable(selectedTab);
|
|
922
766
|
this.requestUpdate();
|
|
923
767
|
}
|
|
924
768
|
|
|
925
|
-
|
|
769
|
+
#scrollToPosition(translationValue) {
|
|
926
770
|
if (translationValue === this._translationValue) {
|
|
927
771
|
return Promise.resolve();
|
|
928
772
|
}
|
|
@@ -943,22 +787,44 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
943
787
|
});
|
|
944
788
|
}
|
|
945
789
|
|
|
946
|
-
|
|
947
|
-
|
|
790
|
+
#setAriaControls() {
|
|
791
|
+
// debounce so only runs once when tabs/panels slots changing
|
|
792
|
+
if (this.#updateAriaControlsRequested) return;
|
|
793
|
+
|
|
794
|
+
this.#updateAriaControlsRequested = true;
|
|
795
|
+
setTimeout(() => {
|
|
796
|
+
this.#tabs?.forEach((tab) => {
|
|
797
|
+
const panel = this.#getPanel(tab.id);
|
|
798
|
+
if (!panel) {
|
|
799
|
+
console.warn('d2l-tabs: tab without matching panel');
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
tab.setAttribute('aria-controls', `${panel.id}`);
|
|
803
|
+
});
|
|
804
|
+
this.#updateAriaControlsRequested = false;
|
|
805
|
+
}, 0);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
#setFocusable(tab) {
|
|
809
|
+
const currentFocusable = this.#tabs.find(tab => tab.tabIndex === 0);
|
|
948
810
|
if (currentFocusable) currentFocusable.tabIndex = -1;
|
|
949
811
|
|
|
950
812
|
tab.tabIndex = 0;
|
|
951
813
|
}
|
|
952
814
|
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
815
|
+
#showTabsList() {
|
|
816
|
+
// don't animate the tabs list visibility if it's the inital render
|
|
817
|
+
if (reduceMotion || !this.#initialized) {
|
|
818
|
+
this._state = 'shown';
|
|
819
|
+
} else {
|
|
820
|
+
this._state = 'anim';
|
|
821
|
+
requestAnimationFrame(() => {
|
|
822
|
+
this._state = 'shown';
|
|
823
|
+
});
|
|
824
|
+
}
|
|
959
825
|
}
|
|
960
826
|
|
|
961
|
-
async
|
|
827
|
+
async #tryExpandTabsContainer(measures) {
|
|
962
828
|
|
|
963
829
|
if (!this._scrollCollapsed) return false;
|
|
964
830
|
|
|
@@ -985,14 +851,14 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
985
851
|
|
|
986
852
|
await expandedPromise;
|
|
987
853
|
|
|
988
|
-
this
|
|
854
|
+
this.#measures = null;
|
|
989
855
|
|
|
990
|
-
await this
|
|
856
|
+
await this.#updateScrollVisibility(this.#getMeasures());
|
|
991
857
|
this._maxWidth = null;
|
|
992
858
|
|
|
993
859
|
if (!this._allowScrollNext) {
|
|
994
860
|
if (!this._allowScrollPrevious) {
|
|
995
|
-
this
|
|
861
|
+
this.#focusSelected();
|
|
996
862
|
} else {
|
|
997
863
|
if (this.shadowRoot) this.shadowRoot.querySelector('.d2l-tabs-scroll-previous-container button').focus();
|
|
998
864
|
}
|
|
@@ -1002,14 +868,14 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
1002
868
|
return true;
|
|
1003
869
|
}
|
|
1004
870
|
|
|
1005
|
-
|
|
871
|
+
#updateMeasures() {
|
|
1006
872
|
let totalTabsWidth = 0;
|
|
1007
873
|
if (!this.shadowRoot) return;
|
|
1008
|
-
const tabs = this
|
|
874
|
+
const tabs = this.#tabs;
|
|
1009
875
|
|
|
1010
876
|
const tabRects = tabs.map((tab) => {
|
|
1011
877
|
const tabRect = tab.getBoundingClientRect();
|
|
1012
|
-
const offsetLeft =
|
|
878
|
+
const offsetLeft = getOffsetLeft(tab, tabRect);
|
|
1013
879
|
|
|
1014
880
|
const measures = {
|
|
1015
881
|
rect: tabRect,
|
|
@@ -1019,7 +885,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
1019
885
|
return measures;
|
|
1020
886
|
});
|
|
1021
887
|
|
|
1022
|
-
this
|
|
888
|
+
this.#measures = {
|
|
1023
889
|
tabsContainerRect: this.shadowRoot.querySelector('.d2l-tabs-container').getBoundingClientRect(),
|
|
1024
890
|
tabsContainerListRect: this.shadowRoot.querySelector('.d2l-tabs-container-list').getBoundingClientRect(),
|
|
1025
891
|
tabRects: tabRects,
|
|
@@ -1027,20 +893,29 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
1027
893
|
};
|
|
1028
894
|
}
|
|
1029
895
|
|
|
1030
|
-
|
|
1031
|
-
const measures = this
|
|
1032
|
-
const newTranslationValue = this
|
|
896
|
+
#updateScrollPosition(selectedTab) {
|
|
897
|
+
const measures = this.#getMeasures();
|
|
898
|
+
const newTranslationValue = this.#calculateScrollPosition(selectedTab, measures);
|
|
1033
899
|
return this.#updateScrollPositionLogic(measures, newTranslationValue);
|
|
1034
900
|
}
|
|
1035
901
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
const
|
|
1039
|
-
const
|
|
1040
|
-
|
|
902
|
+
#updateScrollPositionLogic(measures, newTranslationValue) {
|
|
903
|
+
const scrollToPromise = this.#scrollToPosition(newTranslationValue);
|
|
904
|
+
const scrollVisibilityPromise = this.#updateScrollVisibility(measures);
|
|
905
|
+
const p = Promise.all([
|
|
906
|
+
scrollVisibilityPromise,
|
|
907
|
+
scrollToPromise
|
|
908
|
+
]);
|
|
909
|
+
p.then(() => {
|
|
910
|
+
if (this.#loadingCompleteResolve) {
|
|
911
|
+
this.#loadingCompleteResolve();
|
|
912
|
+
this.#loadingCompleteResolve = undefined;
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
return p;
|
|
1041
916
|
}
|
|
1042
917
|
|
|
1043
|
-
|
|
918
|
+
#updateScrollVisibility(measures) {
|
|
1044
919
|
|
|
1045
920
|
const lastTabMeasures = measures.tabRects[measures.tabRects.length - 1];
|
|
1046
921
|
if (!lastTabMeasures) {
|
|
@@ -1060,20 +935,28 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
1060
935
|
return this.updateComplete;
|
|
1061
936
|
}
|
|
1062
937
|
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
938
|
+
async #updateSelectedTab(selectedTab) {
|
|
939
|
+
await this.updateComplete;
|
|
940
|
+
|
|
941
|
+
selectedTab.selected = true;
|
|
942
|
+
selectedTab.tabIndex = 0;
|
|
943
|
+
|
|
944
|
+
const selectedPanel = this.#getPanel(selectedTab.id);
|
|
945
|
+
if (selectedPanel) selectedPanel._selected = true;
|
|
946
|
+
this.#tabs.forEach((tab) => {
|
|
947
|
+
if (tab.id !== selectedTab.id) {
|
|
948
|
+
if (tab.selected) {
|
|
949
|
+
tab.selected = false;
|
|
950
|
+
const panel = this.#getPanel(tab.id);
|
|
951
|
+
// panel may not exist if it's being removed
|
|
952
|
+
if (panel) panel._selected = false;
|
|
953
|
+
}
|
|
954
|
+
if (tab.tabIndex === 0) tab.tabIndex = -1;
|
|
1073
955
|
}
|
|
1074
|
-
|
|
1075
|
-
|
|
956
|
+
});
|
|
957
|
+
}
|
|
1076
958
|
|
|
959
|
+
#updateTabListVisibility(tabs) {
|
|
1077
960
|
const visibleCount = tabs.filter(tab => !tab.hidden).length;
|
|
1078
961
|
if (this._state === 'shown' && visibleCount < 2) {
|
|
1079
962
|
this.#hideTabsList();
|
|
@@ -1085,233 +968,15 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
1085
968
|
}
|
|
1086
969
|
}
|
|
1087
970
|
|
|
1088
|
-
|
|
1089
|
-
const tabs = this
|
|
971
|
+
#updateTabsContainerWidth(selectedTab) {
|
|
972
|
+
const tabs = this.#tabs;
|
|
1090
973
|
if (!this.maxToShow || this.maxToShow <= 0 || this.maxToShow >= tabs.length) return;
|
|
1091
974
|
if (tabs.indexOf(selectedTab) > this.maxToShow - 1) return;
|
|
1092
975
|
return this.#updateTabsContainerWidthLogic();
|
|
1093
976
|
}
|
|
1094
977
|
|
|
1095
|
-
// remove with GAUD-8299-core-tabs-use-new-structure flag clean up
|
|
1096
|
-
_updateTabsContainerWidthDefaultSlotBehavior(selectedTabInfo) {
|
|
1097
|
-
if (!this.maxToShow || this.maxToShow <= 0 || this.maxToShow >= this._tabInfos.length) return;
|
|
1098
|
-
if (this._tabInfos.indexOf(selectedTabInfo) > this.maxToShow - 1) return;
|
|
1099
|
-
return this.#updateTabsContainerWidthLogic();
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
#calculateScrollPositionLogic(tabsDataStructure, selectedTabIndex, measures) {
|
|
1103
|
-
if (!measures.tabRects[selectedTabIndex]) return 0;
|
|
1104
|
-
|
|
1105
|
-
const selectedTabMeasures = measures.tabRects[selectedTabIndex];
|
|
1106
|
-
|
|
1107
|
-
const isOverflowingLeft = (selectedTabMeasures.offsetLeft + this._translationValue < 0);
|
|
1108
|
-
const isOverflowingRight = (selectedTabMeasures.offsetLeft + selectedTabMeasures.rect.width + this._translationValue > measures.tabsContainerRect.width);
|
|
1109
|
-
|
|
1110
|
-
const isRTL = this.#isRTL();
|
|
1111
|
-
|
|
1112
|
-
let getNewTranslationValue;
|
|
1113
|
-
if (!isRTL) {
|
|
1114
|
-
getNewTranslationValue = () => {
|
|
1115
|
-
if (selectedTabIndex === 0) {
|
|
1116
|
-
// position selected tab at beginning
|
|
1117
|
-
return 0;
|
|
1118
|
-
} else if (selectedTabIndex === (tabsDataStructure.length - 1)) {
|
|
1119
|
-
// position selected tab at end
|
|
1120
|
-
return -1 * (selectedTabMeasures.offsetLeft - measures.tabsContainerRect.width + selectedTabMeasures.rect.width);
|
|
1121
|
-
} else {
|
|
1122
|
-
// position selected tab in middle
|
|
1123
|
-
return -1 * (selectedTabMeasures.offsetLeft - (measures.tabsContainerRect.width / 2) + (selectedTabMeasures.rect.width / 2));
|
|
1124
|
-
}
|
|
1125
|
-
};
|
|
1126
|
-
} else {
|
|
1127
|
-
getNewTranslationValue = () => {
|
|
1128
|
-
if (selectedTabIndex === 0) {
|
|
1129
|
-
// position selected tab at beginning
|
|
1130
|
-
return 0;
|
|
1131
|
-
} else if (selectedTabIndex === (tabsDataStructure.length - 1)) {
|
|
1132
|
-
// position selected tab at end
|
|
1133
|
-
return -1 * selectedTabMeasures.offsetLeft;
|
|
1134
|
-
} else {
|
|
1135
|
-
// position selected tab in middle
|
|
1136
|
-
return (measures.tabsContainerRect.width / 2) - (selectedTabMeasures.offsetLeft + selectedTabMeasures.rect.width / 2) + (selectedTabMeasures.rect.width / 2);
|
|
1137
|
-
}
|
|
1138
|
-
};
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
let newTranslationValue = this._translationValue;
|
|
1142
|
-
if (isOverflowingLeft || isOverflowingRight) {
|
|
1143
|
-
newTranslationValue = getNewTranslationValue();
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
let expectedPosition;
|
|
1147
|
-
|
|
1148
|
-
// make sure the new position will not place selected tab behind left scroll button
|
|
1149
|
-
if (!isRTL) {
|
|
1150
|
-
expectedPosition = selectedTabMeasures.offsetLeft + newTranslationValue;
|
|
1151
|
-
if (newTranslationValue < 0 && this._isPositionInLeftScrollArea(expectedPosition)) {
|
|
1152
|
-
newTranslationValue = getNewTranslationValue();
|
|
1153
|
-
}
|
|
1154
|
-
} else {
|
|
1155
|
-
expectedPosition = selectedTabMeasures.offsetLeft + selectedTabMeasures.rect.width + newTranslationValue;
|
|
1156
|
-
if (newTranslationValue > 0 && this._isPositionInRightScrollArea(expectedPosition, measures)) {
|
|
1157
|
-
newTranslationValue = getNewTranslationValue();
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
|
|
1161
|
-
if (!isRTL) {
|
|
1162
|
-
// make sure there will not be any empty space between left side of container and first tab
|
|
1163
|
-
if (newTranslationValue > 0) newTranslationValue = 0;
|
|
1164
|
-
} else {
|
|
1165
|
-
// make sure there will not be any empty space between right side of container and first tab
|
|
1166
|
-
if (newTranslationValue < 0) newTranslationValue = 0;
|
|
1167
|
-
}
|
|
1168
|
-
|
|
1169
|
-
// make sure the new position will not place selected tab behind the right scroll button
|
|
1170
|
-
if (!isRTL) {
|
|
1171
|
-
expectedPosition = selectedTabMeasures.offsetLeft + selectedTabMeasures.rect.width + newTranslationValue;
|
|
1172
|
-
if ((selectedTabIndex < tabsDataStructure.length - 1) && this._isPositionInRightScrollArea(expectedPosition, measures)) {
|
|
1173
|
-
newTranslationValue = getNewTranslationValue();
|
|
1174
|
-
}
|
|
1175
|
-
} else {
|
|
1176
|
-
expectedPosition = selectedTabMeasures.offsetLeft + newTranslationValue;
|
|
1177
|
-
if ((selectedTabIndex < tabsDataStructure.length - 1) && this._isPositionInLeftScrollArea(expectedPosition)) {
|
|
1178
|
-
newTranslationValue = getNewTranslationValue();
|
|
1179
|
-
}
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
return newTranslationValue;
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
|
-
#checkTabPanelMatch() {
|
|
1186
|
-
// debounce so only runs once when tabs/panels slots changing
|
|
1187
|
-
if (this.#checkTabPanelMatchRequested) return;
|
|
1188
|
-
|
|
1189
|
-
this.#checkTabPanelMatchRequested = true;
|
|
1190
|
-
setTimeout(() => {
|
|
1191
|
-
if ((this._tabs && !this.#panels) || (this.#panels && !this._tabs)) {
|
|
1192
|
-
console.warn('d2l-tabs: tabs and panels are not in sync');
|
|
1193
|
-
} else if (this._tabs.length !== this.#panels.length) {
|
|
1194
|
-
console.warn('d2l-tabs: number of tabs and panels does not match');
|
|
1195
|
-
}
|
|
1196
|
-
this.#checkTabPanelMatchRequested = false;
|
|
1197
|
-
}, 0);
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
#handleTabDeselected(e) {
|
|
1201
|
-
const panel = this._getPanel(e.target.id);
|
|
1202
|
-
if (panel) {
|
|
1203
|
-
if (this.#newTabsPanelStructure) panel._selected = false;
|
|
1204
|
-
else panel.selected = false; // remove with GAUD-8299-core-tabs-use-new-structure flag clean up
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
|
-
#handleTabHiddenChange() {
|
|
1209
|
-
if (!this._tabs || this._tabs.length <= 1) return;
|
|
1210
|
-
|
|
1211
|
-
let visibleTabCount = 0;
|
|
1212
|
-
this._tabs.forEach((tab) => {
|
|
1213
|
-
if (!tab.hidden) visibleTabCount++;
|
|
1214
|
-
});
|
|
1215
|
-
|
|
1216
|
-
if (visibleTabCount > 1 && this._state === 'hidden') this.#showTabsList();
|
|
1217
|
-
else if (visibleTabCount <= 1 && this._state === 'shown') this.#hideTabsList();
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
#hideTabsList() {
|
|
1221
|
-
// don't animate the tabs list visibility if it's the inital render
|
|
1222
|
-
if (reduceMotion || !this._initialized || !isVisible(this)) {
|
|
1223
|
-
this._state = 'hidden';
|
|
1224
|
-
} else if (this.shadowRoot) {
|
|
1225
|
-
const layout = this.shadowRoot.querySelector('.d2l-tabs-layout');
|
|
1226
|
-
const handleTransitionEnd = (e) => {
|
|
1227
|
-
if (e.propertyName !== 'max-height') return;
|
|
1228
|
-
layout.removeEventListener('transitionend', handleTransitionEnd);
|
|
1229
|
-
this._state = 'hidden';
|
|
1230
|
-
};
|
|
1231
|
-
layout.addEventListener('transitionend', handleTransitionEnd);
|
|
1232
|
-
this._state = 'anim';
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
#isRTL() {
|
|
1237
|
-
return document.documentElement.getAttribute('dir') === 'rtl';
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
|
-
#setAriaControls() {
|
|
1241
|
-
// debounce so only runs once when tabs/panels slots changing
|
|
1242
|
-
if (this.#updateAriaControlsRequested) return;
|
|
1243
|
-
|
|
1244
|
-
this.#updateAriaControlsRequested = true;
|
|
1245
|
-
setTimeout(() => {
|
|
1246
|
-
this._tabs?.forEach((tab) => {
|
|
1247
|
-
const panel = this._getPanel(tab.id);
|
|
1248
|
-
if (!panel) {
|
|
1249
|
-
console.warn('d2l-tabs: tab without matching panel');
|
|
1250
|
-
return;
|
|
1251
|
-
}
|
|
1252
|
-
tab.setAttribute('aria-controls', `${panel.id}`);
|
|
1253
|
-
});
|
|
1254
|
-
this.#updateAriaControlsRequested = false;
|
|
1255
|
-
}, 0);
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
#showTabsList() {
|
|
1259
|
-
// don't animate the tabs list visibility if it's the inital render
|
|
1260
|
-
if (reduceMotion || !this._initialized) {
|
|
1261
|
-
this._state = 'shown';
|
|
1262
|
-
} else {
|
|
1263
|
-
this._state = 'anim';
|
|
1264
|
-
requestAnimationFrame(() => {
|
|
1265
|
-
this._state = 'shown';
|
|
1266
|
-
});
|
|
1267
|
-
}
|
|
1268
|
-
}
|
|
1269
|
-
|
|
1270
|
-
#updateScrollPositionLogic(measures, newTranslationValue) {
|
|
1271
|
-
const scrollToPromise = this._scrollToPosition(newTranslationValue);
|
|
1272
|
-
const scrollVisibilityPromise = this._updateScrollVisibility(measures);
|
|
1273
|
-
const p = Promise.all([
|
|
1274
|
-
scrollVisibilityPromise,
|
|
1275
|
-
scrollToPromise
|
|
1276
|
-
]);
|
|
1277
|
-
p.then(() => {
|
|
1278
|
-
if (this._loadingCompleteResolve) {
|
|
1279
|
-
this._loadingCompleteResolve();
|
|
1280
|
-
this._loadingCompleteResolve = undefined;
|
|
1281
|
-
}
|
|
1282
|
-
});
|
|
1283
|
-
return p;
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1286
|
-
async #updateSelectedTab(selectedTab) {
|
|
1287
|
-
await this.updateComplete;
|
|
1288
|
-
|
|
1289
|
-
selectedTab.selected = true;
|
|
1290
|
-
selectedTab.tabIndex = 0;
|
|
1291
|
-
|
|
1292
|
-
const selectedPanel = this._getPanel(selectedTab.id);
|
|
1293
|
-
if (selectedPanel) {
|
|
1294
|
-
if (this.#newTabsPanelStructure) selectedPanel._selected = true;
|
|
1295
|
-
else selectedPanel.selected = true; // remove with GAUD-8299-core-tabs-use-new-structure flag clean up
|
|
1296
|
-
}
|
|
1297
|
-
this._tabs.forEach((tab) => {
|
|
1298
|
-
if (tab.id !== selectedTab.id) {
|
|
1299
|
-
if (tab.selected) {
|
|
1300
|
-
tab.selected = false;
|
|
1301
|
-
const panel = this._getPanel(tab.id);
|
|
1302
|
-
// panel may not exist if it's being removed
|
|
1303
|
-
if (panel) {
|
|
1304
|
-
if (this.#newTabsPanelStructure) panel._selected = false;
|
|
1305
|
-
else panel.selected = false; // remove with GAUD-8299-core-tabs-use-new-structure flag clean up
|
|
1306
|
-
}
|
|
1307
|
-
}
|
|
1308
|
-
if (tab.tabIndex === 0) tab.tabIndex = -1;
|
|
1309
|
-
}
|
|
1310
|
-
});
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
978
|
#updateTabsContainerWidthLogic() {
|
|
1314
|
-
const measures = this
|
|
979
|
+
const measures = this.#getMeasures();
|
|
1315
980
|
|
|
1316
981
|
let maxWidth = 4; // initial value to allow for padding hack
|
|
1317
982
|
for (let i = 0; i < this.maxToShow; i++) {
|
|
@@ -1326,7 +991,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
|
1326
991
|
|
|
1327
992
|
this._maxWidth = maxWidth;
|
|
1328
993
|
this._scrollCollapsed = true;
|
|
1329
|
-
this
|
|
994
|
+
this.#measures = null;
|
|
1330
995
|
|
|
1331
996
|
return this.updateComplete;
|
|
1332
997
|
}
|