All files / Toasts ToastController.js

2.43% Statements 1/41
0% Branches 0/16
0% Functions 0/14
2.7% Lines 1/37

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97                                                                21x                                                                                                                                
import React, { Component } from 'react';
 
import { NOOP } from './utils';
 
function Timer(callback, delay) {
    let timerId;
    let start = delay;
    let remaining = delay;
 
    this.clear = function () {
        clearTimeout(timerId);
    };
 
    this.pause = function () {
        clearTimeout(timerId);
        remaining -= Date.now() - start;
    };
 
    this.resume = function () {
        start = Date.now();
        clearTimeout(timerId);
        timerId = setTimeout(callback, remaining);
    }
 
    this.resume();
}
 
export class ToastController extends Component {
    state = {
        isRunning: Boolean(this.props.autoDismiss),
 
    };
    static defaultProps = {
        autoDismiss: false
    };
 
    componentDidMount() {
        this.startTimer();
    }
    componentDidUpdate(prevProps) {
        if (prevProps.autoDismiss !== this.props.autoDismiss) {
            const startOrClear = this.props.autoDismiss
                ? this.startTimer
                : this.clearTimer;
 
            startOrClear();
        }
    }
    componentWillUnmount() {
        this.clearTimer();
    }
 
    startTimer = () => {
        const { autoDismiss, autoDismissTimeout, onDismiss } = this.props;
 
        if (!autoDismiss) return;
 
        this.setState({ isRunning: true });
        this.timeout = new Timer(onDismiss, autoDismissTimeout);
    };
 
    clearTimer = () => {
        if (this.timeout) this.timeout.clear();
    };
 
    onMouseEnter = () => {
        this.setState({ isRunning: false }, () => {
            if (this.timeout) this.timeout.pause();
        });
    };
 
    onMouseLeave = () => {
        this.setState({ isRunning: true }, () => {
            if (this.timeout) this.timeout.resume();
        });
    };
 
    render() {
        const { autoDismiss, autoDismissTimeout, component: Toast, ...props } = this.props;
        const { isRunning } = this.state;
 
        // NOTE: conditions here so methods can be clean
        const handleMouseEnter = autoDismiss ? this.onMouseEnter : NOOP;
        const handleMouseLeave = autoDismiss ? this.onMouseLeave : NOOP;
 
        return (
            <Toast
                autoDismiss={autoDismiss}
                autoDismissTimeout={autoDismissTimeout}
                isRunning={isRunning}
                onMouseEnter={handleMouseEnter}
                onMouseLeave={handleMouseLeave}
                {...props}
            />
        );
    }
}