ui-lib.tsx 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import styles from "./ui-lib.module.scss";
  2. import LoadingIcon from "../icons/three-dots.svg";
  3. import CloseIcon from "../icons/close.svg";
  4. import { createRoot } from 'react-dom/client'
  5. export function Popover(props: {
  6. children: JSX.Element;
  7. content: JSX.Element;
  8. open?: boolean;
  9. onClose?: () => void;
  10. }) {
  11. return (
  12. <div className={styles.popover}>
  13. {props.children}
  14. {props.open && (
  15. <div className={styles["popover-content"]}>
  16. <div className={styles["popover-mask"]} onClick={props.onClose}></div>
  17. {props.content}
  18. </div>
  19. )}
  20. </div>
  21. );
  22. }
  23. export function Card(props: { children: JSX.Element[]; className?: string }) {
  24. return (
  25. <div className={styles.card + " " + props.className}>{props.children}</div>
  26. );
  27. }
  28. export function ListItem(props: { children: JSX.Element[] }) {
  29. if (props.children.length > 2) {
  30. throw Error("Only Support Two Children");
  31. }
  32. return <div className={styles["list-item"]}>{props.children}</div>;
  33. }
  34. export function List(props: { children: JSX.Element[] }) {
  35. return <div className={styles.list}>{props.children}</div>;
  36. }
  37. export function Loading() {
  38. return <div style={{
  39. height: "100vh",
  40. width: "100vw",
  41. display: "flex",
  42. alignItems: "center",
  43. justifyContent: "center"
  44. }}><LoadingIcon /></div>
  45. }
  46. interface ModalProps {
  47. title: string,
  48. children?: JSX.Element,
  49. actions?: JSX.Element[],
  50. onClose?: () => void,
  51. }
  52. export function Modal(props: ModalProps) {
  53. return <div className={styles['modal-container']}>
  54. <div className={styles['modal-header']}>
  55. <div className={styles['modal-title']}>{props.title}</div>
  56. <div className={styles['modal-close-btn']} onClick={props.onClose}>
  57. <CloseIcon />
  58. </div>
  59. </div>
  60. <div className={styles['modal-content']}>{props.children}</div>
  61. <div className={styles['modal-footer']}>
  62. <div className={styles['modal-actions']}>
  63. {props.actions?.map((action, i) => <div key={i} className={styles['modal-action']}>{action}</div>)}
  64. </div>
  65. </div>
  66. </div>
  67. }
  68. export function showModal(props: ModalProps) {
  69. const div = document.createElement('div')
  70. div.className = "modal-mask";
  71. document.body.appendChild(div)
  72. const root = createRoot(div)
  73. root.render(<Modal {...props} onClose={() => {
  74. props.onClose?.();
  75. root.unmount();
  76. div.remove();
  77. }}></Modal>)
  78. }