use-scroll-animate 9.0.0 → 9.2.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/CHANGELOG.md CHANGED
@@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [9.2.0] - 2026-10-09
11
+
12
+ ### Added
13
+ - **Lottie / Rive import — `motionary/fx/lottie`** (= `motionary/components/fx-lottie`, `registerLottiePack()`, also in `registerEffectPacks()` and the marketplace): `lottieToKeyframes(json)` (layer position / anchor / rotation / scale / opacity → WAAPI keyframes + duration), `lottieToSvg(json)` (ellipse / rect / path shapes with fill / stroke, nested groups), `riveInputs(instance, stateMachine, el, { hover, press, click, enter })` (drive a Rive state machine's boolean / trigger inputs). Effects `lottie-play` (attention) and `icon-pop` (click).
14
+ - **2 new components (9.2)** in `motionary/components/widgets`:
15
+ - `<usa-lottie>` — Lottie player without lottie-web: `src` or `json`, `autoplay` (on screen), `loop`, `speed`, `label`; `play()`, `pause()`, `stop()`, `parsed`; `usa:load` { duration, layers }, `usa:complete`, `usa:error`.
16
+ - `<usa-lottie-icon>` — animated icon set shipped as tiny Lottie files (`heart`, `bell`, `check`, `spinner`, `star`, `bolt`; JSON exported as `LOTTIE_ICONS`); `trigger` click · hover · enter · loop, `size`, `color`, `label`; `play()`.
17
+ - Showcase: 3 new gallery cards with copyable code, live demos and live Store thumbnails.
18
+
19
+ ### Accessibility
20
+ - `<usa-lottie>` is an `img` with `label`; icons are decorative (`aria-hidden`) unless they get a `label` (then `img`). Reduced motion: the first frame is shown, nothing autoplays, `icon-pop` / `lottie-play` do nothing.
21
+
22
+ ## [9.1.0] - 2026-10-09
23
+
24
+ ### Added
25
+ - **2 new components (9.1)** in `motionary/components/widgets` (also in `dist/widgets.umd.js`):
26
+ - `<usa-chapter-nav>` — chapter navigation for long-form stories: one entry per `[data-chapter]` section in `for` (title from `data-chapter` or its first heading), per-chapter reading-progress bars, `aria-current="step"` on the current chapter, click to glide there; `orientation`, `label`; `current`, `goTo(i)`; `usa:chapter` { index, title }.
27
+ - `<usa-scene>` — scroll-scrubbed cinematic shot: its media (`img` / `video` / `[data-shot]`) follows a `camera` move (`dolly-in` · `dolly-out` · `pan-left` · `pan-right` · `tilt-up` · `tilt-down` · `zoom-in` · `zoom-out` · `orbit`, `strength`) as the scene crosses the viewport; `[data-caption][data-at]` captions fade in on cue; `autoplay` plays the move on its own (back and forth) instead of following the scroll; `progress`, `setProgress(p)`; `usa:shot`.
28
+ - **Cinematic pack — `motionary/fx/cinema`** (= `motionary/components/fx-cinema`, `registerCinemaPack()`, also in `registerEffectPacks()`): `dolly-in` (enter), `pan-reveal` (enter), `letterbox` (enter), `rack-focus` (attention). `cameraFrame(move, p, strength)`, `CAMERA_MOVES`. Listed in the `motionary/marketplace` catalogue.
29
+ - Showcase: 4 new gallery cards with copyable code, live demos and live Store thumbnails.
30
+
31
+ ### Accessibility
32
+ - Chapter nav is a labelled `navigation` with an ordered list of real buttons; the current one has `aria-current="step"`; bars are `aria-hidden`. Scene captions are real text in reading order. Reduced motion: the scene is a still frame with captions shown, chapter jumps are instant, entrances fade, `rack-focus` does nothing.
33
+
10
34
  ## [9.0.0] - 2026-10-09
11
35
 
12
36
  ### ⚠ Breaking
@@ -0,0 +1,100 @@
1
+ 'use strict';
2
+
3
+ var registry = require('../chunks/registry-BVklOepd.cjs');
4
+ require('../chunks/base-DoRUZBy-.cjs');
5
+
6
+ const CAMERA_MOVES = ['dolly-in', 'dolly-out', 'pan-left', 'pan-right', 'tilt-up', 'tilt-down', 'zoom-in', 'zoom-out', 'orbit'];
7
+ /** Transform of camera `move` at progress `p` (0–1, clamped), `strength` 0–2 (9.1). */
8
+ function cameraFrame(move, p, strength = 1) {
9
+ const t = Math.min(1, Math.max(0, p));
10
+ const k = Math.min(2, Math.max(0, strength));
11
+ const f = (n) => Math.round(n * 1000) / 1000;
12
+ switch (move) {
13
+ case 'dolly-in':
14
+ return `scale(${f(1 + 0.18 * k * t)})`;
15
+ case 'dolly-out':
16
+ return `scale(${f(1 + 0.18 * k * (1 - t))})`;
17
+ case 'pan-left':
18
+ return `scale(${f(1 + 0.12 * k)}) translateX(${f(6 * k - 12 * k * t)}%)`;
19
+ case 'pan-right':
20
+ return `scale(${f(1 + 0.12 * k)}) translateX(${f(-6 * k + 12 * k * t)}%)`;
21
+ case 'tilt-up':
22
+ return `scale(${f(1 + 0.12 * k)}) translateY(${f(-6 * k + 12 * k * t)}%)`;
23
+ case 'tilt-down':
24
+ return `scale(${f(1 + 0.12 * k)}) translateY(${f(6 * k - 12 * k * t)}%)`;
25
+ case 'zoom-in':
26
+ return `scale(${f(1 + 0.4 * k * t * t)})`;
27
+ case 'zoom-out':
28
+ return `scale(${f(1 + 0.4 * k * (1 - t) * (1 - t))})`;
29
+ case 'orbit':
30
+ return `perspective(900px) rotateY(${f(-12 * k + 24 * k * t)}deg) scale(${f(1 + 0.08 * k)})`;
31
+ default:
32
+ return 'none';
33
+ }
34
+ }
35
+ const fade = (el, ctx) => ctx.animate(el, [{ opacity: 0 }, { opacity: 1 }], { duration: 300 })?.finished.catch(() => undefined);
36
+ const CINEMA_FX = [
37
+ {
38
+ name: 'dolly-in',
39
+ kind: 'enter',
40
+ description: 'A slow camera push: starts slightly large and soft, settles sharp (`duration`).',
41
+ defaults: { duration: 1600 },
42
+ run: (el, o, ctx) => {
43
+ if (ctx.reduced)
44
+ return fade(el, ctx);
45
+ return ctx.animate(el, [{ transform: 'scale(1.14)', filter: 'blur(6px)', opacity: 0 }, { opacity: 1, offset: 0.3 }, { transform: 'scale(1)', filter: 'blur(0)', opacity: 1 }], { duration: o.duration, delay: o.delay, easing: 'cubic-bezier(.16,.84,.3,1)', fill: 'backwards' })?.finished.catch(() => undefined);
46
+ },
47
+ },
48
+ {
49
+ name: 'pan-reveal',
50
+ kind: 'enter',
51
+ description: 'The camera pans across the element while a wipe uncovers it (`from`).',
52
+ defaults: { from: 'left', duration: 1200 },
53
+ run: (el, o, ctx) => {
54
+ if (ctx.reduced)
55
+ return fade(el, ctx);
56
+ const r = o.from === 'right';
57
+ return ctx.animate(el, [{ clipPath: r ? 'inset(0 0 0 100%)' : 'inset(0 100% 0 0)', transform: `translateX(${r ? 4 : -4}%) scale(1.06)` }, { clipPath: 'inset(0 0 0 0)', transform: 'none' }], { duration: o.duration, delay: o.delay, easing: 'cubic-bezier(.65,0,.35,1)', fill: 'backwards' })?.finished.catch(() => undefined);
58
+ },
59
+ },
60
+ {
61
+ name: 'letterbox',
62
+ kind: 'enter',
63
+ description: 'Cinema bars slide in, hold, then open up to reveal the element (`hold`).',
64
+ defaults: { duration: 1400, hold: 0.35 },
65
+ run: (el, o, ctx) => {
66
+ if (ctx.reduced)
67
+ return fade(el, ctx);
68
+ const h = Math.min(0.8, Math.max(0, Number(o.hold) || 0));
69
+ const a = 0.25;
70
+ const b = Math.min(0.95, a + h);
71
+ return ctx.animate(el, [{ clipPath: 'inset(50% 0 50% 0)', opacity: 0.6 }, { clipPath: 'inset(12% 0 12% 0)', opacity: 1, offset: a }, { clipPath: 'inset(12% 0 12% 0)', offset: b }, { clipPath: 'inset(0 0 0 0)' }], { duration: o.duration, delay: o.delay, easing: 'ease-in-out', fill: 'backwards' })?.finished.catch(() => undefined);
72
+ },
73
+ },
74
+ {
75
+ name: 'rack-focus',
76
+ kind: 'attention',
77
+ description: "Focus pulls from the element's first child to the rest and back, like racking focus between subjects.",
78
+ defaults: { duration: 1800 },
79
+ run: (el, o, ctx) => {
80
+ if (ctx.reduced)
81
+ return;
82
+ const kids = Array.from(el.children);
83
+ if (kids.length < 2)
84
+ return ctx.animate(el, [{ filter: 'blur(0)' }, { filter: 'blur(4px)', offset: 0.5 }, { filter: 'blur(0)' }], { duration: o.duration })?.finished.catch(() => undefined);
85
+ const [first, ...rest] = kids;
86
+ const runs = [ctx.animate(first, [{ filter: 'blur(0)' }, { filter: 'blur(5px)', offset: 0.35 }, { filter: 'blur(5px)', offset: 0.65 }, { filter: 'blur(0)' }], { duration: o.duration, easing: 'ease-in-out' }), ...rest.map((k) => ctx.animate(k, [{ filter: 'blur(5px)' }, { filter: 'blur(0)', offset: 0.35 }, { filter: 'blur(0)', offset: 0.65 }, { filter: 'blur(5px)' }, { filter: 'blur(0)' }], { duration: o.duration, easing: 'ease-in-out' }))];
87
+ return Promise.all(runs.map((r) => r?.finished.catch(() => undefined))).then(() => undefined);
88
+ },
89
+ },
90
+ ];
91
+ /** Register dolly-in, pan-reveal, letterbox and rack-focus (9.1). */
92
+ function registerCinemaPack() {
93
+ registry.registerEffects(CINEMA_FX);
94
+ }
95
+
96
+ exports.CAMERA_MOVES = CAMERA_MOVES;
97
+ exports.CINEMA_FX = CINEMA_FX;
98
+ exports.cameraFrame = cameraFrame;
99
+ exports.registerCinemaPack = registerCinemaPack;
100
+ //# sourceMappingURL=fx-cinema.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fx-cinema.cjs","sources":["../../src/components/fx2/cinema.ts"],"sourcesContent":["/**\n * 9.1 — Cinematic pack (`motionary/fx/cinema`, also `motionary/components/fx-cinema`):\n *\n * - `dolly-in` (enter) — a slow camera push: the element starts slightly\n * large and soft and settles sharp, like a dolly shot (`duration`).\n * - `pan-reveal` (enter) — the camera pans across the element while a\n * wipe uncovers it (`from` left|right).\n * - `letterbox` (enter) — cinema bars slide in, hold, then open up to\n * reveal the element (`hold`).\n * - `rack-focus` (attention) — focus pulls from the element's first child\n * to the rest and back, like a focus puller racking between subjects.\n *\n * `cameraFrame(move, p)` gives the transform of a camera move at progress\n * 0–1 (used by `<usa-scene>`). Reduced motion: entrances fade, rack-focus\n * does nothing.\n */\nimport type { EffectContext, EffectDefinition } from '../fx/registry';\nimport { registerEffects } from '../fx/registry';\n\nexport const CAMERA_MOVES = ['dolly-in', 'dolly-out', 'pan-left', 'pan-right', 'tilt-up', 'tilt-down', 'zoom-in', 'zoom-out', 'orbit'] as const;\nexport type CameraMove = (typeof CAMERA_MOVES)[number];\n\n/** Transform of camera `move` at progress `p` (0–1, clamped), `strength` 0–2 (9.1). */\nexport function cameraFrame(move: string, p: number, strength = 1): string {\n const t = Math.min(1, Math.max(0, p));\n const k = Math.min(2, Math.max(0, strength));\n const f = (n: number) => Math.round(n * 1000) / 1000;\n switch (move) {\n case 'dolly-in':\n return `scale(${f(1 + 0.18 * k * t)})`;\n case 'dolly-out':\n return `scale(${f(1 + 0.18 * k * (1 - t))})`;\n case 'pan-left':\n return `scale(${f(1 + 0.12 * k)}) translateX(${f(6 * k - 12 * k * t)}%)`;\n case 'pan-right':\n return `scale(${f(1 + 0.12 * k)}) translateX(${f(-6 * k + 12 * k * t)}%)`;\n case 'tilt-up':\n return `scale(${f(1 + 0.12 * k)}) translateY(${f(-6 * k + 12 * k * t)}%)`;\n case 'tilt-down':\n return `scale(${f(1 + 0.12 * k)}) translateY(${f(6 * k - 12 * k * t)}%)`;\n case 'zoom-in':\n return `scale(${f(1 + 0.4 * k * t * t)})`;\n case 'zoom-out':\n return `scale(${f(1 + 0.4 * k * (1 - t) * (1 - t))})`;\n case 'orbit':\n return `perspective(900px) rotateY(${f(-12 * k + 24 * k * t)}deg) scale(${f(1 + 0.08 * k)})`;\n default:\n return 'none';\n }\n}\n\nconst fade = (el: HTMLElement, ctx: EffectContext) => ctx.animate(el, [{ opacity: 0 }, { opacity: 1 }], { duration: 300 })?.finished.catch(() => undefined);\n\nexport const CINEMA_FX: EffectDefinition[] = [\n {\n name: 'dolly-in',\n kind: 'enter',\n description: 'A slow camera push: starts slightly large and soft, settles sharp (`duration`).',\n defaults: { duration: 1600 },\n run: (el: HTMLElement, o: any, ctx: EffectContext) => {\n if (ctx.reduced) return fade(el, ctx);\n return ctx.animate(el, [{ transform: 'scale(1.14)', filter: 'blur(6px)', opacity: 0 }, { opacity: 1, offset: 0.3 }, { transform: 'scale(1)', filter: 'blur(0)', opacity: 1 }], { duration: o.duration, delay: o.delay, easing: 'cubic-bezier(.16,.84,.3,1)', fill: 'backwards' })?.finished.catch(() => undefined);\n },\n },\n {\n name: 'pan-reveal',\n kind: 'enter',\n description: 'The camera pans across the element while a wipe uncovers it (`from`).',\n defaults: { from: 'left', duration: 1200 },\n run: (el: HTMLElement, o: any, ctx: EffectContext) => {\n if (ctx.reduced) return fade(el, ctx);\n const r = o.from === 'right';\n return ctx.animate(el, [{ clipPath: r ? 'inset(0 0 0 100%)' : 'inset(0 100% 0 0)', transform: `translateX(${r ? 4 : -4}%) scale(1.06)` }, { clipPath: 'inset(0 0 0 0)', transform: 'none' }], { duration: o.duration, delay: o.delay, easing: 'cubic-bezier(.65,0,.35,1)', fill: 'backwards' })?.finished.catch(() => undefined);\n },\n },\n {\n name: 'letterbox',\n kind: 'enter',\n description: 'Cinema bars slide in, hold, then open up to reveal the element (`hold`).',\n defaults: { duration: 1400, hold: 0.35 },\n run: (el: HTMLElement, o: any, ctx: EffectContext) => {\n if (ctx.reduced) return fade(el, ctx);\n const h = Math.min(0.8, Math.max(0, Number(o.hold) || 0));\n const a = 0.25;\n const b = Math.min(0.95, a + h);\n return ctx.animate(el, [{ clipPath: 'inset(50% 0 50% 0)', opacity: 0.6 }, { clipPath: 'inset(12% 0 12% 0)', opacity: 1, offset: a }, { clipPath: 'inset(12% 0 12% 0)', offset: b }, { clipPath: 'inset(0 0 0 0)' }], { duration: o.duration, delay: o.delay, easing: 'ease-in-out', fill: 'backwards' })?.finished.catch(() => undefined);\n },\n },\n {\n name: 'rack-focus',\n kind: 'attention',\n description: \"Focus pulls from the element's first child to the rest and back, like racking focus between subjects.\",\n defaults: { duration: 1800 },\n run: (el: HTMLElement, o: any, ctx: EffectContext) => {\n if (ctx.reduced) return;\n const kids = Array.from(el.children) as HTMLElement[];\n if (kids.length < 2) return ctx.animate(el, [{ filter: 'blur(0)' }, { filter: 'blur(4px)', offset: 0.5 }, { filter: 'blur(0)' }], { duration: o.duration })?.finished.catch(() => undefined);\n const [first, ...rest] = kids;\n const runs = [ctx.animate(first, [{ filter: 'blur(0)' }, { filter: 'blur(5px)', offset: 0.35 }, { filter: 'blur(5px)', offset: 0.65 }, { filter: 'blur(0)' }], { duration: o.duration, easing: 'ease-in-out' }), ...rest.map((k) => ctx.animate(k, [{ filter: 'blur(5px)' }, { filter: 'blur(0)', offset: 0.35 }, { filter: 'blur(0)', offset: 0.65 }, { filter: 'blur(5px)' }, { filter: 'blur(0)' }], { duration: o.duration, easing: 'ease-in-out' }))];\n return Promise.all(runs.map((r) => r?.finished.catch(() => undefined))).then(() => undefined);\n },\n },\n];\n\n/** Register dolly-in, pan-reveal, letterbox and rack-focus (9.1). */\nexport function registerCinemaPack(): void {\n registerEffects(CINEMA_FX);\n}\n"],"names":["registerEffects"],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ type MotionSensitivity = 'full' | 'gentle' | 'minimal' | 'static';
2
+ type Cleanup = () => void;
3
+
4
+ /**
5
+ * 5.0 — unified plugin-style effect registration. Every effect (built-in or
6
+ * yours) is a plain object registered once and played the same way:
7
+ * `playEffect(el, name)`, `bindEffect(el, name, { trigger })` or
8
+ * `<usa-fx effect="name" trigger="click">`. Effects get a context that
9
+ * already applies reduced motion, motion sensitivity, intensity and the
10
+ * animation budget.
11
+ */
12
+
13
+ declare const EFFECT_KINDS: readonly ["enter", "exit", "attention", "click", "hover", "card", "loop", "page", "background", "text", "cursor", "scroll"];
14
+ type EffectKind = (typeof EFFECT_KINDS)[number];
15
+ interface EffectContext {
16
+ /** Reduced motion applies (OS setting, `minimal` / `static` sensitivity). */
17
+ readonly reduced: boolean;
18
+ readonly sensitivity: MotionSensitivity;
19
+ /** The triggering event (pointer position for click effects), if any. */
20
+ readonly event?: Event;
21
+ /** `el.animate()` with the library's motion rules (may return `null`). */
22
+ animate(el: Element, keyframes: Keyframe[], options: KeyframeAnimationOptions): Animation | null;
23
+ /** Register teardown for long-running effects (loops, listeners). */
24
+ onCleanup(fn: Cleanup): void;
25
+ }
26
+ interface EffectDefinition<O extends Record<string, unknown> = Record<string, any>> {
27
+ /** Unique, kebab-case. */
28
+ name: string;
29
+ kind: EffectKind;
30
+ /** One line for docs and the gallery. */
31
+ description?: string;
32
+ /** Option defaults (merged under the caller's options). */
33
+ defaults?: Partial<O>;
34
+ /**
35
+ * Under reduced motion: `'skip'` (do nothing — default for loop, background
36
+ * and cursor effects) or `'run'` (run with `ctx.reduced === true`, the
37
+ * effect degrades itself — default for everything else).
38
+ */
39
+ reduced?: 'skip' | 'run';
40
+ /** Play the effect. Return an Animation / Promise to be awaited, or a cleanup. */
41
+ run(el: HTMLElement, options: O, ctx: EffectContext): void | Cleanup | Animation | null | Promise<unknown>;
42
+ }
43
+
44
+ /**
45
+ * 9.1 — Cinematic pack (`motionary/fx/cinema`, also `motionary/components/fx-cinema`):
46
+ *
47
+ * - `dolly-in` (enter) — a slow camera push: the element starts slightly
48
+ * large and soft and settles sharp, like a dolly shot (`duration`).
49
+ * - `pan-reveal` (enter) — the camera pans across the element while a
50
+ * wipe uncovers it (`from` left|right).
51
+ * - `letterbox` (enter) — cinema bars slide in, hold, then open up to
52
+ * reveal the element (`hold`).
53
+ * - `rack-focus` (attention) — focus pulls from the element's first child
54
+ * to the rest and back, like a focus puller racking between subjects.
55
+ *
56
+ * `cameraFrame(move, p)` gives the transform of a camera move at progress
57
+ * 0–1 (used by `<usa-scene>`). Reduced motion: entrances fade, rack-focus
58
+ * does nothing.
59
+ */
60
+
61
+ declare const CAMERA_MOVES: readonly ["dolly-in", "dolly-out", "pan-left", "pan-right", "tilt-up", "tilt-down", "zoom-in", "zoom-out", "orbit"];
62
+ type CameraMove = (typeof CAMERA_MOVES)[number];
63
+ /** Transform of camera `move` at progress `p` (0–1, clamped), `strength` 0–2 (9.1). */
64
+ declare function cameraFrame(move: string, p: number, strength?: number): string;
65
+ declare const CINEMA_FX: EffectDefinition[];
66
+ /** Register dolly-in, pan-reveal, letterbox and rack-focus (9.1). */
67
+ declare function registerCinemaPack(): void;
68
+
69
+ export { CAMERA_MOVES, CINEMA_FX, cameraFrame, registerCinemaPack };
70
+ export type { CameraMove };
@@ -0,0 +1,70 @@
1
+ type MotionSensitivity = 'full' | 'gentle' | 'minimal' | 'static';
2
+ type Cleanup = () => void;
3
+
4
+ /**
5
+ * 5.0 — unified plugin-style effect registration. Every effect (built-in or
6
+ * yours) is a plain object registered once and played the same way:
7
+ * `playEffect(el, name)`, `bindEffect(el, name, { trigger })` or
8
+ * `<usa-fx effect="name" trigger="click">`. Effects get a context that
9
+ * already applies reduced motion, motion sensitivity, intensity and the
10
+ * animation budget.
11
+ */
12
+
13
+ declare const EFFECT_KINDS: readonly ["enter", "exit", "attention", "click", "hover", "card", "loop", "page", "background", "text", "cursor", "scroll"];
14
+ type EffectKind = (typeof EFFECT_KINDS)[number];
15
+ interface EffectContext {
16
+ /** Reduced motion applies (OS setting, `minimal` / `static` sensitivity). */
17
+ readonly reduced: boolean;
18
+ readonly sensitivity: MotionSensitivity;
19
+ /** The triggering event (pointer position for click effects), if any. */
20
+ readonly event?: Event;
21
+ /** `el.animate()` with the library's motion rules (may return `null`). */
22
+ animate(el: Element, keyframes: Keyframe[], options: KeyframeAnimationOptions): Animation | null;
23
+ /** Register teardown for long-running effects (loops, listeners). */
24
+ onCleanup(fn: Cleanup): void;
25
+ }
26
+ interface EffectDefinition<O extends Record<string, unknown> = Record<string, any>> {
27
+ /** Unique, kebab-case. */
28
+ name: string;
29
+ kind: EffectKind;
30
+ /** One line for docs and the gallery. */
31
+ description?: string;
32
+ /** Option defaults (merged under the caller's options). */
33
+ defaults?: Partial<O>;
34
+ /**
35
+ * Under reduced motion: `'skip'` (do nothing — default for loop, background
36
+ * and cursor effects) or `'run'` (run with `ctx.reduced === true`, the
37
+ * effect degrades itself — default for everything else).
38
+ */
39
+ reduced?: 'skip' | 'run';
40
+ /** Play the effect. Return an Animation / Promise to be awaited, or a cleanup. */
41
+ run(el: HTMLElement, options: O, ctx: EffectContext): void | Cleanup | Animation | null | Promise<unknown>;
42
+ }
43
+
44
+ /**
45
+ * 9.1 — Cinematic pack (`motionary/fx/cinema`, also `motionary/components/fx-cinema`):
46
+ *
47
+ * - `dolly-in` (enter) — a slow camera push: the element starts slightly
48
+ * large and soft and settles sharp, like a dolly shot (`duration`).
49
+ * - `pan-reveal` (enter) — the camera pans across the element while a
50
+ * wipe uncovers it (`from` left|right).
51
+ * - `letterbox` (enter) — cinema bars slide in, hold, then open up to
52
+ * reveal the element (`hold`).
53
+ * - `rack-focus` (attention) — focus pulls from the element's first child
54
+ * to the rest and back, like a focus puller racking between subjects.
55
+ *
56
+ * `cameraFrame(move, p)` gives the transform of a camera move at progress
57
+ * 0–1 (used by `<usa-scene>`). Reduced motion: entrances fade, rack-focus
58
+ * does nothing.
59
+ */
60
+
61
+ declare const CAMERA_MOVES: readonly ["dolly-in", "dolly-out", "pan-left", "pan-right", "tilt-up", "tilt-down", "zoom-in", "zoom-out", "orbit"];
62
+ type CameraMove = (typeof CAMERA_MOVES)[number];
63
+ /** Transform of camera `move` at progress `p` (0–1, clamped), `strength` 0–2 (9.1). */
64
+ declare function cameraFrame(move: string, p: number, strength?: number): string;
65
+ declare const CINEMA_FX: EffectDefinition[];
66
+ /** Register dolly-in, pan-reveal, letterbox and rack-focus (9.1). */
67
+ declare function registerCinemaPack(): void;
68
+
69
+ export { CAMERA_MOVES, CINEMA_FX, cameraFrame, registerCinemaPack };
70
+ export type { CameraMove };
@@ -0,0 +1,95 @@
1
+ import { registerEffects } from '../chunks/registry-CnO7ZVPK.js';
2
+ import '../chunks/base-CLuqlLfG.js';
3
+
4
+ const CAMERA_MOVES = ['dolly-in', 'dolly-out', 'pan-left', 'pan-right', 'tilt-up', 'tilt-down', 'zoom-in', 'zoom-out', 'orbit'];
5
+ /** Transform of camera `move` at progress `p` (0–1, clamped), `strength` 0–2 (9.1). */
6
+ function cameraFrame(move, p, strength = 1) {
7
+ const t = Math.min(1, Math.max(0, p));
8
+ const k = Math.min(2, Math.max(0, strength));
9
+ const f = (n) => Math.round(n * 1000) / 1000;
10
+ switch (move) {
11
+ case 'dolly-in':
12
+ return `scale(${f(1 + 0.18 * k * t)})`;
13
+ case 'dolly-out':
14
+ return `scale(${f(1 + 0.18 * k * (1 - t))})`;
15
+ case 'pan-left':
16
+ return `scale(${f(1 + 0.12 * k)}) translateX(${f(6 * k - 12 * k * t)}%)`;
17
+ case 'pan-right':
18
+ return `scale(${f(1 + 0.12 * k)}) translateX(${f(-6 * k + 12 * k * t)}%)`;
19
+ case 'tilt-up':
20
+ return `scale(${f(1 + 0.12 * k)}) translateY(${f(-6 * k + 12 * k * t)}%)`;
21
+ case 'tilt-down':
22
+ return `scale(${f(1 + 0.12 * k)}) translateY(${f(6 * k - 12 * k * t)}%)`;
23
+ case 'zoom-in':
24
+ return `scale(${f(1 + 0.4 * k * t * t)})`;
25
+ case 'zoom-out':
26
+ return `scale(${f(1 + 0.4 * k * (1 - t) * (1 - t))})`;
27
+ case 'orbit':
28
+ return `perspective(900px) rotateY(${f(-12 * k + 24 * k * t)}deg) scale(${f(1 + 0.08 * k)})`;
29
+ default:
30
+ return 'none';
31
+ }
32
+ }
33
+ const fade = (el, ctx) => ctx.animate(el, [{ opacity: 0 }, { opacity: 1 }], { duration: 300 })?.finished.catch(() => undefined);
34
+ const CINEMA_FX = [
35
+ {
36
+ name: 'dolly-in',
37
+ kind: 'enter',
38
+ description: 'A slow camera push: starts slightly large and soft, settles sharp (`duration`).',
39
+ defaults: { duration: 1600 },
40
+ run: (el, o, ctx) => {
41
+ if (ctx.reduced)
42
+ return fade(el, ctx);
43
+ return ctx.animate(el, [{ transform: 'scale(1.14)', filter: 'blur(6px)', opacity: 0 }, { opacity: 1, offset: 0.3 }, { transform: 'scale(1)', filter: 'blur(0)', opacity: 1 }], { duration: o.duration, delay: o.delay, easing: 'cubic-bezier(.16,.84,.3,1)', fill: 'backwards' })?.finished.catch(() => undefined);
44
+ },
45
+ },
46
+ {
47
+ name: 'pan-reveal',
48
+ kind: 'enter',
49
+ description: 'The camera pans across the element while a wipe uncovers it (`from`).',
50
+ defaults: { from: 'left', duration: 1200 },
51
+ run: (el, o, ctx) => {
52
+ if (ctx.reduced)
53
+ return fade(el, ctx);
54
+ const r = o.from === 'right';
55
+ return ctx.animate(el, [{ clipPath: r ? 'inset(0 0 0 100%)' : 'inset(0 100% 0 0)', transform: `translateX(${r ? 4 : -4}%) scale(1.06)` }, { clipPath: 'inset(0 0 0 0)', transform: 'none' }], { duration: o.duration, delay: o.delay, easing: 'cubic-bezier(.65,0,.35,1)', fill: 'backwards' })?.finished.catch(() => undefined);
56
+ },
57
+ },
58
+ {
59
+ name: 'letterbox',
60
+ kind: 'enter',
61
+ description: 'Cinema bars slide in, hold, then open up to reveal the element (`hold`).',
62
+ defaults: { duration: 1400, hold: 0.35 },
63
+ run: (el, o, ctx) => {
64
+ if (ctx.reduced)
65
+ return fade(el, ctx);
66
+ const h = Math.min(0.8, Math.max(0, Number(o.hold) || 0));
67
+ const a = 0.25;
68
+ const b = Math.min(0.95, a + h);
69
+ return ctx.animate(el, [{ clipPath: 'inset(50% 0 50% 0)', opacity: 0.6 }, { clipPath: 'inset(12% 0 12% 0)', opacity: 1, offset: a }, { clipPath: 'inset(12% 0 12% 0)', offset: b }, { clipPath: 'inset(0 0 0 0)' }], { duration: o.duration, delay: o.delay, easing: 'ease-in-out', fill: 'backwards' })?.finished.catch(() => undefined);
70
+ },
71
+ },
72
+ {
73
+ name: 'rack-focus',
74
+ kind: 'attention',
75
+ description: "Focus pulls from the element's first child to the rest and back, like racking focus between subjects.",
76
+ defaults: { duration: 1800 },
77
+ run: (el, o, ctx) => {
78
+ if (ctx.reduced)
79
+ return;
80
+ const kids = Array.from(el.children);
81
+ if (kids.length < 2)
82
+ return ctx.animate(el, [{ filter: 'blur(0)' }, { filter: 'blur(4px)', offset: 0.5 }, { filter: 'blur(0)' }], { duration: o.duration })?.finished.catch(() => undefined);
83
+ const [first, ...rest] = kids;
84
+ const runs = [ctx.animate(first, [{ filter: 'blur(0)' }, { filter: 'blur(5px)', offset: 0.35 }, { filter: 'blur(5px)', offset: 0.65 }, { filter: 'blur(0)' }], { duration: o.duration, easing: 'ease-in-out' }), ...rest.map((k) => ctx.animate(k, [{ filter: 'blur(5px)' }, { filter: 'blur(0)', offset: 0.35 }, { filter: 'blur(0)', offset: 0.65 }, { filter: 'blur(5px)' }, { filter: 'blur(0)' }], { duration: o.duration, easing: 'ease-in-out' }))];
85
+ return Promise.all(runs.map((r) => r?.finished.catch(() => undefined))).then(() => undefined);
86
+ },
87
+ },
88
+ ];
89
+ /** Register dolly-in, pan-reveal, letterbox and rack-focus (9.1). */
90
+ function registerCinemaPack() {
91
+ registerEffects(CINEMA_FX);
92
+ }
93
+
94
+ export { CAMERA_MOVES, CINEMA_FX, cameraFrame, registerCinemaPack };
95
+ //# sourceMappingURL=fx-cinema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fx-cinema.js","sources":["../../src/components/fx2/cinema.ts"],"sourcesContent":["/**\n * 9.1 — Cinematic pack (`motionary/fx/cinema`, also `motionary/components/fx-cinema`):\n *\n * - `dolly-in` (enter) — a slow camera push: the element starts slightly\n * large and soft and settles sharp, like a dolly shot (`duration`).\n * - `pan-reveal` (enter) — the camera pans across the element while a\n * wipe uncovers it (`from` left|right).\n * - `letterbox` (enter) — cinema bars slide in, hold, then open up to\n * reveal the element (`hold`).\n * - `rack-focus` (attention) — focus pulls from the element's first child\n * to the rest and back, like a focus puller racking between subjects.\n *\n * `cameraFrame(move, p)` gives the transform of a camera move at progress\n * 0–1 (used by `<usa-scene>`). Reduced motion: entrances fade, rack-focus\n * does nothing.\n */\nimport type { EffectContext, EffectDefinition } from '../fx/registry';\nimport { registerEffects } from '../fx/registry';\n\nexport const CAMERA_MOVES = ['dolly-in', 'dolly-out', 'pan-left', 'pan-right', 'tilt-up', 'tilt-down', 'zoom-in', 'zoom-out', 'orbit'] as const;\nexport type CameraMove = (typeof CAMERA_MOVES)[number];\n\n/** Transform of camera `move` at progress `p` (0–1, clamped), `strength` 0–2 (9.1). */\nexport function cameraFrame(move: string, p: number, strength = 1): string {\n const t = Math.min(1, Math.max(0, p));\n const k = Math.min(2, Math.max(0, strength));\n const f = (n: number) => Math.round(n * 1000) / 1000;\n switch (move) {\n case 'dolly-in':\n return `scale(${f(1 + 0.18 * k * t)})`;\n case 'dolly-out':\n return `scale(${f(1 + 0.18 * k * (1 - t))})`;\n case 'pan-left':\n return `scale(${f(1 + 0.12 * k)}) translateX(${f(6 * k - 12 * k * t)}%)`;\n case 'pan-right':\n return `scale(${f(1 + 0.12 * k)}) translateX(${f(-6 * k + 12 * k * t)}%)`;\n case 'tilt-up':\n return `scale(${f(1 + 0.12 * k)}) translateY(${f(-6 * k + 12 * k * t)}%)`;\n case 'tilt-down':\n return `scale(${f(1 + 0.12 * k)}) translateY(${f(6 * k - 12 * k * t)}%)`;\n case 'zoom-in':\n return `scale(${f(1 + 0.4 * k * t * t)})`;\n case 'zoom-out':\n return `scale(${f(1 + 0.4 * k * (1 - t) * (1 - t))})`;\n case 'orbit':\n return `perspective(900px) rotateY(${f(-12 * k + 24 * k * t)}deg) scale(${f(1 + 0.08 * k)})`;\n default:\n return 'none';\n }\n}\n\nconst fade = (el: HTMLElement, ctx: EffectContext) => ctx.animate(el, [{ opacity: 0 }, { opacity: 1 }], { duration: 300 })?.finished.catch(() => undefined);\n\nexport const CINEMA_FX: EffectDefinition[] = [\n {\n name: 'dolly-in',\n kind: 'enter',\n description: 'A slow camera push: starts slightly large and soft, settles sharp (`duration`).',\n defaults: { duration: 1600 },\n run: (el: HTMLElement, o: any, ctx: EffectContext) => {\n if (ctx.reduced) return fade(el, ctx);\n return ctx.animate(el, [{ transform: 'scale(1.14)', filter: 'blur(6px)', opacity: 0 }, { opacity: 1, offset: 0.3 }, { transform: 'scale(1)', filter: 'blur(0)', opacity: 1 }], { duration: o.duration, delay: o.delay, easing: 'cubic-bezier(.16,.84,.3,1)', fill: 'backwards' })?.finished.catch(() => undefined);\n },\n },\n {\n name: 'pan-reveal',\n kind: 'enter',\n description: 'The camera pans across the element while a wipe uncovers it (`from`).',\n defaults: { from: 'left', duration: 1200 },\n run: (el: HTMLElement, o: any, ctx: EffectContext) => {\n if (ctx.reduced) return fade(el, ctx);\n const r = o.from === 'right';\n return ctx.animate(el, [{ clipPath: r ? 'inset(0 0 0 100%)' : 'inset(0 100% 0 0)', transform: `translateX(${r ? 4 : -4}%) scale(1.06)` }, { clipPath: 'inset(0 0 0 0)', transform: 'none' }], { duration: o.duration, delay: o.delay, easing: 'cubic-bezier(.65,0,.35,1)', fill: 'backwards' })?.finished.catch(() => undefined);\n },\n },\n {\n name: 'letterbox',\n kind: 'enter',\n description: 'Cinema bars slide in, hold, then open up to reveal the element (`hold`).',\n defaults: { duration: 1400, hold: 0.35 },\n run: (el: HTMLElement, o: any, ctx: EffectContext) => {\n if (ctx.reduced) return fade(el, ctx);\n const h = Math.min(0.8, Math.max(0, Number(o.hold) || 0));\n const a = 0.25;\n const b = Math.min(0.95, a + h);\n return ctx.animate(el, [{ clipPath: 'inset(50% 0 50% 0)', opacity: 0.6 }, { clipPath: 'inset(12% 0 12% 0)', opacity: 1, offset: a }, { clipPath: 'inset(12% 0 12% 0)', offset: b }, { clipPath: 'inset(0 0 0 0)' }], { duration: o.duration, delay: o.delay, easing: 'ease-in-out', fill: 'backwards' })?.finished.catch(() => undefined);\n },\n },\n {\n name: 'rack-focus',\n kind: 'attention',\n description: \"Focus pulls from the element's first child to the rest and back, like racking focus between subjects.\",\n defaults: { duration: 1800 },\n run: (el: HTMLElement, o: any, ctx: EffectContext) => {\n if (ctx.reduced) return;\n const kids = Array.from(el.children) as HTMLElement[];\n if (kids.length < 2) return ctx.animate(el, [{ filter: 'blur(0)' }, { filter: 'blur(4px)', offset: 0.5 }, { filter: 'blur(0)' }], { duration: o.duration })?.finished.catch(() => undefined);\n const [first, ...rest] = kids;\n const runs = [ctx.animate(first, [{ filter: 'blur(0)' }, { filter: 'blur(5px)', offset: 0.35 }, { filter: 'blur(5px)', offset: 0.65 }, { filter: 'blur(0)' }], { duration: o.duration, easing: 'ease-in-out' }), ...rest.map((k) => ctx.animate(k, [{ filter: 'blur(5px)' }, { filter: 'blur(0)', offset: 0.35 }, { filter: 'blur(0)', offset: 0.65 }, { filter: 'blur(5px)' }, { filter: 'blur(0)' }], { duration: o.duration, easing: 'ease-in-out' }))];\n return Promise.all(runs.map((r) => r?.finished.catch(() => undefined))).then(() => undefined);\n },\n },\n];\n\n/** Register dolly-in, pan-reveal, letterbox and rack-focus (9.1). */\nexport function registerCinemaPack(): void {\n registerEffects(CINEMA_FX);\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,216 @@
1
+ 'use strict';
2
+
3
+ var registry = require('../chunks/registry-BVklOepd.cjs');
4
+ require('../chunks/base-DoRUZBy-.cjs');
5
+
6
+ const arr = (v) => (Array.isArray(v) ? v.map(Number) : [Number(v)]);
7
+ /** Frames (t) → values for one transform property (static props give one key at t = ip) (9.2). */
8
+ function track(p, ip) {
9
+ if (!p)
10
+ return [];
11
+ if (!p.a || !Array.isArray(p.k) || typeof p.k[0] !== 'object')
12
+ return [{ t: ip, v: arr(p.k) }];
13
+ return p.k.filter((k) => k && k.s != null).map((k) => ({ t: Number(k.t), v: arr(k.s) }));
14
+ }
15
+ const at = (tr, t) => {
16
+ if (!tr.length)
17
+ return undefined;
18
+ if (t <= tr[0].t)
19
+ return tr[0].v;
20
+ for (let i = 1; i < tr.length; i++)
21
+ if (t <= tr[i].t) {
22
+ const a = tr[i - 1];
23
+ const b = tr[i];
24
+ const u = b.t === a.t ? 1 : (t - a.t) / (b.t - a.t);
25
+ return a.v.map((x, j) => x + ((b.v[j] ?? x) - x) * u);
26
+ }
27
+ return tr[tr.length - 1].v;
28
+ };
29
+ const r2 = (n) => Math.round(n * 100) / 100;
30
+ /** Lottie JSON → WAAPI keyframes per layer + duration (ms) (9.2). */
31
+ function lottieToKeyframes(json) {
32
+ const d = typeof json === 'string' ? JSON.parse(json) : json;
33
+ const fr = Number(d?.fr) || 30;
34
+ const ip = Number(d?.ip) || 0;
35
+ const op = Number(d?.op) || ip + fr;
36
+ const span = Math.max(1, op - ip);
37
+ const layers = (Array.isArray(d?.layers) ? d.layers : []).map((L, index) => {
38
+ const ks = L?.ks || {};
39
+ const tracks = { p: track(ks.p, ip), s: track(ks.s, ip), r: track(ks.r, ip), o: track(ks.o, ip) };
40
+ const anchor = arr(ks.a?.k ?? [0, 0]).slice(0, 2) || [0, 0];
41
+ const times = Array.from(new Set([ip, op, ...Object.values(tracks).flat().map((k) => k.t)])).filter((t) => t >= ip && t <= op).sort((a, b) => a - b);
42
+ const keyframes = times.map((t) => {
43
+ const p = at(tracks.p, t);
44
+ const s = at(tracks.s, t);
45
+ const r = at(tracks.r, t);
46
+ const o = at(tracks.o, t);
47
+ // Lottie order: move the anchor to the position, rotate + scale around the anchor
48
+ const pp = p || anchor;
49
+ const tf = [`translate(${r2(pp[0])}px, ${r2(pp[1] ?? 0)}px)`];
50
+ if (r)
51
+ tf.push(`rotate(${r2(r[0])}deg)`);
52
+ if (s)
53
+ tf.push(`scale(${r2(s[0] / 100)}, ${r2((s[1] ?? s[0]) / 100)})`);
54
+ tf.push(`translate(${r2(-anchor[0])}px, ${r2(-anchor[1])}px)`);
55
+ const k = { offset: r2((t - ip) / span), transform: tf.join(' ') };
56
+ if (o)
57
+ k.opacity = r2(o[0] / 100);
58
+ return k;
59
+ });
60
+ return { name: String(L?.nm ?? `layer ${index + 1}`), index, keyframes, anchor };
61
+ });
62
+ return { width: Number(d?.w) || 100, height: Number(d?.h) || 100, duration: Math.round((span / fr) * 1000), layers };
63
+ }
64
+ const hex = (c) => {
65
+ const v = arr(c?.k ?? c).slice(0, 3).map((x) => Math.round(Math.min(1, Math.max(0, x)) * 255));
66
+ return `#${v.map((x) => x.toString(16).padStart(2, '0')).join('')}`;
67
+ };
68
+ function shapes(items, fill, stroke, sw) {
69
+ let f = fill;
70
+ let s = stroke;
71
+ let w = sw;
72
+ for (const it of items) {
73
+ if (it?.ty === 'fl')
74
+ f = hex(it.c);
75
+ if (it?.ty === 'st') {
76
+ s = hex(it.c);
77
+ w = Number(it.w?.k) || 2;
78
+ }
79
+ }
80
+ const paint = `fill="${f}"${s !== 'none' ? ` stroke="${s}" stroke-width="${w}"` : ''}`;
81
+ return items
82
+ .map((it) => {
83
+ if (it?.ty === 'gr')
84
+ return `<g>${shapes(it.it || [], f, s, w)}</g>`;
85
+ if (it?.ty === 'el') {
86
+ const [cx, cy] = arr(it.p?.k ?? [0, 0]);
87
+ const [sx, sy] = arr(it.s?.k ?? [10, 10]);
88
+ return `<ellipse cx="${cx}" cy="${cy}" rx="${sx / 2}" ry="${(sy ?? sx) / 2}" ${paint}/>`;
89
+ }
90
+ if (it?.ty === 'rc') {
91
+ const [cx, cy] = arr(it.p?.k ?? [0, 0]);
92
+ const [sx, sy] = arr(it.s?.k ?? [10, 10]);
93
+ return `<rect x="${cx - sx / 2}" y="${cy - sy / 2}" width="${sx}" height="${sy}" rx="${Number(it.r?.k) || 0}" ${paint}/>`;
94
+ }
95
+ if (it?.ty === 'sh') {
96
+ const k = it.ks?.k;
97
+ const v = k?.v || [];
98
+ if (!v.length)
99
+ return '';
100
+ const i = k.i || [];
101
+ const o = k.o || [];
102
+ let dd = `M${v[0][0]} ${v[0][1]}`;
103
+ for (let n = 1; n < v.length + (k.c ? 1 : 0); n++) {
104
+ const a = v[n - 1];
105
+ const b = v[n % v.length];
106
+ const c1 = [a[0] + (o[n - 1]?.[0] || 0), a[1] + (o[n - 1]?.[1] || 0)];
107
+ const c2 = [b[0] + (i[n % v.length]?.[0] || 0), b[1] + (i[n % v.length]?.[1] || 0)];
108
+ dd += ` C${c1[0]} ${c1[1]} ${c2[0]} ${c2[1]} ${b[0]} ${b[1]}`;
109
+ }
110
+ return `<path d="${dd}${k.c ? 'Z' : ''}" ${paint}/>`;
111
+ }
112
+ return '';
113
+ })
114
+ .join('');
115
+ }
116
+ /** Render the simple vector layers of a Lottie JSON as an SVG string (one `<g data-layer>` per layer, top layer last) (9.2). */
117
+ function lottieToSvg(json) {
118
+ const d = typeof json === 'string' ? JSON.parse(json) : json;
119
+ const w = Number(d?.w) || 100;
120
+ const h = Number(d?.h) || 100;
121
+ const ls = Array.isArray(d?.layers) ? d.layers : [];
122
+ const groups = ls
123
+ .map((L, i) => ({ L, i }))
124
+ .reverse()
125
+ .map(({ L, i }) => `<g data-layer="${i}"><g class="usa-lt-inner">${shapes(L?.shapes || [], '#000', 'none', 0)}</g></g>`)
126
+ .join('');
127
+ return `<svg viewBox="0 0 ${w} ${h}" width="${w}" height="${h}" aria-hidden="true">${groups}</svg>`;
128
+ }
129
+ /** Wire hover / press / click / enter on `el` to a Rive state machine's inputs: map { hover: 'isHover', click: 'fire' } (9.2). */
130
+ function riveInputs(instance, stateMachine, el, map) {
131
+ const inputs = (instance.stateMachineInputs(stateMachine) || []);
132
+ const get = (n) => inputs.find((i) => i.name === n);
133
+ const set = (n, v) => {
134
+ const i = get(n);
135
+ if (!i)
136
+ return;
137
+ // Rive StateMachineInputType: 58 = trigger (fire on true), 59 = boolean
138
+ if (i.type === 58 && typeof i.fire === 'function') {
139
+ if (v)
140
+ i.fire();
141
+ }
142
+ else
143
+ i.value = v;
144
+ };
145
+ const offs = [];
146
+ const on = (t, fn) => {
147
+ el.addEventListener(t, fn);
148
+ offs.push(() => el.removeEventListener(t, fn));
149
+ };
150
+ if (map.hover)
151
+ (on('pointerenter', () => set(map.hover, true)), on('pointerleave', () => set(map.hover, false)));
152
+ if (map.press)
153
+ (on('pointerdown', () => set(map.press, true)), on('pointerup', () => set(map.press, false)));
154
+ if (map.click)
155
+ on('click', () => set(map.click, true));
156
+ if (map.enter && typeof IntersectionObserver !== 'undefined') {
157
+ const io = new IntersectionObserver((es) => es.forEach((e) => set(map.enter, e.isIntersecting)));
158
+ io.observe(el);
159
+ offs.push(() => io.disconnect());
160
+ }
161
+ return () => offs.splice(0).forEach((f) => f());
162
+ }
163
+ const LOTTIE_FX = [
164
+ {
165
+ name: 'lottie-play',
166
+ kind: 'attention',
167
+ description: 'Replays the Lottie keyframes stored on an element by <usa-lottie> (or a `json` option) once.',
168
+ defaults: {},
169
+ run: (el, o, ctx) => {
170
+ if (ctx.reduced)
171
+ return;
172
+ const host = el.closest('usa-lottie');
173
+ if (host?.play)
174
+ return void host.play();
175
+ if (!o.json)
176
+ return;
177
+ const m = lottieToKeyframes(o.json);
178
+ return Promise.all(m.layers.map((l) => ctx.animate(el, l.keyframes, { duration: m.duration })?.finished.catch(() => undefined))).then(() => undefined);
179
+ },
180
+ },
181
+ {
182
+ name: 'icon-pop',
183
+ kind: 'click',
184
+ description: 'A sticker-like pop with a ring burst, for icons (`color`).',
185
+ defaults: { color: '#f43f5e', duration: 500 },
186
+ run: (el, o, ctx) => {
187
+ if (ctx.reduced)
188
+ return;
189
+ if (getComputedStyle(el).position === 'static') {
190
+ const prev = el.style.position;
191
+ el.style.position = 'relative';
192
+ ctx.onCleanup(() => (el.style.position = prev));
193
+ }
194
+ const ring = document.createElement('span');
195
+ ring.setAttribute('aria-hidden', 'true');
196
+ Object.assign(ring.style, { position: 'absolute', inset: '0', borderRadius: '50%', border: `2px solid ${o.color}`, pointerEvents: 'none' });
197
+ el.appendChild(ring);
198
+ ctx.onCleanup(() => ring.remove());
199
+ const a = ctx.animate(el, [{ transform: 'scale(1)' }, { transform: 'scale(.8)', offset: 0.2 }, { transform: 'scale(1.2)', offset: 0.55 }, { transform: 'scale(1)' }], { duration: o.duration, easing: 'cubic-bezier(.3,1.5,.5,1)' });
200
+ const b = ctx.animate(ring, [{ transform: 'scale(.6)', opacity: 1 }, { transform: 'scale(1.8)', opacity: 0 }], { duration: o.duration, easing: 'ease-out' });
201
+ const end = () => ring.remove();
202
+ return Promise.all([a?.finished.catch(() => undefined), b?.finished.catch(() => undefined)]).then(end, end);
203
+ },
204
+ },
205
+ ];
206
+ /** Register lottie-play and icon-pop (9.2). */
207
+ function registerLottiePack() {
208
+ registry.registerEffects(LOTTIE_FX);
209
+ }
210
+
211
+ exports.LOTTIE_FX = LOTTIE_FX;
212
+ exports.lottieToKeyframes = lottieToKeyframes;
213
+ exports.lottieToSvg = lottieToSvg;
214
+ exports.registerLottiePack = registerLottiePack;
215
+ exports.riveInputs = riveInputs;
216
+ //# sourceMappingURL=fx-lottie.cjs.map