import React__default, { useState, useEffect, Children } from 'react';
import { useReducedMotion, AnimatePresence, motion } from 'framer-motion';
import { tokens } from '@jobber/design';

const TIMING_QUICK = toSeconds(tokens["timing-quick"]);
const TIMING_BASE = toSeconds(tokens["timing-base"]);
const baseTransition = {
    visible: { opacity: 1 },
    hidden: { opacity: 0 },
};
const fade = {
    visible: { opacity: 1 },
    hidden: { opacity: 0 },
};
const popIn = {
    visible: Object.assign({ scale: 1 }, baseTransition.visible),
    hidden: Object.assign({ scale: 0.95 }, baseTransition.hidden),
};
const fromTop = {
    visible: Object.assign({ y: 0 }, baseTransition.visible),
    hidden: Object.assign({ y: -tokens["space-base"] }, baseTransition.hidden),
};
const fromBottom = {
    visible: Object.assign({ y: 0 }, baseTransition.visible),
    hidden: Object.assign({ y: tokens["space-base"] }, baseTransition.hidden),
};
const fromLeft = {
    visible: Object.assign({ x: 0 }, baseTransition.visible),
    hidden: Object.assign({ x: -tokens["space-base"] }, baseTransition.hidden),
};
const fromRight = {
    visible: Object.assign({ x: 0 }, baseTransition.visible),
    hidden: Object.assign({ x: tokens["space-base"] }, baseTransition.hidden),
};
const fromLeftToRight = {
    initial: Object.assign({ x: -tokens["space-base"] }, baseTransition.hidden),
    visible: Object.assign({ x: 0 }, baseTransition.visible),
    hidden: Object.assign({ x: tokens["space-base"] }, baseTransition.hidden),
};
const fromRightToLeft = {
    initial: Object.assign({ x: tokens["space-base"] }, baseTransition.hidden),
    visible: Object.assign({ x: 0 }, baseTransition.visible),
    hidden: Object.assign({ x: -tokens["space-base"] }, baseTransition.hidden),
};
function toSeconds(ms) {
    return ms / 1000;
}

function usePreviousValue(value) {
    const [previousValue, setPreviousValue] = useState(value);
    useEffect(() => {
        setPreviousValue(value);
    }, [value]);
    return [previousValue, setPreviousValue];
}

const transitions = {
    fromBottom,
    fromTop,
    fromLeft,
    fromRight,
    popIn,
    fromLeftToRight,
    fromRightToLeft,
    fade,
};
function AnimatedPresence(props) {
    const shouldReduceMotion = useReducedMotion();
    if (shouldReduceMotion) {
        return React__default.createElement(React__default.Fragment, null, props.children);
    }
    return React__default.createElement(InternalAnimatedPresence, Object.assign({}, props));
}
function InternalAnimatedPresence({ transition = "fromTop", initial = false, children, }) {
    const transitionVariation = transitions[transition];
    const hasInitialTransition = "initial" in transitionVariation;
    const childCount = Children.count(children);
    // Set the initial value to 0 so it staggers the animation on mount when
    // initial is true.
    const [lastChildIndex, setLastChildIndex] = usePreviousValue(0);
    // Whenever the children count changes, update the last index.
    useEffect(() => {
        setLastChildIndex(childCount - 1);
    }, [childCount]);
    return (React__default.createElement(AnimatePresence, { initial: initial, mode: "popLayout" }, Children.map(children, (child, i) => child && (React__default.createElement(motion.div, { layout: true, variants: transitionVariation, initial: hasInitialTransition ? "initial" : "hidden", animate: "visible", exit: "hidden", transition: {
            duration: TIMING_BASE,
            delay: generateDelayTime(i),
        } }, child)))));
    function generateDelayTime(index) {
        // Don't add a delay if it's already rendered.
        if (lastChildIndex > index)
            return 0;
        // Stagger the animation starting after the previous last child index.
        return (index - lastChildIndex) * TIMING_QUICK;
    }
}

export { AnimatedPresence as A };
