wix-style-react
Version:
wix-style-react
268 lines (266 loc) • 10.2 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _react = _interopRequireDefault(require("react"));
var _CSSTransition = _interopRequireDefault(require("react-transition-group/CSSTransition"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _Focusable = require("../common/Focusable");
var _Content = _interopRequireDefault(require("./Content"));
var _DragHandle = _interopRequireDefault(require("./DragHandle"));
var _constants = require("./constants");
var _MediaOverlaySt = require("./MediaOverlay.st.css");
var _jsxFileName = "/home/builduser/work/a9c1ac8876d5057c/packages/wix-style-react/dist/cjs/MediaOverlay/MediaOverlay.js";
var layerToVisiblePropMap = {
[_constants.Layer.Default]: _constants.Visible.Default,
[_constants.Layer.Hover]: _constants.Visible.Hover,
[_constants.Layer.Top]: _constants.Visible.Always
};
var placementToRowAlignment = {
[_constants.Placement.TopStart]: 'top',
[_constants.Placement.TopEnd]: 'top',
[_constants.Placement.Middle]: 'middle',
[_constants.Placement.BottomStart]: 'bottom',
[_constants.Placement.BottomEnd]: 'bottom'
};
/** MediaOverlay */
class MediaOverlay extends _react.default.PureComponent {
constructor() {
super(...arguments);
this.state = {
isHovered: false
};
this._onMouseEnter = () => {
if (this.props.hovered === undefined) {
this.setState({
isHovered: true
});
}
};
this._onMouseLeave = () => {
if (this.props.hovered === undefined) {
this.setState({
isHovered: false
});
}
};
this._getFocusProps = () => {
var {
onClick,
focusableOnFocus,
focusableOnBlur,
ariaHidden
} = this.props;
if (onClick) {
return {
onFocus: focusableOnFocus,
onBlur: focusableOnBlur,
tabIndex: ariaHidden ? -1 : 0
};
}
return {
tabIndex: -1
};
};
this._getHoverSkin = () => {
var {
skin,
hoverSkin
} = this.props;
return hoverSkin || skin; // hoverSkin defaults to skin prop value if not provided
};
this._hasSingleSkin = () => this.props.skin === this._getHoverSkin();
this._filterContent = layer => {
var {
children
} = this.props;
var contentElements = _react.default.Children.map(children, child => child) || [];
var filterProps = {
visible: layerToVisiblePropMap[layer]
};
return contentElements.filter(child => /*#__PURE__*/_react.default.isValidElement(child) && child.type.displayName === _Content.default.displayName && Object.keys(filterProps).every(prop => filterProps[prop] === child.props[prop]));
};
this._isContentEmpty = layer => !this._filterContent(layer).length;
this._renderDefaultLayer = () => {
var skin = this._hasSingleSkin() ? _constants.Skin.None : this.props.skin;
return this._renderTransitionOverlay(_constants.Layer.Default, skin, false);
};
this._renderHoverLayer = () => {
var skin = this._hasSingleSkin() ? _constants.Skin.None : this._getHoverSkin();
return this._renderTransitionOverlay(_constants.Layer.Hover, skin, true);
};
this._renderTopLayer = () => this._renderOverlay(_constants.Layer.Top, _constants.Skin.None);
// When both skins for default and hover layers are the same - we don't want to
// animate them with opacity transition as this will produce an undesired effect
// (but we still want to animate all the content inside an overlay layer). As a
// workaround we create this background layer that has no content or animations
// and will render here only the common skin background.
this._renderSingleSkinLayer = () => this._hasSingleSkin() && this._renderOverlay(_constants.Layer.SingleSkin, this.props.skin);
this._shouldRenderOverlay = (layer, skin) => skin !== _constants.Skin.None || !this._isContentEmpty(layer);
this._renderOverlay = (layer, skin) => {
if (!this._shouldRenderOverlay(layer, skin)) {
return;
}
return /*#__PURE__*/_react.default.createElement("div", {
className: (0, _MediaOverlaySt.st)(_MediaOverlaySt.classes.overlay, {
layer,
skin
}),
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 166,
columnNumber: 7
}
}, this._renderContent(layer));
};
this._renderTransitionOverlay = (layer, skin, mountOnEnter) => {
if (!this._shouldRenderOverlay(layer, skin)) {
return;
}
var {
hovered
} = this.props;
var transitionProps = {
in: hovered !== undefined ? hovered : this.state.isHovered,
timeout: 200,
mountOnEnter,
unmountOnExit: mountOnEnter,
classNames: {
enter: _MediaOverlaySt.classes.hoverEnter,
enterActive: _MediaOverlaySt.classes.hoverEnterActive,
enterDone: _MediaOverlaySt.classes.hoverEnterDone,
exit: _MediaOverlaySt.classes.hoverExit
}
};
return /*#__PURE__*/_react.default.createElement(_CSSTransition.default, (0, _extends2.default)({}, transitionProps, {
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 192,
columnNumber: 7
}
}), this._renderOverlay(layer, skin));
};
this._renderContent = layer => {
if (this._isContentEmpty(layer)) {
return;
}
var contentElements = this._filterContent(layer);
if (!contentElements.length) {
return;
}
return contentElements.map((_ref, index) => {
var {
props
} = _ref;
return /*#__PURE__*/_react.default.createElement("div", {
key: index,
className: (0, _MediaOverlaySt.st)(_MediaOverlaySt.classes.contentRow, {
placement: props.placement,
row: placementToRowAlignment[props.placement]
}),
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 210,
columnNumber: 7
}
}, /*#__PURE__*/_react.default.createElement("div", {
className: (0, _MediaOverlaySt.st)(_MediaOverlaySt.classes.contentArea, {
placement: props.placement
}),
"data-hook": "content-area",
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 217,
columnNumber: 9
}
}, props.children));
});
};
}
render() {
var {
dataHook,
skin,
media,
onClick,
removeRoundedBorders,
className,
borderRadius,
ariaHidden
} = this.props;
var isMediaImageUrl = typeof media === 'string';
var Component = onClick ? 'button' : 'div';
return /*#__PURE__*/_react.default.createElement(Component, (0, _extends2.default)({
"aria-hidden": ariaHidden,
"data-hook": dataHook,
onMouseEnter: this._onMouseEnter,
onMouseLeave: this._onMouseLeave,
onClick: onClick
}, this._getFocusProps(), {
className: (0, _MediaOverlaySt.st)(_MediaOverlaySt.classes.root, {
clickable: !!onClick,
removeRadius: removeRoundedBorders
}, className),
"data-skin": skin,
"data-hoverskin": this._getHoverSkin(),
style: {
backgroundImage: isMediaImageUrl && "url(".concat(media, ")"),
borderRadius
},
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 242,
columnNumber: 7
}
}), !isMediaImageUrl && /*#__PURE__*/_react.default.isValidElement(media) && media, this._renderSingleSkinLayer(), this._renderDefaultLayer(), this._renderHoverLayer(), this._renderTopLayer());
}
}
MediaOverlay.displayName = 'MediaOverlay';
MediaOverlay.Content = _Content.default;
MediaOverlay.DragHandle = _DragHandle.default;
MediaOverlay.propTypes = {
/** Applies a data-hook HTML attribute that can be used in the tests. */
dataHook: _propTypes.default.string,
/** Specifies a CSS class name to be appended to the component’s root element. */
className: _propTypes.default.string,
/** Sets a default overlay skin. */
skin: _propTypes.default.oneOf(['none', 'gradient', 'dark']),
/** Sets a hover overlay skin. */
hoverSkin: _propTypes.default.oneOf(['none', 'gradient', 'dark']),
/** Accept image URL or a custom node as a media background. */
media: _propTypes.default.node.isRequired,
/**
* Defines a click handler. When provided, component will be clickable and will have a pointer cursor on hover.
*/
onClick: _propTypes.default.func,
/**
* Accepts any component as `<MediaOverlay.Content>` content.
* Each element has the following properties:
* - `visible` - define when to display this content. Possible values are:
* - `default` (default) - content is visible only when not hovered.
* - `hover` - content is visible only when hovered.
* - `always` - content is always visible.
* - `placement` - define where to place this content. Possible values are `top-start`,
* `top-end`, `middle` (default), `bottom-end` and `bottom-start`.
*/
children: _propTypes.default.node,
/** Toggles hover state in a controlled mode. */
hovered: _propTypes.default.bool,
/** Removes a default borders radius. */
removeRoundedBorders: _propTypes.default.bool,
/** Control border radius of the media container. */
borderRadius: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
/** Adding aria-hidden="true" to an element removes that element and all of its children from the accessibility tree. */
ariaHidden: _propTypes.default.bool
};
MediaOverlay.defaultProps = {
skin: 'none'
};
var _default = exports.default = (0, _Focusable.withFocusable)(MediaOverlay);
//# sourceMappingURL=MediaOverlay.js.map