103 lines
2.2 KiB
TypeScript
103 lines
2.2 KiB
TypeScript
import { Modal } from '../modal';
|
|
import { Button } from '../button';
|
|
import { cn } from '@/lib/utils';
|
|
import { AlertCircle, Info } from 'lucide-react';
|
|
import type { DialogProps, DialogVariant } from './types';
|
|
|
|
const variantIcons: Record<
|
|
DialogVariant,
|
|
typeof AlertCircle | typeof Info | undefined
|
|
> = {
|
|
alert: AlertCircle,
|
|
confirm: AlertCircle,
|
|
info: Info,
|
|
default: undefined,
|
|
};
|
|
|
|
const variantStyles: Record<DialogVariant, string> = {
|
|
alert: 'text-destructive',
|
|
confirm: 'text-primary',
|
|
info: 'text-muted-foreground',
|
|
default: '',
|
|
};
|
|
|
|
export function Dialog({
|
|
open,
|
|
onClose,
|
|
onOpenChange,
|
|
title,
|
|
children,
|
|
footer,
|
|
variant = 'default',
|
|
onConfirm,
|
|
onCancel,
|
|
confirmLabel = 'Confirm',
|
|
cancelLabel = 'Cancel',
|
|
showCancel = true,
|
|
size = 'md',
|
|
}: DialogProps) {
|
|
const handleClose = () => {
|
|
if (onOpenChange) {
|
|
onOpenChange(false);
|
|
} else if (onClose) {
|
|
onClose();
|
|
}
|
|
};
|
|
|
|
const handleConfirm = async () => {
|
|
if (onConfirm) {
|
|
await onConfirm();
|
|
}
|
|
handleClose();
|
|
};
|
|
|
|
const handleCancel = () => {
|
|
if (onCancel) {
|
|
onCancel();
|
|
}
|
|
handleClose();
|
|
};
|
|
|
|
const IconComponent = variantIcons[variant];
|
|
const iconStyle = variantStyles[variant];
|
|
|
|
return (
|
|
<Modal
|
|
open={open}
|
|
onClose={handleClose}
|
|
size={size}
|
|
closeOnOverlayClick={variant === 'default'}
|
|
title={title}
|
|
footer={
|
|
footer || onConfirm || onCancel ? (
|
|
footer ? (
|
|
footer
|
|
) : (
|
|
<div className="flex justify-end gap-2">
|
|
{showCancel && (
|
|
<Button variant="outline" onClick={handleCancel}>
|
|
{cancelLabel}
|
|
</Button>
|
|
)}
|
|
{onConfirm && (
|
|
<Button
|
|
variant={variant === 'alert' ? 'destructive' : 'default'}
|
|
onClick={handleConfirm}
|
|
>
|
|
{confirmLabel}
|
|
</Button>
|
|
)}
|
|
</div>
|
|
)
|
|
) : undefined
|
|
}
|
|
>
|
|
{title && IconComponent && (
|
|
<div className="flex items-center gap-4 mb-4">
|
|
<IconComponent className={cn('h-5 w-5', iconStyle)} />
|
|
</div>
|
|
)}
|
|
{children}
|
|
</Modal>
|
|
);
|
|
}
|