UNPKG

wix-style-react

Version:
200 lines • 10.7 kB
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