@brightspace-ui/core 3.94.2 → 3.95.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.
@@ -193,6 +193,9 @@
193
193
  document.addEventListener('d2l-tab-panel-text-changed', (e) => {
194
194
  console.log('tab panel text changed', e);
195
195
  });
196
+ document.addEventListener('d2l-tab-content-change', (e) => {
197
+ console.log('tab content changed', e);
198
+ });
196
199
  </script>
197
200
 
198
201
  </body>
@@ -112,6 +112,16 @@ export const TabMixin = superclass => class extends SkeletonMixin(superclass) {
112
112
  }
113
113
  }
114
114
 
115
+ /**
116
+ * IMPORTANT: Call this in any consumer when anything changes that could impact the tab's size
117
+ * Notifies the parent d2l-tabs component of a change so that it can update virtual scrolling calculations
118
+ * */
119
+ dispatchContentChangeEvent() {
120
+ this.dispatchEvent(new CustomEvent(
121
+ 'd2l-tab-content-change', { bubbles: true, composed: true }
122
+ ));
123
+ }
124
+
115
125
  renderContent() {
116
126
  console.warn('Subclasses to implement/override renderContent');
117
127
  return html`<div>Default Tab Content</div>`;
@@ -3,6 +3,9 @@ import { classMap } from 'lit/directives/class-map.js';
3
3
  import { getFocusPseudoClass } from '../../helpers/focus.js';
4
4
  import { TabMixin } from './tab-mixin.js';
5
5
 
6
+ /**
7
+ * @fires d2l-tab-content-change - Dispatched when the text attribute is changed. Triggers virtual scrolling calculations in parent d2l-tabs.
8
+ */
6
9
  class Tab extends TabMixin(LitElement) {
7
10
 
8
11
  static get properties() {
@@ -38,6 +41,14 @@ class Tab extends TabMixin(LitElement) {
38
41
  return styles;
39
42
  }
40
43
 
44
+ updated(changedProperties) {
45
+ super.updated(changedProperties);
46
+
47
+ if (changedProperties.has('text')) {
48
+ this.dispatchContentChangeEvent();
49
+ }
50
+ }
51
+
41
52
  renderContent() {
42
53
  const contentClasses = {
43
54
  'd2l-tab-text': true,
@@ -242,33 +242,61 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
242
242
  super.firstUpdated(changedProperties);
243
243
 
244
244
  this.arrowKeysFocusablesProvider = async() => {
245
- return [...this.shadowRoot.querySelectorAll('d2l-tab-internal')];
245
+ return this._defaultSlotBehavior ? [...this.shadowRoot.querySelectorAll('d2l-tab-internal')] : this._tabs;
246
246
  };
247
247
 
248
248
  this.arrowKeysOnBeforeFocus = async(tab) => {
249
- const tabInfo = this._getTabInfo(tab.controlsPanel);
250
- this._setFocusable(tabInfo);
249
+ if (this._defaultSlotBehavior) {
250
+ // remove this section after d2l-tab/d2l-tab-panel backport
251
+ const tabInfo = this._getTabInfo(tab.controlsPanel);
252
+ this._setFocusableDefaultSlotBehavior(tabInfo);
251
253
 
252
- this.requestUpdate();
253
- await this.updateComplete;
254
-
255
- if (!this._scrollCollapsed) {
256
- return this._updateScrollPositionDefaultSlotBehavior(tabInfo);
257
- } else {
258
- const measures = this._getMeasures();
259
- const newTranslationValue = this._calculateScrollPositionDefaultSlotBehavior(tabInfo, measures);
254
+ this.requestUpdate();
255
+ await this.updateComplete;
260
256
 
261
- if (!this.#isRTL()) {
262
- if (newTranslationValue >= 0) return;
257
+ if (!this._scrollCollapsed) {
258
+ return this._updateScrollPositionDefaultSlotBehavior(tabInfo);
263
259
  } else {
264
- if (newTranslationValue <= 0) return;
260
+ const measures = this._getMeasures();
261
+ const newTranslationValue = this._calculateScrollPositionDefaultSlotBehavior(tabInfo, measures);
262
+
263
+ if (!this.#isRTL()) {
264
+ if (newTranslationValue >= 0) return;
265
+ } else {
266
+ if (newTranslationValue <= 0) return;
267
+ }
268
+
269
+ const expanded = await this._tryExpandTabsContainer(measures);
270
+ if (expanded) {
271
+ return;
272
+ } else {
273
+ return this._updateScrollPositionDefaultSlotBehavior(tabInfo);
274
+ }
265
275
  }
276
+ } else {
277
+ this._setFocusable(tab);
266
278
 
267
- const expanded = await this._tryExpandTabsContainer(measures);
268
- if (expanded) {
269
- return;
279
+ this.requestUpdate();
280
+ await this.updateComplete;
281
+
282
+ if (!this._scrollCollapsed) {
283
+ return this._updateScrollPosition(tab);
270
284
  } else {
271
- return this._updateScrollPositionDefaultSlotBehavior(tabInfo);
285
+ const measures = this._getMeasures();
286
+ const newTranslationValue = this._calculateScrollPosition(tab, measures);
287
+
288
+ if (!this.#isRTL()) {
289
+ if (newTranslationValue >= 0) return;
290
+ } else {
291
+ if (newTranslationValue <= 0) return;
292
+ }
293
+
294
+ const expanded = await this._tryExpandTabsContainer(measures);
295
+ if (expanded) {
296
+ return;
297
+ } else {
298
+ return this._updateScrollPosition(tab);
299
+ }
272
300
  }
273
301
  }
274
302
  };
@@ -315,6 +343,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
315
343
  </div>
316
344
  ${this.arrowKeysContainer(html`
317
345
  <div class="d2l-tabs-container-list"
346
+ @d2l-tab-content-change="${this._handleTabContentChange}"
318
347
  @d2l-tab-selected="${this._handleTabSelected}"
319
348
  @focusout="${this._handleFocusOut}"
320
349
  aria-label="${ifDefined(this.text)}"
@@ -411,6 +440,21 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
411
440
  }
412
441
 
413
442
  async _focusSelected() {
443
+ if (this._defaultSlotBehavior) {
444
+ this._focusSelectedDefaultSlotBehavior();
445
+ return;
446
+ }
447
+
448
+ const selectedTab = this._tabs.find(ti => ti.selected);
449
+ if (!selectedTab) return;
450
+
451
+ await this._updateScrollPosition(selectedTab);
452
+
453
+ selectedTab.focus();
454
+ }
455
+
456
+ // remove after d2l-tab/d2l-tab-panel backport
457
+ async _focusSelectedDefaultSlotBehavior() {
414
458
  const selectedTab = this.shadowRoot && this.shadowRoot.querySelector('d2l-tab-internal[aria-selected="true"]');
415
459
  if (!selectedTab) return;
416
460
 
@@ -498,7 +542,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
498
542
  };
499
543
  if (tabInfo.selected) {
500
544
  selectedTabInfo = tabInfo;
501
- this._setFocusable(tabInfo);
545
+ this._setFocusableDefaultSlotBehavior(tabInfo);
502
546
  }
503
547
  return tabInfo;
504
548
  });
@@ -566,7 +610,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
566
610
  // event could be from nested tabs
567
611
  if (!tabInfo) return;
568
612
 
569
- this._setFocusable(tabInfo);
613
+ this._setFocusableDefaultSlotBehavior(tabInfo);
570
614
  tabInfo.selected = true;
571
615
  this.requestUpdate();
572
616
  }
@@ -579,6 +623,7 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
579
623
  this.#setAriaControls();
580
624
  }
581
625
 
626
+ // remove after d2l-tab/d2l-tab-panel backport
582
627
  async _handlePanelTextChange(e) {
583
628
  const tabInfo = this._getTabInfo(e.target.id);
584
629
  // event could be from nested tabs
@@ -674,6 +719,11 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
674
719
 
675
720
  }
676
721
 
722
+ async _handleTabContentChange() {
723
+ this._updateMeasures();
724
+ await this._updateScrollVisibility(this._getMeasures());
725
+ }
726
+
677
727
  async _handleTabSelected(e) {
678
728
  if (this._defaultSlotBehavior) {
679
729
  this._handleTabSelectedDefaultSlotBehavior(e);
@@ -757,8 +807,13 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
757
807
  }
758
808
 
759
809
  _resetFocusables() {
760
- const selectedTab = this._tabInfos.find(ti => ti.selected);
761
- if (selectedTab) this._setFocusable(selectedTab);
810
+ if (this._defaultSlotBehavior) {
811
+ const selectedTab = this._tabInfos.find(ti => ti.selected);
812
+ if (selectedTab) this._setFocusableDefaultSlotBehavior(selectedTab);
813
+ } else {
814
+ const selectedTab = this._tabs.find(ti => ti.selected);
815
+ if (selectedTab) this._setFocusable(selectedTab);
816
+ }
762
817
  this.requestUpdate();
763
818
  }
764
819
 
@@ -783,7 +838,15 @@ class Tabs extends LocalizeCoreElement(ArrowKeysMixin(SkeletonMixin(LitElement))
783
838
  });
784
839
  }
785
840
 
786
- _setFocusable(tabInfo) {
841
+ _setFocusable(tab) {
842
+ const currentFocusable = this._tabs.find(tab => tab.tabIndex === 0);
843
+ if (currentFocusable) currentFocusable.tabIndex = -1;
844
+
845
+ tab.tabIndex = 0;
846
+ }
847
+
848
+ // remove after d2l-tab/d2l-tab-panel backport
849
+ _setFocusableDefaultSlotBehavior(tabInfo) {
787
850
  const currentFocusable = this._tabInfos.find(ti => ti.activeFocusable);
788
851
  if (currentFocusable) currentFocusable.activeFocusable = false;
789
852
 
@@ -12892,6 +12892,10 @@
12892
12892
  }
12893
12893
  ],
12894
12894
  "events": [
12895
+ {
12896
+ "name": "d2l-tab-content-change",
12897
+ "description": "Dispatched when the text attribute is changed. Triggers virtual scrolling calculations in parent d2l-tabs."
12898
+ },
12895
12899
  {
12896
12900
  "name": "d2l-tab-selected"
12897
12901
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.94.2",
3
+ "version": "3.95.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",