UNPKG

react-lottie-hook

Version:
466 lines (451 loc) 19.9 kB
'use strict'; 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