1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-07-14 15:35:35 +00:00
seahub/frontend/src/components/toast/toast.js

157 lines
3.3 KiB
JavaScript
Raw Normal View History

2018-10-09 02:23:32 +00:00
import React from 'react';
2018-12-07 04:59:25 +00:00
import PropTypes from 'prop-types';
import Transition from 'react-transition-group/Transition';
import Alert from './alert';
2018-10-09 02:23:32 +00:00
2018-12-07 04:59:25 +00:00
const ANIMATION_DURATION = 240;
export default class Toast extends React.PureComponent {
static propTypes = {
/**
* The z-index of the toast.
*/
2018-12-07 04:59:25 +00:00
zIndex: PropTypes.number,
/**
* Duration of the toast.
*/
2018-12-07 04:59:25 +00:00
duration: PropTypes.number,
/**
* Function called when the toast is all the way closed.
*/
2018-12-07 04:59:25 +00:00
onRemove: PropTypes.func,
/**
* The type of the alert.
*/
intent: PropTypes.oneOf(['none', 'success', 'warning', 'danger']).isRequired,
2018-12-07 04:59:25 +00:00
/**
* The title of the alert.
*/
2018-12-07 04:59:25 +00:00
title: PropTypes.node,
/**
* Description of the alert.
*/
2018-12-07 04:59:25 +00:00
children: PropTypes.node,
/**
* When true, show a close icon button inside of the toast.
*/
2018-12-07 04:59:25 +00:00
hasCloseButton: PropTypes.bool,
/**
* When false, will close the Toast and call onRemove when finished.
*/
2018-12-07 04:59:25 +00:00
isShown: PropTypes.bool
};
2018-12-07 04:59:25 +00:00
static defaultProps = {
intent: 'none'
};
2018-12-07 04:59:25 +00:00
state = {
isShown: true,
height: 0
};
2018-12-07 04:59:25 +00:00
componentDidUpdate(prevProps) {
if (prevProps.isShown !== this.props.isShown) {
// eslint-disable-next-line react/no-did-update-set-state
2018-12-07 04:59:25 +00:00
this.setState({
isShown: this.props.isShown
});
}
}
componentDidMount() {
this.startCloseTimer();
}
componentWillUnmount() {
this.clearCloseTimer();
}
close = (event) => {
if (event) {
event.nativeEvent.stopImmediatePropagation();
event.stopPropagation();
}
2018-12-07 04:59:25 +00:00
this.clearCloseTimer();
this.setState({
isShown: false
});
};
2018-12-07 04:59:25 +00:00
startCloseTimer = () => {
if (this.props.duration) {
this.closeTimer = setTimeout(() => {
this.close();
}, this.props.duration * 1000);
}
};
2018-12-07 04:59:25 +00:00
clearCloseTimer = () => {
if (this.closeTimer) {
clearTimeout(this.closeTimer);
this.closeTimer = null;
}
};
2018-12-07 04:59:25 +00:00
handleMouseEnter = () => {
this.clearCloseTimer();
};
2018-12-07 04:59:25 +00:00
handleMouseLeave = () => {
this.startCloseTimer();
};
2018-12-07 04:59:25 +00:00
onRef = ref => {
if (ref === null) return;
const { height } = ref.getBoundingClientRect();
this.setState({
height
});
};
2018-12-07 04:59:25 +00:00
render() {
return (
<Transition
appear
unmountOnExit
timeout={ANIMATION_DURATION}
in={this.state.isShown}
onExited={this.props.onRemove}
2018-12-07 04:59:25 +00:00
>
{state => (
<div
data-state={state}
className={`seahub-toast-container ${state}`}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
style={{
height: this.state.height,
zIndex: this.props.zIndex,
marginBottom: this.state.isShown ? 0 : -this.state.height
}}
2018-12-07 04:59:25 +00:00
>
<div ref={this.onRef} style={{ padding: 8 }}>
<Alert
intent={this.props.intent}
title={this.props.title}
children={this.props.children || ''}
isRemovable={this.props.hasCloseButton}
onRemove={(event) => this.close(event)}
2018-12-07 04:59:25 +00:00
/>
</div>
</div>
)}
2018-12-07 04:59:25 +00:00
</Transition>
);
2018-10-09 02:23:32 +00:00
}
}