UNPKG

vcc-ui

Version:

VCC UI is a collection of React UI Components that can be used for developing front-end applications at Volvo Car Corporation.

137 lines (116 loc) 3.01 kB
import React, { useContext, useEffect, useRef, useState } from "react"; import { Block } from "../block"; import { LineTransitionContext } from "./"; import { useFela } from "react-fela"; const ActiveLineWithTransition = () => { const [transitionFinished, setTransitionFinished] = useState(false); const { activeIndex, itemsDimensions } = useContext(LineTransitionContext); const [lastActiveIndex, setLastActiveIndex] = useState(activeIndex); const activeIndicator = useRef(); const { theme: { colors, direction } } = useFela(); const isRtl = direction === "rtl"; const goingRight = activeIndex >= lastActiveIndex; const onTransitionEndEvent = e => { if ( (goingRight && e.propertyName === "width") || (isRtl && !goingRight && e.propertyName === "width") || (!goingRight && e.propertyName === "left") ) { setTransitionFinished(true); } }; useEffect(() => { if (activeIndicator && activeIndicator.current) { activeIndicator.current.addEventListener( transitionEndEvent, onTransitionEndEvent ); return () => { activeIndicator.current.removeEventListener( transitionEndEvent, onTransitionEndEvent ); }; } }); useEffect(() => { if (transitionFinished) { setTransitionFinished(false); setLastActiveIndex(activeIndex); } }); if (!itemsDimensions) { return null; } const activeItem = itemsDimensions[activeIndex]; const prevItem = itemsDimensions[lastActiveIndex]; const getWidth = () => { if (transitionFinished) { return activeItem.width; } else if (goingRight) { return activeItem.x - prevItem.x + activeItem.width; } else { return prevItem.x - activeItem.x + prevItem.width; } }; const getX = () => { if (transitionFinished) { return activeItem.x; } else if (goingRight) { return prevItem.x; } else { return activeItem.x; } }; const width = getWidth(); const x = getX(); return ( <Block extend={styles({ width, x, colors, isRtl })} innerRef={activeIndicator} /> ); }; const transitionBezier = "ease-out"; const transitionTime = "200ms"; const styles = ({ width, x, colors: { primary }, isRtl }) => ({ position: "absolute", bottom: 0, zIndex: 10, transition: `width ${transitionTime} ${transitionBezier}, ${ isRtl ? "right" : "left" } ${transitionTime} ${transitionBezier}`, left: x, width, height: 3, background: primary }); const createElement = type => { return typeof document !== "undefined" && document.createElement(type); }; const transitionEndEvent = (() => { if (typeof document === "undefined") { return ""; } const el = createElement("fakeelement"); const transitions = { transition: "transitionend", OTransition: "oTransitionEnd", MozTransition: "transitionend", WebkitTransition: "webkitTransitionEnd" }; for (let t in transitions) { if (String(el.style[t]) !== "undefined") { return transitions[t]; } } return transitions.transition; })(); export default ActiveLineWithTransition;