1- import { useCallback , useEffect } from 'react'
1+ import { createContext , useCallback , useContext , useEffect , useMemo , useState } from 'react'
22import FocusTrap from 'focus-trap-react'
33
4+ import { noop } from '@Common/Helper'
45import { ALLOW_ACTION_OUTSIDE_FOCUS_TRAP } from '@Shared/constants'
56import { preventBodyScroll } from '@Shared/Helpers'
67
78import { DTFocusTrapType } from './types'
89
10+ const FocusTrapControlContext = createContext < {
11+ disableFocusTrap : ( ) => void
12+ resumeFocusTrap : ( ) => void
13+ } > ( null )
14+
15+ export const useFocusTrapControl = ( ) => {
16+ const context = useContext ( FocusTrapControlContext )
17+ if ( ! context ) {
18+ return {
19+ disableFocusTrap : noop ,
20+ resumeFocusTrap : noop ,
21+ }
22+ }
23+ return context
24+ }
25+
926const DTFocusTrap = ( {
1027 onEscape,
1128 deactivateFocusOnEscape = true ,
1229 children,
1330 initialFocus = undefined ,
1431} : DTFocusTrapType ) => {
32+ const [ isFocusEnabled , setIsFocusEnabled ] = useState ( true )
33+
1534 const handleEscape = useCallback (
1635 ( e ?: KeyboardEvent | MouseEvent ) => {
1736 onEscape ( e )
@@ -28,28 +47,39 @@ const DTFocusTrap = ({
2847 }
2948 } , [ ] )
3049
50+ const focusContextValue = useMemo (
51+ ( ) => ( {
52+ disableFocusTrap : ( ) => setIsFocusEnabled ( false ) ,
53+ resumeFocusTrap : ( ) => setIsFocusEnabled ( true ) ,
54+ } ) ,
55+ [ ] ,
56+ )
57+
3158 return (
32- < FocusTrap
33- focusTrapOptions = { {
34- escapeDeactivates : handleEscape ,
35- initialFocus,
36- allowOutsideClick : ( event ) => {
37- // Allow up to 3 parent levels to check for the allowed class
38- let el = event . target as Element | null
39- let depth = 0
40- while ( el && depth < 4 ) {
41- if ( el . classList && el . classList . contains ( ALLOW_ACTION_OUTSIDE_FOCUS_TRAP ) ) {
42- return true
59+ < FocusTrapControlContext . Provider value = { focusContextValue } >
60+ < FocusTrap
61+ active = { isFocusEnabled }
62+ focusTrapOptions = { {
63+ escapeDeactivates : handleEscape ,
64+ initialFocus,
65+ allowOutsideClick : ( event ) => {
66+ // Allow up to 3 parent levels to check for the allowed class
67+ let el = event . target as Element | null
68+ let depth = 0
69+ while ( el && depth < 4 ) {
70+ if ( el . classList && el . classList . contains ( ALLOW_ACTION_OUTSIDE_FOCUS_TRAP ) ) {
71+ return true
72+ }
73+ el = el . parentElement
74+ depth += 1
4375 }
44- el = el . parentElement
45- depth += 1
46- }
47- return false
48- } ,
49- } }
50- >
51- { children }
52- </ FocusTrap >
76+ return false
77+ } ,
78+ } }
79+ >
80+ { children }
81+ </ FocusTrap >
82+ </ FocusTrapControlContext . Provider >
5383 )
5484}
5585
0 commit comments