@brightspace-ui/core 3.100.3 → 3.101.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.
- package/components/dialog/README.md +80 -0
- package/components/dialog/demo/dialog-async-content-until.js +89 -0
- package/components/dialog/demo/dialog.html +23 -0
- package/components/dropdown/dropdown-popover-mixin.js +2 -2
- package/components/filter/filter.js +2 -6
- package/components/list/demo/demo-list.js +0 -1
- package/custom-elements.json +25 -0
- package/package.json +1 -1
@@ -258,6 +258,86 @@ document.querySelector('#open').addEventListener('click', () => {
|
|
258
258
|
});
|
259
259
|
```
|
260
260
|
|
261
|
+
## Loading Asynchronous Content
|
262
|
+
|
263
|
+
The `until` directive can be used for manging the rendering of dialog content when it is loaded asynchronously. The example below loads some dialog content asynchronously, displaying a [Loading Spinner](../loading-spinner/) until the content is ready.
|
264
|
+
|
265
|
+
Notes on this example:
|
266
|
+
- Dialog sizing: `this.resolveLoadingComplete` (part of `LoadingCompleteMixin`) on image load triggers the dialog resize
|
267
|
+
- Focus management: focus will go to the first footer button by default. If focus should instead go to a focusable element in the content then that would need to be specified, often by using `.focus()` on the other focusable element.
|
268
|
+
|
269
|
+
<!-- docs: demo code autoSize:false size:xlarge -->
|
270
|
+
```html
|
271
|
+
<script type="module">
|
272
|
+
import '@brightspace-ui/core/components/button/button.js';
|
273
|
+
import '@brightspace-ui/core/components/loading-spinner/loading-spinner.js';
|
274
|
+
import { html, LitElement, noChange } from 'lit';
|
275
|
+
import { guard } from 'lit/directives/guard.js';
|
276
|
+
import { LoadingCompleteMixin } from '@brightspace-ui/core/mixins/loading-complete/loading-complete-mixin.js';
|
277
|
+
import { until } from 'lit/directives/until.js';
|
278
|
+
|
279
|
+
class DialogAsyncContentUntil extends LoadingCompleteMixin(LitElement) {
|
280
|
+
|
281
|
+
static get properties() {
|
282
|
+
return {
|
283
|
+
key: { type: String }
|
284
|
+
};
|
285
|
+
}
|
286
|
+
|
287
|
+
constructor() {
|
288
|
+
super();
|
289
|
+
this.key = null;
|
290
|
+
}
|
291
|
+
|
292
|
+
render() {
|
293
|
+
const loadingSpinner = html`<d2l-loading-spinner size="100" style="width: 100%;"></d2l-loading-spinner>`;
|
294
|
+
return html`${guard([this.key], () => until(this.#getContent(this.key), loadingSpinner, noChange))}`;
|
295
|
+
}
|
296
|
+
|
297
|
+
#getContent(key) {
|
298
|
+
return new Promise((resolve) => {
|
299
|
+
if (!key) return;
|
300
|
+
setTimeout(() => {
|
301
|
+
resolve(html`
|
302
|
+
<d2l-button>Focus on me!</d2l-button>
|
303
|
+
<img
|
304
|
+
src="https://us.v-cdn.net/cdn-cgi/image/fit=scale-down,width=1600/https://us.v-cdn.net/6036482/uploads/Y6MNPRWX5OVH/moose-poses-guided-tour.png"
|
305
|
+
style="height: 300px; display: block;"
|
306
|
+
@load="${this.#handleImageLoad}"
|
307
|
+
>
|
308
|
+
`);
|
309
|
+
}, 1000);
|
310
|
+
});
|
311
|
+
}
|
312
|
+
|
313
|
+
#handleImageLoad() {
|
314
|
+
this.shadowRoot.querySelector('d2l-button').focus();
|
315
|
+
this.resolveLoadingComplete();
|
316
|
+
}
|
317
|
+
}
|
318
|
+
|
319
|
+
customElements.define('d2l-dialog-demo-async-content-until', DialogAsyncContentUntil);
|
320
|
+
</script>
|
321
|
+
<script type="module">
|
322
|
+
import '@brightspace-ui/core/components/button/button.js';
|
323
|
+
import '@brightspace-ui/core/components/dialog/dialog.js';
|
324
|
+
|
325
|
+
document.querySelector('#open').addEventListener('click', () => {
|
326
|
+
document.querySelector('#dialog').opened = true;
|
327
|
+
document.querySelector('d2l-dialog-demo-async-content-until').key = 'my-dialog';
|
328
|
+
});
|
329
|
+
document.querySelector('#dialog').addEventListener('d2l-dialog-close', (e) => {
|
330
|
+
console.log('dialog action:', e.detail.action);
|
331
|
+
});
|
332
|
+
</script>
|
333
|
+
<d2l-dialog id="dialog" title-text="Async Dialog">
|
334
|
+
<d2l-dialog-demo-async-content-until></d2l-dialog-demo-async-content-until>
|
335
|
+
<d2l-button slot="footer" primary data-dialog-action="done">Done</d2l-button>
|
336
|
+
<d2l-button slot="footer" data-dialog-action>Cancel</d2l-button>
|
337
|
+
</d2l-dialog>
|
338
|
+
<d2l-button id="open">Show Dialog</d2l-button>
|
339
|
+
```
|
340
|
+
|
261
341
|
## Accessibility
|
262
342
|
|
263
343
|
### Focus Management
|
@@ -0,0 +1,89 @@
|
|
1
|
+
import '../../button/button.js';
|
2
|
+
import '../../list/list.js';
|
3
|
+
import '../../list/list-item.js';
|
4
|
+
import '../../list/list-item-content.js';
|
5
|
+
import '../../loading-spinner/loading-spinner.js';
|
6
|
+
import { css, html, LitElement, noChange } from 'lit';
|
7
|
+
import { guard } from 'lit/directives/guard.js';
|
8
|
+
import { LoadingCompleteMixin } from '../../../mixins/loading-complete/loading-complete-mixin.js';
|
9
|
+
import { until } from 'lit/directives/until.js';
|
10
|
+
|
11
|
+
class DialogAsyncContentUntil extends LoadingCompleteMixin(LitElement) {
|
12
|
+
|
13
|
+
static get properties() {
|
14
|
+
return {
|
15
|
+
href: { type: String }
|
16
|
+
};
|
17
|
+
}
|
18
|
+
|
19
|
+
static get styles() {
|
20
|
+
return css`
|
21
|
+
.content-button {
|
22
|
+
padding-block: 1rem;
|
23
|
+
}
|
24
|
+
.d2l-dialog-content-loading {
|
25
|
+
text-align: center;
|
26
|
+
}
|
27
|
+
`;
|
28
|
+
}
|
29
|
+
|
30
|
+
constructor() {
|
31
|
+
super();
|
32
|
+
this.href = null;
|
33
|
+
}
|
34
|
+
|
35
|
+
render() {
|
36
|
+
const loadingSpinner = html`
|
37
|
+
<div class="d2l-dialog-content-loading">
|
38
|
+
<d2l-loading-spinner size="100"></d2l-loading-spinner>
|
39
|
+
</div>
|
40
|
+
`;
|
41
|
+
return html`${guard([this.href], () => until(this._getContent(this.href), loadingSpinner, noChange))}`;
|
42
|
+
}
|
43
|
+
|
44
|
+
_getContent(href) {
|
45
|
+
return new Promise((resolve) => {
|
46
|
+
if (!href) return;
|
47
|
+
setTimeout(() => {
|
48
|
+
resolve(html`
|
49
|
+
<d2l-button class="content-button">Focus on me!</d2l-button>
|
50
|
+
<d2l-list>
|
51
|
+
<d2l-list-item>
|
52
|
+
<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}">
|
53
|
+
<d2l-list-item-content>
|
54
|
+
<div>Introductory Earth Sciences</div>
|
55
|
+
<div slot="supporting-info">This course explores the geological process of the Earth's interior and surface. These include volcanism, earthquakes, mountains...</div>
|
56
|
+
</d2l-list-item-content>
|
57
|
+
</d2l-list-item>
|
58
|
+
<d2l-list-item>
|
59
|
+
<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}">
|
60
|
+
<d2l-list-item-content>
|
61
|
+
<div>Engineering Materials for Energy Systems</div>
|
62
|
+
<div slot="supporting-info">This course explores the geological processes of the Earth's interior and surface. These include volcanism, earthquakes, mountain...</div>
|
63
|
+
</d2l-list-item-content>
|
64
|
+
</d2l-list-item>
|
65
|
+
<d2l-list-item>
|
66
|
+
<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}">
|
67
|
+
<d2l-list-item-content>
|
68
|
+
<div>Geomorphology and GIS </div>
|
69
|
+
<div slot="supporting-info">This course explores the geological processes of the Earth's interior and surface. These include volcanism, earthquakes, mountain...</div>
|
70
|
+
</d2l-list-item-content>
|
71
|
+
</d2l-list-item>
|
72
|
+
</d2l-list>
|
73
|
+
`);
|
74
|
+
}, 1000);
|
75
|
+
});
|
76
|
+
}
|
77
|
+
|
78
|
+
#handleImageLoad() {
|
79
|
+
const images = this.shadowRoot.querySelectorAll('img');
|
80
|
+
for (const image of images) {
|
81
|
+
if (!image.complete) return;
|
82
|
+
}
|
83
|
+
this.shadowRoot.querySelector('.content-button').focus();
|
84
|
+
this.resolveLoadingComplete();
|
85
|
+
}
|
86
|
+
|
87
|
+
}
|
88
|
+
|
89
|
+
customElements.define('d2l-dialog-demo-async-content-until', DialogAsyncContentUntil);
|
@@ -18,6 +18,7 @@
|
|
18
18
|
import '../../list/demo/demo-list.js';
|
19
19
|
import '../dialog.js';
|
20
20
|
import './dialog-async-content.js';
|
21
|
+
import './dialog-async-content-until.js';
|
21
22
|
import './dialog-container.js';
|
22
23
|
</script>
|
23
24
|
<style>
|
@@ -133,6 +134,28 @@
|
|
133
134
|
</template>
|
134
135
|
</d2l-demo-snippet>
|
135
136
|
|
137
|
+
<h2>Dialog (async using until)</h2>
|
138
|
+
|
139
|
+
<d2l-demo-snippet>
|
140
|
+
<template>
|
141
|
+
<d2l-button id="openAsyncUntil">Show Dialog</d2l-button>
|
142
|
+
<d2l-dialog id="dialogAsyncUntil" title-text="Dialog Title">
|
143
|
+
<d2l-dialog-demo-async-content-until></d2l-dialog-demo-async-content-until>
|
144
|
+
<d2l-button slot="footer" primary data-dialog-action="ok">Click Me!</d2l-button>
|
145
|
+
<d2l-button slot="footer" data-dialog-action>Cancel</d2l-button>
|
146
|
+
</d2l-dialog>
|
147
|
+
<script>
|
148
|
+
document.querySelector('#openAsyncUntil').addEventListener('click', () => {
|
149
|
+
document.querySelector('#dialogAsyncUntil').opened = true;
|
150
|
+
document.querySelector('d2l-dialog-demo-async-content-until').href = 'some-href';
|
151
|
+
});
|
152
|
+
document.querySelector('#dialogAsyncUntil').addEventListener('d2l-dialog-close', (e) => {
|
153
|
+
console.log('dialog action:', e.detail.action);
|
154
|
+
});
|
155
|
+
</script>
|
156
|
+
</template>
|
157
|
+
</d2l-demo-snippet>
|
158
|
+
|
136
159
|
<h2>Dialog (intercept closing)</h2>
|
137
160
|
|
138
161
|
<d2l-demo-snippet>
|
@@ -285,7 +285,7 @@ export const DropdownPopoverMixin = superclass => class extends LocalizeCoreElem
|
|
285
285
|
case 'left': return 'inline-start';
|
286
286
|
case 'right': return 'inline-end';
|
287
287
|
default: return undefined;
|
288
|
-
|
288
|
+
}
|
289
289
|
}
|
290
290
|
|
291
291
|
#adaptPositionSpan(val) {
|
@@ -293,7 +293,7 @@ export const DropdownPopoverMixin = superclass => class extends LocalizeCoreElem
|
|
293
293
|
case 'start': return 'end';
|
294
294
|
case 'end': return 'start';
|
295
295
|
default: return 'all';
|
296
|
-
|
296
|
+
}
|
297
297
|
}
|
298
298
|
|
299
299
|
#getMobileCloseButtonStyles() {
|
@@ -644,9 +644,7 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
|
|
644
644
|
<div class="d2l-filter-dimension-set-value d2l-body-compact">
|
645
645
|
<div class="d2l-filter-dimension-set-value-text">${item.text}</div>
|
646
646
|
${item.count !== undefined ? html`<div class="d2l-body-small">(${formatNumber(item.count)})</div>` : nothing}
|
647
|
-
${item.additionalContent
|
648
|
-
? html`<d2l-icon icon="${item.selected ? 'tier1:arrow-collapse-small' : 'tier1:arrow-expand-small'}" aria-hidden="true"></d2l-icon>`
|
649
|
-
: nothing}
|
647
|
+
${item.additionalContent ? html`<d2l-icon icon="${item.selected ? 'tier1:arrow-collapse-small' : 'tier1:arrow-expand-small'}" aria-hidden="true"></d2l-icon>` : nothing}
|
650
648
|
</div>
|
651
649
|
${item.additionalContent ? html`
|
652
650
|
<d2l-expand-collapse-content
|
@@ -658,9 +656,7 @@ class Filter extends FocusMixin(LocalizeCoreElement(RtlMixin(LitElement))) {
|
|
658
656
|
` : nothing}
|
659
657
|
</div>
|
660
658
|
</d2l-list-item>
|
661
|
-
${item.additionalContent && item.selected && this._displayKeyboardTooltip
|
662
|
-
? html`<d2l-tooltip align="start" announced for="${itemId}" for-type="descriptor" @d2l-tooltip-hide="${this._handleTooltipHide}">${this.localizeHTML('components.filter.additionalContentTooltip')}</d2l-tooltip>`
|
663
|
-
: nothing}
|
659
|
+
${item.additionalContent && item.selected && this._displayKeyboardTooltip ? html`<d2l-tooltip align="start" announced for="${itemId}" for-type="descriptor" @d2l-tooltip-hide="${this._handleTooltipHide}">${this.localizeHTML('components.filter.additionalContentTooltip')}</d2l-tooltip>` : nothing}
|
664
660
|
`;
|
665
661
|
}
|
666
662
|
|
package/custom-elements.json
CHANGED
@@ -1982,6 +1982,31 @@
|
|
1982
1982
|
}
|
1983
1983
|
]
|
1984
1984
|
},
|
1985
|
+
{
|
1986
|
+
"name": "d2l-dialog-demo-async-content-until",
|
1987
|
+
"path": "./components/dialog/demo/dialog-async-content-until.js",
|
1988
|
+
"attributes": [
|
1989
|
+
{
|
1990
|
+
"name": "href",
|
1991
|
+
"type": "string"
|
1992
|
+
}
|
1993
|
+
],
|
1994
|
+
"properties": [
|
1995
|
+
{
|
1996
|
+
"name": "href",
|
1997
|
+
"attribute": "href",
|
1998
|
+
"type": "string"
|
1999
|
+
},
|
2000
|
+
{
|
2001
|
+
"name": "loadingComplete",
|
2002
|
+
"type": "Promise<any>"
|
2003
|
+
},
|
2004
|
+
{
|
2005
|
+
"name": "resolveLoadingComplete",
|
2006
|
+
"type": "() => void"
|
2007
|
+
}
|
2008
|
+
]
|
2009
|
+
},
|
1985
2010
|
{
|
1986
2011
|
"name": "d2l-dialog-demo-async-content",
|
1987
2012
|
"path": "./components/dialog/demo/dialog-async-content.js",
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@brightspace-ui/core",
|
3
|
-
"version": "3.
|
3
|
+
"version": "3.101.0",
|
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",
|