JSFiddle - React, Tailwind, and code Playground

HTML

<div id='status'>
    Active
</div>
<div id='console'>
</div>
<script>
/*! Idle Timer - v0.9.2 - 2013-01-06
* https://github.com/mikesherov/jquery-idletimer
* Copyright (c) 2013 Paul Irish; Licensed MIT */
( function( $ ) {

$.idleTimer = function( firstParam, elem, opts ) {

	// defaults that are to be stored as instance props on the elem
	opts = $.extend( {
		startImmediately: true,   //starts a timeout as soon as the timer is set up
		idle: false,              //indicates if the user is idle
		enabled: true,            //indicates if the idle timer is enabled
		timeout: 30000,           //the amount of time (ms) before the user is considered idle
		events: "mousemove keydown DOMMouseScroll mousewheel mousedown touchstart touchmove" // activity is one of these events
	}, opts );


	elem = elem || document;

	var jqElem = $( elem ),
		obj = jqElem.data("idleTimerObj") || {},

		/* (intentionally not documented)
		 * Toggles the idle state and fires an appropriate event.
		 * @return {void}
		 */
		toggleIdleState = function( myelem ) {

			// curse you, mozilla setTimeout lateness bug!
			if ( typeof myelem === "number" ) {
				myelem = undefined;
			}

			var obj = $.data( myelem || elem, "idleTimerObj" );

			//toggle the state
			obj.idle = !obj.idle;

			// reset timeout
			var elapsed = ( +new Date() ) - obj.olddate;
			obj.olddate = +new Date();

			// handle Chrome always triggering idle after js alert or comfirm popup
			if ( obj.idle && ( elapsed < opts.timeout ) ) {
				obj.idle = false;
				clearTimeout( $.idleTimer.tId );
				if ( opts.enabled ) {
					$.idleTimer.tId = setTimeout( toggleIdleState, opts.timeout );
				}
				return;
			}

			// create a custom event, but first, store the new state on the element
			// and then append that string to a namespace
			var event = $.Event( $.data( elem, "idleTimer", obj.idle ? "idle" : "active" ) + ".idleTimer" );
			$( elem ).trigger( event );
		},

		/**
		 * Stops the idle timer. This removes appropriate...

CSS

#console {
    background-color: black;
    color: white;
    border: 4px solid #ccc;
    width: 100%;
    min-height: 500px;
    box-sizing: border-box;
    margin: 5px;
}

#status:before {
    content: 'Status:';
}

JavaScript

$(document).ready(function(){
    var $doc = $(document),
        $console = $('#console'),
        $status = $('#status'),
        lastState = false;
    
    function update(e, src){
        if(lastState !== $doc.data('idleTimerObj').idle){
            lastState = $doc.data('idleTimerObj').idle;
        } else {
            return;
        }
        $status.html(e.type + ' (from ' + src + ')');
        $console.append('<hr><p>' + src + '</p>');
        $console.append(e.type + ' occured');
        $console.append(JSON.stringify($doc.data('idleTimerObj')));
    }
    $doc.on('idle.idleTimer active.idleTimer', function(e){
        update(e, 'event handler');
    });
    setInterval(function(){
        update({type:'interval hit',}, 'interval');
    }, 3 * 1000);
    $doc.idleTimer(3 * 1000);
});