Skip to content

Commit 4eebe20

Browse files
authored
fix: Dialog sizing logic wait for descendants to update (#5306)
* add additional resizing logic to dialog-mixin so it wait for descendants lifecycle updates before resize * add ff conditional to guard behavior
1 parent 83510b7 commit 4eebe20

File tree

6 files changed

+57
-8
lines changed

6 files changed

+57
-8
lines changed

components/dialog/demo/dialog-async-content.js

+13-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import '../../list/list-item.js';
33
import '../../list/list-item-content.js';
44
import { html, LitElement } from 'lit';
55
import { InitialStateError, runAsync } from '../../../directives/run-async/run-async.js';
6+
import { LoadingCompleteMixin } from '../../../mixins/loading-complete/loading-complete-mixin.js';
67

7-
class DialogAsyncContent extends LitElement {
8+
class DialogAsyncContent extends LoadingCompleteMixin(LitElement) {
89

910
static get properties() {
1011
return {
@@ -32,21 +33,21 @@ class DialogAsyncContent extends LitElement {
3233
resolve(html`
3334
<d2l-list>
3435
<d2l-list-item>
35-
<img slot="illustration" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg"></img>
36+
<img slot="illustration" src="https://s.brightspace.com/course-images/images/38e839b1-37fa-470c-8830-b189ce4ae134/tile-high-density-max-size.jpg" @load="${this.#handleImageLoad}">
3637
<d2l-list-item-content>
3738
<div>Introductory Earth Sciences</div>
3839
<div slot="supporting-info">This course explores the geological process of the Earth's interior and surface. These include volcanism, earthquakes, mountains...</div>
3940
</d2l-list-item-content>
4041
</d2l-list-item>
4142
<d2l-list-item>
42-
<img slot="illustration" src="https://s.brightspace.com/course-images/images/e5fd575a-bc14-4a80-89e1-46f349a76178/tile-high-density-max-size.jpg"></img>
43+
<img slot="illustration" src="https://s.brightspace.com/course-images/images/e5fd575a-bc14-4a80-89e1-46f349a76178/tile-high-density-max-size.jpg" @load="${this.#handleImageLoad}">
4344
<d2l-list-item-content>
4445
<div>Engineering Materials for Energy Systems</div>
4546
<div slot="supporting-info">This course explores the geological processes of the Earth's interior and surface. These include volcanism, earthquakes, mountain...</div>
4647
</d2l-list-item-content>
4748
</d2l-list-item>
4849
<d2l-list-item>
49-
<img slot="illustration" src="https://s.brightspace.com/course-images/images/63b162ab-b582-4bf9-8c1d-1dad04714121/tile-high-density-max-size.jpg"></img>
50+
<img slot="illustration" src="https://s.brightspace.com/course-images/images/63b162ab-b582-4bf9-8c1d-1dad04714121/tile-high-density-max-size.jpg" @load="${this.#handleImageLoad}">
5051
<d2l-list-item-content>
5152
<div>Geomorphology and GIS </div>
5253
<div slot="supporting-info">This course explores the geological processes of the Earth's interior and surface. These include volcanism, earthquakes, mountain...</div>
@@ -58,6 +59,14 @@ class DialogAsyncContent extends LitElement {
5859
});
5960
}
6061

62+
#handleImageLoad() {
63+
const images = this.shadowRoot.querySelectorAll('img');
64+
for (const image of images) {
65+
if (!image.complete) return;
66+
}
67+
this.resolveLoadingComplete();
68+
}
69+
6170
}
6271

6372
customElements.define('d2l-dialog-demo-async-content', DialogAsyncContent);

components/dialog/dialog-mixin.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import '../focus-trap/focus-trap.js';
22
import '../../helpers/viewport-size.js';
33
import { allowBodyScroll, preventBodyScroll } from '../backdrop/backdrop.js';
44
import { clearDismissible, setDismissible } from '../../helpers/dismissible.js';
5-
import { findComposedAncestor, isComposedAncestor } from '../../helpers/dom.js';
5+
import { findComposedAncestor, getComposedChildren, isComposedAncestor } from '../../helpers/dom.js';
66
import { getComposedActiveElement, getFirstFocusableDescendant, getNextFocusable, isFocusable } from '../../helpers/focus.js';
77
import { classMap } from 'lit/directives/class-map.js';
88
import { getUniqueId } from '../../helpers/uniqueId.js';
@@ -11,6 +11,7 @@ import { ifDefined } from 'lit/directives/if-defined.js';
1111
import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
1212
import { styleMap } from 'lit/directives/style-map.js';
1313
import { tryGetIfrauBackdropService } from '../../helpers/ifrauBackdropService.js';
14+
import { waitForElem } from '../../helpers/internal/waitForElem.js';
1415

1516
window.D2L = window.D2L || {};
1617
window.D2L.DialogMixin = window.D2L.DialogMixin || {};
@@ -452,6 +453,11 @@ export const DialogMixin = superclass => class extends RtlMixin(superclass) {
452453
if (reduceMotion) await new Promise(resolve => requestAnimationFrame(resolve));
453454
else await animPromise;
454455

456+
const flag = window.D2L?.LP?.Web?.UI?.Flags.Flag('GAUD-7397-dialog-resize-updateComplete', true) ?? true;
457+
if (flag) {
458+
await this.#waitForUpdateComplete();
459+
}
460+
await this._updateSize();
455461
/** Dispatched when the dialog is opened */
456462
this.dispatchEvent(new CustomEvent(
457463
'd2l-dialog-open', { bubbles: true, composed: true }
@@ -580,4 +586,10 @@ export const DialogMixin = superclass => class extends RtlMixin(superclass) {
580586
});
581587
});
582588
}
589+
590+
async #waitForUpdateComplete() {
591+
const predicate = () => true;
592+
const composedChildren = getComposedChildren(this, predicate);
593+
await Promise.all(composedChildren.map(child => waitForElem(child, predicate)));
594+
}
583595
};
Loading

helpers/README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ elemIdListRemoves(node, attrName, value);
8686
findComposedAncestor(node, predicate);
8787

8888
// gets the composed children (including shadow children & distributed children)
89-
getComposedChildren(element);
89+
// includes a predicate which will add children nodes when predicate(node) is true
90+
getComposedChildren(element, predicate = () => true);
9091

9192
// gets the composed parent (including shadow host & insertion points)
9293
getComposedParent(node);

helpers/dom.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export function getBoundingAncestor(node) {
7979
});
8080
}
8181

82-
export function getComposedChildren(node) {
82+
export function getComposedChildren(node, predicate = () => true) {
8383

8484
if (!node) {
8585
return null;
@@ -104,7 +104,9 @@ export function getComposedChildren(node) {
104104

105105
for (let i = 0; i < nodes.length; i++) {
106106
if (nodes[i].nodeType === 1) {
107-
children.push(nodes[i]);
107+
if (predicate(nodes[i])) {
108+
children.push(nodes[i]);
109+
}
108110
}
109111
}
110112

helpers/internal/waitForElem.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { getComposedChildren } from '../dom.js';
2+
3+
export async function waitForElem(elem, predicate = () => true) {
4+
5+
if (!elem) return;
6+
7+
const update = elem.updateComplete;
8+
if (typeof update === 'object' && Promise.resolve(update) === update) {
9+
await update;
10+
await new Promise(resolve => {
11+
requestAnimationFrame(() => resolve());
12+
});
13+
}
14+
15+
if (typeof elem.getLoadingComplete === 'function') {
16+
await elem.getLoadingComplete();
17+
await new Promise(resolve => {
18+
requestAnimationFrame(() => resolve());
19+
});
20+
}
21+
22+
const children = getComposedChildren(elem, predicate);
23+
await Promise.all(children.map(e => waitForElem(e, predicate)));
24+
25+
}

0 commit comments

Comments
 (0)