{"version":3,"file":"useModalAccessibility-G-hAOrA1.js","sources":["../../../client/app/bundles/Shared/utils/keyNames.ts","../../../client/app/bundles/Shared/hooks/useModalAccessibility.tsx"],"sourcesContent":["export const ESCAPE = 'Escape'\nexport const TAB = 'Tab'\n","import { useEffect, useRef } from 'react';\n\nimport { ESCAPE, TAB } from '../utils/keyNames';\nimport { MOUSEDOWN, KEYDOWN, } from '../utils/eventNames'\n\n// this hook traps keyboard focus inside of the modal, preventing keyboard users from inadvertently leaving the modal when they are trying to navigate it, which can be confusing.\n// it also ensures that pressing ESCAPE or clicking outside of the modal will close it.\n\n// it should be used inside of a modal like so:\n// const { modalRef } = useModalAccessibility(handleCloseModal);\n// where handleCloseModal is defined as a prop or inside the modal component,\n// and then the modal element should be passed the following props:\n// aria-labelledby={id of element with modal title}\n// aria-modal=\"true\"\n// ref={modalRef}\n// role=\"dialog\"\n// tabIndex={-1}\n\nconst useModalAccessibility = (handleClose) => {\n const modalRef = useRef(null);\n\n const trapFocus = (event) => {\n const focusableModalElements = modalRef.current.querySelectorAll('input, button, select, textarea, a[href]');\n const firstElement = focusableModalElements[0];\n const lastElement = focusableModalElements[focusableModalElements.length - 1];\n\n if (event.shiftKey && document.activeElement === firstElement) {\n lastElement.focus();\n event.preventDefault();\n } else if (!event.shiftKey && document.activeElement === lastElement) {\n firstElement.focus();\n event.preventDefault();\n }\n };\n\n useEffect(() => {\n if (modalRef.current) {\n modalRef.current.focus();\n }\n\n const handleDocumentClick = (event) => {\n if (modalRef.current && !modalRef.current.contains(event.target)) {\n handleClose();\n }\n };\n\n const handleDocumentKeyDown = (event) => {\n if (event.key === ESCAPE) {\n handleClose();\n } else if (event.key === TAB) {\n trapFocus(event);\n }\n };\n\n document.addEventListener(MOUSEDOWN, handleDocumentClick);\n document.addEventListener(KEYDOWN, handleDocumentKeyDown);\n\n return () => {\n document.removeEventListener(MOUSEDOWN, handleDocumentClick);\n document.removeEventListener(KEYDOWN, handleDocumentKeyDown);\n };\n }, [handleClose]);\n\n return { modalRef };\n};\n\nexport default useModalAccessibility;\n"],"names":["ESCAPE","TAB","useModalAccessibility","handleClose","modalRef","useRef","trapFocus","event","focusableModalElements","firstElement","lastElement","useEffect","handleDocumentClick","handleDocumentKeyDown","MOUSEDOWN","KEYDOWN"],"mappings":"gGAAO,MAAMA,EAAS,SACTC,EAAM,MCiBbC,EAAyBC,GAAgB,CACvC,MAAAC,EAAWC,SAAO,IAAI,EAEtBC,EAAaC,GAAU,CAC3B,MAAMC,EAAyBJ,EAAS,QAAQ,iBAAiB,0CAA0C,EACrGK,EAAeD,EAAuB,CAAC,EACvCE,EAAcF,EAAuBA,EAAuB,OAAS,CAAC,EAExED,EAAM,UAAY,SAAS,gBAAkBE,GAC/CC,EAAY,MAAM,EAClBH,EAAM,eAAe,GACZ,CAACA,EAAM,UAAY,SAAS,gBAAkBG,IACvDD,EAAa,MAAM,EACnBF,EAAM,eAAe,EACvB,EAGFI,OAAAA,EAAAA,UAAU,IAAM,CACVP,EAAS,SACXA,EAAS,QAAQ,QAGb,MAAAQ,EAAuBL,GAAU,CACjCH,EAAS,SAAW,CAACA,EAAS,QAAQ,SAASG,EAAM,MAAM,GACjDJ,GACd,EAGIU,EAAyBN,GAAU,CACnCA,EAAM,MAAQP,EACJG,IACHI,EAAM,MAAQN,GACvBK,EAAUC,CAAK,CACjB,EAGO,gBAAA,iBAAiBO,EAAWF,CAAmB,EAC/C,SAAA,iBAAiBG,EAASF,CAAqB,EAEjD,IAAM,CACF,SAAA,oBAAoBC,EAAWF,CAAmB,EAClD,SAAA,oBAAoBG,EAASF,CAAqB,CAAA,CAC7D,EACC,CAACV,CAAW,CAAC,EAET,CAAE,SAAAC,CAAS,CACpB"}