UNPKG

@momentum-ui/react-collaboration

Version:

Cisco Momentum UI Framework for React Collaboration Applications

121 lines 5.78 kB
var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import React, { useEffect, useState, useRef, useCallback } from 'react'; import { STYLE, DEFAULTS } from './ScreenReaderAnnouncer.constants'; var registry = {}; // This hides the announcer, since it should not be visible on the page (see https://www.a11yproject.com/posts/how-to-hide-content/) var containerStyle = { clip: 'rect(0 0 0 0)', clipPath: 'inset(50%)', height: '1px', overflow: 'hidden', position: 'absolute', width: '1px', whiteSpace: 'nowrap', }; var register = function (identity, announce) { if (registry[identity]) { throw Error("ScreenReaderAnnouncer with identity ".concat(identity, " is already registered")); } registry[identity] = { announce: announce }; }; var deregister = function (identity) { delete registry[identity]; }; var isRegistered = function (announcerIdentity) { return !!registry[announcerIdentity]; }; /** * Announce a message via a screen reader. * To allow for multiple announcers to exist concurrently, an announcer identity can be provided. * This is useful for scenarios where another announcer may be hidden from the screen reader. * An example of this is when an element with role="dialog" and aria-modal="true" is on the page. * In this case, everything outside of the modal is hidden from the accessibility tree. * If an unregistered announcer identity is used, this will error. */ var announce = function (options, announcerIdentity) { if (announcerIdentity === void 0) { announcerIdentity = DEFAULTS.IDENTITY; } if (registry[announcerIdentity]) { return registry[announcerIdentity].announce(options); } throw Error("ScreenReaderAnnouncer with identity ".concat(announcerIdentity, " is not registered")); }; /** * @deprecated Use the equivalent from momentum.design (NPM: `@momentum-design/components/dist/react`) */ var ScreenReaderAnnouncement = function (_a) { var clear = _a.clear, delay = _a.delay, identity = _a.identity, level = _a.level, body = _a.body, timeout = _a.timeout; var _b = useState(), message = _b[0], setMessage = _b[1]; useEffect(function () { var timer = setTimeout(function () { setMessage(body); timer = setTimeout(function () { clear({ messageIdentity: identity }); }, timeout); }, delay); return function () { clearTimeout(timer); }; }, [clear, delay, identity, body, timeout]); return (React.createElement("div", { "aria-live": level, "data-testid": "screen-reader-announcement-".concat(identity) }, message)); }; /** * Component which will cause a screen reader to announce a message when required. * To allow for multiple announcers to exist concurrently, each announcer must have a unique identity. * If no identity is provided, a default one is used (useful for a top level announcer). * If an announcer with a duplicate identity is mounted, an error will occur. * @deprecated Use the equivalent from momentum.design (NPM: `@momentum-design/components/dist/react`) */ var ScreenReaderAnnouncer = function (_a) { var _b = _a.identity, identity = _b === void 0 ? DEFAULTS.IDENTITY : _b; var messageIndex = useRef(0); var _c = useState([]), messages = _c[0], setMessages = _c[1]; var announce = useCallback(function (_a) { var _b = _a.delay, delay = _b === void 0 ? DEFAULTS.DELAY : _b, _c = _a.level, level = _c === void 0 ? DEFAULTS.LEVEL : _c, body = _a.body, _d = _a.timeout, timeout = _d === void 0 ? DEFAULTS.TIMEOUT : _d; var messageIdentity = "message-".concat(messageIndex.current); setMessages(function (previous) { return previous.concat([{ messageIdentity: messageIdentity, body: body, level: level, delay: delay, timeout: timeout }]); }); messageIndex.current += 1; }, []); var clear = useCallback(function (_a) { var messageIdentity = _a.messageIdentity; setMessages(function (previous) { return previous.filter(function (message) { return message.messageIdentity !== messageIdentity; }); }); }, []); useEffect(function () { register(identity, announce); return function () { deregister(identity); }; }, [announce, clear, identity]); return (React.createElement("div", { className: STYLE.wrapper, "data-testid": "screen-reader-announcer", style: containerStyle }, messages.map(function (_a) { var messageIdentity = _a.messageIdentity, messageProps = __rest(_a, ["messageIdentity"]); return (React.createElement(ScreenReaderAnnouncement, __assign({ key: messageIdentity, identity: messageIdentity, clear: clear }, messageProps))); }))); }; export default ScreenReaderAnnouncer; ScreenReaderAnnouncer.announce = announce; ScreenReaderAnnouncer.isRegistered = isRegistered; //# sourceMappingURL=ScreenReaderAnnouncer.js.map