import styles from "./ui-lib.module.scss"; import LoadingIcon from "../icons/three-dots.svg"; import CloseIcon from "../icons/close.svg"; import EyeIcon from "../icons/eye.svg"; import EyeOffIcon from "../icons/eye-off.svg"; import DownIcon from "../icons/down.svg"; import { createRoot } from "react-dom/client"; import React, { HTMLProps, useEffect, useState } from "react"; import { IconButton } from "./button"; export function Popover(props: { children: JSX.Element; content: JSX.Element; open?: boolean; onClose?: () => void; }) { return (
{props.children} {props.open && (
{props.content}
)}
); } export function Card(props: { children: JSX.Element[]; className?: string }) { return (
{props.children}
); } export function ListItem(props: { title: string; subTitle?: string; children?: JSX.Element | JSX.Element[]; icon?: JSX.Element; className?: string; }) { return (
{props.icon &&
{props.icon}
}
{props.title}
{props.subTitle && (
{props.subTitle}
)}
{props.children}
); } export function List(props: { children: | Array | JSX.Element | null | undefined; }) { return
{props.children}
; } export function Loading() { return (
); } interface ModalProps { title: string; children?: JSX.Element | JSX.Element[]; actions?: JSX.Element[]; onClose?: () => void; } export function Modal(props: ModalProps) { useEffect(() => { const onKeyDown = (e: KeyboardEvent) => { if (e.key === "Escape") { props.onClose?.(); } }; window.addEventListener("keydown", onKeyDown); return () => { window.removeEventListener("keydown", onKeyDown); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return (
{props.title}
{props.children}
{props.actions?.map((action, i) => (
{action}
))}
); } 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(); } export type ToastProps = { content: string; action?: { text: string; onClick: () => void; }; onClose?: () => void; }; export function Toast(props: ToastProps) { return (
{props.content} {props.action && ( )}
); } export function showToast( content: string, action?: ToastProps["action"], 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(); } export type InputProps = React.HTMLProps & { autoHeight?: boolean; rows?: number; }; export function Input(props: InputProps) { return ( ); } export function PasswordInput(props: HTMLProps) { const [visible, setVisible] = useState(false); function changeVisibility() { setVisible(!visible); } return (
: } onClick={changeVisibility} className={"password-eye"} />
); } export function Select( props: React.DetailedHTMLProps< React.SelectHTMLAttributes, HTMLSelectElement >, ) { const { className, children, ...otherProps } = props; return (
); }