@brightspace-ui/core 2.77.0 → 2.78.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.
Files changed (37) hide show
  1. package/components/button/button-icon.js +1 -0
  2. package/components/collapsible-panel/README.md +28 -15
  3. package/components/list/README.md +67 -0
  4. package/components/list/demo/demo-list-nested-lazy-load.js +133 -0
  5. package/components/list/demo/demo-list-nested.js +279 -0
  6. package/components/list/demo/list-demo-scenarios.js +321 -0
  7. package/components/list/demo/list-drag-and-drop.html +2 -2
  8. package/components/list/demo/list-expand-collapse.html +134 -0
  9. package/components/list/list-item-checkbox-mixin.js +2 -8
  10. package/components/list/list-item-drag-drop-mixin.js +78 -14
  11. package/components/list/list-item-drag-image.js +5 -3
  12. package/components/list/list-item-expand-collapse-mixin.js +168 -0
  13. package/components/list/list-item-generic-layout.js +21 -12
  14. package/components/list/list-item-mixin.js +88 -11
  15. package/components/list/list.js +45 -9
  16. package/components/selection/selection-summary.js +43 -12
  17. package/custom-elements.json +386 -194
  18. package/lang/ar.js +1 -0
  19. package/lang/cy.js +1 -0
  20. package/lang/da.js +1 -0
  21. package/lang/de.js +1 -0
  22. package/lang/en.js +1 -0
  23. package/lang/es-es.js +1 -0
  24. package/lang/es.js +1 -0
  25. package/lang/fr-fr.js +1 -0
  26. package/lang/fr.js +1 -0
  27. package/lang/hi.js +1 -0
  28. package/lang/ja.js +1 -0
  29. package/lang/ko.js +1 -0
  30. package/lang/nl.js +1 -0
  31. package/lang/pt.js +1 -0
  32. package/lang/sv.js +1 -0
  33. package/lang/tr.js +1 -0
  34. package/lang/zh-cn.js +1 -0
  35. package/lang/zh-tw.js +1 -0
  36. package/package.json +1 -1
  37. 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;
@@ -97,17 +97,16 @@ The `d2l-collapsible-panel` element is a container that provides specific layout
97
97
 
98
98
  <style>
99
99
  d2l-collapsible-panel {
100
- width: 500px;
101
- margin-block: 2rem;
100
+ width: 800px;
102
101
  }
103
102
  /* TODO: remove this when daylight demo resizing is fixed */
104
103
  d2l-collapsible-panel:not([expanded]) {
105
- margin-bottom: 8rem;
104
+ margin-bottom: 14rem;
106
105
  }
107
106
  </style>
108
107
 
109
- <d2l-collapsible-panel panel-title="Cake Decoration">
110
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas odio ligula, aliquam efficitur sollicitudin non, dignissim quis nisl. Nullam rutrum, lectus sed finibus consectetur, dolor leo blandit lorem, vitae consectetur arcu enim ornare tortor.
108
+ <d2l-collapsible-panel panel-title="Collapsible Panel">
109
+ The collapsible panel is also nicknamed caketray! Team Polaris coined this nickname back in 2020 while creating a labs component for a tool called Learning Paths (which is now replaced with the collapsible panel). They wanted to distinguish this labs component from d2l-card, but they didn't know what to call it, so they named it caketray to serve as a reminder to change the name later. Caketray caught on around the company, so much so that we had to make it an official nickname so some teams could find it! You'll see some other cake-related examples throughout this documentation to pay tribute to the collapsible panel's heritage.
111
110
  </d2l-collapsible-panel>
112
111
  ```
113
112
 
@@ -204,9 +203,7 @@ Use an inline collapsible panel to progressively disclose sections of a complex
204
203
  ## Summary Items [d2l-collapsible-panel-summary-item]
205
204
  An optional summary can help the user understand what’s inside the collapsible panel without having to expand it. This can be helpful if the user needs more than the heading to explain what’s inside.
206
205
 
207
- More than one d2l-collapsible-panel-summary-item can be added to the summary slot, and each will appear on its own line.
208
-
209
- <!-- docs: demo live -->
206
+ <!-- docs: demo -->
210
207
  ```html
211
208
  <script type="module">
