useModal.ts•1.49 kB
import { FormEvent, useCallback, useState } from "react";
import { useBoolean } from "@/utils";
export default function useModal<ModalState extends object, ConfirmActionEvent = FormEvent<HTMLFormElement>>(initiallyOpen?: boolean, confirmCallback?: (state: ModalState, event?: ConfirmActionEvent) => Promise<void> | void) {
const [modalState, setModalState] = useState<ModalState>();
const [isActionLoading, setLoading] = useState(false);
const {
value: isModalOpen,
setTrue: openModalInternal,
setFalse: closeModalInternal,
} = useBoolean(initiallyOpen || false);
const openModal = useCallback((state?: ModalState) => {
if (state) {
setModalState(state);
}
openModalInternal();
}, [openModalInternal]);
const closeModal = useCallback(() => {
closeModalInternal();
setModalState({} as ModalState);
}, [closeModalInternal]);
const confirmAction = useCallback((event?: ConfirmActionEvent) => {
if (confirmCallback) {
setLoading(true);
const maybePromise = confirmCallback(modalState as ModalState, event);
if (maybePromise instanceof Promise) {
return maybePromise
.finally(closeModal)
.finally(() => setLoading(false));
} else {
closeModal();
return maybePromise; // Not a promise.
}
}
}, [closeModal, confirmCallback, modalState]);
return {
isModalOpen,
openModal,
closeModal,
confirmAction,
isActionLoading,
};
}