From bb6fe7325dfe76c0618d34455e56122c3204a3b3 Mon Sep 17 00:00:00 2001 From: "Thomas F. K. Jorna" Date: Mon, 11 Oct 2021 01:27:47 +0200 Subject: chore: build --- components/Sidebar/Collapse.tsx | 146 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 components/Sidebar/Collapse.tsx (limited to 'components/Sidebar/Collapse.tsx') diff --git a/components/Sidebar/Collapse.tsx b/components/Sidebar/Collapse.tsx new file mode 100644 index 0000000..b297605 --- /dev/null +++ b/components/Sidebar/Collapse.tsx @@ -0,0 +1,146 @@ +// modified from https://github.com/chakra-ui/chakra-ui/blob/fc3b97d0978cf2adb9fc79157c6e42b4b68155c5/packages/transition/src/collapse.tsx + +import { cx, mergeWith, warn, __DEV__ } from '@chakra-ui/utils' +import { AnimatePresence, HTMLMotionProps, motion, Variants as _Variants } from 'framer-motion' +import * as React from 'react' +import { TransitionEasings, Variants, withDelay, WithTransitionConfig } from './transition-utils' + +const isNumeric = (value?: string | number) => value != null && parseInt(value.toString(), 10) > 0 + +export interface CollapseOptions { + /** + * If `true`, the opacity of the content will be animated + * @default true + */ + animateOpacity?: boolean + /** + * The size you want the content in its collapsed state. + * @default 0 + */ + startingSize?: number | string + /** + * The size you want the content in its expanded state. + * @default "auto" + */ + endingSize?: number | string + /** + * The dimension you want to collapse by. + * @default "size" + */ + dimension?: string +} + +const defaultTransitions = { + exit: { + size: { duration: 0.2, ease: TransitionEasings.ease }, + opacity: { duration: 0.3, ease: TransitionEasings.ease }, + }, + enter: { + size: { duration: 0.3, ease: TransitionEasings.ease }, + opacity: { duration: 0.4, ease: TransitionEasings.ease }, + }, +} + +const variants: Variants = { + exit: ({ animateOpacity, startingSize, transition, transitionEnd, delay, dimension }) => ({ + ...(animateOpacity && { opacity: isNumeric(startingSize) ? 1 : 0 }), + overflow: 'hidden', + [dimension as string]: startingSize, + transitionEnd: transitionEnd?.exit, + transition: transition?.exit ?? withDelay.exit(defaultTransitions.exit, delay), + }), + enter: ({ animateOpacity, endingSize, transition, transitionEnd, delay, dimension }) => ({ + ...(animateOpacity && { opacity: 1 }), + [dimension as string]: endingSize, + transitionEnd: transitionEnd?.enter, + transition: transition?.enter ?? withDelay.enter(defaultTransitions.enter, delay), + }), +} + +export type ICollapse = CollapseProps + +export interface CollapseProps + extends WithTransitionConfig>, + CollapseOptions {} + +export const Collapse = React.forwardRef((props, ref) => { + const { + in: isOpen, + unmountOnExit, + animateOpacity = true, + startingSize = 0, + endingSize = 'auto', + dimension = 'height', + style, + className, + transition, + transitionEnd, + ...rest + } = props + + const [mounted, setMounted] = React.useState(false) + React.useEffect(() => { + const timeout = setTimeout(() => { + setMounted(true) + }) + return () => clearTimeout(timeout) + }, []) + + /** + * Warn 🚨: `startingSize` and `unmountOnExit` are mutually exclusive + * + * If you specify a starting size, the collapsed needs to be mounted + * for the size to take effect. + */ + warn({ + condition: Boolean(startingSize > 0 && unmountOnExit), + message: `startingSize and unmountOnExit are mutually exclusive. You can't use them together`, + }) + + const hasStartingSize = parseFloat(startingSize.toString()) > 0 + + const custom = { + startingSize, + endingSize, + animateOpacity, + dimension, + transition: !mounted ? { enter: { duration: 0 } } : transition, + transitionEnd: mergeWith(transitionEnd, { + enter: { overflow: 'initial' }, + exit: unmountOnExit + ? undefined + : { + display: hasStartingSize ? 'block' : 'none', + }, + }), + } + + const show = unmountOnExit ? isOpen : true + const animate = isOpen || unmountOnExit ? 'enter' : 'exit' + + return ( + + {show && ( + + )} + + ) +}) + +if (__DEV__) { + Collapse.displayName = 'Collapse' +} -- cgit v1.2.3