apeman-react-toast
Version:
apeman react package for toast components.
189 lines (160 loc) • 4.17 kB
JSX
/**
* Toast component
* @constructor ApToast
*/
;
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;