@brightspace-ui/core 1.213.1 → 1.216.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 (76) hide show
  1. package/components/button/button-mixin.js +1 -1
  2. package/components/calendar/calendar.js +5 -5
  3. package/components/card/card-footer-link.js +2 -2
  4. package/components/card/card.js +1 -1
  5. package/components/demo/code-view.js +2 -2
  6. package/components/demo/demo-snippet.js +5 -2
  7. package/components/dialog/dialog-confirm.js +1 -0
  8. package/components/dialog/dialog-mixin.js +7 -2
  9. package/components/dropdown/dropdown-button-subtle.js +1 -1
  10. package/components/dropdown/dropdown-button.js +1 -1
  11. package/components/dropdown/dropdown-content-mixin.js +6 -6
  12. package/components/dropdown/dropdown-context-menu.js +1 -1
  13. package/components/dropdown/dropdown-menu.js +1 -0
  14. package/components/dropdown/dropdown-more.js +1 -1
  15. package/components/dropdown/dropdown-opener-mixin.js +1 -0
  16. package/components/dropdown/dropdown-tabs.js +1 -0
  17. package/components/dropdown/dropdown.js +1 -0
  18. package/components/expand-collapse/expand-collapse-content.js +4 -4
  19. package/components/filter/filter.js +5 -4
  20. package/components/focus-trap/focus-trap.js +6 -5
  21. package/components/form/demo/form-demo.js +1 -1
  22. package/components/form/demo/form-dialog-demo.js +4 -4
  23. package/components/form/demo/form-native-demo.js +1 -1
  24. package/components/form/form-element-mixin.js +12 -3
  25. package/components/form/form-errory-summary.js +2 -2
  26. package/components/form/form-native.js +1 -1
  27. package/components/form/form.js +1 -1
  28. package/components/hierarchical-view/hierarchical-view-mixin.js +7 -6
  29. package/components/html-block/demo/html-block.html +31 -0
  30. package/components/html-block/html-block.js +18 -7
  31. package/components/inputs/demo/input-radio-solo-test.js +1 -1
  32. package/components/inputs/demo/input-radio-spacer-test.js +1 -1
  33. package/components/inputs/demo/input-select-test.js +1 -1
  34. package/components/inputs/input-checkbox.js +1 -1
  35. package/components/inputs/input-date-range.js +4 -3
  36. package/components/inputs/input-date-time-range-to.js +1 -1
  37. package/components/inputs/input-date-time-range.js +4 -3
  38. package/components/inputs/input-date-time.js +6 -5
  39. package/components/inputs/input-date.js +3 -0
  40. package/components/inputs/input-number.js +2 -1
  41. package/components/inputs/input-percent.js +2 -1
  42. package/components/inputs/input-search.js +3 -3
  43. package/components/inputs/input-text.js +8 -8
  44. package/components/inputs/input-textarea.js +5 -5
  45. package/components/inputs/input-time-range.js +4 -4
  46. package/components/inputs/input-time.js +1 -1
  47. package/components/link/link.js +1 -1
  48. package/components/list/README.md +91 -59
  49. package/components/list/demo/list-drag-and-drop.js +25 -16
  50. package/components/list/list-header.js +1 -0
  51. package/components/list/list-item-button.js +1 -0
  52. package/components/list/list-item-checkbox-mixin.js +4 -2
  53. package/components/list/list-item-drag-drop-mixin.js +12 -6
  54. package/components/list/list-item-generic-layout.js +5 -4
  55. package/components/list/list-item-mixin.js +1 -0
  56. package/components/list/list-item.js +1 -0
  57. package/components/list/list.js +9 -4
  58. package/components/menu/demo/custom-view.js +1 -1
  59. package/components/menu/menu-item-link.js +1 -1
  60. package/components/menu/menu-item-mixin.js +1 -1
  61. package/components/menu/menu.js +2 -2
  62. package/components/overflow-group/overflow-group.js +1 -1
  63. package/components/scroll-wrapper/demo/scroll-wrapper-test.js +1 -1
  64. package/components/selection/selection-action.js +1 -1
  65. package/components/selection/selection-input.js +1 -1
  66. package/components/selection/selection-select-all.js +1 -1
  67. package/components/switch/switch-mixin.js +1 -1
  68. package/components/table/table-col-sort-button.js +1 -1
  69. package/components/tabs/tabs.js +20 -15
  70. package/components/tooltip/tooltip.js +1 -1
  71. package/custom-elements.json +97 -69
  72. package/directives/animate/animate.js +35 -18
  73. package/helpers/demo/announce-test.js +1 -0
  74. package/mixins/arrow-keys-mixin.js +3 -1
  75. package/package.json +1 -1
  76. package/templates/primary-secondary/primary-secondary.js +2 -1
