wix-style-react
Version:
201 lines (175 loc) • 5.58 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import Card from '../Card';
import Button from '../Button';
import TextButton from '../TextButton';
import Text from '../Text';
import Heading from '../Heading';
import Proportion from '../Proportion';
import Tooltip from '../Tooltip';
import MediaOverlay from '../MediaOverlay';
import { DataHook } from './constants';
import { st, classes } from './CardGalleryItem.st.css';
class CardGalleryItem extends React.PureComponent {
static displayName = 'CardGalleryItem';
static propTypes = {
/** Accepts a <Badge/> or any other static indicator. Passed element will be displayed at the top left corner of a card. */
badge: PropTypes.node,
/** Set card title. */
title: PropTypes.node,
/** Set card subtitle. */
subtitle: PropTypes.node,
/** Specifies background image URL. */
backgroundImageUrl: PropTypes.string,
/** Accepts any component to be rendered as a background image. */
backgroundImageNode: PropTypes.node,
/** Defines properties for the primary action button. */
primaryActionProps: PropTypes.shape({
/** Label of primary action button */
label: PropTypes.node,
/** On click handler of primary action button and of the whole card */
onClick: PropTypes.func,
/** Disable the primary action button */
disabled: PropTypes.bool,
/** Message to be displayed when primary action button is disabled */
disabledMessage: PropTypes.string,
}).isRequired,
/** Defines properties for the secondary action button. */
secondaryActionProps: PropTypes.shape({
/** Label of secondary action text button */
label: PropTypes.node,
/** On click handler of secondary action text button */
onClick: PropTypes.func,
}).isRequired,
/** Defines a popover menu to be displayed on hover at the top right corner or a card. */
settingsMenu: PropTypes.node,
/** Applies a data-hook HTML attribute that can be used in the tests. */
dataHook: PropTypes.string,
};
static defaultProps = {
primaryActionProps: {
onClick: () => {},
},
secondaryActionProps: {
onClick: () => {},
},
};
state = {
isHovered: false,
};
_onMouseEnter = () => {
this.setState({ isHovered: true });
};
_onMouseLeave = () => {
this.setState({ isHovered: false });
};
_hasFooter() {
const { title, subtitle } = this.props;
return !!(title || subtitle);
}
_renderBadge() {
return (
<div className={classes.badgeWrapper} data-hook={DataHook.Badge}>
{this.props.badge}
</div>
);
}
_renderFooter() {
const { title, subtitle } = this.props;
return (
<>
<Card.Divider />
<div className={classes.footer}>
<Heading appearance="H3" ellipsis dataHook={DataHook.Title}>
{title}
</Heading>
<Text size="small" secondary ellipsis dataHook={DataHook.Subtitle}>
{subtitle}
</Text>
</div>
</>
);
}
_renderActions() {
const {
primaryActionProps: { label, disabled, disabledMessage },
secondaryActionProps,
} = this.props;
const primaryAction = (
<Button dataHook={DataHook.PrimaryAction} disabled={disabled}>
{label}
</Button>
);
return (
<div className={classes.primaryAction} data-hook={DataHook.HoverContent}>
{disabled && disabledMessage ? (
<Tooltip disabled={!disabled} content={disabledMessage}>
{primaryAction}
</Tooltip>
) : (
primaryAction
)}
<div className={classes.secondaryAction}>
<TextButton
skin="light"
onClick={event => {
secondaryActionProps.onClick(event);
event.stopPropagation();
}}
dataHook={DataHook.SecondaryAction}
>
{secondaryActionProps.label}
</TextButton>
</div>
</div>
);
}
_renderSettingsMenu() {
return (
<div data-hook={DataHook.SettingsMenu}>{this.props.settingsMenu}</div>
);
}
render() {
const {
primaryActionProps,
dataHook,
badge,
backgroundImageUrl,
backgroundImageNode,
settingsMenu,
} = this.props;
return (
<Proportion dataHook={dataHook}>
<div
className={st(classes.root, { withFooter: !!this._hasFooter() })}
onMouseEnter={this._onMouseEnter}
onMouseLeave={this._onMouseLeave}
onClick={primaryActionProps.onClick}
data-hook={DataHook.Container}
>
<Card stretchVertically>
<MediaOverlay
media={backgroundImageUrl || backgroundImageNode || ''}
className={classes.overlay}
hoverSkin="dark"
hovered={this.state.isHovered}
dataHook={DataHook.HoverComponent}
>
<MediaOverlay.Content visible="hover">
{this._renderActions()}
</MediaOverlay.Content>
{settingsMenu && (
<MediaOverlay.Content visible="hover" placement="top-end">
{this._renderSettingsMenu()}
</MediaOverlay.Content>
)}
</MediaOverlay>
{badge && this._renderBadge()}
{this._hasFooter() && this._renderFooter()}
</Card>
</div>
</Proportion>
);
}
}
export default CardGalleryItem;