UNPKG

@awsui/components-react

Version:

On July 19th, 2022, we launched [Cloudscape Design System](https://cloudscape.design). Cloudscape is an evolution of AWS-UI. It consists of user interface guidelines, front-end components, design resources, and development tools for building intuitive, en

77 lines 3.46 kB
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import styles from './styles.css.js'; import testUtilStyles from './test-classes/styles.css.js'; /** * The controller that manages a single live region container. It has a timer * to make sure announcements are throttled correctly. It can also make sure * that a message is announced again even if it matches the previous content * of the live region. * * @see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions */ export class LiveRegionController { constructor(politeness, delay = LiveRegionController.defaultDelay) { this.politeness = politeness; this.delay = delay; this._addedTerminalPeriod = false; this._nextAnnouncement = ''; this._element = document.createElement('div'); this._element.className = `${styles.announcer} ${testUtilStyles.announcer}`; this._element.setAttribute('aria-live', this.politeness); this._element.setAttribute('aria-atomic', 'true'); document.body.appendChild(this._element); } /** * Reset the state of the controller and clear any active announcements. */ destroy() { var _a; (_a = this._element) === null || _a === void 0 ? void 0 : _a.remove(); if (this._timeoutId !== undefined) { clearTimeout(this._timeoutId); this._timeoutId = undefined; } } announce({ message, forceReannounce = false }) { if (!message) { return; } this._nextAnnouncement = message.trim(); if (this.delay === 0 || forceReannounce) { // If the delay is 0, just skip the timeout shenanigans and update the // element synchronously. Great for tests. return this._updateElement(forceReannounce); } if (this._timeoutId === undefined) { this._timeoutId = setTimeout(() => this._updateElement(false), this.delay * 1000); } } _updateElement(forceReannounce) { if (this._nextAnnouncement !== this._lastAnnouncement) { // The aria-atomic does not work properly in Voice Over, causing // certain parts of the content to be ignored. To fix that, // we assign the source text content as a single node. this._element.textContent = this._nextAnnouncement; this._addedTerminalPeriod = false; } else if (forceReannounce) { // A (generally) safe way of forcing re-announcements is toggling the // terminal period. If we only keep adding periods, it's going to be // eventually interpreted as an ellipsis. this._element.textContent = this._nextAnnouncement + (this._addedTerminalPeriod ? '' : '.'); this._addedTerminalPeriod = !this._addedTerminalPeriod; } // Track the announced text for deduplication. this._lastAnnouncement = this._nextAnnouncement; // Reset the state for the next announcement. this._timeoutId = undefined; } } /** * The default delay for announcements when no delay is explicitly provided. * During internal unit testing, you can import this and explicitly set it to * 0 to make the live region update the DOM without waiting for a timer. */ LiveRegionController.defaultDelay = 2; //# sourceMappingURL=controller.js.map