"use client"; import * as Dialog from "@radix-ui/react-dialog"; import React, { createContext, useContext, useEffect, useMemo, useRef, useState, } from "react"; import { isIOS } from "src/utils/isDevice"; import { CloseTiny } from "./Icons/CloseTiny"; import { useVisualViewport } from "./ViewportSizeLayout"; import { useIsMobile } from "src/hooks/isMobile"; import { MobileSheet } from "./MobileSheet"; import { GoToArrowLined } from "./Icons/GoToArrowLined"; type ModalProps = { className?: string; open?: boolean; onOpenChange?: (open: boolean) => void; asChild?: boolean; trigger?: React.ReactNode; title?: React.ReactNode; children: React.ReactNode; actionButton?: React.ReactNode; sheetOnMobile?: boolean; sheetClassName?: string; }; type ModalChromeProps = ModalProps & { onBack?: () => void }; type BackEntry = { run: () => void }; const ModalBackContext = createContext< ((entry: BackEntry) => () => void) | null >(null); export function useModalBack(back: (() => void) | null) { let register = useContext(ModalBackContext); let latest = useRef(back); latest.current = back; let active = !!back; useEffect(() => { if (!register || !active) return; return register({ run: () => latest.current?.() }); }, [register, active]); } export const Modal = (props: ModalProps) => { let [backStack, setBackStack] = useState([]); let register = useMemo( () => (entry: BackEntry) => { setBackStack((stack) => [...stack, entry]); return () => setBackStack((stack) => stack.filter((e) => e !== entry)); }, [], ); let modalProps = { ...props, onBack: backStack[backStack.length - 1]?.run, children: ( {props.children} ), }; if (props.sheetOnMobile) return ; return ; }; const SheetOnMobileModal = (props: ModalChromeProps) => { let isMobile = useIsMobile(); if (!isMobile) return ; return ( {props.children} ); }; const DialogModal = ({ className, open, onOpenChange, asChild, trigger, actionButton, title, children, onBack, }: ModalChromeProps) => { let { height, offsetTop, difference } = useVisualViewport(); let keyboardOpen = isIOS() && difference !== 0 && height > 0; return ( {trigger !== undefined && ( {trigger} )}
{onBack && ( )}
{title ? (

{title}

{actionButton && actionButton}
) : ( )}
{children}
); };