@brightspace-ui/core 2.76.3 → 2.78.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.
Files changed (39) hide show
  1. package/components/button/button-icon.js +1 -0
  2. package/components/inputs/demo/input-search.html +8 -0
  3. package/components/inputs/docs/input-search.md +1 -0
  4. package/components/inputs/input-search.js +18 -0
  5. package/components/list/README.md +67 -0
  6. package/components/list/demo/demo-list-nested-lazy-load.js +133 -0
  7. package/components/list/demo/demo-list-nested.js +279 -0
  8. package/components/list/demo/list-demo-scenarios.js +321 -0
  9. package/components/list/demo/list-drag-and-drop.html +2 -2
  10. package/components/list/demo/list-expand-collapse.html +134 -0
  11. package/components/list/list-item-checkbox-mixin.js +2 -8
  12. package/components/list/list-item-drag-drop-mixin.js +78 -14
  13. package/components/list/list-item-drag-image.js +5 -3
  14. package/components/list/list-item-expand-collapse-mixin.js +168 -0
  15. package/components/list/list-item-generic-layout.js +21 -12
  16. package/components/list/list-item-mixin.js +88 -11
  17. package/components/list/list.js +45 -9
  18. package/components/selection/selection-summary.js +43 -12
  19. package/custom-elements.json +399 -194
  20. package/lang/ar.js +1 -0
  21. package/lang/cy.js +1 -0
  22. package/lang/da.js +1 -0
  23. package/lang/de.js +1 -0
  24. package/lang/en.js +1 -0
  25. package/lang/es-es.js +1 -0
  26. package/lang/es.js +1 -0
  27. package/lang/fr-fr.js +1 -0
  28. package/lang/fr.js +1 -0
  29. package/lang/hi.js +1 -0
  30. package/lang/ja.js +1 -0
  31. package/lang/ko.js +1 -0
  32. package/lang/nl.js +1 -0
  33. package/lang/pt.js +1 -0
  34. package/lang/sv.js +1 -0
  35. package/lang/tr.js +1 -0
  36. package/lang/zh-cn.js +1 -0
  37. package/lang/zh-tw.js +1 -0
  38. package/package.json +1 -1
  39. package/components/list/demo/list-drag-and-drop.js +0 -181
