import gsap from "gsap"; const MODAL_MAX_Y_OFFSET = 106; const BUTTONS_MAX_Y_OFFSET = 20; const BUTTONS_TIME = 0.1; const MODAL_TIME = 0.225; const state = useState("confirmationModal", () => reactive({ isOpen: false, text: "", onConfirm: null as (() => void) | null, offsetY: MODAL_MAX_Y_OFFSET, buttonsYOffset: 0, modalButtonsYOffset: BUTTONS_MAX_Y_OFFSET, isVisible: false, isClosing: false, }), ); const open = (text: string, onConfirm?: (() => void) | null) => { gsap.killTweensOf(state.value); state.value.text = text; state.value.onConfirm = onConfirm || null; state.value.isVisible = true; state.value.isClosing = false; state.value.isOpen = true; gsap .timeline() // standard buttons down .fromTo( state.value, { buttonsYOffset: 0 }, { buttonsYOffset: BUTTONS_MAX_Y_OFFSET, duration: BUTTONS_TIME, ease: "none", }, ) // modal up .fromTo( state.value, { offsetY: MODAL_MAX_Y_OFFSET }, { offsetY: 0, duration: MODAL_TIME, ease: "none" }, ) // modal buttons up .fromTo( state.value, { modalButtonsYOffset: BUTTONS_MAX_Y_OFFSET }, { modalButtonsYOffset: 0, duration: BUTTONS_TIME, ease: "none" }, ); }; const close = () => { if (!state.value.isVisible || state.value.isClosing) return; state.value.isClosing = true; gsap .timeline() // modal buttons down .to(state.value, { modalButtonsYOffset: BUTTONS_MAX_Y_OFFSET, duration: BUTTONS_TIME, ease: "none", }) // modal down .to(state.value, { offsetY: MODAL_MAX_Y_OFFSET, duration: MODAL_TIME, ease: "none", }) // standard buttons up .to(state.value, { buttonsYOffset: 0, duration: BUTTONS_TIME, ease: "none", }) .call(() => { state.value.isVisible = false; state.value.isClosing = false; state.value.isOpen = false; state.value.text = ""; state.value.onConfirm = null; }); }; export const useConfirmationModal = () => ({ open, close, state: readonly(state), });