@brightspace-ui/core 2.112.8 → 2.114.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.
- package/components/scroll-wrapper/demo/scroll-wrapper-test.js +41 -7
- package/components/scroll-wrapper/demo/scroll-wrapper.html +9 -0
- package/components/scroll-wrapper/scroll-wrapper.js +144 -28
- package/components/selection/README.md +1 -0
- package/components/selection/selection-controls.js +10 -2
- package/components/selection/selection-summary.js +1 -1
- package/components/table/demo/table.html +10 -3
- package/components/table/table-wrapper.js +91 -22
- package/components/tag-list/tag-list-item-mixin.js +26 -13
- package/components/tag-list/tag-list.js +3 -2
- package/custom-elements.json +86 -0
- package/package.json +1 -1
|
@@ -9,7 +9,9 @@ class TestScrollWrapper extends RtlMixin(LitElement) {
|
|
|
9
9
|
return {
|
|
10
10
|
hideActions: { attribute: 'hide-actions', type: Boolean },
|
|
11
11
|
scroll: { attribute: 'scroll', type: Number },
|
|
12
|
-
|
|
12
|
+
splitScrollers: { attribute: 'split-scrollers', type: Boolean },
|
|
13
|
+
width: { type: Number },
|
|
14
|
+
_customScrollers: { state: true }
|
|
13
15
|
};
|
|
14
16
|
}
|
|
15
17
|
|
|
@@ -22,6 +24,16 @@ class TestScrollWrapper extends RtlMixin(LitElement) {
|
|
|
22
24
|
background: linear-gradient(to right, #e66465, #9198e5);
|
|
23
25
|
height: 100px;
|
|
24
26
|
}
|
|
27
|
+
.d2l-scroll-wrapper-gradient-secondary {
|
|
28
|
+
background: linear-gradient(to left, #e66465, #9198e5);
|
|
29
|
+
height: 40px;
|
|
30
|
+
position: relative;
|
|
31
|
+
}
|
|
32
|
+
.d2l-scroll-wrapper-gradient-secondary button {
|
|
33
|
+
inset-inline-end: 0;
|
|
34
|
+
position: absolute;
|
|
35
|
+
top: 0;
|
|
36
|
+
}
|
|
25
37
|
`;
|
|
26
38
|
}
|
|
27
39
|
|
|
@@ -29,24 +41,46 @@ class TestScrollWrapper extends RtlMixin(LitElement) {
|
|
|
29
41
|
super();
|
|
30
42
|
this.hideActions = false;
|
|
31
43
|
this.scroll = 0;
|
|
44
|
+
this.splitScrollers = false;
|
|
32
45
|
this.width = 300;
|
|
46
|
+
this._customScrollers = {};
|
|
33
47
|
}
|
|
34
48
|
|
|
35
49
|
firstUpdated(changedProperties) {
|
|
36
50
|
super.firstUpdated(changedProperties);
|
|
37
|
-
if (this.scroll
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
51
|
+
if (this.scroll !== 0) {
|
|
52
|
+
requestAnimationFrame(() => this.shadowRoot.querySelector('d2l-scroll-wrapper').scrollDistance(this.scroll, false));
|
|
53
|
+
}
|
|
54
|
+
if (this.splitScrollers) {
|
|
55
|
+
this._customScrollers = { primary: this.shadowRoot.querySelector('.primary'), secondary: this.shadowRoot.querySelectorAll('.secondary') };
|
|
56
|
+
}
|
|
41
57
|
}
|
|
42
58
|
|
|
43
59
|
render() {
|
|
44
60
|
const style = {
|
|
45
61
|
width: `${this.width}px`
|
|
46
62
|
};
|
|
47
|
-
|
|
48
|
-
|
|
63
|
+
|
|
64
|
+
const secondaryScroller = html`
|
|
65
|
+
<div class="secondary">
|
|
66
|
+
<div class="d2l-scroll-wrapper-gradient-secondary" style="${styleMap(style)}">
|
|
67
|
+
Secondary scroller (No mouse scroll)
|
|
68
|
+
<button>Focus</button>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
`;
|
|
72
|
+
|
|
73
|
+
const contents = this.splitScrollers ? html`
|
|
74
|
+
${secondaryScroller}
|
|
75
|
+
<div class="primary">
|
|
49
76
|
<div class="d2l-scroll-wrapper-gradient" style="${styleMap(style)}"></div>
|
|
77
|
+
</div>
|
|
78
|
+
${secondaryScroller}
|
|
79
|
+
` : html`<div class="d2l-scroll-wrapper-gradient" style="${styleMap(style)}"></div>`;
|
|
80
|
+
|
|
81
|
+
return html`
|
|
82
|
+
<d2l-scroll-wrapper ?hide-actions="${this.hideActions}" .customScrollers="${this._customScrollers}">
|
|
83
|
+
${contents}
|
|
50
84
|
</d2l-scroll-wrapper>
|
|
51
85
|
`;
|
|
52
86
|
}
|
|
@@ -31,6 +31,15 @@
|
|
|
31
31
|
</template>
|
|
32
32
|
</d2l-demo-snippet>
|
|
33
33
|
|
|
34
|
+
<h2>Split scrollers</h2>
|
|
35
|
+
<d2l-demo-snippet>
|
|
36
|
+
<template>
|
|
37
|
+
<div style="max-width: 700px;">
|
|
38
|
+
<d2l-test-scroll-wrapper width="1000" split-scrollers></d2l-test-scroll-wrapper>
|
|
39
|
+
</div>
|
|
40
|
+
</template>
|
|
41
|
+
</d2l-demo-snippet>
|
|
42
|
+
|
|
34
43
|
</d2l-demo-page>
|
|
35
44
|
</body>
|
|
36
45
|
</html>
|
|
@@ -2,12 +2,37 @@ import '../colors/colors.js';
|
|
|
2
2
|
import '../icons/icon.js';
|
|
3
3
|
import { css, html, LitElement, unsafeCSS } from 'lit';
|
|
4
4
|
import { getFocusPseudoClass } from '../../helpers/focus.js';
|
|
5
|
-
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
6
5
|
import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
|
|
7
6
|
import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
|
|
8
7
|
|
|
9
8
|
const RTL_MULTIPLIER = navigator.userAgent.indexOf('Edge/') > 0 ? 1 : -1; /* legacy-Edge doesn't reverse scrolling in RTL */
|
|
10
9
|
const SCROLL_AMOUNT = 0.8;
|
|
10
|
+
const PRINT_MEDIA_QUERY_LIST = matchMedia('print');
|
|
11
|
+
|
|
12
|
+
let focusStyleSheet;
|
|
13
|
+
function getFocusStyleSheet() {
|
|
14
|
+
if (!focusStyleSheet) {
|
|
15
|
+
focusStyleSheet = new CSSStyleSheet();
|
|
16
|
+
focusStyleSheet.replaceSync(css`
|
|
17
|
+
.d2l-scroll-wrapper-focus:${unsafeCSS(getFocusPseudoClass())} {
|
|
18
|
+
box-shadow: 0 0 0 2px #ffffff, 0 0 0 4px var(--d2l-color-celestine), 0 2px 12px 0 rgba(0, 0, 0, 0.15);
|
|
19
|
+
outline: none;
|
|
20
|
+
}`);
|
|
21
|
+
}
|
|
22
|
+
return focusStyleSheet;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function getStyleSheetInsertionPoint(elem) {
|
|
26
|
+
if (elem.nodeType === Node.DOCUMENT_NODE || elem.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
|
|
27
|
+
if (elem.querySelector('.d2l-scroll-wrapper-focus') !== null) {
|
|
28
|
+
return elem;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (elem.parentNode) {
|
|
32
|
+
return getStyleSheetInsertionPoint(elem.parentNode);
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
11
36
|
|
|
12
37
|
/**
|
|
13
38
|
*
|
|
@@ -18,6 +43,14 @@ class ScrollWrapper extends RtlMixin(LitElement) {
|
|
|
18
43
|
|
|
19
44
|
static get properties() {
|
|
20
45
|
return {
|
|
46
|
+
/**
|
|
47
|
+
* An object containing custom primary/secondary scroll containers
|
|
48
|
+
* @type {Object}
|
|
49
|
+
*/
|
|
50
|
+
customScrollers: {
|
|
51
|
+
attribute: false,
|
|
52
|
+
type: Object
|
|
53
|
+
},
|
|
21
54
|
/**
|
|
22
55
|
* Whether to hide left/right scroll buttons
|
|
23
56
|
* @type {boolean}
|
|
@@ -31,6 +64,7 @@ class ScrollWrapper extends RtlMixin(LitElement) {
|
|
|
31
64
|
reflect: true,
|
|
32
65
|
type: Boolean
|
|
33
66
|
},
|
|
67
|
+
_printMode: { state: true },
|
|
34
68
|
_scrollbarLeft: {
|
|
35
69
|
attribute: 'scrollbar-left',
|
|
36
70
|
reflect: true,
|
|
@@ -55,13 +89,8 @@ class ScrollWrapper extends RtlMixin(LitElement) {
|
|
|
55
89
|
}
|
|
56
90
|
.d2l-scroll-wrapper-container {
|
|
57
91
|
box-sizing: border-box;
|
|
58
|
-
outline: none;
|
|
59
|
-
overflow-x: auto;
|
|
60
92
|
overflow-y: var(--d2l-scroll-wrapper-overflow-y, visible);
|
|
61
93
|
}
|
|
62
|
-
.d2l-scroll-wrapper-container:${unsafeCSS(getFocusPseudoClass())} {
|
|
63
|
-
box-shadow: 0 0 0 2px #ffffff, 0 0 0 4px var(--d2l-color-celestine), 0 2px 12px 0 rgba(0, 0, 0, 0.15);
|
|
64
|
-
}
|
|
65
94
|
:host([h-scrollbar]) .d2l-scroll-wrapper-container {
|
|
66
95
|
border-left: 1px dashed var(--d2l-color-mica);
|
|
67
96
|
border-right: 1px dashed var(--d2l-color-mica);
|
|
@@ -121,47 +150,48 @@ class ScrollWrapper extends RtlMixin(LitElement) {
|
|
|
121
150
|
:host([scrollbar-left]) .d2l-scroll-wrapper-button-left {
|
|
122
151
|
display: none;
|
|
123
152
|
}
|
|
124
|
-
|
|
125
|
-
/* hide wrapper visuals from print view */
|
|
126
|
-
@media print {
|
|
127
|
-
.d2l-scroll-wrapper-actions {
|
|
128
|
-
display: none;
|
|
129
|
-
}
|
|
130
|
-
.d2l-scroll-wrapper-container {
|
|
131
|
-
overflow-x: visible;
|
|
132
|
-
}
|
|
133
|
-
:host([h-scrollbar]) .d2l-scroll-wrapper-container {
|
|
134
|
-
border-left: none;
|
|
135
|
-
border-right: none;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
153
|
`;
|
|
139
154
|
}
|
|
140
155
|
|
|
141
156
|
constructor() {
|
|
142
157
|
super();
|
|
158
|
+
this.customScrollers = {};
|
|
143
159
|
this.hideActions = false;
|
|
160
|
+
this._allScrollers = [];
|
|
161
|
+
this._baseContainer = null;
|
|
144
162
|
this._container = null;
|
|
145
163
|
this._hScrollbar = true;
|
|
146
|
-
this.
|
|
164
|
+
this._printMode = PRINT_MEDIA_QUERY_LIST.matches;
|
|
165
|
+
this._resizeObserver = new ResizeObserver(() => requestAnimationFrame(() => this.checkScrollbar()));
|
|
147
166
|
this._scrollbarLeft = false;
|
|
148
167
|
this._scrollbarRight = false;
|
|
168
|
+
this._syncDriver = null;
|
|
169
|
+
this._syncDriverTimeout = null;
|
|
170
|
+
this._checkScrollThresholds = this._checkScrollThresholds.bind(this);
|
|
171
|
+
this._handlePrintChange = this._handlePrintChange.bind(this);
|
|
172
|
+
this._synchronizeScroll = this._synchronizeScroll.bind(this);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
connectedCallback() {
|
|
176
|
+
super.connectedCallback();
|
|
177
|
+
PRINT_MEDIA_QUERY_LIST?.addEventListener('change', this._handlePrintChange);
|
|
149
178
|
}
|
|
150
179
|
|
|
151
180
|
disconnectedCallback() {
|
|
152
181
|
super.disconnectedCallback();
|
|
153
|
-
|
|
182
|
+
this._disconnectAll();
|
|
183
|
+
PRINT_MEDIA_QUERY_LIST?.removeEventListener('change', this._handlePrintChange);
|
|
154
184
|
}
|
|
155
185
|
|
|
156
186
|
firstUpdated(changedProperties) {
|
|
157
187
|
super.firstUpdated(changedProperties);
|
|
158
|
-
this.
|
|
159
|
-
this._resizeObserver = new ResizeObserver(() => requestAnimationFrame(() => this.checkScrollbar()));
|
|
160
|
-
this._resizeObserver.observe(this._container);
|
|
188
|
+
this._updateScrollTargets();
|
|
161
189
|
}
|
|
162
190
|
|
|
163
191
|
render() {
|
|
164
|
-
|
|
192
|
+
// when printing, just get scroll-wrapper out of the way
|
|
193
|
+
if (this._printMode) return html`<slot></slot>`;
|
|
194
|
+
|
|
165
195
|
const actions = !this.hideActions ? html`
|
|
166
196
|
<div class="d2l-scroll-wrapper-actions">
|
|
167
197
|
<div class="d2l-scroll-wrapper-button d2l-scroll-wrapper-button-left" @click="${this._scrollLeft}">
|
|
@@ -173,10 +203,17 @@ class ScrollWrapper extends RtlMixin(LitElement) {
|
|
|
173
203
|
</div>` : null;
|
|
174
204
|
return html`
|
|
175
205
|
${actions}
|
|
176
|
-
<div class="d2l-scroll-wrapper-container"
|
|
206
|
+
<div class="d2l-scroll-wrapper-container"><slot></slot></div>
|
|
177
207
|
`;
|
|
178
208
|
}
|
|
179
209
|
|
|
210
|
+
updated(changedProperties) {
|
|
211
|
+
super.updated(changedProperties);
|
|
212
|
+
|
|
213
|
+
if (changedProperties.has('customScrollers')) this._updateScrollTargets();
|
|
214
|
+
if (changedProperties.has('_hScrollbar')) this._updateTabIndex();
|
|
215
|
+
}
|
|
216
|
+
|
|
180
217
|
checkScrollbar() {
|
|
181
218
|
if (!this._container) return;
|
|
182
219
|
this._hScrollbar = this._container.offsetWidth !== this._container.scrollWidth;
|
|
@@ -201,12 +238,39 @@ class ScrollWrapper extends RtlMixin(LitElement) {
|
|
|
201
238
|
|
|
202
239
|
_checkScrollThresholds() {
|
|
203
240
|
if (!this._container) return;
|
|
204
|
-
const lowerScrollValue = this._container.scrollWidth - this.
|
|
241
|
+
const lowerScrollValue = this._container.scrollWidth - this._baseContainer.offsetWidth - Math.abs(this._container.scrollLeft);
|
|
205
242
|
this._scrollbarLeft = (this._container.scrollLeft === 0);
|
|
206
243
|
this._scrollbarRight = (lowerScrollValue <= 0);
|
|
207
244
|
|
|
208
245
|
}
|
|
209
246
|
|
|
247
|
+
_disconnectAll() {
|
|
248
|
+
this._resizeObserver?.disconnect();
|
|
249
|
+
|
|
250
|
+
if (this._container) {
|
|
251
|
+
this._container.style.removeProperty('overflow-x');
|
|
252
|
+
this._container.classList.remove('d2l-scroll-wrapper-focus');
|
|
253
|
+
this._container.removeAttribute('tabindex');
|
|
254
|
+
this._container.removeEventListener('scroll', this._synchronizeScroll);
|
|
255
|
+
this._container.removeEventListener('scroll', this._checkScrollThresholds);
|
|
256
|
+
this._secondaryScrollers.forEach(element => {
|
|
257
|
+
element.style.removeProperty('overflow-x');
|
|
258
|
+
element.removeEventListener('scroll', this._synchronizeScroll);
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async _handlePrintChange() {
|
|
264
|
+
if (!this._printMode) {
|
|
265
|
+
this._disconnectAll();
|
|
266
|
+
}
|
|
267
|
+
this._printMode = PRINT_MEDIA_QUERY_LIST.matches;
|
|
268
|
+
if (!this._printMode) {
|
|
269
|
+
await this.updateComplete;
|
|
270
|
+
this._updateScrollTargets();
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
210
274
|
_scrollLeft() {
|
|
211
275
|
if (!this._container) return;
|
|
212
276
|
const scrollDistance = this._container.clientWidth * SCROLL_AMOUNT * -1;
|
|
@@ -219,6 +283,58 @@ class ScrollWrapper extends RtlMixin(LitElement) {
|
|
|
219
283
|
this.scrollDistance(scrollDistance, true);
|
|
220
284
|
}
|
|
221
285
|
|
|
286
|
+
_synchronizeScroll(e) {
|
|
287
|
+
if (this._syncDriver && e.target !== this._syncDriver) return;
|
|
288
|
+
if (this._syncDriverTimeout) clearTimeout(this._syncDriverTimeout);
|
|
289
|
+
|
|
290
|
+
this._syncDriver = e.target;
|
|
291
|
+
this._allScrollers.forEach(element => {
|
|
292
|
+
if (element && element !== e.target) element.scrollLeft = e.target.scrollLeft;
|
|
293
|
+
});
|
|
294
|
+
this._syncDriverTimeout = setTimeout(() => this._syncDriver = null, 100);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
_updateScrollTargets() {
|
|
298
|
+
this._disconnectAll();
|
|
299
|
+
|
|
300
|
+
if (this._printMode) return;
|
|
301
|
+
|
|
302
|
+
this._baseContainer = this.shadowRoot.querySelector('.d2l-scroll-wrapper-container');
|
|
303
|
+
this._container = this.customScrollers?.primary || this._baseContainer;
|
|
304
|
+
this._secondaryScrollers = this.customScrollers?.secondary || [];
|
|
305
|
+
if (this._secondaryScrollers.length === undefined) this._secondaryScrollers = [ this._secondaryScrollers ];
|
|
306
|
+
this._allScrollers = [ this._container, ...this._secondaryScrollers ];
|
|
307
|
+
|
|
308
|
+
if (this._container) {
|
|
309
|
+
this._container.classList.add('d2l-scroll-wrapper-focus');
|
|
310
|
+
const styleRoot = getStyleSheetInsertionPoint(this._container);
|
|
311
|
+
if (styleRoot && 'adoptedStyleSheets' in styleRoot) {
|
|
312
|
+
const sheet = getFocusStyleSheet();
|
|
313
|
+
if (styleRoot.adoptedStyleSheets.indexOf(sheet) === -1) {
|
|
314
|
+
styleRoot.adoptedStyleSheets = [...styleRoot.adoptedStyleSheets, sheet];
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
this._container.style.overflowX = 'auto';
|
|
318
|
+
this._resizeObserver.observe(this._container);
|
|
319
|
+
this._container.addEventListener('scroll', this._checkScrollThresholds);
|
|
320
|
+
this._updateTabIndex();
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (this._secondaryScrollers.length) {
|
|
324
|
+
this._secondaryScrollers.forEach(element => {
|
|
325
|
+
element.style.overflowX = 'hidden';
|
|
326
|
+
element.addEventListener('scroll', this._synchronizeScroll);
|
|
327
|
+
});
|
|
328
|
+
this._container.addEventListener('scroll', this._synchronizeScroll);
|
|
329
|
+
this._synchronizeScroll({ target: this._container });
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
_updateTabIndex() {
|
|
334
|
+
if (!this._container) return;
|
|
335
|
+
if (this._hScrollbar) this._container.tabIndex = 0;
|
|
336
|
+
else this._container.removeAttribute('tabindex');
|
|
337
|
+
}
|
|
222
338
|
}
|
|
223
339
|
|
|
224
340
|
customElements.define('d2l-scroll-wrapper', ScrollWrapper);
|
|
@@ -486,6 +486,7 @@ When using lists, use the list-specific `d2l-list-controls` instead, which exten
|
|
|
486
486
|
| Property | Type | Description |
|
|
487
487
|
|---|---|---|
|
|
488
488
|
| `no-selection` | Boolean | Whether to render select-all and selection summary |
|
|
489
|
+
| `no-selection-text` | String | Text to display if no items are selected (overrides pageable counts) |
|
|
489
490
|
| `no-sticky` | Boolean | Disables sticky positioning for the controls |
|
|
490
491
|
| `select-all-pages-allowed` | Boolean | Whether all pages can be selected |
|
|
491
492
|
<!-- docs: end hidden content -->
|
|
@@ -24,6 +24,11 @@ export class SelectionControls extends PageableSubscriberMixin(SelectionObserver
|
|
|
24
24
|
* @type {boolean}
|
|
25
25
|
*/
|
|
26
26
|
noSelection: { type: Boolean, attribute: 'no-selection' },
|
|
27
|
+
/**
|
|
28
|
+
* ADVANCED: Text to display if no items are selected (overrides pageable counts)
|
|
29
|
+
* @type {string}
|
|
30
|
+
*/
|
|
31
|
+
noSelectionText: { type: String, attribute: 'no-selection-text' },
|
|
27
32
|
/**
|
|
28
33
|
* Disables sticky positioning for the controls
|
|
29
34
|
* @type {boolean}
|
|
@@ -150,8 +155,11 @@ export class SelectionControls extends PageableSubscriberMixin(SelectionObserver
|
|
|
150
155
|
if (changedProperties.has('noSticky')) {
|
|
151
156
|
this._stickyObserverUpdate();
|
|
152
157
|
}
|
|
153
|
-
|
|
154
|
-
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
willUpdate(changedProperties) {
|
|
161
|
+
if (changedProperties.has('noSelectionText') || changedProperties.has('_pageableInfo')) {
|
|
162
|
+
this._noSelectionText = this.noSelectionText || this._getNoSelectionText();
|
|
155
163
|
}
|
|
156
164
|
}
|
|
157
165
|
|
|
@@ -44,7 +44,7 @@ class Summary extends LocalizeCoreElement(SelectionObserverMixin(LitElement)) {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
willUpdate(changedProperties) {
|
|
47
|
-
if (changedProperties.has('_provider') || changedProperties.has('selectionInfo')) {
|
|
47
|
+
if (changedProperties.has('_provider') || changedProperties.has('selectionInfo') || changedProperties.has('noSelectionText')) {
|
|
48
48
|
this._updateSelectSummary();
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
<h2>Default, Sticky columns</h2>
|
|
59
59
|
<d2l-demo-snippet overflow-hidden>
|
|
60
60
|
<template>
|
|
61
|
-
<div style="overflow: auto; width:
|
|
61
|
+
<div style="overflow: auto; width: 400px;">
|
|
62
62
|
<d2l-test-table type="default" sticky-headers sticky-controls></d2l-test-table>
|
|
63
63
|
</div>
|
|
64
64
|
</template>
|
|
@@ -67,12 +67,19 @@
|
|
|
67
67
|
<h2>Default with Scroll-Wrapper (no sticky)</h2>
|
|
68
68
|
<d2l-demo-snippet overflow-hidden>
|
|
69
69
|
<template>
|
|
70
|
-
<div style="height:
|
|
71
|
-
<d2l-test-table type="default" sticky-controls style="width:
|
|
70
|
+
<div style="height: 400px; overflow: auto;">
|
|
71
|
+
<d2l-test-table type="default" sticky-controls style="width: 400px;"></d2l-test-table>
|
|
72
72
|
</div>
|
|
73
73
|
</template>
|
|
74
74
|
</d2l-demo-snippet>
|
|
75
75
|
|
|
76
|
+
<h2>Scroll-wrapper + sticky</h2>
|
|
77
|
+
<d2l-demo-snippet>
|
|
78
|
+
<template>
|
|
79
|
+
<d2l-test-table sticky-headers sticky-controls sticky-headers-scroll-wrapper style="width: 400px;"></d2l-test-table>
|
|
80
|
+
</template>
|
|
81
|
+
</d2l-demo-snippet>
|
|
82
|
+
|
|
76
83
|
<div style="margin-bottom: 1000px;"></div>
|
|
77
84
|
</d2l-demo-page>
|
|
78
85
|
</body>
|
|
@@ -2,6 +2,7 @@ import '../colors/colors.js';
|
|
|
2
2
|
import '../scroll-wrapper/scroll-wrapper.js';
|
|
3
3
|
import { css, html, LitElement, nothing } from 'lit';
|
|
4
4
|
import { PageableMixin } from '../paging/pageable-mixin.js';
|
|
5
|
+
import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
|
|
5
6
|
import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
|
|
6
7
|
import { SelectionMixin } from '../selection/selection-mixin.js';
|
|
7
8
|
|
|
@@ -114,10 +115,35 @@ export const tableStyles = css`
|
|
|
114
115
|
|
|
115
116
|
/* sticky-headers */
|
|
116
117
|
|
|
118
|
+
/* all sticky cells */
|
|
119
|
+
d2l-table-wrapper[sticky-headers] .d2l-table > * > tr > .d2l-table-sticky-cell,
|
|
120
|
+
d2l-table-wrapper[sticky-headers] .d2l-table > * > tr > [sticky] {
|
|
121
|
+
position: -webkit-sticky;
|
|
122
|
+
position: sticky;
|
|
123
|
+
z-index: 1;
|
|
124
|
+
}
|
|
125
|
+
d2l-table-wrapper:not([dir="rtl"])[sticky-headers] .d2l-table > * > tr > .d2l-table-sticky-cell,
|
|
126
|
+
d2l-table-wrapper:not([dir="rtl"])[sticky-headers] .d2l-table > * > tr > [sticky] {
|
|
127
|
+
left: 0;
|
|
128
|
+
}
|
|
129
|
+
d2l-table-wrapper[dir="rtl"][sticky-headers] .d2l-table > * > tr > .d2l-table-sticky-cell,
|
|
130
|
+
d2l-table-wrapper[dir="rtl"][sticky-headers] .d2l-table > * > tr > [sticky] {
|
|
131
|
+
right: 0;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* non-header sticky cells */
|
|
135
|
+
d2l-table-wrapper[sticky-headers] .d2l-table > * > tr:not([selected]) {
|
|
136
|
+
background-color: inherit; /* white background so sticky cells layer on top of non-sticky cells */
|
|
137
|
+
}
|
|
138
|
+
d2l-table-wrapper[sticky-headers] .d2l-table > tbody > tr:not([header]):not(.d2l-table-header) > .d2l-table-sticky-cell,
|
|
139
|
+
d2l-table-wrapper[sticky-headers] .d2l-table > tbody > tr:not([header]):not(.d2l-table-header) > [sticky] {
|
|
140
|
+
background-color: inherit;
|
|
141
|
+
}
|
|
142
|
+
|
|
117
143
|
/* all header cells */
|
|
118
144
|
d2l-table-wrapper[sticky-headers] .d2l-table > thead > tr > th,
|
|
119
|
-
d2l-table-wrapper[sticky-headers] .d2l-table > * > tr.d2l-table-header > *,
|
|
120
|
-
d2l-table-wrapper[sticky-headers] .d2l-table > * > tr[header] > * {
|
|
145
|
+
d2l-table-wrapper[sticky-headers]:not([sticky-headers-scroll-wrapper]) .d2l-table > * > tr.d2l-table-header > *,
|
|
146
|
+
d2l-table-wrapper[sticky-headers]:not([sticky-headers-scroll-wrapper]) .d2l-table > * > tr[header] > * {
|
|
121
147
|
position: -webkit-sticky;
|
|
122
148
|
position: sticky;
|
|
123
149
|
z-index: 2;
|
|
@@ -126,17 +152,12 @@ export const tableStyles = css`
|
|
|
126
152
|
/* header cells that are also sticky */
|
|
127
153
|
d2l-table-wrapper[sticky-headers] .d2l-table > thead > tr > th.d2l-table-sticky-cell,
|
|
128
154
|
d2l-table-wrapper[sticky-headers] .d2l-table > thead > tr > th[sticky],
|
|
129
|
-
d2l-table-wrapper[sticky-headers] .d2l-table > * > tr.d2l-table-header > .d2l-table-sticky-cell,
|
|
130
|
-
d2l-table-wrapper[sticky-headers] .d2l-table > * > tr.d2l-table-header > [sticky],
|
|
131
|
-
d2l-table-wrapper[sticky-headers] .d2l-table > * > tr[header] > .d2l-table-sticky-cell,
|
|
132
|
-
d2l-table-wrapper[sticky-headers] .d2l-table > * > tr[header] > [sticky] {
|
|
133
|
-
left: 0;
|
|
155
|
+
d2l-table-wrapper[sticky-headers]:not([sticky-headers-scroll-wrapper]) .d2l-table > * > tr.d2l-table-header > .d2l-table-sticky-cell,
|
|
156
|
+
d2l-table-wrapper[sticky-headers]:not([sticky-headers-scroll-wrapper]) .d2l-table > * > tr.d2l-table-header > [sticky],
|
|
157
|
+
d2l-table-wrapper[sticky-headers]:not([sticky-headers-scroll-wrapper]) .d2l-table > * > tr[header] > .d2l-table-sticky-cell,
|
|
158
|
+
d2l-table-wrapper[sticky-headers]:not([sticky-headers-scroll-wrapper]) .d2l-table > * > tr[header] > [sticky] {
|
|
134
159
|
z-index: 3;
|
|
135
160
|
}
|
|
136
|
-
d2l-table-wrapper[dir="rtl"][sticky-headers] .d2l-table > * > tr > .d2l-table-sticky-cell,
|
|
137
|
-
d2l-table-wrapper[dir="rtl"][sticky-headers] .d2l-table > * > tr > [sticky] {
|
|
138
|
-
right: 0;
|
|
139
|
-
}
|
|
140
161
|
|
|
141
162
|
/* first column that's sticky: offset by size of border-radius so top/bottom border doesn't show through (default style only) */
|
|
142
163
|
d2l-table-wrapper[sticky-headers][type="default"]:not([dir="rtl"]) .d2l-table > * > tr > .d2l-table-sticky-cell.d2l-table-cell-first,
|
|
@@ -148,17 +169,20 @@ export const tableStyles = css`
|
|
|
148
169
|
right: var(--d2l-table-border-radius-sticky-offset, 0);
|
|
149
170
|
}
|
|
150
171
|
|
|
151
|
-
/*
|
|
152
|
-
d2l-table-wrapper[sticky-headers] .d2l-table
|
|
153
|
-
|
|
172
|
+
/* sticky + scroll-wrapper */
|
|
173
|
+
d2l-table-wrapper[sticky-headers][sticky-headers-scroll-wrapper] .d2l-table {
|
|
174
|
+
display: block;
|
|
154
175
|
}
|
|
155
|
-
|
|
156
|
-
d2l-table-wrapper[sticky-headers]
|
|
157
|
-
|
|
158
|
-
left: 0;
|
|
159
|
-
position: -webkit-sticky;
|
|
176
|
+
|
|
177
|
+
d2l-table-wrapper[sticky-headers][sticky-headers-scroll-wrapper] .d2l-table > thead {
|
|
178
|
+
display: block;
|
|
160
179
|
position: sticky;
|
|
161
|
-
|
|
180
|
+
top: calc(var(--d2l-table-sticky-top, 0px) + var(--d2l-table-border-radius-sticky-offset, 0px));
|
|
181
|
+
z-index: 2;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
d2l-table-wrapper[sticky-headers][sticky-headers-scroll-wrapper] .d2l-table > tbody {
|
|
185
|
+
display: block;
|
|
162
186
|
}
|
|
163
187
|
`;
|
|
164
188
|
|
|
@@ -190,6 +214,15 @@ export class TableWrapper extends RtlMixin(PageableMixin(SelectionMixin(LitEleme
|
|
|
190
214
|
reflect: true,
|
|
191
215
|
type: Boolean
|
|
192
216
|
},
|
|
217
|
+
/**
|
|
218
|
+
* When used in combo with `sticky-headers`, whether to additionally wrap the table in a scroll-wrapper. Requires sticky headers to be in a separate thead.
|
|
219
|
+
* @type {boolean}
|
|
220
|
+
*/
|
|
221
|
+
stickyHeadersScrollWrapper: {
|
|
222
|
+
attribute: 'sticky-headers-scroll-wrapper',
|
|
223
|
+
reflect: true,
|
|
224
|
+
type: Boolean
|
|
225
|
+
},
|
|
193
226
|
/**
|
|
194
227
|
* Type of table style to apply. The "light" style has fewer borders and tighter padding.
|
|
195
228
|
* @type {'default'|'light'}
|
|
@@ -257,6 +290,7 @@ export class TableWrapper extends RtlMixin(PageableMixin(SelectionMixin(LitEleme
|
|
|
257
290
|
super();
|
|
258
291
|
this.noColumnBorder = false;
|
|
259
292
|
this.stickyHeaders = false;
|
|
293
|
+
this.stickyHeadersScrollWrapper = false;
|
|
260
294
|
this.type = 'default';
|
|
261
295
|
|
|
262
296
|
this._controls = null;
|
|
@@ -266,6 +300,7 @@ export class TableWrapper extends RtlMixin(PageableMixin(SelectionMixin(LitEleme
|
|
|
266
300
|
this._table = null;
|
|
267
301
|
this._tableIntersectionObserver = null;
|
|
268
302
|
this._tableMutationObserver = null;
|
|
303
|
+
this._tableScrollers = {};
|
|
269
304
|
}
|
|
270
305
|
|
|
271
306
|
disconnectedCallback() {
|
|
@@ -275,14 +310,16 @@ export class TableWrapper extends RtlMixin(PageableMixin(SelectionMixin(LitEleme
|
|
|
275
310
|
this._controlsScrolledMutationObserver?.disconnect();
|
|
276
311
|
this._tableMutationObserver?.disconnect();
|
|
277
312
|
this._tableIntersectionObserver?.disconnect();
|
|
313
|
+
this._tableResizeObserver?.disconnect();
|
|
278
314
|
}
|
|
279
315
|
|
|
280
316
|
render() {
|
|
281
317
|
const slot = html`<slot @slotchange="${this._handleSlotChange}"></slot>`;
|
|
318
|
+
const useScrollWrapper = this.stickyHeadersScrollWrapper || !this.stickyHeaders;
|
|
282
319
|
return html`
|
|
283
320
|
<slot name="controls" @slotchange="${this._handleControlsSlotChange}"></slot>
|
|
284
321
|
${this.stickyHeaders && this._controlsScrolled ? html`<div class="d2l-sticky-headers-backdrop"></div>` : nothing}
|
|
285
|
-
${
|
|
322
|
+
${useScrollWrapper ? html`<d2l-scroll-wrapper .customScrollers="${this._tableScrollers}">${slot}</d2l-scroll-wrapper>` : slot}
|
|
286
323
|
${this._renderPagerContainer()}
|
|
287
324
|
`;
|
|
288
325
|
}
|
|
@@ -388,6 +425,10 @@ export class TableWrapper extends RtlMixin(PageableMixin(SelectionMixin(LitEleme
|
|
|
388
425
|
this._table = e.target.assignedNodes({ flatten: true }).find(
|
|
389
426
|
node => (node.nodeType === Node.ELEMENT_NODE && node.tagName === 'TABLE' && node.classList.contains('d2l-table'))
|
|
390
427
|
);
|
|
428
|
+
this._tableScrollers = (this.stickyHeadersScrollWrapper && this.stickyHeaders) ? {
|
|
429
|
+
primary: this._table?.querySelector('tbody'),
|
|
430
|
+
secondary: this._table?.querySelector('thead'),
|
|
431
|
+
} : {};
|
|
391
432
|
|
|
392
433
|
// observes mutations to <table>'s direct children and also
|
|
393
434
|
// its subtree (rows or cells added/removed to any descendant)
|
|
@@ -397,6 +438,7 @@ export class TableWrapper extends RtlMixin(PageableMixin(SelectionMixin(LitEleme
|
|
|
397
438
|
childList: true,
|
|
398
439
|
subtree: true
|
|
399
440
|
});
|
|
441
|
+
this._tableResizeObserver?.disconnect();
|
|
400
442
|
|
|
401
443
|
if (!this._table) return;
|
|
402
444
|
|
|
@@ -418,6 +460,9 @@ export class TableWrapper extends RtlMixin(PageableMixin(SelectionMixin(LitEleme
|
|
|
418
460
|
this._tableIntersectionObserver.observe(this._table);
|
|
419
461
|
}
|
|
420
462
|
|
|
463
|
+
if (!this._tableResizeObserver) this._tableResizeObserver = new ResizeObserver(() => this._syncColumnWidths());
|
|
464
|
+
this._tableResizeObserver.observe(this._table);
|
|
465
|
+
|
|
421
466
|
this._handleTableChange();
|
|
422
467
|
}
|
|
423
468
|
|
|
@@ -426,6 +471,7 @@ export class TableWrapper extends RtlMixin(PageableMixin(SelectionMixin(LitEleme
|
|
|
426
471
|
|
|
427
472
|
this._updateItemShowingCount();
|
|
428
473
|
this._applyClassNames();
|
|
474
|
+
this._syncColumnWidths();
|
|
429
475
|
this._updateStickyTops();
|
|
430
476
|
}
|
|
431
477
|
|
|
@@ -438,12 +484,35 @@ export class TableWrapper extends RtlMixin(PageableMixin(SelectionMixin(LitEleme
|
|
|
438
484
|
if (target) this[observerName].observe(target, options);
|
|
439
485
|
}
|
|
440
486
|
|
|
487
|
+
_syncColumnWidths() {
|
|
488
|
+
if (!this._table || !this.stickyHeaders || !this.stickyHeadersScrollWrapper) return;
|
|
489
|
+
|
|
490
|
+
const head = this._table.querySelector('thead');
|
|
491
|
+
const body = this._table.querySelector('tbody');
|
|
492
|
+
if (!head || !body) return;
|
|
493
|
+
|
|
494
|
+
const firstRowHead = head.rows[0];
|
|
495
|
+
const firstRowBody = body.rows[0];
|
|
496
|
+
if (!firstRowHead || !firstRowBody || firstRowHead.cells.length !== firstRowBody.cells.length) return;
|
|
497
|
+
|
|
498
|
+
for (let i = 0; i < firstRowHead.cells.length; i++) {
|
|
499
|
+
const headCell = firstRowHead.cells[i];
|
|
500
|
+
const bodyCell = firstRowBody.cells[i];
|
|
501
|
+
|
|
502
|
+
if (headCell.clientWidth > bodyCell.clientWidth) {
|
|
503
|
+
bodyCell.style.minWidth = getComputedStyle(headCell).width;
|
|
504
|
+
} else if (headCell.clientWidth < bodyCell.clientWidth) {
|
|
505
|
+
headCell.style.minWidth = getComputedStyle(bodyCell).width;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
441
510
|
_updateStickyTops() {
|
|
442
511
|
const hasStickyControls = this._controls && !this._controls.noSticky;
|
|
443
512
|
let rowTop = hasStickyControls ? this._controls.offsetHeight + 6 : 0; // +6 for the internal `margin-bottom`.
|
|
444
513
|
this.style.setProperty('--d2l-table-sticky-top', `${rowTop}px`);
|
|
445
514
|
|
|
446
|
-
if (!this._table || !this.stickyHeaders) return;
|
|
515
|
+
if (!this._table || !this.stickyHeaders || this.stickyHeadersScrollWrapper) return;
|
|
447
516
|
|
|
448
517
|
const stickyRows = Array.from(this._table.querySelectorAll('tr.d2l-table-header, tr[header], thead tr'));
|
|
449
518
|
stickyRows.forEach(r => {
|
|
@@ -2,6 +2,7 @@ import '../button/button-icon.js';
|
|
|
2
2
|
import '../colors/colors.js';
|
|
3
3
|
import '../tooltip/tooltip.js';
|
|
4
4
|
import { css, html, nothing } from 'lit';
|
|
5
|
+
import { findComposedAncestor, isComposedAncestor } from '../../helpers/dom.js';
|
|
5
6
|
import { heading4Styles, labelStyles } from '../typography/styles.js';
|
|
6
7
|
import { announce } from '../../helpers/announce.js';
|
|
7
8
|
import { classMap } from 'lit/directives/class-map.js';
|
|
@@ -30,7 +31,10 @@ export const TagListItemMixin = superclass => class extends LocalizeCoreElement(
|
|
|
30
31
|
* @ignore
|
|
31
32
|
*/
|
|
32
33
|
keyboardTooltipItem: { type: Boolean, attribute: 'keyboard-tooltip-item' },
|
|
33
|
-
|
|
34
|
+
/**
|
|
35
|
+
* @ignore
|
|
36
|
+
*/
|
|
37
|
+
keyboardTooltipShown: { type: Boolean, attribute: 'keyboard-tooltip-shown' }
|
|
34
38
|
};
|
|
35
39
|
}
|
|
36
40
|
|
|
@@ -127,9 +131,8 @@ export const TagListItemMixin = superclass => class extends LocalizeCoreElement(
|
|
|
127
131
|
this.clearable = false;
|
|
128
132
|
/** @ignore */
|
|
129
133
|
this.keyboardTooltipItem = false;
|
|
130
|
-
this.
|
|
134
|
+
this.keyboardTooltipShown = false;
|
|
131
135
|
this._id = getUniqueId();
|
|
132
|
-
this._keyboardTooltipShown = false;
|
|
133
136
|
}
|
|
134
137
|
|
|
135
138
|
firstUpdated(changedProperties) {
|
|
@@ -140,17 +143,26 @@ export const TagListItemMixin = superclass => class extends LocalizeCoreElement(
|
|
|
140
143
|
this.addEventListener('focus', async(e) => {
|
|
141
144
|
// ignore focus events coming from inside the tag content
|
|
142
145
|
if (e.composedPath()[0] !== this) return;
|
|
146
|
+
const tagList = findComposedAncestor(this, elem => elem.tagName === 'D2L-TAG-LIST');
|
|
147
|
+
if (this.keyboardTooltipItem && this.keyboardTooltipShown && !isComposedAncestor(tagList, e.relatedTarget)) {
|
|
148
|
+
const arrows = this.localize('components.tag-list-item.tooltip-arrow-keys');
|
|
149
|
+
const arrowsDescription = this.localize('components.tag-list-item.tooltip-arrow-keys-desc');
|
|
150
|
+
|
|
151
|
+
let message = `${arrows} - ${arrowsDescription}`;
|
|
152
|
+
if (this.clearable) {
|
|
153
|
+
const del = this.localize('components.tag-list-item.tooltip-delete-key');
|
|
154
|
+
const delDescription = this.localize('components.tag-list-item.tooltip-delete-key-desc');
|
|
155
|
+
message += `; ${del} - ${delDescription}`;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
announce(message);
|
|
159
|
+
}
|
|
143
160
|
|
|
144
|
-
this._displayKeyboardTooltip = (this.keyboardTooltipItem && !this._keyboardTooltipShown);
|
|
145
161
|
await this.updateComplete;
|
|
146
162
|
|
|
147
163
|
container.focus();
|
|
148
164
|
});
|
|
149
165
|
|
|
150
|
-
this.addEventListener('blur', () => {
|
|
151
|
-
this._displayKeyboardTooltip = false;
|
|
152
|
-
});
|
|
153
|
-
|
|
154
166
|
this.addEventListener('keydown', this._handleKeydown);
|
|
155
167
|
}
|
|
156
168
|
|
|
@@ -167,11 +179,10 @@ export const TagListItemMixin = superclass => class extends LocalizeCoreElement(
|
|
|
167
179
|
}
|
|
168
180
|
|
|
169
181
|
_handleKeyboardTooltipHide() {
|
|
170
|
-
|
|
182
|
+
this.keyboardTooltipShown = true;
|
|
171
183
|
}
|
|
172
184
|
|
|
173
185
|
_handleKeyboardTooltipShow() {
|
|
174
|
-
this._keyboardTooltipShown = true;
|
|
175
186
|
/** @ignore */
|
|
176
187
|
this.dispatchEvent(new CustomEvent(
|
|
177
188
|
'd2l-tag-list-item-tooltip-show',
|
|
@@ -181,7 +192,7 @@ export const TagListItemMixin = superclass => class extends LocalizeCoreElement(
|
|
|
181
192
|
|
|
182
193
|
_handleKeydown(e) {
|
|
183
194
|
const openKeys = e.keyCode === keyCodes.SPACE || e.keyCode === keyCodes.ENTER;
|
|
184
|
-
if (this.
|
|
195
|
+
if (this.keyboardTooltipItem && !this.keyboardTooltipShown && openKeys) this.keyboardTooltipShown = true;
|
|
185
196
|
|
|
186
197
|
const clearKeys = e.keyCode === keyCodes.BACKSPACE || e.keyCode === keyCodes.DELETE;
|
|
187
198
|
if (!this.clearable || !clearKeys) return;
|
|
@@ -194,7 +205,9 @@ export const TagListItemMixin = superclass => class extends LocalizeCoreElement(
|
|
|
194
205
|
<div class="d2l-tag-list-item-tooltip-title-key">${this.localize('components.tag-list-item.tooltip-title')}</div>
|
|
195
206
|
<ul>
|
|
196
207
|
<li><span class="d2l-tag-list-item-tooltip-title-key">${this.localize('components.tag-list-item.tooltip-arrow-keys')}</span> - ${this.localize('components.tag-list-item.tooltip-arrow-keys-desc')}</li>
|
|
197
|
-
|
|
208
|
+
${this.clearable ? html`
|
|
209
|
+
<li><span class="d2l-tag-list-item-tooltip-title-key">${this.localize('components.tag-list-item.tooltip-delete-key')}</span> - ${this.localize('components.tag-list-item.tooltip-delete-key-desc')}</li>
|
|
210
|
+
` : nothing}
|
|
198
211
|
</ul>
|
|
199
212
|
`;
|
|
200
213
|
}
|
|
@@ -209,7 +222,7 @@ export const TagListItemMixin = superclass => class extends LocalizeCoreElement(
|
|
|
209
222
|
const hasDescription = !!options.description;
|
|
210
223
|
|
|
211
224
|
let tooltip = nothing;
|
|
212
|
-
if (this.
|
|
225
|
+
if (this.keyboardTooltipItem && !this.keyboardTooltipShown) {
|
|
213
226
|
tooltip = html`
|
|
214
227
|
<d2l-tooltip
|
|
215
228
|
align="start"
|
|
@@ -355,7 +355,7 @@ class TagList extends LocalizeCoreElement(InteractiveMixin(ArrowKeysMixin(LitEle
|
|
|
355
355
|
}
|
|
356
356
|
|
|
357
357
|
_handleKeyboardTooltipShown() {
|
|
358
|
-
this._hasShownKeyboardTooltip = true;
|
|
358
|
+
if (!this._hasShownKeyboardTooltip) this._hasShownKeyboardTooltip = true;
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
async _handleResize() {
|
|
@@ -398,7 +398,8 @@ class TagList extends LocalizeCoreElement(InteractiveMixin(ArrowKeysMixin(LitEle
|
|
|
398
398
|
this._chomp();
|
|
399
399
|
|
|
400
400
|
this._contentReady = true;
|
|
401
|
-
|
|
401
|
+
this._items[0].setAttribute('keyboard-tooltip-item', true);
|
|
402
|
+
if (this._hasShownKeyboardTooltip) this._items[0].setAttribute('keyboard-tooltip-shown', true);
|
|
402
403
|
}
|
|
403
404
|
|
|
404
405
|
async _toggleHiddenTagVisibility(e) {
|
package/custom-elements.json
CHANGED
|
@@ -7992,6 +7992,11 @@
|
|
|
7992
7992
|
"path": "./components/list/list-controls.js",
|
|
7993
7993
|
"description": "Controls for list components containing select-all, etc.",
|
|
7994
7994
|
"attributes": [
|
|
7995
|
+
{
|
|
7996
|
+
"name": "no-selection-text",
|
|
7997
|
+
"description": "ADVANCED: Text to display if no items are selected (overrides pageable counts)",
|
|
7998
|
+
"type": "string"
|
|
7999
|
+
},
|
|
7995
8000
|
{
|
|
7996
8001
|
"name": "no-selection",
|
|
7997
8002
|
"description": "Whether to render select-all and selection summary",
|
|
@@ -8022,6 +8027,12 @@
|
|
|
8022
8027
|
}
|
|
8023
8028
|
],
|
|
8024
8029
|
"properties": [
|
|
8030
|
+
{
|
|
8031
|
+
"name": "noSelectionText",
|
|
8032
|
+
"attribute": "no-selection-text",
|
|
8033
|
+
"description": "ADVANCED: Text to display if no items are selected (overrides pageable counts)",
|
|
8034
|
+
"type": "string"
|
|
8035
|
+
},
|
|
8025
8036
|
{
|
|
8026
8037
|
"name": "noSelection",
|
|
8027
8038
|
"attribute": "no-selection",
|
|
@@ -10157,6 +10168,11 @@
|
|
|
10157
10168
|
"type": "number",
|
|
10158
10169
|
"default": "0"
|
|
10159
10170
|
},
|
|
10171
|
+
{
|
|
10172
|
+
"name": "split-scrollers",
|
|
10173
|
+
"type": "boolean",
|
|
10174
|
+
"default": "false"
|
|
10175
|
+
},
|
|
10160
10176
|
{
|
|
10161
10177
|
"name": "width",
|
|
10162
10178
|
"type": "number",
|
|
@@ -10176,6 +10192,12 @@
|
|
|
10176
10192
|
"type": "number",
|
|
10177
10193
|
"default": "0"
|
|
10178
10194
|
},
|
|
10195
|
+
{
|
|
10196
|
+
"name": "splitScrollers",
|
|
10197
|
+
"attribute": "split-scrollers",
|
|
10198
|
+
"type": "boolean",
|
|
10199
|
+
"default": "false"
|
|
10200
|
+
},
|
|
10179
10201
|
{
|
|
10180
10202
|
"name": "width",
|
|
10181
10203
|
"attribute": "width",
|
|
@@ -10197,6 +10219,12 @@
|
|
|
10197
10219
|
}
|
|
10198
10220
|
],
|
|
10199
10221
|
"properties": [
|
|
10222
|
+
{
|
|
10223
|
+
"name": "customScrollers",
|
|
10224
|
+
"description": "An object containing custom primary/secondary scroll containers",
|
|
10225
|
+
"type": "Object",
|
|
10226
|
+
"default": "{}"
|
|
10227
|
+
},
|
|
10200
10228
|
{
|
|
10201
10229
|
"name": "hideActions",
|
|
10202
10230
|
"attribute": "hide-actions",
|
|
@@ -10621,6 +10649,11 @@
|
|
|
10621
10649
|
"path": "./components/selection/selection-controls.js",
|
|
10622
10650
|
"description": "Controls for selection components (e.g. list, table-wrapper) containing select-all, etc.",
|
|
10623
10651
|
"attributes": [
|
|
10652
|
+
{
|
|
10653
|
+
"name": "no-selection-text",
|
|
10654
|
+
"description": "ADVANCED: Text to display if no items are selected (overrides pageable counts)",
|
|
10655
|
+
"type": "string"
|
|
10656
|
+
},
|
|
10624
10657
|
{
|
|
10625
10658
|
"name": "no-selection",
|
|
10626
10659
|
"description": "Whether to render select-all and selection summary",
|
|
@@ -10651,6 +10684,12 @@
|
|
|
10651
10684
|
}
|
|
10652
10685
|
],
|
|
10653
10686
|
"properties": [
|
|
10687
|
+
{
|
|
10688
|
+
"name": "noSelectionText",
|
|
10689
|
+
"attribute": "no-selection-text",
|
|
10690
|
+
"description": "ADVANCED: Text to display if no items are selected (overrides pageable counts)",
|
|
10691
|
+
"type": "string"
|
|
10692
|
+
},
|
|
10654
10693
|
{
|
|
10655
10694
|
"name": "noSelection",
|
|
10656
10695
|
"attribute": "no-selection",
|
|
@@ -11503,6 +11542,12 @@
|
|
|
11503
11542
|
"type": "boolean",
|
|
11504
11543
|
"default": "false"
|
|
11505
11544
|
},
|
|
11545
|
+
{
|
|
11546
|
+
"name": "sticky-headers-scroll-wrapper",
|
|
11547
|
+
"description": "When used in combo with `sticky-headers`, whether to additionally wrap the table in a scroll-wrapper. Requires sticky headers to be in a separate thead.",
|
|
11548
|
+
"type": "boolean",
|
|
11549
|
+
"default": "false"
|
|
11550
|
+
},
|
|
11506
11551
|
{
|
|
11507
11552
|
"name": "type",
|
|
11508
11553
|
"description": "Type of table style to apply. The \"light\" style has fewer borders and tighter padding.",
|
|
@@ -11559,6 +11604,13 @@
|
|
|
11559
11604
|
"type": "boolean",
|
|
11560
11605
|
"default": "false"
|
|
11561
11606
|
},
|
|
11607
|
+
{
|
|
11608
|
+
"name": "stickyHeadersScrollWrapper",
|
|
11609
|
+
"attribute": "sticky-headers-scroll-wrapper",
|
|
11610
|
+
"description": "When used in combo with `sticky-headers`, whether to additionally wrap the table in a scroll-wrapper. Requires sticky headers to be in a separate thead.",
|
|
11611
|
+
"type": "boolean",
|
|
11612
|
+
"default": "false"
|
|
11613
|
+
},
|
|
11562
11614
|
{
|
|
11563
11615
|
"name": "type",
|
|
11564
11616
|
"attribute": "type",
|
|
@@ -11647,6 +11699,11 @@
|
|
|
11647
11699
|
"path": "./components/table/table-controls.js",
|
|
11648
11700
|
"description": "Controls for table components containing a selection summary and selection actions.",
|
|
11649
11701
|
"attributes": [
|
|
11702
|
+
{
|
|
11703
|
+
"name": "no-selection-text",
|
|
11704
|
+
"description": "ADVANCED: Text to display if no items are selected (overrides pageable counts)",
|
|
11705
|
+
"type": "string"
|
|
11706
|
+
},
|
|
11650
11707
|
{
|
|
11651
11708
|
"name": "no-selection",
|
|
11652
11709
|
"description": "Whether to render the selection summary",
|
|
@@ -11677,6 +11734,12 @@
|
|
|
11677
11734
|
}
|
|
11678
11735
|
],
|
|
11679
11736
|
"properties": [
|
|
11737
|
+
{
|
|
11738
|
+
"name": "noSelectionText",
|
|
11739
|
+
"attribute": "no-selection-text",
|
|
11740
|
+
"description": "ADVANCED: Text to display if no items are selected (overrides pageable counts)",
|
|
11741
|
+
"type": "string"
|
|
11742
|
+
},
|
|
11680
11743
|
{
|
|
11681
11744
|
"name": "noSelection",
|
|
11682
11745
|
"attribute": "no-selection",
|
|
@@ -11747,6 +11810,12 @@
|
|
|
11747
11810
|
"type": "boolean",
|
|
11748
11811
|
"default": "false"
|
|
11749
11812
|
},
|
|
11813
|
+
{
|
|
11814
|
+
"name": "sticky-headers-scroll-wrapper",
|
|
11815
|
+
"description": "When used in combo with `sticky-headers`, whether to additionally wrap the table in a scroll-wrapper. Requires sticky headers to be in a separate thead.",
|
|
11816
|
+
"type": "boolean",
|
|
11817
|
+
"default": "false"
|
|
11818
|
+
},
|
|
11750
11819
|
{
|
|
11751
11820
|
"name": "type",
|
|
11752
11821
|
"description": "Type of table style to apply. The \"light\" style has fewer borders and tighter padding.",
|
|
@@ -11785,6 +11854,13 @@
|
|
|
11785
11854
|
"type": "boolean",
|
|
11786
11855
|
"default": "false"
|
|
11787
11856
|
},
|
|
11857
|
+
{
|
|
11858
|
+
"name": "stickyHeadersScrollWrapper",
|
|
11859
|
+
"attribute": "sticky-headers-scroll-wrapper",
|
|
11860
|
+
"description": "When used in combo with `sticky-headers`, whether to additionally wrap the table in a scroll-wrapper. Requires sticky headers to be in a separate thead.",
|
|
11861
|
+
"type": "boolean",
|
|
11862
|
+
"default": "false"
|
|
11863
|
+
},
|
|
11788
11864
|
{
|
|
11789
11865
|
"name": "type",
|
|
11790
11866
|
"attribute": "type",
|
|
@@ -12056,6 +12132,11 @@
|
|
|
12056
12132
|
"type": "boolean",
|
|
12057
12133
|
"default": "false"
|
|
12058
12134
|
},
|
|
12135
|
+
{
|
|
12136
|
+
"name": "keyboardTooltipShown",
|
|
12137
|
+
"type": "boolean",
|
|
12138
|
+
"default": "false"
|
|
12139
|
+
},
|
|
12059
12140
|
{
|
|
12060
12141
|
"name": "documentLocaleSettings",
|
|
12061
12142
|
"default": "\"getDocumentLocaleSettings()\""
|
|
@@ -12161,6 +12242,11 @@
|
|
|
12161
12242
|
"type": "boolean",
|
|
12162
12243
|
"default": "false"
|
|
12163
12244
|
},
|
|
12245
|
+
{
|
|
12246
|
+
"name": "keyboardTooltipShown",
|
|
12247
|
+
"type": "boolean",
|
|
12248
|
+
"default": "false"
|
|
12249
|
+
},
|
|
12164
12250
|
{
|
|
12165
12251
|
"name": "documentLocaleSettings",
|
|
12166
12252
|
"default": "\"getDocumentLocaleSettings()\""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightspace-ui/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.114.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",
|