UNPKG

wix-style-react

Version:
229 lines (203 loc) • 5.39 kB
import React from 'react'; import PropTypes from 'prop-types'; import ArrowLeft from 'wix-ui-icons-common/ArrowLeft'; import { st, classes } from './ComposerHeader.st.css'; import TextButton from '../TextButton'; import Text from '../Text/Text'; import { dataHooks } from './constants'; const ComposerHeaderActions = () => ''; const ComposerHeaderMainActions = () => ''; const ComposerHeaderSaveStatus = ({ saveStatusValue, saveStatusError, dataHook, size, }) => ( <Text dataHook={dataHook || dataHooks.saveStatus} className={classes.saveStatus} secondary light size={size} skin={saveStatusError ? 'error' : 'standard'} tagName="span" weight="thin" > {saveStatusValue} </Text> ); ComposerHeaderActions.displayName = 'Actions'; ComposerHeaderMainActions.displayName = 'MainActions'; ComposerHeaderSaveStatus.displayName = 'SaveStatus'; ComposerHeaderActions.defaultProps = { justifyContent: 'flex-start', }; const filterChildren = ({ children, displayName }) => { const actions = React.Children.map(children, child => child); return ( actions && actions.filter( child => React.isValidElement(child) && child.type.displayName === displayName, ) ); }; const renderSingleAction = ({ props, index }) => { const { children, dataHook, ...rest } = props; return ( children && ( <div key={index} data-hook={dataHook} style={{ ...rest, justifyContent: rest.justifyContent }} className={classes.actions} > {children} </div> ) ); }; const BackButton = React.memo(({ backButtonValue, onBackClick, size }) => { return ( backButtonValue && ( <TextButton skin="dark" prefixIcon={<ArrowLeft />} dataHook={dataHooks.backButton} className={classes.backButton} size={size} onClick={onBackClick} > {backButtonValue} </TextButton> ) ); }); const Actions = React.memo(({ children }) => { const actions = filterChildren({ children, displayName: 'Actions' }); return ( actions && ( <div className={classes.container}> {actions.map(({ props }, index) => renderSingleAction({ props, index }), )} </div> ) ); }); const MainActions = React.memo(({ children }) => { const mainActions = filterChildren({ children, displayName: 'MainActions' }); /** * We only support one type of main action. * It will be always the first one the in list. * */ const exists = mainActions && mainActions[0]; return ( exists && ( <div className={classes.mainActions} data-hook={mainActions[0].props.dataHook || dataHooks.mainAction} > {mainActions[0] && mainActions[0].props.children} </div> ) ); }); const shouldRenderDivider = ({ children, divider }) => { const actions = filterChildren({ children, displayName: 'Actions' }); const sides = { left: { item: 0, justifyContent: 'flex-start', }, right: { item: actions && actions.length - 1, justifyContent: 'flex-end', }, }; if (actions && actions.length === 1) { return actions[0].props.justifyContent === sides[divider].justifyContent; } if (actions && actions.length > 1) { return ( actions[sides[divider].item].props.justifyContent === sides[divider].justifyContent ); } return; }; const LeftDivider = React.memo(({ backButton, children }) => { const shouldRender = backButton && shouldRenderDivider({ children, divider: 'left', }); return ( shouldRender && ( <div className={classes.divider} data-hook={dataHooks.leftDivider} /> ) ); }); const RightDivider = React.memo(({ children }) => { const mainActions = filterChildren({ children, displayName: 'MainActions' }); const shouldRender = mainActions && mainActions[0] && shouldRenderDivider({ children, divider: 'right', }); return ( shouldRender && ( <div className={classes.divider} data-hook={dataHooks.rightDivider} /> ) ); }); /** ComposerHeader */ const ComposerHeader = ({ children, dataHook, size, dropShadow, backButtonValue, onBackClick, ...rest }) => { return ( <div data-hook={dataHook} className={st(classes.root, { size, dropShadow })} > <BackButton size={size} backButtonValue={backButtonValue} onBackClick={onBackClick} /> <LeftDivider backButton={backButtonValue} children={children} /> <Actions>{children}</Actions> <RightDivider children={children} /> <MainActions>{children}</MainActions> </div> ); }; ComposerHeader.propTypes = { /** hook for testing purposes */ dataHook: PropTypes.string, /** back button value */ backButtonValue: PropTypes.node, /** back button callback function */ onBackClick: PropTypes.func, /** composer header size */ size: PropTypes.oneOf(['small', 'medium']), /** shadow effect */ dropShadow: PropTypes.bool, }; ComposerHeader.defaultProps = { size: 'medium', }; ComposerHeader.displayName = 'ComposerHeader'; ComposerHeader.Actions = ComposerHeaderActions; ComposerHeader.MainActions = ComposerHeaderMainActions; ComposerHeader.SaveStatus = ComposerHeaderSaveStatus; export default ComposerHeader;