UNPKG

apeman-react-toast

Version:
189 lines (160 loc) 4.17 kB
/** * Toast component * @constructor ApToast */ "use strict"; import React, {PropTypes as types} from 'react'; import {ApPureMixin} from 'apeman-react-mixins'; import classnames from 'classnames'; import arrayfilter from 'arrayfilter'; import ApToastItem from './ap_toast_item'; /** @lends ApToast */ let ApToast = React.createClass({ //-------------------- // Specs //-------------------- propTypes: { message: types.string, duration: types.number, icon: types.string }, mixins: [ ApPureMixin ], statics: { itemJoiner: '____' }, getInitialState() { return { items: '' }; }, getDefaultProps() { return { message: null, duration: 2000, icon: null }; }, render() { let s = this, {state, props} = s; let valid = state.items.length; if (!valid) { return null; } return ( <div className={classnames('ap-toast', props.className, { })} style={Object.assign({}, props.style)}> <div className="ap-toast-inner"> {s._renderToastItem()} </div> </div> ); }, //-------------------- // Lifecycle //-------------------- componentWillMount() { let s = this; }, componentDidMount() { let s = this, props = s.props; s.startTicking(); s.pushToastItem(props.message); }, componentWillReceiveProps(nextProps) { let s = this; s.pushToastItem(nextProps.message); }, componentWillUnmount() { let s = this; s.stopTicking(); }, //------------------ // Custom //------------------ startTicking() { let s = this; clearTimeout(s._tickTimer); s._ticking = true; s.doTick(); }, stopTicking() { let s = this; clearTimeout(s._tickTimer); s._ticking = false; }, doTick() { let s = this, props = s.props; if (!s._ticking) { return; } s._tickTimer = setTimeout(()=> { s.shiftToastItem(); s.doTick(); }, props.duration); }, pushToastItem(message) { let s = this; if (!message) { return; } let items = (s.state.items || '').split(ApToast.itemJoiner); let duplicate = items[items.length - 1] === message; if (duplicate) { return; } s.setState({ items: items.concat(message).join(ApToast.itemJoiner) }); }, shiftToastItem() { let s = this; let items = (s.state.items || '').split(ApToast.itemJoiner); if (!items.length) { s.setState({items: null}); return; } s.setState({ items: items.slice(1).join(ApToast.itemJoiner) }); }, dismissToastItem(message) { let s = this; let items = (s.state.items || '').split(ApToast.itemJoiner); s.setState({ items: items.filter((filtering)=> filtering !== message) .join(ApToast.itemJoiner) }); }, handleToastItemTap(e){ let s = this; let text = e.target.dataset['text']; s.dismissToastItem(text); }, //------------------ // Private //------------------ _ticking: false, _tickTimer: null, _renderToastItem() { let s = this, {state, props} = s; return (state.items || '').split(ApToast.itemJoiner) .filter(arrayfilter.emptyReject()) .map((text, i) => ( <ApToastItem key={`toast-${text}-${i}`} text={text} icon={props.icon} onTap={s.handleToastItemTap} > </ApToastItem> ) ); } }); module.exports = ApToast;