11import { Dialog , Transition } from "@headlessui/react" ;
2- import React , { Fragment , useRef } from "react" ;
2+ import React , { Fragment , useRef , useState } from "react" ;
33import { Badge } from "@/components/ui/badge" ;
44import { Icon } from "@iconify-icon/react" ;
55import { ObjectHelpButton } from "@/components/menu/object-help-button" ;
66import { useAtomValue } from "jotai/index" ;
77import { currentBranchAtom } from "@/state/atoms/branches.atom" ;
88import { IModelSchema } from "@/state/atoms/schema.atom" ;
9+ import ModalDelete from "../modals/modal-delete" ;
910
1011interface Props {
1112 open : boolean ;
@@ -15,9 +16,16 @@ interface Props {
1516 offset ?: number ;
1617}
1718
19+ interface SlideOverContextProps {
20+ setPreventClose ?: ( value : boolean ) => void ;
21+ }
22+
23+ export const SlideOverContext = React . createContext < SlideOverContextProps > ( { } ) ;
24+
1825export default function SlideOver ( props : Props ) {
1926 const { open, setOpen, title, offset = 0 } = props ;
2027 const initialFocusRef = useRef ( null ) ;
28+ const [ preventClose , setPreventClose ] = useState ( false ) ;
2129
2230 // Need to define full classes so tailwind can compile the css
2331 const panelWidth = "w-[400px]" ;
@@ -27,52 +35,69 @@ export default function SlideOver(props: Props) {
2735 1 : "-translate-x-[400px]" ,
2836 } ;
2937
38+ const context = {
39+ isOpen : open || ( ! open && preventClose ) ,
40+ setPreventClose : ( value : boolean ) => setPreventClose ( value ) ,
41+ } ;
42+
3043 return (
31- < Transition . Root show = { open } as = { Fragment } >
32- < Dialog as = "div" className = "relative z-10" onClose = { setOpen } initialFocus = { initialFocusRef } >
33- < Transition . Child
34- as = { Fragment }
35- enter = "ease-in-out duration-500"
36- enterFrom = "opacity-0"
37- enterTo = "opacity-100"
38- leave = "ease-in-out duration-500"
39- leaveFrom = "opacity-100"
40- leaveTo = "opacity-0" >
41- < div
42- className = "fixed inset-0 bg-black bg-opacity-40 transition-opacity"
43- data-cy = "side-panel-background"
44- data-testid = "side-panel-background"
45- />
46- </ Transition . Child >
47-
48- < div className = "before:fixed inset-0 overflow-hidden" >
49- < div className = "absolute inset-0 overflow-hidden" >
50- < div className = "pointer-events-none fixed inset-y-0 right-0 flex" >
51- < button type = "button" tabIndex = { - 1 } ref = { initialFocusRef } />
52- < Transition . Child
53- as = { Fragment }
54- enter = "transform transition ease-in-out duration-500"
55- enterFrom = "translate-x-full"
56- enterTo = { `${ offestWidth [ offset ] } ` }
57- leave = "transform transition ease-in-out duration-500"
58- leaveFrom = { `${ offestWidth [ offset ] } ` }
59- leaveTo = "translate-x-full" >
60- < Dialog . Panel
61- className = { `bg-custom-white pointer-events-auto shadow-xl flex flex-col ${ panelWidth } ${ offestWidth [ offset ] } ` }
62- data-testid = "side-panel-container" >
63- < div className = "px-4 py-4 sm:px-4 bg-gray-50 border-b" >
64- < div className = "w-full" >
65- < Dialog . Title className = "text-base leading-6" > { title } </ Dialog . Title >
44+ < SlideOverContext . Provider value = { context } >
45+ < Transition . Root show = { open || ( ! open && preventClose ) } as = { Fragment } >
46+ < Dialog as = "div" className = "relative z-10" onClose = { setOpen } initialFocus = { initialFocusRef } >
47+ < Transition . Child
48+ as = { Fragment }
49+ enter = "ease-in-out duration-500"
50+ enterFrom = "opacity-0"
51+ enterTo = "opacity-100"
52+ leave = "ease-in-out duration-500"
53+ leaveFrom = "opacity-100"
54+ leaveTo = "opacity-0" >
55+ < div
56+ className = "fixed inset-0 bg-black bg-opacity-40 transition-opacity"
57+ data-cy = "side-panel-background"
58+ data-testid = "side-panel-background"
59+ />
60+ </ Transition . Child >
61+
62+ < div className = "before:fixed inset-0 overflow-hidden" >
63+ < div className = "absolute inset-0 overflow-hidden" >
64+ < div className = "pointer-events-none fixed inset-y-0 right-0 flex" >
65+ < button type = "button" tabIndex = { - 1 } ref = { initialFocusRef } />
66+ < Transition . Child
67+ as = { Fragment }
68+ enter = "transform transition ease-in-out duration-500"
69+ enterFrom = "translate-x-full"
70+ enterTo = { `${ offestWidth [ offset ] } ` }
71+ leave = "transform transition ease-in-out duration-500"
72+ leaveFrom = { `${ offestWidth [ offset ] } ` }
73+ leaveTo = "translate-x-full" >
74+ < Dialog . Panel
75+ className = { `bg-custom-white pointer-events-auto shadow-xl flex flex-col ${ panelWidth } ${ offestWidth [ offset ] } ` }
76+ data-testid = "side-panel-container" >
77+ < div className = "px-4 py-4 sm:px-4 bg-gray-50 border-b" >
78+ < div className = "w-full" >
79+ < Dialog . Title className = "text-base leading-6" > { title } </ Dialog . Title >
80+ </ div >
6681 </ div >
67- </ div >
68- { props . children }
69- </ Dialog . Panel >
70- </ Transition . Child >
82+ { props . children }
83+ </ Dialog . Panel >
84+ </ Transition . Child >
85+ </ div >
7186 </ div >
7287 </ div >
73- </ div >
74- </ Dialog >
75- </ Transition . Root >
88+ </ Dialog >
89+ </ Transition . Root >
90+
91+ < ModalDelete
92+ title = "Closing form"
93+ description = { "Are you sure you want to close this form? All unsaved changes will be lost." }
94+ onCancel = { ( ) => setOpen ( true ) }
95+ onDelete = { ( ) => setPreventClose ( false ) }
96+ open = { ! open && preventClose }
97+ setOpen = { ( ) => setPreventClose ( false ) }
98+ confirmLabel = "Close"
99+ />
100+ </ SlideOverContext . Provider >
76101 ) ;
77102}
78103
0 commit comments