@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.
Files changed (154) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +4 -10
  3. package/build/_virtual/_rolldown/runtime.cjs +23 -0
  4. package/build/animation/Lottie.cjs +39 -0
  5. package/build/animation/Lottie.d.cts +47 -0
  6. package/build/animation/Lottie.d.ts +47 -0
  7. package/build/animation/Lottie.js +37 -0
  8. package/build/animation/LottieDisplay.cjs +55 -0
  9. package/build/animation/LottieDisplay.d.cts +46 -0
  10. package/build/animation/LottieDisplay.d.ts +46 -0
  11. package/build/animation/LottieDisplay.js +53 -0
  12. package/build/animation/LottieInstanceContext.cjs +16 -0
  13. package/build/animation/LottieInstanceContext.js +17 -0
  14. package/build/animation/LottieLight.cjs +19 -0
  15. package/build/animation/LottieLight.d.cts +23 -0
  16. package/build/animation/LottieLight.d.ts +23 -0
  17. package/build/animation/LottieLight.js +17 -0
  18. package/build/animation/LottieRegistryContext.cjs +36 -0
  19. package/build/animation/LottieRegistryContext.js +35 -0
  20. package/build/animation/LottieSvg.cjs +20 -0
  21. package/build/animation/LottieSvg.d.cts +24 -0
  22. package/build/animation/LottieSvg.d.ts +24 -0
  23. package/build/animation/LottieSvg.js +18 -0
  24. package/build/animation/collectMarkerCrossings.cjs +38 -0
  25. package/build/animation/collectMarkerCrossings.js +38 -0
  26. package/build/animation/createLottieComponent.cjs +131 -0
  27. package/build/animation/createLottieComponent.d.cts +45 -0
  28. package/build/animation/createLottieComponent.d.ts +45 -0
  29. package/build/animation/createLottieComponent.js +131 -0
  30. package/build/animation/hasExpressions.cjs +25 -0
  31. package/build/animation/hasExpressions.js +25 -0
  32. package/build/animation/normalizeAnimationSource.cjs +38 -0
  33. package/build/animation/normalizeAnimationSource.js +38 -0
  34. package/build/animation/polymorphicForwardRef.cjs +18 -0
  35. package/build/animation/polymorphicForwardRef.js +19 -0
  36. package/build/animation/renderStyledElement.cjs +31 -0
  37. package/build/animation/renderStyledElement.js +31 -0
  38. package/build/animation/resolveSeekTarget.cjs +97 -0
  39. package/build/animation/resolveSeekTarget.js +95 -0
  40. package/build/animation/styleLayer.cjs +24 -0
  41. package/build/animation/styleLayer.js +24 -0
  42. package/build/animation/stylePrecedence.cjs +12 -0
  43. package/build/animation/stylePrecedence.js +12 -0
  44. package/build/animation/types.cjs +71 -0
  45. package/build/animation/types.d.cts +461 -0
  46. package/build/animation/types.d.ts +461 -0
  47. package/build/animation/types.js +68 -0
  48. package/build/animation/useLottie.cjs +40 -0
  49. package/build/animation/useLottie.d.cts +36 -0
  50. package/build/animation/useLottie.d.ts +36 -0
  51. package/build/animation/useLottie.js +38 -0
  52. package/build/animation/useLottieAnimation.cjs +434 -0
  53. package/build/animation/useLottieAnimation.d.cts +40 -0
  54. package/build/animation/useLottieAnimation.d.ts +40 -0
  55. package/build/animation/useLottieAnimation.js +434 -0
  56. package/build/animation/useLottieInstance.cjs +20 -0
  57. package/build/animation/useLottieInstance.d.cts +14 -0
  58. package/build/animation/useLottieInstance.d.ts +14 -0
  59. package/build/animation/useLottieInstance.js +20 -0
  60. package/build/animation/useLottieLight.cjs +20 -0
  61. package/build/animation/useLottieLight.d.cts +16 -0
  62. package/build/animation/useLottieLight.d.ts +16 -0
  63. package/build/animation/useLottieLight.js +18 -0
  64. package/build/animation/useLottieSvg.cjs +18 -0
  65. package/build/animation/useLottieSvg.d.cts +14 -0
  66. package/build/animation/useLottieSvg.d.ts +14 -0
  67. package/build/animation/useLottieSvg.js +16 -0
  68. package/build/controls/LottieControls.cjs +180 -0
  69. package/build/controls/LottieControls.d.cts +58 -0
  70. package/build/controls/LottieControls.d.ts +58 -0
  71. package/build/controls/LottieControls.js +178 -0
  72. package/build/controls/LottieDirectionButton.cjs +36 -0
  73. package/build/controls/LottieDirectionButton.js +35 -0
  74. package/build/controls/LottieFullscreenButton.cjs +35 -0
  75. package/build/controls/LottieFullscreenButton.js +34 -0
  76. package/build/controls/LottieLoopButton.cjs +32 -0
  77. package/build/controls/LottieLoopButton.js +31 -0
  78. package/build/controls/LottiePlayButton.cjs +34 -0
  79. package/build/controls/LottiePlayButton.js +33 -0
  80. package/build/controls/LottieReadout.cjs +61 -0
  81. package/build/controls/LottieReadout.d.cts +13 -0
  82. package/build/controls/LottieReadout.d.ts +13 -0
  83. package/build/controls/LottieReadout.js +60 -0
  84. package/build/controls/LottieSeekBar.cjs +87 -0
  85. package/build/controls/LottieSeekBar.js +86 -0
  86. package/build/controls/LottieSpeedSelect.cjs +51 -0
  87. package/build/controls/LottieSpeedSelect.js +50 -0
  88. package/build/controls/LottieStopButton.cjs +29 -0
  89. package/build/controls/LottieStopButton.js +28 -0
  90. package/build/controls/controlIcon.cjs +25 -0
  91. package/build/controls/controlIcon.js +25 -0
  92. package/build/controls/useFullscreen.cjs +46 -0
  93. package/build/controls/useFullscreen.js +46 -0
  94. package/build/controls/useShortcuts.cjs +70 -0
  95. package/build/controls/useShortcuts.js +70 -0
  96. package/build/index.cjs +36 -0
  97. package/build/index.d.cts +19 -0
  98. package/build/index.d.ts +19 -80
  99. package/build/index.js +17 -667
  100. package/build/interactions/LottieInteractions.cjs +41 -0
  101. package/build/interactions/LottieInteractions.d.cts +37 -0
  102. package/build/interactions/LottieInteractions.d.ts +37 -0
  103. package/build/interactions/LottieInteractions.js +41 -0
  104. package/build/interactions/coverProgress.cjs +55 -0
  105. package/build/interactions/coverProgress.js +53 -0
  106. package/build/interactions/lottieInView.cjs +109 -0
  107. package/build/interactions/lottieInView.d.cts +44 -0
  108. package/build/interactions/lottieInView.d.ts +44 -0
  109. package/build/interactions/lottieInView.js +109 -0
  110. package/build/interactions/lottieScrollScrub.cjs +152 -0
  111. package/build/interactions/lottieScrollScrub.d.cts +47 -0
  112. package/build/interactions/lottieScrollScrub.d.ts +47 -0
  113. package/build/interactions/lottieScrollScrub.js +152 -0
  114. package/build/interactions/types.d.cts +46 -0
  115. package/build/interactions/types.d.ts +46 -0
  116. package/build/interactions/useInteractionsRunner.cjs +142 -0
  117. package/build/interactions/useInteractionsRunner.js +141 -0
  118. package/build/interactions/useLottieInteractions.cjs +21 -0
  119. package/build/interactions/useLottieInteractions.d.cts +19 -0
  120. package/build/interactions/useLottieInteractions.d.ts +19 -0
  121. package/build/interactions/useLottieInteractions.js +21 -0
  122. package/build/overlays/LottieError.cjs +74 -0
  123. package/build/overlays/LottieError.d.cts +40 -0
  124. package/build/overlays/LottieError.d.ts +40 -0
  125. package/build/overlays/LottieError.js +72 -0
  126. package/build/overlays/LottieLoading.cjs +89 -0
  127. package/build/overlays/LottieLoading.d.cts +45 -0
  128. package/build/overlays/LottieLoading.d.ts +45 -0
  129. package/build/overlays/LottieLoading.js +87 -0
  130. package/build/overlays/overlayStyles.cjs +33 -0
  131. package/build/overlays/overlayStyles.js +33 -0
  132. package/build/utils/SubscriptionManager.cjs +42 -0
  133. package/build/utils/SubscriptionManager.d.cts +30 -0
  134. package/build/utils/SubscriptionManager.d.ts +30 -0
  135. package/build/utils/SubscriptionManager.js +42 -0
  136. package/build/utils/createLogger.cjs +25 -0
  137. package/build/utils/createLogger.js +25 -0
  138. package/build/utils/isSameJson.cjs +37 -0
  139. package/build/utils/isSameJson.js +37 -0
  140. package/build/utils/mergeRefs.cjs +37 -0
  141. package/build/utils/mergeRefs.js +37 -0
  142. package/build/utils/useStableValue.cjs +26 -0
  143. package/build/utils/useStableValue.js +26 -0
  144. package/changes.json +3 -8
  145. package/package.json +144 -89
  146. package/LICENSE +0 -46
  147. package/build/index.es.js +0 -653
  148. package/build/index.es.js.map +0 -1
  149. package/build/index.es.min.js +0 -3
  150. package/build/index.js.map +0 -1
  151. package/build/index.min.js +0 -3
  152. package/build/index.umd.js +0 -670
  153. package/build/index.umd.js.map +0 -1
  154. package/build/index.umd.min.js +0 -3
