UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

161 lines (160 loc) 4.34 kB
import { useEffectOnce } from "../internal/hooks/useEffectOnce.js"; import { useEffectCallback } from "../internal/hooks/useEffectCallback.js"; import { c } from "react-compiler-runtime"; import { jsx } from "react/jsx-runtime"; import { useEffect, useRef } from "react"; import { announceFromElement } from "@primer/live-region-element"; //#region src/live-region/Announce.tsx /** * `Announce` is a component that will announce the text content of the * `children` passed in to screen readers using the given politeness level. It * will also announce any changes to the text content of `children` */ function Announce(props) { const $ = c(24); let children; let delayMs; let rest; let t0; let t1; let t2; let t3; if ($[0] !== props) { ({as: t0, announceOnShow: t1, children, delayMs, hidden: t2, politeness: t3, ...rest} = props); $[0] = props; $[1] = children; $[2] = delayMs; $[3] = rest; $[4] = t0; $[5] = t1; $[6] = t2; $[7] = t3; } else { children = $[1]; delayMs = $[2]; rest = $[3]; t0 = $[4]; t1 = $[5]; t2 = $[6]; t3 = $[7]; } const BaseComponent = t0 === void 0 ? "div" : t0; const announceOnShow = t1 === void 0 ? true : t1; const hidden = t2 === void 0 ? false : t2; const politeness = t3 === void 0 ? "polite" : t3; const ref = useRef(null); const previousAnnouncementText = useRef(null); const savedAnnouncement = useRef(null); let t4; if ($[8] !== delayMs || $[9] !== hidden || $[10] !== politeness) { t4 = () => { var _savedAnnouncement$cu; const { current: element } = ref; if (!element) return; if (hidden) return; const textContent = getTextContent(element); if (!textContent) return; if (textContent === previousAnnouncementText.current) return; if (!isVisible(element)) return; (_savedAnnouncement$cu = savedAnnouncement.current) === null || _savedAnnouncement$cu === void 0 || _savedAnnouncement$cu.cancel(); savedAnnouncement.current = announceFromElement(element, politeness === "assertive" ? { politeness } : { politeness, delayMs }); previousAnnouncementText.current = textContent; }; $[8] = delayMs; $[9] = hidden; $[10] = politeness; $[11] = t4; } else t4 = $[11]; const announce = useEffectCallback(t4); let t5; if ($[12] !== announce || $[13] !== announceOnShow) { t5 = () => { if (announceOnShow) announce(); }; $[12] = announce; $[13] = announceOnShow; $[14] = t5; } else t5 = $[14]; useEffectOnce(t5); let t6; let t7; if ($[15] !== announce) { t6 = () => { const { current: container } = ref; if (container === null) return; const observer = new MutationObserver(() => { announce(); }); observer.observe(container, { subtree: true, childList: true, characterData: true }); return () => { observer.disconnect(); }; }; t7 = [announce]; $[15] = announce; $[16] = t6; $[17] = t7; } else { t6 = $[16]; t7 = $[17]; } useEffect(t6, t7); let t8; let t9; if ($[18] === Symbol.for("react.memo_cache_sentinel")) { t8 = () => () => { if (savedAnnouncement.current !== null) { savedAnnouncement.current.cancel(); savedAnnouncement.current = null; } }; t9 = []; $[18] = t8; $[19] = t9; } else { t8 = $[18]; t9 = $[19]; } useEffect(t8, t9); let t10; if ($[20] !== BaseComponent || $[21] !== children || $[22] !== rest) { t10 = /*#__PURE__*/ jsx(BaseComponent, { ...rest, ref, children }); $[20] = BaseComponent; $[21] = children; $[22] = rest; $[23] = t10; } else t10 = $[23]; return t10; } function getTextContent(element) { let value = ""; if (element.hasAttribute("aria-label")) value = element.getAttribute("aria-label"); else if (element.textContent) value = element.textContent; return value ? value.trim() : ""; } /** * Determine if an element is visible (not hidden via `display: none` or * `visibility: hidden`). Prefers the native `checkVisibility()` API when * available and falls back to `getComputedStyle` for older browsers. */ function isVisible(element) { if (typeof element.checkVisibility === "function") return element.checkVisibility({ visibilityProperty: true, checkVisibilityCSS: true }); const style = window.getComputedStyle(element); return style.display !== "none" && style.visibility !== "hidden"; } //#endregion export { Announce };