@brightspace-ui/core 2.59.4 → 2.60.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.
@@ -1,119 +1,35 @@
1
- import '../overflow-group/overflow-group.js';
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 { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
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 RtlMixin(LocalizeCoreElement(LitElement)) {
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, white);
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
- d2l-selection-select-all {
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 (!parent) return;
125
-
126
- this._extendSeparator = parent.hasAttribute('extend-separators');
40
+ if (parent) this._extendSeparator = parent.hasAttribute('extend-separators');
127
41
  }
128
42
 
129
- render() {
130
- const classes = {
131
- 'd2l-list-header-container': true,
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);
@@ -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
- <div class="d2l-selection-header-wrapper">
78
- <div class="d2l-selection-header">
79
- <d2l-selection-select-all></d2l-selection-select-all>
80
- <d2l-selection-action text="Bookmark" icon="tier1:bookmark-hollow" requires-selection></d2l-selection-action>
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
- <div class="d2l-selection-header">
60
- <div style="flex: auto;">
61
- <d2l-selection-select-all></d2l-selection-select-all>
62
- <d2l-selection-action text="Bookmark" icon="tier1:bookmark-hollow" requires-selection></d2l-selection-action>
63
- <d2l-selection-action text="Settings" icon="tier1:gear"></d2l-selection-action>
64
- <d2l-selection-action-dropdown text="Actions 1" requires-selection>
65
- <d2l-dropdown-menu>
66
- <d2l-menu label="Actions">
67
- <d2l-selection-action-menu-item text="Action 1"></d2l-selection-action-menu-item>
68
- <d2l-selection-action-menu-item text="Action 2"></d2l-selection-action-menu-item>
69
- </d2l-menu>
70
- </d2l-dropdown-menu>
71
- </d2l-selection-action-dropdown>
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
- <div class="d2l-selection-header">
90
- <div style="flex: auto;">
91
- <d2l-selection-action text="Bookmark" icon="tier1:bookmark-hollow" requires-selection></d2l-selection-action>
92
- <d2l-selection-action text="Settings" icon="tier1:gear"></d2l-selection-action>
93
- </div>
94
- <d2l-selection-summary style="flex: none;"></d2l-selection-summary>
95
- </div>
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
- <div class="d2l-selection-header">
113
- <d2l-selection-select-all selection-for="collection-1"></d2l-selection-select-all>
114
- <d2l-selection-action selection-for="collection-1" text="Add Note" icon="tier1:add-message" style="flex: 1; padding: 0 0.5rem;"></d2l-selection-action>
115
- <d2l-selection-summary selection-for="collection-1"></d2l-selection-summary>
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
- <div class="d2l-selection-header">
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
- <d2l-selection-summary selection-for="collection-2"></d2l-selection-summary>
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);
@@ -87,10 +87,12 @@ export const SelectionObserverMixin = superclass => class extends superclass {
87
87
  }
88
88
 
89
89
  _handleSelectionObserverSubscribe(e) {
90
- if (e.target !== this && this._provider) {
90
+ if (this._provider) {
91
+ const target = e.composedPath()[0];
92
+ if (target === this) return;
93
+
91
94
  e.stopPropagation();
92
95
  e.detail.provider = this._provider;
93
- const target = e.composedPath()[0];
94
96
  this._provider.subscribeObserver(target);
95
97
  }
96
98
  }
@@ -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",
@@ -10030,7 +10126,30 @@
10030
10126
  },
10031
10127
  {
10032
10128
  "name": "d2l-test-selection-observer-shadow",
10033
- "path": "./components/selection/test/selection-component.js"
10129
+ "path": "./components/selection/test/selection-component.js",
10130
+ "attributes": [
10131
+ {
10132
+ "name": "selection-for",
10133
+ "description": "Id of the `SelectionMixin` component this component wants to observe (if not located within that component)",
10134
+ "type": "string"
10135
+ }
10136
+ ],
10137
+ "properties": [
10138
+ {
10139
+ "name": "selectionFor",
10140
+ "attribute": "selection-for",
10141
+ "description": "Id of the `SelectionMixin` component this component wants to observe (if not located within that component)",
10142
+ "type": "string"
10143
+ },
10144
+ {
10145
+ "name": "selectionInfo"
10146
+ }
10147
+ ],
10148
+ "events": [
10149
+ {
10150
+ "name": "d2l-selection-observer-subscribe"
10151
+ }
10152
+ ]
10034
10153
  },
10035
10154
  {
10036
10155
  "name": "d2l-test-skeleton-box",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "2.59.4",
3
+ "version": "2.60.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",