@brightspace-ui/core 3.33.1 → 3.35.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.
@@ -216,7 +216,10 @@ class HtmlBlock extends LitElement {
216
216
 
217
217
  const contextValsPromise = contextKeysPromise.then(contextKeys => {
218
218
  return Promise.allSettled(contextKeys.map(key => {
219
- return tryGet(key, undefined, ctx => this._context.set(key, ctx));
219
+ return tryGet(key, undefined, ctx => {
220
+ this._context.set(key, ctx);
221
+ this.updated(new Map([['_context']]));
222
+ });
220
223
  }));
221
224
  });
222
225
 
@@ -234,24 +237,17 @@ class HtmlBlock extends LitElement {
234
237
  'd2l-html-block-compact': this.compact
235
238
  };
236
239
 
237
- if (this._embedsFeatureEnabled()) {
238
- return html`
239
- <div class="${classMap(renderContainerClasses)}">
240
- ${!this.noDeferredRendering ? until(this._processEmbeds(), nothing) : nothing}
241
- </div>
242
- ${this.noDeferredRendering ? html`<slot @slotchange="${this._handleSlotChange}"></slot>` : ''}
243
- `;
244
- } else {
245
- return html`
246
- <div class="${classMap(renderContainerClasses)}"></div>
247
- ${this.noDeferredRendering ? html`<slot @slotchange="${this._handleSlotChange}"></slot>` : ''}
248
- `;
249
- }
240
+ return html`
241
+ <div class="${classMap(renderContainerClasses)}">
242
+ ${!this.noDeferredRendering ? until(this._processEmbeds(), nothing) : nothing}
243
+ </div>
244
+ ${this.noDeferredRendering ? html`<slot @slotchange="${this._handleSlotChange}"></slot>` : ''}
245
+ `;
250
246
  }
251
247
 