@@ -0,0 +1,41 @@
1
+ const require_LottieInstanceContext = require("../animation/LottieInstanceContext.cjs");
2
+ const require_LottieRegistryContext = require("../animation/LottieRegistryContext.cjs");
3
+ const require_useInteractionsRunner = require("./useInteractionsRunner.cjs");
4
+ let react = require("react");
5
+ let react_jsx_runtime = require("react/jsx-runtime");
6
+ //#region src/interactions/LottieInteractions.tsx
7
+ /**
8
+ * Attaches behaviours to animations, from any of three positions.
9
+ *
10
+ * Around a `<Lottie>` it drives every animation inside it, however deep and
11
+ * however many, with no display of its own to place. Inside a `<Lottie>` it
12
+ * drives that animation. Handed a `lottie` from the hook path it drives
13
+ * exactly that one, like every other component here.
14
+ *
15
+ * ```jsx
16
+ * <LottieInteractions interactions={[lottieInView({ once: true })]}>
17
+ * <Lottie src={anim} autoplay={false} />
18
+ * </LottieInteractions>
19
+ * ```
20
+ *
21
+ * The resolution is the nearest claim wins: the `lottie` prop, else the
22
+ * animation whose `<Lottie>` this sits inside, else whatever renders below.
23
+ * When one of the first two wins, the children pass through untouched, so an
24
+ * animation below still reaches a wrapper further out. Wrapping nothing is
25
+ * not an error, because the animations inside may mount later; it simply
26
+ * does nothing yet.
27
+ */
28
+ function LottieInteractions({ lottie, interactions, children }) {
29
+ const surrounding = (0, react.useContext)(require_LottieInstanceContext.LottieInstanceContext);
30
+ const explicit = lottie ?? surrounding;
31
+ const [store] = (0, react.useState)(require_LottieRegistryContext.createLottieRegistry);
32
+ const single = require_useInteractionsRunner.useSingleInstanceSource(explicit);
33
+ require_useInteractionsRunner.useInteractionsRunner(explicit !== null ? single : store, interactions);
34
+ if (explicit !== null) return children ?? null;
35
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_LottieRegistryContext.LottieRegistryContext.Provider, {
36
+ value: store,
37
+ children
38
+ });
39
+ }
40
+ //#endregion
41
+ exports.LottieInteractions = LottieInteractions;
@@ -0,0 +1,37 @@
1
+ import { LottieInstance } from "../animation/types.cjs";
2
+ import { LottieInteraction } from "./types.cjs";
3
+ import { ReactNode } from "react";
4
+ //#region src/interactions/LottieInteractions.d.ts
5
+ /** What {@link LottieInteractions} owns. It renders no element of its own. */
6
+ interface LottieInteractionsProps {
7
+ /** The animation to drive. Omit it around or inside `<Lottie>`. */
8
+ lottie?: LottieInstance;
9
+ /** The behaviours, each made by a factory such as `lottieInView(...)`. */
10
+ interactions: readonly LottieInteraction[];
11
+ /** Anything at all, rendered untouched. */
12
+ children?: ReactNode;
13
+ }
14
+ /**
15
+ * Attaches behaviours to animations, from any of three positions.
16
+ *
17
+ * Around a `<Lottie>` it drives every animation inside it, however deep and
18
+ * however many, with no display of its own to place. Inside a `<Lottie>` it
19
+ * drives that animation. Handed a `lottie` from the hook path it drives
20
+ * exactly that one, like every other component here.
21
+ *
22
+ * ```jsx
23
+ * <LottieInteractions interactions={[lottieInView({ once: true })]}>
24
+ * <Lottie src={anim} autoplay={false} />
25
+ * </LottieInteractions>
26
+ * ```
27
+ *
28
+ * The resolution is the nearest claim wins: the `lottie` prop, else the
29
+ * animation whose `<Lottie>` this sits inside, else whatever renders below.
30
+ * When one of the first two wins, the children pass through untouched, so an
31
+ * animation below still reaches a wrapper further out. Wrapping nothing is
32
+ * not an error, because the animations inside may mount later; it simply
33
+ * does nothing yet.
34
+ */
35
+ declare function LottieInteractions({ lottie, interactions, children }: LottieInteractionsProps): ReactNode;
36
+ //#endregion
37
+ export { LottieInteractions, LottieInteractionsProps };
@@ -0,0 +1,37 @@
1
+ import { LottieInstance } from "../animation/types.js";
2
+ import { LottieInteraction } from "./types.js";
3
+ import { ReactNode } from "react";
4
+ //#region src/interactions/LottieInteractions.d.ts
5
+ /** What {@link LottieInteractions} owns. It renders no element of its own. */
6
+ interface LottieInteractionsProps {
7
+ /** The animation to drive. Omit it around or inside `<Lottie>`. */
8
+ lottie?: LottieInstance;
9
+ /** The behaviours, each made by a factory such as `lottieInView(...)`. */
10
+ interactions: readonly LottieInteraction[];
11
+ /** Anything at all, rendered untouched. */
12
+ children?: ReactNode;
13
+ }
14
+ /**
15
+ * Attaches behaviours to animations, from any of three positions.
16
+ *
17
+ * Around a `<Lottie>` it drives every animation inside it, however deep and
18
+ * however many, with no display of its own to place. Inside a `<Lottie>` it
19
+ * drives that animation. Handed a `lottie` from the hook path it drives
20
+ * exactly that one, like every other component here.
21
+ *
22
+ * ```jsx
23
+ * <LottieInteractions interactions={[lottieInView({ once: true })]}>
24
+ * <Lottie src={anim} autoplay={false} />
25
+ * </LottieInteractions>
26
+ * ```
27
+ *
28
+ * The resolution is the nearest claim wins: the `lottie` prop, else the
29
+ * animation whose `<Lottie>` this sits inside, else whatever renders below.
30
+ * When one of the first two wins, the children pass through untouched, so an
31
+ * animation below still reaches a wrapper further out. Wrapping nothing is
32
+ * not an error, because the animations inside may mount later; it simply
33
+ * does nothing yet.
34
+ */
35
+ declare function LottieInteractions({ lottie, interactions, children }: LottieInteractionsProps): ReactNode;
36
+ //#endregion
37
+ export { LottieInteractions, LottieInteractionsProps };
@@ -0,0 +1,41 @@
1
+ import { LottieInstanceContext } from "../animation/LottieInstanceContext.js";
2
+ import { LottieRegistryContext, createLottieRegistry } from "../animation/LottieRegistryContext.js";
3
+ import { useInteractionsRunner, useSingleInstanceSource } from "./useInteractionsRunner.js";
4
+ import { useContext, useState } from "react";
5
+ import { jsx } from "react/jsx-runtime";
6
+ //#region src/interactions/LottieInteractions.tsx
7
+ /**
8
+ * Attaches behaviours to animations, from any of three positions.
9
+ *
10
+ * Around a `<Lottie>` it drives every animation inside it, however deep and
11
+ * however many, with no display of its own to place. Inside a `<Lottie>` it
12
+ * drives that animation. Handed a `lottie` from the hook path it drives
13
+ * exactly that one, like every other component here.
14
+ *
15
+ * ```jsx
16
+ * <LottieInteractions interactions={[lottieInView({ once: true })]}>
17
+ * <Lottie src={anim} autoplay={false} />
18
+ * </LottieInteractions>
19
+ * ```
20
+ *
21
+ * The resolution is the nearest claim wins: the `lottie` prop, else the
22
+ * animation whose `<Lottie>` this sits inside, else whatever renders below.
23
+ * When one of the first two wins, the children pass through untouched, so an
24
+ * animation below still reaches a wrapper further out. Wrapping nothing is
25
+ * not an error, because the animations inside may mount later; it simply
26
+ * does nothing yet.
27
+ */
28
+ function LottieInteractions({ lottie, interactions, children }) {
29
+ const surrounding = useContext(LottieInstanceContext);
30
+ const explicit = lottie ?? surrounding;
31
+ const [store] = useState(createLottieRegistry);
32
+ const single = useSingleInstanceSource(explicit);
33
+ useInteractionsRunner(explicit !== null ? single : store, interactions);
34
+ if (explicit !== null) return children ?? null;
35
+ return /* @__PURE__ */ jsx(LottieRegistryContext.Provider, {
36
+ value: store,
37
+ children
38
+ });
39
+ }
40
+ //#endregion
41
+ export { LottieInteractions };
@@ -0,0 +1,55 @@
1
+ //#region src/interactions/coverProgress.ts
2
+ /**
3
+ * Where an element's journey across a viewport stands: 0 as its leading edge
4
+ * reaches the viewport's far end, 1 as its trailing edge leaves the near end.
5
+ *
6
+ * This is the platform's `cover` range written out, which is what makes the
7
+ * fallback and a real `ViewTimeline` agree wherever both can run. It reads
8
+ * a rectangle rather than the live layout, so the caller decides where the
9
+ * rectangle comes from and the arithmetic stays measurable.
10
+ */
11
+ function coverProgress(rect, viewport, axis) {
12
+ const size = axis === "inline" ? viewport.width : viewport.height;
13
+ const leading = axis === "inline" ? rect.left : rect.top;
14
+ const span = size + (axis === "inline" ? rect.width : rect.height);
15
+ if (span === 0) return 0;
16
+ return Math.min(Math.max((size - leading) / span, 0), 1);
17
+ }
18
+ /**
19
+ * The journey progress mapped into a band of it, clamped at the band's ends.
20
+ *
21
+ * Holding still below the band and holding still above it are what replace
22
+ * v2's `stop` bands: they are not features, they are what clamping does.
23
+ */
24
+ function bandProgress(progress, range) {
25
+ const [start, end] = range;
26
+ if (end === start) return progress < start ? 0 : 1;
27
+ return Math.min(Math.max((progress - start) / (end - start), 0), 1);
28
+ }
29
+ /**
30
+ * Compares two banded samples and names the edges crossed between them.
31
+ *
32
+ * Inside means strictly between the clamps; a sample pinned at 0 or 1 is
33
+ * outside, which is what makes leaving fire exactly when the scrub reaches
34
+ * an end. The first sample of a gesture has no predecessor, and starting
35
+ * already inside counts as entering forward. A single sample that crosses
36
+ * the whole band reports both edges in its direction of travel.
37
+ */
38
+ function bandEdges(previous, current) {
39
+ const isInside = current > 0 && current < 1;
40
+ if (previous === null) return isInside ? { enter: "forward" } : {};
41
+ const wasInside = previous > 0 && previous < 1;
42
+ const direction = current >= previous ? "forward" : "backward";
43
+ const events = {};
44
+ if (!wasInside && isInside) events.enter = direction;
45
+ if (wasInside && !isInside) events.leave = direction;
46
+ if (!wasInside && !isInside && previous !== current && previous <= 0 !== current <= 0) {
47
+ events.enter = direction;
48
+ events.leave = direction;
49
+ }
50
+ return events;
51
+ }
52
+ //#endregion
53
+ exports.bandEdges = bandEdges;
54
+ exports.bandProgress = bandProgress;
55
+ exports.coverProgress = coverProgress;
@@ -0,0 +1,53 @@
1
+ //#region src/interactions/coverProgress.ts
2
+ /**
3
+ * Where an element's journey across a viewport stands: 0 as its leading edge
4
+ * reaches the viewport's far end, 1 as its trailing edge leaves the near end.
5
+ *
6
+ * This is the platform's `cover` range written out, which is what makes the
7
+ * fallback and a real `ViewTimeline` agree wherever both can run. It reads
8
+ * a rectangle rather than the live layout, so the caller decides where the
9
+ * rectangle comes from and the arithmetic stays measurable.
10
+ */
11
+ function coverProgress(rect, viewport, axis) {
12
+ const size = axis === "inline" ? viewport.width : viewport.height;
13
+ const leading = axis === "inline" ? rect.left : rect.top;
14
+ const span = size + (axis === "inline" ? rect.width : rect.height);
15
+ if (span === 0) return 0;
16
+ return Math.min(Math.max((size - leading) / span, 0), 1);
17
+ }
18
+ /**
19
+ * The journey progress mapped into a band of it, clamped at the band's ends.
20
+ *
21
+ * Holding still below the band and holding still above it are what replace
22
+ * v2's `stop` bands: they are not features, they are what clamping does.
23
+ */
24
+ function bandProgress(progress, range) {
25
+ const [start, end] = range;
26
+ if (end === start) return progress < start ? 0 : 1;
27
+ return Math.min(Math.max((progress - start) / (end - start), 0), 1);
28
+ }
29
+ /**
30
+ * Compares two banded samples and names the edges crossed between them.
31
+ *
32
+ * Inside means strictly between the clamps; a sample pinned at 0 or 1 is
33
+ * outside, which is what makes leaving fire exactly when the scrub reaches
34
+ * an end. The first sample of a gesture has no predecessor, and starting
35
+ * already inside counts as entering forward. A single sample that crosses
36
+ * the whole band reports both edges in its direction of travel.
37
+ */
38
+ function bandEdges(previous, current) {
39
+ const isInside = current > 0 && current < 1;
40
+ if (previous === null) return isInside ? { enter: "forward" } : {};
41
+ const wasInside = previous > 0 && previous < 1;
42
+ const direction = current >= previous ? "forward" : "backward";
43
+ const events = {};
44
+ if (!wasInside && isInside) events.enter = direction;
45
+ if (wasInside && !isInside) events.leave = direction;
46
+ if (!wasInside && !isInside && previous !== current && previous <= 0 !== current <= 0) {
47
+ events.enter = direction;
48
+ events.leave = direction;
49
+ }
50
+ return events;
51
+ }
52
+ //#endregion
53
+ export { bandEdges, bandProgress, coverProgress };
@@ -0,0 +1,109 @@
1
+ const require_types = require("../animation/types.cjs");
2
+ //#region src/interactions/lottieInView.ts
3
+ function isInViewOptions(value) {
4
+ if (typeof value !== "object" || value === null) return false;
5
+ if ("once" in value && typeof value.once !== "boolean") return false;
6
+ if ("amount" in value && typeof value.amount !== "number") return false;
7
+ return !("margin" in value && typeof value.margin !== "string");
8
+ }
9
+ /** Whether a play command would fight something that outranks it. */
10
+ function playable(state) {
11
+ return state !== require_types.LottieState.loading && state !== require_types.LottieState.error && state !== require_types.LottieState.frozen;
12
+ }
13
+ function attachInView(context, raw) {
14
+ const options = isInViewOptions(raw) ? raw : {};
15
+ let observer = null;
16
+ let observedRoot = null;
17
+ let playedByUs = false;
18
+ let previousState = context.lottie.state;
19
+ let lastIntersecting = null;
20
+ const warnRedundant = () => {
21
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
22
+ if (context.memory.warnedRedundant !== true && !playedByUs && context.lottie.state === require_types.LottieState.playing) {
23
+ context.memory.warnedRedundant = true;
24
+ console.warn("[lottie-react] an in-view trigger is watching an animation that already plays by itself. With autoplay on, the trigger has nothing left to start; drop one of the two.");
25
+ }
26
+ }
27
+ };
28
+ const playFromEntry = () => {
29
+ if (options.once === true) {
30
+ context.memory.entered = true;
31
+ observer?.disconnect();
32
+ observer = null;
33
+ }
34
+ playedByUs = true;
35
+ context.lottie.play();
36
+ };
37
+ const handleEntries = (entries) => {
38
+ const entry = entries.at(-1);
39
+ if (entry === void 0) return;
40
+ lastIntersecting = entry.isIntersecting;
41
+ const lottie = context.lottie;
42
+ if (entry.isIntersecting) {
43
+ if (options.once === true && context.memory.entered === true) return;
44
+ if (playable(lottie.state)) playFromEntry();
45
+ } else if (options.once !== true && lottie.state === require_types.LottieState.playing) lottie.pause();
46
+ };
47
+ const arm = () => {
48
+ const root = context.lottie.root;
49
+ if (root === observedRoot) return;
50
+ observer?.disconnect();
51
+ observer = null;
52
+ observedRoot = root;
53
+ if (root === null) return;
54
+ if (options.once === true && context.memory.entered === true) return;
55
+ try {
56
+ observer = new IntersectionObserver(handleEntries, {
57
+ threshold: options.amount ?? 0,
58
+ rootMargin: options.margin
59
+ });
60
+ } catch {
61
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") console.warn(`[lottie-react] the margin ${JSON.stringify(options.margin)} was refused, so the trigger watches without it. A margin is written in px or %, the only lengths the platform accepts here.`);
62
+ observer = new IntersectionObserver(handleEntries, { threshold: options.amount ?? 0 });
63
+ }
64
+ observer.observe(root);
65
+ };
66
+ const stopListening = context.onChange(() => {
67
+ const state = context.lottie.state;
68
+ if (previousState === require_types.LottieState.loading && state === require_types.LottieState.playing) warnRedundant();
69
+ if (previousState === require_types.LottieState.loading && lastIntersecting === true && playable(state) && state !== require_types.LottieState.playing && !(options.once === true && context.memory.entered === true)) playFromEntry();
70
+ previousState = state;
71
+ arm();
72
+ });
73
+ warnRedundant();
74
+ arm();
75
+ return () => {
76
+ stopListening();
77
+ observer?.disconnect();
78
+ };
79
+ }
80
+ /**
81
+ * Plays the animation when it scrolls into view and pauses it when it leaves,
82
+ * or with `once`, plays on the first entry and never again.
83
+ *
84
+ * ```jsx
85
+ * <LottieInteractions interactions={[lottieInView({ once: true })]}>
86
+ * <Lottie src={anim} autoplay={false} />
87
+ * </LottieInteractions>
88
+ * ```
89
+ *
90
+ * An entry seen while the animation is still loading plays as soon as the
91
+ * load finishes, so an animation already on screen at page load starts by
92
+ * itself.
93
+ *
94
+ * Leaving pauses rather than stops, so coming back resumes mid-motion instead
95
+ * of restarting. The trigger never overrides a load still in flight or a
96
+ * failed one, and it cannot tell its own pause from one a person asked for,
97
+ * so re-entering resumes either.
98
+ */
99
+ function lottieInView(options = {}) {
100
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
101
+ if (options.amount === 1) console.warn("[lottie-react] amount: 1 never fires for an animation taller than the viewport, because such an element is never entirely visible. Use a smaller amount, or a negative margin for a centre band.");
102
+ }
103
+ return {
104
+ attach: attachInView,
105
+ options
106
+ };
107
+ }
108
+ //#endregion
109
+ exports.lottieInView = lottieInView;
@@ -0,0 +1,44 @@
1
+ import { LottieInteraction } from "./types.cjs";
2
+ //#region src/interactions/lottieInView.d.ts
3
+ /** What {@link lottieInView} can be told. */
4
+ interface LottieInViewOptions {
5
+ /**
6
+ * Play on the first entry and then stop watching for good, so scrolling
7
+ * past again replays nothing. Off unless asked for.
8
+ */
9
+ once?: boolean;
10
+ /**
11
+ * How much of the animation must be visible to count as entered, `0` to
12
+ * `1`. The default is `0`: a single visible pixel. `1` is accepted and
13
+ * warned about, because an element taller than the viewport can never be
14
+ * entirely visible, so a threshold of one silently never fires for it.
15
+ */
16
+ amount?: number;
17
+ /**
18
+ * Grows or shrinks the viewport the entry is measured against, in the
19
+ * platform's own `rootMargin` grammar: px or % only.
20
+ */
21
+ margin?: string;
22
+ }
23
+ /**
24
+ * Plays the animation when it scrolls into view and pauses it when it leaves,
25
+ * or with `once`, plays on the first entry and never again.
26
+ *
27
+ * ```jsx
28
+ * <LottieInteractions interactions={[lottieInView({ once: true })]}>
29
+ * <Lottie src={anim} autoplay={false} />
30
+ * </LottieInteractions>
31
+ * ```
32
+ *
33
+ * An entry seen while the animation is still loading plays as soon as the
34
+ * load finishes, so an animation already on screen at page load starts by
35
+ * itself.
36
+ *
37
+ * Leaving pauses rather than stops, so coming back resumes mid-motion instead
38
+ * of restarting. The trigger never overrides a load still in flight or a
39
+ * failed one, and it cannot tell its own pause from one a person asked for,
40
+ * so re-entering resumes either.
41
+ */
42
+ declare function lottieInView(options?: LottieInViewOptions): LottieInteraction;
43
+ //#endregion
44
+ export { LottieInViewOptions, lottieInView };
@@ -0,0 +1,44 @@
1
+ import { LottieInteraction } from "./types.js";
2
+ //#region src/interactions/lottieInView.d.ts
3
+ /** What {@link lottieInView} can be told. */
4
+ interface LottieInViewOptions {
5
+ /**
6
+ * Play on the first entry and then stop watching for good, so scrolling
7
+ * past again replays nothing. Off unless asked for.
8
+ */
9
+ once?: boolean;
10
+ /**
11
+ * How much of the animation must be visible to count as entered, `0` to
12
+ * `1`. The default is `0`: a single visible pixel. `1` is accepted and
13
+ * warned about, because an element taller than the viewport can never be
14
+ * entirely visible, so a threshold of one silently never fires for it.
15
+ */
16
+ amount?: number;
17
+ /**
18
+ * Grows or shrinks the viewport the entry is measured against, in the
19
+ * platform's own `rootMargin` grammar: px or % only.
20
+ */
21
+ margin?: string;
22
+ }
23
+ /**
24
+ * Plays the animation when it scrolls into view and pauses it when it leaves,
25
+ * or with `once`, plays on the first entry and never again.
26
+ *
27
+ * ```jsx
28
+ * <LottieInteractions interactions={[lottieInView({ once: true })]}>
29
+ * <Lottie src={anim} autoplay={false} />
30
+ * </LottieInteractions>
31
+ * ```
32
+ *
33
+ * An entry seen while the animation is still loading plays as soon as the
34
+ * load finishes, so an animation already on screen at page load starts by
35
+ * itself.
36
+ *
37
+ * Leaving pauses rather than stops, so coming back resumes mid-motion instead
38
+ * of restarting. The trigger never overrides a load still in flight or a
39
+ * failed one, and it cannot tell its own pause from one a person asked for,
40
+ * so re-entering resumes either.
41
+ */
42
+ declare function lottieInView(options?: LottieInViewOptions): LottieInteraction;
43
+ //#endregion
44
+ export { LottieInViewOptions, lottieInView };
@@ -0,0 +1,109 @@
1
+ import { LottieState } from "../animation/types.js";
2
+ //#region src/interactions/lottieInView.ts
3
+ function isInViewOptions(value) {
4
+ if (typeof value !== "object" || value === null) return false;
5
+ if ("once" in value && typeof value.once !== "boolean") return false;
6
+ if ("amount" in value && typeof value.amount !== "number") return false;
7
+ return !("margin" in value && typeof value.margin !== "string");
8
+ }
9
+ /** Whether a play command would fight something that outranks it. */
10
+ function playable(state) {
11
+ return state !== LottieState.loading && state !== LottieState.error && state !== LottieState.frozen;
12
+ }
13
+ function attachInView(context, raw) {
14
+ const options = isInViewOptions(raw) ? raw : {};
15
+ let observer = null;
16
+ let observedRoot = null;
17
+ let playedByUs = false;
18
+ let previousState = context.lottie.state;
19
+ let lastIntersecting = null;
20
+ const warnRedundant = () => {
21
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
22
+ if (context.memory.warnedRedundant !== true && !playedByUs && context.lottie.state === LottieState.playing) {
23
+ context.memory.warnedRedundant = true;
24
+ console.warn("[lottie-react] an in-view trigger is watching an animation that already plays by itself. With autoplay on, the trigger has nothing left to start; drop one of the two.");
25
+ }
26
+ }
27
+ };
28
+ const playFromEntry = () => {
29
+ if (options.once === true) {
30
+ context.memory.entered = true;
31
+ observer?.disconnect();
32
+ observer = null;
33
+ }
34
+ playedByUs = true;
35
+ context.lottie.play();
36
+ };
37
+ const handleEntries = (entries) => {
38
+ const entry = entries.at(-1);
39
+ if (entry === void 0) return;
40
+ lastIntersecting = entry.isIntersecting;
41
+ const lottie = context.lottie;
42
+ if (entry.isIntersecting) {
43
+ if (options.once === true && context.memory.entered === true) return;
44
+ if (playable(lottie.state)) playFromEntry();
45
+ } else if (options.once !== true && lottie.state === LottieState.playing) lottie.pause();
46
+ };
47
+ const arm = () => {
48
+ const root = context.lottie.root;
49
+ if (root === observedRoot) return;
50
+ observer?.disconnect();
51
+ observer = null;
52
+ observedRoot = root;
53
+ if (root === null) return;
54
+ if (options.once === true && context.memory.entered === true) return;
55
+ try {
56
+ observer = new IntersectionObserver(handleEntries, {
57
+ threshold: options.amount ?? 0,
58
+ rootMargin: options.margin
59
+ });
60
+ } catch {
61
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") console.warn(`[lottie-react] the margin ${JSON.stringify(options.margin)} was refused, so the trigger watches without it. A margin is written in px or %, the only lengths the platform accepts here.`);
62
+ observer = new IntersectionObserver(handleEntries, { threshold: options.amount ?? 0 });
63
+ }
64
+ observer.observe(root);
65
+ };
66
+ const stopListening = context.onChange(() => {
67
+ const state = context.lottie.state;
68
+ if (previousState === LottieState.loading && state === LottieState.playing) warnRedundant();
69
+ if (previousState === LottieState.loading && lastIntersecting === true && playable(state) && state !== LottieState.playing && !(options.once === true && context.memory.entered === true)) playFromEntry();
70
+ previousState = state;
71
+ arm();
72
+ });
73
+ warnRedundant();
74
+ arm();
75
+ return () => {
76
+ stopListening();
77
+ observer?.disconnect();
78
+ };
79
+ }
80
+ /**
81
+ * Plays the animation when it scrolls into view and pauses it when it leaves,
82
+ * or with `once`, plays on the first entry and never again.
83
+ *
84
+ * ```jsx
85
+ * <LottieInteractions interactions={[lottieInView({ once: true })]}>
86
+ * <Lottie src={anim} autoplay={false} />
87
+ * </LottieInteractions>
88
+ * ```
89
+ *
90
+ * An entry seen while the animation is still loading plays as soon as the
91
+ * load finishes, so an animation already on screen at page load starts by
92
+ * itself.
93
+ *
94
+ * Leaving pauses rather than stops, so coming back resumes mid-motion instead
95
+ * of restarting. The trigger never overrides a load still in flight or a
96
+ * failed one, and it cannot tell its own pause from one a person asked for,
97
+ * so re-entering resumes either.
98
+ */
99
+ function lottieInView(options = {}) {
100
+ if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
101
+ if (options.amount === 1) console.warn("[lottie-react] amount: 1 never fires for an animation taller than the viewport, because such an element is never entirely visible. Use a smaller amount, or a negative margin for a centre band.");
102
+ }
103
+ return {
104
+ attach: attachInView,
105
+ options
106
+ };
107
+ }
108
+ //#endregion
109
+ export { lottieInView };