@@ -62,6 +62,7 @@ class ButtonIcon extends ThemeMixin(ButtonMixin(VisibleOnAncestorMixin(RtlMixin(
62
62
  --d2l-button-icon-h-align: calc(((2rem + 2px - 0.9rem) / 2) * -1);
63
63
  --d2l-icon-fill-color: var(--d2l-button-icon-fill-color, var(--d2l-color-tungsten));
64
64
  display: inline-block;
65
+ line-height: 0;
65
66
  }
66
67
  :host([hidden]) {
67
68
  display: none;
@@ -28,6 +28,14 @@
28
28
  </template>
29
29
  </d2l-demo-snippet>
30
30
 
31
+ <h2>Search Input (Search on Input)</h2>
32
+ <d2l-demo-snippet>
33
+ <template>
34
+ <d2l-input-search label="Search" value="Will dispatch search after every input" placeholder="Search for some stuff" search-on-input>
35
+ </d2l-input-search>
36
+ </template>
37
+ </d2l-demo-snippet>
38
+
31
39
  <script>
32
40
  document.body.addEventListener('d2l-input-search-searched', (e) => {
33
41
  // eslint-disable-next-line no-console
@@ -60,6 +60,7 @@ For text searches use `<d2l-input-search>`, which wraps the native `<input type=
60
60
  | `disabled` | Boolean | Disables the input |
61
61
  | `maxlength` | Number | Imposes an upper character limit |
62
62
  | `no-clear` | Boolean | Prevents the "clear" button from appearing |
63
+ | `search-on-input` | Boolean | Dispatch search events after each input event |
63
64
  | `placeholder` | String, default:`'Search...'` | Placeholder text |
64
65
  | `value` | String, default: `''` | Value of the input |
65
66
 
@@ -8,6 +8,8 @@ import { inputStyles } from './input-styles.js';
8
8
  import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
9
9
  import { RtlMixin } from '../../mixins/rtl-mixin.js';
10
10
 
11
+ const INPUT_TIMEOUT_MS = 400;
12
+
11
13
  /**
12
14
  * This component wraps the native "<input type="search">"" element and is for text searching.
13
15
  * @fires d2l-input-search-searched - Dispatched when a search is performed. When the input is cleared, this will be fired with an empty value.
@@ -50,6 +52,11 @@ class InputSearch extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement)))
50
52
  * @type {string}
51
53
  */
52
54
  placeholder: { type: String },
55
+ /**
56
+ * Dispatch search events after each input event
57
+ * @type {boolean}
58
+ */
59
+ searchOnInput: { type: Boolean, attribute: 'search-on-input' },
53
60
  /**
54
61
  * Value of the input
55
62
  * @type {string}
@@ -81,9 +88,11 @@ class InputSearch extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement)))
81
88
 
82
89
  constructor() {
83
90
  super();
91
+ this._inputTimeout = undefined;
84
92
  this._lastSearchValue = '';
85
93
  this.disabled = false;
86
94
  this.noClear = false;
95
+ this.searchOnInput = false;
87
96
  this.value = '';
88
97
  }
89
98
 
@@ -151,6 +160,12 @@ class InputSearch extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement)))
151
160
  return showSearch;
152
161
  }
153
162
 
163
+ _debounceInput() {
164
+ clearTimeout(this._inputTimeout);
165
+ this._setLastSearchValue(this.value);
166
+ this._inputTimeout = setTimeout(() => this._dispatchEvent(), INPUT_TIMEOUT_MS);
167
+ }
168
+
154
169
  _dispatchEvent() {
155
170
  this.dispatchEvent(new CustomEvent(
156
171
  'd2l-input-search-searched',
@@ -169,6 +184,9 @@ class InputSearch extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement)))
169
184
 
170
185
  _handleInput(e) {
171
186
  this.value = e.target.value;
187
+ if (this.searchOnInput) {
188
+ this._debounceInput();
189
+ }
172
190
  }
173
191
 
174
192
  _handleInputKeyPress(e) {
@@ -193,6 +193,67 @@ If a `d2l-list-item` is selectable then it should have a `label` attribute that
193
193
  </d2l-list>
194
194
  ```
195
195
 
196
+ ## Expandable Lists
197
+
198
+ The `d2l-list` supports expandable items within a list. Expand and collapse toggle is enabled when `d2l-list-item`s have the `expandable` and `key` attributes set. When items are expandable the default state is collapsed. If you would like the default state to be expanded, add the `expanded` attribute to the `d2l-list-item`.
199
+
200
+ ### Expandable List Accessibility Properties
201
+
202
+ If a `d2l-list-item` is expandable then it should have a `label` attribute that corresponds to the hidden label for the expand/collapse toggle.
203
+
204
+ ### Expandable List Example
205
+
206
+ <!-- docs: demo code autoSize:false size:medium -->
207
+ ```html
208
+ <script type="module">
209
+ import '@brightspace-ui/core/components/list/list.js';
210
+ import '@brightspace-ui/core/components/list/list-header.js';
211
+ import '@brightspace-ui/core/components/list/list-item.js';
212
+ import '@brightspace-ui/core/components/list/list-item-content.js';
213
+ import '@brightspace-ui/core/components/selection/selection-action.js';
214
+ </script>
215
+
216
+ <d2l-list grid style="width: 100%">
217
+ <d2l-list-header slot="header">
218
+ <d2l-selection-action icon="tier1:delete" text="Delete" requires-selection></d2l-selection-action>
219
+ </d2l-list-header>
220
+ <d2l-list-item selectable expandable key="expand-1" label="Expandable item #1">
221
+ <d2l-list-item-content>
222
+ <div>Expandable item #1</div>
223
+ <div slot="supporting-info">Supporting information</div>
224
+ </d2l-list-item-content>
225
+ <d2l-list grid style="width: 100%" slot="nested">
226
+ <d2l-list-item selectable key="nested-1" label="Nested 1">
227
+ <d2l-list-item-content><div>Nested item #1</div></d2l-list-item-content>
228
+ </d2l-list-item>
229
+ <d2l-list-item selectable key="nested-2" label="Nested 2">
230
+ <d2l-list-item-content><div>Nested item #2</div></d2l-list-item-content>
231
+ </d2l-list-item>
232
+ </d2l-list>
233
+ </d2l-list-item>
234
+ <d2l-list-item selectable expandable expanded key="expand-2" label="Expandable item #2">
235
+ <d2l-list-item-content>
236
+ <div>Expandable Item #2</div>
237
+ <div slot="supporting-info">Supporting information</div>
238
+ </d2l-list-item-content>
239
+ <d2l-list grid style="width: 100%" slot="nested">
240
+ <d2l-list-item selectable key="nested-3" label="Nested 3">
241
+ <d2l-list-item-content><div>Nested item #3</div></d2l-list-item-content>
242
+ </d2l-list-item>
243
+ <d2l-list-item selectable key="nested-4" label="Nested 4">
244
+ <d2l-list-item-content><div>Nested item #4</div></d2l-list-item-content>
245
+ </d2l-list-item>
246
+ </d2l-list>
247
+ </d2l-list-item>
248
+ <d2l-list-item selectable key="expand-3" label="Item with no children">
249
+ <d2l-list-item-content>
250
+ <div>Item with no children</div>
251
+ <div slot="supporting-info">Supporting information</div>
252
+ </d2l-list-item-content>
253
+ </d2l-list-item>
254
+ </d2l-list>
255
+ ```
256
+
196
257
  ## Pageable Lists
197
258
 
198
259
  Load-More paging functionality can be implemented in lists by placing a `d2l-pager-load-more` in `d2l-list`'s `pager` slot. The consumer must handle the `d2l-pager-load-more` event by loading more items, updating the pager state, and signalling completion by calling `complete()` on the event detail. Focus will be automatically moved on the first new item once complete. See [Paging](../../components/paging) for more details.
@@ -347,6 +408,8 @@ The `d2l-list-item` provides the appropriate `listitem` semantics for children w
347
408
  | `drag-target-handle-only` | Boolean | Make the drag target the drag handle only. |
348
409
  | `drop-nested` | Boolean | Whether nested items can be dropped on this item |
349
410
  | `drop-text` | String | Text to drag and drop |
411
+ | `expandable` | Boolean | Whether or not to show the expand/collapse toggle. |
412
+ | `expanded` | Boolean | Whether the item is expanded. Requires `expandable` to be set. |
350
413
  | `href` | String | Address of item link if navigable |
351
414
  | `key` | String | Value to identify item if selectable or draggable |
352
415
  | `label` | String | Explicitly defined label for the element |
@@ -366,6 +429,7 @@ The `d2l-list-item` provides the appropriate `listitem` semantics for children w
366
429
  ### Events
367
430
 
368
431
  - `d2l-list-item-link-click`: dispatched when the item's primary link action is clicked
432
+ - `d2l-list-item-expand-collapse-toggled`: dispatched when the item's expand/collapse toggle is clicked
369
433
  <!-- docs: end hidden content -->
370
434
 
371
435
  ### Breakpoints Property
@@ -417,6 +481,8 @@ The `d2l-list-item-button` provides the same functionality as `d2l-list-item` ex
417
481
  | `drag-handle-text` | String | The drag-handle label for assistive technology. If implementing drag & drop, you should change this to dynamically announce what the drag-handle is moving for assistive technology in keyboard mode. |
418
482
  | `drop-nested` | Boolean | Whether nested items can be dropped on this item |
419
483
  | `drop-text` | String | Text to drag and drop |
484
+ | `expandable` | Boolean | Whether or not to show the expand/collapse toggle. |
485
+ | `expanded` | Boolean | Whether the item is expanded. Requires `expandable` to be set. |
420
486
  | `key` | String | Value to identify item if selectable or draggable |
421
487
  | `label` | String | Explicitly defined label for the element |
422
488
  | `labelled-by` | String | The id of element that provides the label for this element |
@@ -428,6 +494,7 @@ The `d2l-list-item-button` provides the same functionality as `d2l-list-item` ex
428
494
  ### Events
429
495
 
430
496
  - `d2l-list-item-button-click`: dispatched when the item's primary button action is clicked
497
+ - `d2l-list-item-expand-collapse-toggled`: dispatched when the item's expand/collapse toggle is clicked
431
498
  <!-- docs: end hidden content -->
432
499
 
433
500
  ## ListItemMixin
@@ -0,0 +1,133 @@
1
+ import '../list-item-content.js';
2
+ import '../list-item.js';
3
+ import '../list.js';
4
+ import '../list-header.js';
5
+ import '../../selection/selection-action.js';
6
+ import { html, LitElement, nothing } from 'lit';
7
+ import { getUniqueId } from '../../../helpers/uniqueId.js';
8
+ import { ifDefined } from 'lit/directives/if-defined.js';
9
+ import { repeat } from 'lit/directives/repeat.js';
10
+
11
+ class ListDemoNestedLazyLoad extends LitElement {
12
+
13
+ static get properties() {
14
+ return {
15
+ _items: { state: true },
16
+ };
17
+ }
18
+
19
+ constructor() {
20
+ super();
21
+ this._items = new Map();
22
+ this._items.set('a', {
23
+ key: 'a',
24
+ primaryText: 'Item 1: Click Expand To Lazy Load Item',
25
+ items: [],
26
+ expandable: true,
27
+ selected: false
28
+ });
29
+ this._items.set('b', {
30
+ key: 'b',
31
+ primaryText: 'Item 2: Click Expand To Lazy Load Item',
32
+ items: [],
33
+ expandable: true,
34
+ selected: false
35
+ });
36
+ }
37
+
38
+ render() {
39
+ return html`
40
+ <div>
41
+ ${this._renderList(this._items.values(), false, true)}
42
+ </div>
43
+ `;
44
+ }
45
+
46
+ _handleListItemToggle(e) {
47
+ const listItem = e.target;
48
+ const itemKey = e.target.key;
49
+ const previouslyCollapsed = !e.target.expanded;
50
+ const itemToAddChildren = this._items.get(itemKey);
51
+ if (!previouslyCollapsed && itemToAddChildren.items.length === 0) {
52
+ if (listItem.selected) {
53
+ itemToAddChildren.selected = true;
54
+ }
55
+ const uniqueId = getUniqueId();
56
+ itemToAddChildren.items = [{
57
+ key: uniqueId,
58
+ primaryText: `Lazy Loaded Item ${uniqueId}`,
59
+ items: [],
60
+ expandable: false,
61
+ selected: listItem.selected
62
+ }];
63
+
64
+ setTimeout(() => {
65
+ // fake lazy loading items
66
+ this._items.set(itemKey, itemToAddChildren);
67
+ this.requestUpdate();
68
+ }, 2000);
69
+ }
70
+ }
71
+
72
+ _renderIllustration(item) {
73
+ if (!item.imgSrc) {
74
+ return nothing;
75
+ }
76
+ return html`<img slot="illustration" src="${item.imgSrc}">`;
77
+ }
78
+
79
+ _renderItemContent(item) {
80
+ return html`
81
+ <d2l-list-item-content>
82
+ <div>${item.primaryText}</div>
83
+ <div slot="supporting-info">${item.supportingText}</div>
84
+ </d2l-list-item-content>`;
85
+ }
86
+
87
+ _renderList(items, nested, includeHeader = false) {
88
+ return html`
89
+ <d2l-list grid drag-multiple slot="${ifDefined(nested ? 'nested' : undefined)}">
90
+ ${ includeHeader ? this._renderListHeader() : nothing }
91
+ ${repeat(items, item => item.key, item => html`
92
+ ${this._renderListItem(item)}
93
+ `)}
94
+ </d2l-list>
95
+ `;
96
+ }
97
+
98
+ _renderListHeader() {
99
+ return html`
100
+ <d2l-list-header slot="header">
101
+ <d2l-selection-action icon="tier1:bookmark-hollow" text="Bookmark" requires-selection></d2l-selection-action>
102
+ <d2l-selection-action icon="tier1:gear" text="Settings"></d2l-selection-action>
103
+ </d2l-list-header>
104
+ `;
105
+ }
106
+
107
+ _renderListItem(item) {
108
+ return html`
109
+ <d2l-list-item
110
+ draggable
111
+ selectable
112
+ ?selected="${item.selected}"
113
+ drag-handle-text="${item.primaryText}"
114
+ key="${item.key}"
115
+ label="${item.primaryText}"
116
+ ?expandable="${item.expandable}"
117
+ @d2l-list-item-expand-collapse-toggled="${this._handleListItemToggle}">
118
+ ${this._renderIllustration(item)}
119
+ ${this._renderItemContent(item)}
120
+ ${this._renderNestedList(item)}
121
+ </d2l-list-item>
122
+ `;
123
+ }
124
+
125
+ _renderNestedList(item) {
126
+ if (item?.items?.length <= 0) {
127
+ return nothing;
128
+ }
129
+ return this._renderList(item.items, true);
130
+ }
131
+ }
132
+
133
+ customElements.define('d2l-demo-list-nested-lazy-load', ListDemoNestedLazyLoad);
@@ -0,0 +1,279 @@
1
+ import '../list-item-content.js';
2
+ import '../list-item.js';
3
+ import '../list-item-button.js';
4
+ import '../list.js';
5
+ import '../../dropdown/dropdown-menu.js';
6
+ import '../../dropdown/dropdown-more.js';
7
+ import '../../menu/menu.js';
8
+ import '../../menu/menu-item.js';
9
+ import '../../paging/pager-load-more.js';
10
+ import '../list-header.js';
11
+ import '../../selection/selection-action.js';
12
+ import { css, html, LitElement, nothing } from 'lit';
13
+ import { ifDefined } from 'lit/directives/if-defined.js';
14
+ import { listDemos } from './list-demo-scenarios.js';
15
+ import { moveLocations } from '../list-item-drag-drop-mixin.js';
16
+ import { repeat } from 'lit/directives/repeat.js';
17
+
18
+ class ListDemoNested extends LitElement {
19
+
20
+ static get properties() {
21
+ return {
22
+ demoItemKey: { type: String, attribute: 'demo-item-key' },
23
+ draggable: { type: Boolean },
24
+ selectable: { type: Boolean },
25
+ disableExpandFeature: { type: Boolean, attribute: 'disable-expand-feature' },
26
+ expanded: { type: Boolean },
27
+ includeSecondaryActions: { type: Boolean, attribute: 'include-secondary-actions' },
28
+ includeListHeader: { type: Boolean, attribute: 'include-list-header' },
29
+ includeActionHref: { type: Boolean, attribute: 'include-action-href' },
30
+ useButtonListItem: { type: Boolean, attribute: 'use-button-item' },
31
+ showLoadMore: { type: Boolean, attribute: 'show-load-more' },
32
+ noPrimaryAction: { type: Boolean, attribute: 'no-primary-action' },
33
+ disableListGrid: { type: Boolean, attribute: 'disable-list-grid' },
34
+ _items: { state: true },
35
+ _loadedItems: { state: true },
36
+ _remainingItemCount: { state: true },
37
+ _lastItemLoadedIndex: { state: true }
38
+ };
39
+ }
40
+
41
+ static get styles() {
42
+ return [
43
+ css`
44
+ .secondary-actions {
45
+ padding-right: 6px;
46
+ }
47
+ `
48
+ ];
49
+ }
50
+
51
+ constructor() {
52
+ super();
53
+ this._items = [];
54
+ this._loadedItems = [];
55
+ this._remainingItemCount = 0;
56
+ this._lastItemLoadedIndex = 1;
57
+ this._pageSize = 1;
58
+ }
59
+
60
+ render() {
61
+ return html`
62
+ <div @d2l-list-items-move="${this._handleListItemsMove}">
63
+ ${this._renderList(this._loadedItems, false, this.includeListHeader, this.showLoadMore)}
64
+ </div>
65
+ `;
66
+ }
67
+
68
+ updated(changedProperties) {
69
+ super.updated(changedProperties);
70
+ if (changedProperties.has('demoItemKey')) {
71
+ this._items = listDemos[this.demoItemKey] ?? [];
72
+ this._loadedItems = this._items;
73
+ }
74
+ if (changedProperties.has('_items') || changedProperties.has('demoItemKey') || changedProperties.has('showLoadMore') || changedProperties.has('_lastItemLoadedIndex')) {
75
+ this._loadedItems = this.showLoadMore ? this._items.slice(0, this._lastItemLoadedIndex + 1) : this._items;
76
+ this._remainingItemCount = this.showLoadMore ? this._items.length - this._loadedItems.length : 0;
77
+ }
78
+ }
79
+
80
+ _handleButtonClick(e) {
81
+ // eslint-disable-next-line no-console
82
+ console.log('d2l-list-item-button clicked!', e);
83
+ }
84
+
85
+ async _handleListItemsMove(e) {
86
+
87
+ const sourceListItems = e.detail.sourceItems;
88
+ const target = e.detail.target;
89
+
90
+ // helper that gets the array containing item data, the item data, and the index within the array
91
+ const getItemInfo = (items, key) => {
92
+ for (let i = 0; i < items.length; i++) {
93
+ if (items[i].key === key) {
94
+ return { owner: items, item: items[i], index: i };
95
+ }
96
+ if (items[i].items && items[i].items.length > 0) {
97
+ const tempItemData = getItemInfo(items[i].items, key);
98
+ if (tempItemData) return tempItemData;
99
+ }
100
+ }
101
+ };
102
+
103
+ const dataToMove = [];
104
+
105
+ // remove data elements from original locations
106
+ sourceListItems.forEach(sourceListItem => {
107
+ const info = getItemInfo(this._items, sourceListItem.key);
108
+ if (info?.owner) {
109
+ info.owner.splice(info.index, 1);
110
+ }
111
+ if (info?.item) {
112
+ dataToMove.push(info.item);
113
+ }
114
+ });
115
+
116
+ // append data elements to new location
117
+ const targetInfo = getItemInfo(this._items, target.item.key);
118
+ let targetItems;
119
+ let targetIndex;
120
+ if (target.location === moveLocations.nest) {
121
+ if (!targetInfo.item.items) targetInfo.item.items = [];
122
+ targetItems = targetInfo.item.items;
123
+ targetIndex = targetItems.length;
124
+ } else {
125
+ targetItems = targetInfo?.owner;
126
+ if (!targetItems) return;
127
+ if (target.location === moveLocations.above) targetIndex = targetInfo.index;
128
+ else if (target.location === moveLocations.below) targetIndex = targetInfo.index + 1;
129
+ }
130
+ for (let i = dataToMove.length - 1; i >= 0; i--) {
131
+ targetItems.splice(targetIndex, 0, dataToMove[i]);
132
+ }
133
+
134
+ this.requestUpdate();
135
+ await this.updateComplete;
136
+
137
+ if (e.detail.keyboardActive) {
138
+ setTimeout(() => {
139
+ if (!this.shadowRoot) return;
140
+ const newItem = this.shadowRoot.querySelector('d2l-list').getListItemByKey(sourceListItems[0].key);
141
+ newItem.activateDragHandle();
142
+ });
143
+ }
144
+
145
+ }
146
+
147
+ _handlePagerLoadMore(e) {
148
+ // mock delay consumers might have
149
+ setTimeout(() => {
150
+ this._lastItemLoadedIndex += this._pageSize;
151
+ e.detail.complete();
152
+ }, 1000);
153
+ }
154
+
155
+ _renderIllustration(item) {
156
+ if (!item.imgSrc) {
157
+ return nothing;
158
+ }
159
+ return html`<img slot="illustration" src="${item.imgSrc}">`;
160
+ }
161
+
162
+ _renderItemContent(item) {
163
+ return html`
164
+ <d2l-list-item-content>
165
+ <div>${item.primaryText}</div>
166
+ <div slot="supporting-info">${item.supportingText}</div>
167
+ </d2l-list-item-content>`;
168
+ }
169
+
170
+ _renderList(items, nested, includeHeader = false, showLoadMore = false) {
171
+ return html`
172
+ <d2l-list ?grid="${!this.disableListGrid}" drag-multiple slot="${ifDefined(nested ? 'nested' : undefined)}">
173
+ ${ includeHeader ? this._renderListHeader() : nothing }
174
+ ${repeat(items, item => item.key, item => html`
175
+ ${this._renderListItem(item)}
176
+ ${this._renderListItemButton(item)}
177
+ `)}
178
+ ${ showLoadMore ? this._renderShowLoadMore() : nothing }
179
+ </d2l-list>
180
+ `;
181
+ }
182
+
183
+ _renderListHeader() {
184
+ return html`
185
+ <d2l-list-header slot="header">
186
+ <d2l-selection-action icon="tier1:bookmark-hollow" text="Bookmark" requires-selection></d2l-selection-action>
187
+ <d2l-selection-action icon="tier1:gear" text="Settings"></d2l-selection-action>
188
+ </d2l-list-header>
189
+ `;
190
+ }
191
+
192
+ _renderListItem(item) {
193
+ if (this.useButtonListItem) {
194
+ return nothing;
195
+ }
196
+ const hasChildren = item?.items?.length > 0;
197
+ return html`
198
+ <d2l-list-item
199
+ action-href="${this.includeActionHref ? 'http://www.d2l.com' : ''}"
200
+ ?draggable="${this.draggable}"
201
+ drag-handle-text="${item.primaryText}"
202
+ ?drop-nested="${item.dropNested}"
203
+ key="${item.key}"
204
+ label="${item.primaryText}"
205
+ ?selectable="${this.selectable}"
206
+ ?expandable="${this.disableExpandFeature ? false : hasChildren}"
207
+ ?expanded="${this.expanded}"
208
+ ?no-primary-action="${this.noPrimaryAction}">
209
+ ${this._renderIllustration(item)}
210
+ ${this._renderItemContent(item)}
211
+ ${this._renderSecondaryActions()}
212
+ ${this._renderNestedList(item)}
213
+ </d2l-list-item>
214
+ `;
215
+ }
216
+
217
+ _renderListItemButton(item) {
218
+ if (!this.useButtonListItem) {
219
+ return nothing;
220
+ }
221
+ const hasChildren = item?.items?.length > 0;
222
+ return html`
223
+ <d2l-list-item-button
224
+ ?draggable="${this.draggable}"
225
+ drag-handle-text="${item.primaryText}"
226
+ ?drop-nested="${item.dropNested}"
227
+ key="${item.key}"
228
+ label="${item.primaryText}"
229
+ ?selectable="${this.selectable}"
230
+ ?expandable="${this.disableExpandFeature ? false : hasChildren}"
231
+ ?expanded="${this.expanded}"
232
+ @d2l-list-item-button-click="${this._handleButtonClick}">
233
+ ${this._renderIllustration(item)}
234
+ ${this._renderItemContent(item)}
235
+ ${this._renderSecondaryActions()}
236
+ ${this._renderNestedList(item)}
237
+ </d2l-list-item-button>
238
+ `;
239
+ }
240
+
241
+ _renderNestedList(item) {
242
+ if (item?.items?.length <= 0) {
243
+ return nothing;
244
+ }
245
+ return this._renderList(item.items, true);
246
+ }
247
+
248
+ _renderSecondaryActions() {
249
+ if (!this.includeSecondaryActions) {
250
+ return nothing;
251
+ }
252
+ return html`
253
+ <div slot="actions" class="secondary-actions">
254
+ <d2l-dropdown-more text="Open!">
255
+ <d2l-dropdown-menu>
256
+ <d2l-menu label="More Actions">
257
+ <d2l-menu-item text="Action 1"></d2l-menu-item>
258
+ <d2l-menu-item text="Action 2"></d2l-menu-item>
259
+ </d2l-menu>
260
+ </d2l-dropdown-menu>
261
+ </d2l-dropdown-more>
262
+ </div>
263
+ `;
264
+ }
265
+
266
+ _renderShowLoadMore() {
267
+ return html`
268
+ <d2l-pager-load-more slot="pager"
269
+ @d2l-pager-load-more="${this._handlePagerLoadMore}"
270
+ ?has-more="${this._lastItemLoadedIndex < this._items.length - 1}"
271
+ item-count="${this._items.length}"
272
+ page-size="${this._remainingItemCount < this._pageSize ? this._remainingItemCount : this._pageSize}">
273
+ </d2l-pager-load-more>
274
+ `;
275
+ }
276
+
277
+ }
278
+
279
+ customElements.define('d2l-demo-list-nested', ListDemoNested);