@kiyasov/noty
Version:
214 lines (178 loc) • 4.52 kB
JavaScript
import React, { Component, Fragment } from "react";
import _ from "lodash";
import PropTypes from "prop-types";
export default class NotyContainer extends Component {
constructor(props) {
super(props);
const { ttl } = this.props;
this.state = {
isShow: true,
ttl: ttl / 1000,
styleProgressBar: {
width: `100%`
}
};
}
static propTypes = {
onClose: PropTypes.func.isRequired,
emit: PropTypes.func.isRequired
};
componentDidCatch(error, info) {
console.error(error, info);
}
setInterval = () => {
const { ttl } = this.props;
if (!ttl) return;
this.interval = setInterval(() => {
this.ttl();
}, 1000);
setTimeout(() => {
this.setState({
styleProgressBar: {
transition: `width ${ttl}ms linear`,
width: `0%`
}
});
}, 1000);
};
clearInterval = () => {
const { ttl } = this.props;
if (!ttl) return;
clearInterval(this.interval);
};
componentDidMount() {
const { emit, id } = this.props;
this.setInterval();
emit("onShow", id);
}
componentWillUnmount() {
this.clearInterval();
}
componentDidUpdate(prevProps) {
const { ttl } = this.props;
let { ttl: timeout } = prevProps;
if (ttl !== timeout) {
this.setState({
ttl: ttl / 1000
});
}
}
ttl = () => {
let { ttl } = this.state;
if (ttl === 0) {
this.clearInterval();
this.onClose();
} else {
this.setState({
ttl: --ttl
});
}
};
onClose = e => {
if (e) e.preventDefault();
const { id, onClose, isButton } = this.props;
const type = _.toInteger(e ? e.currentTarget.getAttribute("data-type") : 0);
if (!isButton && type === 1) return false;
this.setState({
isShow: false
});
setTimeout(() => {
onClose(id, type);
}, 500);
};
resetTtl = () => {
const { ttl, emit, id } = this.props;
if (ttl) {
this.setState({
ttl: ttl / 1000,
styleProgressBar: {
width: `100%`,
transition: "width 0ms linear"
}
});
this.clearInterval();
}
emit("onHover", id);
};
render() {
const {
text,
title,
id,
animate,
isProgressBar,
isCloseButton,
type,
ttl,
props,
template,
theme
} = this.props;
const { styleProgressBar, isShow } = this.state;
return (
<div
id={id}
onMouseEnter={this.resetTtl}
onMouseLeave={this.setInterval}
className={`animated ${
isShow ? animate.open : animate.close
} noty_bar noty_type__${type} noty_theme__${theme} noty_has_timeout noty_has_progressbar`}
>
<div onClick={this.onClose} className="noty_body" data-type="1">
{template ? (
<div
dangerouslySetInnerHTML={{
__html: _.reduce(
template.split(/({{[^}]*(?:}[^}]+)*}*}})/g).filter(Boolean),
(arr, item) => {
if (item.match(/({{[^}]*(?:}[^}]+)*}*}})/g)) {
item = eval(
_.trim(item.replace("{{", "").replace("}}", ""))
);
}
arr += item;
return arr;
},
""
)
}}
/>
) : (
<Fragment>
{title.length ? (
<div
className="notify-title"
dangerouslySetInnerHTML={{
__html: `${props.t ? props.t(title) : title}!`
}}
/>
) : null}
{text.length ? (
<div
className="notify-text"
dangerouslySetInnerHTML={{
__html: `${props.t ? props.t(text) : text}`
}}
/>
) : null}
</Fragment>
)}
</div>
{isProgressBar && ttl ? (
<div className="noty_progressbar" style={styleProgressBar}>
<span style={{opacity: 0.9}}></span>
</div>
) : null}
{isCloseButton ? (
<div
className="noty_close_button"
onClick={this.onClose}
data-type="2"
>
×
</div>
) : null}
</div>
);
}
}