toast 支持配置是否保留

This commit is contained in:
2betop 2019-12-29 10:48:53 +08:00
parent aa185d96e7
commit bef3e9b011
2 changed files with 59 additions and 63 deletions

View File

@ -90,6 +90,20 @@
animation-name: bounceOut;
}
&-close {
position: absolute;
top: $gap-xs;
right: $gap-sm;
color: $white;
line-height: 1;
opacity: 0.8;
&:hover {
color: $white;
opacity: 1;
}
}
&-title {
display: $Toast-display;
font-size: $fontSizeMd;

View File

@ -13,8 +13,14 @@ import Transition, {
import React from 'react';
import cx from 'classnames';
import Html from './Html';
import {uuid, autobind} from '../utils/helper';
import {ClassNamesFn, themeable} from '../theme';
import {uuid, autobind, noop} from '../utils/helper';
import {ClassNamesFn, themeable, classnames} from '../theme';
import {Icon} from './icons';
interface Config {
closeButton?: boolean;
timeout?: number;
}
const fadeStyles: {
[propName: string]: string;
@ -25,12 +31,6 @@ const fadeStyles: {
};
let toastRef: any = null;
let config: {
closeButton?: boolean;
timeOut?: number;
extendedTimeOut?: number;
} = {};
const show = (
content: string,
title: string = '',
@ -40,7 +40,7 @@ const show = (
if (!toastRef || !toastRef[method]) {
return;
}
toastRef[method](content, title || '', {...config, ...conf});
toastRef[method](content, title || '', {...conf});
};
interface ToastComponentProps {
@ -52,14 +52,13 @@ interface ToastComponentProps {
| 'bottom-left'
| 'bottom-right';
closeButton: boolean;
timeOut: number;
extendedTimeOut: number;
timeout: number;
classPrefix: string;
classnames: ClassNamesFn;
className?: string;
}
interface Item {
interface Item extends Config {
title?: string;
body: string;
level: 'info' | 'success' | 'error' | 'warning';
@ -76,12 +75,11 @@ export class ToastComponent extends React.Component<
> {
static defaultProps: Pick<
ToastComponentProps,
'position' | 'closeButton' | 'timeOut' | 'extendedTimeOut'
'position' | 'closeButton' | 'timeout'
> = {
position: 'top-right',
closeButton: false,
timeOut: 5000,
extendedTimeOut: 3000
timeout: 5000
};
// 当前ToastComponent是否真正render了
@ -90,15 +88,6 @@ export class ToastComponent extends React.Component<
items: []
};
componentWillMount() {
const {closeButton, timeOut, extendedTimeOut} = this.props;
config = {
closeButton,
timeOut,
extendedTimeOut
};
}
componentDidMount() {
this.hasRendered = true;
toastRef = this;
@ -157,27 +146,27 @@ export class ToastComponent extends React.Component<
return null;
}
const {classPrefix: ns, className, timeOut, position} = this.props;
const {classnames: cx, className, timeout, position} = this.props;
const items = this.state.items;
return (
<div
className={cx(
`${ns}Toast-wrap ${ns}Toast-wrap--${position.replace(
/\-(\w)/g,
(_, l) => l.toUpperCase()
`Toast-wrap Toast-wrap--${position.replace(/\-(\w)/g, (_, l) =>
l.toUpperCase()
)}`,
className
)}
>
{items.map((item, index) => (
<ToastMessage
classnames={classnames}
key={item.id}
classPrefix={ns}
title={item.title}
body={item.body}
level={item.level || 'info'}
timeOut={timeOut}
timeout={item.timeout ?? timeout}
closeButton={item.closeButton}
onDismiss={this.handleDismissed.bind(this, index)}
/>
))}
@ -192,7 +181,8 @@ interface ToastMessageProps {
title?: string;
body: string;
level: 'info' | 'success' | 'error' | 'warning';
timeOut: number;
timeout: number;
closeButton?: boolean;
position:
| 'top-right'
| 'top-center'
@ -201,7 +191,7 @@ interface ToastMessageProps {
| 'bottom-left'
| 'bottom-right';
onDismiss?: () => void;
classPrefix: string;
classnames: ClassNamesFn;
allowHtml: boolean;
}
@ -209,9 +199,12 @@ interface ToastMessageState {
visible: boolean;
}
export class ToastMessage extends React.Component<ToastMessageProps> {
export class ToastMessage extends React.Component<
ToastMessageProps,
ToastMessageState
> {
static defaultProps = {
timeOut: 5000,
timeout: 5000,
classPrefix: '',
position: 'top-right',
allowHtml: true,
@ -225,15 +218,6 @@ export class ToastMessage extends React.Component<ToastMessageProps> {
// content: React.RefObject<HTMLDivElement>;
timer: NodeJS.Timeout;
mounted: boolean = false;
constructor(props: ToastMessageProps) {
super(props);
// this.content = React.createRef();
this.handleMouseEnter = this.handleMouseEnter.bind(this);
this.handleMouseLeave = this.handleMouseLeave.bind(this);
this.handleEntered = this.handleEntered.bind(this);
this.close = this.close.bind(this);
}
componentDidMount() {
this.mounted = true;
@ -247,21 +231,25 @@ export class ToastMessage extends React.Component<ToastMessageProps> {
this.mounted = false;
}
@autobind
handleMouseEnter() {
clearTimeout(this.timer);
}
@autobind
handleMouseLeave() {
this.handleEntered();
}
@autobind
handleEntered() {
const timeOut = this.props.timeOut;
if (this.mounted) {
this.timer = setTimeout(this.close, timeOut);
const timeout = this.props.timeout;
if (this.mounted && timeout) {
this.timer = setTimeout(this.close, timeout);
}
}
@autobind
close() {
clearTimeout(this.timer);
this.setState({
@ -272,8 +260,8 @@ export class ToastMessage extends React.Component<ToastMessageProps> {
render() {
const {
onDismiss,
classPrefix: ns,
position,
classnames: cx,
closeButton,
title,
body,
allowHtml,
@ -290,26 +278,20 @@ export class ToastMessage extends React.Component<ToastMessageProps> {
onExited={onDismiss}
>
{(status: string) => {
// if (status === ENTERING) {
// // force reflow
// // 由于从 mount 进来到加上 in 这个 class 估计是时间太短上次的样式还没应用进去所以这里强制reflow一把。
// // 否则看不到动画。
// this.content.current && this.content.current.offsetWidth;
// }
return (
<div
// ref={this.content}
className={cx(
`${ns}Toast ${ns}Toast--${level}`,
fadeStyles[status]
)}
className={cx(`Toast Toast--${level}`, fadeStyles[status])}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
onClick={this.close}
onClick={closeButton ? noop : this.close}
>
{title ? <div className={`${ns}Toast-title`}>{title}</div> : null}
<div className={`${ns}Toast-body`}>
{closeButton ? (
<a onClick={this.close} className={cx(`Toast-close`)}>
<Icon icon="close" className="icon" />
</a>
) : null}
{title ? <div className={cx('Toast-title')}>{title}</div> : null}
<div className={cx('Toast-body')}>
{allowHtml ? <Html html={body} /> : body}
</div>
</div>