@@ -137,6 +137,7 @@ The `d2l-list` is the container to create a styled list of items using `d2l-list
137
137
 
138
138
  | Property | Type | Description |
139
139
  |---|---|---|
140
+ | `drag-multiple` | Boolean | Whether the user can drag multiple items |
140
141
  | `grid` | Boolean | Enables keyboard grid for supported list items. See [Accessibility](#accessibility). |
141
142
  | `selection-single` | Boolean | Whether to render with single selection behaviour. If `selection-single` is specified, the list-items will render with radios instead of checkboxes, and the list component will maintain a single selected item. |
142
143
  | `separators` | String | Display separators (`all` (default), `between`, `none`) |
@@ -150,18 +151,20 @@ The `d2l-list` is the container to create a styled list of items using `d2l-list
150
151
 
151
152
  ### Methods
152
153
 
153
- - `getListItemCount`: returns the length of the items within the list
154
- - `getListItemIndex` (Object): returns the index of the given element within the list
155
- - `getSelectedListItems` (Array): returns the selected items; pass `true` to include nested lists
156
- - `getSelectionInfo` (Object): returns a `SelectionInfo` object containing the `state` (`none`, `some`, `all`), and the `keys` (Array) for the selected items
154
+ - `getItems()` (Array): returns the list items within the list
155
+ - `getListItemByKey(key)` (ListItem): returns the list item element from the root or nested lists for the specified key
156
+ - `getListItemCount()` (Number): returns the number of items within the list
157
+ - `getListItemIndex(item)` (Object): returns the index of the given element within the list
158
+ - `getSelectedListItems(includeNested)` (Array): returns the selected items; pass `true` to include nested lists
159
+ - `getSelectionInfo(includeNested)` (Object): returns a `SelectionInfo` object containing the `state` (`none`, `some`, `all`), and the `keys` (Array) for the selected items
157
160
 
158
161
  ## Selection Lists
159
162
 
160
- The `d2l-list` supports selectable items within a list, including both single and multi. Selection is enabled when a `d2l-list-item` has the `selectable` attribute set on it, and is by default multi-select which is indicated by a checkbox. Setting `selection-single` on the `d2l-list` wrapper enables single selection, which renders the selectable items with radio buttons. A `d2l-list-header` component can be added before the `d2l-list-item` component in order to have an easy multi-select header with actions.
163
+ The `d2l-list` supports selectable items within a list, including both single and multi selection. Selection is enabled when `d2l-list-item`s have the `selectable` attribute. When items are selectable, multiple selection is the default behaviour, however the `selection-single` attribute can be applied to the `d2l-list` to enable single selection. A `d2l-list-header` component can be added to `d2l-list`'s `header` slot to provide select-all and bulk actions.
161
164
 
162
165
  ### Accessibility Properties
163
166
 
164
- If a `d2l-list-item` is selectable then it should have a `label` attribute set on it which corresponds to the hidden label for the checkbox.
167
+ If a `d2l-list-item` is selectable then it should have a `label` attribute that corresponds to the hidden label for the checkbox.
165
168
 
166
169
  ### Example
167
170
 
@@ -202,12 +205,15 @@ The `d2l-list` supports drag & drop.
202
205
  ![List](./screenshots/drag-and-drop.gif?raw=true)
203
206
  <!-- docs: end hidden content -->
204
207
 
205
- Because the list itself is a rendering component, there is some light work involved in hooking up this behaviour.
208
+ The `d2l-list` is simply a rendering component, so there is some light work involved in hooking up this behaviour. In order for items to be draggable, they must have their `draggable` and `key` attributes set. Optionally, the `drop-nested` attribute can be applied to items to indicate whether other items can be dropped as nested children on the item.
206
209
 
207
- - `d2l-list-item` components within the list must be `draggable` and have `key` set to something unique
208
- - Reordering and re-rendering is the controlling component's responsibility
210
+ Reordering and re-rendering is the consuming component's responsibility. For a simple flat list, listen for the `d2l-list-item-position-change` event and call the `reorder` helper method. Alternatively, or for more complex lists such as those with nested lists, listen for the `d2l-list-items-move` event on the root list and update the consumer data using the provided source and target event detail.
209
211
 
210
- Here is a simple component example that adds drag 'n' drop to a list:
212
+ ### Accessibility Properties
213
+
214
+ If an item is draggable, the `drag-handle-text` attribute should be used to provide an accessible label for assistive technology in keyboard mode.
215
+
216
+ ### Example
211
217
 
212
218
  <!-- docs: demo code autoSize:false size:medium -->
