wix-style-react
Version:
wix-style-react
200 lines • 10.7 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 { classes, st } from './CardGalleryItem.st.css';
import { WixStyleReactContext } from '../WixStyleReactProvider/context';
import { DragHandle } from '../DragHandle/DragHandle';
import Image from '../Image';
import { DraggableContainer } from '../DraggableContainer/DraggableContainer';
class CardGalleryItem extends React.PureComponent {
constructor() {
super(...arguments);
this.state = {
isHovered: false,
isFocused: false,
};
this._onMouseEnter = () => {
this.setState({ isHovered: true });
};
this._onMouseLeave = () => {
this.setState({ isHovered: false });
};
this._onFocus = e => {
try {
if (process.env.NODE_ENV === 'test' ||
e.target.matches(':focus-visible')) {
this.setState({ isFocused: true });
}
}
catch {
this.setState({ isFocused: true });
}
};
this._onBlur = () => {
this.setState({ isFocused: false });
};
}
_hasFooter() {
const { title, subtitle, suffix, imagePlacement } = this.props;
return !!(title || subtitle || suffix || imagePlacement === 'side');
}
_renderBadge() {
return (React.createElement("div", { className: classes.badgeWrapper, "data-hook": DataHook.Badge }, this.props.badge));
}
_renderDragHandle() {
const { dragHandleProps, dragging, dragDisabled } = this.props;
return (React.createElement(DragHandle, { ...dragHandleProps, dragging: dragging, disabled: dragDisabled, dataHook: DataHook.dragHandle }));
}
_renderFooter() {
const { title, subtitle, size, suffix, draggable, imagePlacement, backgroundImageNode, backgroundImageUrl, settingsMenu, } = this.props;
const heading = size === 'medium' && imagePlacement !== 'side' ? (React.createElement(Heading, { size: "small", ellipsis: true, dataHook: DataHook.Title }, title)) : (React.createElement(Text, { size: "small", weight: "normal", ellipsis: true, dataHook: DataHook.Title }, title));
const textSize = imagePlacement === 'side' ? 'tiny' : size === 'medium' ? 'small' : 'tiny';
return (React.createElement(React.Fragment, null,
imagePlacement === 'top' && React.createElement(Card.Divider, null),
React.createElement("div", { className: classes.footer, "data-hook": DataHook.footer },
draggable && (React.createElement("div", { className: classes.dragHandleWrapper }, this._renderDragHandle())),
imagePlacement === 'side' && (React.createElement("div", { className: st(classes.footerImage, { size }), "data-hook": DataHook.footerImage }, backgroundImageUrl ? (React.createElement(Image, { src: backgroundImageUrl })) : (backgroundImageNode))),
React.createElement("div", { className: classes.footerContent },
heading,
React.createElement(Text, { size: textSize, secondary: true, ellipsis: true, dataHook: DataHook.Subtitle }, subtitle)),
suffix && (React.createElement("div", { className: classes.footerSuffix, "data-hook": DataHook.suffix }, suffix)),
imagePlacement === 'side' &&
settingsMenu &&
this._renderSettingsMenu())));
}
_renderActions() {
const { primaryActionProps: { label, disabled, disabledMessage }, secondaryActionProps, draggable, } = this.props;
const primaryAction = (React.createElement(WixStyleReactContext.Consumer, null, ({ newColorsBranding }) => (React.createElement(Button, { dataHook: DataHook.PrimaryAction, disabled: disabled, skin: newColorsBranding ? 'light' : 'standard', onPointerDown: draggable ? e => e.stopPropagation() : undefined }, label))));
return (React.createElement("div", { className: classes.primaryAction, "data-hook": DataHook.HoverContent },
disabled && disabledMessage ? (React.createElement(Tooltip, { disabled: !disabled, content: disabledMessage }, primaryAction)) : (primaryAction),
secondaryActionProps && (React.createElement("div", { className: classes.secondaryAction },
React.createElement(TextButton, { skin: "light", onClick: event => {
if (secondaryActionProps.onClick) {
secondaryActionProps.onClick(event);
}
event.stopPropagation();
}, dataHook: DataHook.SecondaryAction, onPointerDown: draggable ? e => e.stopPropagation() : undefined }, secondaryActionProps.label)))));
}
_renderSettingsMenu() {
return (React.createElement("div", { className: classes.settingsMenu, "data-hook": DataHook.SettingsMenu }, this.props.settingsMenu));
}
render() {
const { primaryActionProps, secondaryActionProps, dataHook, badge, backgroundImageUrl, backgroundImageNode, settingsMenu, size, draggable, dragging, droppable, dragDisabled, tabIndex, aspectRatio, imagePlacement, showSuffixOnHover, suffix, } = this.props;
const withFooter = !!this._hasFooter();
const showActions = !dragging && !droppable && !!(primaryActionProps || secondaryActionProps);
const withFloatingDragHandle = !!draggable && !withFooter;
const withHover = showActions || withFloatingDragHandle;
return (React.createElement(DraggableContainer, { draggable: draggable && !showActions, dragging: dragging, dim: true, dragDisabled: dragDisabled, tabIndex: tabIndex, className: st(classes.root, {
withFooter,
size,
dragging,
draggable,
showActions,
imagePlacement,
showSuffixOnHover,
suffix: !!suffix,
}), "data-hook": dataHook, onFocus: this._onFocus, onBlur: this._onBlur },
React.createElement("div", { onMouseEnter: this._onMouseEnter, onMouseLeave: this._onMouseLeave, onClick: primaryActionProps.onClick, "data-hook": DataHook.Container },
React.createElement(Card, { stretchVertically: true, showShadow: true },
imagePlacement === 'top' && (React.createElement(Proportion, { aspectRatio: aspectRatio },
React.createElement(MediaOverlay, { media: backgroundImageUrl || backgroundImageNode || '', className: classes.overlay, hoverSkin: withHover ? 'dark' : undefined, hovered: this.state.isHovered || this.state.isFocused, dataHook: DataHook.HoverComponent },
showActions && (React.createElement(MediaOverlay.Content, { visible: "hover" }, this._renderActions())),
settingsMenu && showActions && (React.createElement(MediaOverlay.Content, { visible: "hover", placement: "top-end" }, this._renderSettingsMenu()))),
badge && this._renderBadge(),
React.createElement("div", { className: classes.dragHandleFloatingWrapper }, withFloatingDragHandle && this._renderDragHandle()))),
withFooter && this._renderFooter()))));
}
}
CardGalleryItem.displayName = 'CardGalleryItem';
CardGalleryItem.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 size. */
size: PropTypes.oneOf(['small', 'medium']),
/** Set card title. */
title: PropTypes.node,
/** Set card subtitle. */
subtitle: PropTypes.node,
/** Accepts any component to be rendered as a suffix of the card's footer */
suffix: PropTypes.node,
/**
Show drag handle
*/
draggable: PropTypes.bool,
/**
* Removes buttons when other element is dragging and this card is droppable
*/
droppable: PropTypes.bool,
/**
Extra props to pass to the `<DragHandle />` element
*/
dragHandleProps: PropTypes.object,
/**
* Indicates the element is dragging
*/
dragging: PropTypes.bool,
/**
Show disabled drag handle
*/
dragDisabled: PropTypes.bool,
/** Specifies the tab order of the component. */
tabIndex: PropTypes.number,
/** 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,
}),
/** 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,
/**
* Recommended values:
* - Square - 1
* - Portrait - 3/4
* - Cinema - 16/9
* - Landscape - 4/3
* - Custom number (e.g. 1.5)
*/
aspectRatio: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
/** Sets placement of background image. */
imagePlacement: PropTypes.oneOf(['top', 'side']),
/** Sets suffix behavior to appear only on card hover. */
showSuffixOnHover: PropTypes.bool,
};
CardGalleryItem.defaultProps = {
aspectRatio: 1.6,
primaryActionProps: {
onClick: () => { },
},
size: 'medium',
imagePlacement: 'top',
showSuffixOnHover: false,
};
export default CardGalleryItem;
//# sourceMappingURL=CardGalleryItem.js.map