@depup/lottie-react 2.4.1-depup.0 → 3.0.0-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +9 -0
- package/README.md +4 -10
- package/build/_virtual/_rolldown/runtime.cjs +23 -0
- package/build/animation/Lottie.cjs +39 -0
- package/build/animation/Lottie.d.cts +47 -0
- package/build/animation/Lottie.d.ts +47 -0
- package/build/animation/Lottie.js +37 -0
- package/build/animation/LottieDisplay.cjs +55 -0
- package/build/animation/LottieDisplay.d.cts +46 -0
- package/build/animation/LottieDisplay.d.ts +46 -0
- package/build/animation/LottieDisplay.js +53 -0
- package/build/animation/LottieInstanceContext.cjs +16 -0
- package/build/animation/LottieInstanceContext.js +17 -0
- package/build/animation/LottieLight.cjs +19 -0
- package/build/animation/LottieLight.d.cts +23 -0
- package/build/animation/LottieLight.d.ts +23 -0
- package/build/animation/LottieLight.js +17 -0
- package/build/animation/LottieRegistryContext.cjs +36 -0
- package/build/animation/LottieRegistryContext.js +35 -0
- package/build/animation/LottieSvg.cjs +20 -0
- package/build/animation/LottieSvg.d.cts +24 -0
- package/build/animation/LottieSvg.d.ts +24 -0
- package/build/animation/LottieSvg.js +18 -0
- package/build/animation/collectMarkerCrossings.cjs +38 -0
- package/build/animation/collectMarkerCrossings.js +38 -0
- package/build/animation/createLottieComponent.cjs +131 -0
- package/build/animation/createLottieComponent.d.cts +45 -0
- package/build/animation/createLottieComponent.d.ts +45 -0
- package/build/animation/createLottieComponent.js +131 -0
- package/build/animation/hasExpressions.cjs +25 -0
- package/build/animation/hasExpressions.js +25 -0
- package/build/animation/normalizeAnimationSource.cjs +38 -0
- package/build/animation/normalizeAnimationSource.js +38 -0
- package/build/animation/polymorphicForwardRef.cjs +18 -0
- package/build/animation/polymorphicForwardRef.js +19 -0
- package/build/animation/renderStyledElement.cjs +31 -0
- package/build/animation/renderStyledElement.js +31 -0
- package/build/animation/resolveSeekTarget.cjs +97 -0
- package/build/animation/resolveSeekTarget.js +95 -0
- package/build/animation/styleLayer.cjs +24 -0
- package/build/animation/styleLayer.js +24 -0
- package/build/animation/stylePrecedence.cjs +12 -0
- package/build/animation/stylePrecedence.js +12 -0
- package/build/animation/types.cjs +71 -0
- package/build/animation/types.d.cts +461 -0
- package/build/animation/types.d.ts +461 -0
- package/build/animation/types.js +68 -0
- package/build/animation/useLottie.cjs +40 -0
- package/build/animation/useLottie.d.cts +36 -0
- package/build/animation/useLottie.d.ts +36 -0
- package/build/animation/useLottie.js +38 -0
- package/build/animation/useLottieAnimation.cjs +434 -0
- package/build/animation/useLottieAnimation.d.cts +40 -0
- package/build/animation/useLottieAnimation.d.ts +40 -0
- package/build/animation/useLottieAnimation.js +434 -0
- package/build/animation/useLottieInstance.cjs +20 -0
- package/build/animation/useLottieInstance.d.cts +14 -0
- package/build/animation/useLottieInstance.d.ts +14 -0
- package/build/animation/useLottieInstance.js +20 -0
- package/build/animation/useLottieLight.cjs +20 -0
- package/build/animation/useLottieLight.d.cts +16 -0
- package/build/animation/useLottieLight.d.ts +16 -0
- package/build/animation/useLottieLight.js +18 -0
- package/build/animation/useLottieSvg.cjs +18 -0
- package/build/animation/useLottieSvg.d.cts +14 -0
- package/build/animation/useLottieSvg.d.ts +14 -0
- package/build/animation/useLottieSvg.js +16 -0
- package/build/controls/LottieControls.cjs +180 -0
- package/build/controls/LottieControls.d.cts +58 -0
- package/build/controls/LottieControls.d.ts +58 -0
- package/build/controls/LottieControls.js +178 -0
- package/build/controls/LottieDirectionButton.cjs +36 -0
- package/build/controls/LottieDirectionButton.js +35 -0
- package/build/controls/LottieFullscreenButton.cjs +35 -0
- package/build/controls/LottieFullscreenButton.js +34 -0
- package/build/controls/LottieLoopButton.cjs +32 -0
- package/build/controls/LottieLoopButton.js +31 -0
- package/build/controls/LottiePlayButton.cjs +34 -0
- package/build/controls/LottiePlayButton.js +33 -0
- package/build/controls/LottieReadout.cjs +61 -0
- package/build/controls/LottieReadout.d.cts +13 -0
- package/build/controls/LottieReadout.d.ts +13 -0
- package/build/controls/LottieReadout.js +60 -0
- package/build/controls/LottieSeekBar.cjs +87 -0
- package/build/controls/LottieSeekBar.js +86 -0
- package/build/controls/LottieSpeedSelect.cjs +51 -0
- package/build/controls/LottieSpeedSelect.js +50 -0
- package/build/controls/LottieStopButton.cjs +29 -0
- package/build/controls/LottieStopButton.js +28 -0
- package/build/controls/controlIcon.cjs +25 -0
- package/build/controls/controlIcon.js +25 -0
- package/build/controls/useFullscreen.cjs +46 -0
- package/build/controls/useFullscreen.js +46 -0
- package/build/controls/useShortcuts.cjs +70 -0
- package/build/controls/useShortcuts.js +70 -0
- package/build/index.cjs +36 -0
- package/build/index.d.cts +19 -0
- package/build/index.d.ts +19 -80
- package/build/index.js +17 -667
- package/build/interactions/LottieInteractions.cjs +41 -0
- package/build/interactions/LottieInteractions.d.cts +37 -0
- package/build/interactions/LottieInteractions.d.ts +37 -0
- package/build/interactions/LottieInteractions.js +41 -0
- package/build/interactions/coverProgress.cjs +55 -0
- package/build/interactions/coverProgress.js +53 -0
- package/build/interactions/lottieInView.cjs +109 -0
- package/build/interactions/lottieInView.d.cts +44 -0
- package/build/interactions/lottieInView.d.ts +44 -0
- package/build/interactions/lottieInView.js +109 -0
- package/build/interactions/lottieScrollScrub.cjs +152 -0
- package/build/interactions/lottieScrollScrub.d.cts +47 -0
- package/build/interactions/lottieScrollScrub.d.ts +47 -0
- package/build/interactions/lottieScrollScrub.js +152 -0
- package/build/interactions/types.d.cts +46 -0
- package/build/interactions/types.d.ts +46 -0
- package/build/interactions/useInteractionsRunner.cjs +142 -0
- package/build/interactions/useInteractionsRunner.js +141 -0
- package/build/interactions/useLottieInteractions.cjs +21 -0
- package/build/interactions/useLottieInteractions.d.cts +19 -0
- package/build/interactions/useLottieInteractions.d.ts +19 -0
- package/build/interactions/useLottieInteractions.js +21 -0
- package/build/overlays/LottieError.cjs +74 -0
- package/build/overlays/LottieError.d.cts +40 -0
- package/build/overlays/LottieError.d.ts +40 -0
- package/build/overlays/LottieError.js +72 -0
- package/build/overlays/LottieLoading.cjs +89 -0
- package/build/overlays/LottieLoading.d.cts +45 -0
- package/build/overlays/LottieLoading.d.ts +45 -0
- package/build/overlays/LottieLoading.js +87 -0
- package/build/overlays/overlayStyles.cjs +33 -0
- package/build/overlays/overlayStyles.js +33 -0
- package/build/utils/SubscriptionManager.cjs +42 -0
- package/build/utils/SubscriptionManager.d.cts +30 -0
- package/build/utils/SubscriptionManager.d.ts +30 -0
- package/build/utils/SubscriptionManager.js +42 -0
- package/build/utils/createLogger.cjs +25 -0
- package/build/utils/createLogger.js +25 -0
- package/build/utils/isSameJson.cjs +37 -0
- package/build/utils/isSameJson.js +37 -0
- package/build/utils/mergeRefs.cjs +37 -0
- package/build/utils/mergeRefs.js +37 -0
- package/build/utils/useStableValue.cjs +26 -0
- package/build/utils/useStableValue.js +26 -0
- package/changes.json +3 -8
- package/package.json +144 -89
- package/LICENSE +0 -46
- package/build/index.es.js +0 -653
- package/build/index.es.js.map +0 -1
- package/build/index.es.min.js +0 -3
- package/build/index.js.map +0 -1
- package/build/index.min.js +0 -3
- package/build/index.umd.js +0 -670
- package/build/index.umd.js.map +0 -1
- package/build/index.umd.min.js +0 -3
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
const require_createLogger = require("../utils/createLogger.cjs");
|
|
2
|
+
const require_SubscriptionManager = require("../utils/SubscriptionManager.cjs");
|
|
3
|
+
const require_useStableValue = require("../utils/useStableValue.cjs");
|
|
4
|
+
const require_collectMarkerCrossings = require("./collectMarkerCrossings.cjs");
|
|
5
|
+
const require_hasExpressions = require("./hasExpressions.cjs");
|
|
6
|
+
const require_LottieRegistryContext = require("./LottieRegistryContext.cjs");
|
|
7
|
+
const require_normalizeAnimationSource = require("./normalizeAnimationSource.cjs");
|
|
8
|
+
const require_resolveSeekTarget = require("./resolveSeekTarget.cjs");
|
|
9
|
+
const require_types = require("./types.cjs");
|
|
10
|
+
let react = require("react");
|
|
11
|
+
//#region src/animation/useLottieAnimation.ts
|
|
12
|
+
/** Nothing guarantees a thrown value is an `Error`, and a reason has to be one. */
|
|
13
|
+
function toError(cause) {
|
|
14
|
+
return cause instanceof Error ? cause : new Error(String(cause));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Everything the animation does, with no opinion about how it is rendered.
|
|
18
|
+
*
|
|
19
|
+
* It takes the engine as an argument so the same logic serves every build.
|
|
20
|
+
* Reach it through `useLottie`, `useLottieSvg` or `useLottieLight` rather than
|
|
21
|
+
* directly.
|
|
22
|
+
*/
|
|
23
|
+
function useLottieAnimation(lottie, options) {
|
|
24
|
+
const { src, renderer, rendererSettings, loop, speed, direction, autoplay = false, segment, assetsPath, debug = false, subscriptions } = options;
|
|
25
|
+
const [manager] = (0, react.useState)(() => new require_SubscriptionManager.SubscriptionManager());
|
|
26
|
+
const [display, setDisplay] = (0, react.useState)(null);
|
|
27
|
+
const setDisplayRef = (0, react.useCallback)((node) => {
|
|
28
|
+
setDisplay(node);
|
|
29
|
+
}, []);
|
|
30
|
+
const [root, setRoot] = (0, react.useState)(null);
|
|
31
|
+
const setRootRef = (0, react.useCallback)((node) => {
|
|
32
|
+
setRoot(node);
|
|
33
|
+
}, []);
|
|
34
|
+
const [animationItem, setAnimationItem] = (0, react.useState)(null);
|
|
35
|
+
const [state, setState] = (0, react.useState)(require_types.LottieState.loading);
|
|
36
|
+
const [error, setError] = (0, react.useState)(null);
|
|
37
|
+
const [loadAttempt, setLoadAttempt] = (0, react.useState)(1);
|
|
38
|
+
const reload = (0, react.useCallback)(() => {
|
|
39
|
+
setLoadAttempt((previous) => previous + 1);
|
|
40
|
+
}, []);
|
|
41
|
+
const [playableFrames, setPlayableFrames] = (0, react.useState)(0);
|
|
42
|
+
const [playableDuration, setPlayableDuration] = (0, react.useState)(0);
|
|
43
|
+
const [speedValue, setSpeedValue] = (0, react.useState)(speed ?? 1);
|
|
44
|
+
const [directionValue, setDirectionValue] = (0, react.useState)(direction ?? require_types.LottieDirection.forward);
|
|
45
|
+
const [loopValue, setLoopValue] = (0, react.useState)(loop ?? false);
|
|
46
|
+
const source = require_useStableValue.useStableValue(src);
|
|
47
|
+
const loadConfig = require_useStableValue.useStableValue({
|
|
48
|
+
renderer,
|
|
49
|
+
rendererSettings,
|
|
50
|
+
autoplay,
|
|
51
|
+
segment,
|
|
52
|
+
assetsPath
|
|
53
|
+
});
|
|
54
|
+
const itemRef = (0, react.useRef)(null);
|
|
55
|
+
const valuesRef = (0, react.useRef)({
|
|
56
|
+
speed: speedValue,
|
|
57
|
+
direction: directionValue,
|
|
58
|
+
loop: loopValue
|
|
59
|
+
});
|
|
60
|
+
valuesRef.current.speed = speedValue;
|
|
61
|
+
valuesRef.current.direction = directionValue;
|
|
62
|
+
valuesRef.current.loop = loopValue;
|
|
63
|
+
const stateRef = (0, react.useRef)(state);
|
|
64
|
+
stateRef.current = state;
|
|
65
|
+
const debugRef = (0, react.useRef)(debug);
|
|
66
|
+
debugRef.current = debug;
|
|
67
|
+
const subscriptionsRef = (0, react.useRef)(subscriptions);
|
|
68
|
+
subscriptionsRef.current = subscriptions;
|
|
69
|
+
const driversRef = (0, react.useRef)({});
|
|
70
|
+
const scrubbedFrom = (0, react.useRef)(null);
|
|
71
|
+
const markerMemory = (0, react.useRef)(null);
|
|
72
|
+
/**
|
|
73
|
+
* Warns once per field when a value is driven from a prop and from a setter.
|
|
74
|
+
*
|
|
75
|
+
* Both keep working, per field and last writer wins, but they will disagree
|
|
76
|
+
* the next time the prop changes, and that is worth saying out loud while
|
|
77
|
+
* someone is building rather than leaving them to find it.
|
|
78
|
+
*/
|
|
79
|
+
const noteDriver = (0, react.useCallback)((field, driver) => {
|
|
80
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
|
|
81
|
+
const previous = driversRef.current[field];
|
|
82
|
+
if (previous === void 0) driversRef.current[field] = driver;
|
|
83
|
+
else if (previous !== driver && previous !== "both") {
|
|
84
|
+
driversRef.current[field] = "both";
|
|
85
|
+
console.warn(`[lottie-react] "${field}" is driven from both the ${field} prop and a setter. Both keep working and the last one to write wins, but they will disagree the next time the prop changes. Drive it from one place.`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}, []);
|
|
89
|
+
const applySpeed = (0, react.useCallback)((next, driver) => {
|
|
90
|
+
noteDriver("speed", driver);
|
|
91
|
+
setSpeedValue(next);
|
|
92
|
+
itemRef.current?.setSpeed(next);
|
|
93
|
+
}, [noteDriver]);
|
|
94
|
+
const applyDirection = (0, react.useCallback)((next, driver) => {
|
|
95
|
+
noteDriver("direction", driver);
|
|
96
|
+
setDirectionValue(next);
|
|
97
|
+
itemRef.current?.setDirection(next === require_types.LottieDirection.forward ? 1 : -1);
|
|
98
|
+
}, [noteDriver]);
|
|
99
|
+
const applyLoop = (0, react.useCallback)((next, driver) => {
|
|
100
|
+
noteDriver("loop", driver);
|
|
101
|
+
setLoopValue(next);
|
|
102
|
+
const item = itemRef.current;
|
|
103
|
+
if (item) {
|
|
104
|
+
item.playCount = item.playDirection < 0 && typeof next === "number" ? next : 0;
|
|
105
|
+
item.loop = next;
|
|
106
|
+
}
|
|
107
|
+
}, [noteDriver]);
|
|
108
|
+
const setSpeed = (0, react.useCallback)((next) => {
|
|
109
|
+
applySpeed(typeof next === "function" ? next(valuesRef.current.speed) : next, "setter");
|
|
110
|
+
}, [applySpeed]);
|
|
111
|
+
const setDirection = (0, react.useCallback)((next) => {
|
|
112
|
+
applyDirection(typeof next === "function" ? next(valuesRef.current.direction) : next, "setter");
|
|
113
|
+
}, [applyDirection]);
|
|
114
|
+
const setLoop = (0, react.useCallback)((next) => {
|
|
115
|
+
applyLoop(typeof next === "function" ? next(valuesRef.current.loop) : next, "setter");
|
|
116
|
+
}, [applyLoop]);
|
|
117
|
+
/**
|
|
118
|
+
* Plays from wherever the animation is, or from the beginning if it is
|
|
119
|
+
* sitting at the end it plays towards.
|
|
120
|
+
*
|
|
121
|
+
* The restart is not a convenience. Playing forwards from the final frame
|
|
122
|
+
* does nothing, and playing in reverse from frame 0 does nothing either: the
|
|
123
|
+
* engine decides it has already finished, pauses, and reports completion
|
|
124
|
+
* without advancing. Both are the same fault seen from either end.
|
|
125
|
+
*/
|
|
126
|
+
const play = (0, react.useCallback)(() => {
|
|
127
|
+
const item = itemRef.current;
|
|
128
|
+
if (item === null) return;
|
|
129
|
+
const reverse = item.playDirection < 0;
|
|
130
|
+
const finished = reverse ? item.currentFrame <= 0 : item.currentFrame >= item.totalFrames - 1;
|
|
131
|
+
const numericLoop = typeof item.loop === "number" ? item.loop : null;
|
|
132
|
+
const exhausted = numericLoop !== null && (reverse ? item.playCount < 0 : item.playCount >= numericLoop);
|
|
133
|
+
if (finished || exhausted) item.playCount = reverse && numericLoop !== null ? numericLoop : 0;
|
|
134
|
+
if (finished) {
|
|
135
|
+
markerMemory.current = null;
|
|
136
|
+
item.goToAndPlay(reverse ? item.totalFrames : 0, true);
|
|
137
|
+
} else item.play();
|
|
138
|
+
setState(require_types.LottieState.playing);
|
|
139
|
+
}, []);
|
|
140
|
+
const pause = (0, react.useCallback)(() => {
|
|
141
|
+
const item = itemRef.current;
|
|
142
|
+
if (item === null) return;
|
|
143
|
+
item.pause();
|
|
144
|
+
setState(require_types.LottieState.paused);
|
|
145
|
+
}, []);
|
|
146
|
+
const stop = (0, react.useCallback)(() => {
|
|
147
|
+
const item = itemRef.current;
|
|
148
|
+
if (item === null) return;
|
|
149
|
+
markerMemory.current = null;
|
|
150
|
+
item.playCount = 0;
|
|
151
|
+
item.goToAndStop(0, true);
|
|
152
|
+
setState(require_types.LottieState.stopped);
|
|
153
|
+
}, []);
|
|
154
|
+
/**
|
|
155
|
+
* Reads the playable range, and how it is being played, back off the engine.
|
|
156
|
+
*
|
|
157
|
+
* A segment rewrites `firstFrame` and `totalFrames`, so the two values we
|
|
158
|
+
* report about length have to follow it or a progress bar keeps measuring
|
|
159
|
+
* whatever was playable before. It settles direction and speed as well: a
|
|
160
|
+
* range whose end precedes its start plays backwards, a forward range played
|
|
161
|
+
* while reversed turns the animation around, and a forward range at a
|
|
162
|
+
* negative speed flips the speed instead. Reporting what was asked for rather
|
|
163
|
+
* than what happened would make each of those a quiet lie.
|
|
164
|
+
*/
|
|
165
|
+
const refreshRange = (0, react.useCallback)((item) => {
|
|
166
|
+
setPlayableFrames(item.totalFrames);
|
|
167
|
+
setPlayableDuration(item.getDuration(false));
|
|
168
|
+
setDirectionValue(item.playDirection < 0 ? require_types.LottieDirection.reverse : require_types.LottieDirection.forward);
|
|
169
|
+
setSpeedValue(item.playSpeed);
|
|
170
|
+
}, []);
|
|
171
|
+
/**
|
|
172
|
+
* Resolves a seek target, and says so in development when it cannot.
|
|
173
|
+
*
|
|
174
|
+
* Shared by `seek` and `scrubTo` so both report the same way. The message is
|
|
175
|
+
* built inside the guard rather than passed in, because an argument built at
|
|
176
|
+
* a call site survives as a discarded expression even once the branch that
|
|
177
|
+
* used it has gone.
|
|
178
|
+
*/
|
|
179
|
+
const resolveOrWarn = (0, react.useCallback)((item, target) => {
|
|
180
|
+
const resolved = require_resolveSeekTarget.resolveSeekTarget(item, target);
|
|
181
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
|
|
182
|
+
if (resolved === null) console.warn(`[lottie-react] the seek target ${JSON.stringify(target)} could not be resolved, so nothing moved. A marker name has to match one the animation carries, and every other unit has to be a finite number.`);
|
|
183
|
+
else if (resolved.frame !== resolved.requested && typeof target === "object" && target.marker !== void 0) console.warn(`[lottie-react] the marker "${target.marker}" lies outside the playable range, so the seek was held at frame ${resolved.frame}. Markers are placed against the whole animation, while seeking is relative to whatever a segment has left playable.`);
|
|
184
|
+
}
|
|
185
|
+
return resolved === null ? null : resolved.frame;
|
|
186
|
+
}, []);
|
|
187
|
+
const seek = (0, react.useCallback)((target) => {
|
|
188
|
+
const item = itemRef.current;
|
|
189
|
+
if (item === null) return;
|
|
190
|
+
const frame = resolveOrWarn(item, target);
|
|
191
|
+
if (frame === null) return;
|
|
192
|
+
markerMemory.current = null;
|
|
193
|
+
if (item.isPaused) item.goToAndStop(frame, true);
|
|
194
|
+
else item.goToAndPlay(frame, true);
|
|
195
|
+
}, [resolveOrWarn]);
|
|
196
|
+
const scrubStart = (0, react.useCallback)(() => {
|
|
197
|
+
const item = itemRef.current;
|
|
198
|
+
if (item === null) return;
|
|
199
|
+
scrubbedFrom.current = stateRef.current;
|
|
200
|
+
item.pause();
|
|
201
|
+
setState(require_types.LottieState.paused);
|
|
202
|
+
}, []);
|
|
203
|
+
const scrubTo = (0, react.useCallback)((frame) => {
|
|
204
|
+
const item = itemRef.current;
|
|
205
|
+
if (item === null) return;
|
|
206
|
+
const resolved = resolveOrWarn(item, frame);
|
|
207
|
+
if (resolved === null) return;
|
|
208
|
+
markerMemory.current = null;
|
|
209
|
+
item.goToAndStop(resolved, true);
|
|
210
|
+
setState(require_types.LottieState.paused);
|
|
211
|
+
}, [resolveOrWarn]);
|
|
212
|
+
const scrubEnd = (0, react.useCallback)(() => {
|
|
213
|
+
if (itemRef.current === null) return;
|
|
214
|
+
const before = scrubbedFrom.current;
|
|
215
|
+
scrubbedFrom.current = null;
|
|
216
|
+
if (before === require_types.LottieState.playing) play();
|
|
217
|
+
}, [play]);
|
|
218
|
+
const playSegments = (0, react.useCallback)((segments, options) => {
|
|
219
|
+
const item = itemRef.current;
|
|
220
|
+
if (item === null) return;
|
|
221
|
+
const ranges = require_resolveSeekTarget.resolveSegments(item, segments);
|
|
222
|
+
if (ranges === null) {
|
|
223
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") console.warn(`[lottie-react] playSegments could not use ${JSON.stringify(segments)}, so nothing changed. A range is two different finite frame numbers, and a marker has to carry a duration. A marker without one labels a position rather than a span: seek to it and play instead.`);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
item.playSegments(ranges, options?.queue !== true || item.isPaused);
|
|
227
|
+
setState(require_types.LottieState.playing);
|
|
228
|
+
}, []);
|
|
229
|
+
const resetSegments = (0, react.useCallback)(() => {
|
|
230
|
+
const item = itemRef.current;
|
|
231
|
+
if (item === null) return;
|
|
232
|
+
const wasPlaying = !item.isPaused;
|
|
233
|
+
const { segment } = loadConfig;
|
|
234
|
+
if (segment === void 0) item.resetSegments(true);
|
|
235
|
+
else item.playSegments([[segment[0], segment[1]]], true);
|
|
236
|
+
if (!wasPlaying) item.pause();
|
|
237
|
+
}, [loadConfig]);
|
|
238
|
+
(0, react.useEffect)(() => {
|
|
239
|
+
const unsubscribers = [
|
|
240
|
+
manager.subscribe(require_types.LottieSubscription.ready, () => subscriptionsRef.current?.ready?.()),
|
|
241
|
+
manager.subscribe(require_types.LottieSubscription.play, () => subscriptionsRef.current?.play?.()),
|
|
242
|
+
manager.subscribe(require_types.LottieSubscription.pause, () => subscriptionsRef.current?.pause?.()),
|
|
243
|
+
manager.subscribe(require_types.LottieSubscription.stop, () => subscriptionsRef.current?.stop?.()),
|
|
244
|
+
manager.subscribe(require_types.LottieSubscription.complete, () => subscriptionsRef.current?.complete?.()),
|
|
245
|
+
manager.subscribe(require_types.LottieSubscription.loopCompleted, () => subscriptionsRef.current?.loopCompleted?.()),
|
|
246
|
+
manager.subscribe(require_types.LottieSubscription.frame, (event) => subscriptionsRef.current?.frame?.(event)),
|
|
247
|
+
manager.subscribe(require_types.LottieSubscription.marker, (event) => subscriptionsRef.current?.marker?.(event)),
|
|
248
|
+
manager.subscribe(require_types.LottieSubscription.newState, (event) => subscriptionsRef.current?.newState?.(event)),
|
|
249
|
+
manager.subscribe(require_types.LottieSubscription.error, (event) => subscriptionsRef.current?.error?.(event))
|
|
250
|
+
];
|
|
251
|
+
return () => {
|
|
252
|
+
for (const unsubscribe of unsubscribers) unsubscribe();
|
|
253
|
+
};
|
|
254
|
+
}, [manager]);
|
|
255
|
+
const notifiedState = (0, react.useRef)(state);
|
|
256
|
+
(0, react.useEffect)(() => {
|
|
257
|
+
const previous = notifiedState.current;
|
|
258
|
+
if (previous === state) return;
|
|
259
|
+
notifiedState.current = state;
|
|
260
|
+
manager.notify(require_types.LottieSubscription.newState, { state });
|
|
261
|
+
if (state === require_types.LottieState.playing) manager.notify(require_types.LottieSubscription.play);
|
|
262
|
+
else if (state === require_types.LottieState.paused) manager.notify(require_types.LottieSubscription.pause);
|
|
263
|
+
else if (state === require_types.LottieState.stopped && previous !== require_types.LottieState.loading) manager.notify(require_types.LottieSubscription.stop);
|
|
264
|
+
}, [state, manager]);
|
|
265
|
+
(0, react.useEffect)(() => {
|
|
266
|
+
if (display === null) return;
|
|
267
|
+
const logger = require_createLogger.createLogger(debugRef.current);
|
|
268
|
+
setState(require_types.LottieState.loading);
|
|
269
|
+
setError(null);
|
|
270
|
+
markerMemory.current = null;
|
|
271
|
+
const fail = (cause) => {
|
|
272
|
+
manager.notify(require_types.LottieSubscription.error, { error: cause });
|
|
273
|
+
setError(cause);
|
|
274
|
+
setState(require_types.LottieState.error);
|
|
275
|
+
};
|
|
276
|
+
const normalized = require_normalizeAnimationSource.normalizeAnimationSource(source);
|
|
277
|
+
if (normalized === null) {
|
|
278
|
+
fail(/* @__PURE__ */ new Error("lottie-react: `src` must be a non-empty path or a parsed animation object."));
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
const chosenRenderer = loadConfig.renderer ?? require_types.LottieRenderer.svg;
|
|
282
|
+
const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
283
|
+
const autoplayed = loadConfig.autoplay && !reducedMotion;
|
|
284
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
|
|
285
|
+
if (loadConfig.autoplay && reducedMotion) console.warn("[lottie-react] autoplay was not started because this device asks for reduced motion. The animation is loaded and play() works; offer a control rather than starting it for them.");
|
|
286
|
+
}
|
|
287
|
+
logger.log("loading the animation", {
|
|
288
|
+
loadAttempt,
|
|
289
|
+
renderer: chosenRenderer,
|
|
290
|
+
autoplay: autoplayed,
|
|
291
|
+
loop: valuesRef.current.loop,
|
|
292
|
+
segment: loadConfig.segment
|
|
293
|
+
});
|
|
294
|
+
let item;
|
|
295
|
+
try {
|
|
296
|
+
item = lottie.loadAnimation({
|
|
297
|
+
...normalized,
|
|
298
|
+
container: display,
|
|
299
|
+
renderer: chosenRenderer,
|
|
300
|
+
rendererSettings: loadConfig.rendererSettings,
|
|
301
|
+
loop: valuesRef.current.loop,
|
|
302
|
+
autoplay: autoplayed,
|
|
303
|
+
initialSegment: loadConfig.segment === void 0 ? void 0 : [loadConfig.segment[0], loadConfig.segment[1]],
|
|
304
|
+
assetsPath: loadConfig.assetsPath
|
|
305
|
+
});
|
|
306
|
+
} catch (cause) {
|
|
307
|
+
fail(toError(cause));
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
itemRef.current = item;
|
|
311
|
+
setAnimationItem(item);
|
|
312
|
+
item.setSpeed(valuesRef.current.speed);
|
|
313
|
+
item.setDirection(valuesRef.current.direction === require_types.LottieDirection.forward ? 1 : -1);
|
|
314
|
+
let sortedMarkers = [];
|
|
315
|
+
const onDomLoaded = () => {
|
|
316
|
+
sortedMarkers = require_resolveSeekTarget.readMarkers(item).sort((a, b) => a.time - b.time);
|
|
317
|
+
setPlayableFrames(item.totalFrames);
|
|
318
|
+
setPlayableDuration(item.getDuration(false));
|
|
319
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
|
|
320
|
+
if (autoplayed) {
|
|
321
|
+
const repeats = valuesRef.current.loop;
|
|
322
|
+
if ((repeats === true ? Number.POSITIVE_INFINITY : item.getDuration(false) * (typeof repeats === "number" ? repeats + 1 : 1)) > 5) console.warn("[lottie-react] this animation starts by itself and moves for more than five seconds, which needs a way to pause it whenever anything else shares the page (WCAG 2.2.2, level A). <LottieControls> is one; any pause affordance satisfies it.");
|
|
323
|
+
}
|
|
324
|
+
if ("expressionsPlugin" in item && item.expressionsPlugin === null && "animationData" in item && require_hasExpressions.hasExpressions(item.animationData)) console.warn("[lottie-react] this animation uses expressions, which the light engine does not evaluate, so it renders without them. LottieSvg and useLottieSvg run them and still draw svg only; Lottie and useLottie run them with every renderer.");
|
|
325
|
+
}
|
|
326
|
+
setState(item.isPaused ? require_types.LottieState.stopped : require_types.LottieState.playing);
|
|
327
|
+
manager.notify(require_types.LottieSubscription.ready);
|
|
328
|
+
};
|
|
329
|
+
const onDataFailed = () => {
|
|
330
|
+
fail(/* @__PURE__ */ new Error("lottie-react: the animation could not be loaded. The engine reported no reason; check that the `src` path resolves and returns animation JSON."));
|
|
331
|
+
};
|
|
332
|
+
const onComplete = () => {
|
|
333
|
+
setState(require_types.LottieState.stopped);
|
|
334
|
+
manager.notify(require_types.LottieSubscription.complete);
|
|
335
|
+
};
|
|
336
|
+
const onLoopComplete = () => {
|
|
337
|
+
manager.notify(require_types.LottieSubscription.loopCompleted);
|
|
338
|
+
};
|
|
339
|
+
const onEnterFrame = () => {
|
|
340
|
+
const current = item.currentFrame;
|
|
341
|
+
manager.notify(require_types.LottieSubscription.frame, { currentFrame: current });
|
|
342
|
+
const previous = markerMemory.current;
|
|
343
|
+
markerMemory.current = current;
|
|
344
|
+
if (previous === null || sortedMarkers.length === 0) return;
|
|
345
|
+
const announce = (from, to) => {
|
|
346
|
+
const crossed = require_collectMarkerCrossings.collectMarkerCrossings(sortedMarkers, item.firstFrame, from, to);
|
|
347
|
+
if (crossed !== null) for (const name of crossed) manager.notify(require_types.LottieSubscription.marker, { marker: name });
|
|
348
|
+
};
|
|
349
|
+
const forward = item.playDirection >= 0;
|
|
350
|
+
if (!(forward ? current < previous : current > previous)) announce(previous, current);
|
|
351
|
+
else if (forward) {
|
|
352
|
+
announce(previous, item.totalFrames);
|
|
353
|
+
announce(-1, current);
|
|
354
|
+
} else {
|
|
355
|
+
announce(previous, -1);
|
|
356
|
+
announce(item.totalFrames, current);
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
const onSegmentStart = () => {
|
|
360
|
+
markerMemory.current = null;
|
|
361
|
+
refreshRange(item);
|
|
362
|
+
};
|
|
363
|
+
const listeners = [
|
|
364
|
+
["DOMLoaded", onDomLoaded],
|
|
365
|
+
["data_failed", onDataFailed],
|
|
366
|
+
["complete", onComplete],
|
|
367
|
+
["loopComplete", onLoopComplete],
|
|
368
|
+
["enterFrame", onEnterFrame],
|
|
369
|
+
["segmentStart", onSegmentStart]
|
|
370
|
+
];
|
|
371
|
+
for (const [name, handler] of listeners) item.addEventListener(name, handler);
|
|
372
|
+
return () => {
|
|
373
|
+
for (const [name, handler] of listeners) item.removeEventListener(name, handler);
|
|
374
|
+
item.destroy();
|
|
375
|
+
itemRef.current = null;
|
|
376
|
+
setAnimationItem(null);
|
|
377
|
+
logger.log("the animation was destroyed");
|
|
378
|
+
};
|
|
379
|
+
}, [
|
|
380
|
+
display,
|
|
381
|
+
source,
|
|
382
|
+
loadConfig,
|
|
383
|
+
lottie,
|
|
384
|
+
manager,
|
|
385
|
+
refreshRange,
|
|
386
|
+
loadAttempt
|
|
387
|
+
]);
|
|
388
|
+
(0, react.useEffect)(() => {
|
|
389
|
+
if (speed !== void 0) applySpeed(speed, "prop");
|
|
390
|
+
}, [speed, applySpeed]);
|
|
391
|
+
(0, react.useEffect)(() => {
|
|
392
|
+
if (direction !== void 0) applyDirection(direction, "prop");
|
|
393
|
+
}, [direction, applyDirection]);
|
|
394
|
+
(0, react.useEffect)(() => {
|
|
395
|
+
if (loop !== void 0) applyLoop(loop, "prop");
|
|
396
|
+
}, [loop, applyLoop]);
|
|
397
|
+
const instance = {
|
|
398
|
+
state,
|
|
399
|
+
error,
|
|
400
|
+
reload,
|
|
401
|
+
speed: speedValue,
|
|
402
|
+
direction: directionValue,
|
|
403
|
+
loop: loopValue,
|
|
404
|
+
playableFrames,
|
|
405
|
+
playableDuration,
|
|
406
|
+
play,
|
|
407
|
+
pause,
|
|
408
|
+
stop,
|
|
409
|
+
seek,
|
|
410
|
+
scrubStart,
|
|
411
|
+
scrubTo,
|
|
412
|
+
scrubEnd,
|
|
413
|
+
playSegments,
|
|
414
|
+
resetSegments,
|
|
415
|
+
setSpeed,
|
|
416
|
+
setDirection,
|
|
417
|
+
setLoop,
|
|
418
|
+
subscribe: manager.subscribe,
|
|
419
|
+
setDisplayRef,
|
|
420
|
+
setRootRef,
|
|
421
|
+
root,
|
|
422
|
+
animationItem
|
|
423
|
+
};
|
|
424
|
+
const registry = (0, react.useContext)(require_LottieRegistryContext.LottieRegistryContext);
|
|
425
|
+
const box = (0, react.useRef)({ current: instance }).current;
|
|
426
|
+
box.current = instance;
|
|
427
|
+
(0, react.useEffect)(() => registry?.register(box), [registry, box]);
|
|
428
|
+
(0, react.useEffect)(() => {
|
|
429
|
+
registry?.bump();
|
|
430
|
+
});
|
|
431
|
+
return instance;
|
|
432
|
+
}
|
|
433
|
+
//#endregion
|
|
434
|
+
exports.useLottieAnimation = useLottieAnimation;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { LottieDirection, LottieRenderer, LottieSubscriptions, RendererRows } from "./types.cjs";
|
|
2
|
+
import "lottie-web";
|
|
3
|
+
//#region src/animation/useLottieAnimation.d.ts
|
|
4
|
+
/** The options both public hooks take. */
|
|
5
|
+
interface UseLottieOptions<Renderer extends LottieRenderer = typeof LottieRenderer.svg> {
|
|
6
|
+
/**
|
|
7
|
+
* Where the animation comes from: a path or URL to fetch, or the parsed
|
|
8
|
+
* animation itself.
|
|
9
|
+
*
|
|
10
|
+
* Changing it loads a new animation, which is compared by content, so an
|
|
11
|
+
* object written inline at the call site is safe.
|
|
12
|
+
*/
|
|
13
|
+
src: string | object;
|
|
14
|
+
/** Which renderer draws it. Load-time; changing it reloads. */
|
|
15
|
+
renderer?: Renderer;
|
|
16
|
+
/** Settings for the chosen renderer. Load-time; changing it reloads. */
|
|
17
|
+
rendererSettings?: RendererRows[Renderer]["settings"];
|
|
18
|
+
/**
|
|
19
|
+
* `false` for none, `true` for forever, or a number of repeats. Reactive,
|
|
20
|
+
* and a change counts from itself: a new number means that many repeats
|
|
21
|
+
* from now.
|
|
22
|
+
*/
|
|
23
|
+
loop?: boolean | number;
|
|
24
|
+
/** Playback rate, where `1` is the animation's own speed. Reactive. */
|
|
25
|
+
speed?: number;
|
|
26
|
+
/** Which way it plays. Reactive. */
|
|
27
|
+
direction?: LottieDirection;
|
|
28
|
+
/** Whether it starts on its own. Load-time. */
|
|
29
|
+
autoplay?: boolean;
|
|
30
|
+
/** The frame range to play, as `[first, last]`. Load-time. */
|
|
31
|
+
segment?: readonly [number, number];
|
|
32
|
+
/** Where the animation's images live, if they are not beside it. Load-time. */
|
|
33
|
+
assetsPath?: string;
|
|
34
|
+
/** Traces the load lifecycle to the console. Off by default. */
|
|
35
|
+
debug?: boolean;
|
|
36
|
+
/** Handlers called as the animation reports things. */
|
|
37
|
+
subscriptions?: Partial<LottieSubscriptions>;
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { UseLottieOptions };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { LottieDirection, LottieRenderer, LottieSubscriptions, RendererRows } from "./types.js";
|
|
2
|
+
import "lottie-web";
|
|
3
|
+
//#region src/animation/useLottieAnimation.d.ts
|
|
4
|
+
/** The options both public hooks take. */
|
|
5
|
+
interface UseLottieOptions<Renderer extends LottieRenderer = typeof LottieRenderer.svg> {
|
|
6
|
+
/**
|
|
7
|
+
* Where the animation comes from: a path or URL to fetch, or the parsed
|
|
8
|
+
* animation itself.
|
|
9
|
+
*
|
|
10
|
+
* Changing it loads a new animation, which is compared by content, so an
|
|
11
|
+
* object written inline at the call site is safe.
|
|
12
|
+
*/
|
|
13
|
+
src: string | object;
|
|
14
|
+
/** Which renderer draws it. Load-time; changing it reloads. */
|
|
15
|
+
renderer?: Renderer;
|
|
16
|
+
/** Settings for the chosen renderer. Load-time; changing it reloads. */
|
|
17
|
+
rendererSettings?: RendererRows[Renderer]["settings"];
|
|
18
|
+
/**
|
|
19
|
+
* `false` for none, `true` for forever, or a number of repeats. Reactive,
|
|
20
|
+
* and a change counts from itself: a new number means that many repeats
|
|
21
|
+
* from now.
|
|
22
|
+
*/
|
|
23
|
+
loop?: boolean | number;
|
|
24
|
+
/** Playback rate, where `1` is the animation's own speed. Reactive. */
|
|
25
|
+
speed?: number;
|
|
26
|
+
/** Which way it plays. Reactive. */
|
|
27
|
+
direction?: LottieDirection;
|
|
28
|
+
/** Whether it starts on its own. Load-time. */
|
|
29
|
+
autoplay?: boolean;
|
|
30
|
+
/** The frame range to play, as `[first, last]`. Load-time. */
|
|
31
|
+
segment?: readonly [number, number];
|
|
32
|
+
/** Where the animation's images live, if they are not beside it. Load-time. */
|
|
33
|
+
assetsPath?: string;
|
|
34
|
+
/** Traces the load lifecycle to the console. Off by default. */
|
|
35
|
+
debug?: boolean;
|
|
36
|
+
/** Handlers called as the animation reports things. */
|
|
37
|
+
subscriptions?: Partial<LottieSubscriptions>;
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { UseLottieOptions };
|