Switch to tRPC (#173)

This commit is contained in:
Luke Vella 2022-05-18 10:22:40 +01:00 committed by GitHub
parent 3d7e7e8a95
commit 2c4157ea24
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
245 changed files with 1585 additions and 1755 deletions

View file

@ -0,0 +1 @@
export { useModal } from "./use-modal";

View file

@ -0,0 +1,61 @@
import * as React from "react";
import { useList } from "react-use";
import { useRequiredContext } from "../use-required-context";
import Modal, { ModalProps } from "./modal";
export interface ModalProviderProps {
children?: React.ReactNode;
}
const ModalContext =
React.createContext<{
render: (el: ModalProps) => void;
} | null>(null);
ModalContext.displayName = "<ModalProvider />";
export const useModalContext = () => {
return useRequiredContext(ModalContext);
};
const ModalProvider: React.VoidFunctionComponent<ModalProviderProps> = ({
children,
}) => {
const [modals, { push, removeAt, updateAt }] = useList<ModalProps>([]);
const removeModalAt = (index: number) => {
updateAt(index, { ...modals[index], visible: false });
setTimeout(() => {
removeAt(index);
}, 500);
};
return (
<ModalContext.Provider
value={{
render: (props) => {
push(props);
},
}}
>
{children}
{modals.map((props, i) => (
<Modal
key={i}
visible={true}
{...props}
onOk={() => {
props.onOk?.();
removeModalAt(i);
}}
onCancel={() => {
props.onCancel?.();
removeModalAt(i);
}}
/>
))}
</ModalContext.Provider>
);
};
export default ModalProvider;

View file

@ -0,0 +1,126 @@
import { Dialog } from "@headlessui/react";
import { AnimatePresence, motion } from "framer-motion";
import * as React from "react";
import X from "@/components/icons/x.svg";
import Button, { ButtonProps } from "../button";
export interface ModalProps {
description?: React.ReactNode;
title?: React.ReactNode;
okText?: string;
cancelText?: string;
okButtonProps?: ButtonProps;
onOk?: () => void;
onCancel?: () => void;
footer?: React.ReactNode;
content?: React.ReactNode;
overlayClosable?: boolean;
visible?: boolean;
showClose?: boolean;
}
const Modal: React.VoidFunctionComponent<ModalProps> = ({
description,
title,
okText,
cancelText,
okButtonProps,
footer,
content,
overlayClosable,
onCancel,
onOk,
visible,
showClose,
}) => {
const initialFocusRef = React.useRef<HTMLButtonElement>(null);
return (
<AnimatePresence>
{visible ? (
<Dialog
open={visible}
className="fixed inset-0 z-40 overflow-y-auto"
initialFocus={initialFocusRef}
onClose={() => {
if (overlayClosable) onCancel?.();
}}
>
<motion.div
transition={{ duration: 0.5 }}
className="flex min-h-screen items-center justify-center"
>
<Dialog.Overlay
as={motion.div}
transition={{ duration: 0.5 }}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-0 bg-slate-900 bg-opacity-25"
/>
<motion.div
transition={{ duration: 0.1 }}
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.9 }}
className="relative z-50 my-8 inline-block max-w-full transform text-left align-middle"
>
<div className="mx-4 max-w-full overflow-hidden rounded-xl bg-white shadow-xl xs:rounded-xl">
{showClose ? (
<button
className="absolute right-5 top-1 z-10 rounded-lg p-2 text-slate-400 transition-colors hover:bg-slate-500/10 hover:text-slate-500 active:bg-slate-500/20"
onClick={onCancel}
>
<X className="h-4" />
</button>
) : null}
{content ?? (
<div className="max-w-md p-6">
{title ? (
<Dialog.Title className="mb-2 font-medium">
{title}
</Dialog.Title>
) : null}
{description ? (
<Dialog.Description className="m-0">
{description}
</Dialog.Description>
) : null}
</div>
)}
{footer === undefined ? (
<div className="flex h-14 items-center justify-end space-x-3 rounded-br-lg rounded-bl-lg border-t bg-slate-50 px-4">
{cancelText ? (
<Button
onClick={() => {
onCancel?.();
}}
>
{cancelText}
</Button>
) : null}
{okText ? (
<Button
ref={initialFocusRef}
type="primary"
onClick={() => {
onOk?.();
}}
{...okButtonProps}
>
{okText}
</Button>
) : null}
</div>
) : null}
</div>
</motion.div>
</motion.div>
</Dialog>
) : null}
</AnimatePresence>
);
};
export default Modal;

View file

@ -0,0 +1,27 @@
import React from "react";
import Modal, { ModalProps } from "./modal";
type OpenModalFn = () => void;
type CloseModalFn = () => void;
export const useModal = (
props?: ModalProps,
): [React.ReactElement<ModalProps>, OpenModalFn, CloseModalFn] => {
const [visible, setVisible] = React.useState(false);
const modal = (
<Modal
{...props}
visible={visible}
onOk={() => {
props?.onOk?.();
setVisible(false);
}}
onCancel={() => {
props?.onCancel?.();
setVisible(false);
}}
/>
);
return [modal, () => setVisible(true), () => setVisible(false)];
};