@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,180 @@
1
+ const require_renderStyledElement = require("../animation/renderStyledElement.cjs");
2
+ const require_useLottieInstance = require("../animation/useLottieInstance.cjs");
3
+ const require_types = require("../animation/types.cjs");
4
+ const require_LottieDirectionButton = require("./LottieDirectionButton.cjs");
5
+ const require_LottieFullscreenButton = require("./LottieFullscreenButton.cjs");
6
+ const require_LottieLoopButton = require("./LottieLoopButton.cjs");
7
+ const require_LottiePlayButton = require("./LottiePlayButton.cjs");
8
+ const require_LottieReadout = require("./LottieReadout.cjs");
9
+ const require_LottieSeekBar = require("./LottieSeekBar.cjs");
10
+ const require_LottieSpeedSelect = require("./LottieSpeedSelect.cjs");
11
+ const require_LottieStopButton = require("./LottieStopButton.cjs");
12
+ const require_useFullscreen = require("./useFullscreen.cjs");
13
+ const require_useShortcuts = require("./useShortcuts.cjs");
14
+ let react = require("react");
15
+ let react_jsx_runtime = require("react/jsx-runtime");
16
+ //#region src/controls/LottieControls.tsx
17
+ /**
18
+ * The class the bar carries, and the name React deduplicates its stylesheet by.
19
+ * One string does both, so two components can only collide in the document if
20
+ * they already collide in CSS.
21
+ */
22
+ const lottieControlsClass = "lottie-controls";
23
+ /**
24
+ * Everything the bar and its controls look like, at zero specificity and inside
25
+ * the library's cascade layer, so that any rule the consumer writes beats them
26
+ * per property.
27
+ *
28
+ * The whole set lives here rather than one sheet per control, because the class
29
+ * and the `href` are one string and eight stylesheets would mean eight names to
30
+ * keep from colliding instead of one. Every rule below is scoped under the bar's
31
+ * own class, so the controls' classes need no such guarantee.
32
+ *
33
+ * Every control carries a faint fill before it is touched, a stronger one under
34
+ * the pointer and stronger again when it is a toggle that is on, so the three
35
+ * states can never read as each other and the bar is legible at rest rather
36
+ * than only under a cursor. The readout is the one thing with no fill, because
37
+ * it is the one thing that is not a control.
38
+ *
39
+ * Five of these are load-bearing rather than taste.
40
+ *
41
+ * `container-type` is what lets the narrow-width rule measure the bar instead of
42
+ * the window, so a small animation on a wide page counts as narrow. It has a
43
+ * consequence worth knowing: the bar's own width can no longer be worked out
44
+ * from its contents, so it has to be stretched by whatever holds it. Inside the
45
+ * element `<Lottie>` renders that is automatic, and in a row that sizes to its
46
+ * contents the bar would have no width at all.
47
+ *
48
+ * `accent-color` colours the seek bar's track and thumb with one property. The
49
+ * player this replaces reached for `::-webkit-slider-thumb` and its Firefox
50
+ * counterpart instead, unscoped, and so restyled every range input on the page.
51
+ *
52
+ * `field-sizing` on the rate picker makes it as wide as the value showing
53
+ * rather than as wide as its widest option. Measured in Chromium against the
54
+ * real component, that is 35.2px rather than 61.0px, so without it two fifths
55
+ * of the control is space held for `0.25x` while `1x` is displayed, which reads
56
+ * as a gap between the value and its chevron. It is newly enough available that
57
+ * a browser without it simply keeps the wider box, which is a roomy control
58
+ * rather than a broken one.
59
+ *
60
+ * The focus ring is written inside `:where()` along with everything else, so a
61
+ * consumer can still replace it, and it is `:focus-visible` so it appears for
62
+ * the keyboard rather than for every click.
63
+ *
64
+ * Sizes are in `em` and colours are `currentColor` throughout, so the bar takes
65
+ * the surrounding text's size and colour rather than any this library picked.
66
+ * `1.5em` is the smallest target WCAG accepts at a 16px root.
67
+ */
68
+ const lottieControlsStyles = `:where(.${lottieControlsClass}){container-type:inline-size;display:flex;align-items:center;gap:0.3em;padding:0.35em;border-radius:0.6em;background:color-mix(in srgb,currentColor 7%,transparent);color:currentColor}:where(.${lottieControlsClass}) :where(button,select,input){min-width:1.5em;min-height:1.5em;padding:0;border:0;border-radius:0.25em;background:transparent;color:inherit;font:inherit}:where(.${lottieControlsClass}) :where(button,select){background:color-mix(in srgb,currentColor 10%,transparent)}:where(.${lottieControlsClass}) :where(button){display:inline-flex;align-items:center;justify-content:center;cursor:pointer}:where(.${lottieControlsClass}) :where(button)>:where(svg){width:1em;height:1em}:where(.${lottieControlsClass}) :where(button:hover,select:hover){background:color-mix(in srgb,currentColor 22%,transparent)}:where(.${lottieControlsClass}) :where(button[aria-pressed="true"]){background:color-mix(in srgb,currentColor 38%,transparent)}:where(.${lottieControlsClass}) :where(button:disabled,select:disabled,input:disabled){opacity:0.5;cursor:default}:where(.${lottieControlsClass}) :where(button:focus-visible,select:focus-visible,input:focus-visible){outline:2px solid currentColor;outline-offset:1px}:where(.${lottieControlsClass}) :where(.${require_LottieSeekBar.lottieSeekClass}){flex:1;min-width:6em;accent-color:currentColor;cursor:pointer}:where(.${lottieControlsClass}) :where(.${require_LottieSpeedSelect.lottieSpeedClass}){field-sizing:content;padding:0 0.35em}:where(.${lottieControlsClass}) :where(.${require_LottieReadout.lottieReadoutClass}){padding:0 0.4em;font-variant-numeric:tabular-nums;white-space:nowrap;opacity:0.8}:where(.${lottieControlsClass}) :where(.${require_LottieReadout.lottieReadoutClass})>:where(span){display:inline-block;text-align:right}@container (max-width:400px){:where(.${lottieControlsClass}) :where(.${require_LottieStopButton.lottieStopClass},.${require_LottieReadout.lottieReadoutClass},.${require_LottieDirectionButton.lottieDirectionClass},.${require_LottieSpeedSelect.lottieSpeedClass}){display:none}}`;
69
+ /**
70
+ * A bar of controls for driving an animation.
71
+ *
72
+ * Render it among the children of a component that publishes an animation, or
73
+ * anywhere at all with the result of `useLottie`. It sits below the animation
74
+ * rather than over it, because this control set is for inspecting a file and
75
+ * covering the thing being inspected defeats it.
76
+ *
77
+ * ```jsx
78
+ * <Lottie src="/hero.json">
79
+ * <LottieDisplay />
80
+ * <LottieControls />
81
+ * </Lottie>
82
+ * ```
83
+ *
84
+ * Left to right: play and stop, the seek bar, the position, looping and
85
+ * direction, then the playback rate and fullscreen. That order follows what
86
+ * every Lottie player that publishes one does, and it is why the rate sits away
87
+ * from the transport controls rather than beside them.
88
+ *
89
+ * Three keys work while the animation holds focus, or while it is the thing
90
+ * filling the screen: `k` plays and pauses, `l` loops, `f` fills the screen.
91
+ * They belong to this bar, so a page that renders no controls has no key
92
+ * listener either.
93
+ *
94
+ * Fullscreen takes this bar with the animation, since both sit inside the
95
+ * element `<Lottie>` renders. On the hook path that element is yours, so the
96
+ * button appears once something carries `setRootRef` and not before.
97
+ *
98
+ * While the animation is loading, and after a load has failed, every control is
99
+ * disabled and so are the keys. Both are states in which an overlay covers this
100
+ * bar, so leaving them usable would mean a keyboard could reach controls
101
+ * nothing can see.
102
+ *
103
+ * It takes every attribute of the `div` it renders, and `ref` names that same
104
+ * element. Its own rules are all zero-specificity, so any of them can be
105
+ * replaced one property at a time from your own stylesheet, which is why there
106
+ * is no theme prop. If your CSS lives in cascade layers, declare
107
+ * `@layer lottie-react;` before your own styles so the library's layer ranks
108
+ * below them.
109
+ */
110
+ const LottieControls = (0, react.forwardRef)(function LottieControls({ lottie, unit, className, ...rest }, ref) {
111
+ const instance = require_useLottieInstance.useLottieInstance(lottie);
112
+ const { loop, setLoop } = instance;
113
+ const disabled = instance.state === require_types.LottieState.loading || instance.state === require_types.LottieState.error;
114
+ const remembered = (0, react.useRef)(true);
115
+ const toggleLoop = (0, react.useCallback)(() => {
116
+ if (loop === false) setLoop(remembered.current);
117
+ else {
118
+ remembered.current = loop;
119
+ setLoop(false);
120
+ }
121
+ }, [loop, setLoop]);
122
+ const { isFullscreen, toggle: toggleFullscreen } = require_useFullscreen.useFullscreen(instance.root);
123
+ require_useShortcuts.useShortcuts(instance, {
124
+ disabled,
125
+ toggleLoop,
126
+ toggleFullscreen
127
+ });
128
+ return require_renderStyledElement.renderStyledElement({
129
+ tag: "div",
130
+ styleClass: lottieControlsClass,
131
+ styles: lottieControlsStyles,
132
+ className,
133
+ attributes: {
134
+ role: "group",
135
+ "aria-label": "Animation controls",
136
+ ...rest
137
+ },
138
+ ref,
139
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
140
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_LottiePlayButton.LottiePlayButton, {
141
+ lottie: instance,
142
+ disabled
143
+ }),
144
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_LottieStopButton.LottieStopButton, {
145
+ lottie: instance,
146
+ disabled
147
+ }),
148
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_LottieSeekBar.LottieSeekBar, {
149
+ lottie: instance,
150
+ disabled
151
+ }),
152
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_LottieReadout.LottieReadout, {
153
+ lottie: instance,
154
+ unit
155
+ }),
156
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_LottieLoopButton.LottieLoopButton, {
157
+ lottie: instance,
158
+ toggle: toggleLoop,
159
+ disabled
160
+ }),
161
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_LottieDirectionButton.LottieDirectionButton, {
162
+ lottie: instance,
163
+ disabled
164
+ }),
165
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_LottieSpeedSelect.LottieSpeedSelect, {
166
+ lottie: instance,
167
+ disabled
168
+ }),
169
+ toggleFullscreen !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_LottieFullscreenButton.LottieFullscreenButton, {
170
+ isFullscreen,
171
+ toggle: toggleFullscreen,
172
+ disabled
173
+ })
174
+ ] })
175
+ });
176
+ });
177
+ //#endregion
178
+ exports.LottieControls = LottieControls;
179
+ exports.lottieControlsClass = lottieControlsClass;
180
+ exports.lottieControlsStyles = lottieControlsStyles;
@@ -0,0 +1,58 @@
1
+ import { FixedElementProps, LottieInstance } from "../animation/types.cjs";
2
+ import { LottieReadoutUnit } from "./LottieReadout.cjs";
3
+ //#region src/controls/LottieControls.d.ts
4
+ /** What this component owns. Every other prop belongs to the element. */
5
+ interface LottieControlsOwnProps {
6
+ /** The animation to drive. Omit it inside a component that publishes one. */
7
+ lottie?: LottieInstance;
8
+ /** What the position is counted in. Frames unless you say otherwise. */
9
+ unit?: LottieReadoutUnit;
10
+ /** Added to the library's class rather than replacing it. */
11
+ className?: string;
12
+ }
13
+ /** What {@link LottieControls} accepts. */
14
+ type LottieControlsProps = FixedElementProps<LottieControlsOwnProps, "div">;
15
+ /**
16
+ * A bar of controls for driving an animation.
17
+ *
18
+ * Render it among the children of a component that publishes an animation, or
19
+ * anywhere at all with the result of `useLottie`. It sits below the animation
20
+ * rather than over it, because this control set is for inspecting a file and
21
+ * covering the thing being inspected defeats it.
22
+ *
23
+ * ```jsx
24
+ * <Lottie src="/hero.json">
25
+ * <LottieDisplay />
26
+ * <LottieControls />
27
+ * </Lottie>
28
+ * ```
29
+ *
30
+ * Left to right: play and stop, the seek bar, the position, looping and
31
+ * direction, then the playback rate and fullscreen. That order follows what
32
+ * every Lottie player that publishes one does, and it is why the rate sits away
33
+ * from the transport controls rather than beside them.
34
+ *
35
+ * Three keys work while the animation holds focus, or while it is the thing
36
+ * filling the screen: `k` plays and pauses, `l` loops, `f` fills the screen.
37
+ * They belong to this bar, so a page that renders no controls has no key
38
+ * listener either.
39
+ *
40
+ * Fullscreen takes this bar with the animation, since both sit inside the
41
+ * element `<Lottie>` renders. On the hook path that element is yours, so the
42
+ * button appears once something carries `setRootRef` and not before.
43
+ *
44
+ * While the animation is loading, and after a load has failed, every control is
45
+ * disabled and so are the keys. Both are states in which an overlay covers this
46
+ * bar, so leaving them usable would mean a keyboard could reach controls
47
+ * nothing can see.
48
+ *
49
+ * It takes every attribute of the `div` it renders, and `ref` names that same
50
+ * element. Its own rules are all zero-specificity, so any of them can be
51
+ * replaced one property at a time from your own stylesheet, which is why there
52
+ * is no theme prop. If your CSS lives in cascade layers, declare
53
+ * `@layer lottie-react;` before your own styles so the library's layer ranks
54
+ * below them.
55
+ */
56
+ declare const LottieControls: import("react").ForwardRefExoticComponent<LottieControlsOwnProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof LottieControlsOwnProps> & import("react").RefAttributes<HTMLDivElement>>;
57
+ //#endregion
58
+ export { LottieControls, LottieControlsProps };
@@ -0,0 +1,58 @@
1
+ import { FixedElementProps, LottieInstance } from "../animation/types.js";
2
+ import { LottieReadoutUnit } from "./LottieReadout.js";
3
+ //#region src/controls/LottieControls.d.ts
4
+ /** What this component owns. Every other prop belongs to the element. */
5
+ interface LottieControlsOwnProps {
6
+ /** The animation to drive. Omit it inside a component that publishes one. */
7
+ lottie?: LottieInstance;
8
+ /** What the position is counted in. Frames unless you say otherwise. */
9
+ unit?: LottieReadoutUnit;
10
+ /** Added to the library's class rather than replacing it. */
11
+ className?: string;
12
+ }
13
+ /** What {@link LottieControls} accepts. */
14
+ type LottieControlsProps = FixedElementProps<LottieControlsOwnProps, "div">;
15
+ /**
16
+ * A bar of controls for driving an animation.
17
+ *
18
+ * Render it among the children of a component that publishes an animation, or
19
+ * anywhere at all with the result of `useLottie`. It sits below the animation
20
+ * rather than over it, because this control set is for inspecting a file and
21
+ * covering the thing being inspected defeats it.
22
+ *
23
+ * ```jsx
24
+ * <Lottie src="/hero.json">
25
+ * <LottieDisplay />
26
+ * <LottieControls />
27
+ * </Lottie>
28
+ * ```
29
+ *
30
+ * Left to right: play and stop, the seek bar, the position, looping and
31
+ * direction, then the playback rate and fullscreen. That order follows what
32
+ * every Lottie player that publishes one does, and it is why the rate sits away
33
+ * from the transport controls rather than beside them.
34
+ *
35
+ * Three keys work while the animation holds focus, or while it is the thing
36
+ * filling the screen: `k` plays and pauses, `l` loops, `f` fills the screen.
37
+ * They belong to this bar, so a page that renders no controls has no key
38
+ * listener either.
39
+ *
40
+ * Fullscreen takes this bar with the animation, since both sit inside the
41
+ * element `<Lottie>` renders. On the hook path that element is yours, so the
42
+ * button appears once something carries `setRootRef` and not before.
43
+ *
44
+ * While the animation is loading, and after a load has failed, every control is
45
+ * disabled and so are the keys. Both are states in which an overlay covers this
46
+ * bar, so leaving them usable would mean a keyboard could reach controls
47
+ * nothing can see.
48
+ *
49
+ * It takes every attribute of the `div` it renders, and `ref` names that same
50
+ * element. Its own rules are all zero-specificity, so any of them can be
51
+ * replaced one property at a time from your own stylesheet, which is why there
52
+ * is no theme prop. If your CSS lives in cascade layers, declare
53
+ * `@layer lottie-react;` before your own styles so the library's layer ranks
54
+ * below them.
55
+ */
56
+ declare const LottieControls: import("react").ForwardRefExoticComponent<LottieControlsOwnProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, keyof LottieControlsOwnProps> & import("react").RefAttributes<HTMLDivElement>>;
57
+ //#endregion
58
+ export { LottieControls, LottieControlsProps };
@@ -0,0 +1,178 @@
1
+ import { renderStyledElement } from "../animation/renderStyledElement.js";
2
+ import { useLottieInstance } from "../animation/useLottieInstance.js";
3
+ import { LottieState } from "../animation/types.js";
4
+ import { LottieDirectionButton, lottieDirectionClass } from "./LottieDirectionButton.js";
5
+ import { LottieFullscreenButton } from "./LottieFullscreenButton.js";
6
+ import { LottieLoopButton } from "./LottieLoopButton.js";
7
+ import { LottiePlayButton } from "./LottiePlayButton.js";
8
+ import { LottieReadout, lottieReadoutClass } from "./LottieReadout.js";
9
+ import { LottieSeekBar, lottieSeekClass } from "./LottieSeekBar.js";
10
+ import { LottieSpeedSelect, lottieSpeedClass } from "./LottieSpeedSelect.js";
11
+ import { LottieStopButton, lottieStopClass } from "./LottieStopButton.js";
12
+ import { useFullscreen } from "./useFullscreen.js";
13
+ import { useShortcuts } from "./useShortcuts.js";
14
+ import { forwardRef, useCallback, useRef } from "react";
15
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
16
+ //#region src/controls/LottieControls.tsx
17
+ /**
18
+ * The class the bar carries, and the name React deduplicates its stylesheet by.
19
+ * One string does both, so two components can only collide in the document if
20
+ * they already collide in CSS.
21
+ */
22
+ const lottieControlsClass = "lottie-controls";
23
+ /**
24
+ * Everything the bar and its controls look like, at zero specificity and inside
25
+ * the library's cascade layer, so that any rule the consumer writes beats them
26
+ * per property.
27
+ *
28
+ * The whole set lives here rather than one sheet per control, because the class
29
+ * and the `href` are one string and eight stylesheets would mean eight names to
30
+ * keep from colliding instead of one. Every rule below is scoped under the bar's
31
+ * own class, so the controls' classes need no such guarantee.
32
+ *
33
+ * Every control carries a faint fill before it is touched, a stronger one under
34
+ * the pointer and stronger again when it is a toggle that is on, so the three
35
+ * states can never read as each other and the bar is legible at rest rather
36
+ * than only under a cursor. The readout is the one thing with no fill, because
37
+ * it is the one thing that is not a control.
38
+ *
39
+ * Five of these are load-bearing rather than taste.
40
+ *
41
+ * `container-type` is what lets the narrow-width rule measure the bar instead of
42
+ * the window, so a small animation on a wide page counts as narrow. It has a
43
+ * consequence worth knowing: the bar's own width can no longer be worked out
44
+ * from its contents, so it has to be stretched by whatever holds it. Inside the
45
+ * element `<Lottie>` renders that is automatic, and in a row that sizes to its
46
+ * contents the bar would have no width at all.
47
+ *
48
+ * `accent-color` colours the seek bar's track and thumb with one property. The
49
+ * player this replaces reached for `::-webkit-slider-thumb` and its Firefox
50
+ * counterpart instead, unscoped, and so restyled every range input on the page.
51
+ *
52
+ * `field-sizing` on the rate picker makes it as wide as the value showing
53
+ * rather than as wide as its widest option. Measured in Chromium against the
54
+ * real component, that is 35.2px rather than 61.0px, so without it two fifths
55
+ * of the control is space held for `0.25x` while `1x` is displayed, which reads
56
+ * as a gap between the value and its chevron. It is newly enough available that
57
+ * a browser without it simply keeps the wider box, which is a roomy control
58
+ * rather than a broken one.
59
+ *
60
+ * The focus ring is written inside `:where()` along with everything else, so a
61
+ * consumer can still replace it, and it is `:focus-visible` so it appears for
62
+ * the keyboard rather than for every click.
63
+ *
64
+ * Sizes are in `em` and colours are `currentColor` throughout, so the bar takes
65
+ * the surrounding text's size and colour rather than any this library picked.
66
+ * `1.5em` is the smallest target WCAG accepts at a 16px root.
67
+ */
68
+ const lottieControlsStyles = `:where(.${lottieControlsClass}){container-type:inline-size;display:flex;align-items:center;gap:0.3em;padding:0.35em;border-radius:0.6em;background:color-mix(in srgb,currentColor 7%,transparent);color:currentColor}:where(.${lottieControlsClass}) :where(button,select,input){min-width:1.5em;min-height:1.5em;padding:0;border:0;border-radius:0.25em;background:transparent;color:inherit;font:inherit}:where(.${lottieControlsClass}) :where(button,select){background:color-mix(in srgb,currentColor 10%,transparent)}:where(.${lottieControlsClass}) :where(button){display:inline-flex;align-items:center;justify-content:center;cursor:pointer}:where(.${lottieControlsClass}) :where(button)>:where(svg){width:1em;height:1em}:where(.${lottieControlsClass}) :where(button:hover,select:hover){background:color-mix(in srgb,currentColor 22%,transparent)}:where(.${lottieControlsClass}) :where(button[aria-pressed="true"]){background:color-mix(in srgb,currentColor 38%,transparent)}:where(.${lottieControlsClass}) :where(button:disabled,select:disabled,input:disabled){opacity:0.5;cursor:default}:where(.${lottieControlsClass}) :where(button:focus-visible,select:focus-visible,input:focus-visible){outline:2px solid currentColor;outline-offset:1px}:where(.${lottieControlsClass}) :where(.${lottieSeekClass}){flex:1;min-width:6em;accent-color:currentColor;cursor:pointer}:where(.${lottieControlsClass}) :where(.${lottieSpeedClass}){field-sizing:content;padding:0 0.35em}:where(.${lottieControlsClass}) :where(.${lottieReadoutClass}){padding:0 0.4em;font-variant-numeric:tabular-nums;white-space:nowrap;opacity:0.8}:where(.${lottieControlsClass}) :where(.${lottieReadoutClass})>:where(span){display:inline-block;text-align:right}@container (max-width:400px){:where(.${lottieControlsClass}) :where(.${lottieStopClass},.${lottieReadoutClass},.${lottieDirectionClass},.${lottieSpeedClass}){display:none}}`;
69
+ /**
70
+ * A bar of controls for driving an animation.
71
+ *
72
+ * Render it among the children of a component that publishes an animation, or
73
+ * anywhere at all with the result of `useLottie`. It sits below the animation
74
+ * rather than over it, because this control set is for inspecting a file and
75
+ * covering the thing being inspected defeats it.
76
+ *
77
+ * ```jsx
78
+ * <Lottie src="/hero.json">
79
+ * <LottieDisplay />
80
+ * <LottieControls />
81
+ * </Lottie>
82
+ * ```
83
+ *
84
+ * Left to right: play and stop, the seek bar, the position, looping and
85
+ * direction, then the playback rate and fullscreen. That order follows what
86
+ * every Lottie player that publishes one does, and it is why the rate sits away
87
+ * from the transport controls rather than beside them.
88
+ *
89
+ * Three keys work while the animation holds focus, or while it is the thing
90
+ * filling the screen: `k` plays and pauses, `l` loops, `f` fills the screen.
91
+ * They belong to this bar, so a page that renders no controls has no key
92
+ * listener either.
93
+ *
94
+ * Fullscreen takes this bar with the animation, since both sit inside the
95
+ * element `<Lottie>` renders. On the hook path that element is yours, so the
96
+ * button appears once something carries `setRootRef` and not before.
97
+ *
98
+ * While the animation is loading, and after a load has failed, every control is
99
+ * disabled and so are the keys. Both are states in which an overlay covers this
100
+ * bar, so leaving them usable would mean a keyboard could reach controls
101
+ * nothing can see.
102
+ *
103
+ * It takes every attribute of the `div` it renders, and `ref` names that same
104
+ * element. Its own rules are all zero-specificity, so any of them can be
105
+ * replaced one property at a time from your own stylesheet, which is why there
106
+ * is no theme prop. If your CSS lives in cascade layers, declare
107
+ * `@layer lottie-react;` before your own styles so the library's layer ranks
108
+ * below them.
109
+ */
110
+ const LottieControls = forwardRef(function LottieControls({ lottie, unit, className, ...rest }, ref) {
111
+ const instance = useLottieInstance(lottie);
112
+ const { loop, setLoop } = instance;
113
+ const disabled = instance.state === LottieState.loading || instance.state === LottieState.error;
114
+ const remembered = useRef(true);
115
+ const toggleLoop = useCallback(() => {
116
+ if (loop === false) setLoop(remembered.current);
117
+ else {
118
+ remembered.current = loop;
119
+ setLoop(false);
120
+ }
121
+ }, [loop, setLoop]);
122
+ const { isFullscreen, toggle: toggleFullscreen } = useFullscreen(instance.root);
123
+ useShortcuts(instance, {
124
+ disabled,
125
+ toggleLoop,
126
+ toggleFullscreen
127
+ });
128
+ return renderStyledElement({
129
+ tag: "div",
130
+ styleClass: lottieControlsClass,
131
+ styles: lottieControlsStyles,
132
+ className,
133
+ attributes: {
134
+ role: "group",
135
+ "aria-label": "Animation controls",
136
+ ...rest
137
+ },
138
+ ref,
139
+ children: /* @__PURE__ */ jsxs(Fragment, { children: [
140
+ /* @__PURE__ */ jsx(LottiePlayButton, {
141
+ lottie: instance,
142
+ disabled
143
+ }),
144
+ /* @__PURE__ */ jsx(LottieStopButton, {
145
+ lottie: instance,
146
+ disabled
147
+ }),
148
+ /* @__PURE__ */ jsx(LottieSeekBar, {
149
+ lottie: instance,
150
+ disabled
151
+ }),
152
+ /* @__PURE__ */ jsx(LottieReadout, {
153
+ lottie: instance,
154
+ unit
155
+ }),
156
+ /* @__PURE__ */ jsx(LottieLoopButton, {
157
+ lottie: instance,
158
+ toggle: toggleLoop,
159
+ disabled
160
+ }),
161
+ /* @__PURE__ */ jsx(LottieDirectionButton, {
162
+ lottie: instance,
163
+ disabled
164
+ }),
165
+ /* @__PURE__ */ jsx(LottieSpeedSelect, {
166
+ lottie: instance,
167
+ disabled
168
+ }),
169
+ toggleFullscreen !== null && /* @__PURE__ */ jsx(LottieFullscreenButton, {
170
+ isFullscreen,
171
+ toggle: toggleFullscreen,
172
+ disabled
173
+ })
174
+ ] })
175
+ });
176
+ });
177
+ //#endregion
178
+ export { LottieControls, lottieControlsClass, lottieControlsStyles };
@@ -0,0 +1,36 @@
1
+ const require_useLottieInstance = require("../animation/useLottieInstance.cjs");
2
+ const require_types = require("../animation/types.cjs");
3
+ const require_controlIcon = require("./controlIcon.cjs");
4
+ let react_jsx_runtime = require("react/jsx-runtime");
5
+ //#region src/controls/LottieDirectionButton.tsx
6
+ /** The class this control carries, which the bar's stylesheet targets. */
7
+ const lottieDirectionClass = "lottie-direction";
8
+ const forwardPath = "M4 18l8.5-6L4 6zm9 0l8.5-6L13 6z";
9
+ const reversePath = "M20 18V6l-8.5 6zm-9 0V6l-8.5 6z";
10
+ /**
11
+ * Turns playing in reverse on and off.
12
+ *
13
+ * The label names the control rather than the next action, and `aria-pressed`
14
+ * carries which way it is currently set. Naming the action instead is what left
15
+ * the old player saying "Reverse direction" while showing a forward arrow, so a
16
+ * reader had to guess whether either described the present.
17
+ */
18
+ function LottieDirectionButton({ lottie, className, ...rest }) {
19
+ const instance = require_useLottieInstance.useLottieInstance(lottie);
20
+ const reversed = instance.direction === require_types.LottieDirection.reverse;
21
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
22
+ "aria-label": "Play in reverse",
23
+ title: "Play in reverse",
24
+ ...rest,
25
+ "aria-pressed": reversed,
26
+ className: className ? `${lottieDirectionClass} ${className}` : lottieDirectionClass,
27
+ onClick: () => {
28
+ instance.setDirection(reversed ? require_types.LottieDirection.forward : require_types.LottieDirection.reverse);
29
+ },
30
+ type: "button",
31
+ children: require_controlIcon.controlIcon(reversed ? reversePath : forwardPath)
32
+ });
33
+ }
34
+ //#endregion
35
+ exports.LottieDirectionButton = LottieDirectionButton;
36
+ exports.lottieDirectionClass = lottieDirectionClass;
@@ -0,0 +1,35 @@
1
+ import { useLottieInstance } from "../animation/useLottieInstance.js";
2
+ import { LottieDirection } from "../animation/types.js";
3
+ import { controlIcon } from "./controlIcon.js";
4
+ import { jsx } from "react/jsx-runtime";
5
+ //#region src/controls/LottieDirectionButton.tsx
6
+ /** The class this control carries, which the bar's stylesheet targets. */
7
+ const lottieDirectionClass = "lottie-direction";
8
+ const forwardPath = "M4 18l8.5-6L4 6zm9 0l8.5-6L13 6z";
9
+ const reversePath = "M20 18V6l-8.5 6zm-9 0V6l-8.5 6z";
10
+ /**
11
+ * Turns playing in reverse on and off.
12
+ *
13
+ * The label names the control rather than the next action, and `aria-pressed`
14
+ * carries which way it is currently set. Naming the action instead is what left
15
+ * the old player saying "Reverse direction" while showing a forward arrow, so a
16
+ * reader had to guess whether either described the present.
17
+ */
18
+ function LottieDirectionButton({ lottie, className, ...rest }) {
19
+ const instance = useLottieInstance(lottie);
20
+ const reversed = instance.direction === LottieDirection.reverse;
21
+ return /* @__PURE__ */ jsx("button", {
22
+ "aria-label": "Play in reverse",
23
+ title: "Play in reverse",
24
+ ...rest,
25
+ "aria-pressed": reversed,
26
+ className: className ? `${lottieDirectionClass} ${className}` : lottieDirectionClass,
27
+ onClick: () => {
28
+ instance.setDirection(reversed ? LottieDirection.forward : LottieDirection.reverse);
29
+ },
30
+ type: "button",
31
+ children: controlIcon(reversed ? reversePath : forwardPath)
32
+ });
33
+ }
34
+ //#endregion
35
+ export { LottieDirectionButton, lottieDirectionClass };
@@ -0,0 +1,35 @@
1
+ const require_controlIcon = require("./controlIcon.cjs");
2
+ let react_jsx_runtime = require("react/jsx-runtime");
3
+ //#region src/controls/LottieFullscreenButton.tsx
4
+ /** The class this control carries, which the bar's stylesheet targets. */
5
+ const lottieFullscreenClass = "lottie-fullscreen";
6
+ const enterPath = "M7 14H5v5h5v-2H7zM5 10h2V7h3V5H5zm12 7h-3v2h5v-5h-2zM14 5v2h3v3h2V5z";
7
+ const exitPath = "M5 16h3v3h2v-5H5zm3-8H5v2h5V5H8zm6 11h2v-3h3v-2h-5zm2-11V5h-2v5h5V8z";
8
+ /**
9
+ * Fills the screen with the animation and everything around it.
10
+ *
11
+ * The only control that is handed its state rather than reading the animation,
12
+ * because what it needs is a property of an element and of the browser rather
13
+ * than of the animation, and because the bar needs the same toggle for the `f`
14
+ * key. Two copies of one piece of state derived from one event is how they
15
+ * would drift.
16
+ *
17
+ * The label says what pressing it will do and changes with the icon, the way
18
+ * play and pause do in this bar, rather than naming a control whose state is
19
+ * carried separately. That is also what every video player does here.
20
+ */
21
+ function LottieFullscreenButton({ isFullscreen, toggle, className, ...rest }) {
22
+ const label = isFullscreen ? "Exit full screen" : "Full screen";
23
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
24
+ "aria-label": label,
25
+ title: label,
26
+ ...rest,
27
+ className: className ? `${lottieFullscreenClass} ${className}` : lottieFullscreenClass,
28
+ onClick: toggle,
29
+ type: "button",
30
+ children: require_controlIcon.controlIcon(isFullscreen ? exitPath : enterPath)
31
+ });
32
+ }
33
+ //#endregion
34
+ exports.LottieFullscreenButton = LottieFullscreenButton;
35
+ exports.lottieFullscreenClass = lottieFullscreenClass;
@@ -0,0 +1,34 @@
1
+ import { controlIcon } from "./controlIcon.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ //#region src/controls/LottieFullscreenButton.tsx
4
+ /** The class this control carries, which the bar's stylesheet targets. */
5
+ const lottieFullscreenClass = "lottie-fullscreen";
6
+ const enterPath = "M7 14H5v5h5v-2H7zM5 10h2V7h3V5H5zm12 7h-3v2h5v-5h-2zM14 5v2h3v3h2V5z";
7
+ const exitPath = "M5 16h3v3h2v-5H5zm3-8H5v2h5V5H8zm6 11h2v-3h3v-2h-5zm2-11V5h-2v5h5V8z";
8
+ /**
9
+ * Fills the screen with the animation and everything around it.
10
+ *
11
+ * The only control that is handed its state rather than reading the animation,
12
+ * because what it needs is a property of an element and of the browser rather
13
+ * than of the animation, and because the bar needs the same toggle for the `f`
14
+ * key. Two copies of one piece of state derived from one event is how they
15
+ * would drift.
16
+ *
17
+ * The label says what pressing it will do and changes with the icon, the way
18
+ * play and pause do in this bar, rather than naming a control whose state is
19
+ * carried separately. That is also what every video player does here.
20
+ */
21
+ function LottieFullscreenButton({ isFullscreen, toggle, className, ...rest }) {
22
+ const label = isFullscreen ? "Exit full screen" : "Full screen";
23
+ return /* @__PURE__ */ jsx("button", {
24
+ "aria-label": label,
25
+ title: label,
26
+ ...rest,
27
+ className: className ? `${lottieFullscreenClass} ${className}` : lottieFullscreenClass,
28
+ onClick: toggle,
29
+ type: "button",
30
+ children: controlIcon(isFullscreen ? exitPath : enterPath)
31
+ });
32
+ }
33
+ //#endregion
34
+ export { LottieFullscreenButton, lottieFullscreenClass };
@@ -0,0 +1,32 @@
1
+ const require_useLottieInstance = require("../animation/useLottieInstance.cjs");
2
+ const require_controlIcon = require("./controlIcon.cjs");
3
+ let react_jsx_runtime = require("react/jsx-runtime");
4
+ //#region src/controls/LottieLoopButton.tsx
5
+ /** The class this control carries, which the bar's stylesheet targets. */
6
+ const lottieLoopClass = "lottie-loop";
7
+ const loopPath = "M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4z";
8
+ /**
9
+ * Turns looping on and off.
10
+ *
11
+ * The switching itself is handed in rather than done here, because the `l`
12
+ * shortcut does the same thing and the count in force has to be remembered
13
+ * across both. Two memories would mean pressing the key and then the button
14
+ * loses a `loop={3}`, which is the exact fault that got the old surface's
15
+ * `toggleLoop` dropped rather than rebuilt.
16
+ */
17
+ function LottieLoopButton({ lottie, toggle, className, ...rest }) {
18
+ const looping = require_useLottieInstance.useLottieInstance(lottie).loop !== false;
19
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
20
+ "aria-label": "Loop",
21
+ title: "Loop",
22
+ ...rest,
23
+ "aria-pressed": looping,
24
+ className: className ? `${lottieLoopClass} ${className}` : lottieLoopClass,
25
+ onClick: toggle,
26
+ type: "button",
27
+ children: require_controlIcon.controlIcon(loopPath)
28
+ });
29
+ }
30
+ //#endregion
31
+ exports.LottieLoopButton = LottieLoopButton;
32
+ exports.lottieLoopClass = lottieLoopClass;