koval-ui
Version:
React components collection with minimalistic design. Supports theming, layout, and input validation.
1 lines • 3.22 kB
Source Map (JSON)
{"version":3,"file":"useFocusTrap.cjs","sources":["../../../../src/internal/hooks/useFocusTrap.ts"],"sourcesContent":["import type {KeyboardEvent} from 'react';\nimport {useCallback, useEffect, useRef, useState} from 'react';\n\nimport {EventType, useEventListener} from '@/internal/hooks/useEventListener.ts';\n\n/**\n * React hook. Makes provided HTMLElement retain focus inside. Works conditionally using last parameter.\n */\nexport const useFocusTrap = (element: HTMLElement | null, isOpen: boolean, condition = true) => {\n const focusableElementsRef = useRef<NodeListOf<HTMLElement>>(null);\n const [elements, setElements] = useState<(HTMLElement | null)[]>([]);\n useEffect(() => {\n if (condition && isOpen) {\n // @ts-expect-error TS2540: Cannot assign to current because it is a read-only property.\n focusableElementsRef.current = element?.querySelectorAll(\n 'button, [href], input, select, textarea, [tabindex]:not([tabindex=\"-1\"])'\n );\n const first = focusableElementsRef.current ? focusableElementsRef.current[0] : null;\n const last = focusableElementsRef.current\n ? focusableElementsRef.current[focusableElementsRef.current.length - 1]\n : null;\n setElements([first, last]);\n }\n }, [isOpen, element, condition]);\n\n useEffect(() => {\n condition && isOpen && elements[0]?.focus();\n }, [condition, elements, isOpen]);\n\n const handleTabKeyPress = useCallback(\n (event: KeyboardEvent) => {\n const [first, last] = elements;\n if (condition && isOpen && event.key === 'Tab') {\n if (event.shiftKey && document.activeElement === first) {\n event.preventDefault();\n last!.focus();\n } else if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault();\n first!.focus();\n }\n }\n },\n [condition, elements, isOpen]\n );\n\n useEventListener(EventType.keydown, handleTabKeyPress);\n};\n"],"names":["useFocusTrap","element","isOpen","condition","focusableElementsRef","useRef","elements","setElements","useState","useEffect","first","last","handleTabKeyPress","useCallback","event","useEventListener","EventType"],"mappings":"0JAQaA,EAAe,CAACC,EAA6BC,EAAiBC,EAAY,KAAS,CAC5F,MAAMC,EAAuBC,EAAAA,OAAgC,IAAI,EAC3D,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAAiC,CAAA,CAAE,EACnEC,EAAAA,UAAU,IAAM,CACZ,GAAIN,GAAaD,EAAQ,CAErBE,EAAqB,QAAUH,GAAS,iBACpC,0EAAA,EAEJ,MAAMS,EAAQN,EAAqB,QAAUA,EAAqB,QAAQ,CAAC,EAAI,KACzEO,EAAOP,EAAqB,QAC5BA,EAAqB,QAAQA,EAAqB,QAAQ,OAAS,CAAC,EACpE,KACNG,EAAY,CAACG,EAAOC,CAAI,CAAC,CAC7B,CACJ,EAAG,CAACT,EAAQD,EAASE,CAAS,CAAC,EAE/BM,EAAAA,UAAU,IAAM,CACZN,GAAaD,GAAUI,EAAS,CAAC,GAAG,MAAA,CACxC,EAAG,CAACH,EAAWG,EAAUJ,CAAM,CAAC,EAEhC,MAAMU,EAAoBC,EAAAA,YACrBC,GAAyB,CACtB,KAAM,CAACJ,EAAOC,CAAI,EAAIL,EAClBH,GAAaD,GAAUY,EAAM,MAAQ,QACjCA,EAAM,UAAY,SAAS,gBAAkBJ,GAC7CI,EAAM,eAAA,EACNH,EAAM,MAAA,GACC,CAACG,EAAM,UAAY,SAAS,gBAAkBH,IACrDG,EAAM,eAAA,EACNJ,EAAO,MAAA,GAGnB,EACA,CAACP,EAAWG,EAAUJ,CAAM,CAAA,EAGhCa,mBAAiBC,EAAAA,UAAU,QAASJ,CAAiB,CACzD"}