213
219
  ```html
@@ -227,18 +233,9 @@ Here is a simple component example that adds drag 'n' drop to a list:
227
233
  constructor() {
228
234
  super();
229
235
  this.list = [
230
- {
231
- key: '1',
232
- content: 'Initially first list item'
233
- },
234
- {
235
- key: '2',
236
- content: 'Initially second list item'
237
- },
238
- {
239
- key: '3',
240
- content: 'Initially third list item'
241
- }
236
+ { key: '1', content: 'Initially first list item' },
237
+ { key: '2', content: 'Initially second list item' },
238
+ { key: '3', content: 'Initially third list item' }
242
239
  ];
243
240
  }
244
241
 
@@ -319,7 +316,7 @@ The `d2l-list-header` component can be placed in the `d2l-list`'s `header` slot
319
316
 
320
317
  ## List Item [d2l-list-item]
321
318
 
322
- The `d2l-list-item` provides the appropriate `listitem` semantics for children within a list. It also provides some basic layout, breakpoints for responsiveness, a navigation link for the primary action, and selection. It extends `ListItemLinkMixin` and `ListItemMixin` and has all the same use cases as the mixin.
319
+ The `d2l-list-item` provides the appropriate `listitem` semantics for children within a list. It also provides some basic layout, breakpoints for responsiveness, a navigation link for the primary action, and selection.
323
320
 
324
321
  <!-- docs: start hidden content -->
325
322
  ![List](./screenshots/list-item.png?raw=true)
@@ -353,7 +350,20 @@ The `d2l-list-item` provides the appropriate `listitem` semantics for children w
353
350
 
354
351
  | Property | Type | Description |
355
352
  |---|---|---|
353
+ | `breakpoints` | Array | Breakpoints for responsiveness in pixels. There are four different breakpoints and only the four largest breakpoints will be used. |
354
+ | `disabled` | Boolean | Disables the input |
355
+ | `draggable` | Boolean | Whether the item is draggable |
356
+ | `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. |
357
+ | `drop-nested` | Boolean | Whether nested items can be dropped on this item |
358
+ | `drop-text` | String | Text to drag and drop |
356
359
  | `href` | String | Address of item link if navigable |
360
+ | `key` | String | Value to identify item if selectable or draggable |
361
+ | `label` | String | Explicitly defined label for the element |
362
+ | `labelled-by` | String | The id of element that provides the label for this element |
363
+ | `selectable` | Boolean | Indicates an input should be rendered for selecting the item |
364
+ | `selected` | Boolean | Whether the item is selected |
365
+ | `skeleton` | Boolean | Renders the input as a skeleton loader |
366
+ | `slim` | Boolean | Whether to render the list-item with reduced whitespace|
357
367
 
358
368
  ### Events
359
369
 
@@ -376,6 +386,56 @@ The `d2l-list-item` provides the appropriate `listitem` semantics for children w
376
386
  - Image: max dimensions: `width: 216px` and `height: 120px` and has `20px margin` from the main content;
377
387
  - default break: `843px < x` where `x` is the width of the component.
378
388
 
