@brightspace-ui/core 3.42.0 → 3.44.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/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",
|