toast 支持配置是否保留
This commit is contained in:
parent
aa185d96e7
commit
bef3e9b011
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue