@brightspace-ui/core 3.92.0 → 3.93.0
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.
@@ -11,6 +11,7 @@
|
|
11
11
|
import '../../dropdown/dropdown-menu.js';
|
12
12
|
import '../../menu/menu.js';
|
13
13
|
import '../../menu/menu-item.js';
|
14
|
+
import '../tab.js';
|
14
15
|
import '../tabs.js';
|
15
16
|
import '../tab-panel.js';
|
16
17
|
</script>
|
@@ -35,35 +36,17 @@
|
|
35
36
|
</d2l-demo-snippet>
|
36
37
|
|
37
38
|
<h2>Tabs (paired d2l-tab with d2l-panel)</h2>
|
39
|
+
<div>This format is still a WIP. Please do not use yet.</div>
|
38
40
|
|
39
41
|
<d2l-demo-snippet>
|
40
|
-
<div>This format is not yet functional. Please do not use yet.</div>
|
41
42
|
<template>
|
42
43
|
<d2l-tabs>
|
43
44
|
<d2l-tab id="all" text="All" slot="tabs"></d2l-tab>
|
44
45
|
<d2l-tab id="biology" text="Biology" slot="tabs"></d2l-tab>
|
45
46
|
<d2l-tab id="chemistry" text="Chemistry" slot="tabs"></d2l-tab>
|
46
|
-
<d2l-tab id="earth" text="Earth & Planetary Sciences" slot="tabs"></d2l-tab>
|
47
|
-
<d2l-tab id="physics" text="Physics" slot="tabs"></d2l-tab>
|
48
|
-
<d2l-tab id="math" text="Math" slot="tabs"></d2l-tab>
|
49
47
|
<d2l-tab-panel labelled-by="all" slot="panels">Tab content for All</d2l-tab-panel>
|
50
48
|
<d2l-tab-panel labelled-by="biology" slot="panels">Tab content for Biology</d2l-tab-panel>
|
51
49
|
<d2l-tab-panel labelled-by="chemistry" slot="panels">Tab content for Chemistry</d2l-tab-panel>
|
52
|
-
<d2l-tab-panel labelled-by="earth" slot="panels">Tab content for Earth & Planetary Sciences</d2l-tab-panel>
|
53
|
-
<d2l-tab-panel labelled-by="physics" slot="panels">Tab content for physics</d2l-tab-panel>
|
54
|
-
<d2l-tab-panel labelled-by="math" slot="panels">Tab content for math</d2l-tab-panel>
|
55
|
-
<d2l-dropdown-button-subtle slot="ext" text="Explore Topics">
|
56
|
-
<d2l-dropdown-menu>
|
57
|
-
<d2l-menu label="Astronomy">
|
58
|
-
<d2l-menu-item text="Introduction"></d2l-menu-item>
|
59
|
-
<d2l-menu-item text="Searching for the Heavens "></d2l-menu-item>
|
60
|
-
<d2l-menu-item text="The Solar System"></d2l-menu-item>
|
61
|
-
<d2l-menu-item text="Stars & Galaxies"></d2l-menu-item>
|
62
|
-
<d2l-menu-item text="The Night Sky"></d2l-menu-item>
|
63
|
-
<d2l-menu-item text="The Universe"></d2l-menu-item>
|
64
|
-
</d2l-menu>
|
65
|
-
</d2l-dropdown-menu>
|
66
|
-
</d2l-dropdown-button-subtle>
|
67
50
|
</d2l-tabs>
|
68
51
|
</template>
|
69
52
|
</d2l-demo-snippet>
|
@@ -12,6 +12,8 @@ export const TabMixin = superclass => class extends SkeletonMixin(superclass) {
|
|
12
12
|
static get properties() {
|
13
13
|
return {
|
14
14
|
selected: { type: Boolean, reflect: true },
|
15
|
+
// eslint-disable-next-line lit/no-native-attributes
|
16
|
+
role: { type: String, reflect: true }
|
15
17
|
};
|
16
18
|
}
|
17
19
|
|
@@ -62,10 +64,8 @@ export const TabMixin = superclass => class extends SkeletonMixin(superclass) {
|
|
62
64
|
|
63
65
|
constructor() {
|
64
66
|
super();
|
65
|
-
this.ariaSelected = false;
|
66
67
|
this.role = 'tab';
|
67
68
|
this.selected = false;
|
68
|
-
this.tabIndex = -1;
|
69
69
|
}
|
70
70
|
|
71
71
|
connectedCallback() {
|
package/components/tabs/tabs.js
CHANGED
@@ -22,7 +22,6 @@ const scrollButtonWidth = 56;
|
|
22
22
|
* A component for tabbed content. It supports the "d2l-tab-panel" component for the content, renders tabs responsively, and provides virtual scrolling for large tab lists.
|
23
23
|
* @slot - Contains the tab panels (e.g., "d2l-tab-panel" components)
|
24
24
|
* @slot ext - Additional content (e.g., a button) positioned at right
|
25
|
-
* @fires d2l-tabs-initialized - Dispatched when the component is initialized
|
26
25
|
*/
|
27
26
|
class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))) {
|
28
27
|
|
@@ -35,6 +34,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
35
34
|
maxToShow: { type: Number, attribute: 'max-to-show' },
|
36
35
|
_allowScrollNext: { type: Boolean },
|
37
36
|
_allowScrollPrevious: { type: Boolean },
|
37
|
+
_defaultSlotBehavior: { state: true },
|
38
38
|
_maxWidth: { type: Number },
|
39
39
|
_scrollCollapsed: { type: Boolean },
|
40
40
|
_state: { type: String },
|
@@ -199,12 +199,13 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
199
199
|
this.maxToShow = -1;
|
200
200
|
this._allowScrollNext = false;
|
201
201
|
this._allowScrollPrevious = false;
|
202
|
+
this._defaultSlotBehavior = true; // remove after d2l-tab/d2l-tab-panel backport
|
202
203
|
this._loadingCompleteResolve = undefined;
|
203
204
|
this._loadingCompletePromise = new Promise(resolve => this._loadingCompleteResolve = resolve);
|
204
205
|
this._maxWidth = null;
|
205
206
|
this._scrollCollapsed = false;
|
206
207
|
this._state = 'shown';
|
207
|
-
this._tabInfos = [];
|
208
|
+
this._tabInfos = []; // remove after d2l-tab/d2l-tab-panel backport
|
208
209
|
this._translationValue = 0;
|
209
210
|
}
|
210
211
|
|
@@ -315,6 +316,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
315
316
|
text="${tabInfo.text}">
|
316
317
|
</d2l-tab-internal>
|
317
318
|
`)}
|
319
|
+
<slot name="tabs" @slotchange="${this._handleTabsSlotChange}"></slot>
|
318
320
|
</div>
|
319
321
|
`)}
|
320
322
|
<div class="d2l-tabs-scroll-next-container">
|
@@ -330,7 +332,8 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
330
332
|
<div class="${classMap(panelContainerClasses)}"
|
331
333
|
@d2l-tab-panel-selected="${this._handlePanelSelected}"
|
332
334
|
@d2l-tab-panel-text-changed="${this._handlePanelTextChange}">
|
333
|
-
<slot @slotchange="${this.
|
335
|
+
<slot @slotchange="${this._handleDefaultSlotChange}"></slot>
|
336
|
+
<slot name="panels"></slot>
|
334
337
|
</div>
|
335
338
|
`;
|
336
339
|
}
|
@@ -340,7 +343,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
340
343
|
}
|
341
344
|
|
342
345
|
async getLoadingComplete() {
|
343
|
-
return this._loadingCompletePromise;
|
346
|
+
return this._defaultSlotBehavior ? this._loadingCompletePromise : true;
|
344
347
|
}
|
345
348
|
|
346
349
|
getTabListRect() {
|
@@ -495,6 +498,16 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
495
498
|
}
|
496
499
|
|
497
500
|
_getPanel(id) {
|
501
|
+
if (this._defaultSlotBehavior) return this._getPanelDefaultSlotBehavior(id);
|
502
|
+
|
503
|
+
if (!this.shadowRoot) return;
|
504
|
+
const slot = this.shadowRoot.querySelector('slot[name="panels"]');
|
505
|
+
const panels = this._getPanels(slot);
|
506
|
+
return panels.find(panel => panel.labelledBy === id);
|
507
|
+
}
|
508
|
+
|
509
|
+
// remove after d2l-tab/d2l-tab-panel backport
|
510
|
+
_getPanelDefaultSlotBehavior(id) {
|
498
511
|
if (!this.shadowRoot) return;
|
499
512
|
// use simple selector for slot (Edge)
|
500
513
|
const slot = this.shadowRoot.querySelector('.d2l-panels-container').querySelector('slot');
|
@@ -508,30 +521,16 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
508
521
|
|
509
522
|
_getPanels(slot) {
|
510
523
|
if (!slot) return;
|
511
|
-
return slot.
|
512
|
-
.filter((node) => node.nodeType === Node.ELEMENT_NODE && node.role === 'tabpanel');
|
524
|
+
return slot.assignedElements({ flatten: true }).filter((node) => node.role === 'tabpanel');
|
513
525
|
}
|
514
526
|
|
527
|
+
// remove after d2l-tab/d2l-tab-panel backport
|
515
528
|
_getTabInfo(id) {
|
516
529
|
return this._tabInfos.find((t) => t.id === id);
|
517
530
|
}
|
518
531
|
|
519
|
-
|
520
|
-
if (
|
521
|
-
this._resetFocusables();
|
522
|
-
}
|
523
|
-
|
524
|
-
_handlePanelSelected(e) {
|
525
|
-
const tabInfo = this._getTabInfo(e.target.id);
|
526
|
-
// event could be from nested tabs
|
527
|
-
if (!tabInfo) return;
|
528
|
-
|
529
|
-
this._setFocusable(tabInfo);
|
530
|
-
tabInfo.selected = true;
|
531
|
-
this.requestUpdate();
|
532
|
-
}
|
533
|
-
|
534
|
-
async _handlePanelsSlotChange(e) {
|
532
|
+
async _handleDefaultSlotChange(e) {
|
533
|
+
if (!this._defaultSlotBehavior) return;
|
535
534
|
|
536
535
|
const panels = this._getPanels(e.target);
|
537
536
|
|
@@ -611,10 +610,24 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
611
610
|
});
|
612
611
|
}
|
613
612
|
|
614
|
-
|
615
|
-
'd2l-tabs-initialized', { bubbles: true, composed: true }
|
616
|
-
));
|
613
|
+
}
|
617
614
|
|
615
|
+
_handleFocusOut(e) {
|
616
|
+
if (e.relatedTarget && e.relatedTarget.role === 'tab') return;
|
617
|
+
this._resetFocusables();
|
618
|
+
}
|
619
|
+
|
620
|
+
// remove after d2l-tab/d2l-tab-panel backport
|
621
|
+
_handlePanelSelected(e) {
|
622
|
+
if (!this._defaultSlotBehavior) return;
|
623
|
+
|
624
|
+
const tabInfo = this._getTabInfo(e.target.id);
|
625
|
+
// event could be from nested tabs
|
626
|
+
if (!tabInfo) return;
|
627
|
+
|
628
|
+
this._setFocusable(tabInfo);
|
629
|
+
tabInfo.selected = true;
|
630
|
+
this.requestUpdate();
|
618
631
|
}
|
619
632
|
|
620
633
|
async _handlePanelTextChange(e) {
|
@@ -713,6 +726,35 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
713
726
|
}
|
714
727
|
|
715
728
|
async _handleTabSelected(e) {
|
729
|
+
if (this._defaultSlotBehavior) {
|
730
|
+
this._handleTabSelectedDefaultSlotBehavior(e);
|
731
|
+
return;
|
732
|
+
}
|
733
|
+
|
734
|
+
const selectedTab = e.target;
|
735
|
+
const selectedPanel = this._getPanel(e.target.id);
|
736
|
+
selectedTab.tabIndex = 0;
|
737
|
+
|
738
|
+
await this.updateComplete;
|
739
|
+
|
740
|
+
selectedPanel.selected = true;
|
741
|
+
this._tabs.forEach((tab) => {
|
742
|
+
if (tab.id !== selectedTab.id) {
|
743
|
+
if (tab.selected) {
|
744
|
+
tab.selected = false;
|
745
|
+
const panel = this._getPanel(tab.id);
|
746
|
+
// panel may not exist if it's being removed
|
747
|
+
if (panel) panel.selected = false;
|
748
|
+
}
|
749
|
+
if (tab.tabIndex === 0) tab.tabIndex = -1;
|
750
|
+
}
|
751
|
+
});
|
752
|
+
|
753
|
+
this.requestUpdate();
|
754
|
+
}
|
755
|
+
|
756
|
+
// remove after d2l-tab/d2l-tab-panel backport
|
757
|
+
async _handleTabSelectedDefaultSlotBehavior(e) {
|
716
758
|
e.stopPropagation();
|
717
759
|
|
718
760
|
const selectedTab = e.target;
|
@@ -739,6 +781,38 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
|
|
739
781
|
this.requestUpdate();
|
740
782
|
}
|
741
783
|
|
784
|
+
async _handleTabsSlotChange(e) {
|
785
|
+
this._defaultSlotBehavior = false;
|
786
|
+
|
787
|
+
this._tabs = e.target.assignedElements({ flatten: true }).filter((node) => node.role === 'tab');
|
788
|
+
|
789
|
+
// handle case where there are less than two tabs initially
|
790
|
+
this._updateTabListVisibility(this._tabs);
|
791
|
+
|
792
|
+
if (!this._initialized && this._tabs.length === 0) return;
|
793
|
+
|
794
|
+
let selectedTab;
|
795
|
+
if (this._tabs.length > 0) {
|
796
|
+
selectedTab = this._tabs.find((tab) => tab.state !== 'removing');
|
797
|
+
if (selectedTab) {
|
798
|
+
selectedTab.selected = true;
|
799
|
+
selectedTab.tabIndex = 0;
|
800
|
+
}
|
801
|
+
}
|
802
|
+
|
803
|
+
await this.updateComplete;
|
804
|
+
|
805
|
+
if (!this._initialized && this._tabs.length > 0) {
|
806
|
+
this._initialized = true;
|
807
|
+
}
|
808
|
+
|
809
|
+
if (selectedTab) {
|
810
|
+
// set corresponding panel to selected
|
811
|
+
const selectedPanel = this._getPanel(selectedTab.id);
|
812
|
+
if (selectedPanel) selectedPanel.selected = true;
|
813
|
+
}
|
814
|
+
}
|
815
|
+
|
742
816
|
_isPositionInLeftScrollArea(position) {
|
743
817
|
return position > 0 && position < scrollButtonWidth;
|
744
818
|
}
|
package/custom-elements.json
CHANGED
@@ -12838,6 +12838,11 @@
|
|
12838
12838
|
"description": "ACCESSIBILITY: REQUIRED: The text used for the tab, as well as labelling the panel.",
|
12839
12839
|
"type": "string"
|
12840
12840
|
},
|
12841
|
+
{
|
12842
|
+
"name": "role",
|
12843
|
+
"type": "string",
|
12844
|
+
"default": "\"tab\""
|
12845
|
+
},
|
12841
12846
|
{
|
12842
12847
|
"name": "selected",
|
12843
12848
|
"type": "boolean",
|
@@ -12856,13 +12861,9 @@
|
|
12856
12861
|
"description": "ACCESSIBILITY: REQUIRED: The text used for the tab, as well as labelling the panel.",
|
12857
12862
|
"type": "string"
|
12858
12863
|
},
|
12859
|
-
{
|
12860
|
-
"name": "ariaSelected",
|
12861
|
-
"type": "boolean",
|
12862
|
-
"default": "false"
|
12863
|
-
},
|
12864
12864
|
{
|
12865
12865
|
"name": "role",
|
12866
|
+
"attribute": "role",
|
12866
12867
|
"type": "string",
|
12867
12868
|
"default": "\"tab\""
|
12868
12869
|
},
|
@@ -12872,11 +12873,6 @@
|
|
12872
12873
|
"type": "boolean",
|
12873
12874
|
"default": "false"
|
12874
12875
|
},
|
12875
|
-
{
|
12876
|
-
"name": "tabIndex",
|
12877
|
-
"type": "number",
|
12878
|
-
"default": "-1"
|
12879
|
-
},
|
12880
12876
|
{
|
12881
12877
|
"name": "skeleton",
|
12882
12878
|
"attribute": "skeleton",
|
@@ -12935,12 +12931,6 @@
|
|
12935
12931
|
"type": "boolean"
|
12936
12932
|
}
|
12937
12933
|
],
|
12938
|
-
"events": [
|
12939
|
-
{
|
12940
|
-
"name": "d2l-tabs-initialized",
|
12941
|
-
"description": "Dispatched when the component is initialized"
|
12942
|
-
}
|
12943
|
-
],
|
12944
12934
|
"slots": [
|
12945
12935
|
{
|
12946
12936
|
"name": "",
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@brightspace-ui/core",
|
3
|
-
"version": "3.
|
3
|
+
"version": "3.93.0",
|
4
4
|
"description": "A collection of accessible, free, open-source web components for building Brightspace applications",
|
5
5
|
"type": "module",
|
6
6
|
"repository": "https://github.com/BrightspaceUI/core.git",
|