@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,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;
|