@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.
- package/components/popover/popover-mixin.js +92 -104
- package/package.json +1 -1
|
@@ -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
|
-
|
|
594
|
-
#
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
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.#
|
|
602
|
-
document.body.addEventListener('focus', this.#
|
|
603
|
-
document.addEventListener('click', this.#
|
|
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.#
|
|
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.#
|
|
688
|
+
addResizeNoopEventListener(this.#handleResize);
|
|
622
689
|
|
|
623
|
-
this._ancestorMutationObserver ??= new MutationObserver(this.#
|
|
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.#
|
|
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.#
|
|
1178
|
-
document.body?.removeEventListener('focus', this.#
|
|
1179
|
-
document.removeEventListener('click', this.#
|
|
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.#
|
|
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.#
|
|
1190
|
+
node.removeEventListener('scroll', this.#reposition);
|
|
1192
1191
|
});
|
|
1193
1192
|
this._scrollablesObserved = null;
|
|
1194
1193
|
this._ancestorMutationObserver?.disconnect();
|
|
1195
|
-
removeResizeNoopEventListener(this.#
|
|
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.
|
|
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",
|