import React, { Children, Component, HTMLAttributes, ReactElement } from 'react'; import PopoutWrapper from '../PopoutWrapper/PopoutWrapper'; import getClassName from '../../helpers/getClassName'; import classNames from '../../lib/classNames'; import transitionEvents from '../../lib/transitionEvents'; import withInsets from '../../hoc/withInsets'; import withPlatform from '../../hoc/withPlatform'; import { isNumeric } from '../../lib/utils'; import { HasInsets, HasPlatform } from '../../types'; import { ANDROID, IOS } from '../../lib/platform'; export interface ActionSheetProps extends HTMLAttributes, HasPlatform, HasInsets { /** * iOS only */ header?: React.ReactNode; /** * iOS only */ text?: React.ReactNode; onClose(): void; } export interface ActionSheetState { closing: boolean; } export type CloseCallback = () => void; export type ClickHandler = (event: React.MouseEvent) => void; export type ActionType = (event: React.MouseEvent) => void; export type ItemClickHandler = (action: ActionType, autoclose: boolean) => (event: React.MouseEvent) => void; export type AnimationEndCallback = (e?: AnimationEvent) => void; export type IsItemLast = (index: number) => boolean; class ActionSheet extends Component { constructor(props: ActionSheetProps) { super(props); this.elRef = React.createRef(); } state: ActionSheetState = { closing: false, }; elRef: React.RefObject; onClose: CloseCallback = () => { this.setState({ closing: true }); this.waitTransitionFinish(this.props.onClose); }; onItemClick: ItemClickHandler = (action: ActionType, autoclose: boolean) => (event: React.MouseEvent) => { event.persist(); if (autoclose) { this.setState({ closing: true }); this.waitTransitionFinish(() => { autoclose && this.props.onClose(); action && action(event); }); } else { action && action(event); } }; stopPropagation: ClickHandler = (e: React.MouseEvent) => e.stopPropagation(); waitTransitionFinish(eventHandler: AnimationEndCallback) { if (transitionEvents.supported) { const eventName = transitionEvents.prefix ? transitionEvents.prefix + 'TransitionEnd' : 'transitionend'; this.elRef.current.removeEventListener(eventName, eventHandler); this.elRef.current.addEventListener(eventName, eventHandler); } else { setTimeout(eventHandler, this.props.platform === ANDROID ? 200 : 300); } } isItemLast: IsItemLast = (index: number) => { const childrenArray = Children.toArray(this.props.children); const lastElement = childrenArray[childrenArray.length - 1] as ReactElement; if (index === childrenArray.length - 1) { return true; } else if (index === childrenArray.length - 2 && lastElement.props.mode === 'cancel') { return true; } return false; }; render() { const { children, className, header, text, style, insets, platform, ...restProps } = this.props; return (
{platform === IOS &&
{header &&
{header}
} {text &&
{text}
}
} {Children.toArray(children).map((child: React.ReactElement, index: number, arr: []) => child && React.cloneElement(child, { onClick: this.onItemClick(child.props.onClick, child.props.autoclose), style: index === arr.length - 1 && isNumeric(insets.bottom) ? { marginBottom: insets.bottom } : null, isLast: this.isItemLast(index), }), )}
); } } export default withPlatform(withInsets(ActionSheet));