/** * Drawer component * * @author Brauer Ilya * @date 2020-12-04 */ import * as React from 'react'; import {joinClassNames, Overlay, SIZE} from '../../index'; import * as styles from './drawer.m.scss'; import {getSizeThemeKey} from '../../utils/getSizeThemeKey'; import {SizeClassNames} from '../../type/SizeTypes'; type DrawerPosition = 'right' | 'bottom'; type DrawerTheme = 'light' | 'dark'; interface IProps { isOpen: boolean; onClose: (e: Event | React.SyntheticEvent) => void; parentContainer?: HTMLElement; title?: string; leftExtraItems?: React.ReactNode; rightExtraItems?: React.ReactNode; } interface IDefProps { hasBackdrop: boolean; shouldCloseOnClickOutside: boolean; shouldCloseOnEsc: boolean; position: DrawerPosition; size: SIZE; theme: DrawerTheme; } interface IState { isOpen: boolean; } export class Drawer extends React.PureComponent, IState> { static defaultProps: IDefProps = { hasBackdrop: true, shouldCloseOnClickOutside: true, shouldCloseOnEsc: true, size: SIZE.MIDDLE, position: 'right', theme: 'light' }; drawerRef = React.createRef(); override state: IState = { isOpen: this.props.isOpen }; override componentDidMount (): void { this.updateIsOpenDrawer(); } override componentDidUpdate (prevProps: Readonly>, prevState: Readonly, snapshot?: any): void { if (prevProps.isOpen !== this.props.isOpen) { this.updateIsOpenDrawer(); } } updateIsOpenDrawer = () => { if (this.props.isOpen !== this.state.isOpen && !this.state.isOpen) { this.setState({ isOpen: true }, () => { if (this.props.parentContainer) { this.calcSize(); } }); } }; calcSize = () => { if (this.props.parentContainer) { const boundaryRect = this.props.parentContainer.getBoundingClientRect(); if (this.drawerRef.current) { if (this.props.position === 'bottom') { this.drawerRef.current.style.left = boundaryRect.left + 10 + 'px'; this.drawerRef.current.style.right = '0px'; this.drawerRef.current.style.width = boundaryRect.width - 20 + 'px'; } else if (this.props.position === 'right') { this.drawerRef.current.style.top = boundaryRect.top + 10 + 'px'; this.drawerRef.current.style.bottom = '0px'; this.drawerRef.current.style.height = boundaryRect.height - 20 + 'px'; } } } }; updateIsOpenDrawerAfterAnimation = () => { if (this.props.isOpen !== this.state.isOpen && this.state.isOpen ) { this.setState({ isOpen: false }); } }; get hasHeader () { return this.props.title || this.props.rightExtraItems || this.props.leftExtraItems; } override render () { const { onClose, hasBackdrop, shouldCloseOnClickOutside, shouldCloseOnEsc, size, title, leftExtraItems, rightExtraItems } = this.props; let sizeClassName; if (size) { const sizeThemeKey = getSizeThemeKey('', size); sizeClassName = styles[sizeThemeKey]; } const classNameContainer = joinClassNames( styles.container, sizeClassName, [styles.positionRight, this.props.position === 'right'], [styles.positionBottom, this.props.position === 'bottom'], [styles.noBackdrop, this.props.hasBackdrop !== true], [styles.animationShow, this.props.isOpen], [styles.animationHide, !this.props.isOpen], [styles.darkTheme, this.props.theme === 'dark'], [styles.lightTheme, this.props.theme === 'light'], [styles.hasParent, this.props.parentContainer !== undefined] ); const classNameContent = joinClassNames( styles.content, [styles.withTitle, title !== undefined] ); const leftExtraStyles = joinClassNames( styles.extraItemsContainer, styles.leftExtraItemsContainer ); return (
{this.hasHeader && (
{leftExtraItems && (
{leftExtraItems}
)}
{title}
{rightExtraItems}
)}
{this.props.children}
); } }