import styles from "./ui-lib.module.scss"; import LoadingIcon from "../icons/three-dots.svg"; import CloseIcon from "../icons/close.svg"; import { createRoot } from "react-dom/client"; export function Popover(props: { children: JSX.Element; content: JSX.Element; open?: boolean; onClose?: () => void; }) { return ( <div className={styles.popover}> {props.children} {props.open && ( <div className={styles["popover-content"]}> <div className={styles["popover-mask"]} onClick={props.onClose}></div> {props.content} </div> )} </div> ); } export function Card(props: { children: JSX.Element[]; className?: string }) { return ( <div className={styles.card + " " + props.className}>{props.children}</div> ); } export function ListItem(props: { children: JSX.Element[] }) { if (props.children.length > 2) { throw Error("Only Support Two Children"); } return <div className={styles["list-item"]}>{props.children}</div>; } export function List(props: { children: JSX.Element[] }) { return <div className={styles.list}>{props.children}</div>; } export function Loading() { return ( <div style={{ height: "100vh", width: "100vw", display: "flex", alignItems: "center", justifyContent: "center", }} > <LoadingIcon /> </div> ); } interface ModalProps { title: string; children?: JSX.Element; actions?: JSX.Element[]; onClose?: () => void; } export function Modal(props: ModalProps) { return ( <div className={styles["modal-container"]}> <div className={styles["modal-header"]}> <div className={styles["modal-title"]}>{props.title}</div> <div className={styles["modal-close-btn"]} onClick={props.onClose}> <CloseIcon /> </div> </div> <div className={styles["modal-content"]}>{props.children}</div> <div className={styles["modal-footer"]}> <div className={styles["modal-actions"]}> {props.actions?.map((action, i) => ( <div key={i} className={styles["modal-action"]}> {action} </div> ))} </div> </div> </div> ); } export function showModal(props: ModalProps) { const div = document.createElement("div"); div.className = "modal-mask"; document.body.appendChild(div); const root = createRoot(div); const closeModal = () => { props.onClose?.(); root.unmount(); div.remove(); }; div.onclick = (e) => { if (e.target === div) { closeModal(); } }; root.render(<Modal {...props} onClose={closeModal}></Modal>); } export type ToastProps = { content: string }; export function Toast(props: ToastProps) { return ( <div className={styles["toast-container"]}> <div className={styles["toast-content"]}>{props.content}</div> </div> ); } export function showToast(content: string, delay = 3000) { const div = document.createElement("div"); div.className = styles.show; document.body.appendChild(div); const root = createRoot(div); const close = () => { div.classList.add(styles.hide); setTimeout(() => { root.unmount(); div.remove(); }, 300); }; setTimeout(() => { close(); }, delay); root.render(<Toast content={content} />); }