motionary 7.0.0 → 7.1.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 +14 -0
- package/dist/chunks/audio-DcPvT2Kh.js +333 -0
- package/dist/chunks/audio-DcPvT2Kh.js.map +1 -0
- package/dist/chunks/audio-EXUoijsG.cjs +342 -0
- package/dist/chunks/audio-EXUoijsG.cjs.map +1 -0
- package/dist/chunks/{base-DchG4q_S.js → base-2-yYc93C.js} +2 -2
- package/dist/chunks/{base-DchG4q_S.js.map → base-2-yYc93C.js.map} +1 -1
- package/dist/chunks/{core-DVyTlo9Q.js → core-D5rU0CV6.js} +2 -2
- package/dist/chunks/{core-DVyTlo9Q.js.map → core-D5rU0CV6.js.map} +1 -1
- package/dist/chunks/{core-D2vF8kZb.js → core-DuO-AVXL.js} +2 -2
- package/dist/chunks/{core-D2vF8kZb.js.map → core-DuO-AVXL.js.map} +1 -1
- package/dist/chunks/{fx-DUMVKSvg.js → fx-CMxWNwH8.js} +2 -2
- package/dist/chunks/{fx-DUMVKSvg.js.map → fx-CMxWNwH8.js.map} +1 -1
- package/dist/chunks/{gpu-Bkw605Ds.js → gpu-DLPghVWr.js} +2 -2
- package/dist/chunks/{gpu-Bkw605Ds.js.map → gpu-DLPghVWr.js.map} +1 -1
- package/dist/chunks/{player-C-TwEEy6.js → player-DxvCYo7Q.js} +4 -4
- package/dist/chunks/{player-C-TwEEy6.js.map → player-DxvCYo7Q.js.map} +1 -1
- package/dist/chunks/{registry-D23neB4M.js → registry-CyKExAmE.js} +2 -2
- package/dist/chunks/{registry-D23neB4M.js.map → registry-CyKExAmE.js.map} +1 -1
- package/dist/chunks/{spring-BhoT09Qb.js → spring-BK8DiezC.js} +2 -2
- package/dist/chunks/{spring-BhoT09Qb.js.map → spring-BK8DiezC.js.map} +1 -1
- package/dist/chunks/{variants-C_hv_s23.js → variants-BQ6bhzn4.js} +2 -2
- package/dist/chunks/{variants-C_hv_s23.js.map → variants-BQ6bhzn4.js.map} +1 -1
- package/dist/components/a11y.js +2 -2
- package/dist/components/angular.js +7 -7
- package/dist/components/background.js +2 -2
- package/dist/components/bridge.js +1 -1
- package/dist/components/cards.js +2 -2
- package/dist/components/click.js +3 -3
- package/dist/components/depth.js +3 -3
- package/dist/components/effects.cjs +11 -336
- package/dist/components/effects.cjs.map +1 -1
- package/dist/components/effects.js +9 -333
- package/dist/components/effects.js.map +1 -1
- package/dist/components/feedback.js +1 -1
- package/dist/components/fx-3d.js +2 -2
- package/dist/components/fx-focus.js +2 -2
- package/dist/components/fx-gpu.js +3 -3
- package/dist/components/fx-light.js +2 -2
- package/dist/components/fx-morph.js +2 -2
- package/dist/components/fx-music.cjs +179 -0
- package/dist/components/fx-music.cjs.map +1 -0
- package/dist/components/fx-music.d.cts +102 -0
- package/dist/components/fx-music.d.ts +102 -0
- package/dist/components/fx-music.js +174 -0
- package/dist/components/fx-music.js.map +1 -0
- package/dist/components/fx-physics.js +2 -2
- package/dist/components/fx-text.js +2 -2
- package/dist/components/fx-transitions.js +3 -3
- package/dist/components/fx-weather.js +2 -2
- package/dist/components/fx.js +5 -5
- package/dist/components/fx2.cjs +8 -0
- package/dist/components/fx2.cjs.map +1 -1
- package/dist/components/fx2.d.cts +59 -1
- package/dist/components/fx2.d.ts +59 -1
- package/dist/components/fx2.js +10 -5
- package/dist/components/fx2.js.map +1 -1
- package/dist/components/gesture.js +4 -4
- package/dist/components/interaction.js +1 -1
- package/dist/components/layout.js +1 -1
- package/dist/components/marketplace.js +2 -2
- package/dist/components/packs.js +1 -1
- package/dist/components/page.js +3 -3
- package/dist/components/perf.js +2 -2
- package/dist/components/physics.js +3 -3
- package/dist/components/reveal.js +1 -1
- package/dist/components/solid.js +7 -7
- package/dist/components/svelte.js +7 -7
- package/dist/components/svg.js +1 -1
- package/dist/components/text.js +2 -2
- package/dist/components/timeline.js +3 -3
- package/dist/components/transitions.js +1 -1
- package/dist/components/ui.js +4 -4
- package/dist/components/vue.js +7 -7
- package/dist/components/webgl.js +1 -1
- package/dist/components/widgets.cjs +542 -61
- package/dist/components/widgets.cjs.map +1 -1
- package/dist/components/widgets.d.cts +79 -2
- package/dist/components/widgets.d.ts +79 -2
- package/dist/components/widgets.js +542 -67
- package/dist/components/widgets.js.map +1 -1
- package/dist/components.js +9 -9
- package/dist/index.js +2 -2
- package/dist/widgets.umd.js +1 -1
- package/dist/widgets.umd.js.map +1 -1
- package/docs/ROADMAP.md +1 -1
- package/docs/components.md +25 -0
- package/package.json +21 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [7.1.0] - 2026-10-08
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **4 new components (7.1)** in `motionary/components/widgets` (also in `dist/widgets.umd.js`; the existing `<usa-audio>`, `<usa-beat>` and `<usa-player>` are unchanged):
|
|
14
|
+
- `<usa-music-player>` — music player card: the cover spins like a record while playing, play ↔ pause, dancing mini equalizer bars, scrubbable progress slider (← / → ±5 s); plays a child `<audio>` / `src` or simulates `duration`; `play()`, `pause()`, `toggle()`, `seek()`; `usa:play`, `usa:pause`, `usa:seek`, `usa:prev`, `usa:next`.
|
|
15
|
+
- `<usa-volume-knob>` — rotary knob (`role="slider"`): drag, wheel or keys; value arc + LED tick ring; the cap springs to the angle; `usa:input` / `usa:change`.
|
|
16
|
+
- `<usa-equalizer>` — graphic EQ: one vertical slider per band with springy caps and a smooth response curve; presets `flat | bass | vocal | rock | electronic` glide every band (`applyPreset()`); `values`; `usa:change`. `EQ_PRESETS`.
|
|
17
|
+
- `<usa-lyrics>` — synced karaoke lyrics from LRC or `[data-t]` lines: the active line glows, centres and fills word by word, past lines dim; follows `for` (`<audio>`, `<video>`, `<usa-music-player>`); click to `usa:seek`. `parseLRC()`.
|
|
18
|
+
- **Music visualization — `motionary/fx/music`** (= `motionary/components/fx-music`, `registerMusicPack()`, also in `registerEffectPacks()`): `waveform-scope`, `radial-spectrum`, `spectrum-mirror`, `sound-particles` (Canvas 2D backgrounds) and `beat-bounce`, `vinyl-spin` (loops). They read the live analyser (`enableAudio()` / `<usa-audio>`) or a synthetic signal (`syntheticSample()`, `musicSample()`).
|
|
19
|
+
- Showcase: 7 new gallery cards with copyable code (the lyrics card follows a demo player); Animation Store 285 → 292 items.
|
|
20
|
+
|
|
21
|
+
### Accessibility
|
|
22
|
+
- The player is a labelled group with a `slider` for progress and an `aria-pressed` play button; the knob and every EQ band are `slider`s with `aria-valuetext`; the lyrics region marks the current line with `aria-current`. Reduced motion: no spin, dancing bars, cap spring, glide, sweep or smooth scroll; visual backgrounds draw one static frame and the loop effects do nothing.
|
|
23
|
+
|
|
10
24
|
## [7.0.0] - 2026-10-08
|
|
11
25
|
|
|
12
26
|
### ⚠️ Breaking — removed (deprecated in 6.9; `npx usa-codemod-7 --write src`)
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { playEffect } from './registry-CyKExAmE.js';
|
|
2
|
+
import { u as defineElement, p as prefersReducedMotion } from './base-2-yYc93C.js';
|
|
3
|
+
import { c as canvasBackground, h as hexRgb } from './generative-2LhxG5BJ.js';
|
|
4
|
+
import { P as PALETTE } from './shared-CkKHWrtJ.js';
|
|
5
|
+
|
|
6
|
+
let actx = null;
|
|
7
|
+
let current = null;
|
|
8
|
+
const mediaSources = new WeakMap();
|
|
9
|
+
/** The running analyser, if `enableAudio()` was called. */
|
|
10
|
+
const getAudio = () => current;
|
|
11
|
+
function audioContext() {
|
|
12
|
+
const AC = globalThis.AudioContext || globalThis.webkitAudioContext;
|
|
13
|
+
if (!AC)
|
|
14
|
+
throw new Error('[motionary] Web Audio is not available');
|
|
15
|
+
if (!actx || actx.state === 'closed')
|
|
16
|
+
actx = new AC();
|
|
17
|
+
return actx;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Start analysing `input` and make it the source of every sound-reactive
|
|
21
|
+
* effect. Call from a user gesture. Replaces a previous source.
|
|
22
|
+
*/
|
|
23
|
+
async function enableAudio(input = 'mic', opts = {}) {
|
|
24
|
+
current?.stop();
|
|
25
|
+
const ac = audioContext();
|
|
26
|
+
if (ac.state === 'suspended')
|
|
27
|
+
await ac.resume().catch(() => undefined);
|
|
28
|
+
const analyser = ac.createAnalyser();
|
|
29
|
+
analyser.fftSize = opts.fftSize || 512;
|
|
30
|
+
analyser.smoothingTimeConstant = opts.smoothing ?? 0.8;
|
|
31
|
+
let src;
|
|
32
|
+
let release = () => { };
|
|
33
|
+
const media = typeof input === 'string' && input !== 'mic' ? document.querySelector(input) : input;
|
|
34
|
+
if (media === 'mic') {
|
|
35
|
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
36
|
+
src = ac.createMediaStreamSource(stream);
|
|
37
|
+
src.connect(analyser); // never to the speakers: no feedback
|
|
38
|
+
release = () => stream.getTracks().forEach((t) => t.stop());
|
|
39
|
+
}
|
|
40
|
+
else if (media && typeof media.play === 'function') {
|
|
41
|
+
const m = media;
|
|
42
|
+
let node = mediaSources.get(m);
|
|
43
|
+
if (!node)
|
|
44
|
+
mediaSources.set(m, (node = ac.createMediaElementSource(m)));
|
|
45
|
+
try {
|
|
46
|
+
node.disconnect();
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
/* not connected */
|
|
50
|
+
}
|
|
51
|
+
src = node;
|
|
52
|
+
src.connect(analyser);
|
|
53
|
+
analyser.connect(ac.destination);
|
|
54
|
+
release = () => {
|
|
55
|
+
try {
|
|
56
|
+
node.disconnect();
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
/* already */
|
|
60
|
+
}
|
|
61
|
+
node.connect(ac.destination); // keep the media audible
|
|
62
|
+
};
|
|
63
|
+
if (m.paused)
|
|
64
|
+
await m.play()?.catch?.(() => undefined);
|
|
65
|
+
}
|
|
66
|
+
else if (media && typeof media.getTracks === 'function') {
|
|
67
|
+
src = ac.createMediaStreamSource(media);
|
|
68
|
+
src.connect(analyser);
|
|
69
|
+
}
|
|
70
|
+
else
|
|
71
|
+
throw new Error(`[motionary] enableAudio: no audio source for ${String(input)}`);
|
|
72
|
+
const freq = new Uint8Array(analyser.frequencyBinCount);
|
|
73
|
+
const wave = new Uint8Array(analyser.fftSize);
|
|
74
|
+
const self = {
|
|
75
|
+
context: ac,
|
|
76
|
+
analyser,
|
|
77
|
+
sample: () => {
|
|
78
|
+
analyser.getByteFrequencyData(freq);
|
|
79
|
+
analyser.getByteTimeDomainData(wave);
|
|
80
|
+
let sq = 0;
|
|
81
|
+
for (let i = 0; i < wave.length; i++)
|
|
82
|
+
sq += ((wave[i] - 128) / 128) ** 2;
|
|
83
|
+
const n = Math.max(1, Math.round(freq.length * 0.08));
|
|
84
|
+
let b = 0;
|
|
85
|
+
for (let i = 0; i < n; i++)
|
|
86
|
+
b += freq[i];
|
|
87
|
+
return { level: Math.min(1, Math.sqrt(sq / wave.length) * 2), bass: b / n / 255, freq, wave };
|
|
88
|
+
},
|
|
89
|
+
stop: () => {
|
|
90
|
+
if (current === self) {
|
|
91
|
+
current = null;
|
|
92
|
+
if (raf && typeof cancelAnimationFrame === 'function')
|
|
93
|
+
cancelAnimationFrame(raf);
|
|
94
|
+
raf = 0;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
src.disconnect();
|
|
98
|
+
analyser.disconnect();
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
/* already */
|
|
102
|
+
}
|
|
103
|
+
release();
|
|
104
|
+
setVars(0, 0);
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
current = self;
|
|
108
|
+
kick();
|
|
109
|
+
return self;
|
|
110
|
+
}
|
|
111
|
+
/** Stop the current audio source (if any). */
|
|
112
|
+
function disableAudio() {
|
|
113
|
+
current?.stop();
|
|
114
|
+
}
|
|
115
|
+
/** A pure beat detector: feed it energy (0–1) and a timestamp per frame; it answers "beat?". */
|
|
116
|
+
function createBeatDetector(o = {}) {
|
|
117
|
+
const { threshold = 1.35, cooldown = 250, history = 43, floor = 0.08 } = o;
|
|
118
|
+
const hist = [];
|
|
119
|
+
let last = -Infinity;
|
|
120
|
+
return (energy, now) => {
|
|
121
|
+
const avg = hist.length ? hist.reduce((a, b) => a + b, 0) / hist.length : energy;
|
|
122
|
+
const ready = hist.length >= 8;
|
|
123
|
+
hist.push(energy);
|
|
124
|
+
if (hist.length > history)
|
|
125
|
+
hist.shift();
|
|
126
|
+
if (ready && energy > floor && energy > avg * threshold && now - last >= cooldown) {
|
|
127
|
+
last = now;
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
return false;
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const listeners = new Set();
|
|
134
|
+
let raf = 0;
|
|
135
|
+
function setVars(level, bass) {
|
|
136
|
+
if (typeof document === 'undefined')
|
|
137
|
+
return;
|
|
138
|
+
const s = document.documentElement.style;
|
|
139
|
+
s.setProperty('--usa-audio-level', level.toFixed(3));
|
|
140
|
+
s.setProperty('--usa-audio-bass', bass.toFixed(3));
|
|
141
|
+
}
|
|
142
|
+
function loop(now) {
|
|
143
|
+
raf = 0;
|
|
144
|
+
if (!current)
|
|
145
|
+
return;
|
|
146
|
+
const { level, bass } = current.sample();
|
|
147
|
+
const reduced = prefersReducedMotion();
|
|
148
|
+
setVars(reduced ? 0 : level, reduced ? 0 : bass);
|
|
149
|
+
for (const l of Array.from(listeners))
|
|
150
|
+
if (l.detect(bass, now))
|
|
151
|
+
l.cb({ energy: bass, time: now });
|
|
152
|
+
kick();
|
|
153
|
+
}
|
|
154
|
+
function kick() {
|
|
155
|
+
if (!raf && current && typeof requestAnimationFrame === 'function')
|
|
156
|
+
raf = requestAnimationFrame(loop);
|
|
157
|
+
}
|
|
158
|
+
/** Call `cb` on every detected beat of the current audio source. Returns an unsubscribe. */
|
|
159
|
+
function onBeat(cb, o = {}) {
|
|
160
|
+
const l = { detect: createBeatDetector(o), cb };
|
|
161
|
+
listeners.add(l);
|
|
162
|
+
kick();
|
|
163
|
+
return () => void listeners.delete(l);
|
|
164
|
+
}
|
|
165
|
+
/** Play the registered effect `name` on `el` at every beat (not under reduced motion). Returns an unbind. */
|
|
166
|
+
function bindBeat(el, name, options = {}) {
|
|
167
|
+
const { threshold, cooldown, history, floor, ...fx } = options;
|
|
168
|
+
return onBeat(() => {
|
|
169
|
+
if (!prefersReducedMotion())
|
|
170
|
+
playEffect(el, name, fx).catch(() => undefined);
|
|
171
|
+
}, { threshold, cooldown, history, floor });
|
|
172
|
+
}
|
|
173
|
+
// --- visual effects ----------------------------------------------------------
|
|
174
|
+
/** The current sample, or a gentle synthetic one while no audio is enabled. */
|
|
175
|
+
function read(t, bins) {
|
|
176
|
+
if (current)
|
|
177
|
+
return { ...current.sample(), idle: false };
|
|
178
|
+
const freq = new Uint8Array(bins);
|
|
179
|
+
const wave = new Uint8Array(bins * 2);
|
|
180
|
+
for (let i = 0; i < bins; i++)
|
|
181
|
+
freq[i] = 70 + 50 * Math.sin(t * 2 + i * 0.35) * Math.cos(t * 0.7 + i * 0.11) * (1 - i / bins);
|
|
182
|
+
for (let i = 0; i < wave.length; i++)
|
|
183
|
+
wave[i] = 128 + 22 * Math.sin(t * 3 + i * 0.12);
|
|
184
|
+
return { level: 0.25 + 0.1 * Math.sin(t * 2), bass: 0.35 + 0.2 * Math.sin(t * 2.4), freq, wave, idle: true };
|
|
185
|
+
}
|
|
186
|
+
const audioFx = (name, description, defaults, spec) => ({
|
|
187
|
+
name,
|
|
188
|
+
kind: 'background',
|
|
189
|
+
description,
|
|
190
|
+
reduced: 'skip',
|
|
191
|
+
defaults: { colors: PALETTE, background: '#0b0d12', speed: 1, quality: 1, ...defaults },
|
|
192
|
+
run: (el, o, ctx) => canvasBackground(el, ctx, spec, o),
|
|
193
|
+
});
|
|
194
|
+
const AUDIO_FX = [
|
|
195
|
+
audioFx('spectrum-bars', 'Frequency bars dance to the audio (mirror them with `mirror: true`).', { bars: 48, gap: 2, mirror: false }, {
|
|
196
|
+
draw: ({ ctx, w, h, t, o }) => {
|
|
197
|
+
ctx.fillStyle = o.background;
|
|
198
|
+
ctx.fillRect(0, 0, w, h);
|
|
199
|
+
const s = read(t, o.bars);
|
|
200
|
+
const per = Math.max(1, Math.floor((s.freq.length * 0.7) / o.bars));
|
|
201
|
+
const bw = w / o.bars;
|
|
202
|
+
for (let i = 0; i < o.bars; i++) {
|
|
203
|
+
let v = 0;
|
|
204
|
+
for (let k = 0; k < per; k++)
|
|
205
|
+
v += s.freq[Math.min(s.freq.length - 1, i * per + k)];
|
|
206
|
+
const bh = (v / per / 255) * h * (o.mirror ? 0.5 : 0.9);
|
|
207
|
+
ctx.fillStyle = o.colors[i % o.colors.length];
|
|
208
|
+
ctx.fillRect(i * bw + o.gap / 2, o.mirror ? h / 2 - bh : h - bh, Math.max(1, bw - o.gap), o.mirror ? bh * 2 : bh);
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
}),
|
|
212
|
+
audioFx('pulse-ring', 'Glowing rings pulse with the bass.', { rings: 3, color: '#7c5cff' }, {
|
|
213
|
+
draw: ({ ctx, w, h, t, o }) => {
|
|
214
|
+
ctx.fillStyle = o.background;
|
|
215
|
+
ctx.fillRect(0, 0, w, h);
|
|
216
|
+
const s = read(t, 32);
|
|
217
|
+
const [r, g, b] = hexRgb(o.color);
|
|
218
|
+
const base = Math.min(w, h) * 0.18;
|
|
219
|
+
for (let i = 0; i < o.rings; i++) {
|
|
220
|
+
const rad = base * (1 + i * 0.55) * (1 + s.bass * 0.6);
|
|
221
|
+
ctx.strokeStyle = `rgba(${r},${g},${b},${(0.9 - i * 0.25) * (0.4 + s.level)})`;
|
|
222
|
+
ctx.lineWidth = 3 + s.bass * 10 - i;
|
|
223
|
+
ctx.beginPath();
|
|
224
|
+
ctx.arc(w / 2, h / 2, rad, 0, Math.PI * 2);
|
|
225
|
+
ctx.stroke();
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
}),
|
|
229
|
+
audioFx('wave-ring', 'The live waveform wrapped into a circle.', { color: '#22d3ee', amplitude: 0.35 }, {
|
|
230
|
+
draw: ({ ctx, w, h, t, o }) => {
|
|
231
|
+
ctx.fillStyle = o.background;
|
|
232
|
+
ctx.fillRect(0, 0, w, h);
|
|
233
|
+
const s = read(t, 64);
|
|
234
|
+
const n = s.wave.length;
|
|
235
|
+
const base = Math.min(w, h) * 0.28;
|
|
236
|
+
ctx.strokeStyle = o.color;
|
|
237
|
+
ctx.lineWidth = 2;
|
|
238
|
+
ctx.beginPath();
|
|
239
|
+
for (let i = 0; i <= n; i++) {
|
|
240
|
+
const a = (i / n) * Math.PI * 2;
|
|
241
|
+
const rad = base * (1 + ((s.wave[i % n] - 128) / 128) * o.amplitude * 2);
|
|
242
|
+
const x = w / 2 + Math.cos(a) * rad;
|
|
243
|
+
const y = h / 2 + Math.sin(a) * rad;
|
|
244
|
+
if (i)
|
|
245
|
+
ctx.lineTo(x, y);
|
|
246
|
+
else
|
|
247
|
+
ctx.moveTo(x, y);
|
|
248
|
+
}
|
|
249
|
+
ctx.closePath();
|
|
250
|
+
ctx.stroke();
|
|
251
|
+
},
|
|
252
|
+
}),
|
|
253
|
+
];
|
|
254
|
+
/**
|
|
255
|
+
* `<usa-audio source="#track | mic" label="…">` — a toggle button (yours, as
|
|
256
|
+
* `[data-audio-toggle]`, or one it renders) that enables the audio source on
|
|
257
|
+
* click; children with `data-usa-beat="effect"` play that effect on every
|
|
258
|
+
* beat (`data-usa-beat-options` JSON; `threshold` / `cooldown` attributes).
|
|
259
|
+
* Emits `usa-beat` and `usa-audio-error`.
|
|
260
|
+
*/
|
|
261
|
+
function defineAudio(tag = 'usa-audio') {
|
|
262
|
+
return defineElement(tag, (Base) => class UsaAudio extends Base {
|
|
263
|
+
constructor() {
|
|
264
|
+
super(...arguments);
|
|
265
|
+
this.active = false;
|
|
266
|
+
this.audio = null;
|
|
267
|
+
this.off = null;
|
|
268
|
+
}
|
|
269
|
+
static get observedAttributes() {
|
|
270
|
+
return ['source'];
|
|
271
|
+
}
|
|
272
|
+
button() {
|
|
273
|
+
let b = this.querySelector('[data-audio-toggle]');
|
|
274
|
+
if (!b) {
|
|
275
|
+
b = document.createElement('button');
|
|
276
|
+
b.type = 'button';
|
|
277
|
+
b.setAttribute('data-audio-toggle', '');
|
|
278
|
+
b.textContent = this.str('label', '🔊 Enable sound-reactive effects');
|
|
279
|
+
this.prepend(b);
|
|
280
|
+
this.onCleanup(() => b.remove());
|
|
281
|
+
}
|
|
282
|
+
return b;
|
|
283
|
+
}
|
|
284
|
+
async toggle() {
|
|
285
|
+
const b = this.button();
|
|
286
|
+
if (this.active)
|
|
287
|
+
return this.stop();
|
|
288
|
+
try {
|
|
289
|
+
this.audio = await enableAudio(this.str('source', 'mic'));
|
|
290
|
+
this.active = true;
|
|
291
|
+
this.removeAttribute('data-audio-error');
|
|
292
|
+
b.setAttribute('aria-pressed', 'true');
|
|
293
|
+
this.off = onBeat((d) => {
|
|
294
|
+
this.dispatchEvent(new CustomEvent('usa-beat', { detail: d, bubbles: true }));
|
|
295
|
+
if (prefersReducedMotion())
|
|
296
|
+
return;
|
|
297
|
+
this.querySelectorAll('[data-usa-beat]').forEach((el) => {
|
|
298
|
+
let opts = {};
|
|
299
|
+
try {
|
|
300
|
+
opts = JSON.parse(el.dataset.usaBeatOptions || '{}') || {};
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
/* ignore bad JSON */
|
|
304
|
+
}
|
|
305
|
+
playEffect(el, el.dataset.usaBeat || 'pulse', opts).catch(() => undefined);
|
|
306
|
+
});
|
|
307
|
+
}, { threshold: this.num('threshold', 1.35), cooldown: this.num('cooldown', 250) });
|
|
308
|
+
}
|
|
309
|
+
catch (err) {
|
|
310
|
+
this.setAttribute('data-audio-error', '');
|
|
311
|
+
this.dispatchEvent(new CustomEvent('usa-audio-error', { detail: { error: err }, bubbles: true }));
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
stop() {
|
|
315
|
+
this.off?.();
|
|
316
|
+
this.off = null;
|
|
317
|
+
if (this.audio && current === this.audio)
|
|
318
|
+
this.audio.stop();
|
|
319
|
+
this.audio = null;
|
|
320
|
+
this.active = false;
|
|
321
|
+
this.querySelector('[data-audio-toggle]')?.setAttribute('aria-pressed', 'false');
|
|
322
|
+
}
|
|
323
|
+
mount() {
|
|
324
|
+
const b = this.button();
|
|
325
|
+
b.setAttribute('aria-pressed', 'false');
|
|
326
|
+
this.listen(b, 'click', () => void this.toggle());
|
|
327
|
+
this.onCleanup(() => this.stop());
|
|
328
|
+
}
|
|
329
|
+
}, { id: 'usa-audio', text: 'usa-audio{display:block}usa-audio[data-audio-error] [data-audio-toggle]{outline:2px solid #ff5c8a}' });
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export { AUDIO_FX as A, disableAudio as a, bindBeat as b, createBeatDetector as c, defineAudio as d, enableAudio as e, getAudio as g, onBeat as o };
|
|
333
|
+
//# sourceMappingURL=audio-DcPvT2Kh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio-DcPvT2Kh.js","sources":["../../src/components/effects/audio.ts"],"sourcesContent":["/**\n * 5.6 — sound-reactive effects (Web Audio).\n *\n * - `enableAudio(input)` — start analysing the microphone (`'mic'`), an\n * `<audio>` / `<video>` element (or a selector for one) or a `MediaStream`.\n * Browsers only allow an `AudioContext` to start inside a user gesture, so\n * call it from a click handler (or use `<usa-audio>`, which renders the\n * toggle button for you).\n * - Background effects (kind `background`, Canvas 2D through\n * `canvasBackground()`): `spectrum-bars`, `pulse-ring`, `wave-ring`. Before\n * audio is enabled they idle gently.\n * - Beat detection: `createBeatDetector()` (pure: energy → beat?), `onBeat(cb)`\n * and `bindBeat(el, effect, options)`, which plays any registered effect on\n * every beat. `<usa-audio>` does the same for `[data-usa-beat=\"effect\"]`\n * children and emits `usa-beat`.\n * - While audio runs, `--usa-audio-level` and `--usa-audio-bass` (0–1) are set\n * on `<html>` for CSS-driven reactions.\n *\n * Reduced motion: the visual effects are skipped, beats play no effects and\n * the CSS variables stay at 0 — audio itself keeps playing.\n */\nimport type { EffectDefinition } from '../fx/registry';\nimport { playEffect } from '../fx/registry';\nimport { defineElement, prefersReducedMotion, type UsaElement } from '../base';\nimport { canvasBackground, hexRgb, type GenerativeSpec } from './generative';\nimport { PALETTE } from './shared';\n\nexport type AudioInput = 'mic' | HTMLMediaElement | MediaStream | string;\n\nexport interface AudioSample {\n /** Overall loudness (RMS of the waveform), 0–1. */\n level: number;\n /** Low-frequency energy (first ~8 % of the spectrum), 0–1. */\n bass: number;\n /** Frequency bins, 0–255 each. */\n freq: Uint8Array;\n /** Time-domain waveform, 0–255 (128 = silence). */\n wave: Uint8Array;\n}\n\nexport interface AudioReactive {\n readonly context: AudioContext;\n readonly analyser: AnalyserNode;\n /** Read the analyser now. */\n sample(): AudioSample;\n /** Stop analysing (media keeps playing; the microphone is released). */\n stop(): void;\n}\n\nexport interface BeatOptions {\n /** A beat is energy above `threshold` × the recent average (default 1.35). */\n threshold?: number;\n /** Minimum ms between beats (default 250). */\n cooldown?: number;\n /** Frames of history for the average (default 43 ≈ 0.7 s). */\n history?: number;\n /** Ignore energy below this floor, 0–1 (default 0.08). */\n floor?: number;\n}\n\nlet actx: AudioContext | null = null;\nlet current: AudioReactive | null = null;\nconst mediaSources = new WeakMap<HTMLMediaElement, MediaElementAudioSourceNode>();\n\n/** The running analyser, if `enableAudio()` was called. */\nexport const getAudio = (): AudioReactive | null => current;\n\nfunction audioContext(): AudioContext {\n const AC = (globalThis as any).AudioContext || (globalThis as any).webkitAudioContext;\n if (!AC) throw new Error('[motionary] Web Audio is not available');\n if (!actx || actx.state === 'closed') actx = new AC() as AudioContext;\n return actx;\n}\n\n/**\n * Start analysing `input` and make it the source of every sound-reactive\n * effect. Call from a user gesture. Replaces a previous source.\n */\nexport async function enableAudio(input: AudioInput = 'mic', opts: { fftSize?: number; smoothing?: number } = {}): Promise<AudioReactive> {\n current?.stop();\n const ac = audioContext();\n if (ac.state === 'suspended') await ac.resume().catch(() => undefined);\n const analyser = ac.createAnalyser();\n analyser.fftSize = opts.fftSize || 512;\n analyser.smoothingTimeConstant = opts.smoothing ?? 0.8;\n let src: AudioNode;\n let release = () => {};\n const media = typeof input === 'string' && input !== 'mic' ? document.querySelector<HTMLMediaElement>(input) : input;\n if (media === 'mic') {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n src = ac.createMediaStreamSource(stream);\n src.connect(analyser); // never to the speakers: no feedback\n release = () => stream.getTracks().forEach((t) => t.stop());\n } else if (media && typeof (media as HTMLMediaElement).play === 'function') {\n const m = media as HTMLMediaElement;\n let node = mediaSources.get(m);\n if (!node) mediaSources.set(m, (node = ac.createMediaElementSource(m)));\n try {\n node.disconnect();\n } catch {\n /* not connected */\n }\n src = node;\n src.connect(analyser);\n analyser.connect(ac.destination);\n release = () => {\n try {\n node!.disconnect();\n } catch {\n /* already */\n }\n node!.connect(ac.destination); // keep the media audible\n };\n if (m.paused) await m.play()?.catch?.(() => undefined);\n } else if (media && typeof (media as MediaStream).getTracks === 'function') {\n src = ac.createMediaStreamSource(media as MediaStream);\n src.connect(analyser);\n } else throw new Error(`[motionary] enableAudio: no audio source for ${String(input)}`);\n const freq = new Uint8Array(analyser.frequencyBinCount);\n const wave = new Uint8Array(analyser.fftSize);\n const self: AudioReactive = {\n context: ac,\n analyser,\n sample: () => {\n analyser.getByteFrequencyData(freq);\n analyser.getByteTimeDomainData(wave);\n let sq = 0;\n for (let i = 0; i < wave.length; i++) sq += ((wave[i] - 128) / 128) ** 2;\n const n = Math.max(1, Math.round(freq.length * 0.08));\n let b = 0;\n for (let i = 0; i < n; i++) b += freq[i];\n return { level: Math.min(1, Math.sqrt(sq / wave.length) * 2), bass: b / n / 255, freq, wave };\n },\n stop: () => {\n if (current === self) {\n current = null;\n if (raf && typeof cancelAnimationFrame === 'function') cancelAnimationFrame(raf);\n raf = 0;\n }\n try {\n src.disconnect();\n analyser.disconnect();\n } catch {\n /* already */\n }\n release();\n setVars(0, 0);\n },\n };\n current = self;\n kick();\n return self;\n}\n\n/** Stop the current audio source (if any). */\nexport function disableAudio(): void {\n current?.stop();\n}\n\n/** A pure beat detector: feed it energy (0–1) and a timestamp per frame; it answers \"beat?\". */\nexport function createBeatDetector(o: BeatOptions = {}): (energy: number, now: number) => boolean {\n const { threshold = 1.35, cooldown = 250, history = 43, floor = 0.08 } = o;\n const hist: number[] = [];\n let last = -Infinity;\n return (energy, now) => {\n const avg = hist.length ? hist.reduce((a, b) => a + b, 0) / hist.length : energy;\n const ready = hist.length >= 8;\n hist.push(energy);\n if (hist.length > history) hist.shift();\n if (ready && energy > floor && energy > avg * threshold && now - last >= cooldown) {\n last = now;\n return true;\n }\n return false;\n };\n}\n\ntype BeatListener = { detect: (e: number, t: number) => boolean; cb: (detail: { energy: number; time: number }) => void };\nconst listeners = new Set<BeatListener>();\nlet raf = 0;\n\nfunction setVars(level: number, bass: number): void {\n if (typeof document === 'undefined') return;\n const s = document.documentElement.style;\n s.setProperty('--usa-audio-level', level.toFixed(3));\n s.setProperty('--usa-audio-bass', bass.toFixed(3));\n}\n\nfunction loop(now: number): void {\n raf = 0;\n if (!current) return;\n const { level, bass } = current.sample();\n const reduced = prefersReducedMotion();\n setVars(reduced ? 0 : level, reduced ? 0 : bass);\n for (const l of Array.from(listeners)) if (l.detect(bass, now)) l.cb({ energy: bass, time: now });\n kick();\n}\n\nfunction kick(): void {\n if (!raf && current && typeof requestAnimationFrame === 'function') raf = requestAnimationFrame(loop);\n}\n\n/** Call `cb` on every detected beat of the current audio source. Returns an unsubscribe. */\nexport function onBeat(cb: (detail: { energy: number; time: number }) => void, o: BeatOptions = {}): () => void {\n const l: BeatListener = { detect: createBeatDetector(o), cb };\n listeners.add(l);\n kick();\n return () => void listeners.delete(l);\n}\n\n/** Play the registered effect `name` on `el` at every beat (not under reduced motion). Returns an unbind. */\nexport function bindBeat(el: HTMLElement, name: string, options: Record<string, unknown> & BeatOptions = {}): () => void {\n const { threshold, cooldown, history, floor, ...fx } = options;\n return onBeat(() => {\n if (!prefersReducedMotion()) playEffect(el, name, fx).catch(() => undefined);\n }, { threshold, cooldown, history, floor } as BeatOptions);\n}\n\n// --- visual effects ----------------------------------------------------------\n\n/** The current sample, or a gentle synthetic one while no audio is enabled. */\nfunction read(t: number, bins: number): AudioSample & { idle: boolean } {\n if (current) return { ...current.sample(), idle: false };\n const freq = new Uint8Array(bins);\n const wave = new Uint8Array(bins * 2);\n for (let i = 0; i < bins; i++) freq[i] = 70 + 50 * Math.sin(t * 2 + i * 0.35) * Math.cos(t * 0.7 + i * 0.11) * (1 - i / bins);\n for (let i = 0; i < wave.length; i++) wave[i] = 128 + 22 * Math.sin(t * 3 + i * 0.12);\n return { level: 0.25 + 0.1 * Math.sin(t * 2), bass: 0.35 + 0.2 * Math.sin(t * 2.4), freq, wave, idle: true };\n}\n\nconst audioFx = (name: string, description: string, defaults: Record<string, unknown>, spec: GenerativeSpec): EffectDefinition => ({\n name,\n kind: 'background',\n description,\n reduced: 'skip',\n defaults: { colors: PALETTE, background: '#0b0d12', speed: 1, quality: 1, ...defaults },\n run: (el, o: any, ctx) => canvasBackground(el, ctx, spec, o),\n});\n\nexport const AUDIO_FX: EffectDefinition[] = [\n audioFx('spectrum-bars', 'Frequency bars dance to the audio (mirror them with `mirror: true`).', { bars: 48, gap: 2, mirror: false }, {\n draw: ({ ctx, w, h, t, o }) => {\n ctx.fillStyle = o.background;\n ctx.fillRect(0, 0, w, h);\n const s = read(t, o.bars);\n const per = Math.max(1, Math.floor((s.freq.length * 0.7) / o.bars));\n const bw = w / o.bars;\n for (let i = 0; i < o.bars; i++) {\n let v = 0;\n for (let k = 0; k < per; k++) v += s.freq[Math.min(s.freq.length - 1, i * per + k)];\n const bh = (v / per / 255) * h * (o.mirror ? 0.5 : 0.9);\n ctx.fillStyle = o.colors[i % o.colors.length];\n ctx.fillRect(i * bw + o.gap / 2, o.mirror ? h / 2 - bh : h - bh, Math.max(1, bw - o.gap), o.mirror ? bh * 2 : bh);\n }\n },\n }),\n audioFx('pulse-ring', 'Glowing rings pulse with the bass.', { rings: 3, color: '#7c5cff' }, {\n draw: ({ ctx, w, h, t, o }) => {\n ctx.fillStyle = o.background;\n ctx.fillRect(0, 0, w, h);\n const s = read(t, 32);\n const [r, g, b] = hexRgb(o.color);\n const base = Math.min(w, h) * 0.18;\n for (let i = 0; i < o.rings; i++) {\n const rad = base * (1 + i * 0.55) * (1 + s.bass * 0.6);\n ctx.strokeStyle = `rgba(${r},${g},${b},${(0.9 - i * 0.25) * (0.4 + s.level)})`;\n ctx.lineWidth = 3 + s.bass * 10 - i;\n ctx.beginPath();\n ctx.arc(w / 2, h / 2, rad, 0, Math.PI * 2);\n ctx.stroke();\n }\n },\n }),\n audioFx('wave-ring', 'The live waveform wrapped into a circle.', { color: '#22d3ee', amplitude: 0.35 }, {\n draw: ({ ctx, w, h, t, o }) => {\n ctx.fillStyle = o.background;\n ctx.fillRect(0, 0, w, h);\n const s = read(t, 64);\n const n = s.wave.length;\n const base = Math.min(w, h) * 0.28;\n ctx.strokeStyle = o.color;\n ctx.lineWidth = 2;\n ctx.beginPath();\n for (let i = 0; i <= n; i++) {\n const a = (i / n) * Math.PI * 2;\n const rad = base * (1 + ((s.wave[i % n] - 128) / 128) * o.amplitude * 2);\n const x = w / 2 + Math.cos(a) * rad;\n const y = h / 2 + Math.sin(a) * rad;\n if (i) ctx.lineTo(x, y);\n else ctx.moveTo(x, y);\n }\n ctx.closePath();\n ctx.stroke();\n },\n }),\n];\n\n// --- <usa-audio> -----------------------------------------------------------\n\nexport interface UsaAudioElement extends UsaElement {\n /** `true` while this element's audio source is being analysed. */\n readonly active: boolean;\n /** Start (from a user gesture) or stop analysing. */\n toggle(): Promise<void>;\n}\n\n/**\n * `<usa-audio source=\"#track | mic\" label=\"…\">` — a toggle button (yours, as\n * `[data-audio-toggle]`, or one it renders) that enables the audio source on\n * click; children with `data-usa-beat=\"effect\"` play that effect on every\n * beat (`data-usa-beat-options` JSON; `threshold` / `cooldown` attributes).\n * Emits `usa-beat` and `usa-audio-error`.\n */\nexport function defineAudio(tag = 'usa-audio'): CustomElementConstructor | undefined {\n return defineElement(\n tag,\n (Base) =>\n class UsaAudio extends Base {\n static get observedAttributes(): string[] {\n return ['source'];\n }\n active = false;\n private audio: AudioReactive | null = null;\n private off: (() => void) | null = null;\n private button(): HTMLButtonElement {\n let b = this.querySelector<HTMLButtonElement>('[data-audio-toggle]');\n if (!b) {\n b = document.createElement('button');\n b.type = 'button';\n b.setAttribute('data-audio-toggle', '');\n b.textContent = this.str('label', '🔊 Enable sound-reactive effects');\n this.prepend(b);\n this.onCleanup(() => b!.remove());\n }\n return b;\n }\n async toggle(): Promise<void> {\n const b = this.button();\n if (this.active) return this.stop();\n try {\n this.audio = await enableAudio(this.str('source', 'mic'));\n this.active = true;\n this.removeAttribute('data-audio-error');\n b.setAttribute('aria-pressed', 'true');\n this.off = onBeat((d) => {\n this.dispatchEvent(new CustomEvent('usa-beat', { detail: d, bubbles: true }));\n if (prefersReducedMotion()) return;\n this.querySelectorAll<HTMLElement>('[data-usa-beat]').forEach((el) => {\n let opts = {};\n try {\n opts = JSON.parse(el.dataset.usaBeatOptions || '{}') || {};\n } catch {\n /* ignore bad JSON */\n }\n playEffect(el, el.dataset.usaBeat || 'pulse', opts).catch(() => undefined);\n });\n }, { threshold: this.num('threshold', 1.35), cooldown: this.num('cooldown', 250) });\n } catch (err) {\n this.setAttribute('data-audio-error', '');\n this.dispatchEvent(new CustomEvent('usa-audio-error', { detail: { error: err }, bubbles: true }));\n }\n }\n private stop(): void {\n this.off?.();\n this.off = null;\n if (this.audio && current === this.audio) this.audio.stop();\n this.audio = null;\n this.active = false;\n this.querySelector('[data-audio-toggle]')?.setAttribute('aria-pressed', 'false');\n }\n mount(): void {\n const b = this.button();\n b.setAttribute('aria-pressed', 'false');\n this.listen(b, 'click', () => void this.toggle());\n this.onCleanup(() => this.stop());\n }\n },\n { id: 'usa-audio', text: 'usa-audio{display:block}usa-audio[data-audio-error] [data-audio-toggle]{outline:2px solid #ff5c8a}' }\n );\n}\n"],"names":[],"mappings":"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"}
|