import { Modal as RNModal, Pressable, StyleProp, TextStyle, View, ViewStyle } from "react-native" import { useAppTheme } from "@/theme/context" import type { ThemedStyle } from "@/theme/types" import { s } from "@/utils/responsive" import { Button } from "./Button" import { Text, TextProps } from "./Text" type Presets = "default" | "destructive" export interface DialogProps { /** * Whether the dialog is visible. */ visible: boolean /** * Callback when the dialog is closed. */ onClose: () => void /** * Dialog preset style. * - `default`: Normal dialog with filled confirm button * - `destructive`: Dangerous action with red confirm button * @default "default" */ preset?: Presets /** * Title text which is looked up via i18n. */ titleTx?: TextProps["tx"] /** * Title text to display if not using `titleTx`. */ title?: string /** * Optional title options to pass to i18n. */ titleTxOptions?: TextProps["txOptions"] /** * Message text which is looked up via i18n. */ messageTx?: TextProps["tx"] /** * Message text to display if not using `messageTx`. */ message?: string /** * Optional message options to pass to i18n. */ messageTxOptions?: TextProps["txOptions"] /** * Confirm button text which is looked up via i18n. * @default "common:ok" */ confirmTx?: TextProps["tx"] /** * Confirm button text to display if not using `confirmTx`. */ confirmText?: string /** * Callback when confirm button is pressed. */ onConfirm?: () => void /** * Cancel button text which is looked up via i18n. * @default "common:cancel" */ cancelTx?: TextProps["tx"] /** * Cancel button text to display if not using `cancelTx`. */ cancelText?: string /** * Callback when cancel button is pressed. If not provided, cancel button will not be shown. */ onCancel?: () => void /** * Whether to show the cancel button. * @default true (if onCancel is provided) */ showCancel?: boolean /** * Whether the confirm button is in loading state. */ loading?: boolean /** * Whether to close the dialog when pressing the overlay. * @default false */ closeOnOverlayPress?: boolean /** * Style overrides for the content container. */ contentStyle?: StyleProp } /** * A simple dialog component for confirmations and alerts. * Use this for simple confirm/cancel dialogs. For complex content, use Modal instead. * @param {DialogProps} props - The props for the `Dialog` component. * @returns {JSX.Element} The rendered `Dialog` component. * @example * // Simple alert * setShowAlert(false)} * title="Success" * message="Operation completed successfully." * onConfirm={() => setShowAlert(false)} * /> * * @example * // Destructive confirmation * setShowConfirm(false)} * preset="destructive" * titleTx="common:confirm" * messageTx="session:confirmLogoutMessage" * confirmTx="session:logout" * onConfirm={handleLogout} * onCancel={() => setShowConfirm(false)} * /> */ export function Dialog(props: DialogProps) { const { visible, onClose, preset = "default", titleTx, title, titleTxOptions, messageTx, message, messageTxOptions, confirmTx = "common:ok", confirmText, onConfirm, cancelTx = "common:cancel", cancelText, onCancel, showCancel = !!onCancel, loading = false, closeOnOverlayPress = false, contentStyle: $contentStyleOverride, } = props const { themed, theme } = useAppTheme() const isDestructive = preset === "destructive" const handleConfirm = () => { onConfirm?.() } const handleCancel = () => { onCancel?.() onClose() } const handleOverlayPress = () => { if (closeOnOverlayPress) { onClose() } } const $confirmButtonStyle: StyleProp = [ themed($button), isDestructive && themed($destructiveButton), ] return ( e.stopPropagation()} > {/* Title */} {(titleTx || title) && ( )} {/* Message */} {(messageTx || message) && ( )} {/* Buttons */} {showCancel && (