@brightspace-ui/labs 2.18.0 → 2.19.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.
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import '@brightspace-ui/core/components/icons/icon.js';
|
|
2
|
+
import '@brightspace-ui/core/components/inputs/input-checkbox';
|
|
3
|
+
|
|
4
|
+
import { css, html, LitElement, nothing } from 'lit';
|
|
5
|
+
import { LocalizeLabsElement } from '../localize-labs-element.js';
|
|
6
|
+
import { RtlMixin } from '@brightspace-ui/core/mixins/rtl-mixin.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @property {string} name
|
|
10
|
+
* @property {Number} dataId - returned in event.detail; caller should use this to update its model
|
|
11
|
+
* @property {boolean} isOpen - whether the node is expanded (i.e. children are hidden unless true)
|
|
12
|
+
* @property {string} selectedState - checkbox state: may be "explicit", "indeterminate", or "none"
|
|
13
|
+
* @fires d2l-labs-tree-selector-node-select - user is requesting that this node be selected or deselected
|
|
14
|
+
* @fires d2l-labs-tree-selector-node-open - user has requested that this node be expanded or collapsed
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
class TreeSelectorNode extends LocalizeLabsElement(RtlMixin(LitElement)) {
|
|
18
|
+
static get properties() {
|
|
19
|
+
return {
|
|
20
|
+
name: { type: String },
|
|
21
|
+
dataId: { type: Number, attribute: 'data-id' },
|
|
22
|
+
isOpen: { type: Boolean, reflect: true, attribute: 'open' },
|
|
23
|
+
selectedState: { type: String, reflect: true, attribute: 'selected-state' },
|
|
24
|
+
isOpenable: { type: Boolean, reflect: true, attribute: 'openable' },
|
|
25
|
+
// for screen readers
|
|
26
|
+
indentLevel: { type: Number, attribute: 'indent-level' },
|
|
27
|
+
parentName: { type: String, attribute: 'parent-name' },
|
|
28
|
+
// for search: if isSearch, only search-result nodes are shown; the caller should ensure their ancestors are open
|
|
29
|
+
isSearch: { type: Boolean, reflect: true, attribute: 'search' },
|
|
30
|
+
isSearchResult: { type: Boolean, reflect: true, attribute: 'search-result' }
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static get styles() {
|
|
35
|
+
return css`
|
|
36
|
+
:host {
|
|
37
|
+
display: block;
|
|
38
|
+
font-size: 0.8rem;
|
|
39
|
+
}
|
|
40
|
+
:host([hidden]) {
|
|
41
|
+
display: none;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.d2l-labs-tree-selector-node-node {
|
|
45
|
+
display: flex;
|
|
46
|
+
flex-wrap: nowrap;
|
|
47
|
+
margin-bottom: 16px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
d2l-input-checkbox {
|
|
51
|
+
display: inline-block;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.d2l-labs-tree-selector-node-open-control {
|
|
55
|
+
cursor: default;
|
|
56
|
+
margin-top: -3px;
|
|
57
|
+
}
|
|
58
|
+
.d2l-labs-tree-selector-node-open-control .d2l-labs-tree-selector-node-open {
|
|
59
|
+
display: none;
|
|
60
|
+
}
|
|
61
|
+
.d2l-labs-tree-selector-node-open-control[open] .d2l-labs-tree-selector-node-open {
|
|
62
|
+
display: inline-block;
|
|
63
|
+
}
|
|
64
|
+
.d2l-labs-tree-selector-node-open-control[open] .d2l-labs-tree-selector-node-closed {
|
|
65
|
+
display: none;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.d2l-labs-tree-selector-node-subtree {
|
|
69
|
+
margin-left: 34px;
|
|
70
|
+
margin-right: 0;
|
|
71
|
+
}
|
|
72
|
+
:host([dir="rtl"]) .d2l-labs-tree-selector-node-subtree {
|
|
73
|
+
margin-left: 0;
|
|
74
|
+
margin-right: 34px;
|
|
75
|
+
}
|
|
76
|
+
.d2l-labs-tree-selector-node-subtree[hidden] {
|
|
77
|
+
display: none;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.d2l-labs-tree-selector-node-text {
|
|
81
|
+
cursor: default;
|
|
82
|
+
display: inline-block;
|
|
83
|
+
margin-left: 0.5rem;
|
|
84
|
+
margin-right: 0.5rem;
|
|
85
|
+
width: 100%;
|
|
86
|
+
}
|
|
87
|
+
`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
constructor() {
|
|
91
|
+
super();
|
|
92
|
+
|
|
93
|
+
this.isOpen = false;
|
|
94
|
+
this.selectedState = 'none';
|
|
95
|
+
this.indentLevel = 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* @returns {Promise} - resolves when all tree-selector-nodes in slots, recursively, have finished updating
|
|
100
|
+
*/
|
|
101
|
+
get treeUpdateComplete() {
|
|
102
|
+
return this._waitForTreeUpdateComplete();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
render() {
|
|
106
|
+
return html`
|
|
107
|
+
${this._renderNode()}
|
|
108
|
+
${this._renderSubtree()}
|
|
109
|
+
`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
simulateArrowClick() {
|
|
113
|
+
this._onArrowClick();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
simulateCheckboxClick() {
|
|
117
|
+
this.shadowRoot?.querySelector('d2l-input-checkbox').simulateClick();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
get _arrowLabel() {
|
|
121
|
+
return this.localize(
|
|
122
|
+
this.isOpen ?
|
|
123
|
+
'components:ouFilter:treeSelector:arrowLabel:open' :
|
|
124
|
+
'components:ouFilter:treeSelector:arrowLabel:closed',
|
|
125
|
+
{ name: this.name, level: this.indentLevel, parentName: this.parentName }
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
get _showIndeterminate() {
|
|
130
|
+
return this.selectedState === 'indeterminate';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
get _showSelected() {
|
|
134
|
+
return this.selectedState === 'explicit';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
_onArrowClick() {
|
|
138
|
+
if (!this.isOpenable) return;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @event d2l-labs-tree-selector-node-open
|
|
142
|
+
*/
|
|
143
|
+
this.dispatchEvent(new CustomEvent(
|
|
144
|
+
'd2l-labs-tree-selector-node-open',
|
|
145
|
+
{
|
|
146
|
+
bubbles: true,
|
|
147
|
+
composed: false,
|
|
148
|
+
detail: {
|
|
149
|
+
id: this.dataId,
|
|
150
|
+
isOpen: !this.isOpen
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
_onChange(e) {
|
|
157
|
+
/**
|
|
158
|
+
* @event d2l-labs-tree-selector-node-select
|
|
159
|
+
*/
|
|
160
|
+
this.dispatchEvent(new CustomEvent(
|
|
161
|
+
'd2l-labs-tree-selector-node-select',
|
|
162
|
+
{
|
|
163
|
+
bubbles: true,
|
|
164
|
+
composed: false,
|
|
165
|
+
detail: {
|
|
166
|
+
id: this.dataId,
|
|
167
|
+
isSelected: e.target.checked
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
_renderNode() {
|
|
174
|
+
const label = this.parentName ?
|
|
175
|
+
this.localize('components:ouFilter:treeSelector:node:ariaLabel', { name: this.name, parentName: this.parentName }) :
|
|
176
|
+
this.name;
|
|
177
|
+
|
|
178
|
+
return html`
|
|
179
|
+
<div class="d2l-labs-tree-selector-node-node" ?search="${this.isSearch}" ?search-result="${this.isSearchResult}">
|
|
180
|
+
<d2l-input-checkbox
|
|
181
|
+
?checked="${this._showSelected}"
|
|
182
|
+
?indeterminate="${this._showIndeterminate}"
|
|
183
|
+
aria-label="${label}"
|
|
184
|
+
@change="${this._onChange}"
|
|
185
|
+
></d2l-input-checkbox>
|
|
186
|
+
<span class="d2l-labs-tree-selector-node-text" @click="${this._onArrowClick}" aria-hidden="true">${this.name}</span>
|
|
187
|
+
${this._renderOpenControl()}
|
|
188
|
+
</div>
|
|
189
|
+
`;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
_renderOpenControl() {
|
|
193
|
+
if (this.isOpenable) {
|
|
194
|
+
return html`
|
|
195
|
+
<a href="#" class="d2l-labs-tree-selector-node-open-control"
|
|
196
|
+
?open="${this.isOpen}"
|
|
197
|
+
@click="${this._onArrowClick}"
|
|
198
|
+
aria-label="${this._arrowLabel}"
|
|
199
|
+
aria-expanded="${this.isOpen}"
|
|
200
|
+
>
|
|
201
|
+
<d2l-icon class="d2l-labs-tree-selector-node-closed" icon="tier1:arrow-expand"></d2l-icon>
|
|
202
|
+
<d2l-icon class="d2l-labs-tree-selector-node-open" icon="tier1:arrow-collapse"></d2l-icon>
|
|
203
|
+
</a>
|
|
204
|
+
`;
|
|
205
|
+
} else {
|
|
206
|
+
return html`<span class="no-open-control"></span>`;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
_renderSubtree() {
|
|
211
|
+
if (this.isOpenable) {
|
|
212
|
+
return html`<div class="d2l-labs-tree-selector-node-subtree"
|
|
213
|
+
?hidden="${!this.isOpen}"
|
|
214
|
+
id="subtree"
|
|
215
|
+
>
|
|
216
|
+
<slot name="tree"></slot>
|
|
217
|
+
</div>`;
|
|
218
|
+
} else {
|
|
219
|
+
return nothing;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async _waitForTreeUpdateComplete() {
|
|
224
|
+
await this.updateComplete;
|
|
225
|
+
const slot = this.shadowRoot?.querySelector('slot');
|
|
226
|
+
// to be sure all child nodes have been added, instead of using flatten,
|
|
227
|
+
// we recursively walk down the tree, waiting for each node's update to complete
|
|
228
|
+
if (slot) {
|
|
229
|
+
const childNodes = slot.assignedNodes({ flatten: false });
|
|
230
|
+
return Promise.all(childNodes.map(node => node.treeUpdateComplete));
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
customElements.define('d2l-labs-tree-selector-node', TreeSelectorNode);
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import './tree-selector-node.js';
|
|
2
|
+
import '@brightspace-ui/core/components/button/button-subtle.js';
|
|
3
|
+
import '@brightspace-ui/core/components/dropdown/dropdown-button-subtle.js';
|
|
4
|
+
import '@brightspace-ui/core/components/dropdown/dropdown-content.js';
|
|
5
|
+
import '@brightspace-ui/core/components/dropdown/dropdown.js';
|
|
6
|
+
import '@brightspace-ui/core/components/inputs/input-search.js';
|
|
7
|
+
|
|
8
|
+
import { css, html, LitElement, nothing } from 'lit';
|
|
9
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
10
|
+
import { LocalizeLabsElement } from '../localize-labs-element.js';
|
|
11
|
+
import { selectStyles } from '@brightspace-ui/core/components/inputs/input-select-styles';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @property {String} name
|
|
15
|
+
* @property {Boolean} isSearch - if true, show "search-results" slot instead of "tree" slot
|
|
16
|
+
* @property {Boolean} isSelected - if true, show a "Clear" button in the header
|
|
17
|
+
* @fires d2l-labs-tree-selector-search - user requested or cleared a search; search string is event.detail.value
|
|
18
|
+
* @fires d2l-labs-tree-selector-clear - user requested that all selections be cleared
|
|
19
|
+
* @fires d2l-labs-tree-selector-select-all - user requested that all nodes be checked
|
|
20
|
+
*/
|
|
21
|
+
class TreeSelector extends LocalizeLabsElement(LitElement) {
|
|
22
|
+
|
|
23
|
+
static get properties() {
|
|
24
|
+
return {
|
|
25
|
+
name: { type: String },
|
|
26
|
+
disabled: { type: Boolean, attribute: 'disabled' },
|
|
27
|
+
isSelectAllVisible: { type: Boolean, attribute: 'select-all-ui', reflect: true },
|
|
28
|
+
isSearch: { type: Boolean, attribute: 'search', reflect: true },
|
|
29
|
+
isSelected: { type: Boolean, attribute: 'selected', reflect: true }
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static get styles() {
|
|
34
|
+
return [
|
|
35
|
+
selectStyles,
|
|
36
|
+
css`
|
|
37
|
+
:host {
|
|
38
|
+
display: inline-block;
|
|
39
|
+
}
|
|
40
|
+
:host([hidden]) {
|
|
41
|
+
display: none;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.d2l-labs-filter-dropdown-content-header {
|
|
45
|
+
display: flex;
|
|
46
|
+
justify-content: start;
|
|
47
|
+
}
|
|
48
|
+
.d2l-labs-filter-dropdown-content-header > span {
|
|
49
|
+
align-self: center;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.d2l-labs-tree-selector-margin-button {
|
|
53
|
+
margin-inline-end: 6px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.d2l-labs-tree-selector-margin-auto {
|
|
57
|
+
margin-inline-start: auto;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.d2l-labs-tree-selector-search {
|
|
61
|
+
display: flex;
|
|
62
|
+
flex-wrap: nowrap;
|
|
63
|
+
padding-bottom: 26px;
|
|
64
|
+
padding-top: 4px;
|
|
65
|
+
}
|
|
66
|
+
@media screen and (max-width: 400px) {
|
|
67
|
+
.d2l-labs-tree-selector-search {
|
|
68
|
+
width: 100%;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
:host([search]) d2l-dropdown d2l-dropdown-content .d2l-labs-tree-selector-tree {
|
|
72
|
+
display: none;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.d2l-labs-tree-selector-search-results {
|
|
76
|
+
display: none;
|
|
77
|
+
}
|
|
78
|
+
:host([search]) d2l-dropdown d2l-dropdown-content .d2l-labs-tree-selector-search-results {
|
|
79
|
+
display: block;
|
|
80
|
+
}
|
|
81
|
+
`
|
|
82
|
+
];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
constructor() {
|
|
86
|
+
super();
|
|
87
|
+
|
|
88
|
+
this.name = 'SPECIFY NAME ATTRIBUTE';
|
|
89
|
+
this._isSearch = false;
|
|
90
|
+
this.isSelectAllVisible = false;
|
|
91
|
+
this.disabled = false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @returns {Promise} - resolves when all tree-selector-nodes in slots, recursively, have finished updating
|
|
96
|
+
*/
|
|
97
|
+
get treeUpdateComplete() {
|
|
98
|
+
return this._waitForTreeUpdateComplete();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
render() {
|
|
102
|
+
// Using no-auto-fit on d2l-dropdown-content to avoid having the component jump to the top on every
|
|
103
|
+
// node open and load. The tradeoff is that the user has to scroll the whole page now.
|
|
104
|
+
// We have a defect logged to improve this in future.
|
|
105
|
+
return html`
|
|
106
|
+
<d2l-dropdown>
|
|
107
|
+
<d2l-dropdown-button-subtle text="${this.name}" ?disabled=${this.disabled}>
|
|
108
|
+
<d2l-dropdown-content align="start" no-auto-fit class="vdiff-target">
|
|
109
|
+
<div class="d2l-labs-filter-dropdown-content-header" slot="header">
|
|
110
|
+
<span>${this.localize('components:ouFilter:treeSelector:filterBy')}</span>
|
|
111
|
+
|
|
112
|
+
${this._clearButton}
|
|
113
|
+
|
|
114
|
+
${this._selectAllButton}
|
|
115
|
+
</div>
|
|
116
|
+
<div class="d2l-labs-tree-selector-search">
|
|
117
|
+
<d2l-input-search
|
|
118
|
+
label="${this.localize('components:ouFilter:treeSelector:searchLabel')}"
|
|
119
|
+
placeholder="${this.localize('components:ouFilter:treeSelector:searchPlaceholder')}"
|
|
120
|
+
@d2l-input-search-searched="${this._onSearch}"
|
|
121
|
+
></d2l-input-search>
|
|
122
|
+
</div>
|
|
123
|
+
<div class="d2l-labs-tree-selector-search-results">
|
|
124
|
+
<slot name="search-results"></slot>
|
|
125
|
+
</div>
|
|
126
|
+
<div class="d2l-labs-tree-selector-tree">
|
|
127
|
+
<slot name="tree"></slot>
|
|
128
|
+
</div>
|
|
129
|
+
</d2l-dropdown-content>
|
|
130
|
+
</d2l-dropdown-button-subtle>
|
|
131
|
+
</d2l-dropdown>
|
|
132
|
+
`;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
clearSearchAndSelection(generateEvent = true) {
|
|
136
|
+
this.shadowRoot.querySelector('d2l-input-search').value = '';
|
|
137
|
+
this._onSearch({
|
|
138
|
+
detail: {
|
|
139
|
+
value: ''
|
|
140
|
+
}
|
|
141
|
+
}, generateEvent);
|
|
142
|
+
|
|
143
|
+
this._onClear(generateEvent);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async resize() {
|
|
147
|
+
await this.treeUpdateComplete;
|
|
148
|
+
const content = this.shadowRoot?.querySelector('d2l-dropdown-content');
|
|
149
|
+
content && await content.resize();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
simulateSearch(searchString) {
|
|
153
|
+
this._onSearch({
|
|
154
|
+
detail: {
|
|
155
|
+
value: searchString
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
get _clearButton() {
|
|
161
|
+
if (!this.isSelected) return nothing;
|
|
162
|
+
|
|
163
|
+
const styles = {
|
|
164
|
+
'd2l-labs-tree-selector-select-clear': true,
|
|
165
|
+
'd2l-labs-tree-selector-margin-button': true,
|
|
166
|
+
'd2l-labs-tree-selector-margin-auto': true
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
return html`
|
|
170
|
+
<d2l-button-subtle
|
|
171
|
+
class="${classMap(styles)}"
|
|
172
|
+
text="${this.localize('components:ouFilter:treeSelector:clearLabel')}"
|
|
173
|
+
@click="${this._onClear}"
|
|
174
|
+
></d2l-button-subtle>`;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
get _selectAllButton() {
|
|
178
|
+
if (!this.isSelectAllVisible) return nothing;
|
|
179
|
+
|
|
180
|
+
const styles = {
|
|
181
|
+
'd2l-labs-tree-selector-select-all': true,
|
|
182
|
+
'd2l-labs-tree-selector-margin-auto': !this.isSelected
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
return html`
|
|
186
|
+
<d2l-button-subtle
|
|
187
|
+
class="${classMap(styles)}"
|
|
188
|
+
text="${this.localize('components:ouFilter:treeSelector:selectAllLabel')}"
|
|
189
|
+
@click="${this._onSelectAll}"
|
|
190
|
+
></d2l-button-subtle>`;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
_onClear(generateEvent = true) {
|
|
194
|
+
if (!generateEvent) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* @event d2l-labs-tree-selector-clear
|
|
199
|
+
*/
|
|
200
|
+
this.dispatchEvent(new CustomEvent(
|
|
201
|
+
'd2l-labs-tree-selector-clear',
|
|
202
|
+
{
|
|
203
|
+
bubbles: true,
|
|
204
|
+
composed: false
|
|
205
|
+
}
|
|
206
|
+
));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
_onSearch(event, generateEvent = true) {
|
|
210
|
+
if (!generateEvent) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* @event d2l-labs-tree-selector-search
|
|
215
|
+
*/
|
|
216
|
+
this.dispatchEvent(new CustomEvent(
|
|
217
|
+
'd2l-labs-tree-selector-search',
|
|
218
|
+
{
|
|
219
|
+
bubbles: true,
|
|
220
|
+
composed: false,
|
|
221
|
+
detail: event.detail
|
|
222
|
+
}
|
|
223
|
+
));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
_onSelectAll() {
|
|
227
|
+
/**
|
|
228
|
+
* @event d2l-labs-tree-selector-select-all
|
|
229
|
+
*/
|
|
230
|
+
this.dispatchEvent(new CustomEvent(
|
|
231
|
+
'd2l-labs-tree-selector-select-all',
|
|
232
|
+
{
|
|
233
|
+
bubbles: true,
|
|
234
|
+
composed: false
|
|
235
|
+
}
|
|
236
|
+
));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async _waitForTreeUpdateComplete() {
|
|
240
|
+
await this.updateComplete;
|
|
241
|
+
const slots = [...(this.shadowRoot?.querySelectorAll('slot') || [])];
|
|
242
|
+
// to be sure all child nodes have been added, instead of using flatten,
|
|
243
|
+
// we recursively walk down the tree, waiting for each node's update to complete
|
|
244
|
+
return Promise.all(slots.map(slot => {
|
|
245
|
+
const childNodes = slot.assignedNodes({ flatten: false });
|
|
246
|
+
return Promise.all(childNodes.map(node => node.treeUpdateComplete));
|
|
247
|
+
}));
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
customElements.define('d2l-labs-tree-selector', TreeSelector);
|