react-lottie-hook
Version:
React Lottie written with react hooks
466 lines (451 loc) • 19.9 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var tslib = require('tslib');
var React = require('react');
var lottie = require('lottie-web');
var ReactDOM = require('react-dom');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
var lottie__default = /*#__PURE__*/_interopDefaultLegacy(lottie);
var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM);
var Lottie = function (props) {
if (!props.lottieRef) {
throw new Error("Lottie component requires a valid ref but got: " + props.lottieRef);
}
var getSize = React.useCallback(function (initial) {
if (initial === void 0) { initial = 200; }
return (typeof initial === "number" ? initial + "px" : initial);
}, []);
var styles = React.useMemo(function () { return (tslib.__assign({ width: getSize(props.width), height: getSize(props.height), overflow: "hidden", margin: "0 auto", outline: "none" }, props.style)); }, [props.style, props.width, props.height, getSize]);
return (React__default['default'].createElement("div", { ref: function (r) {
props.lottieRef.current = r;
}, className: props.className, style: styles, onKeyDown: props.onKeyDown, onClick: props.onClick, title: props.title, role: props.ariaRole, "aria-label": props.ariaLabel, "tab-index": "0" }));
};
var AnimType;
(function (AnimType) {
AnimType[AnimType["svg"] = 0] = "svg";
AnimType[AnimType["canvas"] = 1] = "canvas";
AnimType[AnimType["html"] = 2] = "html";
})(AnimType || (AnimType = {}));
exports.Renderer = void 0;
(function (Renderer) {
Renderer["html"] = "html";
Renderer["svg"] = "svg";
Renderer["canvas"] = "canvas";
})(exports.Renderer || (exports.Renderer = {}));
var array = {
isPopulated: function (item) { return Array.isArray(item) && item.length > 0; }
};
var object = {
isPopulated: function (obj) {
return !!obj && typeof obj === "object" && Object.keys(obj).length > 0;
}
};
var string = {
isEmpty: function (str) { return typeof str === "string" && str.length === 0; },
isPopulated: function (str) { return typeof str === "string" && str.length > 0; }
};
var number = {
is: function (number) { return typeof number === "number"; }
};
var boolean = {
is: function (boolean) {
return typeof boolean === "boolean" || (typeof boolean === "number" && Boolean(boolean));
}
};
var useLottie = function (_a) {
var _b = _a.renderer, renderer = _b === void 0 ? exports.Renderer.svg : _b, _c = _a.loop, loop = _c === void 0 ? true : _c, _d = _a.autoplay, autoplay = _d === void 0 ? true : _d, _e = _a.rendererSettings, rendererSettings = _e === void 0 ? {} : _e, _f = _a.segments, segments = _f === void 0 ? [] : _f, _g = _a.animationData, animationData = _g === void 0 ? {} : _g, _h = _a.eventListeners, eventListeners = _h === void 0 ? {} : _h;
var _j = React.useState(undefined), animation = _j[0], setAnimation = _j[1];
var lottieRef = React__default['default'].useRef(null);
var _k = React.useState(animationData), internalAnimationData = _k[0], setInternalAnimationData = _k[1];
var _l = React.useState({
animType: undefined,
animationID: undefined,
assets: [],
assetsPath: undefined,
autoloadSegments: false,
autoplay: false,
currentFrame: 0,
currentRawFrame: 0,
firstFrame: 0,
frameModifier: 0,
frameMult: 0,
frameRate: 0,
initialSegment: undefined,
isPaused: false,
isLoaded: false,
isSubframeEnabled: false,
loop: undefined,
name: undefined,
path: undefined,
playCount: 0,
playDirection: 1,
playSpeed: 0,
segmentPos: 0,
segments: [],
timeCompleted: 0,
totalFrames: 0,
isStopped: false,
animationData: animationData
}), state = _l[0], dispatch = _l[1];
var hasOwnProperty = React.useCallback(function (anim, prop) { return object.isPopulated(anim) && !!anim[prop]; }, []);
var registerEvents = React.useCallback(function (anim, eventListeners) {
if (!object.isPopulated(eventListeners))
return;
Object.entries(eventListeners).forEach(function (_a) {
var eventName = _a[0], callback = _a[1];
if (hasOwnProperty(anim, "addEventListener") && callback !== undefined) {
anim === null || anim === void 0 ? void 0 : anim.addEventListener(eventName, callback);
}
});
}, [hasOwnProperty]);
var deRegisterEvents = React.useCallback(function (anim, eventListeners) {
if (!object.isPopulated(eventListeners))
return;
Object.entries(eventListeners).forEach(function (_a) {
var eventName = _a[0], callback = _a[1];
if (hasOwnProperty(anim, "removeEventListener")) {
anim === null || anim === void 0 ? void 0 : anim.removeEventListener(eventName, callback);
}
});
}, [hasOwnProperty]);
var animationConfig = React.useCallback(function (container) { return ({
container: container,
renderer: renderer,
loop: loop,
autoplay: autoplay,
rendererSettings: rendererSettings,
animationData: internalAnimationData
}); }, [renderer, loop, autoplay, rendererSettings, internalAnimationData]);
var update = function (update) {
dispatch(function (state) { return (tslib.__assign(tslib.__assign({}, state), update)); });
};
var play = React.useCallback(function () {
if (hasOwnProperty(animation, "play")) {
animation === null || animation === void 0 ? void 0 : animation.play();
update({
isPaused: false,
isStopped: false
});
}
}, [animation, hasOwnProperty]);
var playSegments = React.useCallback(function (newSegments, forceFlag) {
if (forceFlag === void 0) { forceFlag = true; }
if (hasOwnProperty(animation, "playSegments")) {
animation === null || animation === void 0 ? void 0 : animation.playSegments(newSegments || segments, forceFlag);
}
}, [animation, segments, hasOwnProperty]);
var stop = React.useCallback(function () {
if (hasOwnProperty(animation, "stop")) {
animation === null || animation === void 0 ? void 0 : animation.stop();
update({
isStopped: true,
isPaused: true
});
}
}, [animation, hasOwnProperty]);
var pause = React.useCallback(function () {
if (hasOwnProperty(animation, "pause")) {
animation === null || animation === void 0 ? void 0 : animation.pause();
update({ isPaused: true });
}
}, [animation, hasOwnProperty]);
var destroy = React.useCallback(function () {
if (hasOwnProperty(animation, "destroy")) {
animation === null || animation === void 0 ? void 0 : animation.destroy();
}
}, [animation, hasOwnProperty]);
var setDirection = React.useCallback(function (direction) {
if (direction === void 0) { direction = 1; }
if (hasOwnProperty(animation, "setDirection")) {
animation === null || animation === void 0 ? void 0 : animation.setDirection(direction);
update({ playDirection: direction });
}
}, [animation, hasOwnProperty]);
var selectAnimation = React.useCallback(function (newAnimation) {
if (object.isPopulated(animation) && object.isPopulated(newAnimation)) {
update({
isStopped: false,
isPaused: false,
animationData: newAnimation
});
}
}, [animation]);
var setSpeed = React.useCallback(function (speed) {
if (hasOwnProperty(animation, "setSpeed")) {
animation === null || animation === void 0 ? void 0 : animation.setSpeed(speed);
update({ playSpeed: speed });
}
}, [animation, hasOwnProperty]);
var resize = React.useCallback(function () {
if (hasOwnProperty(animation, "resize")) {
animation === null || animation === void 0 ? void 0 : animation.resize();
}
}, [animation, hasOwnProperty]);
var goToAndPlay = React.useCallback(function (value, isFrame) {
if (hasOwnProperty(animation, "goToAndPlay")) {
if (state.totalFrames && value > state.totalFrames) {
console.error("[goToAndPlay]: provided value " + value + " exceeds animation total frames which is " + state.totalFrames);
}
animation === null || animation === void 0 ? void 0 : animation.goToAndPlay(value, isFrame);
}
}, [animation, hasOwnProperty, state.totalFrames]);
var goToAndStop = React.useCallback(function (value, isFrame) {
if (hasOwnProperty(animation, "goToAndStop")) {
if (state.totalFrames && value > state.totalFrames) {
console.error("[goToAndStop]: provided value " + value + " exceeds animation total frames which is " + state.totalFrames);
}
animation === null || animation === void 0 ? void 0 : animation.goToAndStop(value, isFrame);
}
}, [animation, hasOwnProperty, state.totalFrames]);
var setSubframe = React.useCallback(function (useSubFrames) {
if (hasOwnProperty(animation, "setSubframe")) {
animation === null || animation === void 0 ? void 0 : animation.setSubframe(useSubFrames);
}
}, [animation, hasOwnProperty]);
var getDuration = React.useCallback(function (inFrames) {
if (hasOwnProperty(animation, "getDuration")) {
return animation === null || animation === void 0 ? void 0 : animation.getDuration(inFrames);
}
return 0;
}, [animation, hasOwnProperty]);
var controls = React.useMemo(function () { return ({
play: play,
stop: stop,
pause: pause,
resize: resize,
destroy: destroy,
setSpeed: setSpeed,
getDuration: getDuration,
setSubframe: setSubframe,
goToAndPlay: goToAndPlay,
goToAndStop: goToAndStop,
playSegments: playSegments,
setDirection: setDirection,
selectAnimation: selectAnimation
}); }, [
play,
stop,
pause,
resize,
destroy,
setSpeed,
getDuration,
setSubframe,
goToAndPlay,
goToAndStop,
setDirection,
playSegments,
selectAnimation,
]);
var filterLottieState = React.useCallback(function (anim) {
var updates = {};
if (string.isPopulated(anim.name))
updates.name = anim.name;
if (string.isPopulated(anim.path))
updates.path = anim.path;
if (array.isPopulated(anim.assets))
updates.assets = anim.assets;
if (string.isPopulated(anim.animType))
updates.animType = anim.animType;
if (string.isPopulated(anim.assetsPath))
updates.assetsPath = anim.assetsPath;
if (string.isPopulated(anim.animationID))
updates.animationID = anim.animationID;
if (number.is(anim.frameMult))
updates.frameMult = anim.frameMult;
if (number.is(anim.frameRate))
updates.frameRate = anim.frameRate;
if (number.is(anim.playCount))
updates.playCount = anim.playCount;
if (number.is(anim.playSpeed))
updates.playSpeed = anim.playSpeed;
if (number.is(anim.firstFrame))
updates.firstFrame = anim.firstFrame;
if (number.is(anim.segmentPos))
updates.segmentPos = anim.segmentPos;
if (number.is(anim.totalFrames))
updates.totalFrames = anim.totalFrames;
if (number.is(anim.currentFrame))
updates.currentFrame = anim.currentFrame;
if (number.is(anim.timeCompleted))
updates.timeCompleted = anim.timeCompleted;
if (number.is(anim.frameModifier))
updates.frameModifier = anim.frameModifier;
if (number.is(anim.playDirection))
updates.playDirection = anim.playDirection;
if (number.is(anim.initialSegment))
updates.initialSegment = anim.initialSegment;
if (number.is(anim.currentRawFrame))
updates.currentRawFrame = anim.currentRawFrame;
if (boolean.is(anim.autoloadSegments))
updates.autoloadSegments = anim.autoloadSegments;
if (boolean.is(anim.isSubframeEnabled))
updates.isSubframeEnabled = anim.isSubframeEnabled;
if (boolean.is(anim.isLoaded))
updates.isLoaded = anim.isLoaded;
if (boolean.is(anim.isPaused))
updates.isPaused = anim.isPaused;
if (boolean.is(anim.autoplay))
updates.autoplay = anim.autoplay;
if (boolean.is(anim.loop))
updates.loop = anim.loop;
if (array.isPopulated(anim.segments))
updates.segments = anim.segments;
updates.isStopped = state.isStopped;
return updates;
}, [state.isStopped]);
React.useEffect(function () {
var anim = lottie__default['default'].loadAnimation(animationConfig(lottieRef.current));
registerEvents(anim, eventListeners);
var updates = filterLottieState(anim);
update(updates);
setAnimation(anim);
return function () {
if (hasOwnProperty(animation, "destroy"))
animation === null || animation === void 0 ? void 0 : animation.destroy();
deRegisterEvents(animation, eventListeners);
controls.destroy();
setAnimation(undefined);
update({ animationData: {} });
};
}, []);
React.useEffect(function () {
if (internalAnimationData !== state.animationData) {
deRegisterEvents(animation, eventListeners);
controls.destroy();
var newOptions = tslib.__assign(tslib.__assign({}, animationConfig(lottieRef.current)), { renderer: renderer, loop: loop, autoplay: autoplay, rendererSettings: rendererSettings, animationData: state.animationData });
var anim = lottie__default['default'].loadAnimation(newOptions);
registerEvents(anim, eventListeners);
setInternalAnimationData(state.animationData);
setAnimation(anim);
var updates = filterLottieState(anim);
update(updates);
}
}, [
animation,
internalAnimationData,
state.animationData,
eventListeners,
rendererSettings,
deRegisterEvents,
animationConfig,
registerEvents,
filterLottieState,
autoplay,
renderer,
controls,
state,
loop,
]);
var lottieState = filterLottieState(state);
return [lottieRef, lottieState, controls];
};
function ownerDocument(node) {
return (node && node.ownerDocument) || document;
}
var setRef = function (ref, value) {
if (typeof ref === "function") {
ref(value);
}
else if (ref) {
ref.current = value;
}
};
var useForkRef = function (refA, refB) {
return React__default['default'].useMemo(function () {
if (refA == null && refB == null) {
return null;
}
return function (refValue) {
setRef(refA, refValue);
setRef(refB, refValue);
};
}, [refA, refB]);
};
var useEnhancedEffect = typeof window !== "undefined" ? React__default['default'].useLayoutEffect : React__default['default'].useEffect;
function useEventCallback(fn) {
var ref = React__default['default'].useRef(fn);
useEnhancedEffect(function () {
ref.current = fn;
});
return React__default['default'].useCallback(function (event) { return (0, ref.current)(event); }, []);
}
function mapEventPropToEvent(eventProp) {
return eventProp.substring(2).toLowerCase();
}
var ClickAway = React__default['default'].forwardRef(function (props, ref) {
var style = props.style, className = props.className, onClickAway = props.onClickAway, _a = props.mouseEvent, mouseEvent = _a === void 0 ? "onClick" : _a, _b = props.touchEvent, touchEvent = _b === void 0 ? "onTouchEnd" : _b, _c = props.onClickIn, onClickIn = _c === void 0 ? function () { return void 0; } : _c, children = props.children;
var _d = React__default['default'].useState(false), clicked = _d[0], setClicked = _d[1];
var movedRef = React__default['default'].useRef(false);
var nodeRef = React__default['default'].useRef(null);
var mountedRef = React__default['default'].useRef(false);
React__default['default'].useEffect(function () {
mountedRef.current = true;
return function () {
mountedRef.current = false;
};
}, []);
var handleNodeRef = useForkRef(nodeRef, ref);
var handleOwnRef = React__default['default'].useCallback(function (instance) {
setRef(handleNodeRef, ReactDOM__default['default'].findDOMNode(instance));
}, [handleNodeRef]);
var handleRef = useForkRef(children.ref, handleOwnRef);
var handleClickIn = React__default['default'].useCallback(function () {
setClicked(function (state) { return !state; });
onClickIn();
}, [onClickIn]);
var handleClickAway = useEventCallback(function (event) {
if (!mountedRef.current) {
return;
}
if (movedRef.current) {
movedRef.current = false;
return;
}
if (!nodeRef.current)
return;
var doc = ownerDocument(nodeRef.current);
if (doc.documentElement &&
doc.documentElement.contains(event.target) &&
!nodeRef.current.contains(event.target)) {
if (clicked) {
setClicked(false);
onClickAway(event);
}
}
});
var handleTouchMove = React__default['default'].useCallback(function () {
movedRef.current = true;
}, []);
React__default['default'].useEffect(function () {
if (touchEvent !== false) {
var mappedTouchEvent_1 = mapEventPropToEvent(touchEvent);
var doc_1 = ownerDocument(nodeRef.current);
doc_1.addEventListener(mappedTouchEvent_1, handleClickAway);
doc_1.addEventListener("touchmove", handleTouchMove);
return function () {
doc_1.removeEventListener(mappedTouchEvent_1, handleClickAway);
doc_1.removeEventListener("touchmove", handleTouchMove);
};
}
return undefined;
}, [handleClickAway, handleTouchMove, touchEvent]);
React__default['default'].useEffect(function () {
if (mouseEvent !== false) {
var mappedMouseEvent_1 = mapEventPropToEvent(mouseEvent);
var doc_2 = ownerDocument(nodeRef.current);
doc_2.addEventListener(mappedMouseEvent_1, handleClickAway);
return function () {
doc_2.removeEventListener(mappedMouseEvent_1, handleClickAway);
};
}
return undefined;
}, [handleClickAway, mouseEvent]);
var Wrapper = (React__default['default'].createElement("div", { role: "presentation", onClick: handleClickIn, style: style, className: className }, children));
return React__default['default'].createElement(React__default['default'].Fragment, null, React__default['default'].cloneElement(Wrapper, { ref: handleRef }));
});
exports.ClickAway = ClickAway;
exports.Lottie = Lottie;
exports.useLottie = useLottie;
//# sourceMappingURL=index.cjs.js.map