'use client' import { Modal as HeroModal } from '@heroui/react' import React, { type PropsWithChildren } from 'react' import Button from '@/components/formElements/Button' import { useMediaQuery } from '@/hooks/useMediaQuery' import { cn } from '@/lib/cn' import { texts } from '@/texts' interface ModalProps { isOpen: boolean onOpenChange: (isOpen: boolean) => void onClose?: () => void onAccept?: () => void onReject?: () => void isLoading?: boolean isDismissable?: boolean title?: string acceptBtnText?: string rejectBtnText?: string acceptBtnDisabled?: boolean rejectBtnDisabled?: boolean hideCloseButton?: boolean hideHeader?: boolean hideFooter?: boolean className?: string containerClassName?: string bodyClassName?: string headerClassName?: string footerClassName?: string headerChildren?: React.ReactNode footerChildren?: React.ReactNode size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | 'full' radius?: 'none' | 'sm' | 'md' | 'lg' shadow?: undefined | 'sm' | 'md' | 'lg' /** `auto` (default): bottom sheet on mobile, centered on desktop. */ placement?: 'auto' | 'top' | 'center' | 'bottom' scrollBehavior?: 'normal' | 'inside' | 'outside' backdrop?: 'transparent' | 'opaque' | 'blur' acceptDanger?: boolean } const Modal = ({ isOpen, onOpenChange, onClose, onAccept, onReject, isLoading = false, isDismissable = true, title = '', children, acceptBtnText = texts.common.confirmPlain, rejectBtnText = texts.common.close, acceptBtnDisabled = false, rejectBtnDisabled = false, hideCloseButton = false, hideHeader = false, hideFooter = false, className = '', containerClassName = '', bodyClassName = '', headerClassName = '', footerClassName = '', headerChildren, footerChildren, size = 'md', radius = 'md', shadow = 'lg', placement = 'auto', scrollBehavior = 'inside', backdrop = 'opaque', acceptDanger = false, }: PropsWithChildren) => { const isMobile = useMediaQuery('(max-width: 768px)') const resolvedPlacement = placement === 'auto' ? (isMobile ? 'bottom' : 'center') : placement const isBottomSheet = resolvedPlacement === 'bottom' && isMobile const getMaxWidth = (modalSize: string): string => { const sizeMap: Record = { xs: 'max-w-[320px]', sm: 'max-w-[384px]', md: 'max-w-[448px]', lg: 'max-w-[512px]', xl: 'max-w-[640px]', '2xl': 'max-w-[768px]', '3xl': 'max-w-[896px]', '4xl': 'max-w-[1024px]', '5xl': 'max-w-[1280px]', full: 'max-w-full', } return sizeMap[modalSize] || 'max-w-full' } const closeHandler = () => { onOpenChange(false) onClose?.() } const handleOpenChange = (nextOpen: boolean) => { onOpenChange(nextOpen) if (!nextOpen) onClose?.() } const normalizedSize = size === 'full' ? 'full' : ['xs', 'sm', 'md', 'lg'].includes(size) ? (size as 'xs' | 'sm' | 'md' | 'lg') : 'lg' const radiusClass = radius === 'none' ? 'rounded-none' : radius === 'sm' ? 'rounded-lg' : radius === 'lg' ? 'rounded-3xl' : 'rounded-2xl' const shadowClass = shadow === 'sm' ? 'shadow-sm' : shadow === 'md' ? 'shadow-md' : shadow === 'lg' ? 'shadow-lg' : '' return ( {!hideCloseButton && !isLoading ? : null} {!hideHeader && ( {headerChildren} {title} )} {children} {!hideFooter && ( {footerChildren ?? ( <> )} )} ) } export default Modal