389
+ ## Button List Item [d2l-list-item-button]
390
+
391
+ The `d2l-list-item-button` provides the same functionality as `d2l-list-item` except with button semantics for its primary action.
392
+
393
+ <!-- docs: start hidden content -->
394
+ ![List](./screenshots/list-item.png?raw=true)
395
+ <!-- docs: end hidden content -->
396
+
397
+ <!-- docs: demo live name:d2l-list-item-button -->
398
+ ```html
399
+ <script type="module">
400
+ import '@brightspace-ui/core/components/list/list.js';
401
+ import '@brightspace-ui/core/components/list/list-item-button.js';
402
+ import '@brightspace-ui/core/components/list/list-item-content.js';
403
+ </script>
404
+
405
+ <d2l-list style="width: 100%">
406
+ <d2l-list-item-button href="http://www.d2l.com" selectable key="1" label="Geomorphology and GIS">
407
+ <d2l-list-item-content>
408
+ <div>Geomorphology and GIS </div>
409
+ <div slot="supporting-info">This course explores the geological processes of the Earth's interior and surface. These include volcanism, earthquakes, mountain...</div>
410
+ </d2l-list-item-content>
411
+ </d2l-list-item-button>
412
+ </d2l-list>
413
+ ```
414
+
415
+ <!-- docs: start hidden content -->
416
+ ### Properties
417
+
418
+ | Property | Type | Description |
419
+ |---|---|---|
420
+ | `breakpoints` | Array | Breakpoints for responsiveness in pixels. There are four different breakpoints and only the four largest breakpoints will be used. |
421
+ | `disabled` | Boolean | Disables the input |
422
+ | `draggable` | Boolean | Whether the item is draggable |
423
+ | `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. |
424
+ | `drop-nested` | Boolean | Whether nested items can be dropped on this item |
425
+ | `drop-text` | String | Text to drag and drop |
426
+ | `key` | String | Value to identify item if selectable or draggable |
427
+ | `label` | String | Explicitly defined label for the element |
428
+ | `labelled-by` | String | The id of element that provides the label for this element |
429
+ | `selectable` | Boolean | Indicates an input should be rendered for selecting the item |
430
+ | `selected` | Boolean | Whether the item is selected |
431
+ | `skeleton` | Boolean | Renders the input as a skeleton loader |
432
+ | `slim` | Boolean | Whether to render the list-item with reduced whitespace|
433
+
434
+ ### Events
435
+
436
+ - `d2l-list-item-button-click`: dispatched when the item's primary button action is clicked
437
+ <!-- docs: end hidden content -->
438
+
379
439
  ## ListItemMixin
380
440
 
381
441
  Want to maintain consistency with `d2l-list-item` but need more modularity? This mixin is for you! This mixin allows you to make a component into a list item without requiring custom styling. All of the properties and functionality from `d2l-list-item` (listed above) will be added to your new component.
@@ -411,42 +471,7 @@ Where the parameters correspond to the slots of `d2l-list-item`:
411
471
  - illustration (TemplateResult): Provide an illustration for your list item.
412
472
  - content (TemplateResult): Core content of the list item, such as a d2l-list-item-content element.
413
473
  - actions (TemplateResult): Secondary actions for the list item.
414
-
415
- ### Accessibility Properties
416
-
417
- - `drag-handle-text`: 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
-
419
- ## Button List Item [d2l-list-item-button]
420
-
421
- The `d2l-list-item-button` provides the same functionality as `d2l-list-item` except with button semantics for its primary action. It extends `ListItemButtonMixin` and `ListItemMixin` and has all the same use cases as the mixin.
422
-
423
- <!-- docs: start hidden content -->
424
- ![List](./screenshots/list-item.png?raw=true)
425
- <!-- docs: end hidden content -->
426
-
427
- <!-- docs: demo live name:d2l-list-item-button -->
428
- ```html
429
- <script type="module">
430
- import '@brightspace-ui/core/components/list/list.js';
431
- import '@brightspace-ui/core/components/list/list-item-button.js';
432
- import '@brightspace-ui/core/components/list/list-item-content.js';
433
- </script>
434
-
435
- <d2l-list style="width: 100%">
436
- <d2l-list-item-button href="http://www.d2l.com" selectable key="1" label="Geomorphology and GIS">
437
- <d2l-list-item-content>
438
- <div>Geomorphology and GIS </div>
439
- <div slot="supporting-info">This course explores the geological processes of the Earth's interior and surface. These include volcanism, earthquakes, mountain...</div>
440
- </d2l-list-item-content>
441
- </d2l-list-item-button>
442
- </d2l-list>
443
- ```
444
-
445
- <!-- docs: start hidden content -->
446
- ### Events
447
-
448
- - `d2l-list-item-button-click`: dispatched when the item's primary button action is clicked
449
- <!-- docs: end hidden content -->
474
+ - nested (TemplateResult): Optional `d2l-list` for a nested list.
450
475
 
451
476
  ## List Item Content
452
477
 
@@ -494,6 +519,13 @@ This event includes a detail object with helper methods attached to it.
494
519
  - `announceFn(any, Number) (optional)`: A callback function that takes a given item in the array and its index, and returns the text to announce
495
520
  - `keyFn(any)`: A callback function that takes a given item in the array and returns its key
496
521
 
522
+ ## Event Details: @d2l-list-items-move
523
+
524
+ **Properties**
525
+
526
+ - `keyboardActive`: (Boolean) Whether the drag handle is in keyboard mode
527
+ - `sourceItems`: (Array) Items being moved
528
+ - `target`: (Object) The target reference `item` where items are being moved, and the `location` (`moveLocations.above`, `moveLocations.below`, or `moveLocations.nest`)
497
529
 
498
530
  <!-- docs: start hidden content -->
499
531
  ## Future Improvements
@@ -21,23 +21,27 @@ class ListDemoDragAndDrop extends LitElement {
21
21
  primaryText: 'Introductory Earth Sciences',
22
22
  supportingText: 'This course explores the geological processes of the Earth\'s interior and surface. These include volcanism, earthquakes, mountain building, glaciation and weathering.',
23
23
  imgSrc: 'https://s.brightspace.com/course-images/images/63b162ab-b582-4bf9-8c1d-1dad04714121/tile-high-density-max-size.jpg',
24
+ dropNested: true,
24
25
  items: [{
25
26
  key: '1-1',
26
27
  primaryText: 'Glaciation',
27
- supportingText: 'Supporting Info',
28
- imgSrc: '',
28
+ supportingText: 'Nesting Allowed',
29
+ imgSrc: 'https://s.brightspace.com/course-images/images/bf648978-6637-4fdc-815b-81572c436c0e/tile-high-density-max-size.jpg',
30
+ dropNested: true,
29
31
  items: []
30
32
  }, {
31
33
  key: '1-2',
32
34
  primaryText: 'Weathering',
33
- supportingText: 'Supporting Info',
34
- imgSrc: '',
35
+ supportingText: 'Nesting Allowed',
36
+ imgSrc: 'https://s.brightspace.com/course-images/images/50f91ba6-7c25-482a-bd71-1c4b7c8d2154/tile-high-density-min-size.jpg',
37
+ dropNested: true,
35
38
  items: []
36
39
  }, {
37
40
  key: '1-3',
38
41
  primaryText: 'Volcanism',
39
- supportingText: 'Supporting Info',
40
- imgSrc: '',
42
+ supportingText: 'Nesting Allowed',
43
+ imgSrc: 'https://s.brightspace.com/course-images/images/5eb2371d-6099-4c8d-8aad-075f357012a2/tile-high-density-min-size.jpg',
44
+ dropNested: true,
41
45
  items: []
42
46
  }]
43
47
  }, {
@@ -48,14 +52,16 @@ class ListDemoDragAndDrop extends LitElement {
48
52
  items: [{
49
53
  key: '2-1',
50
54
  primaryText: 'Contaminant Transport',
51
- supportingText: 'Supporting Info',
52
- imgSrc: '',
55
+ supportingText: 'No Nesting Allowed',
56
+ imgSrc: 'https://s.brightspace.com/course-images/images/824fffa1-86a6-4489-84ba-91edfbc1dcc4/tile-high-density-min-size.jpg',
57
+ dropNested: false,
53
58
  items: []
54
59
  }, {
55
60
  key: '2-2',
56
61
  primaryText: 'Modelling Flow in Fractured Media',
57
- supportingText: 'Supporting Info',
58
- imgSrc: '',
62
+ supportingText: 'No Nesting Allowed',
63
+ imgSrc: 'https://s.brightspace.com/course-images/images/e18c92a4-b996-444f-84b5-988874feccac/tile-high-density-min-size.jpg',
64
+ dropNested: false,
59
65
  items: []
60
66
  }]
61
67
  }, {
@@ -66,14 +72,16 @@ class ListDemoDragAndDrop extends LitElement {
66
72
  items: [{
67
73
  key: '3-1',
68
74
  primaryText: 'Carbon & Nitrogen Cycling',
69
- supportingText: 'Supporting Info',
70
- imgSrc: '',
75
+ supportingText: 'Nesting Allowed',
76
+ imgSrc: 'https://s.brightspace.com/course-images/images/623b420b-a305-4762-8af8-598f0e72e956/tile-high-density-min-size.jpg',
77
+ dropNested: true,
71
78
  items: []
72
79
  }, {
73
80
  key: '3-2',
74
81
  primaryText: 'Wetland Engineering',
75
- supportingText: 'Supporting Info',
76
- imgSrc: '',
82
+ supportingText: 'Nesting Allowed',
83
+ imgSrc: 'https://s.brightspace.com/course-images/images/26102577-8f2a-4e24-84b5-19d76decbc7a/tile-high-density-min-size.jpg',
84
+ dropNested: true,
77
85
  items: []
78
86
  }]
79
87
  }];
@@ -88,11 +96,11 @@ class ListDemoDragAndDrop extends LitElement {
88
96
  action-href="http://www.d2l.com"
89
97
  draggable
90
98
  drag-handle-text="${item.primaryText}"
91
- drop-nested
99
+ ?drop-nested="${item.dropNested}"
92
100
  key="${item.key}"
93
101
  label="${item.primaryText}"
94
102
  selectable>
95
- ${nested ? null : html`<img slot="illustration" src="${item.imgSrc}">`}
103
+ ${item.imgSrc.length === 0 ? null : html`<img slot="illustration" src="${item.imgSrc}">`}
96
104
  <d2l-list-item-content>
97
105
  <div>${item.primaryText}</div>
98
106
  <div slot="supporting-info">${item.supportingText}</div>
@@ -159,6 +167,7 @@ class ListDemoDragAndDrop extends LitElement {
159
167
 
160
168
  if (e.detail.keyboardActive) {
161
169
  requestAnimationFrame(() => {
170
+ if (!this.shadowRoot) return;
162
171
  const newItem = this.shadowRoot.querySelector('d2l-list').getListItemByKey(sourceListItems[0].key);
163
172
  newItem.activateDragHandle();
164
173
  });
@@ -7,6 +7,7 @@ import { RtlMixin } from '../../mixins/rtl-mixin.js';
7
7
 
8
8
  /**
9
9
  * A header for list components containing select-all, etc.
10
+ * @slot - Responsive container using `d2l-overflow-group` for `d2l-selection-action` elements
10
11
  */
11
12
  class ListHeader extends RtlMixin(LocalizeCoreElement(LitElement)) {
12
13
 
@@ -6,6 +6,7 @@ import { LitElement } from 'lit-element/lit-element.js';
6
6
  * @slot - Default content placed inside of the component
7
7
  * @slot illustration - Image associated with the list item located at the left of the item
8
8
  * @slot actions - Actions (e.g., button icons) associated with the listen item located at the right of the item
9
+ * @slot nested - Nested d2l-list element
9
10
  */
10
11
  class ListItemButton extends ListItemButtonMixin(LitElement) {
11
12
 
@@ -25,7 +25,7 @@ export const ListItemCheckboxMixin = superclass => class extends SkeletonMixin(L
25
25
  */
26
26
  key: { type: String, reflect: true },
27
27
  /**
28
- * **Selection:** Indicates a input should be rendered for selecting the item
28
+ * **Selection:** Indicates an input should be rendered for selecting the item
29
29
  * @type {boolean}
30
30
  */
31
31
  selectable: { type: Boolean },
@@ -60,6 +60,8 @@ export const ListItemCheckboxMixin = superclass => class extends SkeletonMixin(L
60
60
 
61
61
  constructor() {
62
62
  super();
63
+ this.disabled = false;
64
+ this.selectable = false;
63
65
  this.selected = false;
64
66
  this.selectionInfo = new SelectionInfo();
65
67
  this._checkboxId = getUniqueId();
@@ -117,7 +119,7 @@ export const ListItemCheckboxMixin = superclass => class extends SkeletonMixin(L
117
119
  event.preventDefault();
118
120
  if (this.disabled) return;
119
121
  this.setSelected(!this.selected);
120
- const checkbox = this.shadowRoot.querySelector(`#${this._checkboxId}`);
122
+ const checkbox = this.shadowRoot && this.shadowRoot.querySelector(`#${this._checkboxId}`);
121
123
  if (checkbox) checkbox.focus();
