@brightspace-ui/core 3.269.1 → 3.269.2

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.
@@ -263,12 +263,6 @@ export const PopoverMixin = superclass => class extends superclass {
263
263
  this._mobile = false;
264
264
  this._showBackdrop = false;
265
265
  this._useNativePopover = isPopoverSupported ? 'manual' : undefined;
266
- this.#handleAncestorMutationBound = this.#handleAncestorMutation.bind(this);
267
- this.#handleAutoCloseClickBound = this.#handleAutoCloseClick.bind(this);
268
- this.#handleAutoCloseFocusBound = this.#handleAutoCloseFocus.bind(this);
269
- this.#handleMobileResizeBound = this.#handleMobileResize.bind(this);
270
- this.#handleResizeBound = this.#handleResize.bind(this);
271
- this.#repositionBound = this.#reposition.bind(this);
272
266
  }
273
267
 
274
268
  connectedCallback() {
@@ -590,23 +584,96 @@ export const PopoverMixin = superclass => class extends superclass {
590
584
  #ancestorMutations;
591
585
  #ifrauContextInfo;
592
586
  #mediaQueryList;
593
- #handleAncestorMutationBound;
594
- #handleAutoCloseClickBound;
595
- #handleAutoCloseFocusBound;
596
- #handleMobileResizeBound;
597
- #handleResizeBound;
598
- #repositionBound;
587
+
588
+ #handleAncestorMutation = (mutations) => {
589
+ if (!this._opener) return;
590
+ const reposition = !!mutations.find(mutation => {
591
+
592
+ // ignore mutations that are within this popover
593
+ if (isComposedAncestor(this._opener, mutation.target)) return false;
594
+
595
+ // ignore elements that are thrashing (ex. iframe's being resized on a setTimeout)
596
+ const previousMutation = this.#ancestorMutations?.get(mutation.target);
597
+ if (previousMutation && previousMutation === mutation.target.style.cssText) return false;
598
+ if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
599
+ this.#ancestorMutations?.set(mutation.target, mutation.target.style.cssText);
600
+ }
601
+
602
+ return true;
603
+ });
604
+ if (reposition) this.#reposition();
605
+ };
606
+
607
+ #handleAutoCloseClick = (e) => {
608
+ if (!this._opened || this._noAutoClose) return;
609
+
610
+ const rootTarget = e.composedPath()[0];
611
+ if (isComposedAncestor(this.#getContentContainer(), rootTarget)
612
+ || (this._opener !== document.body && isComposedAncestor(this._opener, rootTarget))) {
613
+ return;
614
+ }
615
+
616
+ this.close();
617
+ };
618
+
619
+ #handleAutoCloseFocus = () => {
620
+
621
+ // todo: try to use relatedTarget instead - this logic is largely copied as-is from dropdown simply to mitigate risk of this fragile code
622
+ setTimeout(() => {
623
+ // we ignore focusable ancestors othrwise the popover will close when user clicks empty space inside the popover
624
+ if (!this._opened
625
+ || this._noAutoClose
626
+ || !document.activeElement
627
+ || document.activeElement === this._previousFocusableAncestor
628
+ || document.activeElement === document.body) {
629
+ return;
630
+ }
631
+
632
+ const activeElement = getComposedActiveElement();
633
+ if (isComposedAncestor(this, activeElement)
634
+ || isComposedAncestor(this._opener, activeElement)
635
+ || activeElement === this._previousFocusableAncestor) {
636
+ return;
637
+ }
638
+
639
+ this.close();
640
+ }, 0);
641
+
642
+ };
643
+
644
+ #handleMobileResize = async() => {
645
+ this._mobile = this.#mediaQueryList.matches;
646
+ if (this._opened) {
647
+ this._showBackdrop = this._mobile && this._mobileTrayLocation;
648
+ await this.position();
649
+ }
650
+ };
651
+
652
+ #handleResize = () => {
653
+ this.resize();
654
+ };
655
+
656
+ #reposition = () => {
657
+ // throttle repositioning (https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event#scroll_event_throttling)
658
+ if (!this._repositioning) {
659
+ requestAnimationFrame(() => {
660
+ this.position(undefined, { updateLocation: false, updateHeight: false });
661
+ this._repositioning = false;
662
+ });
663
+ }
664
+ this._repositioning = true;
665
+ };
599
666
 
