@brightspace-ui/core 3.42.0 → 3.44.0
Sign up to get free protection for your applications and to get access to all the features.
- package/components/dialog/dialog-mixin.js +1 -0
- package/components/form/demo/form-demo.js +5 -0
- package/components/form/docs/form-element-mixin.md +1 -0
- package/components/form/docs/form.md +1 -0
- package/components/form/form-element-mixin.js +12 -0
- package/components/form/form.js +42 -0
- package/components/inputs/docs/input-checkbox.md +10 -12
- package/components/inputs/input-checkbox.js +3 -3
- package/custom-elements.json +6 -6
- package/package.json +1 -1
@@ -76,6 +76,7 @@ export const DialogMixin = superclass => class extends RtlMixin(superclass) {
|
|
76
76
|
this._handleDropdownOpenClose = this._handleDropdownOpenClose.bind(this);
|
77
77
|
this._handleMvcDialogOpen = this._handleMvcDialogOpen.bind(this);
|
78
78
|
this._inIframe = false;
|
79
|
+
this._isDialogMixin = true;
|
79
80
|
this._isFullHeight = false;
|
80
81
|
this._height = 0;
|
81
82
|
this._left = 0;
|
@@ -71,6 +71,7 @@ class FormNestedDemo extends LitElement {
|
|
71
71
|
</div>
|
72
72
|
<d2l-floating-buttons always-float>
|
73
73
|
<d2l-button primary @click=${this._submit}>Save</d2l-button>
|
74
|
+
<d2l-button @click=${this._reset}>Reset</d2l-button>
|
74
75
|
</d2l-floating-buttons>
|
75
76
|
</d2l-form>
|
76
77
|
`;
|
@@ -85,6 +86,10 @@ class FormNestedDemo extends LitElement {
|
|
85
86
|
e.preventDefault();
|
86
87
|
}
|
87
88
|
|
89
|
+
_reset() {
|
90
|
+
if (this.shadowRoot) this.shadowRoot.querySelector('#root').resetValidation();
|
91
|
+
}
|
92
|
+
|
88
93
|
_submit() {
|
89
94
|
if (this.shadowRoot) this.shadowRoot.querySelector('#root').submit();
|
90
95
|
}
|
@@ -18,6 +18,7 @@ invalid state.
|
|
18
18
|
| `name` | String | The name of the form control. Submitted with the form as part of a name/value pair. |
|
19
19
|
|
20
20
|
**Methods:**
|
21
|
+
- `resetValidation()`: Resets any validation errors on the form element. Note that this does not reset any form element value.
|
21
22
|
- `setFormValue(value)`: Sets the current value of the form control. Submitted with the form as part of a name/value pair. `value` may be a:
|
22
23
|
1. An `Object`: `{ 'key1': val, 'key2': val }`
|
23
24
|
- When an `Object` is provided, all keys-value pairs will be submitted. To avoid collision it is recommended that you prefix each key with the component's `name` property value.
|
@@ -114,6 +114,7 @@ If you're looking to emulate native form element submission, `d2l-form-native` m
|
|
114
114
|
### Methods
|
115
115
|
- `submit()`: Submits the form. This will first perform validation on all elements within the form including nested `d2l-form` elements.
|
116
116
|
- **Note:** If validation succeeds, the form data will be aggregated and passed back to the caller via the `d2l-form-submit` event. It will not be submitted by the form itself.
|
117
|
+
- `resetValidation()`: Resets the validation errors. Note that this does not reset any form values. Daylight dialog components (e.g., `d2l-dialog`) will automatically run this method on close.
|
117
118
|
- `async validate()`: Validates the form and any nested `d2l-form` elements without submitting even if validation succeeds for all elements. Returns a `Map` mapping from an element to the list of error messages associated with it.
|
118
119
|
- **Note:** The return value will include elements and errors from both the root form and any nested descendant forms.
|
119
120
|
|
@@ -227,6 +227,18 @@ export const FormElementMixin = superclass => class extends LocalizeCoreElement(
|
|
227
227
|
await this.updatedComplete;
|
228
228
|
}
|
229
229
|
|
230
|
+
resetValidation() {
|
231
|
+
this.invalid = false;
|
232
|
+
this.validationError = null;
|
233
|
+
this._errors = [];
|
234
|
+
|
235
|
+
this.childErrors.forEach((_, ele) => {
|
236
|
+
if (!isCustomFormElement(ele)) return;
|
237
|
+
ele.resetValidation();
|
238
|
+
});
|
239
|
+
this.childErrors = new Map();
|
240
|
+
}
|
241
|
+
|
230
242
|
setFormValue(formValue) {
|
231
243
|
this.formValue = formValue;
|
232
244
|
}
|
package/components/form/form.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import { css, html, LitElement } from 'lit';
|
2
2
|
import { findFormElements, flattenMap, getFormElementData, isCustomFormElement, isNativeFormElement } from './form-helper.js';
|
3
|
+
import { findComposedAncestor } from '../../helpers/dom.js';
|
3
4
|
import { FormMixin } from './form-mixin.js';
|
4
5
|
|
5
6
|
/**
|
@@ -55,6 +56,12 @@ class Form extends FormMixin(LitElement) {
|
|
55
56
|
this._isSubForm = false;
|
56
57
|
}
|
57
58
|
|
59
|
+
firstUpdated(changedProperties) {
|
60
|
+
super.firstUpdated(changedProperties);
|
61
|
+
|
62
|
+
this._setupDialogValidationReset();
|
63
|
+
}
|
64
|
+
|
58
65
|
render() {
|
59
66
|
let errorSummary = null;
|
60
67
|
if (this._isRootForm()) {
|
@@ -77,6 +84,26 @@ class Form extends FormMixin(LitElement) {
|
|
77
84
|
this._submitData(submitter);
|
78
85
|
}
|
79
86
|
|
87
|
+
resetValidation() {
|
88
|
+
const formElements = this._findFormElements();
|
89
|
+
for (const ele of formElements) {
|
90
|
+
if (this._hasSubForms(ele)) {
|
91
|
+
const forms = this._getSubForms(ele);
|
92
|
+
for (const form of forms) {
|
93
|
+
form.resetValidation();
|
94
|
+
}
|
95
|
+
} else {
|
96
|
+
if (isCustomFormElement(ele)) {
|
97
|
+
ele.resetValidation();
|
98
|
+
} else if (isNativeFormElement(ele)) {
|
99
|
+
this._displayValid(ele);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
this._errors = new Map();
|
104
|
+
this._tooltips = new Map();
|
105
|
+
}
|
106
|
+
|
80
107
|
async submit() {
|
81
108
|
return this.requestSubmit(null);
|
82
109
|
}
|
@@ -165,6 +192,21 @@ class Form extends FormMixin(LitElement) {
|
|
165
192
|
|
166
193
|
}
|
167
194
|
|
195
|
+
_setupDialogValidationReset() {
|
196
|
+
const flag = window.D2L?.LP?.Web?.UI?.Flags.Flag('GAUD-6979-dialog-close-reset-validation', true) ?? true;
|
197
|
+
if (!flag) return;
|
198
|
+
|
199
|
+
const dialogAncestor = findComposedAncestor(
|
200
|
+
this,
|
201
|
+
node => node?._isDialogMixin
|
202
|
+
);
|
203
|
+
if (!dialogAncestor) return;
|
204
|
+
|
205
|
+
dialogAncestor.addEventListener('d2l-dialog-close', () => {
|
206
|
+
this.resetValidation();
|
207
|
+
});
|
208
|
+
}
|
209
|
+
|
168
210
|
async _submitData(submitter) {
|
169
211
|
this._dirty = false;
|
170
212
|
|
@@ -54,13 +54,13 @@ The `<d2l-input-checkbox>` element can be used to get a checkbox and optional vi
|
|
54
54
|
|
55
55
|
| Property | Type | Description |
|
56
56
|
|---|---|---|
|
57
|
-
| `aria-label` | String |
|
57
|
+
| `aria-label` | String | Overrides the text in the `Default` slot for screenreader users |
|
58
58
|
| `checked` | Boolean | Checked state |
|
59
|
-
| `description` | String |
|
59
|
+
| `description` | String | Additional information communicated to screenreader users when focusing on the input |
|
60
60
|
| `disabled` | Boolean | Disables the input |
|
61
61
|
| `indeterminate` | Boolean | Sets checkbox to an indeterminate state |
|
62
62
|
| `name` | String | Name of the input |
|
63
|
-
| `not-tabbable` | Boolean | Sets `tabindex="-1"` on the checkbox |
|
63
|
+
| `not-tabbable` | Boolean | Sets `tabindex="-1"` on the checkbox. Note that an alternative method of focusing is necessary to implement if using this property. |
|
64
64
|
| `value` | String | Value of the input |
|
65
65
|
|
66
66
|
### Events
|
@@ -75,18 +75,10 @@ checkbox.addEventListener('change', (e) => {
|
|
75
75
|
|
76
76
|
### Slots
|
77
77
|
|
78
|
+
* `default`: Primary text that will appear next to the input box and function as the label for the checkbox.
|
78
79
|
* `inline-help`: Help text that will appear below the input. Use this only when other helpful cues are not sufficient, such as a carefully-worded label.
|
79
80
|
<!-- docs: end hidden content -->
|
80
81
|
|
81
|
-
### Accessibility Properties
|
82
|
-
|
83
|
-
To make your usage of `d2l-input-checkbox` accessible, use the following properties when applicable:
|
84
|
-
|
85
|
-
| Attribute | Description |
|
86
|
-
|---|---|
|
87
|
-
| `aria-label` | Use when text on checkbox does not provide enough context |
|
88
|
-
| `description` | Use when label on input does not provide enough context. |
|
89
|
-
|
90
82
|
### Methods
|
91
83
|
|
92
84
|
- `simulateClick()`: useful for testing, it simulates the user clicking on the checkbox, which toggles the state of the checkbox and fires the `change` event
|
@@ -135,3 +127,9 @@ As an alternative to using the `<d2l-input-checkbox>` custom element, you can st
|
|
135
127
|
</script>
|
136
128
|
<d2l-my-checkbox-elem></d2l-my-checkbox-elem>
|
137
129
|
```
|
130
|
+
|
131
|
+
## Accessibility
|
132
|
+
|
133
|
+
The `d2l-input-checkbox` component follows W3C's best practice recommendations for a [checkbox](https://www.w3.org/WAI/ARIA/apg/patterns/checkbox/). This means that the component works in the following way:
|
134
|
+
- The `Space` key is used to select a focused checkbox (not the `Enter` key)
|
135
|
+
- The `aria-checked` state is set to `true`, `false` or `mixed` to represent if it's selected, unselected, or partially selected
|
@@ -69,7 +69,7 @@ class InputCheckbox extends InputInlineHelpMixin(FocusMixin(SkeletonMixin(RtlMix
|
|
69
69
|
static get properties() {
|
70
70
|
return {
|
71
71
|
/**
|
72
|
-
*
|
72
|
+
* ACCESSIBILITY: Overrides the text in the `Default` slot for screenreader users
|
73
73
|
* @type {string}
|
74
74
|
*/
|
75
75
|
ariaLabel: { type: String, attribute: 'aria-label' },
|
@@ -79,7 +79,7 @@ class InputCheckbox extends InputInlineHelpMixin(FocusMixin(SkeletonMixin(RtlMix
|
|
79
79
|
*/
|
80
80
|
checked: { type: Boolean },
|
81
81
|
/**
|
82
|
-
* Additional information communicated
|
82
|
+
* ACCESSIBILITY: Additional information communicated to screenreader users when focusing on the input
|
83
83
|
* @type {string}
|
84
84
|
*/
|
85
85
|
description: { type: String },
|
@@ -99,7 +99,7 @@ class InputCheckbox extends InputInlineHelpMixin(FocusMixin(SkeletonMixin(RtlMix
|
|
99
99
|
*/
|
100
100
|
name: { type: String },
|
101
101
|
/**
|
102
|
-
* Sets "tabindex="-1"" on the checkbox
|
102
|
+
* ACCESSIBILITY: ADVANCED: Sets "tabindex="-1"" on the checkbox. Note that an alternative method of focusing is necessary to implement if using this property.
|
103
103
|
* @type {boolean}
|
104
104
|
*/
|
105
105
|
notTabbable: { type: Boolean, attribute: 'not-tabbable' },
|
package/custom-elements.json
CHANGED
@@ -4934,12 +4934,12 @@
|
|
4934
4934
|
"attributes": [
|
4935
4935
|
{
|
4936
4936
|
"name": "aria-label",
|
4937
|
-
"description": "
|
4937
|
+
"description": "ACCESSIBILITY: Overrides the text in the `Default` slot for screenreader users",
|
4938
4938
|
"type": "string"
|
4939
4939
|
},
|
4940
4940
|
{
|
4941
4941
|
"name": "description",
|
4942
|
-
"description": "Additional information communicated
|
4942
|
+
"description": "ACCESSIBILITY: Additional information communicated to screenreader users when focusing on the input",
|
4943
4943
|
"type": "string"
|
4944
4944
|
},
|
4945
4945
|
{
|
@@ -4968,7 +4968,7 @@
|
|
4968
4968
|
},
|
4969
4969
|
{
|
4970
4970
|
"name": "not-tabbable",
|
4971
|
-
"description": "Sets \"tabindex=\"-1\"\" on the checkbox",
|
4971
|
+
"description": "ACCESSIBILITY: ADVANCED: Sets \"tabindex=\"-1\"\" on the checkbox. Note that an alternative method of focusing is necessary to implement if using this property.",
|
4972
4972
|
"type": "boolean",
|
4973
4973
|
"default": "false"
|
4974
4974
|
},
|
@@ -4988,13 +4988,13 @@
|
|
4988
4988
|
{
|
4989
4989
|
"name": "ariaLabel",
|
4990
4990
|
"attribute": "aria-label",
|
4991
|
-
"description": "
|
4991
|
+
"description": "ACCESSIBILITY: Overrides the text in the `Default` slot for screenreader users",
|
4992
4992
|
"type": "string"
|
4993
4993
|
},
|
4994
4994
|
{
|
4995
4995
|
"name": "description",
|
4996
4996
|
"attribute": "description",
|
4997
|
-
"description": "Additional information communicated
|
4997
|
+
"description": "ACCESSIBILITY: Additional information communicated to screenreader users when focusing on the input",
|
4998
4998
|
"type": "string"
|
4999
4999
|
},
|
5000
5000
|
{
|
@@ -5028,7 +5028,7 @@
|
|
5028
5028
|
{
|
5029
5029
|
"name": "notTabbable",
|
5030
5030
|
"attribute": "not-tabbable",
|
5031
|
-
"description": "Sets \"tabindex=\"-1\"\" on the checkbox",
|
5031
|
+
"description": "ACCESSIBILITY: ADVANCED: Sets \"tabindex=\"-1\"\" on the checkbox. Note that an alternative method of focusing is necessary to implement if using this property.",
|
5032
5032
|
"type": "boolean",
|
5033
5033
|
"default": "false"
|
5034
5034
|
},
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@brightspace-ui/core",
|
3
|
-
"version": "3.
|
3
|
+
"version": "3.44.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",
|