ui-lib.tsx 2.4 KB

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