@brightspace-ui/core 3.269.4 → 3.270.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.
@@ -163,10 +163,6 @@ class AlertToast extends LitElement {
163
163
  this._state = states.CLOSED;
164
164
  this._totalSiblingHeightBelow = 0;
165
165
 
166
- this._closeTimerStop = this._closeTimerStop.bind(this);
167
- this._handlePageResize = this._handlePageResize.bind(this);
168
- this._handleSiblingCloseTimerStart = this._handleSiblingCloseTimerStart.bind(this);
169
- this._handleSiblingResize = this._handleSiblingResize.bind(this);
170
166
  this._resizeObserver = null;
171
167
  }
172
168
 
@@ -185,11 +181,11 @@ class AlertToast extends LitElement {
185
181
 
186
182
  async connectedCallback() {
187
183
  super.connectedCallback();
188
- document.body.addEventListener('d2l-alert-toast-close', this._handleSiblingResize);
189
- document.body.addEventListener('d2l-alert-toast-resize', this._handleSiblingResize);
190
- document.body.addEventListener('d2l-alert-toast-timer-start', this._handleSiblingCloseTimerStart);
191
- document.body.addEventListener('d2l-alert-toast-timer-stop', this._closeTimerStop);
192
- if (mediaQueryList.addEventListener) mediaQueryList.addEventListener('change', this._handlePageResize);
184
+ document.body.addEventListener('d2l-alert-toast-close', this.#handleSiblingResize);
185
+ document.body.addEventListener('d2l-alert-toast-resize', this.#handleSiblingResize);
186
+ document.body.addEventListener('d2l-alert-toast-timer-start', this.#handleSiblingCloseTimerStart);
187
+ document.body.addEventListener('d2l-alert-toast-timer-stop', this.#closeTimerStop);
188
+ if (mediaQueryList.addEventListener) mediaQueryList.addEventListener('change', this.#handlePageResize);
193
189
 
194
190
  await this.updateComplete;
195
191
  this._resizeObserver = new ResizeObserver((e) => requestAnimationFrame(() => this._handleResize(e)));
@@ -198,12 +194,12 @@ class AlertToast extends LitElement {
198
194
 
199
195
  disconnectedCallback() {
200
196
  super.disconnectedCallback();
201
- document.body.removeEventListener('d2l-alert-toast-close', this._handleSiblingResize);
202
- document.body.removeEventListener('d2l-alert-toast-resize', this._handleSiblingResize);
203
- document.body.removeEventListener('d2l-alert-toast-timer-start', this._handleSiblingCloseTimerStart);
204
- document.body.removeEventListener('d2l-alert-toast-timer-stop', this._closeTimerStop);
197
+ document.body.removeEventListener('d2l-alert-toast-close', this.#handleSiblingResize);
198
+ document.body.removeEventListener('d2l-alert-toast-resize', this.#handleSiblingResize);
199
+ document.body.removeEventListener('d2l-alert-toast-timer-start', this.#handleSiblingCloseTimerStart);
200
+ document.body.removeEventListener('d2l-alert-toast-timer-stop', this.#closeTimerStop);
205
201
  if (this._resizeObserver) this._resizeObserver.disconnect();
206
- if (mediaQueryList.removeEventListener) mediaQueryList.removeEventListener('change', this._handlePageResize);
202
+ if (mediaQueryList.removeEventListener) mediaQueryList.removeEventListener('change', this.#handlePageResize);
207
203
 
208
204
  if (this._hasMouse) ALERT_HAS_HOVER = false;
209
205
  if (this._hasFocus) ALERT_HAS_FOCUS = false;
@@ -274,6 +270,39 @@ class AlertToast extends LitElement {
274
270
  }
275
271
  }
276
272
 
273
+ #closeTimerStop = () => {
274
+ if (!this.open) return;
275
+ clearTimeout(this._setTimeoutId);
276
+ };
277
+
278
+ #handlePageResize = (e) => {
279
+ this._smallWidth = e.matches;
280
+ };
281
+
282
+ #handleSiblingCloseTimerStart = () => {
283
+ if (!this.open) return;
284
+ this._closeTimerStart();
285
+ };
286
+
287
+ #handleSiblingResize = (e) => {
288
+ if (e?.composedPath()[0] === this || !this.open) return;
289
+
290
+ if (!e.detail.opening) {
291
+ const containerBottom = this._innerContainer.getBoundingClientRect().bottom;
292
+ const siblingContainerBottom = e.detail.bottom;
293
+ if (siblingContainerBottom < containerBottom) return; // resized alert is above this alert, no need to adjust bottom spacing
294
+ }
295
+
296
+ this._totalSiblingHeightBelow += e.detail.heightDifference;
297
+ if (e.detail.opening) {
298
+ this._numAlertsBelow += 1;
299
+ if (!activeReduceMotion) this._state = states.SLIDING;
300
+ } else if (e.detail.closing) {
301
+ this._numAlertsBelow -= 1;
302
+ if (!activeReduceMotion) this._state = states.SLIDING;
303
+ }
304
+ };
305
+
277
306
  _closeTimerStart() {
278
307
  clearTimeout(this._setTimeoutId);
279
308
  if (!this.noAutoClose && !ALERT_HAS_FOCUS && !ALERT_HAS_HOVER) {
@@ -284,20 +313,11 @@ class AlertToast extends LitElement {
284
313
  }
285
314
  }
286
315
 
287
- _closeTimerStop() {
288
- if (!this.open) return;
289
- clearTimeout(this._setTimeoutId);
290
- }
291
-
292
316
  _handleButtonPress(e) {
293
317
  e.stopPropagation();
294
318
  this.dispatchEvent(new CustomEvent('d2l-alert-toast-button-press'));
295
319
  }
296
320
 
297
- _handlePageResize(e) {
298
- this._smallWidth = e.matches;
299
- }
300
-
301
321
  _handleResize() {
302
322
  const boundingClientRect = this._innerContainer.getBoundingClientRect();
303
323
  const newHeight = boundingClientRect.height;
@@ -318,30 +338,6 @@ class AlertToast extends LitElement {
318
338
  ));
319
339
  }
320
340
 
321
- _handleSiblingCloseTimerStart() {
322
- if (!this.open) return;
323
- this._closeTimerStart();
324
- }
325
-
326
- _handleSiblingResize(e) {
327
- if (e?.composedPath()[0] === this || !this.open) return;
328
-
329
- if (!e.detail.opening) {
330
- const containerBottom = this._innerContainer.getBoundingClientRect().bottom;
331
- const siblingContainerBottom = e.detail.bottom;
332
- if (siblingContainerBottom < containerBottom) return; // resized alert is above this alert, no need to adjust bottom spacing
333
- }
334
-
335
- this._totalSiblingHeightBelow += e.detail.heightDifference;
336
- if (e.detail.opening) {
337
- this._numAlertsBelow += 1;
338
- if (!activeReduceMotion) this._state = states.SLIDING;
339
- } else if (e.detail.closing) {
340
- this._numAlertsBelow -= 1;
341
- if (!activeReduceMotion) this._state = states.SLIDING;
342
- }
343
- }
344
-
345
341
  _onBlur() {
346
342
  ALERT_HAS_FOCUS = false;
347
343
  this._hasFocus = false;
@@ -361,7 +357,7 @@ class AlertToast extends LitElement {
361
357
  _onFocus() {
362
358
  ALERT_HAS_FOCUS = true;
363
359
  this._hasFocus = true;
364
- this._closeTimerStop();
360
+ this.#closeTimerStop();
365
361
  /** @ignore */
366
362
  this.dispatchEvent(new CustomEvent('d2l-alert-toast-timer-stop', { bubbles: true, composed: false }));
367
363
  }
@@ -369,7 +365,7 @@ class AlertToast extends LitElement {
369
365
  _onMouseEnter() {
370
366
  ALERT_HAS_HOVER = true;
371
367
  this._hasMouse = true;
372
- this._closeTimerStop();
368
+ this.#closeTimerStop();
373
369
  /** @ignore */
374
370
  this.dispatchEvent(new CustomEvent('d2l-alert-toast-timer-stop', { bubbles: true, composed: false }));
375
371
  }
@@ -458,7 +454,7 @@ class AlertToast extends LitElement {
458
454
  if (newlyOpened || newlyOpenedReduceMotion) {
459
455
  this._closeTimerStart();
460
456
  } else if (newState !== states.SLIDING && newState !== states.OPEN) {
461
- this._closeTimerStop();
457
+ this.#closeTimerStop();
462
458
  }
463
459
  }
464
460
  }
@@ -227,15 +227,13 @@ class Card extends LitElement {
227
227
  this._footerHidden = true;
228
228
  this._hover = false;
229
229
  this._tooltipShowing = false;
230
- this._onBadgeResize = this._onBadgeResize.bind(this);
231
- this._onFooterResize = this._onFooterResize.bind(this);
232
230
  }
233
231
 
234
232
  firstUpdated(changedProperties) {
235
233
  super.firstUpdated(changedProperties);
236
- const badgeObserver = new ResizeObserver(this._onBadgeResize);
234
+ const badgeObserver = new ResizeObserver(this.#onBadgeResize);
237
235
  badgeObserver.observe(this.shadowRoot.querySelector('.d2l-card-badge'));
238
- const footerObserver = new ResizeObserver(this._onFooterResize);
236
+ const footerObserver = new ResizeObserver(this.#onFooterResize);
239
237
  footerObserver.observe(this.shadowRoot.querySelector('.d2l-card-footer'));
240
238
 
241
239
  if (this._focusOnFirstRender) {
@@ -307,11 +305,19 @@ class Card extends LitElement {
307
305
  else super.focus();
308
306
  }
309
307
 
310
- _onBadgeResize(entries) {
308
+ #onBadgeResize = (entries) => {
311
309
  if (!entries || entries.length === 0) return;
312
310
  const entry = entries[0];
313
311
  requestAnimationFrame(() => this._badgeMarginTop = `${-0.5 * entry.contentRect.height}px`);
314
- }
312
+ };
313
+
314
+ #onFooterResize = (entries) => {
315
+ if (!entries || entries.length === 0) return;
316
+ const entry = entries[0];
317
+ // firefox has a rounding error when calculating the height of the contentRect
318
+ // with `box-sizing: border-box;` so check for numbers which are close to 0 as well
319
+ requestAnimationFrame(() => this._footerHidden = (entry.contentRect.height < 1));
320
+ };
315
321
 
316
322
  _onDropdownClose() {
317
323
  this._dropdownActionOpen = false;
@@ -321,14 +327,6 @@ class Card extends LitElement {
321
327
  this._dropdownActionOpen = true;
322
328
  }
323
329
 
324
- _onFooterResize(entries) {
325
- if (!entries || entries.length === 0) return;
326
- const entry = entries[0];
327
- // firefox has a rounding error when calculating the height of the contentRect
328
- // with `box-sizing: border-box;` so check for numbers which are close to 0 as well
329
- requestAnimationFrame(() => this._footerHidden = (entry.contentRect.height < 1));
330
- }
331
-
332
330
  _onLinkBlur() {
333
331
  this._active = false;
334
332
  }
@@ -79,7 +79,6 @@ export const DialogMixin = superclass => class extends superclass {
79
79
  this._autoSize = true;
80
80
  this._dialogId = getUniqueId();
81
81
  this._fullscreenWithin = 0;
82
- this._handleMvcDialogOpen = this._handleMvcDialogOpen.bind(this);
83
82
  this._inIframe = false;
84
83
  this._isDialogMixin = true;
85
84
  this._isFullHeight = false;
@@ -93,21 +92,19 @@ export const DialogMixin = superclass => class extends superclass {
93
92
  this._scroll = false;
94
93
  this._state = null;
95
94
  this._top = 0;
96
- this._updateOverflow = this._updateOverflow.bind(this);
97
- this._updateSize = this._updateSize.bind(this);
98
95
  this._width = 0;
99
96
  }
100
97
 
101
98
  async connectedCallback() {
102
99
  super.connectedCallback();
103
100
  if (this._useNative) {
104
- window.addEventListener('d2l-mvc-dialog-open', this._handleMvcDialogOpen);
101
+ window.addEventListener('d2l-mvc-dialog-open', this.#handleMvcDialogOpen);
105
102
  }
106
103
  }
107
104
 
108
105
  disconnectedCallback() {
109
106
  super.disconnectedCallback();
110
- window.removeEventListener('d2l-mvc-dialog-open', this._handleMvcDialogOpen);
107
+ window.removeEventListener('d2l-mvc-dialog-open', this.#handleMvcDialogOpen);
111
108
 
112
109
  // If the dialog is disconnected before the close animation finishes
113
110
  if (this.opened && closeDialogWhenDisconnectedFlag) {
@@ -158,7 +155,7 @@ export const DialogMixin = superclass => class extends superclass {
158
155
  resize() {
159
156
  return new Promise(resolve => {
160
157
  setTimeout(async() => {
161
- await this._updateSize();
158
+ await this.#updateSize();
162
159
  resolve();
163
160
  }, 0);
164
161
  });
@@ -172,10 +169,56 @@ export const DialogMixin = superclass => class extends superclass {
172
169
 
173
170
  #useNativeInitialized = false;
174
171
 
172
+ #handleMvcDialogOpen = () => {
173
+ // native dialogs on top layer will be stacked on non-native dialogs regardless of z-index
174
+ // so we need to opt out of native dialogs if a non-native nested dialog is launched
175
+ this._useNative = false;
176
+ };
177
+
178
+ #updateOverflow = () => {
179
+ if (!this.shadowRoot) return;
180
+ const content = this.shadowRoot.querySelector('.d2l-dialog-content');
181
+ // On Windows, browser zoom can cause scrollTop to be a fraction
182
+ const bottomOverflow = content.scrollHeight - (Math.ceil(content.scrollTop) + content.clientHeight);
183
+ this._overflowTop = (content.scrollTop > 0);
184
+ this._overflowBottom = (bottomOverflow > 0);
185
+ };
186
+
187
+ #updateSize = async() => {
188
+ if (this._autoSize) {
189
+ if (this._ifrauContextInfo) {
190
+ if (this._ifrauContextInfo.top > defaultMargin.top) {
191
+ this._top = 0;
192
+ this._margin.top = 0;
193
+ } else if (this._ifrauContextInfo.top < 0) {
194
+ this._top = defaultMargin.top - this._ifrauContextInfo.top;
195
+ this._margin.top = defaultMargin.top;
196
+ } else {
197
+ this._top = defaultMargin.top - this._ifrauContextInfo.top;
198
+ this._margin.top = defaultMargin.top - this._ifrauContextInfo.top;
199
+ }
200
+ }
201
+ this._width = this._getWidth();
202
+ this._left = this._getLeft();
203
+ await this.updateComplete;
204
+ this._height = this._getHeight();
205
+ await this.updateComplete;
206
+ } else {
207
+ this._width = 0;
208
+ }
209
+ await new Promise(resolve => {
210
+ requestAnimationFrame(async() => {
211
+ this.#updateOverflow();
212
+ await this.updateComplete;
213
+ resolve();
214
+ });
215
+ });
216
+ };
217
+
175
218
  _addHandlers() {
176
- window.addEventListener('resize', this._updateSize);
219
+ window.addEventListener('resize', this.#updateSize);
177
220
  this.addEventListener('touchstart', this._handleTouchStart);
178
- if (this.shadowRoot) this.shadowRoot.querySelector('.d2l-dialog-content').addEventListener('scroll', this._updateOverflow);
221
+ if (this.shadowRoot) this.shadowRoot.querySelector('.d2l-dialog-content').addEventListener('scroll', this.#updateOverflow);
179
222
  }
180
223
 
181
224
  _close(action) {
@@ -379,12 +422,6 @@ export const DialogMixin = superclass => class extends superclass {
379
422
  }
380
423
  }
381
424
 
382
- _handleMvcDialogOpen() {
383
- // native dialogs on top layer will be stacked on non-native dialogs regardless of z-index
384
- // so we need to opt out of native dialogs if a non-native nested dialog is launched
385
- this._useNative = false;
386
- }
387
-
388
425
  _handleTouchStart(e) {
389
426
  // elements external to the dialog such as primary-secondary template should not be reacting
390
427
  // to touchstart events originating inside the dialog or backdrop
@@ -450,7 +487,7 @@ export const DialogMixin = superclass => class extends superclass {
450
487
  this._scroll = true;
451
488
  }, 0);
452
489
 
453
- await this._updateSize();
490
+ await this.#updateSize();
454
491
  if (!this._useNative) this._state = 'showing';
455
492
  await this.updateComplete;
456
493
 
@@ -470,7 +507,7 @@ export const DialogMixin = superclass => class extends superclass {
470
507
  requestAnimationFrame(() => this._updateFocusableContentElemPresent());
471
508
 
472
509
  await this.waitForUpdateComplete();
473
- await this._updateSize();
510
+ await this.#updateSize();
474
511
  /** Dispatched when the dialog is opened */
475
512
  this.dispatchEvent(new CustomEvent(
476
513
  'd2l-dialog-open', { bubbles: true, composed: true }
@@ -481,9 +518,9 @@ export const DialogMixin = superclass => class extends superclass {
481
518
  }
482
519
 
483
520
  _removeHandlers() {
484
- window.removeEventListener('resize', this._updateSize);
521
+ window.removeEventListener('resize', this.#updateSize);
485
522
  this.removeEventListener('touchstart', this._handleTouchStart);
486
- this.shadowRoot?.querySelector('.d2l-dialog-content')?.removeEventListener('scroll', this._updateOverflow);
523
+ this.shadowRoot?.querySelector('.d2l-dialog-content')?.removeEventListener('scroll', this.#updateOverflow);
487
524
  }
488
525
 
489
526
  _render(inner, info, iframeTopOverride) {
@@ -564,44 +601,4 @@ export const DialogMixin = superclass => class extends superclass {
564
601
  return elementToFocus;
565
602
  }
566
603
 
567
- _updateOverflow() {
568
- if (!this.shadowRoot) return;
569
- const content = this.shadowRoot.querySelector('.d2l-dialog-content');
570
- // On Windows, browser zoom can cause scrollTop to be a fraction
571
- const bottomOverflow = content.scrollHeight - (Math.ceil(content.scrollTop) + content.clientHeight);
572
- this._overflowTop = (content.scrollTop > 0);
573
- this._overflowBottom = (bottomOverflow > 0);
574
- }
575
-
576
- async _updateSize() {
577
- if (this._autoSize) {
578
- if (this._ifrauContextInfo) {
579
- if (this._ifrauContextInfo.top > defaultMargin.top) {
580
- this._top = 0;
581
- this._margin.top = 0;
582
- } else if (this._ifrauContextInfo.top < 0) {
583
- this._top = defaultMargin.top - this._ifrauContextInfo.top;
584
- this._margin.top = defaultMargin.top;
585
- } else {
586
- this._top = defaultMargin.top - this._ifrauContextInfo.top;
587
- this._margin.top = defaultMargin.top - this._ifrauContextInfo.top;
588
- }
589
- }
590
- this._width = this._getWidth();
591
- this._left = this._getLeft();
592
- await this.updateComplete;
593
- this._height = this._getHeight();
594
- await this.updateComplete;
595
- } else {
596
- this._width = 0;
597
- }
598
- await new Promise(resolve => {
599
- requestAnimationFrame(async() => {
600
- this._updateOverflow();
601
- await this.updateComplete;
602
- resolve();
603
- });
604
- });
605
- }
606
-
607
604
  };
@@ -102,7 +102,6 @@ class Dialog extends PropertyRequiredMixin(LocalizeCoreElement(AsyncContainerMix
102
102
  this.preferNative = false;
103
103
  this.width = 600;
104
104
  this._criticalLabelId = getUniqueId();
105
- this._handleResize = this._handleResize.bind(this);
106
105
  this._titleId = getUniqueId();
107
106
  this._textId = getUniqueId();
108
107
  }
@@ -113,17 +112,17 @@ class Dialog extends PropertyRequiredMixin(LocalizeCoreElement(AsyncContainerMix
113
112
 
114
113
  connectedCallback() {
115
114
  super.connectedCallback();
116
- if (mediaQueryList.addEventListener) mediaQueryList.addEventListener('change', this._handleResize);
115
+ if (mediaQueryList.addEventListener) mediaQueryList.addEventListener('change', this.#handleResize);
117
116
  }
118
117
 
119
118
  disconnectedCallback() {
120
- if (mediaQueryList.removeEventListener) mediaQueryList.removeEventListener('change', this._handleResize);
119
+ if (mediaQueryList.removeEventListener) mediaQueryList.removeEventListener('change', this.#handleResize);
121
120
  super.disconnectedCallback();
122
121
  }
123
122
 
124
123
  firstUpdated(changedProperties) {
125
124
  super.firstUpdated(changedProperties);
126
- this._handleResize();
125
+ this.#handleResize();
127
126
  }
128
127
 
129
128
  render() {
@@ -202,6 +201,11 @@ class Dialog extends PropertyRequiredMixin(LocalizeCoreElement(AsyncContainerMix
202
201
  }
203
202
  }
204
203
 
204
+ #handleResize = () => {
205
+ this._autoSize = !mediaQueryList.matches;
206
+ this.resize();
207
+ };
208
+
205
209
  _abort() {
206
210
  this._close('abort');
207
211
  }
@@ -211,11 +215,6 @@ class Dialog extends PropertyRequiredMixin(LocalizeCoreElement(AsyncContainerMix
211
215
  this._hasFooterContent = (footerContent && footerContent.length > 0);
212
216
  }
213
217
 
214
- _handleResize() {
215
- this._autoSize = !mediaQueryList.matches;
216
- this.resize();
217
- }
218
-
219
218
  _handleSlotChange() {
220
219
  requestAnimationFrame(() => this._updateFocusableContentElemPresent());
221
220
  }
@@ -62,7 +62,6 @@ export const DropdownOpenerMixin = superclass => class extends superclass {
62
62
  this._isHovering = false;
63
63
  this._isFading = false;
64
64
 
65
- this._onOutsideClick = this._onOutsideClick.bind(this);
66
65
  this._contentRendered = null;
67
66
  this._openerRendered = null;
68
67
  }
@@ -77,7 +76,7 @@ export const DropdownOpenerMixin = superclass => class extends superclass {
77
76
  this.addEventListener('mouseleave', this.__onMouseLeave);
78
77
 
79
78
  if (this.openOnHover) {
80
- document.body.addEventListener('mouseup', this._onOutsideClick);
79
+ document.body.addEventListener('mouseup', this.#onOutsideClick);
81
80
  }
82
81
  }
83
82
 
@@ -90,7 +89,7 @@ export const DropdownOpenerMixin = superclass => class extends superclass {
90
89
  this.removeEventListener('mouseleave', this.__onMouseLeave);
91
90
 
92
91
  if (this.openOnHover) {
93
- document.body.removeEventListener('mouseup', this._onOutsideClick);
92
+ document.body.removeEventListener('mouseup', this.#onOutsideClick);
94
93
  }
95
94
  }
96
95
 
@@ -167,6 +166,22 @@ export const DropdownOpenerMixin = superclass => class extends superclass {
167
166
  this.dropdownOpened = !this.dropdownOpened;
168
167
  }
169
168
 
169
+ /* used by open-on-hover option */
170
+ #onOutsideClick = (e) => {
171
+ if (!this.dropdownOpened) return;
172
+ const dropdownContent = this.__getContentElement();
173
+ const isWithinDropdown = isComposedAncestor(dropdownContent, e.composedPath()[0]);
174
+ const isWithinOpener = isComposedAncestor(this.getOpenerElement(), e.composedPath()[0]);
175
+
176
+ const isBackdropClick = isWithinDropdown
177
+ && dropdownContent._mobile
178
+ && e.composedPath().find(node => node.nodeName === 'D2L-BACKDROP');
179
+
180
+ if (!isWithinOpener && (!isWithinDropdown || isBackdropClick)) {
181
+ this.closeDropdown();
182
+ }
183
+ };
184
+
170
185
  __dispatchOpenerClickEvent() {
171
186
  /** Dispatched when the opener is clicked, useful for when no-auto-open is enabled */
172
187
  this.dispatchEvent(new CustomEvent(
@@ -289,22 +304,6 @@ export const DropdownOpenerMixin = superclass => class extends superclass {
289
304
  this._isFading = false;
290
305
  }
291
306
 
292
- /* used by open-on-hover option */
293
- _onOutsideClick(e) {
294
- if (!this.dropdownOpened) return;
295
- const dropdownContent = this.__getContentElement();
296
- const isWithinDropdown = isComposedAncestor(dropdownContent, e.composedPath()[0]);
297
- const isWithinOpener = isComposedAncestor(this.getOpenerElement(), e.composedPath()[0]);
298
-
299
- const isBackdropClick = isWithinDropdown
300
- && dropdownContent._mobile
301
- && e.composedPath().find(node => node.nodeName === 'D2L-BACKDROP');
302
-
303
- if (!isWithinOpener && (!isWithinDropdown || isBackdropClick)) {
304
- this.closeDropdown();
305
- }
306
- }
307
-
308
307
  _setOpenerElementAttribute(val, setActive = false, hasPopup) {
309
308
  const opener = this.getOpenerElement();
310
309
  if (!opener) return false;
@@ -33,9 +33,6 @@ class FocusTrap extends FocusMixin(LitElement) {
33
33
  constructor() {
34
34
  super();
35
35
  this.trap = false;
36
- this._handleBodyFocus = this._handleBodyFocus.bind(this);
37
- this._handleLegacyPromptOpen = this._handleLegacyPromptOpen.bind(this);
38
- this._handleLegacyPromptClose = this._handleLegacyPromptClose.bind(this);
39
36
  this._legacyPromptIds = new Set();
40
37
  }
41
38
 
@@ -45,16 +42,16 @@ class FocusTrap extends FocusMixin(LitElement) {
45
42
 
46
43
  connectedCallback() {
47
44
  super.connectedCallback();
48
- document.body.addEventListener('focus', this._handleBodyFocus, true);
49
- document.body.addEventListener('d2l-legacy-prompt-open', this._handleLegacyPromptOpen);
50
- document.body.addEventListener('d2l-legacy-prompt-close', this._handleLegacyPromptClose);
45
+ document.body.addEventListener('focus', this.#handleBodyFocus, true);
46
+ document.body.addEventListener('d2l-legacy-prompt-open', this.#handleLegacyPromptOpen);
47
+ document.body.addEventListener('d2l-legacy-prompt-close', this.#handleLegacyPromptClose);
51
48
  }
52
49
 
53
50
  disconnectedCallback() {
54
51
  super.disconnectedCallback();
55
- document.body.removeEventListener('focus', this._handleBodyFocus, true);
56
- document.body.removeEventListener('d2l-legacy-prompt-open', this._handleLegacyPromptOpen);
57
- document.body.removeEventListener('d2l-legacy-prompt-close', this._handleLegacyPromptClose);
52
+ document.body.removeEventListener('focus', this.#handleBodyFocus, true);
53
+ document.body.removeEventListener('d2l-legacy-prompt-open', this.#handleLegacyPromptOpen);
54
+ document.body.removeEventListener('d2l-legacy-prompt-close', this.#handleLegacyPromptClose);
58
55
  }
59
56
 
60
57
  render() {
@@ -83,6 +80,25 @@ class FocusTrap extends FocusMixin(LitElement) {
83
80
  '.equatio-toolbar-shadow-root-container'
84
81
  ].join(', ');
85
82
 
83
+ #handleBodyFocus = (e) => {
84
+ const lastTrap = traps[traps.length - 1];
85
+ if (!this.trap || this._legacyPromptIds.size > 0 || lastTrap !== this) return;
86
+ const container = this._getContainer();
87
+ const target = e.composedPath()[0];
88
+ if (isComposedAncestor(container, target) || FocusTrap.#isExempt(target)) return;
89
+ this._focusFirst();
90
+ };
91
+
92
+ #handleLegacyPromptClose = (e) => {
93
+ this._legacyPromptIds.delete(e.detail.id);
94
+ this.requestUpdate();
95
+ };
96
+
97
+ #handleLegacyPromptOpen = (e) => {
98
+ this._legacyPromptIds.add(e.detail.id);
99
+ this.requestUpdate();
100
+ };
101
+
86
102
  _focusFirst() {
87
103
  const focusable = this.shadowRoot &&
88
104
  getNextFocusable(this.shadowRoot.querySelector('.d2l-focus-trap-start'));
@@ -94,15 +110,6 @@ class FocusTrap extends FocusMixin(LitElement) {
94
110
  return this.shadowRoot && this.shadowRoot.querySelector('.d2l-focus-trap-start').parentNode;
95
111
  }
96
112
 
97
- _handleBodyFocus(e) {
98
- const lastTrap = traps[traps.length - 1];
99
- if (!this.trap || this._legacyPromptIds.size > 0 || lastTrap !== this) return;
100
- const container = this._getContainer();
101
- const target = e.composedPath()[0];
102
- if (isComposedAncestor(container, target) || FocusTrap.#isExempt(target)) return;
103
- this._focusFirst();
104
- }
105
-
106
113
  _handleEndFocusIn(e) {
107
114
  const container = this._getContainer();
108
115
  if (this.shadowRoot && (isComposedAncestor(container, e.relatedTarget) || FocusTrap.#isExempt(e.relatedTarget))) {
@@ -116,16 +123,6 @@ class FocusTrap extends FocusMixin(LitElement) {
116
123
  this._focusFirst();
117
124
  }
118
125
 
119
- _handleLegacyPromptClose(e) {
120
- this._legacyPromptIds.delete(e.detail.id);
121
- this.requestUpdate();
122
- }
123
-
124
- _handleLegacyPromptOpen(e) {
125
- this._legacyPromptIds.add(e.detail.id);
126
- this.requestUpdate();
127
- }
128
-
129
126
  _handleStartFocusIn(e) {
130
127
  const container = this._getContainer();
131
128
  if (this.shadowRoot && (isComposedAncestor(container, e.relatedTarget) || FocusTrap.#isExempt(e.relatedTarget))) {
@@ -113,8 +113,6 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
113
113
 
114
114
  constructor() {
115
115
  super();
116
- this._validationCustomConnected = this._validationCustomConnected.bind(this);
117
- this._onFormElementErrorsChange = this._onFormElementErrorsChange.bind(this);
118
116
 
119
117
  this._firstUpdateResolve = null;
120
118
  this._firstUpdatePromise = new Promise((resolve) => {
@@ -160,14 +158,14 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
160
158
 
161
159
  connectedCallback() {
162
160
  super.connectedCallback();
163
- this.shadowRoot.addEventListener('d2l-validation-custom-connected', this._validationCustomConnected);
164
- this.shadowRoot.addEventListener('d2l-form-element-errors-change', this._onFormElementErrorsChange);
161
+ this.shadowRoot.addEventListener('d2l-validation-custom-connected', this.#validationCustomConnected);
162
+ this.shadowRoot.addEventListener('d2l-form-element-errors-change', this.#onFormElementErrorsChange);
165
163
  }
166
164
 
167
165
  disconnectedCallback() {
168
166
  super.disconnectedCallback();
169
- this.shadowRoot.removeEventListener('d2l-validation-custom-connected', this._validationCustomConnected);
170
- this.shadowRoot.removeEventListener('d2l-form-element-errors-change', this._onFormElementErrorsChange);
167
+ this.shadowRoot.removeEventListener('d2l-validation-custom-connected', this.#validationCustomConnected);
168
+ this.shadowRoot.removeEventListener('d2l-form-element-errors-change', this.#onFormElementErrorsChange);
171
169
  }
172
170
 
173
171
  firstUpdated(changedProperties) {
@@ -261,7 +259,7 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
261
259
  this._validationCustoms.delete(custom);
262
260
  }
263
261
 
264
- _onFormElementErrorsChange(e) {
262
+ #onFormElementErrorsChange = (e) => {
265
263
  e.stopPropagation();
266
264
  const errors = e.detail.errors;
267
265
  if (errors.length === 0) {
@@ -273,9 +271,9 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
273
271
  this.childErrors.set(e.target, errors);
274
272
  this.requestUpdate('childErrors');
275
273
  }
276
- }
274
+ };
277
275
 
278
- _validationCustomConnected(e) {
276
+ #validationCustomConnected = (e) => {
279
277
  e.stopPropagation();
280
278
  const custom = e.composedPath()[0];
281
279
  this.validationCustomConnected(custom);
@@ -285,6 +283,6 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
285
283
  this.validationCustomDisconnected(custom);
286
284
  };
287
285
  custom.addEventListener('d2l-validation-custom-disconnected', onDisconnect);
288
- }
286
+ };
289
287
 
290
288
  };