@brightspace-ui/core 1.208.2 → 1.210.1
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/README.md +13 -10
- package/components/alert/README.md +22 -5
- package/components/dialog/README.md +5 -1
- package/components/dropdown/dropdown-content-mixin.js +3 -4
- package/components/dropdown/dropdown-menu.js +1 -3
- package/components/dropdown/dropdown-opener-mixin.js +1 -1
- package/components/form/form-element-mixin.js +13 -0
- package/components/menu/menu-item-mixin.js +3 -1
- package/components/menu/menu-item-styles.js +5 -4
- package/components/menu/menu.js +2 -1
- package/package.json +6 -4
- package/tools/perf-test-helper.js +0 -45
package/README.md
CHANGED
|
@@ -119,29 +119,32 @@ Note: The axe tests require `prefers-reduced-motion` emulation to be turned on i
|
|
|
119
119
|
|
|
120
120
|
This repo uses the [@brightspace-ui/visual-diff utility](https://github.com/BrightspaceUI/visual-diff/) to compare current snapshots against a set of golden snapshots stored in source control.
|
|
121
121
|
|
|
122
|
-
The golden snapshots in source control must be updated by
|
|
122
|
+
The golden snapshots in source control must be updated by the [visual-diff GitHub Action](https://github.com/BrightspaceUI/actions/tree/main/visual-diff). If a pull request results in visual differences, a draft pull request with the new goldens will automatically be opened against its branch.
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
To run the tests locally to help troubleshoot or develop new tests, first install these dependencies:
|
|
125
125
|
|
|
126
126
|
```shell
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
npm install @brightspace-ui/visual-diff@X mocha@Y puppeteer@Z --no-save
|
|
128
|
+
```
|
|
129
129
|
|
|
130
|
-
|
|
131
|
-
npx mocha './**/*.visual-diff.js' -t 10000 --require esm
|
|
130
|
+
Replace `X`, `Y` and `Z` with [the current versions](https://github.com/BrightspaceUI/actions/tree/main/visual-diff#current-dependency-versions) the action is using.
|
|
132
131
|
|
|
133
|
-
|
|
134
|
-
npx mocha './**/*.visual-diff.js' -t 10000 --require esm -g some-pattern
|
|
132
|
+
Then run the tests:
|
|
135
133
|
|
|
134
|
+
```shell
|
|
135
|
+
# run visual-diff tests
|
|
136
|
+
npx mocha './**/*.visual-diff.js' -t 10000
|
|
137
|
+
# subset of visual-diff tests:
|
|
138
|
+
npx mocha './**/*.visual-diff.js' -t 10000 -g some-pattern
|
|
136
139
|
# update visual-diff goldens
|
|
137
|
-
npx mocha './**/*.visual-diff.js' -t 10000 --
|
|
140
|
+
npx mocha './**/*.visual-diff.js' -t 10000 --golden
|
|
138
141
|
```
|
|
139
142
|
|
|
140
143
|
## Versioning & Releasing
|
|
141
144
|
|
|
142
145
|
> TL;DR: Commits prefixed with `fix:` and `feat:` will trigger patch and minor releases when merged to `main`. Read on for more details...
|
|
143
146
|
|
|
144
|
-
The [semantic-release GitHub Action](https://github.com/BrightspaceUI/actions/tree/
|
|
147
|
+
The [semantic-release GitHub Action](https://github.com/BrightspaceUI/actions/tree/main/semantic-release) is called from the `release.yml` GitHub Action workflow to handle version changes and releasing.
|
|
145
148
|
|
|
146
149
|
### Version Changes
|
|
147
150
|
|
|
@@ -4,21 +4,38 @@ Alerts communicate critical information relating to the state of the system and
|
|
|
4
4
|
<!-- docs: demo autoSize:false align:start -->
|
|
5
5
|
```html
|
|
6
6
|
<script type="module">
|
|
7
|
-
|
|
7
|
+
import '@brightspace-ui/core/components/alert/alert-toast.js';
|
|
8
|
+
import '@brightspace-ui/core/components/button/button.js';
|
|
9
|
+
|
|
10
|
+
var alert = document.querySelector('#alert');
|
|
11
|
+
var alertToast = document.querySelector('#alert-toast');
|
|
12
|
+
var button = document.querySelector('#open');
|
|
13
|
+
|
|
14
|
+
alert.addEventListener('d2l-alert-close', function() {
|
|
15
|
+
if (!alertToast.open) button.style.display = 'block';
|
|
16
|
+
});
|
|
17
|
+
alertToast.addEventListener('d2l-alert-toast-close', function() {
|
|
18
|
+
if (alert.hasAttribute('hidden')) button.style.display = 'block';
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
button.addEventListener('click', () => {
|
|
22
|
+
alert.removeAttribute('hidden');
|
|
23
|
+
alertToast.open = true;
|
|
24
|
+
button.style.display = 'none';
|
|
25
|
+
});
|
|
8
26
|
</script>
|
|
9
|
-
<!-- docs: start hidden content -->
|
|
10
27
|
<style>
|
|
11
28
|
d2l-alert-toast {
|
|
12
29
|
margin-left: 0 !important;
|
|
13
30
|
margin-right: 0 !important;
|
|
14
31
|
}
|
|
15
32
|
</style>
|
|
16
|
-
<!-- docs: end hidden content -->
|
|
17
33
|
|
|
18
|
-
<d2l-
|
|
34
|
+
<d2l-button id="open" style="align-self:center;display:none;">Show Alerts</d2l-button>
|
|
35
|
+
<d2l-alert id="alert" type="default" button-text="Undo" has-close-button>
|
|
19
36
|
A message.
|
|
20
37
|
</d2l-alert>
|
|
21
|
-
<d2l-alert-toast type="success" open no-auto-close>
|
|
38
|
+
<d2l-alert-toast id="alert-toast" type="success" open no-auto-close>
|
|
22
39
|
A message.
|
|
23
40
|
</d2l-alert-toast>
|
|
24
41
|
```
|
|
@@ -7,13 +7,17 @@ Dialogs interrupt the user to complete a set of tasks, confirm an action, or off
|
|
|
7
7
|
<script type="module">
|
|
8
8
|
import '@brightspace-ui/core/components/button/button.js';
|
|
9
9
|
import '@brightspace-ui/core/components/dialog/dialog.js';
|
|
10
|
-
</script>
|
|
11
10
|
|
|
11
|
+
document.querySelector('#open-demo').addEventListener('click', () => {
|
|
12
|
+
document.querySelector('#dialog-demo').opened = true;
|
|
13
|
+
});
|
|
14
|
+
</script>
|
|
12
15
|
<d2l-dialog id="dialog-demo" title-text="Dialog Title">
|
|
13
16
|
<div>Some dialog content</div>
|
|
14
17
|
<d2l-button slot="footer" primary data-dialog-action="done">Done</d2l-button>
|
|
15
18
|
<d2l-button slot="footer" data-dialog-action>Cancel</d2l-button>
|
|
16
19
|
</d2l-dialog>
|
|
20
|
+
<d2l-button id="open-demo">Show Dialog</d2l-button>
|
|
17
21
|
```
|
|
18
22
|
|
|
19
23
|
## General Dialog [d2l-dialog]
|
|
@@ -394,7 +394,7 @@ export const DropdownContentMixin = superclass => class extends LocalizeCoreElem
|
|
|
394
394
|
if (this.opened) {
|
|
395
395
|
this.close();
|
|
396
396
|
} else {
|
|
397
|
-
this.open(applyFocus);
|
|
397
|
+
this.open(!this.noAutoFocus && applyFocus);
|
|
398
398
|
}
|
|
399
399
|
}
|
|
400
400
|
|
|
@@ -518,11 +518,10 @@ export const DropdownContentMixin = superclass => class extends LocalizeCoreElem
|
|
|
518
518
|
|
|
519
519
|
await this.__position();
|
|
520
520
|
this._showBackdrop = this._useMobileStyling && this.mobileTray;
|
|
521
|
-
|
|
522
521
|
if (!this.noAutoFocus && this.__applyFocus) {
|
|
523
522
|
const focusable = getFirstFocusableDescendant(this);
|
|
524
523
|
if (focusable) {
|
|
525
|
-
//
|
|
524
|
+
// Removing the rAF call can allow infinite focus looping to happen in content using a focus trap
|
|
526
525
|
requestAnimationFrame(() => focusable.focus());
|
|
527
526
|
} else {
|
|
528
527
|
content.setAttribute('tabindex', '-1');
|
|
@@ -1014,7 +1013,7 @@ export const DropdownContentMixin = superclass => class extends LocalizeCoreElem
|
|
|
1014
1013
|
const content = this.__getContentContainer();
|
|
1015
1014
|
const focusable = getFirstFocusableDescendant(content);
|
|
1016
1015
|
if (focusable) {
|
|
1017
|
-
//
|
|
1016
|
+
// Removing the rAF call can allow infinite focus looping to happen in content using a focus trap
|
|
1018
1017
|
requestAnimationFrame(() => focusable.focus());
|
|
1019
1018
|
} else {
|
|
1020
1019
|
content.setAttribute('tabindex', '-1');
|
|
@@ -262,7 +262,7 @@ export const DropdownOpenerMixin = superclass => class extends superclass {
|
|
|
262
262
|
this._isHovering = false;
|
|
263
263
|
this.openDropdown(false);
|
|
264
264
|
}
|
|
265
|
-
} else this.toggleOpen(
|
|
265
|
+
} else this.toggleOpen(true);
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
/* used by open-on-hover option */
|
|
@@ -97,6 +97,11 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
|
|
|
97
97
|
* @ignore
|
|
98
98
|
*/
|
|
99
99
|
noValidate: { type: Boolean, attribute: 'novalidate' },
|
|
100
|
+
/**
|
|
101
|
+
* @ignore
|
|
102
|
+
* Perform validation immediately instead of waiting for the user to make changes.
|
|
103
|
+
*/
|
|
104
|
+
validateOnInit: { type: Boolean, attribute: 'validate-on-init' },
|
|
100
105
|
/**
|
|
101
106
|
* @ignore
|
|
102
107
|
*/
|
|
@@ -125,6 +130,8 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
|
|
|
125
130
|
/** @ignore */
|
|
126
131
|
this.noValidate = false;
|
|
127
132
|
/** @ignore */
|
|
133
|
+
this.validateOnInit = false;
|
|
134
|
+
/** @ignore */
|
|
128
135
|
this.validationError = null;
|
|
129
136
|
/** @ignore */
|
|
130
137
|
this.childErrors = new Map();
|
|
@@ -171,6 +178,9 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
|
|
|
171
178
|
this.dispatchEvent(new CustomEvent('invalid-change'));
|
|
172
179
|
}
|
|
173
180
|
}
|
|
181
|
+
if (this.validateOnInit && (changedProperties.has('noValidate') || changedProperties.has('validateOnInit'))) {
|
|
182
|
+
this.requestValidate(true);
|
|
183
|
+
}
|
|
174
184
|
}
|
|
175
185
|
|
|
176
186
|
async requestValidate(showNewErrors = true) {
|
|
@@ -210,6 +220,9 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
|
|
|
210
220
|
|
|
211
221
|
validationCustomConnected(custom) {
|
|
212
222
|
this._validationCustoms.add(custom);
|
|
223
|
+
if (this.validateOnInit) {
|
|
224
|
+
this.requestValidate(true);
|
|
225
|
+
}
|
|
213
226
|
}
|
|
214
227
|
|
|
215
228
|
validationCustomDisconnected(custom) {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
import { FocusVisiblePolyfillMixin } from '../../mixins/focus-visible-polyfill-mixin.js';
|
|
3
|
+
export const MenuItemMixin = superclass => class extends FocusVisiblePolyfillMixin(superclass) {
|
|
2
4
|
|
|
3
5
|
static get properties() {
|
|
4
6
|
return {
|
|
@@ -15,9 +15,10 @@ export const menuItemStyles = css`
|
|
|
15
15
|
outline: none;
|
|
16
16
|
width: 100%;
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
:host(:hover),
|
|
20
|
-
:host(
|
|
20
|
+
:host(.focus-visible),
|
|
21
|
+
:host(.focus-visible[first]),
|
|
21
22
|
:host([first]:hover) {
|
|
22
23
|
background-color: var(--d2l-menu-background-color-hover);
|
|
23
24
|
border-bottom: 1px solid var(--d2l-menu-border-color-hover);
|
|
@@ -26,7 +27,7 @@ export const menuItemStyles = css`
|
|
|
26
27
|
z-index: 2;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
:host([disabled]), :host([disabled]:hover), :host([disabled]
|
|
30
|
+
:host([disabled]), :host([disabled]:hover), :host([disabled].focus-visible) {
|
|
30
31
|
cursor: default;
|
|
31
32
|
opacity: 0.75;
|
|
32
33
|
}
|
|
@@ -39,7 +40,7 @@ export const menuItemStyles = css`
|
|
|
39
40
|
border-top-color: transparent;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
:host([last]
|
|
43
|
+
:host([last].focus-visible),
|
|
43
44
|
:host([last]:hover) {
|
|
44
45
|
border-bottom-color: var(--d2l-menu-border-color-hover);
|
|
45
46
|
}
|
package/components/menu/menu.js
CHANGED
|
@@ -2,6 +2,7 @@ import '../colors/colors.js';
|
|
|
2
2
|
import '../icons/icon.js';
|
|
3
3
|
import './menu-item-return.js';
|
|
4
4
|
import { css, html, LitElement } from 'lit-element/lit-element.js';
|
|
5
|
+
import { FocusVisiblePolyfillMixin } from '../../mixins/focus-visible-polyfill-mixin.js';
|
|
5
6
|
import { HierarchicalViewMixin } from '../hierarchical-view/hierarchical-view-mixin.js';
|
|
6
7
|
import { ThemeMixin } from '../../mixins/theme-mixin.js';
|
|
7
8
|
|
|
@@ -20,7 +21,7 @@ const keyCodes = {
|
|
|
20
21
|
* @slot - Menu items
|
|
21
22
|
* @fires d2l-menu-resize - Dispatched when size of menu changes (e.g., when nested menu of a different size is opened)
|
|
22
23
|
*/
|
|
23
|
-
class Menu extends ThemeMixin(HierarchicalViewMixin(LitElement)) {
|
|
24
|
+
class Menu extends ThemeMixin(HierarchicalViewMixin(FocusVisiblePolyfillMixin(LitElement))) {
|
|
24
25
|
|
|
25
26
|
static get properties() {
|
|
26
27
|
return {
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightspace-ui/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.210.1",
|
|
4
4
|
"description": "A collection of accessible, free, open-source web components for building Brightspace applications",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"repository": "https://github.com/BrightspaceUI/core.git",
|
|
6
7
|
"publishConfig": {
|
|
7
8
|
"access": "public"
|
|
@@ -48,7 +49,7 @@
|
|
|
48
49
|
"@web/test-runner": "^0.13",
|
|
49
50
|
"@web/test-runner-playwright": "^0.8.8",
|
|
50
51
|
"axe-core": "^4",
|
|
51
|
-
"chalk": "^
|
|
52
|
+
"chalk": "^5",
|
|
52
53
|
"eslint": "^7",
|
|
53
54
|
"eslint-config-brightspace": "^0.16",
|
|
54
55
|
"eslint-plugin-html": "^6",
|
|
@@ -56,9 +57,10 @@
|
|
|
56
57
|
"eslint-plugin-lit": "^1",
|
|
57
58
|
"eslint-plugin-sort-class-members": "^1",
|
|
58
59
|
"lit-analyzer": "^1",
|
|
59
|
-
"node-sass": "^
|
|
60
|
+
"node-sass": "^7",
|
|
60
61
|
"sinon": "^12",
|
|
61
|
-
"stylelint": "^14"
|
|
62
|
+
"stylelint": "^14",
|
|
63
|
+
"web-test-runner-performance": "^0.1.4"
|
|
62
64
|
},
|
|
63
65
|
"dependencies": {
|
|
64
66
|
"@brightspace-ui/intl": "^3",
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import chai from '@open-wc/testing/import-wrappers/chai.js';
|
|
2
|
-
import { fixture } from '@open-wc/testing';
|
|
3
|
-
|
|
4
|
-
const numComponents = 1000;
|
|
5
|
-
|
|
6
|
-
export async function runTest(element) {
|
|
7
|
-
return new Promise((resolve) => {
|
|
8
|
-
|
|
9
|
-
let total = 0;
|
|
10
|
-
let count = 0;
|
|
11
|
-
window.d2lPerfTestInProgress = true;
|
|
12
|
-
document.body.addEventListener('d2l-component-perf', (e) => {
|
|
13
|
-
count++;
|
|
14
|
-
total += e.detail.value;
|
|
15
|
-
if (count === numComponents) {
|
|
16
|
-
const avg = Math.round(total / count);
|
|
17
|
-
delete window.d2lPerfTestInProgress;
|
|
18
|
-
resolve(avg);
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
for (let i = 0; i < numComponents; i++) {
|
|
23
|
-
fixture(element);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export const chaiPerf = (_chai, utils) => {
|
|
30
|
-
|
|
31
|
-
utils.addMethod(_chai.Assertion.prototype, 'performant', function perfTest(baseline) {
|
|
32
|
-
// eslint-disable-next-line no-invalid-this
|
|
33
|
-
const fixture = this._obj;
|
|
34
|
-
const result = runTest(fixture).then(results => {
|
|
35
|
-
new _chai.Assertion(results).to.be.below(baseline);
|
|
36
|
-
});
|
|
37
|
-
// eslint-disable-next-line no-invalid-this
|
|
38
|
-
this.then = result.then.bind(result);
|
|
39
|
-
// eslint-disable-next-line no-invalid-this
|
|
40
|
-
return this;
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
chai.use(chaiPerf);
|