@brightspace-ui/core 1.215.0 → 1.219.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 (96) 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/count-badge/count-badge-mixin.js +1 -1
  6. package/components/demo/code-view.js +4 -3
  7. package/components/demo/demo-snippet.js +5 -2
  8. package/components/dialog/dialog-confirm.js +1 -0
  9. package/components/dialog/dialog-mixin.js +7 -2
  10. package/components/dropdown/dropdown-button-subtle.js +1 -1
  11. package/components/dropdown/dropdown-button.js +1 -1
  12. package/components/dropdown/dropdown-content-mixin.js +6 -6
  13. package/components/dropdown/dropdown-context-menu.js +1 -1
  14. package/components/dropdown/dropdown-menu.js +1 -0
  15. package/components/dropdown/dropdown-more.js +1 -1
  16. package/components/dropdown/dropdown-opener-mixin.js +1 -0
  17. package/components/dropdown/dropdown-tabs.js +1 -0
  18. package/components/dropdown/dropdown.js +1 -0
  19. package/components/expand-collapse/expand-collapse-content.js +4 -4
  20. package/components/filter/README.md +1 -0
  21. package/components/filter/filter-dimension-set.js +7 -1
  22. package/components/filter/filter.js +63 -4
  23. package/components/focus-trap/focus-trap.js +6 -5
  24. package/components/form/demo/form-demo.js +1 -1
  25. package/components/form/demo/form-dialog-demo.js +4 -4
  26. package/components/form/demo/form-native-demo.js +1 -1
  27. package/components/form/form-element-mixin.js +12 -3
  28. package/components/form/form-errory-summary.js +2 -2
  29. package/components/form/form-native.js +1 -1
  30. package/components/form/form.js +1 -1
  31. package/components/hierarchical-view/hierarchical-view-mixin.js +7 -6
  32. package/components/html-block/html-block.js +1 -0
  33. package/components/inputs/demo/input-radio-solo-test.js +1 -1
  34. package/components/inputs/demo/input-radio-spacer-test.js +1 -1
  35. package/components/inputs/demo/input-select-test.js +1 -1
  36. package/components/inputs/input-checkbox.js +1 -1
  37. package/components/inputs/input-date-range.js +4 -3
  38. package/components/inputs/input-date-time-range-to.js +1 -1
  39. package/components/inputs/input-date-time-range.js +4 -3
  40. package/components/inputs/input-date-time.js +6 -5
  41. package/components/inputs/input-date.js +3 -0
  42. package/components/inputs/input-number.js +2 -1
  43. package/components/inputs/input-percent.js +2 -1
  44. package/components/inputs/input-search.js +3 -3
  45. package/components/inputs/input-text.js +8 -8
  46. package/components/inputs/input-textarea.js +5 -5
  47. package/components/inputs/input-time-range.js +4 -4
  48. package/components/inputs/input-time.js +1 -1
  49. package/components/link/link.js +1 -1
  50. package/components/list/demo/list-drag-and-drop.js +3 -1
  51. package/components/list/list-item-button-mixin.js +7 -1
  52. package/components/list/list-item-checkbox-mixin.js +1 -1
  53. package/components/list/list-item-drag-drop-mixin.js +10 -5
  54. package/components/list/list-item-drag-handle.js +43 -5
  55. package/components/list/list-item-generic-layout.js +5 -4
  56. package/components/list/list-item-link-mixin.js +3 -1
  57. package/components/list/list-item-mixin.js +55 -3
  58. package/components/list/list-item-role-mixin.js +2 -1
  59. package/components/list/list.js +2 -0
  60. package/components/menu/demo/custom-view.js +1 -1
  61. package/components/menu/menu-item-link.js +1 -1
  62. package/components/menu/menu-item-mixin.js +1 -1
  63. package/components/menu/menu.js +2 -2
  64. package/components/overflow-group/overflow-group.js +1 -1
  65. package/components/scroll-wrapper/demo/scroll-wrapper-test.js +1 -1
  66. package/components/selection/selection-action.js +1 -1
  67. package/components/selection/selection-input.js +1 -1
  68. package/components/selection/selection-select-all.js +1 -1
  69. package/components/switch/switch-mixin.js +1 -1
  70. package/components/table/table-col-sort-button.js +1 -1
  71. package/components/tabs/tabs.js +20 -15
  72. package/components/tooltip/tooltip.js +1 -1
  73. package/controllers/subscriber/README.md +3 -3
  74. package/controllers/subscriber/subscriberControllers.js +4 -4
  75. package/custom-elements.json +13 -0
  76. package/helpers/demo/announce-test.js +1 -0
  77. package/lang/ar.js +20 -5
  78. package/lang/cy.js +20 -5
  79. package/lang/da.js +20 -5
  80. package/lang/de.js +20 -5
  81. package/lang/en.js +16 -0
  82. package/lang/es-es.js +20 -5
  83. package/lang/es.js +20 -5
  84. package/lang/fr-fr.js +20 -5
  85. package/lang/fr.js +20 -5
  86. package/lang/ja.js +20 -5
  87. package/lang/ko.js +20 -5
  88. package/lang/nl.js +20 -5
  89. package/lang/pt.js +20 -5
  90. package/lang/sv.js +20 -5
  91. package/lang/tr.js +20 -5
  92. package/lang/zh-tw.js +20 -5
  93. package/lang/zh.js +20 -5
  94. package/mixins/arrow-keys-mixin.js +3 -1
  95. package/package.json +1 -1
  96. package/templates/primary-secondary/primary-secondary.js +2 -1
