import gsap from "gsap"; const MODAL_MAX_Y_OFFSET = 106; const BUTTONS_MAX_Y_OFFSET = 20; const BUTTONS_TIME = 0.167; const MODAL_TIME = 0.25; export const useConfirmationModal = defineStore("confirmationModal", { state: () => ({ isOpen: false, text: "", aLabel: null as string | null, bLabel: null as string | null, onConfirm: null as (() => void) | null, onCancel: null as (() => void) | null, onClosed: null as ((choice: "confirm" | "cancel") => void) | null, keepButtonsDown: null as | boolean | ((choice: "confirm" | "cancel") => boolean) | null, offsetY: MODAL_MAX_Y_OFFSET, buttonsYOffset: 0, modalButtonsYOffset: BUTTONS_MAX_Y_OFFSET, isVisible: false, isClosing: false, }), actions: { open(options: { text: string; aLabel?: string; bLabel?: string; onCancel?: () => void; onConfirm?: () => void; onClosed?: (choice: "confirm" | "cancel") => void; keepButtonsDown?: boolean | ((choice: "confirm" | "cancel") => boolean); timeout?: number; }) { gsap.killTweensOf(this); this.text = options.text; this.aLabel = options.aLabel ?? null; this.bLabel = options.bLabel ?? null; this.onConfirm = options.onConfirm ?? null; this.onCancel = options.onCancel ?? null; this.onClosed = options.onClosed ?? null; this.keepButtonsDown = options.keepButtonsDown ?? null; this.isVisible = true; this.isClosing = false; this.isOpen = true; gsap .timeline() // standard buttons down .fromTo( this, { buttonsYOffset: 0 }, { buttonsYOffset: BUTTONS_MAX_Y_OFFSET, duration: BUTTONS_TIME, ease: "none", }, ) // modal up .fromTo( this, { offsetY: MODAL_MAX_Y_OFFSET }, { offsetY: 0, duration: MODAL_TIME, ease: "none" }, ) // modal buttons up .fromTo( this, { modalButtonsYOffset: BUTTONS_MAX_Y_OFFSET }, { modalButtonsYOffset: 0, duration: BUTTONS_TIME, ease: "none" }, ) .call(() => { if (options.timeout) { setTimeout(() => { this.close("cancel"); }, options.timeout); } }); }, close(choice: "confirm" | "cancel") { if (!this.isVisible || this.isClosing) return; this.isClosing = true; const keepButtonsDown = typeof this.keepButtonsDown === "function" ? this.keepButtonsDown(choice) : !!this.keepButtonsDown; const tl = gsap .timeline() // modal buttons down .to(this, { modalButtonsYOffset: BUTTONS_MAX_Y_OFFSET, duration: BUTTONS_TIME, ease: "none", }) // modal down .to(this, { offsetY: MODAL_MAX_Y_OFFSET, duration: MODAL_TIME, ease: "none", }); if (!keepButtonsDown) { // standard buttons up tl.to(this, { buttonsYOffset: 0, duration: BUTTONS_TIME, ease: "none", }); } tl.call(() => { const closedCallback = this.onClosed; this.$reset(); if (keepButtonsDown) { this.buttonsYOffset = BUTTONS_MAX_Y_OFFSET; } closedCallback?.(choice); }); }, }, });