lib/index.js
import { createStateSelector } from 'redux-mux'
import { assert } from 'chai'
import { ROOT_STATE_KEY, IDLESTATUS_ACTIVE } from 'redux-idle-monitor/lib/constants'
import getStyle from './style'
const IS_DEV = process.env.NODE_ENV !== 'production'
const IS_BROWSER = typeof window === 'object'
const selectState = createStateSelector(ROOT_STATE_KEY)
export const mapIdleStateToProps = (state, ownProps) => {
const { idleStatus, isRunning, isDetectionRunning, isIdle, lastActive, lastEvent } = selectState(state)
return { idleStatus
, isRunning
, isDetectionRunning
, isIdle
, lastActive
, lastEvent
}
}
export const createConnector = ({ connect }) => ReactComponent => connect(mapIdleStateToProps)(ReactComponent)
/** Exports a factory that creates the IdleMonitor component */
export default ({ React, connect }) => {
if(IS_DEV) {
assert.ok(React, 'react-redux-idle-monitor requires React as a dependency.')
assert.typeOf(React, 'object')
assert.ok(connect, 'react-redux-idle-monitor requires connect (react-redux) as a dependency.')
assert.typeOf(connect, 'function')
}
const { Component, PropTypes, Children, cloneElement } = React
const connectIdleMonitor = createConnector({ connect })
const IdleMonitorView = props => {
const { showControls, idleTitle, idleStatus, isRunning, isDetectionRunning, isIdle, lastActive, lastEvent, children, mounted } = props
const { panel, inner, title, ul, li, activeStyle, infoStyle, idleStyle, stopStyle, eventStyle } = getStyle(props)
const { type, x, y } = lastEvent
const lastDate = new Date(lastActive)
return (
<div>
<div style={panel}>
<div style={inner}>
<ul style={ul}>
<li style={title}>{idleTitle}</li>
<li style={li}>{isRunning === true ? <span style={activeStyle}>ON</span> : <span style={stopStyle}>OFF</span>}</li>
{isRunning === true ? <li style={li}><span style={idleStatus === IDLESTATUS_ACTIVE ? activeStyle : idleStyle}>{idleStatus}</span></li> : null}
{isRunning === true ? <li style={li}>{isDetectionRunning ? <span style={infoStyle}>DETECTING</span> : <span style={idleStyle}>SLEEPING</span>}</li> : null}
{isIdle === true ? <li style={li}><span style={idleStyle}>IDLE</span></li> : null}
{mounted === true ? <li style={li}>{lastDate.toJSON().substr(11, 8)}{type ? ` [${type}]` : null}{x >= 0 && y >= 0 ? ` (${x}, ${y})` : null}</li> : null}
</ul>
</div>
</div>
</div>
)
}
const monitorStyleShape = PropTypes.shape( { backgroundColor: PropTypes.string.isRequired
, color: PropTypes.string.isRequired
, activeColor: PropTypes.string.isRequired
, idleColor: PropTypes.string.isRequired
, stopColor: PropTypes.string.isRequired
})
class IdleMonitor extends Component {
static propTypes = { showStatus: PropTypes.bool.isRequired
, showControls: PropTypes.bool.isRequired
, idleTitle: PropTypes.string.isRequired
, idleTheme: PropTypes.string.isRequired
, invertTheme: PropTypes.bool.isRequired
, dockTo: PropTypes.oneOf(['top', 'bottom'])
, opacity: PropTypes.number.isRequired
, paletteMap: PropTypes.object.isRequired
, idleStatus: PropTypes.string.isRequired
, isRunning: PropTypes.bool.isRequired
, isIdle: PropTypes.bool.isRequired
, isDetectionRunning: PropTypes.bool.isRequired
, lastActive: PropTypes.number.isRequired
, lastEvent: PropTypes.object.isRequired
};
static defaultProps = { showStatus: IS_DEV
, showControls: false
, idleTitle: 'IDLEMONITOR'
, idleTheme: 'solarized'
, invertTheme: false
, opacity: 1
, dockTo: 'bottom'
, paletteMap: { background: ['base00', 'base01']
, content: ['base04', 'base02', 'base05']
, accent: ['base0D', 'base0E', 'base0C']
}
};
constructor(props) {
super(props)
this.state = { mounted: false }
}
componentDidMount() { this.setState({ mounted: true }) }
render() {
const { children, showStatus, showControls, idleTitle, idleTheme, invertTheme, dockTo, opacity, paletteMap, ...idleProps } = this.props
return (
<div className="idle-monitor">
{children ? Children.map(children, x => cloneElement(x, { ...idleProps })) : null}
{showStatus ? <IdleMonitorView {...this.props} mounted={this.state.mounted} /> : null}
</div>
)
}
}
return connectIdleMonitor(IdleMonitor)
}