1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-07-13 15:05:30 +00:00
seahub/frontend/src/components/toast/toast.js
2024-09-27 07:26:04 +03:00

161 lines
3.4 KiB
JavaScript

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