252
248
  async updated(changedProperties) {
253
249
  super.updated(changedProperties);
254
- if ((changedProperties.has('html') || changedProperties.has('_context')) && this.html !== undefined && this.html !== null && !this.noDeferredRendering) {
250
+ if ((changedProperties.has('embeds') || changedProperties.has('_context')) && this.html !== undefined && this.html !== null && !this.noDeferredRendering) {
255
251
  await this._updateRenderContainer();
256
252
  }
257
253
  }
@@ -260,10 +256,6 @@ class HtmlBlock extends LitElement {
260
256
  return this._renderersProcessedPromise;
261
257
  }
262
258
 
263
- _embedsFeatureEnabled() {
264
- return window.D2L?.LP?.Web?.UI?.Flags.Flag('shield-7574-enable-embed-rendering-framework', true);
265
- }
266
-
267
259
  async _handleSlotChange(e) {
268
260
  if (!e.target || !this.shadowRoot || !this.noDeferredRendering) return;
269
261
  await this._renderInline(e.target);
@@ -272,6 +264,7 @@ class HtmlBlock extends LitElement {
272
264
  async _processEmbeds() {
273
265
  const htmlFragment = document.createRange().createContextualFragment(this.html);
274
266
  await renderEmbeds(htmlFragment);
267
+ this.updated(new Map([['embeds']]));
275
268
  return htmlFragment;
276
269
  }
277
270
 
@@ -315,7 +308,6 @@ class HtmlBlock extends LitElement {
315
308
 
316
309
  async _updateRenderContainer() {
317
310
  const renderContainer = this.shadowRoot.querySelector('.d2l-html-block-rendered');
318
- if (!this._embedsFeatureEnabled()) renderContainer.innerHTML = this.html;
319
311
  await this._processRenderers(renderContainer);
320
312
  }
321
313
 
@@ -41,6 +41,7 @@ class TestTable extends RtlMixin(DemoPassthroughMixin(TableWrapper, 'd2l-table-w
41
41
  static get properties() {
42
42
  return {
43
43
  paging: { type: Boolean, reflect: true },
44
+ multiLine: { type: Boolean, attribute: 'multi-line' },
44
45
  showButtons: { type: Boolean, attribute: 'show-buttons' },
45
46
  stickyControls: { attribute: 'sticky-controls', type: Boolean, reflect: true },
46
47
  visibleBackground: { attribute: 'visible-background', type: Boolean, reflect: true },
@@ -72,6 +73,7 @@ class TestTable extends RtlMixin(DemoPassthroughMixin(TableWrapper, 'd2l-table-w
72
73
  constructor() {
73
74
  super();
74
75
 
76
+ this.multiLine = false;
75
77
  this.paging = false;
76
78
  this.showButtons = false;
77
79
  this.stickyControls = false;
@@ -99,11 +101,25 @@ class TestTable extends RtlMixin(DemoPassthroughMixin(TableWrapper, 'd2l-table-w
99
101
 
100
102
  <table class="d2l-table">
101
103
  <thead>
102
- <tr>
103
- <th scope="col" sticky><d2l-selection-select-all></d2l-selection-select-all></th>
104
- ${this._renderDoubleSortButton('Location')}
105
- ${columns.map(columnHeading => this._renderSortButton(columnHeading))}
106
- </tr>
104
+ ${this.multiLine ? html`
105
+ <tr>
106
+ <th scope="col" sticky><d2l-selection-select-all></d2l-selection-select-all></th>
107
+ ${this._renderDoubleSortButton('Location')}
108
+ <th scope="col" colspan="${columns.length}" sticky>
109
+ Metrics
110
+ </th>
111
+ </tr>
112
+ <tr>
113
+ <th scope="col" sticky></th>
114
+ ${columns.map(columnHeading => this._renderSortButton(columnHeading))}
115
+ </tr>
116
+ ` : html`
117
+ <tr>
118
+ <th scope="col" sticky><d2l-selection-select-all></d2l-selection-select-all></th>
119
+ ${this._renderDoubleSortButton('Location')}
120
+ ${columns.map(columnHeading => this._renderSortButton(columnHeading))}
121
+ </tr>
122
+ `}
107
123
  </thead>
108
124
  <tbody>
109
125
  <tr class="d2l-table-header">
@@ -182,7 +198,7 @@ class TestTable extends RtlMixin(DemoPassthroughMixin(TableWrapper, 'd2l-table-w
182
198
  _renderDoubleSortButton(name) {
183
199
  const noSort = this._sortField?.toLowerCase() !== 'city' && this._sortField?.toLowerCase() !== 'country';
184
200
  return html`
185
- <th scope="col">
201
+ <th rowspan="${this.multiLine ? 2 : 1}" scope="col">
186
202
  <d2l-table-col-sort-button
187
203
  ?desc="${this._sortDesc}"
188
204
  ?nosort="${noSort}">${name}
@@ -80,6 +80,13 @@
80
80
  </template>
81
81
  </d2l-demo-snippet>
82
82
 
83
+ <h2>Multi-line with scroll-wrapper + sticky</h2>
84
+ <d2l-demo-snippet>
85
+ <template>
86
+ <d2l-test-table multi-line sticky-headers sticky-controls sticky-headers-scroll-wrapper style="width: 400px;"></d2l-test-table>
87
+ </template>
88
+ </d2l-demo-snippet>
89
+
83
90
  <div style="margin-bottom: 1000px;"></div>
84
91
  </d2l-demo-page>
85
92
  </body>
@@ -599,16 +599,87 @@ export class TableWrapper extends RtlMixin(PageableMixin(SelectionMixin(LitEleme
599
599
  const body = this._table.querySelector('tbody');
600
600
  if (!head || !body) return;
601
601
 
602
- const firstRowHead = head.rows[0];
603
- const firstRowBody = body.rows[0];
604
- if (!firstRowHead || !firstRowBody || firstRowHead.cells.length !== firstRowBody.cells.length) return;
602
+ const candidateRowHeadCells = [];
605
603
 
606
- for (let i = 0; i < firstRowHead.cells.length; i++) {
607
- const headCell = firstRowHead.cells[i];
608
- const bodyCell = firstRowBody.cells[i];
609
- const bodyStyle = getComputedStyle(bodyCell);
604
+ // Max length of one of our body rows, which we'll try to map to our candidate head cells.
605
+ const maxRowBodyLength = Math.max(...([...body.rows].map(row => row.cells.length)));
606
+
607
+ const headCellsMap = [];
608
+ for (let i = 0; i < head.rows.length; i++) {
609
+ headCellsMap[i] = [];
610
+ }
611
+
612
+ // Build a map of which cells "exist" in each head row so we can pick out
613
+ // a candidate in each column to sync widths with.
614
+ for (let rowIndex = 0; rowIndex < head.rows.length; rowIndex++) {
615
+ const rowMap = headCellsMap[rowIndex];
616
+
617
+ let spanOffset = 0;
618
+ for (let colIndex = 0; colIndex < maxRowBodyLength; colIndex++) {
619
+ if (rowMap[colIndex] === null) {
620
+ spanOffset++;
621
+ continue;
622
+ }
623
+
624
+ const cell = head.rows[rowIndex].cells[colIndex - spanOffset];
625
+ rowMap[colIndex] = cell;
626
+
627
+ if (!cell) continue;
628
+
629
+ const colSpan = cell.colSpan;
630
+ const rowSpan = cell.rowSpan;
631
+
632
+ for (let offset = 1; offset < colSpan; offset++) {
633
+ rowMap[colIndex + offset] = null;
634
+ }
635
+
636
+ for (let offset = 1; offset < rowSpan; offset++) {
637
+ headCellsMap[rowIndex + offset][colIndex] = null;
638
+ }
639
+ }
640
+ }
641
+
642
+ // Pick out a single head cell for each column to sync widths.
643
+ for (let i = 0; i < maxRowBodyLength; i++) {
644
+ let candidateCell;
645
+ for (const rowMap of headCellsMap) {
646
+ const cell = rowMap[i];
647
+
648
+ if (cell && cell.colSpan === 1) {
649
+ candidateCell = cell;
650
+ break;
651
+ }
652
+ }
653
+
654
+ // This does not support heads without at least one single-column
655
+ // spanning cell in each column.
656
+ if (!candidateCell) return;
657
+
658
+ candidateRowHeadCells[i] = candidateCell;
659
+ }
660
+
661
+ // Pick the body row with the most cells (and no colspans) to measure against
662
+ const candidateRowBody = [...body.rows].find(row => {
663
+ return row.cells.length === maxRowBodyLength
664
+ && ![...row.cells].find(cell => cell.colSpan > 1);
665
+ });
666
+
667
+ if (candidateRowHeadCells.length === 0 || !candidateRowBody) return;
668
+
669
+ let candidateRowBodyLength = 0;
670
+ for (const cell of candidateRowBody.cells) {
671
+ candidateRowBodyLength += cell.colSpan;
672
+ }
673
+
674
+ if (candidateRowHeadCells.length !== candidateRowBodyLength) return;
675
+
676
+ for (let i = 0; i < candidateRowHeadCells.length; i++) {
677
+ const headCell = candidateRowHeadCells[i];
610
678
  const headStyle = getComputedStyle(headCell);
611
679
 
680
+ const bodyCell = candidateRowBody.cells[i];
681
+ const bodyStyle = getComputedStyle(bodyCell);
682
+
612
683
  if (headCell.clientWidth > bodyCell.clientWidth) {
613
684
  const headOverallWidth = parseFloat(headStyle.width) + parseFloat(headStyle.paddingLeft) + parseFloat(headStyle.paddingRight);
614
685
  bodyCell.style.minWidth = `${headOverallWidth - parseFloat(bodyStyle.paddingLeft) - parseFloat(bodyStyle.paddingRight)}px`;
@@ -11944,6 +11944,11 @@
11944
11944
  "name": "d2l-test-table",
11945
11945
  "path": "./components/table/demo/table-test.js",
11946
11946
  "attributes": [
11947
+ {
11948
+ "name": "multi-line",
11949
+ "type": "boolean",
11950
+ "default": "false"
11951
+ },
11947
11952
  {
11948
11953
  "name": "paging",
11949
11954
  "type": "boolean",
@@ -12001,6 +12006,12 @@
12001
12006
  }
12002
12007
  ],
12003
12008
  "properties": [
12009
+ {
12010
+ "name": "multiLine",
12011
+ "attribute": "multi-line",
12012
+ "type": "boolean",
12013
+ "default": "false"
12014
+ },
12004
12015
  {
12005
12016
  "name": "paging",
12006
12017
  "attribute": "paging",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.33.1",
3
+ "version": "3.35.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",