import * as React from "react"; import { createPortal } from "react-dom"; import { useTranslation } from "react-i18next"; import { type FetcherWithComponents, useFetcher } from "react-router"; import type { SendouButtonProps } from "~/components/elements/Button"; import { SendouDialog } from "~/components/elements/Dialog"; import { useIsMounted } from "~/hooks/useIsMounted"; import invariant from "~/utils/invariant"; import { SubmitButton } from "./SubmitButton"; interface ChildProps { onPress?: () => void; type?: "button"; } export function FormWithConfirm({ fields, children, dialogHeading, submitButtonText, action, submitButtonTestId = "submit-button", submitButtonVariant = "destructive", fetcher: _fetcher, }: { fields?: ( | [name: string, value: string | number] | readonly [name: string, value: string | number] )[]; children: React.ReactElement; dialogHeading: string; submitButtonText?: string; action?: string; submitButtonTestId?: string; submitButtonVariant?: SendouButtonProps["variant"]; fetcher?: FetcherWithComponents; }) { const componentsFetcher = useFetcher(); const fetcher = _fetcher ?? componentsFetcher; const isMounted = useIsMounted(); const { t } = useTranslation(["common"]); const [dialogOpen, setDialogOpen] = React.useState(false); const formRef = React.useRef(null); const id = React.useId(); const openDialog = React.useCallback(() => setDialogOpen(true), []); const closeDialog = React.useCallback(() => setDialogOpen(false), []); invariant(React.isValidElement(children)); React.useEffect(() => { if (fetcher.state === "loading") { closeDialog(); } }, [fetcher.state, closeDialog]); return ( <> {isMounted ? // using portal here makes nesting this component in another form work createPortal( {fields?.map(([name, value]) => ( ))} , document.body, ) : null}

{dialogHeading}

{submitButtonText ?? t("common:actions.delete")}
{React.cloneElement(children, { onPress: openDialog, type: "button", })} ); }