@momentum-design/components 0.120.25 → 0.120.27
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/dist/browser/index.js +182 -177
- package/dist/browser/index.js.map +4 -4
- package/dist/components/announcementdialog/announcementdialog.styles.js +1 -1
- package/dist/components/screenreaderannouncer/screenreaderannouncer.component.d.ts +15 -0
- package/dist/components/screenreaderannouncer/screenreaderannouncer.component.js +38 -4
- package/dist/components/screenreaderannouncer/screenreaderannouncer.constants.d.ts +1 -0
- package/dist/components/screenreaderannouncer/screenreaderannouncer.constants.js +1 -0
- package/dist/components/textarea/index.d.ts +1 -0
- package/dist/components/textarea/index.js +1 -0
- package/dist/components/textarea/textarea.component.d.ts +18 -1
- package/dist/components/textarea/textarea.component.js +42 -1
- package/dist/custom-elements.json +3278 -3238
- package/dist/react/index.d.ts +6 -6
- package/dist/react/index.js +6 -6
- package/dist/utils/debounce.d.ts +15 -0
- package/dist/utils/debounce.js +30 -0
- package/package.json +1 -1
@@ -66,6 +66,12 @@ declare class ScreenreaderAnnouncer extends Component {
|
|
66
66
|
* @default 20_000
|
67
67
|
*/
|
68
68
|
timeout: number;
|
69
|
+
/**
|
70
|
+
* The debounce time delay in milliseconds for announcements.
|
71
|
+
*
|
72
|
+
* @default 500
|
73
|
+
*/
|
74
|
+
debounceTime: number;
|
69
75
|
/**
|
70
76
|
* Array to store timeOutIds for clearing timeouts later.
|
71
77
|
* @internal
|
@@ -76,6 +82,8 @@ declare class ScreenreaderAnnouncer extends Component {
|
|
76
82
|
* @internal
|
77
83
|
*/
|
78
84
|
private ariaLiveAnnouncementIds;
|
85
|
+
/** @internal */
|
86
|
+
private debouncedAnnounce?;
|
79
87
|
/**
|
80
88
|
* Announces the given announcement to the screen reader.
|
81
89
|
*
|
@@ -102,6 +110,13 @@ declare class ScreenreaderAnnouncer extends Component {
|
|
102
110
|
* `mdc-screenreaderannouncer-identity`.
|
103
111
|
*/
|
104
112
|
private createAnnouncementAriaLiveRegion;
|
113
|
+
/**
|
114
|
+
* Creates a single debounced function that will read the latest this.announcement when executed.
|
115
|
+
*
|
116
|
+
* This function is used to debounce the announcement so that it will only be made after
|
117
|
+
* this.debounceTime milliseconds have passed since the last time this.announcement was updated.
|
118
|
+
*/
|
119
|
+
private setupDebouncedAnnounce;
|
105
120
|
connectedCallback(): void;
|
106
121
|
disconnectedCallback(): void;
|
107
122
|
protected updated(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
|
@@ -10,6 +10,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
11
11
|
import { v4 as uuidv4 } from 'uuid';
|
12
12
|
import { Component } from '../../models';
|
13
|
+
import { debounce } from '../../utils/debounce';
|
13
14
|
import { DEFAULTS } from './screenreaderannouncer.constants';
|
14
15
|
import styles from './screenreaderannouncer.styles';
|
15
16
|
/**
|
@@ -79,6 +80,12 @@ class ScreenreaderAnnouncer extends Component {
|
|
79
80
|
* @default 20_000
|
80
81
|
*/
|
81
82
|
this.timeout = DEFAULTS.TIMEOUT;
|
83
|
+
/**
|
84
|
+
* The debounce time delay in milliseconds for announcements.
|
85
|
+
*
|
86
|
+
* @default 500
|
87
|
+
*/
|
88
|
+
this.debounceTime = DEFAULTS.DEBOUNCE;
|
82
89
|
/**
|
83
90
|
* Array to store timeOutIds for clearing timeouts later.
|
84
91
|
* @internal
|
@@ -109,8 +116,8 @@ class ScreenreaderAnnouncer extends Component {
|
|
109
116
|
if (announcement.length > 0) {
|
110
117
|
const announcementId = `mdc-screenreaderannouncer-announcement-${uuidv4()}`;
|
111
118
|
const announcementContainer = document.createElement('div');
|
112
|
-
announcementContainer.id
|
113
|
-
announcementContainer.
|
119
|
+
announcementContainer.setAttribute('id', announcementId);
|
120
|
+
announcementContainer.setAttribute('aria-live', ariaLive);
|
114
121
|
(_a = document.getElementById(this.identity)) === null || _a === void 0 ? void 0 : _a.appendChild(announcementContainer);
|
115
122
|
const timeOutId = window.setTimeout(() => {
|
116
123
|
const announcementElement = document.createElement('p');
|
@@ -166,25 +173,48 @@ class ScreenreaderAnnouncer extends Component {
|
|
166
173
|
document.body.appendChild(liveRegionLightDom);
|
167
174
|
}
|
168
175
|
}
|
176
|
+
/**
|
177
|
+
* Creates a single debounced function that will read the latest this.announcement when executed.
|
178
|
+
*
|
179
|
+
* This function is used to debounce the announcement so that it will only be made after
|
180
|
+
* this.debounceTime milliseconds have passed since the last time this.announcement was updated.
|
181
|
+
*/
|
182
|
+
setupDebouncedAnnounce() {
|
183
|
+
// create single debounced function that will read latest this.announcement when executed
|
184
|
+
this.debouncedAnnounce = debounce(() => {
|
185
|
+
if (this.announcement.length > 0) {
|
186
|
+
this.announce(this.announcement, this.delay, this.timeout, this.dataAriaLive);
|
187
|
+
this.announcement = '';
|
188
|
+
}
|
189
|
+
}, this.debounceTime);
|
190
|
+
}
|
169
191
|
connectedCallback() {
|
170
192
|
super.connectedCallback();
|
171
193
|
if (this.identity.length === 0) {
|
172
194
|
this.identity = DEFAULTS.IDENTITY;
|
173
195
|
}
|
174
196
|
this.createAnnouncementAriaLiveRegion();
|
197
|
+
this.setupDebouncedAnnounce();
|
175
198
|
}
|
176
199
|
disconnectedCallback() {
|
200
|
+
var _a;
|
177
201
|
super.disconnectedCallback();
|
178
202
|
this.clearTimeOutsAndAnnouncements();
|
203
|
+
// cancel any pending debounced action and clear DOM timeouts
|
204
|
+
(_a = this.debouncedAnnounce) === null || _a === void 0 ? void 0 : _a.cancel();
|
179
205
|
}
|
180
206
|
updated(changedProperties) {
|
207
|
+
var _a;
|
181
208
|
if (changedProperties.has('identity') && this.identity.length === 0) {
|
182
209
|
this.identity = DEFAULTS.IDENTITY;
|
183
210
|
this.createAnnouncementAriaLiveRegion();
|
184
211
|
}
|
212
|
+
if (changedProperties.has('debounceTime')) {
|
213
|
+
// Reinitiate debounced function if debounceTime changed
|
214
|
+
this.setupDebouncedAnnounce();
|
215
|
+
}
|
185
216
|
if (changedProperties.has('announcement') && this.announcement.length > 0) {
|
186
|
-
|
187
|
-
this.announcement = '';
|
217
|
+
(_a = this.debouncedAnnounce) === null || _a === void 0 ? void 0 : _a.call(this);
|
188
218
|
}
|
189
219
|
}
|
190
220
|
}
|
@@ -209,4 +239,8 @@ __decorate([
|
|
209
239
|
property({ type: Number, reflect: true }),
|
210
240
|
__metadata("design:type", Number)
|
211
241
|
], ScreenreaderAnnouncer.prototype, "timeout", void 0);
|
242
|
+
__decorate([
|
243
|
+
property({ type: Number, reflect: true, attribute: 'debounce-time' }),
|
244
|
+
__metadata("design:type", Number)
|
245
|
+
], ScreenreaderAnnouncer.prototype, "debounceTime", void 0);
|
212
246
|
export default ScreenreaderAnnouncer;
|
@@ -110,14 +110,25 @@ declare class Textarea extends Textarea_base {
|
|
110
110
|
*/
|
111
111
|
minlength?: number;
|
112
112
|
/**
|
113
|
-
* maximum character limit for the textarea field for character counter.
|
113
|
+
* The maximum character limit for the textarea field for character counter.
|
114
114
|
*/
|
115
115
|
maxCharacterLimit?: number;
|
116
|
+
/**
|
117
|
+
* Template string for the announcement that will be read by screen readers when the max character limit is set.
|
118
|
+
* Consumers must use the placeholders `%{number-of-characters}` and `%{max-character-limit}` in the string,
|
119
|
+
* which will be dynamically replaced with the actual values at runtime.
|
120
|
+
* For example: `%{number-of-characters} out of %{max-character-limit} characters are typed.`
|
121
|
+
* Example output: "93 out of 140 characters are typed."
|
122
|
+
*/
|
123
|
+
characterLimitAnnouncement?: string;
|
116
124
|
/**
|
117
125
|
* @internal
|
118
126
|
* The textarea element
|
119
127
|
*/
|
120
128
|
inputElement: HTMLTextAreaElement;
|
129
|
+
/** @internal */
|
130
|
+
private ariaLiveAnnouncer?;
|
131
|
+
/** @internal */
|
121
132
|
private characterLimitExceedingFired;
|
122
133
|
protected get textarea(): HTMLTextAreaElement;
|
123
134
|
connectedCallback(): void;
|
@@ -160,6 +171,12 @@ declare class Textarea extends Textarea_base {
|
|
160
171
|
* @returns void
|
161
172
|
*/
|
162
173
|
private updateValue;
|
174
|
+
/**
|
175
|
+
* Announces the character limit warning based on the current value length.
|
176
|
+
* If the value length exceeds the max character limit, the help text is announced (if help text is present).
|
177
|
+
* If the value length does not exceed the max character limit, then the character limit announcement is announced.
|
178
|
+
*/
|
179
|
+
private announceMaxLengthWarning;
|
163
180
|
/**
|
164
181
|
* Handles the change event of the textarea field.
|
165
182
|
* Updates the value and sets the validity of the textarea field.
|
@@ -9,7 +9,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
9
|
};
|
10
10
|
import { html, nothing } from 'lit';
|
11
11
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
12
|
-
import { property, query } from 'lit/decorators.js';
|
12
|
+
import { property, query, state } from 'lit/decorators.js';
|
13
13
|
import FormfieldWrapper from '../formfieldwrapper';
|
14
14
|
import { DEFAULTS as FORMFIELD_DEFAULTS, VALIDATION } from '../formfieldwrapper/formfieldwrapper.constants';
|
15
15
|
import { AUTO_CAPITALIZE } from '../input/input.constants';
|
@@ -110,6 +110,7 @@ class Textarea extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMix
|
|
110
110
|
* @default 'off'
|
111
111
|
*/
|
112
112
|
this.autocomplete = AUTO_COMPLETE.OFF;
|
113
|
+
/** @internal */
|
113
114
|
this.characterLimitExceedingFired = false;
|
114
115
|
}
|
115
116
|
get textarea() {
|
@@ -255,6 +256,33 @@ class Textarea extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMix
|
|
255
256
|
updateValue() {
|
256
257
|
this.value = this.textarea.value;
|
257
258
|
this.internals.setFormValue(this.textarea.value);
|
259
|
+
this.announceMaxLengthWarning();
|
260
|
+
}
|
261
|
+
/**
|
262
|
+
* Announces the character limit warning based on the current value length.
|
263
|
+
* If the value length exceeds the max character limit, the help text is announced (if help text is present).
|
264
|
+
* If the value length does not exceed the max character limit, then the character limit announcement is announced.
|
265
|
+
*/
|
266
|
+
announceMaxLengthWarning() {
|
267
|
+
this.ariaLiveAnnouncer = '';
|
268
|
+
if (!this.maxCharacterLimit || this.value.length === 0) {
|
269
|
+
return;
|
270
|
+
}
|
271
|
+
if (this.helpText && this.value.length > this.maxCharacterLimit) {
|
272
|
+
// We need to assign the same value multiple times, when the input reaches the max limit,
|
273
|
+
// Lit does a `===` strict comparison and doesn't update the value
|
274
|
+
// Hence we need to manually wait for the update to complete and then assign the value.
|
275
|
+
this.updateComplete
|
276
|
+
.then(() => {
|
277
|
+
this.ariaLiveAnnouncer = this.helpText;
|
278
|
+
})
|
279
|
+
.catch(() => { });
|
280
|
+
}
|
281
|
+
else if (this.characterLimitAnnouncement && this.value.length <= this.maxCharacterLimit) {
|
282
|
+
this.ariaLiveAnnouncer = this.characterLimitAnnouncement
|
283
|
+
.replace('%{number-of-characters}', this.value.length.toString())
|
284
|
+
.replace('%{max-character-limit}', this.maxCharacterLimit.toString());
|
285
|
+
}
|
258
286
|
}
|
259
287
|
/**
|
260
288
|
* Handles the change event of the textarea field.
|
@@ -315,6 +343,11 @@ class Textarea extends AutoFocusOnMountMixin(FormInternalsMixin(DataAriaLabelMix
|
|
315
343
|
aria-describedby="${ifDefined(this.helpText ? FORMFIELD_DEFAULTS.HELPER_TEXT_ID : '')}"
|
316
344
|
aria-invalid="${this.helpTextType === 'error' ? 'true' : 'false'}"
|
317
345
|
></textarea>
|
346
|
+
<mdc-screenreaderannouncer
|
347
|
+
identity="${this.inputId}"
|
348
|
+
announcement="${ifDefined(this.ariaLiveAnnouncer)}"
|
349
|
+
data-aria-live="polite"
|
350
|
+
></mdc-screenreaderannouncer>
|
318
351
|
</div>
|
319
352
|
${this.renderTextareaFooter()}
|
320
353
|
`;
|
@@ -361,8 +394,16 @@ __decorate([
|
|
361
394
|
property({ type: Number, attribute: 'max-character-limit' }),
|
362
395
|
__metadata("design:type", Number)
|
363
396
|
], Textarea.prototype, "maxCharacterLimit", void 0);
|
397
|
+
__decorate([
|
398
|
+
property({ type: String, attribute: 'character-limit-announcement' }),
|
399
|
+
__metadata("design:type", String)
|
400
|
+
], Textarea.prototype, "characterLimitAnnouncement", void 0);
|
364
401
|
__decorate([
|
365
402
|
query('textarea'),
|
366
403
|
__metadata("design:type", HTMLTextAreaElement)
|
367
404
|
], Textarea.prototype, "inputElement", void 0);
|
405
|
+
__decorate([
|
406
|
+
state(),
|
407
|
+
__metadata("design:type", String)
|
408
|
+
], Textarea.prototype, "ariaLiveAnnouncer", void 0);
|
368
409
|
export default Textarea;
|