11import { Options as FocusTrapOptions } from 'focus-trap' ;
2+ import FocusTrap from 'focus-trap-react' ;
23import React , { useMemo , useRef } from 'react' ;
34import { createPortal } from 'react-dom' ;
45import { ModalProps , OverlayProps , WrapperProps } from '..' ;
56
67import { useBodyScrollLock } from '../hooks/useBodyScrollLock' ;
7- import { useFocusTrap } from '../hooks/useFocusTrap' ;
88
99interface ModalWrapperProps < T extends Record < string , unknown > > {
1010 children : React . ReactNode ;
1111 isOpen : boolean ;
12+ open : ( ) => void ;
1213 close : ( ) => void ;
1314 elementId : 'root' | string ;
1415 title ?: React . ReactNode ;
@@ -26,6 +27,7 @@ interface ModalWrapperProps<T extends Record<string, unknown>> {
2627export const ModalWrapper = < T extends Record < string , unknown > > ( {
2728 children,
2829 isOpen,
30+ open,
2931 close,
3032 elementId = 'root' ,
3133 title,
@@ -36,15 +38,24 @@ export const ModalWrapper = <T extends Record<string, unknown>>({
3638 additionalProps,
3739} : ModalWrapperProps < T > ) : React . ReactElement | null => {
3840 const dialogRef = useRef < HTMLDivElement > ( null ) ;
39- const _focusTrapOptions = useMemo (
41+ const _focusTrapOptions : FocusTrapOptions = useMemo (
4042 ( ) => ( {
41- onDeactivate : close ,
42- clickOutsideDeactivates : true ,
4343 ...focusTrapOptions ,
44+ onActivate : ( ) => {
45+ open ( ) ;
46+ focusTrapOptions . onActivate ?.( ) ;
47+ } ,
48+ onDeactivate : ( ) => {
49+ close ( ) ;
50+ focusTrapOptions . onDeactivate ?.( ) ;
51+ } ,
52+ clickOutsideDeactivates : focusTrapOptions . clickOutsideDeactivates ?? true ,
53+ fallbackFocus :
54+ focusTrapOptions . fallbackFocus ?? dialogRef . current ?? undefined ,
4455 } ) ,
45- [ close , focusTrapOptions ]
56+ [ close , focusTrapOptions , open ]
4657 ) ;
47- useFocusTrap ( dialogRef , isOpen , _focusTrapOptions ) ;
58+
4859 useBodyScrollLock ( dialogRef , isOpen , preventScroll ) ;
4960
5061 if ( isOpen === false ) {
@@ -54,22 +65,24 @@ export const ModalWrapper = <T extends Record<string, unknown>>({
5465 return createPortal (
5566 < components . Wrapper >
5667 < components . Overlay />
57- < div
58- ref = { dialogRef }
59- role = "dialog"
60- aria-modal = "true"
61- tabIndex = { - 1 }
62- style = { { position : 'relative' } }
63- >
64- < components . Modal
65- title = { title }
66- description = { description }
67- close = { close }
68- additionalProps = { additionalProps }
68+ < FocusTrap focusTrapOptions = { _focusTrapOptions } >
69+ < div
70+ ref = { dialogRef }
71+ role = "dialog"
72+ aria-modal = "true"
73+ tabIndex = { - 1 }
74+ style = { { position : 'relative' } }
6975 >
70- { children }
71- </ components . Modal >
72- </ div >
76+ < components . Modal
77+ title = { title }
78+ description = { description }
79+ close = { close }
80+ additionalProps = { additionalProps }
81+ >
82+ { children }
83+ </ components . Modal >
84+ </ div >
85+ </ FocusTrap >
7386 </ components . Wrapper > ,
7487 document . getElementById ( elementId ) as HTMLElement
7588 ) ;
0 commit comments