212
209
  import '@brightspace-ui/core/components/collapsible-panel/collapsible-panel.js';
@@ -234,7 +231,7 @@ class CollapsiblePanelDaylightDemo extends LitElement {
234
231
  }
235
232
  /* TODO: remove this when daylight demo resizing is fixed */
236
233
  d2l-collapsible-panel:not([expanded]) {
237
- margin-bottom: 13rem;
234
+ margin-bottom: 12rem;
238
235
  }
239
236
  `];
240
237
  }
@@ -292,9 +289,26 @@ customElements.define('d2l-collapsible-panel-daylight-demo', CollapsiblePanelDay
292
289
  <d2l-collapsible-panel-daylight-demo></d2l-collapsible-panel-daylight-demo>
293
290
  ```
294
291
 
295
- ## Optional slots
292
+ More than one `d2l-collapsible-panel-summary-item` can be added to the `summary` slot, and each will appear on its own line.
293
+
294
+ ```html
295
+ <script type="module">
296
+ import '@brightspace-ui/core/components/collapsible-panel/collapsible-panel.js';
297
+ import '@brightspace-ui/core/components/collapsible-panel/collapsible-panel-summary-item.js';
298
+ </script>
299
+
300
+ <d2l-collapsible-panel panel-title="Cake Decoration">
301
+ <d2l-collapsible-panel-summary-item slot="summary" text="Buttercream icing"></d2l-collapsible-panel-summary-item>
302
+ <d2l-collapsible-panel-summary-item slot="summary" text="Personalized name"></d2l-collapsible-panel-summary-item>
303
+ <d2l-collapsible-panel-summary-item slot="summary" text="Candles"></d2l-collapsible-panel-summary-item>
304
+ <d2l-collapsible-panel-summary-item slot="summary" text="Plates and Forks"></d2l-collapsible-panel-summary-item>
305
+ Expanded content
306
+ </d2l-collapsible-panel>
307
+ ```
308
+
309
+ ## Header and actions slots
296
310
 
297
- Collapsible panels have two optional slots, `actions` and `header` that can be used to add more information to the header area.
311
+ Collapsible panels have two optional slots, `header` and `actions` that can be used to add more information to the header area.
298
312
 
299
313
 
300
314
  <!-- docs: demo live -->
@@ -302,6 +316,7 @@ Collapsible panels have two optional slots, `actions` and `header` that can be u
302
316
  <script type="module">
303
317
  import '@brightspace-ui/core/components/button/button-icon.js';
304
318
  import '@brightspace-ui/core/components/collapsible-panel/collapsible-panel.js';
319
+ import '@brightspace-ui/core/components/collapsible-panel/collapsible-panel-summary-item.js';
305
320
  import '@brightspace-ui/core/components/dropdown/dropdown-more.js';
306
321
  import '@brightspace-ui/core/components/dropdown/dropdown-menu.js';
307
322
  import '@brightspace-ui/core/components/link/link.js';
@@ -314,10 +329,6 @@ Collapsible panels have two optional slots, `actions` and `header` that can be u
314
329
  d2l-collapsible-panel {
315
330
  width: 800px;
316
331
  }
317
- /* TODO: remove this when daylight demo resizing is fixed */
318
- d2l-collapsible-panel:not([expanded]) {
319
- margin-bottom: 4rem;
320
- }
321
332
  </style>
322
333
 
323
334
  <d2l-collapsible-panel panel-title="Submission 1">
@@ -336,6 +347,8 @@ Collapsible panels have two optional slots, `actions` and `header` that can be u
336
347
  <p class="d2l-body-small">Submitted On: Jul 20, 2021 - 2:23 PM</p>
337
348
  <d2l-link small href="https://www.d2l.com" target="blank">Link to post</d2l-link>
338
349
  </div>
350
+ <d2l-collapsible-panel-summary-item slot="summary" text="Week 2 Lab (PDF) attached"></d2l-collapsible-panel-summary-item>
351
+ <d2l-collapsible-panel-summary-item slot="summary" text="1 comment"></d2l-collapsible-panel-summary-item>
339
352
  Expanded content
340
353
  </d2l-collapsible-panel>
341
354
  ```
@@ -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);