react-award
Version:
React component for rewarding users
260 lines (248 loc) • 8.98 kB
JavaScript
var lottie = require('lottie-web');
var React = require('react');
var reactTransitionState = require('react-transition-state');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var lottie__default = /*#__PURE__*/_interopDefaultLegacy(lottie);
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
function _extends() {
_extends = Object.assign ? Object.assign.bind() : function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
/**
* Mask component
*/
var Mask = function Mask(props) {
var backgroundColor = props.backgroundColor,
className = props.className,
children = props.children,
_props$style = props.style,
style = _props$style === void 0 ? {} : _props$style;
if (!props.image) {
return null;
}
return React__default["default"].createElement("div", {
className: className,
style: _extends({
WebkitMaskImage: "url(" + props.image + ")",
maskImage: "url(" + props.image + ")",
backgroundColor: backgroundColor
}, style)
}, children);
};
/**
* Image component
*/
var Image = function Image(props) {
if (!props.image) {
return null;
}
return React__default["default"].createElement("img", {
src: props.image,
style: _extends({
transitionDuration: props.duration + "ms"
}, props.style || {}),
className: props.className
});
};
/**
* A wrapper for the Lottie player that simplifies the event that is triggered when loading,
* and allows you to play or stop the animation in a declarative way.
*/
var Player = function Player(props) {
var animation = props.animation,
play = props.play,
segments = props.segments,
className = props.className,
style = props.style,
speed = props.speed;
var animationRef = React.useRef(null);
var containerRef = React.useRef(null);
// animation loader
React.useEffect(function () {
animationRef.current = props.lottie.loadAnimation({
autoplay: false,
loop: false,
animationData: props.animation,
renderer: 'svg',
container: containerRef.current
});
return function () {
var _animationRef$current;
(_animationRef$current = animationRef.current) == null ? void 0 : _animationRef$current.destroy();
animationRef.current = null;
};
}, [animation]);
// event handlers
React.useEffect(function () {
if (!animationRef.current) {
return;
}
var onLoad = function onLoad() {
var _animationRef$current2, _animationRef$current3, _props$onLoad;
(_animationRef$current2 = animationRef.current) == null ? void 0 : _animationRef$current2.hide();
(_animationRef$current3 = animationRef.current) == null ? void 0 : _animationRef$current3.stop();
(_props$onLoad = props.onLoad) == null ? void 0 : _props$onLoad.call(null);
};
var onComplete = function onComplete() {
var _animationRef$current4, _animationRef$current5, _props$onComplete;
(_animationRef$current4 = animationRef.current) == null ? void 0 : _animationRef$current4.hide();
(_animationRef$current5 = animationRef.current) == null ? void 0 : _animationRef$current5.stop();
(_props$onComplete = props.onComplete) == null ? void 0 : _props$onComplete.call(null);
};
animationRef.current.addEventListener('DOMLoaded', onLoad);
animationRef.current.addEventListener('complete', onComplete);
return function () {
var _animationRef$current6, _animationRef$current7;
(_animationRef$current6 = animationRef.current) == null ? void 0 : _animationRef$current6.removeEventListener('DOMLoaded', onLoad);
(_animationRef$current7 = animationRef.current) == null ? void 0 : _animationRef$current7.removeEventListener('complete', onComplete);
};
}, [props.onLoad, props.onComplete]);
React.useEffect(function () {
if (play) {
var _animationRef$current8, _animationRef$current9;
(_animationRef$current8 = animationRef.current) == null ? void 0 : _animationRef$current8.show();
(_animationRef$current9 = animationRef.current) == null ? void 0 : _animationRef$current9.setSpeed(speed || 1);
if (Array.isArray(segments)) {
var _animationRef$current10;
(_animationRef$current10 = animationRef.current) == null ? void 0 : _animationRef$current10.playSegments(segments, true);
} else {
var _animationRef$current11;
(_animationRef$current11 = animationRef.current) == null ? void 0 : _animationRef$current11.play();
}
}
}, [play, segments, speed]);
return React__default["default"].createElement("div", {
style: style,
className: className,
ref: containerRef
});
};
/**
* Inject award properties to custom child
*/
var withAwardProperties = function withAwardProperties(WrappedComponent) {
return function (props) {
if (!React__default["default"].isValidElement(WrappedComponent)) {
return null;
}
return React__default["default"].cloneElement(WrappedComponent, {
className: "" + props.className,
style: {
transitionDuration: props.duration + "ms"
}
});
};
};
/**
* The "useHover" hook allows you to detect if the mouse is hovering over a specific element in a React component.
* It returns a reference to the element and a boolean value indicating whether the mouse is hovering over it or not.
*/
function useHover() {
var _useState = React.useState(false),
hovered = _useState[0],
setHovered = _useState[1];
var ref = React.useRef(null);
function handleMouseOver() {
setHovered(true);
}
function handleMouseOut() {
//setWasHovered(false);
}
React.useEffect(function () {
var current = ref.current;
if (current) {
current.addEventListener('mouseover', handleMouseOver);
current.addEventListener('mouseout', handleMouseOut);
}
return function () {
if (current) {
current.removeEventListener('mouseover', handleMouseOver);
current.removeEventListener('mouseout', handleMouseOut);
}
};
}, [ref]);
return [ref, hovered];
}
/** Allows to inject the lottie player dependency */
var buildAward = function buildAward(lottie) {
/** Award component */
var Award = function Award(props) {
var _useHover = useHover(),
ref = _useHover[0],
hovered = _useHover[1];
var _useState = React.useState(false),
loaded = _useState[0],
setLoaded = _useState[1];
var _useTransition = reactTransitionState.useTransition({
timeout: props.duration,
preEnter: true
}),
transition = _useTransition[0],
showImage = _useTransition[1];
// current status
var showPlaceholder = props.showPlaceholder && !loaded;
var play = loaded ? props.playOnHover && hovered || !!props.play : false;
React.useEffect(function () {
showImage(play);
}, [play]);
var CustomChild = React.useMemo(function () {
return withAwardProperties(props.children);
}, [props.children]);
return React__default["default"].createElement("div", {
ref: ref,
className: "award-container",
style: props.style
}, React__default["default"].createElement(Mask, {
image: props.image,
style: props.maskStyle,
backgroundColor: props.backgroundColor,
className: "award-mask " + (showPlaceholder && 'placeholder')
}, React__default["default"].createElement(Image, {
image: props.image,
style: props.imageStyle,
duration: props.duration,
className: "award-image " + transition.status
})), React__default["default"].createElement(CustomChild, {
duration: props.duration,
className: "award-image " + transition.status
}), React__default["default"].createElement(Player, {
lottie: lottie,
play: play,
speed: props.speed,
segments: props.segments,
style: props.playerStyle,
animation: props.animation,
onLoad: function onLoad() {
return setLoaded(true);
},
onComplete: props.onComplete,
className: "award-player " + transition.status
}));
};
Award.defaultProps = {
duration: 2000,
backgroundColor: '#CCCCCC',
showPlaceholder: false
};
return Award;
};
/**
* This React component displays a solid color mask with the silhouette of an image,
* and when triggered, it performs a fade-in effect to reveal the image.
*
* The component also plays a confetti animation.
* The user can specify different images or animation files for the component to display.
*/
var Award = buildAward(lottie__default["default"]);
exports.Award = Award;
//# sourceMappingURL=react-award.js.map