koval-ui
Version:
React components collection with minimalistic design. Supports theming, layout, and input validation.
1 lines • 3.24 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","_a","handleTabKeyPress","useCallback","event","useEventListener","EventType"],"mappings":"0JAQaA,EAAe,CAACC,EAA6BC,EAAiBC,EAAY,KAAS,CACtF,MAAAC,EAAuBC,SAAgC,IAAI,EAC3D,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAAiC,CAAA,CAAE,EACnEC,EAAAA,UAAU,IAAM,CACZ,GAAIN,GAAaD,EAAQ,CAErBE,EAAqB,QAAUH,GAAA,YAAAA,EAAS,iBACpC,4EAEJ,MAAMS,EAAQN,EAAqB,QAAUA,EAAqB,QAAQ,CAAC,EAAI,KACzEO,EAAOP,EAAqB,QAC5BA,EAAqB,QAAQA,EAAqB,QAAQ,OAAS,CAAC,EACpE,KACMG,EAAA,CAACG,EAAOC,CAAI,CAAC,CAAA,CAE9B,EAAA,CAACT,EAAQD,EAASE,CAAS,CAAC,EAE/BM,EAAAA,UAAU,IAAM,OACZN,GAAaD,KAAUU,EAAAN,EAAS,CAAC,IAAV,MAAAM,EAAa,QACrC,EAAA,CAACT,EAAWG,EAAUJ,CAAM,CAAC,EAEhC,MAAMW,EAAoBC,EAAA,YACrBC,GAAyB,CAChB,KAAA,CAACL,EAAOC,CAAI,EAAIL,EAClBH,GAAaD,GAAUa,EAAM,MAAQ,QACjCA,EAAM,UAAY,SAAS,gBAAkBL,GAC7CK,EAAM,eAAe,EACrBJ,EAAM,MAAM,GACL,CAACI,EAAM,UAAY,SAAS,gBAAkBJ,IACrDI,EAAM,eAAe,EACrBL,EAAO,MAAM,GAGzB,EACA,CAACP,EAAWG,EAAUJ,CAAM,CAChC,EAEiBc,mBAAAC,EAAAA,UAAU,QAASJ,CAAiB,CACzD"}