@@ -104,8 +104,8 @@ class FormErrorSummary extends LocalizeCoreElement(RtlMixin(LitElement)) {
104
104
  } else {
105
105
  focusEleSelector = 'd2l-button-icon';
106
106
  }
107
- const focusEle = this.shadowRoot.querySelector(focusEleSelector);
108
- focusEle.focus();
107
+ const focusEle = this.shadowRoot && this.shadowRoot.querySelector(focusEleSelector);
108
+ if (focusEle) focusEle.focus();
109
109
  }
110
110
 
111
111
  _toggleExpandCollapse(e) {
@@ -133,7 +133,7 @@ class FormNative extends FormMixin(LitElement) {
133
133
  }
134
134
  }
135
135
  this._errors = errorMap;
136
- if (errorMap.size > 0) {
136
+ if (this.shadowRoot && errorMap.size > 0) {
137
137
  const errorSummary = this.shadowRoot.querySelector('d2l-form-error-summary');
138
138
  this.updateComplete.then(() => errorSummary.focus());
139
139
  }
@@ -100,7 +100,7 @@ class Form extends FormMixin(LitElement) {
100
100
  const flattenedErrorMap = flattenMap(errorMap);
101
101
  this._errors = errorMap;
102
102
  if (errorMap.size > 0) {
103
- const errorSummary = this.shadowRoot.querySelector('d2l-form-error-summary');
103
+ const errorSummary = this.shadowRoot && this.shadowRoot.querySelector('d2l-form-error-summary');
104
104
  if (errorSummary) {
105
105
  this.updateComplete.then(() => errorSummary.focus());
106
106
  }
@@ -222,7 +222,7 @@ export const HierarchicalViewMixin = superclass => class extends superclass {
222
222
  }
223
223
 
224
224
  isActive() {
225
- if (this.childView && !this.shown) {
225
+ if ((this.childView && !this.shown) || !this.shadowRoot) {
226
226
  return false;
227
227
  } else {
228
228
  const content = this.shadowRoot.querySelector('.d2l-hierarchical-view-content');
@@ -290,7 +290,7 @@ export const HierarchicalViewMixin = superclass => class extends superclass {
290
290
 
291
291
  this.__isAutoSized = true;
292
292
  let rect;
293
- if (view === this) {
293
+ if (view === this && this.shadowRoot) {
294
294
  rect = this.shadowRoot.querySelector('.d2l-hierarchical-view-content').getBoundingClientRect();
295
295
  } else {
296
296
  rect = view.getBoundingClientRect();
@@ -325,6 +325,7 @@ export const HierarchicalViewMixin = superclass => class extends superclass {
325
325
  view.resize();
326
326
  return;
327
327
  }
328
+ if (!this.shadowRoot) return;
328
329
  const content = this.shadowRoot.querySelector('.d2l-hierarchical-view-content');
329
330
  const contentRect = content.getBoundingClientRect();
330
331
  if (contentRect.height < 1) return;
@@ -432,7 +433,7 @@ export const HierarchicalViewMixin = superclass => class extends superclass {
432
433
  if (rootTarget === this || !rootTarget.hierarchicalView) return;
433
434
 
434
435
  const parentView = this.__getParentViewFromEvent(e);
435
- if (parentView === this) {
436
+ if (this.shadowRoot && parentView === this) {
436
437
  const content = this.shadowRoot.querySelector('.d2l-hierarchical-view-content');
437
438
 
438
439
  const data = e.detail.data;
@@ -495,16 +496,16 @@ export const HierarchicalViewMixin = superclass => class extends superclass {
495
496
  /* deep link scenario */
496
497
  this.show(e.detail.data, e.detail.sourceView);
497
498
  }
498
- const content = this.shadowRoot.querySelector('.d2l-hierarchical-view-content');
499
+ const content = this.shadowRoot && this.shadowRoot.querySelector('.d2l-hierarchical-view-content');
499
500
 
500
- if (reduceMotion) {
501
+ if (this.shadowRoot && reduceMotion) {
501
502
 
502
503
  content.classList.add('d2l-child-view-show');
503
504
  requestAnimationFrame(() => {
504
505
  e.detail.sourceView.__dispatchShowComplete(e.detail.data, e.detail);
505
506
  });
506
507
 
507
- } else {
508
+ } else if (this.shadowRoot) {
508
509
 
509
510
  if (e.detail.isSource && this.__getParentViewFromEvent(e) === this) {
510
511
  const animationEnd = () => {
@@ -217,6 +217,7 @@ class HtmlBlock extends LitElement {
217
217
  }
218
218
 
219
219
  _findSlottedElement(tagName, slot) {
220
+ if (!this.shadowRoot) return;
220
221
  if (!slot) slot = this.shadowRoot.querySelector('slot');
221
222
  return slot.assignedNodes({ flatten: true })
222
223
  .find(node => (node.nodeType === Node.ELEMENT_NODE && node.tagName === tagName.toUpperCase()));
@@ -38,7 +38,7 @@ class TestInputRadioSolo extends LitElement {
38
38
  }
39
39
 
40
40
  focus() {
41
- const elem = this.shadowRoot.querySelector('input');
41
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('input');
42
42
  if (elem) elem.focus();
43
43
  }
44
44
 
@@ -19,7 +19,7 @@ class TestInputRadioSpacer extends LitElement {
19
19
  }
20
20
 
21
21
  focus() {
22
- const elem = this.shadowRoot.querySelector('input');
22
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('input');
23
23
  if (elem) elem.focus();
24
24
  }
25
25
 
@@ -53,7 +53,7 @@ class TestInputSelect extends SkeletonMixin(RtlMixin(LitElement)) {
53
53
  }
54
54
 
55
55
  focus() {
56
- const elem = this.shadowRoot.querySelector('select');
56
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('select');
57
57
  if (elem) elem.focus();
58
58
  }
59
59
 
@@ -205,7 +205,7 @@ class InputCheckbox extends SkeletonMixin(RtlMixin(LitElement)) {
205
205
  }
206
206
 
207
207
  focus() {
208
- const elem = this.shadowRoot.querySelector('input.d2l-input-checkbox');
208
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('input.d2l-input-checkbox');
209
209
  if (elem) elem.focus();
210
210
  }
211
211
 
@@ -163,8 +163,8 @@ class InputDateRange extends SkeletonMixin(FormElementMixin(RtlMixin(LocalizeCor
163
163
  }
164
164
 
165
165
  render() {
166
- const startDateInput = this.shadowRoot.querySelector('.d2l-input-date-range-start');
167
- const endDateInput = this.shadowRoot.querySelector('.d2l-input-date-range-end');
166
+ const startDateInput = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input-date-range-start');
167
+ const endDateInput = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input-date-range-end');
168
168
  const tooltipStart = (this.validationError && !this.startOpened && !this.childErrors.has(startDateInput)) ? html`<d2l-tooltip align="start" announced for="${this._startInputId}" state="error">${this.validationError}</d2l-tooltip>` : null;
169
169
  const tooltipEnd = (this.validationError && !this.endOpened && !this.childErrors.has(endDateInput)) ? html`<d2l-tooltip align="start" announced for="${this._endInputId}" state="error">${this.validationError}</d2l-tooltip>` : null;
170
170
  return html`
@@ -252,11 +252,12 @@ class InputDateRange extends SkeletonMixin(FormElementMixin(RtlMixin(LocalizeCor
252
252
  }
253
253
 
254
254
  focus() {
255
- const input = this.shadowRoot.querySelector('d2l-input-date');
255
+ const input = this.shadowRoot && this.shadowRoot.querySelector('d2l-input-date');
256
256
  if (input) input.focus();
257
257
  }
258
258
 
259
259
  async validate() {
260
+ if (!this.shadowRoot) return;
260
261
  const startDateInput = this.shadowRoot.querySelector('.d2l-input-date-range-start');
261
262
  const endDateInput = this.shadowRoot.querySelector('.d2l-input-date-range-end');
262
263
  const errors = await Promise.all([startDateInput.validate(), endDateInput.validate(), super.validate()]);
@@ -179,7 +179,7 @@ class InputDateTimeRangeTo extends SkeletonMixin(LocalizeCoreElement(LitElement)
179
179
  }
180
180
 
181
181
  _startObserving() {
182
- if (!this._parentNode) return;
182
+ if (!this.shadowRoot || !this._parentNode) return;
183
183
 
184
184
  const leftElem = this.shadowRoot.querySelector('.d2l-input-date-time-range-start-container');
185
185
  this._leftElemResizeObserver = this._leftElemResizeObserver || new ResizeObserver(() => {
@@ -209,8 +209,8 @@ class InputDateTimeRange extends SkeletonMixin(FormElementMixin(RtlMixin(Localiz
209
209
  }
210
210
 
211
211
  render() {
212
- const startDateTimeInput = this.shadowRoot.querySelector('.d2l-input-date-time-range-start');
213
- const endDateTimeInput = this.shadowRoot.querySelector('.d2l-input-date-time-range-end');
212
+ const startDateTimeInput = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input-date-time-range-start');
213
+ const endDateTimeInput = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input-date-time-range-end');
214
214
 
215
215
  const tooltipStart = (this.validationError && !this.startOpened && !this.childErrors.has(startDateTimeInput)) ? html`<d2l-tooltip align="start" announced for="${this._startInputId}" position="bottom" state="error">${this.validationError}</d2l-tooltip>` : null;
216
216
  const tooltipEnd = (this.validationError && !this.endOpened && !this.childErrors.has(endDateTimeInput)) ? html`<d2l-tooltip align="start" announced for="${this._endInputId}" position="bottom" state="error">${this.validationError}</d2l-tooltip>` : null;
@@ -308,11 +308,12 @@ class InputDateTimeRange extends SkeletonMixin(FormElementMixin(RtlMixin(Localiz
308
308
  }
309
309
 
310
310
  focus() {
311
- const input = this.shadowRoot.querySelector('d2l-input-date-time');
311
+ const input = this.shadowRoot && this.shadowRoot.querySelector('d2l-input-date-time');
312
312
  if (input) input.focus();
313
313
  }
314
314
 
315
315
  async validate() {
316
+ if (!this.shadowRoot) return;
316
317
  const startDateTimeInput = this.shadowRoot.querySelector('.d2l-input-date-time-range-start');
317
318
  const endDateTimeInput = this.shadowRoot.querySelector('.d2l-input-date-time-range-end');
318
319
  const errors = await Promise.all([startDateTimeInput.validate(), endDateTimeInput.validate(), super.validate()]);
@@ -296,11 +296,12 @@ class InputDateTime extends LabelledMixin(SkeletonMixin(FormElementMixin(Localiz
296
296
  }
297
297
 
298
298
  focus() {
299
- const elem = this.shadowRoot.querySelector('d2l-input-date');
299
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('d2l-input-date');
300
300
  if (elem) elem.focus();
301
301
  }
302
302
 
303
303
  async validate() {
304
+ if (!this.shadowRoot) return;
304
305
  const dateInput = this.shadowRoot.querySelector('d2l-input-date');
305
306
  const timeInput = this.shadowRoot.querySelector('d2l-input-time');
306
307
  const errors = await Promise.all([dateInput.validate(), timeInput.validate(), super.validate()]);
@@ -319,7 +320,7 @@ class InputDateTime extends LabelledMixin(SkeletonMixin(FormElementMixin(Localiz
319
320
  if (!newDate) {
320
321
  this.value = '';
321
322
  } else {
322
- const inputTime = this.shadowRoot.querySelector('d2l-input-time');
323
+ const inputTime = this.shadowRoot && this.shadowRoot.querySelector('d2l-input-time');
323
324
  let time;
324
325
  if (e.detail && e.detail.setToNow) time = _getFormattedDefaultTime('now');
325
326
  else time = inputTime ? inputTime.value : _getFormattedDefaultTime(this.timeDefaultValue);
@@ -346,12 +347,12 @@ class InputDateTime extends LabelledMixin(SkeletonMixin(FormElementMixin(Localiz
346
347
  }
347
348
 
348
349
  _handleInputTimeBlur() {
349
- const tooltip = this.shadowRoot.querySelector('d2l-tooltip');
350
+ const tooltip = this.shadowRoot && this.shadowRoot.querySelector('d2l-tooltip');
350
351
  if (tooltip) tooltip.hide();
351
352
  }
352
353
 
353
354
  _handleInputTimeFocus() {
354
- const tooltip = this.shadowRoot.querySelector('d2l-tooltip');
355
+ const tooltip = this.shadowRoot && this.shadowRoot.querySelector('d2l-tooltip');
355
356
  if (tooltip) tooltip.show();
356
357
  }
357
358
 
@@ -360,7 +361,7 @@ class InputDateTime extends LabelledMixin(SkeletonMixin(FormElementMixin(Localiz
360
361
  }
361
362
 
362
363
  async _handleTimeChange(e) {
363
- const date = this.shadowRoot.querySelector('d2l-input-date').value;
364
+ const date = this.shadowRoot && this.shadowRoot.querySelector('d2l-input-date').value;
364
365
  const time = e.target.value;
365
366
  this.value = this.localized ? _formatLocalDateTimeInISO(date, time) : getUTCDateTimeFromLocalDateTime(date, time);
366
367
  this._dispatchChangeEvent();
@@ -336,6 +336,7 @@ class InputDate extends LabelledMixin(SkeletonMixin(FormElementMixin(LocalizeCor
336
336
  }
337
337
 
338
338
  async validate() {
339
+ if (!this.shadowRoot) return;
339
340
  const textInput = this.shadowRoot.querySelector('d2l-input-text');
340
341
  const errors = await Promise.all([textInput.validate(), super.validate()]);
341
342
  return [...errors[0], ...errors[1]];
@@ -407,6 +408,7 @@ class InputDate extends LabelledMixin(SkeletonMixin(FormElementMixin(LocalizeCor
407
408
  }
408
409
 
409
410
  _handleDropdownOpen() {
411
+ if (!this.shadowRoot) return;
410
412
  const calendarOffset = this.shadowRoot.querySelector('d2l-calendar').getBoundingClientRect();
411
413
  const fullCalendarVisible = calendarOffset.y + calendarOffset.height < window.innerHeight;
412
414
  if (this._dropdown && !this._dropdown.openedAbove && !fullCalendarVisible) {
@@ -432,6 +434,7 @@ class InputDate extends LabelledMixin(SkeletonMixin(FormElementMixin(LocalizeCor
432
434
  async _handleFirstDropdownOpen() {
433
435
  this._dropdownFirstOpened = true;
434
436
  await this.updateComplete;
437
+ if (!this.shadowRoot) return;
435
438
  this._calendar = this.shadowRoot.querySelector('d2l-calendar');
436
439
  this._dropdown = this.shadowRoot.querySelector('d2l-dropdown-content');
437
440
  await this._calendar.updateComplete;
@@ -366,7 +366,7 @@ class InputNumber extends LabelledMixin(SkeletonMixin(FormElementMixin(LocalizeC
366
366
  }
367
367
 
368
368
  async focus() {
369
- const elem = this.shadowRoot.querySelector('d2l-input-text');
369
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('d2l-input-text');
370
370
  if (elem) {
371
371
  elem.focus();
372
372
  } else {
@@ -376,6 +376,7 @@ class InputNumber extends LabelledMixin(SkeletonMixin(FormElementMixin(LocalizeC
376
376
  }
377
377
 
378
378
  async validate() {
379
+ if (!this.shadowRoot) return;
379
380
  const inputTextElem = this.shadowRoot.querySelector('d2l-input-text');
380
381
  await inputTextElem.updateComplete;
381
382
  const childErrors = await inputTextElem.validate();
@@ -132,11 +132,12 @@ class InputPercent extends LabelledMixin(SkeletonMixin(FormElementMixin(Localize
132
132
  }
133
133
 
134
134
  focus() {
135
- const elem = this.shadowRoot.querySelector('d2l-input-number');
135
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('d2l-input-number');
136
136
  if (elem) elem.focus();
137
137
  }
138
138
 
139
139
  async validate() {
140
+ if (!this.shadowRoot) return;
140
141
  const inputNumberElem = this.shadowRoot.querySelector('d2l-input-number');
141
142
  await inputNumberElem.updateComplete;
142
143
  const childErrors = await inputNumberElem.validate();
@@ -123,7 +123,7 @@ class InputSearch extends LocalizeCoreElement(RtlMixin(LitElement)) {
123
123
  }
124
124
 
125
125
  focus() {
126
- const elem = this.shadowRoot.querySelector('d2l-input-text');
126
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('d2l-input-text');
127
127
  if (elem) elem.focus();
128
128
  }
129
129
 
@@ -132,7 +132,7 @@ class InputSearch extends LocalizeCoreElement(RtlMixin(LitElement)) {
132
132
  this._dispatchEvent();
133
133
  if (!this.noClear && this.value.length > 0) {
134
134
  this.updateComplete.then(() => {
135
- this.shadowRoot.querySelector('d2l-button-icon').focus();
135
+ if (this.shadowRoot) this.shadowRoot.querySelector('d2l-button-icon').focus();
136
136
  });
137
137
  }
138
138
  }
@@ -158,7 +158,7 @@ class InputSearch extends LocalizeCoreElement(RtlMixin(LitElement)) {
158
158
  this._setLastSearchValue('');
159
159
  this._dispatchEvent();
160
160
  }
161
- this.shadowRoot.querySelector('d2l-input-text').focus();
161
+ if (this.shadowRoot) this.shadowRoot.querySelector('d2l-input-text').focus();
162
162
  }
163
163
 
164
164
  _handleInput(e) {
@@ -271,13 +271,13 @@ class InputText extends LabelledMixin(FormElementMixin(SkeletonMixin(RtlMixin(Li
271
271
 
272
272
  /** @ignore */
273
273
  get selectionEnd() {
274
- const elem = this.shadowRoot.querySelector('.d2l-input');
274
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input');
275
275
  return elem ? elem.selectionEnd : 0;
276
276
  }
277
277
 
278
278
  /** @ignore */
279
279
  get selectionStart() {
280
- const elem = this.shadowRoot.querySelector('.d2l-input');
280
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input');
281
281
  return elem ? elem.selectionStart : 0;
282
282
  }
283
283
 
@@ -301,7 +301,7 @@ class InputText extends LabelledMixin(FormElementMixin(SkeletonMixin(RtlMixin(Li
301
301
 
302
302
  /** @ignore */
303
303
  get validity() {
304
- const elem = this.shadowRoot.querySelector('.d2l-input');
304
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input');
305
305
  if (!elem.validity.valid) {
306
306
  return elem.validity;
307
307
  }
@@ -318,7 +318,7 @@ class InputText extends LabelledMixin(FormElementMixin(SkeletonMixin(RtlMixin(Li
318
318
  disconnectedCallback() {
319
319
  super.disconnectedCallback();
320
320
  if (this._intersectionObserver) this._intersectionObserver.disconnect();
321
- const container = this.shadowRoot.querySelector('.d2l-input-text-container');
321
+ const container = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input-text-container');
322
322
  if (!container) return;
323
323
  container.removeEventListener('blur', this._handleBlur, true);
324
324
  container.removeEventListener('focus', this._handleFocus, true);
@@ -331,7 +331,7 @@ class InputText extends LabelledMixin(FormElementMixin(SkeletonMixin(RtlMixin(Li
331
331
 
332
332
  this._setValue(this.value, true);
333
333
 
334
- const container = this.shadowRoot.querySelector('.d2l-input-text-container');
334
+ const container = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input-text-container');
335
335
  if (!container) return;
336
336
  container.addEventListener('blur', this._handleBlur, true);
337
337
  container.addEventListener('focus', this._handleFocus, true);
@@ -464,7 +464,7 @@ class InputText extends LabelledMixin(FormElementMixin(SkeletonMixin(RtlMixin(Li
464
464
  }
465
465
 
466
466
  async focus() {
467
- const elem = this.shadowRoot.querySelector('.d2l-input');
467
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input');
468
468
  if (elem) {
469
469
  elem.focus();
470
470
  } else {
@@ -572,7 +572,7 @@ class InputText extends LabelledMixin(FormElementMixin(SkeletonMixin(RtlMixin(Li
572
572
  this._prevValue = (oldVal === undefined) ? '' : oldVal;
573
573
  this._value = val;
574
574
 
575
- const input = this.shadowRoot.querySelector('.d2l-input');
575
+ const input = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input');
576
576
  if (!input) return;
577
577
 
578
578
  this.setValidity({ tooShort: this.minlength && this.value.length > 0 && this.value.length < this.minlength });
@@ -595,7 +595,7 @@ class InputText extends LabelledMixin(FormElementMixin(SkeletonMixin(RtlMixin(Li
595
595
  _updateInputLayout() {
596
596
 
597
597
  // defer until we're visible
598
- if (!this._isIntersecting) return;
598
+ if (!this.shadowRoot || !this._isIntersecting) return;
599
599
 
600
600
  const firstContainer = this.shadowRoot.querySelector('.d2l-input-inside-before');
601
601
  const firstSlotHasNodes = firstContainer.querySelector('slot').assignedNodes({ flatten: true }).length > 0
@@ -165,7 +165,7 @@ class InputTextArea extends LabelledMixin(FormElementMixin(SkeletonMixin(RtlMixi
165
165
  /** @ignore */
166
166
  get textarea() {
167
167
  // temporary until consumers are updated
168
- return this.shadowRoot.querySelector('textarea');
168
+ return this.shadowRoot && this.shadowRoot.querySelector('textarea');
169
169
  }
170
170
 
171
171
  /** @ignore */
@@ -178,8 +178,8 @@ class InputTextArea extends LabelledMixin(FormElementMixin(SkeletonMixin(RtlMixi
178
178
 
179
179
  /** @ignore */
180
180
  get validity() {
181
- const elem = this.shadowRoot.querySelector('textarea');
182
- if (!elem.validity.valid) {
181
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('textarea');
182
+ if (elem && !elem.validity.valid) {
183
183
  return elem.validity;
184
184
  }
185
185
  return super.validity;
@@ -264,7 +264,7 @@ class InputTextArea extends LabelledMixin(FormElementMixin(SkeletonMixin(RtlMixi
264
264
  }
265
265
 
266
266
  async focus() {
267
- const elem = this.shadowRoot.querySelector('textarea');
267
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('textarea');
268
268
  if (elem) {
269
269
  elem.focus();
270
270
  } else {
@@ -274,7 +274,7 @@ class InputTextArea extends LabelledMixin(FormElementMixin(SkeletonMixin(RtlMixi
274
274
  }
275
275
 
276
276
  async select() {
277
- const elem = this.shadowRoot.querySelector('textarea');
277
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('textarea');
278
278
  if (elem) {
279
279
  elem.select();
280
280
  } else {
@@ -210,9 +210,8 @@ class InputTimeRange extends SkeletonMixin(FormElementMixin(RtlMixin(LocalizeCor
210
210
  const startLabel = this.startLabel ? this.startLabel : this.localize('components.input-time-range.startTime');
211
211
  const endLabel = this.endLabel ? this.endLabel : this.localize('components.input-time-range.endTime');
212
212
 
213
- const startTimeInput = this.shadowRoot.querySelector('.d2l-input-time-range-start');
214
- const endTimeInput = this.shadowRoot.querySelector('.d2l-input-time-range-end');
215
-
213
+ const startTimeInput = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input-time-range-start');
214
+ const endTimeInput = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input-time-range-end');
216
215
  /**
217
216
  * @type {'five'|'ten'|'fifteen'|'twenty'|'thirty'|'sixty'}
218
217
  */
@@ -304,11 +303,12 @@ class InputTimeRange extends SkeletonMixin(FormElementMixin(RtlMixin(LocalizeCor
304
303
  }
305
304
 
306
305
  focus() {
307
- const input = this.shadowRoot.querySelector('d2l-input-time');
306
+ const input = this.shadowRoot && this.shadowRoot.querySelector('d2l-input-time');
308
307
  if (input) input.focus();
309
308
  }
310
309
 
311
310
  async validate() {
311
+ if (!this.shadowRoot) return;
312
312
  const startTimeInput = this.shadowRoot.querySelector('.d2l-input-time-range-start');
313
313
  const endTimeInput = this.shadowRoot.querySelector('.d2l-input-time-range-end');
314
314
  const errors = await Promise.all([startTimeInput.validate(), endTimeInput.validate(), super.validate()]);
@@ -350,7 +350,7 @@ class InputTime extends LabelledMixin(SkeletonMixin(FormElementMixin(LitElement)
350
350
  }
351
351
 
352
352
  focus() {
353
- const elem = this.shadowRoot.querySelector('.d2l-input');
353
+ const elem = this.shadowRoot && this.shadowRoot.querySelector('.d2l-input');
354
354
  if (elem) elem.focus();
355
355
  }
356
356
 
@@ -118,7 +118,7 @@ class Link extends LitElement {
118
118
  }
119
119
 
120
120
  focus() {
121
- const link = this.shadowRoot.querySelector('.d2l-link');
121
+ const link = this.shadowRoot && this.shadowRoot.querySelector('.d2l-link');
122
122
  if (link) link.focus();
123
123
  }
124
124
  }
@@ -163,10 +163,12 @@ class ListDemoDragAndDrop extends LitElement {
163
163
  targetItems.splice(targetIndex, 0, dataToMove[i]);
164
164
  }
165
165
 
166
- await this.requestUpdate();
166
+ this.requestUpdate();
167
+ await this.updateComplete;
167
168
 
168
169
  if (e.detail.keyboardActive) {
169
170
  requestAnimationFrame(() => {
171
+ if (!this.shadowRoot) return;
170
172
  const newItem = this.shadowRoot.querySelector('d2l-list').getListItemByKey(sourceListItems[0].key);
171
173
  newItem.activateDragHandle();
172
174
  });
@@ -1,5 +1,6 @@
1
1
  import '../colors/colors.js';
2
2
  import { css, html } from 'lit-element/lit-element.js';
3
+ import { getUniqueId } from '../../helpers/uniqueId.js';
3
4
  import { ListItemMixin } from './list-item-mixin.js';
4
5
 
5
6
  export const ListItemButtonMixin = superclass => class extends ListItemMixin(superclass) {
@@ -34,13 +35,18 @@ export const ListItemButtonMixin = superclass => class extends ListItemMixin(sup
34
35
  return styles;
35
36
  }
36
37
 
38
+ constructor() {
39
+ super();
40
+ this._primaryActionId = getUniqueId();
41
+ }
42
+
37
43
  _onButtonClick() {
38
44
  /** Dispatched when the item's primary button action is clicked */
39
45
  this.dispatchEvent(new CustomEvent('d2l-list-item-button-click', { bubbles: true }));
40
46
  }
41
47
 
42
48
  _renderPrimaryAction(labelledBy) {
43
- return html`<button aria-labelledby="${labelledBy}" @click="${this._onButtonClick}"></button>`;
49
+ return html`<button id="${this._primaryActionId}" aria-labelledby="${labelledBy}" @click="${this._onButtonClick}"></button>`;
44
50
  }
45
51
 
46
52
  };
@@ -119,7 +119,7 @@ export const ListItemCheckboxMixin = superclass => class extends SkeletonMixin(L
119
119
  event.preventDefault();
120
120
  if (this.disabled) return;
121
121
  this.setSelected(!this.selected);
122
- const checkbox = this.shadowRoot.querySelector(`#${this._checkboxId}`);
122
+ const checkbox = this.shadowRoot && this.shadowRoot.querySelector(`#${this._checkboxId}`);
123
123
  if (checkbox) checkbox.focus();
124
124
  }
125
125
 
@@ -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) {
@@ -550,8 +550,10 @@ export const ListItemDragDropMixin = superclass => class extends superclass {
550
550
  e.dataTransfer.setData('text/plain', `${this.dropText}`);
551
551
  }
552
552
 
553
- const nodeImage = this.shadowRoot.querySelector('.d2l-list-item-drag-image') || this;
554
- 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
+ }
555
557
 
556
558
  const rootList = this._getRootList(this);
557
559
 
@@ -583,6 +585,7 @@ export const ListItemDragDropMixin = superclass => class extends superclass {
583
585
  }
584
586
 
585
587
  _onDragTargetClick(e) {
588
+ if (!this.shadowRoot) return;
586
589
  if (this._keyboardActiveOnNextClick) {
587
590
  this.shadowRoot.querySelector(`#${this._itemDragId}`).activateKeyboardMode();
588
591
  } else {
@@ -691,7 +694,8 @@ export const ListItemDragDropMixin = superclass => class extends superclass {
691
694
  const dropGrid = listItem.shadowRoot.querySelector('.d2l-list-item-drag-drop-grid');
692
695
  if (dropGrid) dropGrid.dispatchEvent(createDragEvent('drop'));
693
696
  // simulate dragend
694
- 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'));
695
699
  }
696
700
 
697
701
  /**
@@ -743,7 +747,8 @@ export const ListItemDragDropMixin = superclass => class extends superclass {
743
747
  // simulate dragstart for touch and hold
744
748
  this._touchTimeoutId = setTimeout(() => {
745
749
  this._touchStarted = true;
746
- 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'));
747
752
  }, touchHoldDuration);
748
753
  }
749
754