mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 05:22:02 +00:00
105 lines
2.2 KiB
TypeScript
105 lines
2.2 KiB
TypeScript
'use client';
|
|
|
|
import {
|
|
ReactNode,
|
|
RefObject,
|
|
useCallback,
|
|
useEffect,
|
|
useRef,
|
|
useState,
|
|
} from 'react';
|
|
import { cn } from '@/lib/helper';
|
|
|
|
export const useModal = (isNestingModal = false) => {
|
|
const ref = useRef<HTMLDialogElement>(null);
|
|
const [open, setOpen] = useState(false);
|
|
|
|
const openModal = useCallback(() => {
|
|
if (!ref.current) return;
|
|
if (isNestingModal) {
|
|
ref.current.showModal();
|
|
} else {
|
|
ref.current.show();
|
|
}
|
|
setOpen(true);
|
|
}, [isNestingModal]);
|
|
|
|
const closeModal = useCallback(() => {
|
|
if (!ref.current) return;
|
|
ref.current.close();
|
|
setOpen(false);
|
|
}, []);
|
|
|
|
const toggle = useCallback(() => {
|
|
if (open) {
|
|
closeModal();
|
|
} else {
|
|
openModal();
|
|
}
|
|
}, [open, closeModal, openModal]);
|
|
|
|
useEffect(() => {
|
|
const dialog = ref.current;
|
|
if (!dialog) return;
|
|
|
|
const handleClose = () => setOpen(false);
|
|
dialog.addEventListener('close', handleClose);
|
|
|
|
return () => {
|
|
dialog.removeEventListener('close', handleClose);
|
|
};
|
|
}, []);
|
|
|
|
return { ref, open, openModal, closeModal, toggle } as const;
|
|
};
|
|
|
|
interface ModalProps {
|
|
ref: RefObject<HTMLDialogElement | null>;
|
|
children?: ReactNode;
|
|
closeOnBackdrop?: boolean;
|
|
onBackdropClick?: () => void;
|
|
position?: 'top' | 'middle' | 'bottom' | 'start' | 'end';
|
|
className?: {
|
|
modal?: string;
|
|
modalBox?: string;
|
|
};
|
|
}
|
|
|
|
const Modal = ({
|
|
ref,
|
|
children,
|
|
closeOnBackdrop,
|
|
onBackdropClick,
|
|
position = 'middle',
|
|
className,
|
|
}: ModalProps) => {
|
|
const handleBackdropClick = (e: React.MouseEvent<HTMLDialogElement>) => {
|
|
if (closeOnBackdrop && e.target === ref.current) {
|
|
onBackdropClick?.();
|
|
ref.current?.close();
|
|
}
|
|
};
|
|
|
|
return (
|
|
<dialog
|
|
ref={ref}
|
|
className={cn(
|
|
'modal',
|
|
{
|
|
'modal-top': position === 'top',
|
|
'modal-middle': position === 'middle',
|
|
'modal-bottom': position === 'bottom',
|
|
'modal-start': position === 'start',
|
|
'modal-end': position === 'end',
|
|
},
|
|
className?.modal
|
|
)}
|
|
onClick={handleBackdropClick}
|
|
>
|
|
<div className={cn('modal-box', className?.modalBox)}>{children}</div>
|
|
</dialog>
|
|
);
|
|
};
|
|
|
|
export default Modal;
|