import React, { Component, HTMLAttributes, MouseEventHandler, ReactNode, SyntheticEvent } from 'react'; import Tappable from '../Tappable/Tappable'; import PopoutWrapper from '../PopoutWrapper/PopoutWrapper'; import { getClassName } from '../../helpers/getClassName'; import { classNames } from '../../lib/classNames'; import { transitionEvent } from '../../lib/supportEvents'; import { ANDROID, VKCOM, IOS } from '../../lib/platform'; import { HasPlatform } from '../../types'; import { withPlatform } from '../../hoc/withPlatform'; import { withAdaptivity, AdaptivityProps, ViewWidth } from '../../hoc/withAdaptivity'; import Button from '../Button/Button'; import { hasReactNode } from '../../lib/utils'; import Headline from '../Typography/Headline/Headline'; import Title from '../Typography/Title/Title'; import Caption from '../Typography/Caption/Caption'; import ModalDismissButton from '../ModalDismissButton/ModalDismissButton'; export type AlertActionInterface = AlertProps['actions'][0]; export interface AlertProps extends HTMLAttributes, HasPlatform, AdaptivityProps { actionsLayout?: 'vertical' | 'horizontal'; actions?: Array<{ title: string; action?: VoidFunction; autoclose?: boolean; mode: 'cancel' | 'destructive' | 'default'; }>; header?: ReactNode; text?: ReactNode; onClose?: VoidFunction; } export interface AlertState { closing: boolean; } type TransitionEndHandler = (e?: TransitionEvent) => void; type ItemClickHander = (item: AlertActionInterface) => () => void; class Alert extends Component { constructor(props: AlertProps) { super(props); this.element = React.createRef(); this.state = { closing: false, }; } element: React.RefObject; private transitionFinishTimeout: ReturnType; static defaultProps: AlertProps = { actionsLayout: 'horizontal', actions: [], }; onItemClick: ItemClickHander = (item: AlertActionInterface) => () => { const { action, autoclose } = item; if (autoclose) { this.setState({ closing: true }); this.waitTransitionFinish((e?: TransitionEvent) => { if (!e || e.propertyName === 'opacity') { autoclose && this.props.onClose(); action && action(); } }); } else { action && action(); } }; onClose: VoidFunction = () => { this.setState({ closing: true }); this.waitTransitionFinish((e?: TransitionEvent) => { if (!e || e.propertyName === 'opacity') { this.props.onClose(); } }); }; stopPropagation: MouseEventHandler = (e: SyntheticEvent) => { e.stopPropagation(); }; waitTransitionFinish(eventHandler: TransitionEndHandler) { if (transitionEvent.supported) { this.element.current.removeEventListener(transitionEvent.name, eventHandler); this.element.current.addEventListener(transitionEvent.name, eventHandler); } else { clearTimeout(this.transitionFinishTimeout); this.transitionFinishTimeout = setTimeout(eventHandler.bind(this), this.props.platform === ANDROID || this.props.platform === VKCOM ? 200 : 300); } } renderHeader(header: ReactNode) { switch (this.props.platform) { case VKCOM: return {header}; case IOS: return {header}; case ANDROID: return {header}; } } renderText(text: ReactNode) { switch (this.props.platform) { case VKCOM: return {text}; case IOS: return {text}; case ANDROID: return {text}; } } renderAction = (action: AlertActionInterface, i: number) => { const { platform } = this.props; switch (platform) { case ANDROID: return ( ); case VKCOM: return ( ); default: return ( {action.title} ); } }; render() { const { actions, actionsLayout, children, className, style, platform, viewWidth, text, header, ...restProps } = this.props; const { closing } = this.state; const resolvedActionsLayout: AlertProps['actionsLayout'] = platform === VKCOM ? 'horizontal' : actionsLayout; const canShowCloseButton = platform === VKCOM || platform === ANDROID && viewWidth >= ViewWidth.SMALL_TABLET; return (
{canShowCloseButton && }
{hasReactNode(header) && this.renderHeader(header)} {hasReactNode(text) && this.renderText(text)} {children}
); } } export default withPlatform(withAdaptivity(Alert, { viewWidth: true, }));