UNPKG

next

Version:

The React Framework

64 lines (63 loc) 2.76 kB
import { useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; const ANNOUNCER_TYPE = 'next-route-announcer'; const ANNOUNCER_ID = '__next-route-announcer__'; function getAnnouncerNode() { var _existingAnnouncer_shadowRoot; const existingAnnouncer = document.getElementsByName(ANNOUNCER_TYPE)[0]; if (existingAnnouncer == null ? void 0 : (_existingAnnouncer_shadowRoot = existingAnnouncer.shadowRoot) == null ? void 0 : _existingAnnouncer_shadowRoot.childNodes[0]) { return existingAnnouncer.shadowRoot.childNodes[0]; } else { const container = document.createElement(ANNOUNCER_TYPE); container.style.cssText = 'position:absolute'; const announcer = document.createElement('div'); announcer.ariaLive = 'assertive'; announcer.id = ANNOUNCER_ID; announcer.role = 'alert'; announcer.style.cssText = 'position:absolute;border:0;height:1px;margin:-1px;padding:0;width:1px;clip:rect(0 0 0 0);overflow:hidden;white-space:nowrap;word-wrap:normal'; // Use shadow DOM here to avoid any potential CSS bleed const shadow = container.attachShadow({ mode: 'open' }); shadow.appendChild(announcer); document.body.appendChild(container); return announcer; } } export function AppRouterAnnouncer(param) { let { tree } = param; const [portalNode, setPortalNode] = useState(null); useEffect(()=>{ const announcer = getAnnouncerNode(); setPortalNode(announcer); return ()=>{ const container = document.getElementsByTagName(ANNOUNCER_TYPE)[0]; if (container == null ? void 0 : container.isConnected) { document.body.removeChild(container); } }; }, []); const [routeAnnouncement, setRouteAnnouncement] = useState(''); const previousTitle = useRef(undefined); useEffect(()=>{ let currentTitle = ''; if (document.title) { currentTitle = document.title; } else { const pageHeader = document.querySelector('h1'); if (pageHeader) { currentTitle = pageHeader.innerText || pageHeader.textContent || ''; } } // Only announce the title change, but not for the first load because screen // readers do that automatically. if (previousTitle.current !== undefined && previousTitle.current !== currentTitle) { setRouteAnnouncement(currentTitle); } previousTitle.current = currentTitle; }, [ tree ]); return portalNode ? /*#__PURE__*/ createPortal(routeAnnouncement, portalNode) : null; } //# sourceMappingURL=app-router-announcer.js.map