@brightspace-ui/core 2.85.9 → 2.86.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/list/demo/list.html +9 -9
- package/components/selection/selection-controls.js +2 -1
- package/components/table/demo/table-test.js +35 -29
- package/components/table/demo/table.html +29 -4
- package/components/table/table-controls.js +2 -1
- package/components/table/table-wrapper.js +108 -45
- package/components/tooltip/demo/tooltip.html +7 -4
- package/components/tooltip/tooltip.js +13 -0
- package/custom-elements.json +18 -0
- package/package.json +1 -1
|
@@ -84,16 +84,16 @@
|
|
|
84
84
|
<d2l-demo-snippet>
|
|
85
85
|
<template>
|
|
86
86
|
<d2l-list grid>
|
|
87
|
-
<d2l-list-item selectable key="1" label="Introductory Earth Sciences">
|
|
87
|
+
<d2l-list-item no-primary-action selectable key="1" label="Introductory Earth Sciences">
|
|
88
88
|
<img slot="illustration" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg"></img>
|
|
89
89
|
<div>
|
|
90
90
|
<d2l-list-item-content>
|
|
91
91
|
<div>Introductory Earth Sciences</div>
|
|
92
92
|
</d2l-list-item-content>
|
|
93
93
|
<d2l-tag-list description="Tags for this course">
|
|
94
|
-
<d2l-tag-list-item text="Science"></d2l-tag-list-item>
|
|
95
|
-
<d2l-tag-list-item text="Environment"></d2l-tag-list-item>
|
|
96
|
-
<d2l-tag-list-item text="Earth"></d2l-tag-list-item>
|
|
94
|
+
<d2l-tag-list-item text="Science" description="This is a description for the Science tag that is really really really long and will overflow onto the next line."></d2l-tag-list-item>
|
|
95
|
+
<d2l-tag-list-item text="Environment" description="This is a description for the Environment tag."></d2l-tag-list-item>
|
|
96
|
+
<d2l-tag-list-item text="Earth" description="This is a description for the Earth tag."></d2l-tag-list-item>
|
|
97
97
|
</d2l-tag-list>
|
|
98
98
|
</div>
|
|
99
99
|
<div slot="actions">
|
|
@@ -116,8 +116,8 @@
|
|
|
116
116
|
<div>Engineering Materials for Energy Systems</div>
|
|
117
117
|
</d2l-list-item-content>
|
|
118
118
|
<d2l-tag-list description="Tags for this course">
|
|
119
|
-
<d2l-tag-list-item text="Engineering"></d2l-tag-list-item>
|
|
120
|
-
<d2l-tag-list-item text="Energy Systems"></d2l-tag-list-item>
|
|
119
|
+
<d2l-tag-list-item text="Engineering" description="This is a description for the Engineering tag."></d2l-tag-list-item>
|
|
120
|
+
<d2l-tag-list-item text="Energy Systems" description="This is a description for the Energy Systems tag."></d2l-tag-list-item>
|
|
121
121
|
</d2l-tag-list>
|
|
122
122
|
</div>
|
|
123
123
|
<div slot="actions">
|
|
@@ -140,9 +140,9 @@
|
|
|
140
140
|
<div>Geomorphology and GIS</div>
|
|
141
141
|
</d2l-list-item-content>
|
|
142
142
|
<d2l-tag-list description="Tags for this course">
|
|
143
|
-
<d2l-tag-list-item text="Geology"></d2l-tag-list-item>
|
|
144
|
-
<d2l-tag-list-item text="GIS"></d2l-tag-list-item>
|
|
145
|
-
<d2l-tag-list-item text="Earth Sciences"></d2l-tag-list-item>
|
|
143
|
+
<d2l-tag-list-item text="Geology" description="This is a description for the Geology tag."></d2l-tag-list-item>
|
|
144
|
+
<d2l-tag-list-item text="GIS" description="This is a description for the GIS tag."></d2l-tag-list-item>
|
|
145
|
+
<d2l-tag-list-item text="Earth Sciences" description="This is a description for the Earth Sciences tag."></d2l-tag-list-item>
|
|
146
146
|
</d2l-tag-list>
|
|
147
147
|
</div>
|
|
148
148
|
<div slot="actions">
|
|
@@ -26,7 +26,7 @@ export class SelectionControls extends SelectionObserverMixin(RtlMixin(LocalizeC
|
|
|
26
26
|
* Disables sticky positioning for the controls
|
|
27
27
|
* @type {boolean}
|
|
28
28
|
*/
|
|
29
|
-
noSticky: { type: Boolean, attribute: 'no-sticky' },
|
|
29
|
+
noSticky: { type: Boolean, attribute: 'no-sticky', reflect: true },
|
|
30
30
|
/**
|
|
31
31
|
* Whether all pages can be selected
|
|
32
32
|
* @type {boolean}
|
|
@@ -59,6 +59,7 @@ export class SelectionControls extends SelectionObserverMixin(RtlMixin(LocalizeC
|
|
|
59
59
|
bottom: -4px;
|
|
60
60
|
box-shadow: 0 8px 12px -9px rgba(0, 0, 0, 0.3);
|
|
61
61
|
clip: rect(30px, auto, 200px, auto);
|
|
62
|
+
display: var(--d2l-selection-controls-shadow-display, block);
|
|
62
63
|
height: 40px;
|
|
63
64
|
position: absolute;
|
|
64
65
|
width: 100%;
|
|
@@ -15,6 +15,7 @@ import { DemoPassthroughMixin } from '../../demo/demo-passthrough-mixin.js';
|
|
|
15
15
|
import { RtlMixin } from '../../../mixins/rtl-mixin.js';
|
|
16
16
|
|
|
17
17
|
const fruits = ['Apples', 'Oranges', 'Bananas'];
|
|
18
|
+
const thText = ['Additional', 'Placeholder', 'Header', 'Row'];
|
|
18
19
|
|
|
19
20
|
const data = () => [
|
|
20
21
|
{ name: 'Canada', fruit: { 'apples': 356863, 'oranges': 0, 'bananas': 0 }, selected: true },
|
|
@@ -32,6 +33,8 @@ class TestTable extends RtlMixin(DemoPassthroughMixin(TableWrapper, 'd2l-table-w
|
|
|
32
33
|
|
|
33
34
|
static get properties() {
|
|
34
35
|
return {
|
|
36
|
+
stickyControls: { attribute: 'sticky-controls', type: Boolean, reflect: true },
|
|
37
|
+
visibleBackground: { attribute: 'visible-background', type: Boolean, reflect: true },
|
|
35
38
|
_data: { state: true },
|
|
36
39
|
_sortField: { attribute: false, type: String },
|
|
37
40
|
_sortDesc: { attribute: false, type: Boolean }
|
|
@@ -43,6 +46,9 @@ class TestTable extends RtlMixin(DemoPassthroughMixin(TableWrapper, 'd2l-table-w
|
|
|
43
46
|
:host {
|
|
44
47
|
display: block;
|
|
45
48
|
}
|
|
49
|
+
:host([visible-background]) {
|
|
50
|
+
--d2l-table-controls-background-color: #dddddd;
|
|
51
|
+
}
|
|
46
52
|
`];
|
|
47
53
|
}
|
|
48
54
|
|
|
@@ -60,45 +66,37 @@ class TestTable extends RtlMixin(DemoPassthroughMixin(TableWrapper, 'd2l-table-w
|
|
|
60
66
|
});
|
|
61
67
|
return html`
|
|
62
68
|
<d2l-table-wrapper>
|
|
63
|
-
<d2l-table-controls slot="controls" no-sticky>
|
|
64
|
-
<d2l-selection-action
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
</d2l-menu>
|
|
75
|
-
</d2l-menu-item>
|
|
76
|
-
</d2l-menu>
|
|
77
|
-
</d2l-dropdown-menu>
|
|
78
|
-
</d2l-selection-action-dropdown>
|
|
79
|
-
<d2l-dropdown-button-subtle text="Actions">
|
|
80
|
-
<d2l-dropdown-menu>
|
|
81
|
-
<d2l-menu label="Actions">
|
|
82
|
-
<d2l-selection-action-menu-item text="Bookmark (requires selection)" requires-selection></d2l-selection-action-menu-item>
|
|
83
|
-
<d2l-selection-action-menu-item text="Advanced"></d2l-selection-action-menu-item>
|
|
84
|
-
</d2l-menu>
|
|
85
|
-
</d2l-dropdown-menu>
|
|
86
|
-
</d2l-dropdown-button-subtle>
|
|
87
|
-
<d2l-selection-action icon="tier1:gear" text="Settings" requires-selection></d2l-selection-action>
|
|
69
|
+
<d2l-table-controls slot="controls" ?no-sticky="${!this.stickyControls}">
|
|
70
|
+
<d2l-selection-action
|
|
71
|
+
text="Sticky controls"
|
|
72
|
+
icon="tier1:${this.stickyControls ? 'check' : 'close-default'}"
|
|
73
|
+
@d2l-selection-action-click="${this._toggleStickyControls}"
|
|
74
|
+
></d2l-selection-action>
|
|
75
|
+
<d2l-selection-action
|
|
76
|
+
text="Sticky headers"
|
|
77
|
+
icon="tier1:${this.stickyHeaders ? 'check' : 'close-default'}"
|
|
78
|
+
@d2l-selection-action-click="${this._toggleStickyHeaders}"
|
|
79
|
+
></d2l-selection-action>
|
|
88
80
|
</d2l-table-controls>
|
|
89
81
|
|
|
90
82
|
<table class="d2l-table">
|
|
91
83
|
<thead>
|
|
92
84
|
<tr>
|
|
93
|
-
<th scope="col"><d2l-selection-select-all></d2l-selection-select-all></th>
|
|
85
|
+
<th scope="col" sticky><d2l-selection-select-all></d2l-selection-select-all></th>
|
|
94
86
|
<th scope="col">Country</th>
|
|
95
87
|
${fruits.map(fruit => this._renderSortButton(fruit))}
|
|
96
88
|
</tr>
|
|
89
|
+
${[1, 2].map(() => html`
|
|
90
|
+
<tr>
|
|
91
|
+
<th scope="col" sticky></th>
|
|
92
|
+
${thText.map(text => html`<th scope="col">${text}</th>`)}
|
|
93
|
+
</tr>
|
|
94
|
+
`)}
|
|
97
95
|
</thead>
|
|
98
96
|
<tbody>
|
|
99
|
-
${sorted.map(
|
|
97
|
+
${sorted.map(row => html`
|
|
100
98
|
<tr ?selected="${row.selected}" data-name="${row.name}">
|
|
101
|
-
<th scope="row">
|
|
99
|
+
<th scope="row" sticky>
|
|
102
100
|
<d2l-selection-input
|
|
103
101
|
@d2l-selection-change="${this._selectRow}"
|
|
104
102
|
?selected="${row.selected}"
|
|
@@ -107,7 +105,7 @@ class TestTable extends RtlMixin(DemoPassthroughMixin(TableWrapper, 'd2l-table-w
|
|
|
107
105
|
</d2l-selection-input>
|
|
108
106
|
</th>
|
|
109
107
|
<th scope="row">${row.name}</th>
|
|
110
|
-
${fruits.map(
|
|
108
|
+
${fruits.map(fruit => html`<td>${formatter.format(row.fruit[fruit.toLowerCase()])}</td>`)}
|
|
111
109
|
</tr>
|
|
112
110
|
`)}
|
|
113
111
|
</tbody>
|
|
@@ -142,5 +140,13 @@ class TestTable extends RtlMixin(DemoPassthroughMixin(TableWrapper, 'd2l-table-w
|
|
|
142
140
|
this.requestUpdate();
|
|
143
141
|
}
|
|
144
142
|
|
|
143
|
+
_toggleStickyControls() {
|
|
144
|
+
this.stickyControls = !this.stickyControls;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
_toggleStickyHeaders() {
|
|
148
|
+
this.stickyHeaders = !this.stickyHeaders;
|
|
149
|
+
}
|
|
150
|
+
|
|
145
151
|
}
|
|
146
152
|
customElements.define('d2l-test-table', TestTable);
|
|
@@ -16,28 +16,53 @@
|
|
|
16
16
|
<h2>Default</h2>
|
|
17
17
|
<d2l-demo-snippet>
|
|
18
18
|
<template>
|
|
19
|
-
<d2l-test-table type="default"></d2l-test-table>
|
|
19
|
+
<d2l-test-table type="default" sticky-controls></d2l-test-table>
|
|
20
20
|
</template>
|
|
21
21
|
</d2l-demo-snippet>
|
|
22
22
|
|
|
23
23
|
<h2>Default, Sticky</h2>
|
|
24
24
|
<d2l-demo-snippet>
|
|
25
25
|
<template>
|
|
26
|
-
<d2l-test-table type="default" sticky-headers></d2l-test-table>
|
|
26
|
+
<d2l-test-table type="default" sticky-headers sticky-controls></d2l-test-table>
|
|
27
27
|
</template>
|
|
28
28
|
</d2l-demo-snippet>
|
|
29
29
|
|
|
30
30
|
<h2>Light</h2>
|
|
31
31
|
<d2l-demo-snippet>
|
|
32
32
|
<template>
|
|
33
|
-
<d2l-test-table type="light"></d2l-test-table>
|
|
33
|
+
<d2l-test-table type="light" sticky-controls></d2l-test-table>
|
|
34
34
|
</template>
|
|
35
35
|
</d2l-demo-snippet>
|
|
36
36
|
|
|
37
37
|
<h2>Light, Sticky</h2>
|
|
38
38
|
<d2l-demo-snippet>
|
|
39
39
|
<template>
|
|
40
|
-
<d2l-test-table type="light" sticky-headers></d2l-test-table>
|
|
40
|
+
<d2l-test-table type="light" sticky-headers sticky-controls></d2l-test-table>
|
|
41
|
+
</template>
|
|
42
|
+
</d2l-demo-snippet>
|
|
43
|
+
|
|
44
|
+
<h2>Default, Visible controls background</h2>
|
|
45
|
+
<d2l-demo-snippet>
|
|
46
|
+
<template>
|
|
47
|
+
<d2l-test-table type="default" sticky-headers sticky-controls visible-background></d2l-test-table>
|
|
48
|
+
</template>
|
|
49
|
+
</d2l-demo-snippet>
|
|
50
|
+
|
|
51
|
+
<h2>Default, Sticky columns</h2>
|
|
52
|
+
<d2l-demo-snippet overflow-hidden>
|
|
53
|
+
<template>
|
|
54
|
+
<div style="overflow: auto; width: 300px;">
|
|
55
|
+
<d2l-test-table type="default" sticky-headers sticky-controls></d2l-test-table>
|
|
56
|
+
</div>
|
|
57
|
+
</template>
|
|
58
|
+
</d2l-demo-snippet>
|
|
59
|
+
|
|
60
|
+
<h2>Default with Scroll-Wrapper (no sticky)</h2>
|
|
61
|
+
<d2l-demo-snippet overflow-hidden>
|
|
62
|
+
<template>
|
|
63
|
+
<div style="height: 300px; overflow: auto;">
|
|
64
|
+
<d2l-test-table type="default" sticky-controls style="width: 300px;"></d2l-test-table>
|
|
65
|
+
</div>
|
|
41
66
|
</template>
|
|
42
67
|
</d2l-demo-snippet>
|
|
43
68
|
|
|
@@ -21,7 +21,8 @@ class TableControls extends SelectionControls {
|
|
|
21
21
|
return [super.styles, css`
|
|
22
22
|
:host {
|
|
23
23
|
--d2l-selection-controls-background-color: var(--d2l-table-controls-background-color);
|
|
24
|
-
|
|
24
|
+
--d2l-selection-controls-shadow-display: var(--d2l-table-controls-shadow-display);
|
|
25
|
+
z-index: 5; /* Must be greater than d2l-table-wrapper and d2l-scroll-wrapper */
|
|
25
26
|
}
|
|
26
27
|
:host([no-sticky]) {
|
|
27
28
|
z-index: auto;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '../colors/colors.js';
|
|
2
2
|
import '../scroll-wrapper/scroll-wrapper.js';
|
|
3
|
-
import { css, html, LitElement } from 'lit';
|
|
3
|
+
import { css, html, LitElement, nothing } from 'lit';
|
|
4
4
|
import { RtlMixin } from '../../mixins/rtl-mixin.js';
|
|
5
5
|
import { SelectionMixin } from '../selection/selection-mixin.js';
|
|
6
6
|
|
|
@@ -119,7 +119,7 @@ export const tableStyles = css`
|
|
|
119
119
|
d2l-table-wrapper[sticky-headers] .d2l-table > * > tr[header] > * {
|
|
120
120
|
position: -webkit-sticky;
|
|
121
121
|
position: sticky;
|
|
122
|
-
|
|
122
|
+
z-index: 2;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
/* header cells that are also sticky */
|
|
@@ -137,21 +137,14 @@ export const tableStyles = css`
|
|
|
137
137
|
right: 0;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
/* first row: offset by size of border-radius so left/right border doesn't show through (default style only) */
|
|
141
|
-
d2l-table-wrapper[sticky-headers][type="default"] .d2l-table > thead > tr > th,
|
|
142
|
-
d2l-table-wrapper[sticky-headers][type="default"] .d2l-table > * > tr.d2l-table-header > *,
|
|
143
|
-
d2l-table-wrapper[sticky-headers][type="default"] .d2l-table > * > tr[header] > * {
|
|
144
|
-
top: -5px;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
140
|
/* first column that's sticky: offset by size of border-radius so top/bottom border doesn't show through (default style only) */
|
|
148
141
|
d2l-table-wrapper[sticky-headers][type="default"]:not([dir="rtl"]) .d2l-table > * > tr > .d2l-table-sticky-cell.d2l-table-cell-first,
|
|
149
142
|
d2l-table-wrapper[sticky-headers][type="default"]:not([dir="rtl"]) .d2l-table > * > tr > [sticky].d2l-table-cell-first {
|
|
150
|
-
left: -
|
|
143
|
+
left: var(--d2l-table-border-radius-sticky-offset);
|
|
151
144
|
}
|
|
152
145
|
d2l-table-wrapper[sticky-headers][type="default"][dir="rtl"] .d2l-table > * > tr > .d2l-table-sticky-cell.d2l-table-cell-first,
|
|
153
146
|
d2l-table-wrapper[sticky-headers][type="default"][dir="rtl"] .d2l-table > * > tr > [sticky].d2l-table-cell-first {
|
|
154
|
-
right: -
|
|
147
|
+
right: var(--d2l-table-border-radius-sticky-offset);
|
|
155
148
|
}
|
|
156
149
|
|
|
157
150
|
/* non-header sticky cells */
|
|
@@ -202,7 +195,8 @@ export class TableWrapper extends RtlMixin(SelectionMixin(LitElement)) {
|
|
|
202
195
|
type: {
|
|
203
196
|
reflect: true,
|
|
204
197
|
type: String
|
|
205
|
-
}
|
|
198
|
+
},
|
|
199
|
+
_controlsScrolled: { state: true }
|
|
206
200
|
};
|
|
207
201
|
}
|
|
208
202
|
|
|
@@ -212,6 +206,7 @@ export class TableWrapper extends RtlMixin(SelectionMixin(LitElement)) {
|
|
|
212
206
|
--d2l-table-border: 1px solid var(--d2l-table-border-color);
|
|
213
207
|
--d2l-table-border-color: var(--d2l-color-mica);
|
|
214
208
|
--d2l-table-border-radius: 0.3rem;
|
|
209
|
+
--d2l-table-border-radius-sticky-offset: calc(1px - var(--d2l-table-border-radius));
|
|
215
210
|
--d2l-table-cell-height: 41px; /* min-height to be 62px including border */
|
|
216
211
|
--d2l-table-cell-padding: 0.5rem 1rem;
|
|
217
212
|
--d2l-table-cell-padding-alt: calc(0.5rem - 1px) 1rem 0.5rem 1rem;
|
|
@@ -225,12 +220,31 @@ export class TableWrapper extends RtlMixin(SelectionMixin(LitElement)) {
|
|
|
225
220
|
display: none;
|
|
226
221
|
}
|
|
227
222
|
:host([type="light"]) {
|
|
223
|
+
--d2l-table-border-radius: 0rem; /* stylelint-disable-line length-zero-no-unit */
|
|
224
|
+
--d2l-table-border-radius-sticky-offset: 0rem; /* stylelint-disable-line length-zero-no-unit */
|
|
228
225
|
--d2l-table-cell-height: 1.15rem; /* min-height to be 48px including border */
|
|
229
226
|
--d2l-table-cell-padding: 0.6rem;
|
|
230
227
|
--d2l-table-cell-padding-alt: calc(0.6rem - 1px) 0.6rem 0.6rem 0.6rem;
|
|
231
228
|
--d2l-table-border-color: var(--d2l-color-gypsum);
|
|
232
229
|
--d2l-table-header-background-color: #ffffff;
|
|
233
230
|
}
|
|
231
|
+
:host([sticky-headers]) {
|
|
232
|
+
--d2l-table-controls-shadow-display: none;
|
|
233
|
+
}
|
|
234
|
+
.d2l-sticky-headers-backdrop {
|
|
235
|
+
position: sticky;
|
|
236
|
+
top: calc(var(--d2l-table-sticky-top) + var(--d2l-table-border-radius));
|
|
237
|
+
width: 100%;
|
|
238
|
+
z-index: 2; /* Must sit under d2l-table sticky-headers but over sticky columns and regular cells */
|
|
239
|
+
}
|
|
240
|
+
.d2l-sticky-headers-backdrop::after {
|
|
241
|
+
background-color: var(--d2l-table-controls-background-color, white);
|
|
242
|
+
bottom: 0;
|
|
243
|
+
content: "";
|
|
244
|
+
position: absolute;
|
|
245
|
+
top: calc(-7px - var(--d2l-table-border-radius)); /* 6px for the d2l-table-controls margin-bottom, 1px overlap to fix zoom issues */
|
|
246
|
+
width: 100%;
|
|
247
|
+
}
|
|
234
248
|
`;
|
|
235
249
|
}
|
|
236
250
|
|
|
@@ -239,6 +253,12 @@ export class TableWrapper extends RtlMixin(SelectionMixin(LitElement)) {
|
|
|
239
253
|
this.noColumnBorder = false;
|
|
240
254
|
this.stickyHeaders = false;
|
|
241
255
|
this.type = 'default';
|
|
256
|
+
|
|
257
|
+
this._controls = null;
|
|
258
|
+
this._controlsMutationObserver = null;
|
|
259
|
+
this._controlsScrolled = false;
|
|
260
|
+
this._controlsScrolledMutationObserver = null;
|
|
261
|
+
this._table = null;
|
|
242
262
|
this._tableIntersectionObserver = null;
|
|
243
263
|
this._tableMutationObserver = null;
|
|
244
264
|
}
|
|
@@ -246,14 +266,17 @@ export class TableWrapper extends RtlMixin(SelectionMixin(LitElement)) {
|
|
|
246
266
|
disconnectedCallback() {
|
|
247
267
|
super.disconnectedCallback();
|
|
248
268
|
|
|
249
|
-
|
|
250
|
-
|
|
269
|
+
this._controlsMutationObserver?.disconnect();
|
|
270
|
+
this._controlsScrolledMutationObserver?.disconnect();
|
|
271
|
+
this._tableMutationObserver?.disconnect();
|
|
272
|
+
this._tableIntersectionObserver?.disconnect();
|
|
251
273
|
}
|
|
252
274
|
|
|
253
275
|
render() {
|
|
254
276
|
const slot = html`<slot @slotchange="${this._handleSlotChange}"></slot>`;
|
|
255
277
|
return html`
|
|
256
|
-
<slot name="controls"></slot>
|
|
278
|
+
<slot name="controls" @slotchange="${this._handleControlsSlotChange}"></slot>
|
|
279
|
+
${this.stickyHeaders && this._controlsScrolled ? html`<div class="d2l-sticky-headers-backdrop"></div>` : nothing}
|
|
257
280
|
${this.stickyHeaders ? slot : html`<d2l-scroll-wrapper>${slot}</d2l-scroll-wrapper>`}
|
|
258
281
|
`;
|
|
259
282
|
}
|
|
@@ -269,15 +292,11 @@ export class TableWrapper extends RtlMixin(SelectionMixin(LitElement)) {
|
|
|
269
292
|
}
|
|
270
293
|
}
|
|
271
294
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
// wait until start of next frame to read
|
|
275
|
-
await new Promise(resolve => {
|
|
276
|
-
requestAnimationFrame(resolve);
|
|
277
|
-
});
|
|
295
|
+
_applyClassNames() {
|
|
296
|
+
if (!this._table) return;
|
|
278
297
|
|
|
279
298
|
// offsetParent causes reflow/paint so do them all at once
|
|
280
|
-
const rows = Array.from(
|
|
299
|
+
const rows = Array.from(this._table.rows);
|
|
281
300
|
let firstRow = null;
|
|
282
301
|
let lastRow = null;
|
|
283
302
|
rows.forEach((r) => {
|
|
@@ -286,13 +305,9 @@ export class TableWrapper extends RtlMixin(SelectionMixin(LitElement)) {
|
|
|
286
305
|
lastRow = r;
|
|
287
306
|
});
|
|
288
307
|
|
|
289
|
-
const topHeader = table.querySelector('tr.d2l-table-header:first-child th:not([rowspan]), tr[header]:first-child th:not([rowspan]), thead tr:first-child th:not([rowspan])');
|
|
290
|
-
const topHeaderHeight = topHeader ? topHeader.clientHeight : -1;
|
|
291
|
-
|
|
292
308
|
let prevRow = null;
|
|
293
309
|
let skipFirst = 0;
|
|
294
310
|
rows.forEach((r) => {
|
|
295
|
-
|
|
296
311
|
const isHeader = r.parentNode.tagName === 'THEAD' || r.classList.contains('d2l-table-header') || r.hasAttribute('header');
|
|
297
312
|
const isSelected = r.hasAttribute('selected');
|
|
298
313
|
|
|
@@ -317,40 +332,54 @@ export class TableWrapper extends RtlMixin(SelectionMixin(LitElement)) {
|
|
|
317
332
|
|
|
318
333
|
prevRow = r;
|
|
319
334
|
skipFirst = Math.max(0, --skipFirst);
|
|
320
|
-
|
|
321
335
|
});
|
|
336
|
+
}
|
|
322
337
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
th.style.top = `${topHeaderHeight + offset}px`;
|
|
328
|
-
});
|
|
338
|
+
async _handleControlsChange() {
|
|
339
|
+
if (this._controls) {
|
|
340
|
+
await this._controls.updateComplete;
|
|
341
|
+
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
329
342
|
}
|
|
330
343
|
|
|
344
|
+
this._handleControlsScrolledChange();
|
|
345
|
+
this._updateStickyTops();
|
|
331
346
|
}
|
|
332
347
|
|
|
333
|
-
|
|
348
|
+
_handleControlsScrolledChange() {
|
|
349
|
+
this._controlsScrolled = this._controls?._scrolled;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
_handleControlsSlotChange(e) {
|
|
353
|
+
this._controls = e.target.assignedNodes({ flatten: true })[0];
|
|
334
354
|
|
|
335
|
-
|
|
355
|
+
this._registerMutationObserver('_controlsMutationObserver', this._handleControlsChange.bind(this), this._controls, {
|
|
356
|
+
attributes: true,
|
|
357
|
+
attributeFilter: ['hidden', 'no-sticky'],
|
|
358
|
+
});
|
|
359
|
+
this._registerMutationObserver('_controlsScrolledMutationObserver', this._handleControlsScrolledChange.bind(this), this._controls, {
|
|
360
|
+
attributes: true,
|
|
361
|
+
attributeFilter: ['_scrolled'],
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
this._handleControlsChange();
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
_handleSlotChange(e) {
|
|
368
|
+
this._table = e.target.assignedNodes({ flatten: true }).find(
|
|
336
369
|
node => (node.nodeType === Node.ELEMENT_NODE && node.tagName === 'TABLE' && node.classList.contains('d2l-table'))
|
|
337
370
|
);
|
|
338
|
-
if (!table) return;
|
|
339
371
|
|
|
340
372
|
// observes mutations to <table>'s direct children and also
|
|
341
373
|
// its subtree (rows or cells added/removed to any descendant)
|
|
342
|
-
|
|
343
|
-
this._tableMutationObserver = new MutationObserver(() => this._applyClassNames(table, 0));
|
|
344
|
-
} else {
|
|
345
|
-
this._tableMutationObserver.disconnect();
|
|
346
|
-
}
|
|
347
|
-
this._tableMutationObserver.observe(table, {
|
|
374
|
+
this._registerMutationObserver('_tableMutationObserver', this._handleTableChange.bind(this), this._table, {
|
|
348
375
|
attributes: true, /* required for legacy-Edge, otherwise attributeFilter throws a syntax error */
|
|
349
376
|
attributeFilter: ['selected'],
|
|
350
377
|
childList: true,
|
|
351
378
|
subtree: true
|
|
352
379
|
});
|
|
353
380
|
|
|
381
|
+
if (!this._table) return;
|
|
382
|
+
|
|
354
383
|
// observes when visibility of <table> changes to catch cases
|
|
355
384
|
// where table is initially hidden (which would cause first/last
|
|
356
385
|
// row classes to be unset) but then becomes shown
|
|
@@ -359,19 +388,53 @@ export class TableWrapper extends RtlMixin(SelectionMixin(LitElement)) {
|
|
|
359
388
|
this._tableIntersectionObserver = new IntersectionObserver((entries) => {
|
|
360
389
|
entries.forEach((entry) => {
|
|
361
390
|
if (entry.isIntersecting) {
|
|
362
|
-
this.
|
|
391
|
+
this._handleTableChange();
|
|
363
392
|
}
|
|
364
393
|
});
|
|
365
394
|
});
|
|
366
395
|
} else {
|
|
367
396
|
this._tableIntersectionObserver.disconnect();
|
|
368
397
|
}
|
|
369
|
-
this._tableIntersectionObserver.observe(
|
|
398
|
+
this._tableIntersectionObserver.observe(this._table);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
this._handleTableChange();
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
async _handleTableChange() {
|
|
405
|
+
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
406
|
+
|
|
407
|
+
this._applyClassNames();
|
|
408
|
+
this._updateStickyTops();
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
_registerMutationObserver(observerName, callback, target, options) {
|
|
412
|
+
if (this[observerName]) {
|
|
413
|
+
this[observerName].disconnect();
|
|
414
|
+
} else if (target) {
|
|
415
|
+
this[observerName] = new MutationObserver(callback);
|
|
370
416
|
}
|
|
417
|
+
if (target) this[observerName].observe(target, options);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
_updateStickyTops() {
|
|
421
|
+
if (!this._table || !this.stickyHeaders) return;
|
|
422
|
+
|
|
423
|
+
const hasStickyControls = this._controls && !this._controls.noSticky;
|
|
424
|
+
let rowTop = hasStickyControls ? this._controls.offsetHeight + 6 : 0; // +6 for the internal `margin-bottom`.
|
|
425
|
+
this.style.setProperty('--d2l-table-sticky-top', `${rowTop}px`);
|
|
371
426
|
|
|
372
|
-
this.
|
|
427
|
+
const stickyRows = Array.from(this._table.querySelectorAll('tr.d2l-table-header, tr[header], thead tr'));
|
|
428
|
+
stickyRows.forEach(r => {
|
|
429
|
+
const thTop = hasStickyControls ? `${rowTop}px` : `calc(${rowTop}px + var(--d2l-table-border-radius-sticky-offset))`;
|
|
430
|
+
const ths = Array.from(r.querySelectorAll('th'));
|
|
431
|
+
ths.forEach(th => th.style.top = thTop);
|
|
373
432
|
|
|
433
|
+
const rowHeight = r.querySelector('th:not([rowspan])')?.offsetHeight || 0;
|
|
434
|
+
rowTop += rowHeight;
|
|
435
|
+
});
|
|
374
436
|
}
|
|
437
|
+
|
|
375
438
|
}
|
|
376
439
|
|
|
377
440
|
customElements.define('d2l-table-wrapper', TableWrapper);
|
|
@@ -71,9 +71,13 @@
|
|
|
71
71
|
<h2>Tooltip (info)</h2>
|
|
72
72
|
<d2l-demo-snippet>
|
|
73
73
|
<template>
|
|
74
|
-
<d2l-button id="tooltip-
|
|
75
|
-
<d2l-tooltip for="tooltip-
|
|
76
|
-
|
|
74
|
+
<d2l-button id="tooltip-preview">Preview</d2l-button>
|
|
75
|
+
<d2l-tooltip for="tooltip-preview">
|
|
76
|
+
Tooltip for the Preview button.
|
|
77
|
+
</d2l-tooltip>
|
|
78
|
+
<d2l-button id="tooltip-settings">Settings</d2l-button>
|
|
79
|
+
<d2l-tooltip for="tooltip-settings">
|
|
80
|
+
Tooltip for the Settings button.
|
|
77
81
|
</d2l-tooltip>
|
|
78
82
|
</template>
|
|
79
83
|
</d2l-demo-snippet>
|
|
@@ -163,7 +167,6 @@
|
|
|
163
167
|
<d2l-tooltip for="link-long" show-truncated-only>
|
|
164
168
|
Very Very Very Very Long Text - this tooltip will show because the text is truncating.
|
|
165
169
|
</d2l-tooltip>
|
|
166
|
-
|
|
167
170
|
</div>
|
|
168
171
|
</template>
|
|
169
172
|
</d2l-demo-snippet>
|
|
@@ -430,6 +430,8 @@ class Tooltip extends RtlMixin(LitElement) {
|
|
|
430
430
|
this._onTargetTouchStart = this._onTargetTouchStart.bind(this);
|
|
431
431
|
this._onTargetTouchEnd = this._onTargetTouchEnd.bind(this);
|
|
432
432
|
|
|
433
|
+
this._onTooltipShowOther = this._onTooltipShowOther.bind(this);
|
|
434
|
+
|
|
433
435
|
this.announced = false;
|
|
434
436
|
this.closeOnClick = false;
|
|
435
437
|
this.delay = 300;
|
|
@@ -474,6 +476,7 @@ class Tooltip extends RtlMixin(LitElement) {
|
|
|
474
476
|
super.disconnectedCallback();
|
|
475
477
|
this._removeListeners();
|
|
476
478
|
window.removeEventListener('resize', this._onTargetResize);
|
|
479
|
+
document.body.removeEventListener('d2l-tooltip-show', this._onTooltipShowOther);
|
|
477
480
|
clearDismissible(this._dismissibleId);
|
|
478
481
|
delayTimeoutId = null;
|
|
479
482
|
this._dismissibleId = null;
|
|
@@ -859,6 +862,11 @@ class Tooltip extends RtlMixin(LitElement) {
|
|
|
859
862
|
}, 500);
|
|
860
863
|
}
|
|
861
864
|
|
|
865
|
+
_onTooltipShowOther() {
|
|
866
|
+
// only allow one tooltip showing at a time
|
|
867
|
+
this.hide();
|
|
868
|
+
}
|
|
869
|
+
|
|
862
870
|
_removeListeners() {
|
|
863
871
|
if (!this._target) {
|
|
864
872
|
return;
|
|
@@ -889,6 +897,9 @@ class Tooltip extends RtlMixin(LitElement) {
|
|
|
889
897
|
this.dispatchEvent(new CustomEvent(
|
|
890
898
|
'd2l-tooltip-show', { bubbles: true, composed: true }
|
|
891
899
|
));
|
|
900
|
+
|
|
901
|
+
document.body.addEventListener('d2l-tooltip-show', this._onTooltipShowOther, true);
|
|
902
|
+
|
|
892
903
|
if (this.announced && !this._isInteractive(this._target)) announce(this.innerText);
|
|
893
904
|
} else {
|
|
894
905
|
this.setAttribute('aria-hidden', 'true');
|
|
@@ -899,6 +910,8 @@ class Tooltip extends RtlMixin(LitElement) {
|
|
|
899
910
|
this.dispatchEvent(new CustomEvent(
|
|
900
911
|
'd2l-tooltip-hide', { bubbles: true, composed: true }
|
|
901
912
|
));
|
|
913
|
+
|
|
914
|
+
document.body.removeEventListener('d2l-tooltip-show', this._onTooltipShowOther, true);
|
|
902
915
|
}
|
|
903
916
|
}
|
|
904
917
|
|
package/custom-elements.json
CHANGED
|
@@ -11015,6 +11015,14 @@
|
|
|
11015
11015
|
"name": "d2l-test-table",
|
|
11016
11016
|
"path": "./components/table/demo/table-test.js",
|
|
11017
11017
|
"attributes": [
|
|
11018
|
+
{
|
|
11019
|
+
"name": "sticky-controls",
|
|
11020
|
+
"type": "boolean"
|
|
11021
|
+
},
|
|
11022
|
+
{
|
|
11023
|
+
"name": "visible-background",
|
|
11024
|
+
"type": "boolean"
|
|
11025
|
+
},
|
|
11018
11026
|
{
|
|
11019
11027
|
"name": "no-column-border",
|
|
11020
11028
|
"description": "Hides the column borders on \"default\" table type",
|
|
@@ -11052,6 +11060,16 @@
|
|
|
11052
11060
|
}
|
|
11053
11061
|
],
|
|
11054
11062
|
"properties": [
|
|
11063
|
+
{
|
|
11064
|
+
"name": "stickyControls",
|
|
11065
|
+
"attribute": "sticky-controls",
|
|
11066
|
+
"type": "boolean"
|
|
11067
|
+
},
|
|
11068
|
+
{
|
|
11069
|
+
"name": "visibleBackground",
|
|
11070
|
+
"attribute": "visible-background",
|
|
11071
|
+
"type": "boolean"
|
|
11072
|
+
},
|
|
11055
11073
|
{
|
|
11056
11074
|
"name": "noColumnBorder",
|
|
11057
11075
|
"attribute": "no-column-border",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightspace-ui/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.86.1",
|
|
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",
|