600
667
  #addAutoCloseHandlers() {
601
- this.addEventListener('blur', this.#handleAutoCloseFocusBound, { capture: true });
602
- document.body.addEventListener('focus', this.#handleAutoCloseFocusBound, { capture: true });
603
- document.addEventListener('click', this.#handleAutoCloseClickBound, { capture: true });
668
+ this.addEventListener('blur', this.#handleAutoCloseFocus, { capture: true });
669
+ document.body.addEventListener('focus', this.#handleAutoCloseFocus, { capture: true });
670
+ document.addEventListener('click', this.#handleAutoCloseClick, { capture: true });
604
671
  }
605
672
 
606
673
  #addMediaQueryHandlers() {
607
674
  this.#mediaQueryList = window.matchMedia(`(max-width: ${this._mobileBreakpoint - 1}px)`);
608
675
  this._mobile = this.#mediaQueryList.matches;
609
- this.#mediaQueryList.addEventListener?.('change', this.#handleMobileResizeBound);
676
+ this.#mediaQueryList.addEventListener?.('change', this.#handleMobileResize);
610
677
  }
611
678
 
612
679
  #addRepositionHandlers() {
@@ -618,9 +685,9 @@ export const PopoverMixin = superclass => class extends superclass {
618
685
 
619
686
  this.#removeRepositionHandlers();
620
687
  this.#ancestorMutations = new Map();
621
- addResizeNoopEventListener(this.#handleResizeBound);
688
+ addResizeNoopEventListener(this.#handleResize);
622
689
 
623
- this._ancestorMutationObserver ??= new MutationObserver(this.#handleAncestorMutationBound);
690
+ this._ancestorMutationObserver ??= new MutationObserver(this.#handleAncestorMutation);
624
691
  const mutationConfig = { attributes: true, childList: true, subtree: true };
625
692
 
626
693
  let node = this;
@@ -636,7 +703,7 @@ export const PopoverMixin = superclass => class extends superclass {
636
703
  }
637
704
  if (observeScrollable) {
638
705
  this._scrollablesObserved.push(node);
639
- node.addEventListener('scroll', this.#repositionBound);
706
+ node.addEventListener('scroll', this.#reposition);
640
707
  }
641
708
 
642
709
  // observe mutations on each DOM scope (excludes sibling scopes... can only do so much)
@@ -1094,62 +1161,6 @@ export const PopoverMixin = superclass => class extends superclass {
1094
1161
  };
1095
1162
  }
1096
1163
 
1097
- #handleAncestorMutation(mutations) {
1098
- if (!this._opener) return;
1099
- const reposition = !!mutations.find(mutation => {
1100
-
1101
- // ignore mutations that are within this popover
1102
- if (isComposedAncestor(this._opener, mutation.target)) return false;
1103
-
1104
- // ignore elements that are thrashing (ex. iframe's being resized on a setTimeout)
1105
- const previousMutation = this.#ancestorMutations?.get(mutation.target);
1106
- if (previousMutation && previousMutation === mutation.target.style.cssText) return false;
1107
- if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
1108
- this.#ancestorMutations?.set(mutation.target, mutation.target.style.cssText);
1109
- }
1110
-
1111
- return true;
1112
- });
1113
- if (reposition) this.#reposition();
1114
- }
1115
-
1116
- #handleAutoCloseClick(e) {
1117
- if (!this._opened || this._noAutoClose) return;
1118
-
1119
- const rootTarget = e.composedPath()[0];
1120
- if (isComposedAncestor(this.#getContentContainer(), rootTarget)
1121
- || (this._opener !== document.body && isComposedAncestor(this._opener, rootTarget))) {
1122
- return;
1123
- }
1124
-
1125
- this.close();
1126
- }
1127
-
1128
- #handleAutoCloseFocus() {
1129
-
1130
- // todo: try to use relatedTarget instead - this logic is largely copied as-is from dropdown simply to mitigate risk of this fragile code
1131
- setTimeout(() => {
1132
- // we ignore focusable ancestors othrwise the popover will close when user clicks empty space inside the popover
1133
- if (!this._opened
1134
- || this._noAutoClose
1135
- || !document.activeElement
1136
- || document.activeElement === this._previousFocusableAncestor
1137
- || document.activeElement === document.body) {
1138
- return;
1139
- }
1140
-
1141
- const activeElement = getComposedActiveElement();
1142
- if (isComposedAncestor(this, activeElement)
1143
- || isComposedAncestor(this._opener, activeElement)
1144
- || activeElement === this._previousFocusableAncestor) {
1145
- return;
1146
- }
1147
-
1148
- this.close();
1149
- }, 0);
1150
-
1151
- }
1152
-
1153
1164
  #handleBackdropClick() {
1154
1165
  this.close();
1155
1166
  }
@@ -1161,26 +1172,14 @@ export const PopoverMixin = superclass => class extends superclass {
1161
1172
  this.dispatchEvent(new CustomEvent('d2l-popover-focus-enter', { detail: { applyFocus: this._applyFocus } }));
1162
1173
  }
1163
1174
 
1164
- async #handleMobileResize() {
1165
- this._mobile = this.#mediaQueryList.matches;
1166
- if (this._opened) {
1167
- this._showBackdrop = this._mobile && this._mobileTrayLocation;
1168
- await this.position();
1169
- }
1170
- }
1171
-
1172
- #handleResize() {
1173
- this.resize();
1174
- }
1175
-
1176
1175
  #removeAutoCloseHandlers() {
1177
- this.removeEventListener('blur', this.#handleAutoCloseFocusBound, { capture: true });
1178
- document.body?.removeEventListener('focus', this.#handleAutoCloseFocusBound, { capture: true }); // DE41322: document.body can be null in some scenarios
1179
- document.removeEventListener('click', this.#handleAutoCloseClickBound, { capture: true });
1176
+ this.removeEventListener('blur', this.#handleAutoCloseFocus, { capture: true });
1177
+ document.body?.removeEventListener('focus', this.#handleAutoCloseFocus, { capture: true }); // DE41322: document.body can be null in some scenarios
1178
+ document.removeEventListener('click', this.#handleAutoCloseClick, { capture: true });
1180
1179
  }
1181
1180
 
1182
1181
  #removeMediaQueryHandlers() {
1183
- this.#mediaQueryList?.removeEventListener?.('change', this.#handleMobileResizeBound);
1182
+ this.#mediaQueryList?.removeEventListener?.('change', this.#handleMobileResize);
1184
1183
  }
1185
1184
 
1186
1185
  #removeRepositionHandlers() {
@@ -1188,22 +1187,11 @@ export const PopoverMixin = superclass => class extends superclass {
1188
1187
  this._openerIntersectionObserver?.unobserve(this._opener);
1189
1188
  }
1190
1189
  this._scrollablesObserved?.forEach(node => {
1191
- node.removeEventListener('scroll', this.#repositionBound);
1190
+ node.removeEventListener('scroll', this.#reposition);
1192
1191
  });
1193
1192
  this._scrollablesObserved = null;
1194
1193
  this._ancestorMutationObserver?.disconnect();
1195
- removeResizeNoopEventListener(this.#handleResizeBound);
1196
- }
1197
-
1198
- #reposition() {
1199
- // throttle repositioning (https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event#scroll_event_throttling)
1200
- if (!this._repositioning) {
1201
- requestAnimationFrame(() => {
1202
- this.position(undefined, { updateLocation: false, updateHeight: false });
1203
- this._repositioning = false;
1204
- });
1205
- }
1206
- this._repositioning = true;
1194
+ removeResizeNoopEventListener(this.#handleResize);
1207
1195
  }
1208
1196
 
1209
1197
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "3.269.1",
3
+ "version": "3.269.2",
4
4
  "description": "A collection of accessible, free, open-source web components for building Brightspace applications",
5
5
  "type": "module",
6
6
  "repository": "https://github.com/BrightspaceUI/core.git",