UNPKG

mdc-react

Version:

Material Components for the web implemented in React

133 lines (117 loc) 3.95 kB
import { forwardRef, useRef, useCallback, useImperativeHandle } from 'react'; import { CSSTransition } from 'react-transition-group'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { Clone } from '../component'; import Icon from '../icon'; import { numbers, cssClasses } from './constants'; const Banner = forwardRef(({ text, icon, graphic = icon, action, primaryAction = action, secondaryAction, open = false, centered = false, fixed = false, mobileStacked = false, element = 'div', component: Element = element, className, children = text, ...props }, ref) => { const rootRef = useRef(); const contentRef = useRef(); useImperativeHandle(ref, () => rootRef.current); const handleEntering = useCallback((node, isAppearing) => { if (!isAppearing) { node.style.height = `${contentRef.current.offsetHeight}px`; } }, []); const handleExiting = useCallback(node => { node.style.height = '0px'; }, []); const classNames = classnames(cssClasses.ROOT, { [cssClasses.FIXED]: fixed, [cssClasses.CENTERED]: centered, [cssClasses.MOBILE_STACKED]: mobileStacked }, className); const content = ( <div ref={contentRef} className={cssClasses.CONTENT} role="status"> <div className={cssClasses.GRAPHIC_TEXT_WRAPPER}> {graphic && <div className={cssClasses.GRAPHIC}> <Clone component={graphic} fallback={Icon} className={cssClasses.ICON} /> </div> } <Clone component={children} fallback="div" className={cssClasses.TEXT} /> </div> {primaryAction && <div className={cssClasses.ACTIONS}> {secondaryAction && <Clone component={secondaryAction} className={cssClasses.SECONDARY_ACTION} /> } <Clone component={primaryAction} className={cssClasses.PRIMARY_ACTION} /> </div> } </div> ); return ( <CSSTransition in={open} appear={open} timeout={{ appear: 0, enter: numbers.BANNER_ANIMATION_OPEN_TIME_MS, exit: numbers.BANNER_ANIMATION_CLOSE_TIME_MS }} classNames={{ appear: cssClasses.APPEARING, appearDone: cssClasses.APPEARED, enter: cssClasses.OPENING, enterActive: cssClasses.OPEN, enterDone: cssClasses.OPEN, exit: cssClasses.CLOSING }} mountOnEnter unmountOnExit onEntering={handleEntering} onExiting={handleExiting} > <Element ref={rootRef} className={classNames} role="banner" {...props}> {content} </Element> </CSSTransition> ); }); Banner.displayName = 'MDCBanner'; Banner.propTypes = { text: PropTypes.node.isRequired, icon: PropTypes.node, graphic: PropTypes.element, action: PropTypes.element, primaryAction: PropTypes.element, secondaryAction: PropTypes.element, open: PropTypes.bool, appear: PropTypes.bool, fixed: PropTypes.bool, centered: PropTypes.bool, mobileStacked: PropTypes.bool }; export default Banner;