"use client"; import type { ReactNode } from "react"; import { useCallback, useEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; import Button from "./button"; import { useI18n } from "@/translations/provider"; const EXIT_ANIMATION_MS = 220; export type HelpModalProps = { isOpen: boolean; onClose: () => void; title?: ReactNode; description?: ReactNode; buttonText?: ReactNode; }; export function HelpModal({ isOpen, onClose, title: _title, description, buttonText, }: HelpModalProps) { const { dictionary: t } = useI18n(); const [mounted, setMounted] = useState(false); const [isClosing, setIsClosing] = useState(false); const isMountedRef = useRef(true); useEffect(() => { isMountedRef.current = true; setMounted(true); return () => { isMountedRef.current = false; }; }, []); // When isOpen changes from outside, reset isClosing useEffect(() => { if (isOpen) { setIsClosing(false); } }, [isOpen]); const resolvedTitle = "Tips"; const resolvedDescription = description ?? t[ "Psychologically, this practice fosters a sense of empathy and contentment, which can reduce financial stress. Socially, lending strengthens neighborhood bonds and creates support networks that can lead to economic opportunities. This hadith encourages believers to lend dough, bread, and fire to increase their sustenance." ] ?? "Psychologically, this practice fosters a sense of empathy and contentment, which can reduce financial stress. Socially, lending strengthens neighborhood bonds and creates support networks that can lead to economic opportunities. This hadith encourages believers to lend dough, bread, and fire to increase their sustenance."; const resolvedButtonText = buttonText ?? t["Got it"] ?? "Got it"; const closeSheet = useCallback(() => { if (isClosing) return; setIsClosing(true); window.setTimeout(() => { if (isMountedRef.current) { setIsClosing(false); } onClose(); }, EXIT_ANIMATION_MS); }, [isClosing, onClose]); // Lock body scroll useEffect(() => { if (!isOpen || !mounted) return; const previousBodyOverflow = document.body.style.overflow; const previousHtmlOverflow = document.documentElement.style.overflow; document.body.style.overflow = "hidden"; document.documentElement.style.overflow = "hidden"; return () => { document.body.style.overflow = previousBodyOverflow; document.documentElement.style.overflow = previousHtmlOverflow; }; }, [isOpen, mounted]); if (!isOpen || !mounted) return null; return createPortal(
{ if (e.target === e.currentTarget) closeSheet(); }} onKeyDown={(e) => { if ( e.target === e.currentTarget && (e.key === "Escape" || e.key === "Enter" || e.key === " ") ) { e.preventDefault(); closeSheet(); } }} >

{resolvedTitle}

{(() => { const parseBoldText = (text: string) => { const parts = text.split(/(\*\*[^*]+\*\*)/g); return parts.map((part, index) => { if (part.startsWith("**") && part.endsWith("**")) { return ( // biome-ignore lint/suspicious/noArrayIndexKey: parts array is static {part.slice(2, -2)} ); } return part; }); }; const items = Array.isArray(resolvedDescription) ? resolvedDescription : typeof resolvedDescription === "string" && resolvedDescription.includes("\n") ? resolvedDescription .split(/\r?\n/) .map((s) => s.trim()) .filter(Boolean) : null; if (items && Array.isArray(items)) { return (
    {items.map((item, i) => { let cleanItem = item.trim(); let isHeader = false; if (cleanItem.startsWith("###")) { cleanItem = cleanItem.replace(/^###\s*/, ""); isHeader = true; } else { cleanItem = cleanItem.replace(/^[*+-]\s*/, ""); } if (isHeader) { return (
  • {parseBoldText(cleanItem)}
  • ); } return ( // biome-ignore lint/suspicious/noArrayIndexKey: list is static
  • {parseBoldText(cleanItem)}
  • ); })}
); } return (
{typeof resolvedDescription === "string" ? parseBoldText(resolvedDescription) : resolvedDescription}
); })()}
, document.body, ); } export default HelpModal;