import React from 'react'; import classNames from 'classnames'; interface Props { // Value ranges from 0 to 100 value: number; // Optional. Load with initial value and have // it shoot to new value immediately prevValue?: number; sendStatus: -1 | 0 | 1 | 2; visible: boolean; fadeOnComplete: boolean; } interface State { visible: boolean; startFade: boolean; } export class SessionProgress extends React.PureComponent { public static defaultProps = { fadeOnComplete: true, }; constructor(props: any) { super(props); const { visible } = this.props; this.state = { visible, startFade: false, }; } public render() { const { startFade } = this.state; const { value, prevValue, sendStatus } = this.props; // Duration will be the decimal (in seconds) of // the percentage differnce, else 0.25s; // Minimum shift duration of 0.25s; const shiftDuration = this.getShiftDuration(this.props.value, prevValue).toFixed(2); // 1. Width depends on progress. // 2. Opacity is the inverse of fade. // 3. Transition duration scales with the // distance it needs to travel // FIXME VINCE - globalise all JS color references const sessionBrandColor = '#00f782'; const sessionDangerAlt = '#ff4538'; const successColor = sessionBrandColor; const failureColor = sessionDangerAlt; const backgroundColor = sendStatus === 2 ? failureColor : successColor; const style = { 'background-color': backgroundColor, transform: `translateX(-${100 - value}%)`, transition: `transform ${shiftDuration}s cubic-bezier(0.25, 0.46, 0.45, 0.94)`, }; if (value >= 100) { this.onComplete(); } return (
 
); } public onComplete() { const { fadeOnComplete } = this.props; // Fade if (fadeOnComplete) { this.setState({ startFade: true, }); } } private getShiftDuration(value: number, prevValue?: number) { // Generates a shift duration which is based upon the distance requred to travel. // Follows the curve of y = (1-c)*sqrt(x) + c // Input values are between 0 and 100. // Max time = 1.0s. const minTime = 0.25; if (!prevValue) { return minTime; } const distance = Math.abs(value - prevValue) / 100; return (1 - minTime) * Math.sqrt(distance) + minTime; } }