diff options
Diffstat (limited to 'components/Sidebar/transition-utils.tsx')
-rw-r--r-- | components/Sidebar/transition-utils.tsx | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/components/Sidebar/transition-utils.tsx b/components/Sidebar/transition-utils.tsx new file mode 100644 index 0000000..68634bb --- /dev/null +++ b/components/Sidebar/transition-utils.tsx @@ -0,0 +1,144 @@ +// 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<P = {}> = ( + props: P & { + transition?: TransitionConfig + transitionEnd?: TransitionEndConfig + delay?: number | DelayConfig + }, +) => TargetAndTransition + +type Variant<P = {}> = TargetAndTransition | TargetResolver<P> + +export type Variants<P = {}> = { + enter: Variant<P> + exit: Variant<P> + initial?: Variant<P> +} + +type WithMotionState<P> = Partial<Record<'enter' | 'exit', P>> + +export type TransitionConfig = WithMotionState<Transition> + +export type TransitionEndConfig = WithMotionState<Target> + +export type DelayConfig = WithMotionState<number> + +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<P extends object> = Omit<P, 'transition'> & { + /** + * 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'], + }), +} |