``` ~/go/bin/sourcemapper -output ddb -jsurl https://media.dndbeyond.com/character-app/static/js/main.90aa78c5.js ```
117 lines
3.5 KiB
TypeScript
117 lines
3.5 KiB
TypeScript
import clsx from "clsx";
|
|
import { FC, useEffect } from "react";
|
|
|
|
import CloseIcon from "@dndbeyond/fontawesome-cache/svgs/solid/x.svg";
|
|
import { Dialog, DialogProps } from "@dndbeyond/ttui/components/Dialog";
|
|
|
|
import { Button, ButtonProps } from "../Button";
|
|
import styles from "./styles.module.css";
|
|
|
|
/**
|
|
* @heading Text for the title of the modal - defaults to "Confirm"
|
|
* @onClose Function to call when the Close button is clicked
|
|
* @onConfirm Function to call when the Confirm button is clicked
|
|
* @confirmButtonText Provide text to the Confirm button - defaults to "Confirm"
|
|
* @closeButtonText Provide text to the Close button - defaults to "Cancel"
|
|
* @variant "default" | "remove" | "confirm-only"
|
|
* --default: default modal with both Confirm and Close buttons using the "success" button color
|
|
* --remove: modal with both Confirm and Close buttons using the "secondary" color for the header and Confirm button
|
|
* --confirm-only: modal with only the Confirm button using the "success" button color
|
|
* @size "default" | "fit-content"
|
|
* --default: default modal size
|
|
* --fit-content: modal size adjusts to the content
|
|
* @color Passes a ButtonProps color to the confirm button
|
|
* @useMobileFullScreen Boolean to set the modal to full screen on mobile breakpoint
|
|
*/
|
|
export interface ConfirmModalProps extends DialogProps {
|
|
heading?: string;
|
|
onClose: () => void;
|
|
onConfirm: () => void;
|
|
confirmButtonText?: string;
|
|
closeButtonText?: string;
|
|
variant?: "default" | "remove" | "confirm-only";
|
|
size?: "default" | "fit-content";
|
|
color?: ButtonProps["color"];
|
|
useMobileFullScreen?: boolean;
|
|
}
|
|
|
|
export const ConfirmModal: FC<ConfirmModalProps> = ({
|
|
children,
|
|
className,
|
|
heading = "Confirm",
|
|
onClose,
|
|
onConfirm,
|
|
confirmButtonText = "Confirm",
|
|
closeButtonText = "Cancel",
|
|
open,
|
|
variant = "default",
|
|
size = "default",
|
|
color = "success",
|
|
useMobileFullScreen,
|
|
...props
|
|
}) => {
|
|
const isConfirmOnly = variant === "confirm-only";
|
|
|
|
useEffect(() => {
|
|
const body = document.querySelector("body");
|
|
if (!body) return;
|
|
|
|
// Prevent scrolling when modal is visible
|
|
if (open) {
|
|
body.style.overflow = "hidden";
|
|
} else {
|
|
body.style.overflow = "";
|
|
}
|
|
}, [open]);
|
|
|
|
return (
|
|
<Dialog
|
|
className={clsx([
|
|
styles.confirmModal,
|
|
useMobileFullScreen && styles.fullScreen,
|
|
styles[variant],
|
|
styles[size],
|
|
className,
|
|
])}
|
|
onClose={onClose}
|
|
modal
|
|
open={open}
|
|
{...props}
|
|
>
|
|
<header className={styles.header}>
|
|
<h2>{heading}</h2>
|
|
<Button
|
|
className={styles.closeButton}
|
|
size="x-small"
|
|
variant="text"
|
|
onClick={onClose}
|
|
aria-label={`Close ${heading} Modal`}
|
|
forceThemeMode="light"
|
|
>
|
|
<CloseIcon className={styles.closeIcon} />
|
|
</Button>
|
|
</header>
|
|
<div className={styles.content}>{children}</div>
|
|
<footer className={styles.footer}>
|
|
{!isConfirmOnly && (
|
|
<Button className={styles.footerButton} onClick={onClose}>
|
|
{closeButtonText}
|
|
</Button>
|
|
)}
|
|
<Button
|
|
className={clsx([
|
|
styles.footerButton,
|
|
isConfirmOnly && styles.confirmOnly,
|
|
])}
|
|
color={variant === "remove" ? "secondary" : color}
|
|
onClick={onConfirm}
|
|
forceThemeMode="light"
|
|
size={isConfirmOnly ? "x-small" : undefined}
|
|
>
|
|
{confirmButtonText}
|
|
</Button>
|
|
</footer>
|
|
</Dialog>
|
|
);
|
|
};
|