index.tsx 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import React from "react";
  2. import { Button } from "src/components/Button";
  3. import useKeyPress from "src/hooks/useKeyPress";
  4. import * as Styled from "./styles";
  5. type ControlProps = React.PropsWithChildren<{
  6. setVisible: (status: boolean) => void;
  7. }>;
  8. export type ReactComponent = React.FC<React.PropsWithChildren<{}>>;
  9. type ModalTypes = {
  10. Header: ReactComponent;
  11. Content: ReactComponent;
  12. Controls: React.FC<ControlProps>;
  13. };
  14. export interface ModalProps {
  15. visible: boolean;
  16. setVisible:
  17. | React.Dispatch<React.SetStateAction<boolean>>
  18. | ((visible: boolean) => void);
  19. size?: "md" | "lg";
  20. }
  21. const Header: ReactComponent = ({ children }) => {
  22. return (
  23. <Styled.HeaderWrapper>
  24. <Styled.Title>{children}</Styled.Title>
  25. </Styled.HeaderWrapper>
  26. );
  27. };
  28. const Content: ReactComponent = ({ children }) => {
  29. return <Styled.ContentWrapper>{children}</Styled.ContentWrapper>;
  30. };
  31. const Controls: React.FC<ControlProps> = ({ children, setVisible }) => {
  32. const handleEspacePress = useKeyPress("Escape");
  33. React.useEffect(() => {
  34. if (handleEspacePress) setVisible(false);
  35. }, [handleEspacePress, setVisible]);
  36. return (
  37. <Styled.ControlsWrapper>
  38. <Button onClick={() => setVisible(false)}>Close</Button>
  39. {children}
  40. </Styled.ControlsWrapper>
  41. );
  42. };
  43. const Modal: React.FC<React.PropsWithChildren<ModalProps>> & ModalTypes = ({
  44. children,
  45. visible,
  46. setVisible,
  47. size = "md",
  48. }) => {
  49. const onClick = (e: React.SyntheticEvent<HTMLDivElement>) => {
  50. if (e.currentTarget === e.target) {
  51. setVisible(false);
  52. }
  53. };
  54. if (!visible) return null;
  55. return (
  56. <Styled.ModalWrapper onClick={onClick}>
  57. <Styled.ModalInnerWrapper size={size}>{children}</Styled.ModalInnerWrapper>
  58. </Styled.ModalWrapper>
  59. );
  60. };
  61. Modal.Header = Header;
  62. Modal.Content = Content;
  63. Modal.Controls = Controls;
  64. export { Modal };