// Taken from https://github.com/chakra-ui/chakra-ui/blob/fc3b97d0978cf2adb9fc79157c6e42b4b68155c5/packages/transition/src/transition-utils.ts import { isNumber } from '@chakra-ui/utils' import { Target, TargetAndTransition, Transition } from 'framer-motion' type TargetResolver

= ( props: P & { transition?: TransitionConfig transitionEnd?: TransitionEndConfig delay?: number | DelayConfig }, ) => TargetAndTransition type Variant

= TargetAndTransition | TargetResolver

export type Variants

= { enter: Variant

exit: Variant

initial?: Variant

} type WithMotionState

= Partial> export type TransitionConfig = WithMotionState export type TransitionEndConfig = WithMotionState export type DelayConfig = WithMotionState export const TransitionEasings = { ease: [0.25, 0.1, 0.25, 1], easeIn: [0.4, 0, 1, 1], easeOut: [0, 0, 0.2, 1], easeInOut: [0.4, 0, 0.2, 1], } as const export const TransitionVariants = { scale: { enter: { scale: 1 }, exit: { scale: 0.95 }, }, fade: { enter: { opacity: 1 }, exit: { opacity: 0 }, }, pushLeft: { enter: { x: '100%' }, exit: { x: '-30%' }, }, pushRight: { enter: { x: '-100%' }, exit: { x: '30%' }, }, pushUp: { enter: { y: '100%' }, exit: { y: '-30%' }, }, pushDown: { enter: { y: '-100%' }, exit: { y: '30%' }, }, slideLeft: { position: { left: 0, top: 0, bottom: 0, width: '100%' }, enter: { x: 0 }, exit: { x: '-100%' }, }, slideRight: { position: { right: 0, top: 0, bottom: 0, width: '100%' }, enter: { x: 0 }, exit: { x: '100%' }, }, slideUp: { position: { top: 0, left: 0, right: 0, maxWidth: '100vw' }, enter: { y: 0 }, exit: { y: '-100%' }, }, slideDown: { position: { bottom: 0, left: 0, right: 0, maxWidth: '100vw' }, enter: { y: 0 }, exit: { y: '100%' }, }, } export type SlideDirection = 'top' | 'left' | 'bottom' | 'right' export function slideTransition(options?: { direction?: SlideDirection }) { const side = options?.direction ?? 'right' switch (side) { case 'right': return TransitionVariants.slideRight case 'left': return TransitionVariants.slideLeft case 'bottom': return TransitionVariants.slideDown case 'top': return TransitionVariants.slideUp default: return TransitionVariants.slideRight } } export const TransitionDefaults = { enter: { duration: 0.2, ease: TransitionEasings.easeOut, }, exit: { duration: 0.1, ease: TransitionEasings.easeIn, }, } as const export type WithTransitionConfig

= Omit & { /** * If `true`, the element will unmount when `in={false}` and animation is done */ unmountOnExit?: boolean /** * Show the component; triggers the enter or exit states */ in?: boolean /** * Custom `transition` definition for `enter` and `exit` */ transition?: TransitionConfig /** * Custom `transitionEnd` definition for `enter` and `exit` */ transitionEnd?: TransitionEndConfig /** * Custom `delay` definition for `enter` and `exit` */ delay?: number | DelayConfig } export const withDelay = { enter: (transition: Transition, delay?: number | DelayConfig) => ({ ...transition, delay: isNumber(delay) ? delay : delay?.['enter'], }), exit: (transition: Transition, delay?: number | DelayConfig) => ({ ...transition, delay: isNumber(delay) ? delay : delay?.['exit'], }), }