diff --git a/package.json b/package.json index 721396ac..6f35de2b 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "@mui/material": "5.6.0", "@mui/styles": "5.6.0", "@mui/x-date-pickers": "^5.0.0-alpha.4", - "@rowy/form-builder": "^0.6.2", + "@rowy/form-builder": "^0.7.0", "@rowy/multiselect": "^0.4.0", "@tinymce/tinymce-react": "^3", "@uiw/react-md-editor": "^3.14.1", diff --git a/src/components/ConfirmDialog.tsx b/src/components/ConfirmDialog.tsx index ef2549f8..5bb298ef 100644 --- a/src/components/ConfirmDialog.tsx +++ b/src/components/ConfirmDialog.tsx @@ -11,7 +11,6 @@ import { Button, } from "@mui/material"; -import { FadeTransitionMui } from "@src/components/Modal/FadeTransition"; import { projectScope, confirmDialogAtom } from "@src/atoms/projectScope"; export interface IConfirmDialogProps { @@ -62,7 +61,6 @@ export default function ConfirmDialog({ else handleClose(); }} maxWidth={maxWidth} - TransitionComponent={FadeTransitionMui} sx={{ cursor: "default", zIndex: (theme) => theme.zIndex.modal + 50 }} > {title} diff --git a/src/components/Modal/FadeTransition.tsx b/src/components/Modal/FadeTransition.tsx deleted file mode 100644 index 48e4441d..00000000 --- a/src/components/Modal/FadeTransition.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { forwardRef, cloneElement } from "react"; -import { useTheme } from "@mui/material"; -import { Transition } from "react-transition-group"; -import { TransitionProps } from "react-transition-group/Transition"; -import { TransitionProps as MuiTransitionProps } from "@mui/material/transitions"; - -export const FadeTransition: React.ForwardRefExoticComponent< - Pick & React.RefAttributes -> = forwardRef( - ({ children, ...props }: TransitionProps, ref: React.Ref) => { - const theme = useTheme(); - - if (!children) return null; - - const defaultStyle = { - opacity: 0, - transform: "scale(0.8)", - - transition: theme.transitions.create(["transform", "opacity"], { - duration: "300ms", - easing: theme.transitions.easing.strong, - }), - }; - - const transitionStyles = { - entering: { - willChange: "transform, opacity", - }, - - entered: { - opacity: 1, - transform: "none", - }, - - exiting: { - opacity: 0, - transform: "scale(0.8)", - - transitionDuration: theme.transitions.duration.leavingScreen, - }, - - exited: { - opacity: 0, - transform: "none", - transition: "none", - }, - - unmounted: {}, - }; - - return ( - - {(state) => - cloneElement(children as any, { - style: { ...defaultStyle, ...transitionStyles[state] }, - tabIndex: -1, - ref, - }) - } - - ); - } -); - -export default FadeTransition; - -export const FadeTransitionMui = forwardRef(function Transition( - props: MuiTransitionProps & { children?: React.ReactElement }, - ref: React.Ref -) { - return ; -}); diff --git a/src/components/Modal/Modal.tsx b/src/components/Modal/Modal.tsx index fa9a9baa..7cf12cb5 100644 --- a/src/components/Modal/Modal.tsx +++ b/src/components/Modal/Modal.tsx @@ -11,12 +11,10 @@ import { DialogActions, Button, ButtonProps, - Slide, } from "@mui/material"; import LoadingButton, { LoadingButtonProps } from "@mui/lab/LoadingButton"; import CloseIcon from "@mui/icons-material/Close"; -import { FadeTransitionMui } from "./FadeTransition"; import ScrollableDialogContent, { IScrollableDialogContentProps, } from "./ScrollableDialogContent"; @@ -86,8 +84,6 @@ export default function Modal({ onClose={handleClose} fullWidth fullScreen={fullScreen} - TransitionComponent={fullScreen ? Slide : FadeTransitionMui} - TransitionProps={fullScreen ? ({ direction: "up" } as any) : undefined} aria-labelledby="modal-title" {...props} sx={ diff --git a/src/components/Modal/ModalTransition.tsx b/src/components/Modal/ModalTransition.tsx new file mode 100644 index 00000000..d79f590c --- /dev/null +++ b/src/components/Modal/ModalTransition.tsx @@ -0,0 +1,91 @@ +import { forwardRef, cloneElement } from "react"; +import { useTheme, Slide } from "@mui/material"; +import { Transition } from "react-transition-group"; +import { TransitionProps } from "react-transition-group/Transition"; +import { TransitionProps as MuiTransitionProps } from "@mui/material/transitions"; + +export const ModalTransition: React.ForwardRefExoticComponent< + Pick & React.RefAttributes +> = forwardRef(function ModalTransition( + { children, ...props }: TransitionProps, + ref: React.Ref +) { + const theme = useTheme(); + + if (!children) return null; + + const isFullScreenDialog = ( + Array.isArray(children) ? children[0] : children + ).props?.children?.props?.className?.includes("MuiDialog-paperFullScreen"); + + if (isFullScreenDialog) + return ( + + {children as any} + + ); + + const defaultStyle = { + opacity: 0, + transform: "scale(0.8)", + + transition: theme.transitions.create(["transform", "opacity"], { + duration: theme.transitions.duration.enteringScreen, + easing: theme.transitions.easing.strong, + }), + }; + + const transitionStyles = { + entering: { + willChange: "transform, opacity", + }, + + entered: { + opacity: 1, + transform: "none", + }, + + exiting: { + opacity: 0, + transform: "scale(0.8)", + + transitionDuration: theme.transitions.duration.leavingScreen, + }, + + exited: { + opacity: 0, + transform: "none", + transition: "none", + }, + + unmounted: {}, + }; + + return ( + + {(state) => + cloneElement(children as any, { + style: { ...defaultStyle, ...transitionStyles[state] }, + tabIndex: -1, + ref, + }) + } + + ); +}); + +export default ModalTransition; + +export const ModalTransitionMui = forwardRef(function Transition( + props: MuiTransitionProps & { children?: React.ReactElement }, + ref: React.Ref +) { + return ; +}); diff --git a/src/theme/components.tsx b/src/theme/components.tsx index c537dfb4..6c0770c1 100644 --- a/src/theme/components.tsx +++ b/src/theme/components.tsx @@ -4,6 +4,7 @@ import type {} from "@mui/lab/themeAugmentation"; import { MultiSelectProps } from "@rowy/multiselect"; import { toRem } from "./typography"; +import ModalTransition from "@src/components/Modal/ModalTransition"; import RadioIcon from "@src/theme/RadioIcon"; import CheckboxIcon from "@src/theme/CheckboxIcon"; import CheckboxIndeterminateIcon from "@src/theme/CheckboxIndeterminateIcon"; @@ -248,6 +249,9 @@ export const components = (theme: Theme): ThemeOptions => { }, MuiDialog: { + defaultProps: { + TransitionComponent: ModalTransition, + }, styleOverrides: { root: { "--dialog-title-height": "64px", @@ -307,14 +311,8 @@ export const components = (theme: Theme): ThemeOptions => { MuiDialogTitle: { styleOverrides: { root: { - padding: "var(--dialog-spacing)", - paddingTop: (64 - 28) / 2, - paddingBottom: (64 - 28) / 2, - - [theme.breakpoints.down("sm")]: { - paddingTop: (56 - 28) / 2, - paddingBottom: (56 - 28) / 2, - }, + ...(theme.typography.h5 as any), + padding: `calc((var(--dialog-title-height) - ${theme.typography.h5.lineHeight} * ${theme.typography.h5.fontSize}) / 2) var(--dialog-spacing)`, }, }, }, diff --git a/yarn.lock b/yarn.lock index 5861d12c..b3672bac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3350,10 +3350,10 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@rowy/form-builder@^0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@rowy/form-builder/-/form-builder-0.6.2.tgz#aa51c877525afc061f25d614e6526ff57193dd3a" - integrity sha512-Lr4CJk4zQpp8ae27umsuxkRf8zs6GQGGA26u/z6lFDIeM+wIr33IOsRjgx9XlNhrRHGEhfLdwX4okuQGv3MwOA== +"@rowy/form-builder@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@rowy/form-builder/-/form-builder-0.7.0.tgz#75c95d7114d0912a944f737a1c61b60b6cefa935" + integrity sha512-D5koLnPdcGuHCMWgiU0stLVK8Dvu+mKWJY+WSKNUsPtqCxuSeoi1RWTQEy+DYkQl2msVFWvxt4Ei1FlPTNwNsQ== dependencies: "@hookform/resolvers" "^2.6.0" "@types/lodash-es" "^4.17.6"