@brightspace-ui/core 2.35.3 → 2.37.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/empty-state/README.md +68 -28
- package/components/empty-state/demo/empty-state.html +34 -12
- package/components/empty-state/empty-state-action-button.js +100 -0
- package/components/empty-state/empty-state-action-link.js +73 -0
- package/components/empty-state/{empty-state-illustrated-mixin.js → empty-state-illustrated.js} +43 -16
- package/components/empty-state/{empty-state-simple-button.js → empty-state-simple.js} +7 -28
- package/components/empty-state/empty-state-styles.js +19 -18
- package/components/html-block/demo/html-block.html +12 -0
- package/components/html-block/html-block.js +4 -4
- package/custom-elements.json +56 -132
- package/helpers/mathjax.js +12 -12
- package/package.json +1 -1
- package/components/empty-state/empty-state-illustrated-button.js +0 -71
- package/components/empty-state/empty-state-illustrated-link.js +0 -57
- package/components/empty-state/empty-state-simple-link.js +0 -74
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
# Empty State
|
|
2
|
+
|
|
2
3
|
Empty state components are used to convey that there is no data available to be displayed, or that a search or filter has returned no results.
|
|
3
4
|
|
|
4
5
|
<!-- docs: demo align:start -->
|
|
5
6
|
```html
|
|
6
7
|
<script type="module">
|
|
7
|
-
import '@brightspace-ui/core/components/empty-state/empty-state-
|
|
8
|
-
import '@brightspace-ui/core/components/empty-state/empty-state-illustrated
|
|
8
|
+
import '@brightspace-ui/core/components/empty-state/empty-state-action-link.js';
|
|
9
|
+
import '@brightspace-ui/core/components/empty-state/empty-state-illustrated.js';
|
|
10
|
+
import '@brightspace-ui/core/components/empty-state/empty-state-simple.js';
|
|
9
11
|
</script>
|
|
10
12
|
<style>
|
|
11
13
|
body {
|
|
12
14
|
overflow-y: scroll;
|
|
13
15
|
}
|
|
14
|
-
d2l-empty-state-illustrated
|
|
15
|
-
d2l-empty-state-simple
|
|
16
|
+
d2l-empty-state-illustrated,
|
|
17
|
+
d2l-empty-state-simple {
|
|
16
18
|
max-width: 500px;
|
|
17
19
|
width: 100%;
|
|
18
20
|
}
|
|
19
21
|
</style>
|
|
20
22
|
|
|
21
|
-
<d2l-empty-state-simple
|
|
22
|
-
<d2l-empty-state-
|
|
23
|
-
|
|
23
|
+
<d2l-empty-state-simple description="There are no assignments to display.">
|
|
24
|
+
<d2l-empty-state-action-link text="Create an Assignment" href="#"></d2l-empty-state-action-link>
|
|
25
|
+
</d2l-empty-state-simple>
|
|
26
|
+
<d2l-empty-state-illustrated illustration-name="desert-road" title-text="No Learning Paths Yet" description="Get started by clicking below to create your first learning path.">
|
|
27
|
+
<d2l-empty-state-action-link text="Create Learning Paths" href="#"></d2l-empty-state-action-link>
|
|
28
|
+
</d2l-empty-state-illustrated>
|
|
24
29
|
```
|
|
25
30
|
|
|
26
31
|
## Best Practices
|
|
@@ -40,67 +45,102 @@ Empty state components are used to convey that there is no data available to be
|
|
|
40
45
|
<!-- docs: end donts -->
|
|
41
46
|
<!-- docs: end best practices -->
|
|
42
47
|
|
|
43
|
-
## Empty State Simple
|
|
48
|
+
## Empty State Simple [d2l-empty-state-simple]
|
|
44
49
|
|
|
45
|
-
The `d2l-empty-state-simple
|
|
50
|
+
The `d2l-empty-state-simple` component is an empty state component that displays a description. An [empty state action component](#d2l-empty-state-action-button) can be placed inside of the default slot to add an optional action.
|
|
46
51
|
|
|
47
|
-
<!-- docs: demo live name:d2l-empty-state-simple
|
|
52
|
+
<!-- docs: demo live name:d2l-empty-state-simple -->
|
|
48
53
|
```html
|
|
49
54
|
<script type="module">
|
|
50
|
-
import '@brightspace-ui/core/components/empty-state/empty-state-simple
|
|
55
|
+
import '@brightspace-ui/core/components/empty-state/empty-state-simple.js';
|
|
51
56
|
</script>
|
|
52
57
|
|
|
53
|
-
<d2l-empty-state-simple
|
|
58
|
+
<d2l-empty-state-simple description="There are no assignments to display."></d2l-empty-state-simple>
|
|
54
59
|
```
|
|
55
60
|
|
|
56
|
-
## Empty State
|
|
61
|
+
## Empty State Illustrated [d2l-empty-state-illustrated]
|
|
62
|
+
|
|
63
|
+
The `d2l-empty-state-illustrated` component is an empty state component that displays a title and description with an illustration. An [empty state action component](#d2l-empty-state-action-button) can be placed inside of the default slot to add an optional action.
|
|
57
64
|
|
|
58
|
-
The `
|
|
65
|
+
The `illustration-name` property can be set to use one of the preset illustrations or a custom SVG illustration can be added in the `illustration` slot. The catalogue of preset empty state illustrations can be found [here](#preset-empty-state-illustrations).
|
|
59
66
|
|
|
60
|
-
<!-- docs: demo live name:d2l-empty-state-
|
|
67
|
+
<!-- docs: demo live name:d2l-empty-state-illustrated -->
|
|
61
68
|
```html
|
|
62
69
|
<script type="module">
|
|
63
|
-
import '@brightspace-ui/core/components/empty-state/empty-state-
|
|
70
|
+
import '@brightspace-ui/core/components/empty-state/empty-state-illustrated.js';
|
|
64
71
|
</script>
|
|
65
|
-
|
|
66
|
-
<
|
|
72
|
+
<!-- docs: start hidden content -->
|
|
73
|
+
<style>
|
|
74
|
+
body {
|
|
75
|
+
overflow-y: scroll;
|
|
76
|
+
}
|
|
77
|
+
</style>
|
|
78
|
+
<!-- docs: end hidden content -->
|
|
79
|
+
<d2l-empty-state-illustrated illustration-name="desert-road" title-text="No Learning Paths Yet" description="Get started by clicking below to create your first learning path."></d2l-empty-state-illustrated>
|
|
67
80
|
```
|
|
68
|
-
## Empty State Illustrated Button [d2l-empty-state-illustrated-button]
|
|
69
81
|
|
|
70
|
-
|
|
82
|
+
## Empty State Action Button [d2l-empty-state-action-button]
|
|
83
|
+
|
|
84
|
+
`d2l-empty-state-action-button` is an empty state action component that can be placed inside of the default slot of `empty-state-simple` or `empty-state-illustrated` to add a button action to the component. Only a single action can be placed within an empty state component.
|
|
85
|
+
|
|
86
|
+
The `primary` attribute can be set to render a primary button in place of the default subtle button. Note that the `primary` attribute is only valid when placed within `empty-state-illustrated` components and will have no effect on `empty-state-simple`.
|
|
71
87
|
|
|
72
|
-
<!-- docs: demo live name:d2l-empty-state-
|
|
88
|
+
<!-- docs: demo live name:d2l-empty-state-action-button -->
|
|
73
89
|
```html
|
|
74
90
|
<script type="module">
|
|
75
|
-
import '@brightspace-ui/core/components/empty-state/empty-state-
|
|
91
|
+
import '@brightspace-ui/core/components/empty-state/empty-state-action-button.js';
|
|
92
|
+
import '@brightspace-ui/core/components/empty-state/empty-state-illustrated.js';
|
|
93
|
+
import '@brightspace-ui/core/components/empty-state/empty-state-simple.js';
|
|
76
94
|
</script>
|
|
77
95
|
<!-- docs: start hidden content -->
|
|
78
96
|
<style>
|
|
79
97
|
body {
|
|
80
98
|
overflow-y: scroll;
|
|
81
99
|
}
|
|
100
|
+
d2l-empty-state-illustrated,
|
|
101
|
+
d2l-empty-state-simple {
|
|
102
|
+
max-width: 500px;
|
|
103
|
+
width: 100%;
|
|
104
|
+
}
|
|
82
105
|
</style>
|
|
83
106
|
<!-- docs: end hidden content -->
|
|
84
|
-
<d2l-empty-state-
|
|
107
|
+
<d2l-empty-state-simple description="There are no assignments to display.">
|
|
108
|
+
<d2l-empty-state-action-button text="Create an Assignment"></d2l-empty-state-action-button>
|
|
109
|
+
</d2l-empty-state-simple>
|
|
110
|
+
<d2l-empty-state-illustrated illustration-name="desert-road" title-text="No Learning Paths Yet" description="Get started by clicking below to create your first learning path.">
|
|
111
|
+
<d2l-empty-state-action-button text="Create Learning Paths"></d2l-empty-state-action-button>
|
|
112
|
+
</d2l-empty-state-illustrated>
|
|
85
113
|
```
|
|
86
114
|
|
|
87
|
-
## Empty State
|
|
115
|
+
## Empty State Action Link [d2l-empty-state-action-link]
|
|
88
116
|
|
|
89
|
-
|
|
117
|
+
`d2l-empty-state-action-link` is an empty state action component that can be placed inside of the default slot of `empty-state-simple` or `empty-state-illustrated` to add a link action to the component. Only a single action can be placed within an empty state component.
|
|
90
118
|
|
|
91
|
-
<!-- docs: demo live name:d2l-empty-state-
|
|
119
|
+
<!-- docs: demo live name:d2l-empty-state-action-link -->
|
|
92
120
|
```html
|
|
93
121
|
<script type="module">
|
|
94
|
-
import '@brightspace-ui/core/components/empty-state/empty-state-
|
|
122
|
+
import '@brightspace-ui/core/components/empty-state/empty-state-action-link.js';
|
|
123
|
+
import '@brightspace-ui/core/components/empty-state/empty-state-illustrated.js';
|
|
124
|
+
import '@brightspace-ui/core/components/empty-state/empty-state-simple.js';
|
|
95
125
|
</script>
|
|
96
126
|
<!-- docs: start hidden content -->
|
|
97
127
|
<style>
|
|
98
128
|
body {
|
|
99
129
|
overflow-y: scroll;
|
|
100
130
|
}
|
|
131
|
+
d2l-empty-state-illustrated,
|
|
132
|
+
d2l-empty-state-simple {
|
|
133
|
+
max-width: 500px;
|
|
134
|
+
width: 100%;
|
|
135
|
+
}
|
|
101
136
|
</style>
|
|
102
137
|
<!-- docs: end hidden content -->
|
|
103
|
-
<d2l-empty-state-
|
|
138
|
+
<d2l-empty-state-simple description="There are no assignments to display.">
|
|
139
|
+
<d2l-empty-state-action-link text="Create an Assignment" href="#"></d2l-empty-state-action-link>
|
|
140
|
+
</d2l-empty-state-simple>
|
|
141
|
+
<d2l-empty-state-illustrated illustration-name="desert-road" title-text="No Learning Paths Yet" description="Get started by clicking below to create your first learning path.">
|
|
142
|
+
<d2l-empty-state-action-link text="Create Learning Paths" href="#"></d2l-empty-state-action-link>
|
|
143
|
+
</d2l-empty-state-illustrated>
|
|
104
144
|
```
|
|
105
145
|
|
|
106
146
|
## Preset Empty State Illustrations
|
|
@@ -5,46 +5,68 @@
|
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<link rel="stylesheet" href="../../demo/styles.css" type="text/css">
|
|
7
7
|
<script type="module">
|
|
8
|
+
import '../empty-state-action-button.js';
|
|
9
|
+
import '../empty-state-action-link.js';
|
|
10
|
+
import '../empty-state-illustrated.js';
|
|
11
|
+
import '../empty-state-simple.js';
|
|
8
12
|
import '../../demo/demo-page.js';
|
|
9
|
-
import '../empty-state-simple-button.js';
|
|
10
|
-
import '../empty-state-simple-link.js';
|
|
11
|
-
import '../empty-state-illustrated-button.js';
|
|
12
|
-
import '../empty-state-illustrated-link.js';
|
|
13
13
|
</script>
|
|
14
14
|
</head>
|
|
15
15
|
<body unresolved>
|
|
16
16
|
|
|
17
17
|
<d2l-demo-page page-title="d2l-empty-state">
|
|
18
18
|
|
|
19
|
-
<h2>Empty State Simple
|
|
19
|
+
<h2>Empty State Simple</h2>
|
|
20
20
|
|
|
21
|
+
<h5>No Action</h5>
|
|
21
22
|
<d2l-demo-snippet>
|
|
22
23
|
<template>
|
|
23
|
-
<d2l-empty-state-simple
|
|
24
|
+
<d2l-empty-state-simple description="There are no assignments to display."></d2l-empty-state-simple>
|
|
24
25
|
</template>
|
|
25
26
|
</d2l-demo-snippet>
|
|
26
27
|
|
|
27
|
-
<
|
|
28
|
+
<h5>Empty State Action Button</h5>
|
|
29
|
+
<d2l-demo-snippet>
|
|
30
|
+
<template>
|
|
31
|
+
<d2l-empty-state-simple description="There are no assignments to display.">
|
|
32
|
+
<d2l-empty-state-action-button text="Create New Assignment"></d2l-empty-state-action-button>
|
|
33
|
+
</d2l-empty-state-simple>
|
|
34
|
+
</template>
|
|
35
|
+
</d2l-demo-snippet>
|
|
28
36
|
|
|
37
|
+
<h5>Empty State Action Link</h5>
|
|
29
38
|
<d2l-demo-snippet>
|
|
30
39
|
<template>
|
|
31
|
-
<d2l-empty-state-simple
|
|
40
|
+
<d2l-empty-state-simple description="There are no assignments to display.">
|
|
41
|
+
<d2l-empty-state-action-link text="Create New Assignment" href="https://d2l.com"></d2l-empty-state-action-link>
|
|
42
|
+
</d2l-empty-state-simple>
|
|
32
43
|
</template>
|
|
33
44
|
</d2l-demo-snippet>
|
|
34
45
|
|
|
35
|
-
<h2>Empty State Illustrated
|
|
46
|
+
<h2>Empty State Illustrated</h2>
|
|
36
47
|
|
|
48
|
+
<h5>No Action</h5>
|
|
37
49
|
<d2l-demo-snippet>
|
|
38
50
|
<template>
|
|
39
|
-
<d2l-empty-state-illustrated
|
|
51
|
+
<d2l-empty-state-illustrated illustration-name="fish-hook" title-text="No Learning Paths Yet" description="Get started by clicking below to create your first learning path."></d2l-empty-state-illustrated>
|
|
40
52
|
</template>
|
|
41
53
|
</d2l-demo-snippet>
|
|
42
54
|
|
|
43
|
-
<
|
|
55
|
+
<h5>Empty State Action Button</h5>
|
|
56
|
+
<d2l-demo-snippet>
|
|
57
|
+
<template>
|
|
58
|
+
<d2l-empty-state-illustrated illustration-name="fish-hook" title-text="No Learning Paths Yet" description="Get started by clicking below to create your first learning path.">
|
|
59
|
+
<d2l-empty-state-action-button text="Create Learning Paths" primary></d2l-empty-state-action-button>
|
|
60
|
+
</d2l-empty-state-illustrated>
|
|
61
|
+
</template>
|
|
62
|
+
</d2l-demo-snippet>
|
|
44
63
|
|
|
64
|
+
<h5>Empty State Action Link</h5>
|
|
45
65
|
<d2l-demo-snippet>
|
|
46
66
|
<template>
|
|
47
|
-
<d2l-empty-state-illustrated
|
|
67
|
+
<d2l-empty-state-illustrated illustration-name="fish-hook" title-text="No Learning Paths Yet" description="Get started by clicking below to create your first learning path.">
|
|
68
|
+
<d2l-empty-state-action-link text="Create Learning Paths" href="https://d2l.com"></d2l-empty-state-action-link>
|
|
69
|
+
</d2l-empty-state-illustrated>
|
|
48
70
|
</template>
|
|
49
71
|
</d2l-demo-snippet>
|
|
50
72
|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import '../button/button.js';
|
|
2
|
+
import '../button/button-subtle.js';
|
|
3
|
+
import { css, html, LitElement, nothing } from 'lit';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `d2l-empty-state-action-button` is an empty state action component that can be placed inside of the default slot of `empty-state-simple` or `empty-state-illustrated` to add a button action to the component.
|
|
7
|
+
* @fires d2l-empty-state-action - Dispatched when the action button is clicked
|
|
8
|
+
*/
|
|
9
|
+
class EmptyStateActionButton extends LitElement {
|
|
10
|
+
|
|
11
|
+
static get properties() {
|
|
12
|
+
return {
|
|
13
|
+
/**
|
|
14
|
+
* REQUIRED: The action text to be used in the button
|
|
15
|
+
* @type {string}
|
|
16
|
+
*/
|
|
17
|
+
text: { type: String },
|
|
18
|
+
/**
|
|
19
|
+
* This will change the action button to use a primary button instead of the default subtle button. The primary attribute is only valid when `d2l-empty-state-action-button` is placed within `d2l-empty-state-illustrated` components
|
|
20
|
+
* @type {boolean}
|
|
21
|
+
*/
|
|
22
|
+
primary: { type: Boolean },
|
|
23
|
+
_illustrated: { state: true }
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static get styles() {
|
|
28
|
+
return css`
|
|
29
|
+
.d2l-empty-state-action {
|
|
30
|
+
vertical-align: top;
|
|
31
|
+
}
|
|
32
|
+
`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
constructor() {
|
|
36
|
+
super();
|
|
37
|
+
this._illustrated = false;
|
|
38
|
+
this._missingTextErrorHasBeenThrown = false;
|
|
39
|
+
this._validatingTextTimeout = null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
connectedCallback() {
|
|
43
|
+
super.connectedCallback();
|
|
44
|
+
requestAnimationFrame(() => {
|
|
45
|
+
const e = new CustomEvent('d2l-empty-state-illustrated-check', {
|
|
46
|
+
bubbles: true,
|
|
47
|
+
detail: {}
|
|
48
|
+
});
|
|
49
|
+
this.dispatchEvent(e);
|
|
50
|
+
this._illustrated = e.detail.illustrated | false;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
firstUpdated(changedProperties) {
|
|
55
|
+
super.firstUpdated(changedProperties);
|
|
56
|
+
this._validateText();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
render() {
|
|
60
|
+
let actionButton = nothing;
|
|
61
|
+
if (this.text) {
|
|
62
|
+
actionButton = this._illustrated && this.primary
|
|
63
|
+
? html`<d2l-button
|
|
64
|
+
class="d2l-empty-state-action"
|
|
65
|
+
@click=${this._handleActionClick}
|
|
66
|
+
primary>
|
|
67
|
+
${this.text}
|
|
68
|
+
</d2l-button>`
|
|
69
|
+
: html`<d2l-button-subtle
|
|
70
|
+
class="d2l-empty-state-action"
|
|
71
|
+
@click=${this._handleActionClick}
|
|
72
|
+
?slim=${!this._illustrated}
|
|
73
|
+
text=${this.text}>
|
|
74
|
+
</d2l-button-subtle>`;
|
|
75
|
+
}
|
|
76
|
+
return html`${actionButton}`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
_handleActionClick(e) {
|
|
80
|
+
e.stopPropagation();
|
|
81
|
+
this.dispatchEvent(new CustomEvent('d2l-empty-state-action'));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
_validateText() {
|
|
85
|
+
clearTimeout(this._validatingTextTimeout);
|
|
86
|
+
// don't error immediately in case it doesn't get set immediately
|
|
87
|
+
this._validatingTextTimeout = setTimeout(() => {
|
|
88
|
+
this._validatingTextTimeout = null;
|
|
89
|
+
const hasText = (typeof this.text === 'string') && this.text.length > 0;
|
|
90
|
+
|
|
91
|
+
if (!hasText && !this._missingTextErrorHasBeenThrown) {
|
|
92
|
+
this._missingTextErrorHasBeenThrown = true;
|
|
93
|
+
setTimeout(() => { throw new Error('<d2l-empty-state-action-button>: missing required "text" attribute.'); });
|
|
94
|
+
}
|
|
95
|
+
}, 3000);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
customElements.define('d2l-empty-state-action-button', EmptyStateActionButton);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { html, LitElement, nothing } from 'lit';
|
|
2
|
+
import { bodyCompactStyles } from '../typography/styles.js';
|
|
3
|
+
import { linkStyles } from '../link/link.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `d2l-empty-state-action-link` is an empty state action component that can be placed inside of the default slot of `empty-state-simple` or `empty-state-illustrated` to add a link action to the component.
|
|
7
|
+
*/
|
|
8
|
+
class EmptyStateActionLink extends LitElement {
|
|
9
|
+
|
|
10
|
+
static get properties() {
|
|
11
|
+
return {
|
|
12
|
+
/**
|
|
13
|
+
* REQUIRED: The action text to be used in the subtle button
|
|
14
|
+
* @type {string}
|
|
15
|
+
*/
|
|
16
|
+
text: { type: String },
|
|
17
|
+
/**
|
|
18
|
+
* REQUIRED: The action URL or URL fragment of the link
|
|
19
|
+
* @type {string}
|
|
20
|
+
*/
|
|
21
|
+
href: { type: String },
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static get styles() {
|
|
26
|
+
return [bodyCompactStyles, linkStyles];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
constructor() {
|
|
30
|
+
super();
|
|
31
|
+
this._missingHrefErrorHasBeenThrown = false;
|
|
32
|
+
this._missingTextErrorHasBeenThrown = false;
|
|
33
|
+
this._validatingAttributesTimeout = null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
firstUpdated(changedProperties) {
|
|
37
|
+
super.firstUpdated(changedProperties);
|
|
38
|
+
this._validateAttributes();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
render() {
|
|
42
|
+
const actionLink = this.text && this.href
|
|
43
|
+
? html`
|
|
44
|
+
<a class="d2l-body-compact d2l-link" href=${this.href}>${this.text}</a>`
|
|
45
|
+
: nothing;
|
|
46
|
+
|
|
47
|
+
return html`${actionLink}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
_validateAttributes() {
|
|
51
|
+
clearTimeout(this._validatingAttributesTimeout);
|
|
52
|
+
// don't error immediately in case it doesn't get set immediately
|
|
53
|
+
this._validatingAttributesTimeout = setTimeout(() => {
|
|
54
|
+
this._validatingAttributesTimeout = null;
|
|
55
|
+
|
|
56
|
+
const hasHref = (typeof this.href === 'string') && this.href.length > 0;
|
|
57
|
+
const hasText = (typeof this.text === 'string') && this.text.length > 0;
|
|
58
|
+
|
|
59
|
+
if (!hasHref && !this._missingHrefErrorHasBeenThrown) {
|
|
60
|
+
this._missingHrefErrorHasBeenThrown = true;
|
|
61
|
+
setTimeout(() => { throw new Error('<d2l-empty-state-action-link>: missing required "href" attribute.'); });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!hasText && !this._missingTextErrorHasBeenThrown) {
|
|
65
|
+
this._missingTextErrorHasBeenThrown = true;
|
|
66
|
+
setTimeout(() => { throw new Error('<d2l-empty-state-action-link>: missing required "text" attribute.'); });
|
|
67
|
+
}
|
|
68
|
+
}, 3000);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
customElements.define('d2l-empty-state-action-link', EmptyStateActionLink);
|
package/components/empty-state/{empty-state-illustrated-mixin.js → empty-state-illustrated.js}
RENAMED
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import { emptyStateIllustratedStyles, emptyStateStyles } from './empty-state-styles.js';
|
|
2
|
-
import { html, nothing } from 'lit';
|
|
2
|
+
import { html, LitElement, nothing } from 'lit';
|
|
3
3
|
import { bodyCompactStyles } from '../typography/styles.js';
|
|
4
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
4
5
|
import { loadSvg } from '../../generated/empty-state/presetIllustrationLoader.js';
|
|
5
6
|
import ResizeObserver from 'resize-observer-polyfill/dist/ResizeObserver.es.js';
|
|
6
|
-
import {
|
|
7
|
+
import { runAsync } from '../../directives/run-async/run-async.js';
|
|
8
|
+
import { styleMap } from 'lit/directives/style-map.js';
|
|
7
9
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
8
10
|
|
|
9
11
|
const illustrationAspectRatio = 500 / 330;
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
/**
|
|
14
|
+
* The `d2l-empty-state-illustrated` component is an empty state component that displays a title and description with an illustration. An empty state action component can be placed inside of the default slot to add an optional action.
|
|
15
|
+
* @slot - Slot for empty state actions
|
|
16
|
+
* @slot illustration - Slot for custom SVG content if `illustration-name` property is not set
|
|
17
|
+
*/
|
|
18
|
+
class EmptyStateIllustrated extends LitElement {
|
|
12
19
|
|
|
13
20
|
static get properties() {
|
|
14
21
|
return {
|
|
15
|
-
/**
|
|
16
|
-
* The action text to be used in the subtle button
|
|
17
|
-
* @type {string}
|
|
18
|
-
*/
|
|
19
|
-
actionText: { type: String, attribute: 'action-text' },
|
|
20
22
|
/**
|
|
21
23
|
* REQUIRED: A description giving details about the empty state
|
|
22
24
|
* @type {string}
|
|
@@ -33,7 +35,6 @@ export const EmptyStateIllustratedMixin = superclass => class extends RtlMixin(s
|
|
|
33
35
|
*/
|
|
34
36
|
titleText: { type: String, attribute: 'title-text' },
|
|
35
37
|
_contentHeight: { state: true },
|
|
36
|
-
_illustratedComponentType: { state: true },
|
|
37
38
|
_titleSmall: { state: true }
|
|
38
39
|
};
|
|
39
40
|
}
|
|
@@ -44,7 +45,6 @@ export const EmptyStateIllustratedMixin = superclass => class extends RtlMixin(s
|
|
|
44
45
|
|
|
45
46
|
constructor() {
|
|
46
47
|
super();
|
|
47
|
-
|
|
48
48
|
this._contentHeight = 330;
|
|
49
49
|
this._missingDescriptionErrorHasBeenThrown = false;
|
|
50
50
|
this._missingTitleTextErrorHasBeenThrown = false;
|
|
@@ -55,11 +55,13 @@ export const EmptyStateIllustratedMixin = superclass => class extends RtlMixin(s
|
|
|
55
55
|
|
|
56
56
|
connectedCallback() {
|
|
57
57
|
super.connectedCallback();
|
|
58
|
+
this.addEventListener('d2l-empty-state-illustrated-check', this._handleEmptyStateIllustratedCheck);
|
|
58
59
|
this._resizeObserver.observe(this);
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
disconnectedCallback() {
|
|
62
63
|
super.disconnectedCallback();
|
|
64
|
+
this.removeEventListener('d2l-empty-state-illustrated-check', this._handleEmptyStateIllustratedCheck);
|
|
63
65
|
this._resizeObserver.disconnect();
|
|
64
66
|
}
|
|
65
67
|
|
|
@@ -68,7 +70,25 @@ export const EmptyStateIllustratedMixin = superclass => class extends RtlMixin(s
|
|
|
68
70
|
this._validateAttributes();
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
|
|
73
|
+
render() {
|
|
74
|
+
const illustrationContainerStyle = this._getIllustrationContainerStyle();
|
|
75
|
+
const titleClass = this._getTitleClass();
|
|
76
|
+
|
|
77
|
+
return html`
|
|
78
|
+
${this.illustrationName
|
|
79
|
+
? html`
|
|
80
|
+
<div style="${styleMap(illustrationContainerStyle)}">
|
|
81
|
+
${runAsync(this.illustrationName, () => this._getIllustration(this.illustrationName), { success: (illustration) => illustration }, { pendingState: false })}
|
|
82
|
+
</div>`
|
|
83
|
+
: html`<slot class="illustration-slot" name="illustration"></slot>`}
|
|
84
|
+
|
|
85
|
+
<p class="${classMap(titleClass)}">${this.titleText}</p>
|
|
86
|
+
<p class="d2l-body-compact d2l-empty-state-description">${this.description}</p>
|
|
87
|
+
<slot class="action-slot"></slot>
|
|
88
|
+
`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async _getIllustration(illustrationName) {
|
|
72
92
|
if (!illustrationName) return;
|
|
73
93
|
|
|
74
94
|
const svg = await loadSvg(illustrationName);
|
|
@@ -78,13 +98,13 @@ export const EmptyStateIllustratedMixin = superclass => class extends RtlMixin(s
|
|
|
78
98
|
return svg ? html`${unsafeSVG(svg.val)}` : nothing;
|
|
79
99
|
}
|
|
80
100
|
|
|
81
|
-
|
|
101
|
+
_getIllustrationContainerStyle() {
|
|
82
102
|
return {
|
|
83
103
|
height: `${this._contentHeight}px`,
|
|
84
104
|
};
|
|
85
105
|
}
|
|
86
106
|
|
|
87
|
-
|
|
107
|
+
_getTitleClass() {
|
|
88
108
|
return {
|
|
89
109
|
'd2l-empty-state-title': true,
|
|
90
110
|
'd2l-empty-state-title-small': this._titleSmall,
|
|
@@ -92,6 +112,11 @@ export const EmptyStateIllustratedMixin = superclass => class extends RtlMixin(s
|
|
|
92
112
|
};
|
|
93
113
|
}
|
|
94
114
|
|
|
115
|
+
_handleEmptyStateIllustratedCheck(e) {
|
|
116
|
+
e.stopPropagation();
|
|
117
|
+
e.detail.illustrated = true;
|
|
118
|
+
}
|
|
119
|
+
|
|
95
120
|
_onResize(entries) {
|
|
96
121
|
if (!entries || entries.length === 0) return;
|
|
97
122
|
const entry = entries[0];
|
|
@@ -110,17 +135,19 @@ export const EmptyStateIllustratedMixin = superclass => class extends RtlMixin(s
|
|
|
110
135
|
if (!hasTitleText && !this._missingTitleTextErrorHasBeenThrown) {
|
|
111
136
|
this._missingTitleTextErrorHasBeenThrown = true;
|
|
112
137
|
setTimeout(() => {
|
|
113
|
-
throw new Error(
|
|
138
|
+
throw new Error('<d2l-empty-state-illustrated>: missing required "titleText" attribute.');
|
|
114
139
|
});
|
|
115
140
|
}
|
|
116
141
|
|
|
117
142
|
if (!hasDescription && !this._missingDescriptionErrorHasBeenThrown) {
|
|
118
143
|
this._missingDescriptionErrorHasBeenThrown = true;
|
|
119
144
|
setTimeout(() => {
|
|
120
|
-
throw new Error(
|
|
145
|
+
throw new Error('<d2l-empty-state-illustrated>: missing required "description" attribute.');
|
|
121
146
|
});
|
|
122
147
|
}
|
|
123
148
|
}, 3000);
|
|
124
149
|
}
|
|
125
150
|
|
|
126
|
-
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
customElements.define('d2l-empty-state-illustrated', EmptyStateIllustrated);
|
|
@@ -1,22 +1,17 @@
|
|
|
1
1
|
import '../button/button-subtle.js';
|
|
2
2
|
import { emptyStateSimpleStyles, emptyStateStyles } from './empty-state-styles.js';
|
|
3
|
-
import { html, LitElement
|
|
3
|
+
import { html, LitElement } from 'lit';
|
|
4
4
|
import { bodyCompactStyles } from '../typography/styles.js';
|
|
5
5
|
import { RtlMixin } from '../../mixins/rtl-mixin.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* The `d2l-empty-state-simple
|
|
9
|
-
* @
|
|
8
|
+
* The `d2l-empty-state-simple` component is an empty state component that displays a description. An empty state action component can be placed inside of the default slot to add an optional action.
|
|
9
|
+
* @slot - Slot for empty state actions
|
|
10
10
|
*/
|
|
11
|
-
class
|
|
11
|
+
class EmptyStateSimple extends RtlMixin(LitElement) {
|
|
12
12
|
|
|
13
13
|
static get properties() {
|
|
14
14
|
return {
|
|
15
|
-
/**
|
|
16
|
-
* The action text to be used in the subtle button
|
|
17
|
-
* @type {string}
|
|
18
|
-
*/
|
|
19
|
-
actionText: { type: String, attribute: 'action-text' },
|
|
20
15
|
/**
|
|
21
16
|
* REQUIRED: A description giving details about the empty state
|
|
22
17
|
* @type {string}
|
|
@@ -41,28 +36,12 @@ class EmptyStateSimpleButton extends RtlMixin(LitElement) {
|
|
|
41
36
|
}
|
|
42
37
|
|
|
43
38
|
render() {
|
|
44
|
-
const actionButton = this.actionText
|
|
45
|
-
? html`
|
|
46
|
-
<d2l-button-subtle
|
|
47
|
-
class="d2l-empty-state-action"
|
|
48
|
-
@click=${this._handleActionClick}
|
|
49
|
-
h-align="text"
|
|
50
|
-
text=${this.actionText}
|
|
51
|
-
slim>
|
|
52
|
-
</d2l-button-subtle>`
|
|
53
|
-
: nothing;
|
|
54
|
-
|
|
55
39
|
return html`
|
|
56
40
|
<p class="d2l-body-compact d2l-empty-state-description">${this.description}</p>
|
|
57
|
-
|
|
41
|
+
<slot class="action-slot"></slot>
|
|
58
42
|
`;
|
|
59
43
|
}
|
|
60
44
|
|
|
61
|
-
_handleActionClick(e) {
|
|
62
|
-
e.stopPropagation();
|
|
63
|
-
this.dispatchEvent(new CustomEvent('d2l-empty-state-action'));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
45
|
_validateDescription() {
|
|
67
46
|
clearTimeout(this._validatingDescriptionTimeout);
|
|
68
47
|
// don't error immediately in case it doesn't get set immediately
|
|
@@ -72,11 +51,11 @@ class EmptyStateSimpleButton extends RtlMixin(LitElement) {
|
|
|
72
51
|
|
|
73
52
|
if (!hasDescription && !this._missingDescriptionErrorHasBeenThrown) {
|
|
74
53
|
this._missingDescriptionErrorHasBeenThrown = true;
|
|
75
|
-
setTimeout(() => { throw new Error('<d2l-empty-state-simple
|
|
54
|
+
setTimeout(() => { throw new Error('<d2l-empty-state-simple>: missing required "description" attribute.'); });
|
|
76
55
|
}
|
|
77
56
|
}, 3000);
|
|
78
57
|
}
|
|
79
58
|
|
|
80
59
|
}
|
|
81
60
|
|
|
82
|
-
customElements.define('d2l-empty-state-simple
|
|
61
|
+
customElements.define('d2l-empty-state-simple', EmptyStateSimple);
|
|
@@ -14,6 +14,15 @@ export const emptyStateStyles = css`
|
|
|
14
14
|
display: none;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
.action-slot::slotted(*) {
|
|
18
|
+
display: none;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.action-slot::slotted(d2l-empty-state-action-button:first-child),
|
|
22
|
+
.action-slot::slotted(d2l-empty-state-action-link:first-child) {
|
|
23
|
+
display: inline-block;
|
|
24
|
+
}
|
|
25
|
+
|
|
17
26
|
`;
|
|
18
27
|
|
|
19
28
|
export const emptyStateSimpleStyles = css`
|
|
@@ -28,10 +37,6 @@ export const emptyStateSimpleStyles = css`
|
|
|
28
37
|
padding-right: 0.5rem;
|
|
29
38
|
}
|
|
30
39
|
|
|
31
|
-
.d2l-empty-state-action {
|
|
32
|
-
vertical-align: top;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
40
|
`;
|
|
36
41
|
|
|
37
42
|
export const emptyStateIllustratedStyles = css`
|
|
@@ -40,12 +45,16 @@ export const emptyStateIllustratedStyles = css`
|
|
|
40
45
|
text-align: center;
|
|
41
46
|
}
|
|
42
47
|
|
|
43
|
-
.
|
|
44
|
-
|
|
48
|
+
.illustration-slot::slotted(*) {
|
|
49
|
+
display: none;
|
|
45
50
|
}
|
|
46
51
|
|
|
47
|
-
.
|
|
48
|
-
|
|
52
|
+
.illustration-slot::slotted(svg:first-of-type) {
|
|
53
|
+
display: inline-block;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
svg {
|
|
57
|
+
height: 100%;
|
|
49
58
|
max-width: 500px;
|
|
50
59
|
width: 100%;
|
|
51
60
|
}
|
|
@@ -67,16 +76,8 @@ export const emptyStateIllustratedStyles = css`
|
|
|
67
76
|
margin-top: 0.5rem;
|
|
68
77
|
}
|
|
69
78
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
::slotted(svg:first-child) {
|
|
75
|
-
display: inline-block;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
svg {
|
|
79
|
-
height: 100%;
|
|
79
|
+
.d2l-empty-state-description {
|
|
80
|
+
margin: 0 auto 0.8rem;
|
|
80
81
|
max-width: 500px;
|
|
81
82
|
width: 100%;
|
|
82
83
|
}
|
|
@@ -122,6 +122,18 @@
|
|
|
122
122
|
</template>
|
|
123
123
|
</d2l-demo-snippet>
|
|
124
124
|
|
|
125
|
+
<h2>HTML Block (inline, no-deferred-rendering)</h2>
|
|
126
|
+
|
|
127
|
+
<d2l-demo-snippet>
|
|
128
|
+
<template>
|
|
129
|
+
<span>Here's an inline html-block:</span>
|
|
130
|
+
<d2l-html-block inline no-deferred-rendering>
|
|
131
|
+
I'm inline!
|
|
132
|
+
</d2l-html-block>
|
|
133
|
+
<span>Pretty cool!</span>
|
|
134
|
+
</template>
|
|
135
|
+
</d2l-demo-snippet>
|
|
136
|
+
|
|
125
137
|
<h2>HTML Block (large font)</h2>
|
|
126
138
|
|
|
127
139
|
<d2l-demo-snippet>
|
|
@@ -160,14 +160,14 @@ class HtmlBlock extends RtlMixin(LitElement) {
|
|
|
160
160
|
overflow-y: hidden;
|
|
161
161
|
text-align: left;
|
|
162
162
|
}
|
|
163
|
-
:host([hidden]),
|
|
164
|
-
:host([no-deferred-rendering]) div.d2l-html-block-rendered {
|
|
165
|
-
display: none;
|
|
166
|
-
}
|
|
167
163
|
:host([inline]),
|
|
168
164
|
:host([inline]) div.d2l-html-block-rendered {
|
|
169
165
|
display: inline;
|
|
170
166
|
}
|
|
167
|
+
:host([hidden]),
|
|
168
|
+
:host([no-deferred-rendering]) div.d2l-html-block-rendered {
|
|
169
|
+
display: none;
|
|
170
|
+
}
|
|
171
171
|
:host([dir="rtl"]) {
|
|
172
172
|
text-align: right;
|
|
173
173
|
}
|
package/custom-elements.json
CHANGED
|
@@ -2975,96 +2975,81 @@
|
|
|
2975
2975
|
"path": "./components/dropdown/test/dropdown-component.js"
|
|
2976
2976
|
},
|
|
2977
2977
|
{
|
|
2978
|
-
"name": "d2l-empty-state-
|
|
2979
|
-
"path": "./components/empty-state/empty-state-
|
|
2980
|
-
"description": "
|
|
2978
|
+
"name": "d2l-empty-state-action-button",
|
|
2979
|
+
"path": "./components/empty-state/empty-state-action-button.js",
|
|
2980
|
+
"description": "`d2l-empty-state-action-button` is an empty state action component that can be placed inside of the default slot of `empty-state-simple` or `empty-state-illustrated` to add a button action to the component.",
|
|
2981
2981
|
"attributes": [
|
|
2982
2982
|
{
|
|
2983
|
-
"name": "
|
|
2984
|
-
"description": "
|
|
2985
|
-
"type": "boolean"
|
|
2986
|
-
},
|
|
2987
|
-
{
|
|
2988
|
-
"name": "action-text",
|
|
2989
|
-
"description": "The action text to be used in the subtle button",
|
|
2990
|
-
"type": "string"
|
|
2991
|
-
},
|
|
2992
|
-
{
|
|
2993
|
-
"name": "description",
|
|
2994
|
-
"description": "REQUIRED: A description giving details about the empty state",
|
|
2995
|
-
"type": "string"
|
|
2996
|
-
},
|
|
2997
|
-
{
|
|
2998
|
-
"name": "illustration-name",
|
|
2999
|
-
"description": "The name of the preset image you would like to display in the component",
|
|
2983
|
+
"name": "text",
|
|
2984
|
+
"description": "REQUIRED: The action text to be used in the button",
|
|
3000
2985
|
"type": "string"
|
|
3001
2986
|
},
|
|
3002
2987
|
{
|
|
3003
|
-
"name": "
|
|
3004
|
-
"description": "
|
|
3005
|
-
"type": "
|
|
2988
|
+
"name": "primary",
|
|
2989
|
+
"description": "This will change the action button to use a primary button instead of the default subtle button. The primary attribute is only valid when `d2l-empty-state-action-button` is placed within `d2l-empty-state-illustrated` components",
|
|
2990
|
+
"type": "boolean"
|
|
3006
2991
|
}
|
|
3007
2992
|
],
|
|
3008
2993
|
"properties": [
|
|
3009
2994
|
{
|
|
3010
|
-
"name": "
|
|
3011
|
-
"attribute": "
|
|
3012
|
-
"description": "
|
|
3013
|
-
"type": "boolean"
|
|
3014
|
-
},
|
|
3015
|
-
{
|
|
3016
|
-
"name": "actionText",
|
|
3017
|
-
"attribute": "action-text",
|
|
3018
|
-
"description": "The action text to be used in the subtle button",
|
|
3019
|
-
"type": "string"
|
|
3020
|
-
},
|
|
3021
|
-
{
|
|
3022
|
-
"name": "description",
|
|
3023
|
-
"attribute": "description",
|
|
3024
|
-
"description": "REQUIRED: A description giving details about the empty state",
|
|
3025
|
-
"type": "string"
|
|
3026
|
-
},
|
|
3027
|
-
{
|
|
3028
|
-
"name": "illustrationName",
|
|
3029
|
-
"attribute": "illustration-name",
|
|
3030
|
-
"description": "The name of the preset image you would like to display in the component",
|
|
2995
|
+
"name": "text",
|
|
2996
|
+
"attribute": "text",
|
|
2997
|
+
"description": "REQUIRED: The action text to be used in the button",
|
|
3031
2998
|
"type": "string"
|
|
3032
2999
|
},
|
|
3033
3000
|
{
|
|
3034
|
-
"name": "
|
|
3035
|
-
"attribute": "
|
|
3036
|
-
"description": "
|
|
3037
|
-
"type": "
|
|
3001
|
+
"name": "primary",
|
|
3002
|
+
"attribute": "primary",
|
|
3003
|
+
"description": "This will change the action button to use a primary button instead of the default subtle button. The primary attribute is only valid when `d2l-empty-state-action-button` is placed within `d2l-empty-state-illustrated` components",
|
|
3004
|
+
"type": "boolean"
|
|
3038
3005
|
}
|
|
3039
3006
|
],
|
|
3040
3007
|
"events": [
|
|
3041
3008
|
{
|
|
3042
3009
|
"name": "d2l-empty-state-action",
|
|
3043
3010
|
"description": "Dispatched when the action button is clicked"
|
|
3044
|
-
}
|
|
3045
|
-
],
|
|
3046
|
-
"slots": [
|
|
3011
|
+
},
|
|
3047
3012
|
{
|
|
3048
|
-
"name": ""
|
|
3049
|
-
"description": "Custom SVG content if `illustration-name` property is not set"
|
|
3013
|
+
"name": "d2l-empty-state-illustrated-check"
|
|
3050
3014
|
}
|
|
3051
3015
|
]
|
|
3052
3016
|
},
|
|
3053
3017
|
{
|
|
3054
|
-
"name": "d2l-empty-state-
|
|
3055
|
-
"path": "./components/empty-state/empty-state-
|
|
3056
|
-
"description": "
|
|
3018
|
+
"name": "d2l-empty-state-action-link",
|
|
3019
|
+
"path": "./components/empty-state/empty-state-action-link.js",
|
|
3020
|
+
"description": "`d2l-empty-state-action-link` is an empty state action component that can be placed inside of the default slot of `empty-state-simple` or `empty-state-illustrated` to add a link action to the component.",
|
|
3057
3021
|
"attributes": [
|
|
3058
3022
|
{
|
|
3059
|
-
"name": "
|
|
3060
|
-
"description": "The action
|
|
3023
|
+
"name": "text",
|
|
3024
|
+
"description": "REQUIRED: The action text to be used in the subtle button",
|
|
3061
3025
|
"type": "string"
|
|
3062
3026
|
},
|
|
3063
3027
|
{
|
|
3064
|
-
"name": "
|
|
3065
|
-
"description": "The action
|
|
3028
|
+
"name": "href",
|
|
3029
|
+
"description": "REQUIRED: The action URL or URL fragment of the link",
|
|
3030
|
+
"type": "string"
|
|
3031
|
+
}
|
|
3032
|
+
],
|
|
3033
|
+
"properties": [
|
|
3034
|
+
{
|
|
3035
|
+
"name": "text",
|
|
3036
|
+
"attribute": "text",
|
|
3037
|
+
"description": "REQUIRED: The action text to be used in the subtle button",
|
|
3066
3038
|
"type": "string"
|
|
3067
3039
|
},
|
|
3040
|
+
{
|
|
3041
|
+
"name": "href",
|
|
3042
|
+
"attribute": "href",
|
|
3043
|
+
"description": "REQUIRED: The action URL or URL fragment of the link",
|
|
3044
|
+
"type": "string"
|
|
3045
|
+
}
|
|
3046
|
+
]
|
|
3047
|
+
},
|
|
3048
|
+
{
|
|
3049
|
+
"name": "d2l-empty-state-illustrated",
|
|
3050
|
+
"path": "./components/empty-state/empty-state-illustrated.js",
|
|
3051
|
+
"description": "The `d2l-empty-state-illustrated` component is an empty state component that displays a title and description with an illustration. An empty state action component can be placed inside of the default slot to add an optional action.",
|
|
3052
|
+
"attributes": [
|
|
3068
3053
|
{
|
|
3069
3054
|
"name": "description",
|
|
3070
3055
|
"description": "REQUIRED: A description giving details about the empty state",
|
|
@@ -3082,18 +3067,6 @@
|
|
|
3082
3067
|
}
|
|
3083
3068
|
],
|
|
3084
3069
|
"properties": [
|
|
3085
|
-
{
|
|
3086
|
-
"name": "actionHref",
|
|
3087
|
-
"attribute": "action-href",
|
|
3088
|
-
"description": "The action URL or URL fragment of the link",
|
|
3089
|
-
"type": "string"
|
|
3090
|
-
},
|
|
3091
|
-
{
|
|
3092
|
-
"name": "actionText",
|
|
3093
|
-
"attribute": "action-text",
|
|
3094
|
-
"description": "The action text to be used in the subtle button",
|
|
3095
|
-
"type": "string"
|
|
3096
|
-
},
|
|
3097
3070
|
{
|
|
3098
3071
|
"name": "description",
|
|
3099
3072
|
"attribute": "description",
|
|
@@ -3116,20 +3089,19 @@
|
|
|
3116
3089
|
"slots": [
|
|
3117
3090
|
{
|
|
3118
3091
|
"name": "",
|
|
3119
|
-
"description": "
|
|
3092
|
+
"description": "Slot for empty state actions"
|
|
3093
|
+
},
|
|
3094
|
+
{
|
|
3095
|
+
"name": "illustration",
|
|
3096
|
+
"description": "Slot for custom SVG content if `illustration-name` property is not set"
|
|
3120
3097
|
}
|
|
3121
3098
|
]
|
|
3122
3099
|
},
|
|
3123
3100
|
{
|
|
3124
|
-
"name": "d2l-empty-state-simple
|
|
3125
|
-
"path": "./components/empty-state/empty-state-simple
|
|
3126
|
-
"description": "The `d2l-empty-state-simple
|
|
3101
|
+
"name": "d2l-empty-state-simple",
|
|
3102
|
+
"path": "./components/empty-state/empty-state-simple.js",
|
|
3103
|
+
"description": "The `d2l-empty-state-simple` component is an empty state component that displays a description. An empty state action component can be placed inside of the default slot to add an optional action.",
|
|
3127
3104
|
"attributes": [
|
|
3128
|
-
{
|
|
3129
|
-
"name": "action-text",
|
|
3130
|
-
"description": "The action text to be used in the subtle button",
|
|
3131
|
-
"type": "string"
|
|
3132
|
-
},
|
|
3133
3105
|
{
|
|
3134
3106
|
"name": "description",
|
|
3135
3107
|
"description": "REQUIRED: A description giving details about the empty state",
|
|
@@ -3137,12 +3109,6 @@
|
|
|
3137
3109
|
}
|
|
3138
3110
|
],
|
|
3139
3111
|
"properties": [
|
|
3140
|
-
{
|
|
3141
|
-
"name": "actionText",
|
|
3142
|
-
"attribute": "action-text",
|
|
3143
|
-
"description": "The action text to be used in the subtle button",
|
|
3144
|
-
"type": "string"
|
|
3145
|
-
},
|
|
3146
3112
|
{
|
|
3147
3113
|
"name": "description",
|
|
3148
3114
|
"attribute": "description",
|
|
@@ -3150,52 +3116,10 @@
|
|
|
3150
3116
|
"type": "string"
|
|
3151
3117
|
}
|
|
3152
3118
|
],
|
|
3153
|
-
"
|
|
3154
|
-
{
|
|
3155
|
-
"name": "d2l-empty-state-action",
|
|
3156
|
-
"description": "Dispatched when the action button is clicked"
|
|
3157
|
-
}
|
|
3158
|
-
]
|
|
3159
|
-
},
|
|
3160
|
-
{
|
|
3161
|
-
"name": "d2l-empty-state-simple-link",
|
|
3162
|
-
"path": "./components/empty-state/empty-state-simple-link.js",
|
|
3163
|
-
"description": "The `d2l-empty-state-simple-link` component is an empty state component that displays a description and action link.",
|
|
3164
|
-
"attributes": [
|
|
3165
|
-
{
|
|
3166
|
-
"name": "action-href",
|
|
3167
|
-
"description": "The action URL or URL fragment of the link",
|
|
3168
|
-
"type": "string"
|
|
3169
|
-
},
|
|
3170
|
-
{
|
|
3171
|
-
"name": "action-text",
|
|
3172
|
-
"description": "The action text to be used in the link",
|
|
3173
|
-
"type": "string"
|
|
3174
|
-
},
|
|
3175
|
-
{
|
|
3176
|
-
"name": "description",
|
|
3177
|
-
"description": "REQUIRED: A description giving details about the empty state",
|
|
3178
|
-
"type": "string"
|
|
3179
|
-
}
|
|
3180
|
-
],
|
|
3181
|
-
"properties": [
|
|
3182
|
-
{
|
|
3183
|
-
"name": "actionHref",
|
|
3184
|
-
"attribute": "action-href",
|
|
3185
|
-
"description": "The action URL or URL fragment of the link",
|
|
3186
|
-
"type": "string"
|
|
3187
|
-
},
|
|
3188
|
-
{
|
|
3189
|
-
"name": "actionText",
|
|
3190
|
-
"attribute": "action-text",
|
|
3191
|
-
"description": "The action text to be used in the link",
|
|
3192
|
-
"type": "string"
|
|
3193
|
-
},
|
|
3119
|
+
"slots": [
|
|
3194
3120
|
{
|
|
3195
|
-
"name": "
|
|
3196
|
-
"
|
|
3197
|
-
"description": "REQUIRED: A description giving details about the empty state",
|
|
3198
|
-
"type": "string"
|
|
3121
|
+
"name": "",
|
|
3122
|
+
"description": "Slot for empty state actions"
|
|
3199
3123
|
}
|
|
3200
3124
|
]
|
|
3201
3125
|
},
|
package/helpers/mathjax.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const mathjaxContextAttribute = 'data-mathjax-context';
|
|
7
|
-
const mathjaxBaseUrl = 'https://s.brightspace.com/lib/mathjax/3.
|
|
7
|
+
const mathjaxBaseUrl = 'https://s.brightspace.com/lib/mathjax/3.2.2';
|
|
8
8
|
|
|
9
9
|
const mathjaxFontMappings = new Map([
|
|
10
10
|
['MJXTEX', 'MathJax_Main-Regular'],
|
|
@@ -31,6 +31,7 @@ const mathjaxFontMappings = new Map([
|
|
|
31
31
|
]);
|
|
32
32
|
|
|
33
33
|
let mathJaxLoaded;
|
|
34
|
+
let renderingPromise = Promise.resolve();
|
|
34
35
|
|
|
35
36
|
export class HtmlBlockMathRenderer {
|
|
36
37
|
|
|
@@ -70,7 +71,8 @@ export class HtmlBlockMathRenderer {
|
|
|
70
71
|
});
|
|
71
72
|
|
|
72
73
|
await window.MathJax.startup.promise;
|
|
73
|
-
window.MathJax.typesetShadow(elem.getRootNode(), elem);
|
|
74
|
+
renderingPromise = renderingPromise.then(() => window.MathJax.typesetShadow(elem.getRootNode(), elem));
|
|
75
|
+
await renderingPromise;
|
|
74
76
|
return elem;
|
|
75
77
|
}
|
|
76
78
|
|
|
@@ -82,8 +84,10 @@ export class HtmlBlockMathRenderer {
|
|
|
82
84
|
temp.shadowRoot.innerHTML = `<div><mjx-doc><mjx-head></mjx-head><mjx-body>${inner}</mjx-body></mjx-doc></div>`;
|
|
83
85
|
|
|
84
86
|
elem.appendChild(temp);
|
|
87
|
+
|
|
85
88
|
await window.MathJax.startup.promise;
|
|
86
|
-
window.MathJax.typesetShadow(temp.shadowRoot);
|
|
89
|
+
renderingPromise = renderingPromise.then(() => window.MathJax.typesetShadow(temp.shadowRoot));
|
|
90
|
+
await renderingPromise;
|
|
87
91
|
|
|
88
92
|
return temp.shadowRoot.firstChild;
|
|
89
93
|
}
|
|
@@ -94,13 +98,9 @@ export function loadMathJax(mathJaxConfig) {
|
|
|
94
98
|
|
|
95
99
|
if (mathJaxLoaded) return mathJaxLoaded;
|
|
96
100
|
|
|
97
|
-
const loadOptions = ['ui/menu'];
|
|
98
|
-
if (mathJaxConfig && mathJaxConfig.renderLatex) {
|
|
99
|
-
loadOptions.push('[tex]/all-packages');
|
|
100
|
-
}
|
|
101
|
-
|
|
102
101
|
window.MathJax = {
|
|
103
102
|
chtml: {
|
|
103
|
+
adaptiveCSS: false,
|
|
104
104
|
scale: (mathJaxConfig && mathJaxConfig.outputScale) || 1
|
|
105
105
|
},
|
|
106
106
|
options: {
|
|
@@ -108,7 +108,7 @@ export function loadMathJax(mathJaxConfig) {
|
|
|
108
108
|
settings: { zoom: 'None' }
|
|
109
109
|
}
|
|
110
110
|
},
|
|
111
|
-
loader: { load:
|
|
111
|
+
loader: { load: ['ui/menu'] },
|
|
112
112
|
startup: {
|
|
113
113
|
ready: () => {
|
|
114
114
|
|
|
@@ -188,15 +188,15 @@ export function loadMathJax(mathJaxConfig) {
|
|
|
188
188
|
// renders the document. The MathDocument is returned in case
|
|
189
189
|
// you need to rerender the shadowRoot later.
|
|
190
190
|
//
|
|
191
|
-
window.MathJax.typesetShadow = function(root, elem) {
|
|
191
|
+
window.MathJax.typesetShadow = async function(root, elem) {
|
|
192
192
|
const InputJax = startup.getInputJax();
|
|
193
193
|
const OutputJax = startup.getOutputJax();
|
|
194
194
|
const html = mathjax.document(root, { InputJax, OutputJax });
|
|
195
195
|
|
|
196
196
|
if (elem) html.options.elements = [elem];
|
|
197
197
|
|
|
198
|
-
|
|
199
|
-
|
|
198
|
+
await mathjax.handleRetriesFor(() => html.render());
|
|
199
|
+
html.typeset();
|
|
200
200
|
};
|
|
201
201
|
|
|
202
202
|
//
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightspace-ui/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.37.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",
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import '../button/button.js';
|
|
2
|
-
import '../button/button-subtle.js';
|
|
3
|
-
import { html, LitElement, nothing } from 'lit';
|
|
4
|
-
import { classMap } from 'lit/directives/class-map.js';
|
|
5
|
-
import { EmptyStateIllustratedMixin } from './empty-state-illustrated-mixin.js';
|
|
6
|
-
import { runAsync } from '../../directives/run-async/run-async.js';
|
|
7
|
-
import { styleMap } from 'lit/directives/style-map.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* The `d2l-empty-state-illustrated-button` component is an empty state component that displays an illustration and action button. The illustration property can be set to use one of the preset illustrations or a custom SVG illustration can be added in the default slot.
|
|
11
|
-
* @fires d2l-empty-state-action - Dispatched when the action button is clicked
|
|
12
|
-
* @slot - Custom SVG content if `illustration-name` property is not set
|
|
13
|
-
*/
|
|
14
|
-
class EmptyStateIllustratedButton extends EmptyStateIllustratedMixin(LitElement) {
|
|
15
|
-
|
|
16
|
-
static get properties() {
|
|
17
|
-
return {
|
|
18
|
-
/**
|
|
19
|
-
* This will change the action button to use a primary button instead of the default subtle button
|
|
20
|
-
* @type {boolean}
|
|
21
|
-
*/
|
|
22
|
-
primary: { type: Boolean },
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
constructor() {
|
|
27
|
-
super();
|
|
28
|
-
this._illustratedComponentType = 'button';
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
render() {
|
|
32
|
-
const illustrationContainerStyle = this.getIllustrationContainerStyle();
|
|
33
|
-
const titleClass = this.getTitleClass();
|
|
34
|
-
|
|
35
|
-
let actionButton = nothing;
|
|
36
|
-
if (this.actionText) {
|
|
37
|
-
actionButton = this.primary
|
|
38
|
-
? html`<d2l-button
|
|
39
|
-
class="d2l-empty-state-action"
|
|
40
|
-
@click=${this._handleActionClick}
|
|
41
|
-
primary>${this.actionText}
|
|
42
|
-
</d2l-button>`
|
|
43
|
-
: html`<d2l-button-subtle
|
|
44
|
-
class="d2l-empty-state-action"
|
|
45
|
-
@click=${this._handleActionClick}
|
|
46
|
-
text=${this.actionText}>
|
|
47
|
-
</d2l-button-subtle>`;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return html`
|
|
51
|
-
${this.illustrationName
|
|
52
|
-
? html`
|
|
53
|
-
<div style="${styleMap(illustrationContainerStyle)}">
|
|
54
|
-
${runAsync(this.illustrationName, () => this.getIllustration(this.illustrationName), { success: (illustration) => illustration }, { pendingState: false })}
|
|
55
|
-
</div>`
|
|
56
|
-
: html`<slot></slot>`}
|
|
57
|
-
|
|
58
|
-
<p class="${classMap(titleClass)}">${this.titleText}</p>
|
|
59
|
-
<p class="d2l-body-compact d2l-empty-state-description">${this.description}</p>
|
|
60
|
-
${actionButton}
|
|
61
|
-
`;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
_handleActionClick(e) {
|
|
65
|
-
e.stopPropagation();
|
|
66
|
-
this.dispatchEvent(new CustomEvent('d2l-empty-state-action'));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
customElements.define('d2l-empty-state-illustrated-button', EmptyStateIllustratedButton);
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { html, LitElement, nothing } from 'lit';
|
|
2
|
-
import { classMap } from 'lit/directives/class-map.js';
|
|
3
|
-
import { EmptyStateIllustratedMixin } from './empty-state-illustrated-mixin.js';
|
|
4
|
-
import { linkStyles } from '../link/link.js';
|
|
5
|
-
import { runAsync } from '../../directives/run-async/run-async.js';
|
|
6
|
-
import { styleMap } from 'lit/directives/style-map.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* The `d2l-empty-state-illustrated-link` component is an empty state component that displays an illustration and action link. The illustration property can be set to use one of the preset illustrations or a custom SVG illustration can be added in the default slot.
|
|
10
|
-
* @slot - Custom SVG content if `illustration-name` property is not set
|
|
11
|
-
*/
|
|
12
|
-
class EmptyStateIllustratedLink extends EmptyStateIllustratedMixin(LitElement) {
|
|
13
|
-
|
|
14
|
-
static get properties() {
|
|
15
|
-
return {
|
|
16
|
-
/**
|
|
17
|
-
* The action URL or URL fragment of the link
|
|
18
|
-
* @type {string}
|
|
19
|
-
*/
|
|
20
|
-
actionHref: { type: String, attribute: 'action-href' },
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
static get styles() {
|
|
25
|
-
return [super.styles, linkStyles];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
constructor() {
|
|
29
|
-
super();
|
|
30
|
-
this._illustratedComponentType = 'link';
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
render() {
|
|
34
|
-
const illustrationContainerStyle = this.getIllustrationContainerStyle();
|
|
35
|
-
const titleClass = this.getTitleClass();
|
|
36
|
-
|
|
37
|
-
const actionLink = this.actionText && this.actionHref
|
|
38
|
-
? html`<a class="d2l-body-compact d2l-empty-state-action d2l-link" href=${this.actionHref}>${this.actionText}</a>`
|
|
39
|
-
: nothing;
|
|
40
|
-
|
|
41
|
-
return html`
|
|
42
|
-
${this.illustrationName
|
|
43
|
-
? html`
|
|
44
|
-
<div style="${styleMap(illustrationContainerStyle)}">
|
|
45
|
-
${runAsync(this.illustrationName, () => this.getIllustration(this.illustrationName), { success: (illustration) => illustration }, { pendingState: false })}
|
|
46
|
-
</div>`
|
|
47
|
-
: html`<slot></slot>`}
|
|
48
|
-
|
|
49
|
-
<p class="${classMap(titleClass)}">${this.titleText}</p>
|
|
50
|
-
<p class="d2l-body-compact d2l-empty-state-description">${this.description}</p>
|
|
51
|
-
${actionLink}
|
|
52
|
-
`;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
customElements.define('d2l-empty-state-illustrated-link', EmptyStateIllustratedLink);
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { emptyStateSimpleStyles, emptyStateStyles } from './empty-state-styles.js';
|
|
2
|
-
import { html, LitElement, nothing } from 'lit';
|
|
3
|
-
import { bodyCompactStyles } from '../typography/styles.js';
|
|
4
|
-
import { linkStyles } from '../link/link.js';
|
|
5
|
-
import { RtlMixin } from '../../mixins/rtl-mixin.js';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* The `d2l-empty-state-simple-link` component is an empty state component that displays a description and action link.
|
|
9
|
-
*/
|
|
10
|
-
class EmptyStateSimpleLink extends RtlMixin(LitElement) {
|
|
11
|
-
|
|
12
|
-
static get properties() {
|
|
13
|
-
return {
|
|
14
|
-
/**
|
|
15
|
-
* The action URL or URL fragment of the link
|
|
16
|
-
* @type {string}
|
|
17
|
-
*/
|
|
18
|
-
actionHref: { type: String, attribute: 'action-href' },
|
|
19
|
-
/**
|
|
20
|
-
* The action text to be used in the link
|
|
21
|
-
* @type {string}
|
|
22
|
-
*/
|
|
23
|
-
actionText: { type: String, attribute: 'action-text' },
|
|
24
|
-
/**
|
|
25
|
-
* REQUIRED: A description giving details about the empty state
|
|
26
|
-
* @type {string}
|
|
27
|
-
*/
|
|
28
|
-
description: { type: String }
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
static get styles() {
|
|
33
|
-
return [bodyCompactStyles, emptyStateStyles, emptyStateSimpleStyles, linkStyles];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
constructor() {
|
|
37
|
-
super();
|
|
38
|
-
this._missingDescriptionErrorHasBeenThrown = false;
|
|
39
|
-
this._validatingDescriptionTimeout = null;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
firstUpdated(changedProperties) {
|
|
43
|
-
super.firstUpdated(changedProperties);
|
|
44
|
-
this._validateDescription();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
render() {
|
|
48
|
-
const actionLink = this.actionText && this.actionHref
|
|
49
|
-
? html`<a class="d2l-body-compact d2l-link" href=${this.actionHref}>${this.actionText}</a>`
|
|
50
|
-
: nothing;
|
|
51
|
-
|
|
52
|
-
return html`
|
|
53
|
-
<p class="d2l-body-compact d2l-empty-state-description">${this.description}</p>
|
|
54
|
-
${actionLink}
|
|
55
|
-
`;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
_validateDescription() {
|
|
59
|
-
clearTimeout(this._validatingDescriptionTimeout);
|
|
60
|
-
// don't error immediately in case it doesn't get set immediately
|
|
61
|
-
this._validatingDescriptionTimeout = setTimeout(() => {
|
|
62
|
-
this._validatingDescriptionTimeout = null;
|
|
63
|
-
const hasDescription = (typeof this.description === 'string') && this.description.length > 0;
|
|
64
|
-
|
|
65
|
-
if (!hasDescription && !this._missingDescriptionErrorHasBeenThrown) {
|
|
66
|
-
this._missingDescriptionErrorHasBeenThrown = true;
|
|
67
|
-
setTimeout(() => { throw new Error('<d2l-empty-state-simple-link>: missing required "description" attribute.'); });
|
|
68
|
-
}
|
|
69
|
-
}, 3000);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
customElements.define('d2l-empty-state-simple-link', EmptyStateSimpleLink);
|