122
124
  }
123
125
 
@@ -264,7 +264,7 @@ export const ListItemDragDropMixin = superclass => class extends superclass {
264
264
  */
265
265
  dragHandleText: { type: String, attribute: 'drag-handle-text' },
266
266
  /**
267
- * **Drag & drop:** Whether the items can be dropped as nested children
267
+ * **Drag & drop:** Whether nested items can be dropped on this item
268
268
  * @type {boolean}
269
269
  */
270
270
  dropNested: { type: Boolean, attribute: 'drop-nested' },
@@ -360,7 +360,7 @@ export const ListItemDragDropMixin = superclass => class extends superclass {
360
360
  }
361
361
 
362
362
  activateDragHandle() {
363
- this.shadowRoot.querySelector(`#${this._itemDragId}`).activateKeyboardMode();
363
+ if (this.shadowRoot) this.shadowRoot.querySelector(`#${this._itemDragId}`).activateKeyboardMode();
364
364
  }
365
365
 
366
366
  _annoucePositionChange(dragTargetKey, dropTargetKey, dropLocation) {
@@ -374,6 +374,7 @@ export const ListItemDragDropMixin = superclass => class extends superclass {
374
374
  _dispatchListItemsMove(sourceItems, targetItem, moveLocation, keyboardActive) {
375
375
  if (!keyboardActive) keyboardActive = false;
376
376
  const rootList = this._getRootList();
377
+ /** @ignore */
377
378
  rootList.dispatchEvent(new CustomEvent('d2l-list-items-move', {
378
379
  detail: {
379
380
  keyboardActive: keyboardActive,
@@ -549,8 +550,10 @@ export const ListItemDragDropMixin = superclass => class extends superclass {
549
550
  e.dataTransfer.setData('text/plain', `${this.dropText}`);
550
551
  }
551
552
 
552
- const nodeImage = this.shadowRoot.querySelector('.d2l-list-item-drag-image') || this;
553
- e.dataTransfer.setDragImage(nodeImage, 50, 50);
553
+ if (this.shadowRoot) {
554
+ const nodeImage = this.shadowRoot.querySelector('.d2l-list-item-drag-image') || this;
555
+ e.dataTransfer.setDragImage(nodeImage, 50, 50);
556
+ }
554
557
 
555
558
  const rootList = this._getRootList(this);
556
559
 
@@ -582,6 +585,7 @@ export const ListItemDragDropMixin = superclass => class extends superclass {
582
585
  }
583
586
 
584
587
  _onDragTargetClick(e) {
588
+ if (!this.shadowRoot) return;
585
589
  if (this._keyboardActiveOnNextClick) {
586
590
  this.shadowRoot.querySelector(`#${this._itemDragId}`).activateKeyboardMode();
587
591
  } else {
@@ -690,7 +694,8 @@ export const ListItemDragDropMixin = superclass => class extends superclass {
690
694
  const dropGrid = listItem.shadowRoot.querySelector('.d2l-list-item-drag-drop-grid');
691
695
  if (dropGrid) dropGrid.dispatchEvent(createDragEvent('drop'));
692
696
  // simulate dragend
693
- this.shadowRoot.querySelector('.d2l-list-item-drag-area').dispatchEvent(createDragEvent('dragend'));
697
+ if (this.shadowRoot)
698
+ this.shadowRoot.querySelector('.d2l-list-item-drag-area').dispatchEvent(createDragEvent('dragend'));
694
699
  }
695
700
 
696
701
  /**
@@ -742,7 +747,8 @@ export const ListItemDragDropMixin = superclass => class extends superclass {
742
747
  // simulate dragstart for touch and hold
743
748
  this._touchTimeoutId = setTimeout(() => {
744
749
  this._touchStarted = true;
745
- this.shadowRoot.querySelector('.d2l-list-item-drag-area').dispatchEvent(createDragEvent('dragstart'));
750
+ if (this.shadowRoot)
751
+ this.shadowRoot.querySelector('.d2l-list-item-drag-area').dispatchEvent(createDragEvent('dragstart'));
746
752
  }, touchHoldDuration);
747
753
  }
748
754
 
@@ -171,7 +171,7 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
171
171
  }
172
172
 
173
173
  _focusCellItem(num, itemNum) {
174
- const cell = this.shadowRoot.querySelector(`[data-cell-num="${num}"]`);
174
+ const cell = this.shadowRoot && this.shadowRoot.querySelector(`[data-cell-num="${num}"]`);
175
175
  if (!cell) return;
176
176
 
177
177
  const firstFocusable = getFirstFocusableDescendant(cell);
@@ -197,7 +197,7 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
197
197
  let focusable = null;
198
198
  let num = 1;
199
199
  do {
200
- cell = this.shadowRoot.querySelector(`[data-cell-num="${num++}"]`);
200
+ cell = this.shadowRoot && this.shadowRoot.querySelector(`[data-cell-num="${num++}"]`);
201
201
  if (cell) {
202
202
  focusable = getLastFocusableDescendant(cell) || focusable;
203
203
  }
@@ -220,7 +220,7 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
220
220
  let focusable = null;
221
221
 
222
222
  do {
223
- cell = this.shadowRoot.querySelector(`[data-cell-num="${num}"]`);
223
+ cell = this.shadowRoot && this.shadowRoot.querySelector(`[data-cell-num="${num}"]`);
224
224
  if (cell) {
225
225
  focusable = forward ? getFirstFocusableDescendant(cell) : getLastFocusableDescendant(cell);
226
226
  }
@@ -381,7 +381,8 @@ class ListItemGenericLayout extends RtlMixin(LitElement) {
381
381
  }
382
382
 
383
383
  _getThisCell() {
384
- return this.shadowRoot.querySelector(`.d2l-cell[data-cell-num="${this._cellNum}"]`);
384
+ return this.shadowRoot &&
385
+ this.shadowRoot.querySelector(`.d2l-cell[data-cell-num="${this._cellNum}"]`);
385
386
  }
386
387
 
387
388
  _onKeydown(event) {
@@ -303,6 +303,7 @@ export const ListItemMixin = superclass => class extends ListItemDragDropMixin(L
303
303
  }
304
304
 
305
305
  _getNestedList() {
306
+ if (!this.shadowRoot) return;
306
307
  const nestedSlot = this.shadowRoot.querySelector('slot[name="nested"]');
307
308
  let nestedNodes = nestedSlot.assignedNodes();
308
309
  if (nestedNodes.length === 0) {
@@ -6,6 +6,7 @@ import { LitElement } from 'lit-element/lit-element.js';
6
6
  * @slot - Default content placed inside of the component
7
7
  * @slot illustration - Image associated with the list item located at the left of the item
8
8
  * @slot actions - Actions (e.g., button icons) associated with the listen item located at the right of the item
9
+ * @slot nested - Nested d2l-list element
9
10
  */
10
11
  class ListItem extends ListItemLinkMixin(LitElement) {
11
12
 
@@ -10,17 +10,20 @@ export const listSelectionStates = SelectionInfo.states;
10
10
 
11
11
  /**
12
12
  * A container for a styled list of items ("d2l-list-item"). It provides the appropriate "list" semantics as well as options for displaying separators, etc.
13
- * @slot - List content (e.g., `listitem`s)
13
+ * @slot - Slot for list items (ex. `d2l-list-item`, `d2l-list-item-button`, or custom items)
14
+ * @slot header - Slot for `d2l-list-header` to be rendered above the list
15
+ * @fires d2l-list-items-move - Dispatched when one or more items are moved. See [Event Details: d2l-list-items-move](#event-details%3A-%40d2l-list-items-move).
14
16
  */
15
17
  class List extends SelectionMixin(LitElement) {
16
18
 
17
19
  static get properties() {
18
20
  return {
19
21
  /**
20
- * Whether to the user can drag multiple items
22
+ * Not publicly available yet. Whether the user can drag multiple items
21
23
  * @type {boolean}
22
- */
23
- dragMultiple: { type: Boolean, attribute: 'drag-multiple' },
24
+ * @ignore
25
+ */
26
+ dragMultiple: { type: Boolean, reflect: true, attribute: 'drag-multiple' },
24
27
  /**
25
28
  * Whether to extend the separators beyond the content's edge
26
29
  * @type {boolean}
@@ -98,6 +101,7 @@ class List extends SelectionMixin(LitElement) {
98
101
  }
99
102
 
100
103
  getItems() {
104
+ if (!this.shadowRoot) return;
101
105
  const slot = this.shadowRoot.querySelector('slot:not([name])');
102
106
  if (!slot) return [];
103
107
  return slot.assignedNodes({ flatten: true }).filter((node) => {
@@ -154,6 +158,7 @@ class List extends SelectionMixin(LitElement) {
154
158
  _handleKeyDown(e) {
155
159
  if (!this.grid || this.slot === 'nested' || e.keyCode !== keyCodes.TAB) return;
156
160
  e.preventDefault();
161
+ if (!this.shadowRoot) return;
157
162
  const focusable = (e.shiftKey ? getPreviousFocusable(this.shadowRoot.querySelector('slot:not([name])'))
158
163
  : getNextFocusable(this, false, true, true));
159
164
  if (focusable) focusable.focus();
@@ -48,7 +48,7 @@ class CustomView extends HierarchicalViewMixin(LitElement) {
48
48
  }
49
49
 
50
50
  focus() {
51
- this.shadowRoot.querySelector('.d2l-custom-view-back-container > a').focus();
51
+ if (this.shadowRoot) this.shadowRoot.querySelector('.d2l-custom-view-back-container > a').focus();
52
52
  }
53
53
 
54
54
  _handleHide(e) {
@@ -84,7 +84,7 @@ class MenuItemLink extends MenuItemMixin(LitElement) {
84
84
  }
85
85
 
86
86
  _onClick() {
87
- this.shadowRoot.querySelector('a').dispatchEvent(new CustomEvent('click'));
87
+ if (this.shadowRoot) this.shadowRoot.querySelector('a').dispatchEvent(new CustomEvent('click'));
88
88
  }
89
89
 
90
90
  _onKeyDown(e) {
@@ -109,7 +109,7 @@ export const MenuItemMixin = superclass => class extends FocusVisiblePolyfillMix
109
109
  }
110
110
 
111
111
  __initializeItem() {
112
- const slot = this.shadowRoot.querySelector('slot:not([name])');
112
+ const slot = this.shadowRoot && this.shadowRoot.querySelector('slot:not([name])');
113
113
  if (!slot) {
114
114
  return;
115
115
  }
@@ -221,11 +221,11 @@ class Menu extends ThemeMixin(HierarchicalViewMixin(FocusVisiblePolyfillMixin(Li
221
221
  }
222
222
 
223
223
  _getMenuItemReturn() {
224
- return this.shadowRoot.querySelector('d2l-menu-item-return');
224
+ return this.shadowRoot && this.shadowRoot.querySelector('d2l-menu-item-return');
225
225
  }
226
226
 
227
227
  _getMenuItems() {
228
- const slot = this.shadowRoot.querySelector('slot');
228
+ const slot = this.shadowRoot && this.shadowRoot.querySelector('slot');
229
229
  if (!slot) return;
230
230
  const items = slot.assignedNodes({ flatten: true }).filter((node) => node.nodeType === Node.ELEMENT_NODE);
231
231
 
@@ -318,7 +318,7 @@ class OverflowGroup extends RtlMixin(LocalizeCoreElement(LitElement)) {
318
318
  }
319
319
 
320
320
  _chomp() {
321
- if (!this._itemLayouts) return;
321
+ if (!this.shadowRoot || !this._itemLayouts) return;
322
322
 
323
323
  this._overflowMenu = this.shadowRoot.querySelector('.d2l-overflow-dropdown');
324
324
  this._overflowMenuMini = this.shadowRoot.querySelector('.d2l-overflow-dropdown-mini');
@@ -53,7 +53,7 @@ class TestScrollWrapper extends RtlMixin(LitElement) {
53
53
  }
54
54
 
55
55
  focus() {
56
- forceFocusVisible(this.shadowRoot.querySelector('d2l-scroll-wrapper')._container);
56
+ if (this.shadowRoot) forceFocusVisible(this.shadowRoot.querySelector('d2l-scroll-wrapper')._container);
57
57
  }
58
58
 
59
59
  }
@@ -79,7 +79,7 @@ class Action extends LocalizeCoreElement(SelectionObserverMixin(ButtonMixin(RtlM
79
79
  }
80
80
 
81
81
  focus() {
82
- const elem = this.shadowRoot.querySelector('d2l-button-subtle');
82
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('d2l-button-subtle');
83
83
  if (elem) elem.focus();
84
84
  }
85
85
 
@@ -142,7 +142,7 @@ class Input extends SkeletonMixin(LabelledMixin(LitElement)) {
142
142
  }
143
143
 
144
144
  focus() {
145
- const elem = this.shadowRoot.firstElementChild;
145
+ const elem = this.shadowRoot && this.shadowRoot.firstElementChild;
146
146
  if (elem) elem.focus();
147
147
  }
148
148
 
@@ -57,7 +57,7 @@ class SelectAll extends LocalizeCoreElement(SelectionObserverMixin(LitElement))
57
57
  }
58
58
 
59
59
  focus() {
60
- const elem = this.shadowRoot.querySelector('d2l-input-checkbox');
60
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('d2l-input-checkbox');
61
61
  if (elem) elem.focus();
62
62
  }
63
63
 
@@ -213,7 +213,7 @@ export const SwitchMixin = superclass => class extends RtlMixin(FocusVisiblePoly
213
213
  }
214
214
 
215
215
  focus() {
216
- const elem = this.shadowRoot.querySelector('.d2l-switch-container');
216
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('.d2l-switch-container');
217
217
  if (elem) elem.focus();
218
218
  }
219
219
 
@@ -71,7 +71,7 @@ export class TableColSortButton extends LitElement {
71
71
  }
72
72
 
73
73
  focus() {
74
- const button = this.shadowRoot.querySelector('button');
74
+ const button = this.shadowRoot && this.shadowRoot.querySelector('button');
75
75
  if (button) button.focus();
76
76
  }
77
77