@brightspace-ui/core 2.59.3 → 2.60.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/form/form-element-mixin.js +1 -1
- package/components/inputs/input-number.js +14 -0
- package/components/inputs/input-text.js +1 -1
- package/components/list/list-header.js +11 -120
- package/components/list/list.js +0 -14
- package/components/selection/README.md +60 -19
- package/components/selection/demo/selection.html +45 -32
- package/components/selection/selection-header.js +192 -0
- package/components/table/README.md +1 -0
- package/custom-elements.json +96 -0
- package/package.json +1 -1
|
@@ -155,7 +155,7 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
|
|
|
155
155
|
return this.localize('components.form-element.defaultError', { label });
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
/** @ignore */
|
|
158
|
+
/** @ignore Note: this may be our custom FormElementValidityState or native ValidityState depending on the source. */
|
|
159
159
|
get validity() {
|
|
160
160
|
return this._validity;
|
|
161
161
|
}
|
|
@@ -306,6 +306,15 @@ class InputNumber extends FocusMixin(LabelledMixin(SkeletonMixin(FormElementMixi
|
|
|
306
306
|
return super.validationMessage;
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
+
/** @ignore */
|
|
310
|
+
get validity() {
|
|
311
|
+
const elem = this.shadowRoot && this.shadowRoot.querySelector('d2l-input-text');
|
|
312
|
+
if (elem && !elem.validity.valid) {
|
|
313
|
+
return elem.validity;
|
|
314
|
+
}
|
|
315
|
+
return super.validity;
|
|
316
|
+
}
|
|
317
|
+
|
|
309
318
|
firstUpdated(changedProperties) {
|
|
310
319
|
super.firstUpdated(changedProperties);
|
|
311
320
|
this.addEventListener('d2l-localize-resources-change', () => {
|
|
@@ -331,6 +340,7 @@ class InputNumber extends FocusMixin(LabelledMixin(SkeletonMixin(FormElementMixi
|
|
|
331
340
|
?hide-invalid-icon="${this.hideInvalidIcon}"
|
|
332
341
|
id="${this._inputId}"
|
|
333
342
|
input-width="${this.inputWidth}"
|
|
343
|
+
@invalid-change="${this._handleInvalidChange}"
|
|
334
344
|
label="${ifDefined(this.label)}"
|
|
335
345
|
?label-hidden="${this.labelHidden || this.labelledBy}"
|
|
336
346
|
.labelRequired="${false}"
|
|
@@ -464,6 +474,10 @@ class InputNumber extends FocusMixin(LabelledMixin(SkeletonMixin(FormElementMixi
|
|
|
464
474
|
}
|
|
465
475
|
}
|
|
466
476
|
|
|
477
|
+
_handleInvalidChange() {
|
|
478
|
+
this.requestValidate(true);
|
|
479
|
+
}
|
|
480
|
+
|
|
467
481
|
_handleKeyPress(e) {
|
|
468
482
|
// NOTE: keypress event is deprecated, but keydown fires for ALL keys (including Shift/Tab/etc.)
|
|
469
483
|
// which makes it hard to selectively supress "not numbers". The "beforeinput" event is
|
|
@@ -307,7 +307,7 @@ class InputText extends FocusMixin(LabelledMixin(FormElementMixin(SkeletonMixin(
|
|
|
307
307
|
/** @ignore */
|
|
308
308
|
get validity() {
|
|
309
309
|
const elem = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input');
|
|
310
|
-
if (!elem.validity.valid) {
|
|
310
|
+
if (elem && !elem.validity.valid) {
|
|
311
311
|
return elem.validity;
|
|
312
312
|
}
|
|
313
313
|
return super.validity;
|
|
@@ -1,119 +1,35 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import '../selection/selection-select-all.js';
|
|
3
|
-
import '../selection/selection-select-all-pages.js';
|
|
4
|
-
import '../selection/selection-summary.js';
|
|
5
|
-
import { css, html, LitElement } from 'lit';
|
|
6
|
-
import { classMap } from 'lit/directives/class-map.js';
|
|
1
|
+
import { css } from 'lit';
|
|
7
2
|
import { findComposedAncestor } from '../../helpers/dom.js';
|
|
8
|
-
import {
|
|
9
|
-
import { RtlMixin } from '../../mixins/rtl-mixin.js';
|
|
3
|
+
import { SelectionHeader } from '../selection/selection-header.js';
|
|
10
4
|
|
|
11
5
|
/**
|
|
12
6
|
* A header for list components containing select-all, etc.
|
|
13
7
|
* @slot - Responsive container using `d2l-overflow-group` for `d2l-selection-action` elements
|
|
14
8
|
*/
|
|
15
|
-
class ListHeader extends
|
|
16
|
-
|
|
9
|
+
class ListHeader extends SelectionHeader {
|
|
17
10
|
static get properties() {
|
|
18
11
|
return {
|
|
19
|
-
|
|
20
|
-
* Whether to render select-all and selection summary
|
|
21
|
-
* @type {boolean}
|
|
22
|
-
*/
|
|
23
|
-
noSelection: { type: Boolean, attribute: 'no-selection' },
|
|
24
|
-
/**
|
|
25
|
-
* Disables sticky positioning for the header
|
|
26
|
-
* @type {boolean}
|
|
27
|
-
*/
|
|
28
|
-
noSticky: { type: Boolean, attribute: 'no-sticky' },
|
|
29
|
-
/**
|
|
30
|
-
* Whether all pages can be selected
|
|
31
|
-
* @type {boolean}
|
|
32
|
-
*/
|
|
33
|
-
selectAllPagesAllowed: { type: Boolean, attribute: 'select-all-pages-allowed' },
|
|
34
|
-
_hasActions: { state: true },
|
|
35
|
-
_scrolled: { type: Boolean, reflect: true }
|
|
12
|
+
_extendSeparator: { state: true }
|
|
36
13
|
};
|
|
37
14
|
}
|
|
38
15
|
|
|
39
16
|
static get styles() {
|
|
40
|
-
return css`
|
|
17
|
+
return [super.styles, css`
|
|
41
18
|
:host {
|
|
42
|
-
background-color: var(--d2l-list-header-background-color
|
|
43
|
-
display: block;
|
|
44
|
-
position: sticky;
|
|
45
|
-
top: 0;
|
|
19
|
+
--d2l-selection-header-background-color: var(--d2l-list-header-background-color);
|
|
46
20
|
z-index: 6; /* must be greater than d2l-list-item-active-border */
|
|
47
21
|
}
|
|
48
22
|
:host([no-sticky]) {
|
|
49
|
-
background-color: transparent;
|
|
50
|
-
position: static;
|
|
51
23
|
z-index: auto;
|
|
52
24
|
}
|
|
53
|
-
.d2l-list-header-shadow {
|
|
54
|
-
transition: box-shadow 200ms ease-out;
|
|
55
|
-
}
|
|
56
|
-
:host([_scrolled]) .d2l-list-header-shadow {
|
|
57
|
-
background-color: var(--d2l-list-header-background-color, white);
|
|
58
|
-
bottom: -4px;
|
|
59
|
-
box-shadow: 0 8px 12px -9px rgba(0, 0, 0, 0.3);
|
|
60
|
-
clip: rect(30px, auto, 200px, auto);
|
|
61
|
-
height: 40px;
|
|
62
|
-
position: absolute;
|
|
63
|
-
width: 100%;
|
|
64
|
-
z-index: -1;
|
|
65
|
-
}
|
|
66
|
-
:host([hidden]) {
|
|
67
|
-
display: none;
|
|
68
|
-
}
|
|
69
|
-
.d2l-list-header-container {
|
|
70
|
-
align-items: center;
|
|
71
|
-
display: flex;
|
|
72
|
-
margin-bottom: 6px;
|
|
73
|
-
margin-top: 6px;
|
|
74
|
-
min-height: 54px;
|
|
75
|
-
}
|
|
76
|
-
.d2l-list-header-container-slim {
|
|
77
|
-
min-height: 36px;
|
|
78
|
-
}
|
|
79
25
|
.d2l-list-header-extend-separator {
|
|
80
26
|
padding: 0 0.9rem;
|
|
81
27
|
}
|
|
82
|
-
|
|
83
|
-
flex: none;
|
|
84
|
-
}
|
|
85
|
-
d2l-selection-summary {
|
|
86
|
-
flex: none;
|
|
87
|
-
margin-left: 0.9rem;
|
|
88
|
-
}
|
|
89
|
-
:host([dir="rtl"]) d2l-selection-summary {
|
|
90
|
-
margin-left: 0;
|
|
91
|
-
margin-right: 0.9rem;
|
|
92
|
-
}
|
|
93
|
-
d2l-selection-select-all-pages {
|
|
94
|
-
flex: none;
|
|
95
|
-
margin-left: 0.45rem;
|
|
96
|
-
}
|
|
97
|
-
:host([dir="rtl"]) d2l-selection-select-all-pages {
|
|
98
|
-
margin-left: 0;
|
|
99
|
-
margin-right: 0.45rem;
|
|
100
|
-
}
|
|
101
|
-
.d2l-list-header-actions {
|
|
102
|
-
--d2l-overflow-group-justify-content: flex-end;
|
|
103
|
-
flex: auto;
|
|
104
|
-
text-align: right;
|
|
105
|
-
}
|
|
106
|
-
:host([dir="rtl"]) .d2l-list-header-actions {
|
|
107
|
-
text-align: left;
|
|
108
|
-
}
|
|
109
|
-
`;
|
|
28
|
+
`];
|
|
110
29
|
}
|
|
111
30
|
|
|
112
31
|
constructor() {
|
|
113
32
|
super();
|
|
114
|
-
this.noSelection = false;
|
|
115
|
-
this.noSticky = false;
|
|
116
|
-
this.selectAllPagesAllowed = false;
|
|
117
33
|
this._extendSeparator = false;
|
|
118
34
|
}
|
|
119
35
|
|
|
@@ -121,40 +37,15 @@ class ListHeader extends RtlMixin(LocalizeCoreElement(LitElement)) {
|
|
|
121
37
|
super.connectedCallback();
|
|
122
38
|
|
|
123
39
|
const parent = findComposedAncestor(this.parentNode, node => node && node.tagName === 'D2L-LIST');
|
|
124
|
-
if (
|
|
125
|
-
|
|
126
|
-
this._extendSeparator = parent.hasAttribute('extend-separators');
|
|
40
|
+
if (parent) this._extendSeparator = parent.hasAttribute('extend-separators');
|
|
127
41
|
}
|
|
128
42
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
'd2l-list-header-container-slim': (!this._hasActions && !this.selectAllPagesAllowed),
|
|
43
|
+
_getSelectionHeaderContainerClasses() {
|
|
44
|
+
return {
|
|
45
|
+
...super._getSelectionHeaderContainerClasses(),
|
|
133
46
|
'd2l-list-header-extend-separator': this._extendSeparator
|
|
134
47
|
};
|
|
135
|
-
return html`
|
|
136
|
-
<div class="${classMap(classes)}">
|
|
137
|
-
${this.noSelection ? null : html`
|
|
138
|
-
<d2l-selection-select-all></d2l-selection-select-all>
|
|
139
|
-
<d2l-selection-summary
|
|
140
|
-
aria-hidden="true"
|
|
141
|
-
class="d2l-list-header-summary"
|
|
142
|
-
no-selection-text="${this.localize('components.selection.select-all')}">
|
|
143
|
-
</d2l-selection-summary>
|
|
144
|
-
${this.selectAllPagesAllowed ? html`<d2l-selection-select-all-pages></d2l-selection-select-all-pages>` : null}
|
|
145
|
-
`}
|
|
146
|
-
<div class="d2l-list-header-actions">
|
|
147
|
-
<d2l-overflow-group opener-type="icon"><slot @slotchange="${this._handleSlotChange}"></slot></d2l-overflow-group>
|
|
148
|
-
</div>
|
|
149
|
-
</div>
|
|
150
|
-
${!this.noSticky ? html`<div class="d2l-list-header-shadow"></div>` : null}
|
|
151
|
-
`;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
_handleSlotChange(e) {
|
|
155
|
-
this._hasActions = (e.target.assignedNodes({ flatten: true }).filter(node => node.nodeType === Node.ELEMENT_NODE).length > 0);
|
|
156
48
|
}
|
|
157
|
-
|
|
158
49
|
}
|
|
159
50
|
|
|
160
51
|
customElements.define('d2l-list-header', ListHeader);
|
package/components/list/list.js
CHANGED
|
@@ -106,25 +106,11 @@ class List extends PageableMixin(SelectionMixin(LitElement)) {
|
|
|
106
106
|
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
-
if (typeof(IntersectionObserver) === 'function') {
|
|
110
|
-
this._intersectionObserver = new IntersectionObserver(entries => {
|
|
111
|
-
const slot = this.shadowRoot.querySelector('slot[name="header"]');
|
|
112
|
-
const header = slot.assignedNodes({ flatten: true }).find(node => {
|
|
113
|
-
return node.nodeType === Node.ELEMENT_NODE && node.tagName === 'D2L-LIST-HEADER';
|
|
114
|
-
});
|
|
115
|
-
if (!header) return;
|
|
116
|
-
const entry = entries[0];
|
|
117
|
-
header._scrolled = !entry.isIntersecting;
|
|
118
|
-
});
|
|
119
|
-
this._intersectionObserver.observe(this.shadowRoot.querySelector('.d2l-list-top-sentinel'));
|
|
120
|
-
}
|
|
121
|
-
|
|
122
109
|
}
|
|
123
110
|
|
|
124
111
|
render() {
|
|
125
112
|
const role = !this.grid ? 'list' : 'application';
|
|
126
113
|
return html`
|
|
127
|
-
<div class="d2l-list-top-sentinel"></div>
|
|
128
114
|
<div role="${role}" class="d2l-list-container">
|
|
129
115
|
<slot name="header"></slot>
|
|
130
116
|
<slot @keydown="${this._handleKeyDown}" @slotchange="${this._handleSlotChange}"></slot>
|
|
@@ -36,6 +36,7 @@ The `SelectionMixin` defines the `selection-single` attribute that consumers can
|
|
|
36
36
|
</script>
|
|
37
37
|
<script type="module">
|
|
38
38
|
import '@brightspace-ui/core/components/selection/selection-action.js';
|
|
39
|
+
import '@brightspace-ui/core/components/selection/selection-header.js';
|
|
39
40
|
import '@brightspace-ui/core/components/selection/selection-input.js';
|
|
40
41
|
import '@brightspace-ui/core/components/selection/selection-select-all.js';
|
|
41
42
|
import '@brightspace-ui/core/components/selection/selection-summary.js';
|
|
@@ -50,8 +51,6 @@ The `SelectionMixin` defines the `selection-single` attribute that consumers can
|
|
|
50
51
|
}
|
|
51
52
|
li {
|
|
52
53
|
list-style-type: none;
|
|
53
|
-
}
|
|
54
|
-
li, .d2l-selection-header, .d2l-selection-header-wrapper {
|
|
55
54
|
align-items: center;
|
|
56
55
|
display: flex;
|
|
57
56
|
}
|
|
@@ -62,26 +61,13 @@ The `SelectionMixin` defines the `selection-single` attribute that consumers can
|
|
|
62
61
|
margin-left: 10px;
|
|
63
62
|
margin-right: 0;
|
|
64
63
|
}
|
|
65
|
-
.d2l-selection-header-wrapper {
|
|
66
|
-
flex-wrap: wrap;
|
|
67
|
-
}
|
|
68
|
-
.d2l-selection-header {
|
|
69
|
-
flex: auto;
|
|
70
|
-
}
|
|
71
|
-
d2l-selection-summary {
|
|
72
|
-
flex: none;
|
|
73
|
-
}
|
|
74
64
|
</style>
|
|
75
65
|
<!-- docs: end hidden content -->
|
|
76
66
|
<d2l-demo-selection>
|
|
77
|
-
<
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
<d2l-selection-action text="Settings" icon="tier1:gear"></d2l-selection-action>
|
|
82
|
-
</div>
|
|
83
|
-
<d2l-selection-summary></d2l-selection-summary>
|
|
84
|
-
</div>
|
|
67
|
+
<d2l-selection-header>
|
|
68
|
+
<d2l-selection-action text="Bookmark" icon="tier1:bookmark-hollow" requires-selection></d2l-selection-action>
|
|
69
|
+
<d2l-selection-action text="Settings" icon="tier1:gear"></d2l-selection-action>
|
|
70
|
+
</d2l-selection-header>
|
|
85
71
|
<ul>
|
|
86
72
|
<li><d2l-selection-input key="geo" label="Geography" selected></d2l-selection-input>Geography</li>
|
|
87
73
|
<li><d2l-selection-input key="sci" label="Science"></d2l-selection-input>Science</li>
|
|
@@ -441,3 +427,58 @@ The `d2l-selection-summary` component may be placed inside the selection control
|
|
|
441
427
|
| `no-selection-text` | String | Text to display if no items are selected. By default, the "0 selected" message is displayed. |
|
|
442
428
|
| `selection-for` | String | Id of the corresponding `SelectionMixin` component, if not placed within it. |
|
|
443
429
|
<!-- docs: end hidden content -->
|
|
430
|
+
|
|
431
|
+
## Selection Header [d2l-selection-header]
|
|
432
|
+
|
|
433
|
+
The `d2l-selection-header` provides a standardized wrapper to display selection information and actions. It includes a select-all checkbox, summary, a slot for `d2l-selection-action`s, and overflow-group behaviour.
|
|
434
|
+
|
|
435
|
+
When using lists, use the list-specific `d2l-list-header` instead, which extends this component's behaviour.
|
|
436
|
+
|
|
437
|
+
<!-- docs: demo live name:d2l-selection-header autoSize:false size:medium -->
|
|
438
|
+
```html
|
|
439
|
+
<script type="module">
|
|
440
|
+
import '@brightspace-ui/core/components/selection/selection-action.js';
|
|
441
|
+
import '@brightspace-ui/core/components/selection/selection-header.js';
|
|
442
|
+
import '@brightspace-ui/core/components/selection/demo/demo-selection.js';
|
|
443
|
+
</script>
|
|
444
|
+
<!-- docs: start hidden content -->
|
|
445
|
+
<style>
|
|
446
|
+
ul {
|
|
447
|
+
padding: 0;
|
|
448
|
+
}
|
|
449
|
+
li {
|
|
450
|
+
list-style-type: none;
|
|
451
|
+
align-items: center;
|
|
452
|
+
display: flex;
|
|
453
|
+
}
|
|
454
|
+
d2l-selection-input {
|
|
455
|
+
margin-right: 10px;
|
|
456
|
+
}
|
|
457
|
+
[dir="rtl"] d2l-selection-input {
|
|
458
|
+
margin-left: 10px;
|
|
459
|
+
margin-right: 0;
|
|
460
|
+
}
|
|
461
|
+
</style>
|
|
462
|
+
<!-- docs: end hidden content -->
|
|
463
|
+
<d2l-demo-selection>
|
|
464
|
+
<d2l-selection-header>
|
|
465
|
+
<d2l-selection-action text="Bookmark" icon="tier1:bookmark-hollow" requires-selection></d2l-selection-action>
|
|
466
|
+
<d2l-selection-action text="Settings" icon="tier1:gear"></d2l-selection-action>
|
|
467
|
+
</d2l-selection-header>
|
|
468
|
+
<ul>
|
|
469
|
+
<li><d2l-selection-input key="geo" label="Geography" selected></d2l-selection-input>Geography</li>
|
|
470
|
+
<li><d2l-selection-input key="sci" label="Science"></d2l-selection-input>Science</li>
|
|
471
|
+
<li><d2l-selection-input key="mth" label="Math"></d2l-selection-input>Math</li>
|
|
472
|
+
</ul>
|
|
473
|
+
</d2l-demo-selection>
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
<!-- docs: start hidden content -->
|
|
477
|
+
### Properties
|
|
478
|
+
|
|
479
|
+
| Property | Type | Description |
|
|
480
|
+
|---|---|---|
|
|
481
|
+
| `no-selection` | Boolean | Whether to render select-all and selection summary |
|
|
482
|
+
| `no-sticky` | Boolean | Disables sticky positioning for the header |
|
|
483
|
+
| `select-all-pages-allowed` | Boolean | Whether all pages can be selected |
|
|
484
|
+
<!-- docs: end hidden content -->
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import '../selection-action.js';
|
|
12
12
|
import '../selection-action-dropdown.js';
|
|
13
13
|
import '../selection-action-menu-item.js';
|
|
14
|
+
import '../selection-header.js';
|
|
14
15
|
import '../selection-input.js';
|
|
15
16
|
import '../selection-select-all.js';
|
|
16
17
|
import '../selection-summary.js';
|
|
@@ -56,22 +57,19 @@
|
|
|
56
57
|
<d2l-demo-snippet>
|
|
57
58
|
<template>
|
|
58
59
|
<d2l-demo-selection>
|
|
59
|
-
<
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
<d2l-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
<d2l-menu
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
</div>
|
|
73
|
-
<d2l-selection-summary style="flex: none;"></d2l-selection-summary>
|
|
74
|
-
</div>
|
|
60
|
+
<d2l-selection-header>
|
|
61
|
+
<d2l-selection-action text="Bookmark" icon="tier1:bookmark-hollow" requires-selection></d2l-selection-action>
|
|
62
|
+
<d2l-selection-action text="Settings" icon="tier1:gear"></d2l-selection-action>
|
|
63
|
+
<d2l-selection-action-dropdown text="Actions 1" requires-selection>
|
|
64
|
+
<d2l-dropdown-menu>
|
|
65
|
+
<d2l-menu label="Actions">
|
|
66
|
+
<d2l-selection-action-menu-item text="Action 1"></d2l-selection-action-menu-item>
|
|
67
|
+
<d2l-selection-action-menu-item text="Action 2"></d2l-selection-action-menu-item>
|
|
68
|
+
</d2l-menu>
|
|
69
|
+
</d2l-dropdown-menu>
|
|
70
|
+
</d2l-selection-action-dropdown>
|
|
71
|
+
</d2l-selection-header>
|
|
72
|
+
|
|
75
73
|
<ul>
|
|
76
74
|
<li><d2l-selection-input key="geo" label="Geography" selected></d2l-selection-input>Geography</li>
|
|
77
75
|
<li><d2l-selection-input key="sci" label="Science"></d2l-selection-input>Science</li>
|
|
@@ -86,13 +84,31 @@
|
|
|
86
84
|
<d2l-demo-snippet>
|
|
87
85
|
<template>
|
|
88
86
|
<d2l-demo-selection selection-single>
|
|
89
|
-
<
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
87
|
+
<d2l-selection-header>
|
|
88
|
+
<d2l-selection-action text="Bookmark" icon="tier1:bookmark-hollow" requires-selection></d2l-selection-action>
|
|
89
|
+
<d2l-selection-action text="Settings" icon="tier1:gear"></d2l-selection-action>
|
|
90
|
+
</d2l-selection-header>
|
|
91
|
+
|
|
92
|
+
<ul>
|
|
93
|
+
<li><d2l-selection-input key="geo" label="Geography"></d2l-selection-input>Geography</li>
|
|
94
|
+
<li><d2l-selection-input key="sci" label="Science"></d2l-selection-input>Science</li>
|
|
95
|
+
<li><d2l-selection-input key="mth" label="Math"></d2l-selection-input>Math</li>
|
|
96
|
+
</ul>
|
|
97
|
+
</d2l-demo-selection>
|
|
98
|
+
</template>
|
|
99
|
+
</d2l-demo-snippet>
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
<h2>None-sticky selection header</h2>
|
|
103
|
+
|
|
104
|
+
<d2l-demo-snippet>
|
|
105
|
+
<template>
|
|
106
|
+
<d2l-demo-selection>
|
|
107
|
+
<d2l-selection-header no-sticky>
|
|
108
|
+
<d2l-selection-action text="Bookmark" icon="tier1:bookmark-hollow" requires-selection></d2l-selection-action>
|
|
109
|
+
<d2l-selection-action text="Settings" icon="tier1:gear"></d2l-selection-action>
|
|
110
|
+
</d2l-selection-header>
|
|
111
|
+
|
|
96
112
|
<ul>
|
|
97
113
|
<li><d2l-selection-input key="geo" label="Geography"></d2l-selection-input>Geography</li>
|
|
98
114
|
<li><d2l-selection-input key="sci" label="Science"></d2l-selection-input>Science</li>
|
|
@@ -109,11 +125,10 @@
|
|
|
109
125
|
<div class="d2l-selection-collections">
|
|
110
126
|
<div class="d2l-selection-collection">
|
|
111
127
|
Pick Your Toppings
|
|
112
|
-
<
|
|
113
|
-
<d2l-selection-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
</div>
|
|
128
|
+
<d2l-selection-header selection-for="collection-1">
|
|
129
|
+
<d2l-selection-action selection-for="collection-1" text="Add Note" icon="tier1:add-message"></d2l-selection-action>
|
|
130
|
+
</d2l-selection-header>
|
|
131
|
+
|
|
117
132
|
<d2l-demo-selection id="collection-1">
|
|
118
133
|
<ul>
|
|
119
134
|
<li><d2l-selection-input key="let" label="Lettuce" selected></d2l-selection-input>Lettuce</li>
|
|
@@ -126,11 +141,9 @@
|
|
|
126
141
|
|
|
127
142
|
<div class="d2l-selection-collection">
|
|
128
143
|
Pick Your Bread
|
|
129
|
-
<
|
|
130
|
-
<d2l-selection-select-all selection-for="collection-2"></d2l-selection-select-all>
|
|
144
|
+
<d2l-selection-header selection-for="collection-2">
|
|
131
145
|
<d2l-selection-action selection-for="collection-2" text="Add Note" icon="tier1:add-message"></d2l-selection-action>
|
|
132
|
-
|
|
133
|
-
</div>
|
|
146
|
+
</d2l-selection-header>
|
|
134
147
|
<d2l-demo-selection id="collection-2" selection-single>
|
|
135
148
|
<ul>
|
|
136
149
|
<li><d2l-selection-input key="it" label="Italian"></d2l-selection-input>Italian</li>
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import '../overflow-group/overflow-group.js';
|
|
2
|
+
import './selection-select-all.js';
|
|
3
|
+
import './selection-select-all-pages.js';
|
|
4
|
+
import './selection-summary.js';
|
|
5
|
+
import { css, html, LitElement } from 'lit';
|
|
6
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
7
|
+
import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
|
|
8
|
+
import { RtlMixin } from '../../mixins/rtl-mixin.js';
|
|
9
|
+
import { SelectionObserverMixin } from './selection-observer-mixin.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A header for selection components (e.g. list, table-wrapper) containing select-all, etc.
|
|
13
|
+
* @slot - Responsive container using `d2l-overflow-group` for `d2l-selection-action` elements
|
|
14
|
+
*/
|
|
15
|
+
export class SelectionHeader extends SelectionObserverMixin(RtlMixin(LocalizeCoreElement(LitElement))) {
|
|
16
|
+
|
|
17
|
+
static get properties() {
|
|
18
|
+
return {
|
|
19
|
+
/**
|
|
20
|
+
* Whether to render select-all and selection summary
|
|
21
|
+
* @type {boolean}
|
|
22
|
+
*/
|
|
23
|
+
noSelection: { type: Boolean, attribute: 'no-selection' },
|
|
24
|
+
/**
|
|
25
|
+
* Disables sticky positioning for the header
|
|
26
|
+
* @type {boolean}
|
|
27
|
+
*/
|
|
28
|
+
noSticky: { type: Boolean, attribute: 'no-sticky' },
|
|
29
|
+
/**
|
|
30
|
+
* Whether all pages can be selected
|
|
31
|
+
* @type {boolean}
|
|
32
|
+
*/
|
|
33
|
+
selectAllPagesAllowed: { type: Boolean, attribute: 'select-all-pages-allowed' },
|
|
34
|
+
_hasActions: { state: true },
|
|
35
|
+
_scrolled: { type: Boolean, reflect: true }
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static get styles() {
|
|
40
|
+
return css`
|
|
41
|
+
:host {
|
|
42
|
+
background-color: var(--d2l-selection-header-background-color, white);
|
|
43
|
+
display: block;
|
|
44
|
+
position: sticky;
|
|
45
|
+
top: 0;
|
|
46
|
+
}
|
|
47
|
+
:host([no-sticky]) {
|
|
48
|
+
background-color: transparent;
|
|
49
|
+
position: static;
|
|
50
|
+
}
|
|
51
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
52
|
+
.d2l-selection-header-shadow {
|
|
53
|
+
transition: box-shadow 200ms ease-out;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
:host([_scrolled]) .d2l-selection-header-shadow {
|
|
57
|
+
background-color: var(--d2l-selection-header-background-color, white);
|
|
58
|
+
bottom: -4px;
|
|
59
|
+
box-shadow: 0 8px 12px -9px rgba(0, 0, 0, 0.3);
|
|
60
|
+
clip: rect(30px, auto, 200px, auto);
|
|
61
|
+
height: 40px;
|
|
62
|
+
position: absolute;
|
|
63
|
+
width: 100%;
|
|
64
|
+
z-index: -1;
|
|
65
|
+
}
|
|
66
|
+
:host([hidden]) {
|
|
67
|
+
display: none;
|
|
68
|
+
}
|
|
69
|
+
.d2l-selection-header-container {
|
|
70
|
+
align-items: center;
|
|
71
|
+
display: flex;
|
|
72
|
+
margin-bottom: 6px;
|
|
73
|
+
margin-top: 6px;
|
|
74
|
+
min-height: 54px;
|
|
75
|
+
}
|
|
76
|
+
.d2l-selection-header-container-slim {
|
|
77
|
+
min-height: 36px;
|
|
78
|
+
}
|
|
79
|
+
d2l-selection-select-all {
|
|
80
|
+
flex: none;
|
|
81
|
+
}
|
|
82
|
+
d2l-selection-summary {
|
|
83
|
+
flex: none;
|
|
84
|
+
margin-left: 0.9rem;
|
|
85
|
+
}
|
|
86
|
+
:host([dir="rtl"]) d2l-selection-summary {
|
|
87
|
+
margin-left: 0;
|
|
88
|
+
margin-right: 0.9rem;
|
|
89
|
+
}
|
|
90
|
+
d2l-selection-select-all-pages {
|
|
91
|
+
flex: none;
|
|
92
|
+
margin-left: 0.45rem;
|
|
93
|
+
}
|
|
94
|
+
:host([dir="rtl"]) d2l-selection-select-all-pages {
|
|
95
|
+
margin-left: 0;
|
|
96
|
+
margin-right: 0.45rem;
|
|
97
|
+
}
|
|
98
|
+
.d2l-selection-header-actions {
|
|
99
|
+
--d2l-overflow-group-justify-content: flex-end;
|
|
100
|
+
flex: auto;
|
|
101
|
+
text-align: right;
|
|
102
|
+
}
|
|
103
|
+
:host([dir="rtl"]) .d2l-selection-header-actions {
|
|
104
|
+
text-align: left;
|
|
105
|
+
}
|
|
106
|
+
.d2l-sticky-edge {
|
|
107
|
+
left: 0;
|
|
108
|
+
position: absolute;
|
|
109
|
+
right: 0;
|
|
110
|
+
top: -1px;
|
|
111
|
+
}
|
|
112
|
+
`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
constructor() {
|
|
116
|
+
super();
|
|
117
|
+
this.noSelection = false;
|
|
118
|
+
this.noSticky = false;
|
|
119
|
+
this.selectAllPagesAllowed = false;
|
|
120
|
+
this._scrolled = false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
disconnectedCallback() {
|
|
124
|
+
super.disconnectedCallback();
|
|
125
|
+
this._stickyObserverDisconnect();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
render() {
|
|
129
|
+
const classes = this._getSelectionHeaderContainerClasses();
|
|
130
|
+
return html`
|
|
131
|
+
<div class="d2l-sticky-edge"></div>
|
|
132
|
+
<div class="${classMap(classes)}">
|
|
133
|
+
${this.noSelection ? null : html`
|
|
134
|
+
<d2l-selection-select-all></d2l-selection-select-all>
|
|
135
|
+
<d2l-selection-summary
|
|
136
|
+
aria-hidden="true"
|
|
137
|
+
no-selection-text="${this.localize('components.selection.select-all')}"
|
|
138
|
+
>
|
|
139
|
+
</d2l-selection-summary>
|
|
140
|
+
${this.selectAllPagesAllowed ? html`<d2l-selection-select-all-pages></d2l-selection-select-all-pages>` : null}
|
|
141
|
+
`}
|
|
142
|
+
<div class="d2l-selection-header-actions">
|
|
143
|
+
<d2l-overflow-group opener-type="icon"><slot @slotchange="${this._handleSlotChange}"></slot></d2l-overflow-group>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
${!this.noSticky ? html`<div class="d2l-selection-header-shadow"></div>` : null}
|
|
147
|
+
`;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
updated(changedProperties) {
|
|
151
|
+
super.updated(changedProperties);
|
|
152
|
+
|
|
153
|
+
if (changedProperties.has('noSticky')) {
|
|
154
|
+
this._stickyObserverUpdate();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
_getSelectionHeaderContainerClasses() {
|
|
159
|
+
return {
|
|
160
|
+
'd2l-selection-header-container': true,
|
|
161
|
+
'd2l-selection-header-container-slim': (!this._hasActions && !this.selectAllPagesAllowed)
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
_handleSlotChange(e) {
|
|
166
|
+
this._hasActions = (e.target.assignedNodes({ flatten: true }).filter(node => node.nodeType === Node.ELEMENT_NODE).length > 0);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
_stickyObserverDisconnect() {
|
|
170
|
+
if (this._stickyIntersectionObserver) {
|
|
171
|
+
this._stickyIntersectionObserver.disconnect();
|
|
172
|
+
this._stickyIntersectionObserver = undefined;
|
|
173
|
+
this._scrolled = false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
_stickyObserverUpdate() {
|
|
178
|
+
this._stickyObserverDisconnect();
|
|
179
|
+
|
|
180
|
+
if (!this.noSticky && typeof(IntersectionObserver) === 'function') {
|
|
181
|
+
this._stickyIntersectionObserver = new IntersectionObserver(([e]) => {
|
|
182
|
+
this._scrolled = !e.isIntersecting;
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
const target = this.shadowRoot.querySelector('.d2l-sticky-edge');
|
|
186
|
+
this._stickyIntersectionObserver.observe(target);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
customElements.define('d2l-selection-header', SelectionHeader);
|
|
@@ -18,6 +18,7 @@ Tables are used to display tabular data in rows and columns. They can allow user
|
|
|
18
18
|
* There are more than just a few dimensions
|
|
19
19
|
* The dimensions need to be sortable
|
|
20
20
|
* The dimensions need to be easily compared across rows (ie- scannable)
|
|
21
|
+
* Specify [column and row headings](https://www.w3.org/WAI/tutorials/tables/) so data is meaningful to screen reader users
|
|
21
22
|
<!-- docs: end dos -->
|
|
22
23
|
|
|
23
24
|
<!-- docs: start donts -->
|
package/custom-elements.json
CHANGED
|
@@ -7337,6 +7337,11 @@
|
|
|
7337
7337
|
"description": "Whether all pages can be selected",
|
|
7338
7338
|
"type": "boolean",
|
|
7339
7339
|
"default": "false"
|
|
7340
|
+
},
|
|
7341
|
+
{
|
|
7342
|
+
"name": "selection-for",
|
|
7343
|
+
"description": "Id of the `SelectionMixin` component this component wants to observe (if not located within that component)",
|
|
7344
|
+
"type": "string"
|
|
7340
7345
|
}
|
|
7341
7346
|
],
|
|
7342
7347
|
"properties": [
|
|
@@ -7361,11 +7366,25 @@
|
|
|
7361
7366
|
"type": "boolean",
|
|
7362
7367
|
"default": "false"
|
|
7363
7368
|
},
|
|
7369
|
+
{
|
|
7370
|
+
"name": "selectionFor",
|
|
7371
|
+
"attribute": "selection-for",
|
|
7372
|
+
"description": "Id of the `SelectionMixin` component this component wants to observe (if not located within that component)",
|
|
7373
|
+
"type": "string"
|
|
7374
|
+
},
|
|
7375
|
+
{
|
|
7376
|
+
"name": "selectionInfo"
|
|
7377
|
+
},
|
|
7364
7378
|
{
|
|
7365
7379
|
"name": "documentLocaleSettings",
|
|
7366
7380
|
"default": "\"getDocumentLocaleSettings()\""
|
|
7367
7381
|
}
|
|
7368
7382
|
],
|
|
7383
|
+
"events": [
|
|
7384
|
+
{
|
|
7385
|
+
"name": "d2l-selection-observer-subscribe"
|
|
7386
|
+
}
|
|
7387
|
+
],
|
|
7369
7388
|
"slots": [
|
|
7370
7389
|
{
|
|
7371
7390
|
"name": "",
|
|
@@ -9739,6 +9758,83 @@
|
|
|
9739
9758
|
}
|
|
9740
9759
|
]
|
|
9741
9760
|
},
|
|
9761
|
+
{
|
|
9762
|
+
"name": "d2l-selection-header",
|
|
9763
|
+
"path": "./components/selection/selection-header.js",
|
|
9764
|
+
"description": "A header for selection components (e.g. list, table-wrapper) containing select-all, etc.",
|
|
9765
|
+
"attributes": [
|
|
9766
|
+
{
|
|
9767
|
+
"name": "no-selection",
|
|
9768
|
+
"description": "Whether to render select-all and selection summary",
|
|
9769
|
+
"type": "boolean",
|
|
9770
|
+
"default": "false"
|
|
9771
|
+
},
|
|
9772
|
+
{
|
|
9773
|
+
"name": "no-sticky",
|
|
9774
|
+
"description": "Disables sticky positioning for the header",
|
|
9775
|
+
"type": "boolean",
|
|
9776
|
+
"default": "false"
|
|
9777
|
+
},
|
|
9778
|
+
{
|
|
9779
|
+
"name": "select-all-pages-allowed",
|
|
9780
|
+
"description": "Whether all pages can be selected",
|
|
9781
|
+
"type": "boolean",
|
|
9782
|
+
"default": "false"
|
|
9783
|
+
},
|
|
9784
|
+
{
|
|
9785
|
+
"name": "selection-for",
|
|
9786
|
+
"description": "Id of the `SelectionMixin` component this component wants to observe (if not located within that component)",
|
|
9787
|
+
"type": "string"
|
|
9788
|
+
}
|
|
9789
|
+
],
|
|
9790
|
+
"properties": [
|
|
9791
|
+
{
|
|
9792
|
+
"name": "noSelection",
|
|
9793
|
+
"attribute": "no-selection",
|
|
9794
|
+
"description": "Whether to render select-all and selection summary",
|
|
9795
|
+
"type": "boolean",
|
|
9796
|
+
"default": "false"
|
|
9797
|
+
},
|
|
9798
|
+
{
|
|
9799
|
+
"name": "noSticky",
|
|
9800
|
+
"attribute": "no-sticky",
|
|
9801
|
+
"description": "Disables sticky positioning for the header",
|
|
9802
|
+
"type": "boolean",
|
|
9803
|
+
"default": "false"
|
|
9804
|
+
},
|
|
9805
|
+
{
|
|
9806
|
+
"name": "selectAllPagesAllowed",
|
|
9807
|
+
"attribute": "select-all-pages-allowed",
|
|
9808
|
+
"description": "Whether all pages can be selected",
|
|
9809
|
+
"type": "boolean",
|
|
9810
|
+
"default": "false"
|
|
9811
|
+
},
|
|
9812
|
+
{
|
|
9813
|
+
"name": "selectionFor",
|
|
9814
|
+
"attribute": "selection-for",
|
|
9815
|
+
"description": "Id of the `SelectionMixin` component this component wants to observe (if not located within that component)",
|
|
9816
|
+
"type": "string"
|
|
9817
|
+
},
|
|
9818
|
+
{
|
|
9819
|
+
"name": "selectionInfo"
|
|
9820
|
+
},
|
|
9821
|
+
{
|
|
9822
|
+
"name": "documentLocaleSettings",
|
|
9823
|
+
"default": "\"getDocumentLocaleSettings()\""
|
|
9824
|
+
}
|
|
9825
|
+
],
|
|
9826
|
+
"events": [
|
|
9827
|
+
{
|
|
9828
|
+
"name": "d2l-selection-observer-subscribe"
|
|
9829
|
+
}
|
|
9830
|
+
],
|
|
9831
|
+
"slots": [
|
|
9832
|
+
{
|
|
9833
|
+
"name": "",
|
|
9834
|
+
"description": "Responsive container using `d2l-overflow-group` for `d2l-selection-action` elements"
|
|
9835
|
+
}
|
|
9836
|
+
]
|
|
9837
|
+
},
|
|
9742
9838
|
{
|
|
9743
9839
|
"name": "d2l-selection-input",
|
|
9744
9840
|
"path": "./components/selection/selection-input.js",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightspace-ui/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.60.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",
|