use-scroll-animate 6.9.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.
Files changed (204) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +2 -2
  3. package/README_ja.md +2 -2
  4. package/README_zh.md +2 -2
  5. package/dist/chunks/audio-DcPvT2Kh.js +333 -0
  6. package/dist/chunks/audio-DcPvT2Kh.js.map +1 -0
  7. package/dist/chunks/audio-EXUoijsG.cjs +342 -0
  8. package/dist/chunks/audio-EXUoijsG.cjs.map +1 -0
  9. package/dist/chunks/{base-D5MHqeDd.js → base-2-yYc93C.js} +2 -2
  10. package/dist/chunks/{base-D5MHqeDd.js.map → base-2-yYc93C.js.map} +1 -1
  11. package/dist/chunks/{core-DyJu5r5a.js → core-D5rU0CV6.js} +2 -2
  12. package/dist/chunks/{core-DyJu5r5a.js.map → core-D5rU0CV6.js.map} +1 -1
  13. package/dist/chunks/{core-ZGo4hOEk.js → core-DuO-AVXL.js} +2 -2
  14. package/dist/chunks/{core-ZGo4hOEk.js.map → core-DuO-AVXL.js.map} +1 -1
  15. package/dist/chunks/{fx-DlGRMJ-Z.js → fx-CMxWNwH8.js} +2 -2
  16. package/dist/chunks/{fx-DlGRMJ-Z.js.map → fx-CMxWNwH8.js.map} +1 -1
  17. package/dist/chunks/{gpu-DPhMkJq6.js → gpu-DLPghVWr.js} +183 -11
  18. package/dist/chunks/gpu-DLPghVWr.js.map +1 -0
  19. package/dist/chunks/{gpu-C2D4T9Q-.cjs → gpu-Dx0H875w.cjs} +185 -9
  20. package/dist/chunks/gpu-Dx0H875w.cjs.map +1 -0
  21. package/dist/chunks/{index-tags-wv0R_vkO.cjs → index-tags-BTMwrfgV.cjs} +3 -3
  22. package/dist/chunks/index-tags-BTMwrfgV.cjs.map +1 -0
  23. package/dist/chunks/{index-tags-DucKMQr_.js → index-tags-C04JP8g4.js} +3 -3
  24. package/dist/chunks/index-tags-C04JP8g4.js.map +1 -0
  25. package/dist/chunks/{player-DH3TIz-t.js → player-DxvCYo7Q.js} +4 -4
  26. package/dist/chunks/{player-DH3TIz-t.js.map → player-DxvCYo7Q.js.map} +1 -1
  27. package/dist/chunks/{registry-CTLWeg-J.js → registry-CyKExAmE.js} +2 -2
  28. package/dist/chunks/{registry-CTLWeg-J.js.map → registry-CyKExAmE.js.map} +1 -1
  29. package/dist/chunks/{spring-B-9MZOrW.js → spring-BK8DiezC.js} +2 -2
  30. package/dist/chunks/{spring-B-9MZOrW.js.map → spring-BK8DiezC.js.map} +1 -1
  31. package/dist/chunks/{variants-CoZn3k_5.js → variants-BQ6bhzn4.js} +2 -2
  32. package/dist/chunks/{variants-CoZn3k_5.js.map → variants-BQ6bhzn4.js.map} +1 -1
  33. package/dist/components/a11y.cjs +1 -1
  34. package/dist/components/a11y.d.cts +2 -2
  35. package/dist/components/a11y.d.ts +2 -2
  36. package/dist/components/a11y.js +3 -3
  37. package/dist/components/angular.cjs +2 -2
  38. package/dist/components/angular.cjs.map +1 -1
  39. package/dist/components/angular.d.cts +5 -36
  40. package/dist/components/angular.d.ts +5 -36
  41. package/dist/components/angular.js +9 -9
  42. package/dist/components/angular.js.map +1 -1
  43. package/dist/components/background.js +2 -2
  44. package/dist/components/bridge.js +1 -1
  45. package/dist/components/cards.js +2 -2
  46. package/dist/components/click.js +3 -3
  47. package/dist/components/depth.js +3 -3
  48. package/dist/components/effects.cjs +11 -336
  49. package/dist/components/effects.cjs.map +1 -1
  50. package/dist/components/effects.js +9 -333
  51. package/dist/components/effects.js.map +1 -1
  52. package/dist/components/feedback.js +1 -1
  53. package/dist/components/fx-3d.cjs +1 -7
  54. package/dist/components/fx-3d.cjs.map +1 -1
  55. package/dist/components/fx-3d.d.cts +1 -3
  56. package/dist/components/fx-3d.d.ts +1 -3
  57. package/dist/components/fx-3d.js +3 -8
  58. package/dist/components/fx-3d.js.map +1 -1
  59. package/dist/components/fx-focus.js +2 -2
  60. package/dist/components/fx-gpu.cjs +2 -3
  61. package/dist/components/fx-gpu.cjs.map +1 -1
  62. package/dist/components/fx-gpu.d.cts +1 -3
  63. package/dist/components/fx-gpu.d.ts +1 -3
  64. package/dist/components/fx-gpu.js +3 -3
  65. package/dist/components/fx-light.cjs +1 -7
  66. package/dist/components/fx-light.cjs.map +1 -1
  67. package/dist/components/fx-light.d.cts +1 -3
  68. package/dist/components/fx-light.d.ts +1 -3
  69. package/dist/components/fx-light.js +3 -8
  70. package/dist/components/fx-light.js.map +1 -1
  71. package/dist/components/fx-morph.cjs +1 -7
  72. package/dist/components/fx-morph.cjs.map +1 -1
  73. package/dist/components/fx-morph.d.cts +1 -3
  74. package/dist/components/fx-morph.d.ts +1 -3
  75. package/dist/components/fx-morph.js +3 -8
  76. package/dist/components/fx-morph.js.map +1 -1
  77. package/dist/components/fx-music.cjs +179 -0
  78. package/dist/components/fx-music.cjs.map +1 -0
  79. package/dist/components/fx-music.d.cts +102 -0
  80. package/dist/components/fx-music.d.ts +102 -0
  81. package/dist/components/fx-music.js +174 -0
  82. package/dist/components/fx-music.js.map +1 -0
  83. package/dist/components/fx-physics.cjs +1 -7
  84. package/dist/components/fx-physics.cjs.map +1 -1
  85. package/dist/components/fx-physics.d.cts +1 -3
  86. package/dist/components/fx-physics.d.ts +1 -3
  87. package/dist/components/fx-physics.js +3 -8
  88. package/dist/components/fx-physics.js.map +1 -1
  89. package/dist/components/fx-text.cjs +1 -7
  90. package/dist/components/fx-text.cjs.map +1 -1
  91. package/dist/components/fx-text.d.cts +1 -3
  92. package/dist/components/fx-text.d.ts +1 -3
  93. package/dist/components/fx-text.js +3 -8
  94. package/dist/components/fx-text.js.map +1 -1
  95. package/dist/components/fx-transitions.cjs +1 -7
  96. package/dist/components/fx-transitions.cjs.map +1 -1
  97. package/dist/components/fx-transitions.d.cts +1 -3
  98. package/dist/components/fx-transitions.d.ts +1 -3
  99. package/dist/components/fx-transitions.js +4 -9
  100. package/dist/components/fx-transitions.js.map +1 -1
  101. package/dist/components/fx-weather.cjs +1 -7
  102. package/dist/components/fx-weather.cjs.map +1 -1
  103. package/dist/components/fx-weather.d.cts +1 -3
  104. package/dist/components/fx-weather.d.ts +1 -3
  105. package/dist/components/fx-weather.js +3 -8
  106. package/dist/components/fx-weather.js.map +1 -1
  107. package/dist/components/fx.js +5 -5
  108. package/dist/components/fx2.cjs +15 -19
  109. package/dist/components/fx2.cjs.map +1 -1
  110. package/dist/components/fx2.d.cts +97 -22
  111. package/dist/components/fx2.d.ts +97 -22
  112. package/dist/components/fx2.js +16 -19
  113. package/dist/components/fx2.js.map +1 -1
  114. package/dist/components/gesture.js +4 -4
  115. package/dist/components/interaction.cjs +11 -95
  116. package/dist/components/interaction.cjs.map +1 -1
  117. package/dist/components/interaction.css +0 -1
  118. package/dist/components/interaction.d.cts +3 -21
  119. package/dist/components/interaction.d.ts +3 -21
  120. package/dist/components/interaction.js +13 -96
  121. package/dist/components/interaction.js.map +1 -1
  122. package/dist/components/jsx.d.cts +2 -2
  123. package/dist/components/jsx.d.ts +2 -2
  124. package/dist/components/layout.js +1 -1
  125. package/dist/components/lazy.cjs +1 -1
  126. package/dist/components/lazy.d.cts +2 -2
  127. package/dist/components/lazy.d.ts +2 -2
  128. package/dist/components/lazy.js +1 -1
  129. package/dist/components/lite.cjs +115 -258
  130. package/dist/components/lite.cjs.map +1 -1
  131. package/dist/components/lite.js +116 -257
  132. package/dist/components/lite.js.map +1 -1
  133. package/dist/components/marketplace.js +2 -2
  134. package/dist/components/packs.js +1 -1
  135. package/dist/components/page.js +3 -3
  136. package/dist/components/perf.cjs +1 -1
  137. package/dist/components/perf.d.cts +2 -2
  138. package/dist/components/perf.d.ts +2 -2
  139. package/dist/components/perf.js +3 -3
  140. package/dist/components/physics.js +3 -3
  141. package/dist/components/react.cjs +2 -2
  142. package/dist/components/react.cjs.map +1 -1
  143. package/dist/components/react.js +2 -2
  144. package/dist/components/react.js.map +1 -1
  145. package/dist/components/reveal.js +1 -1
  146. package/dist/components/solid.cjs +2 -2
  147. package/dist/components/solid.cjs.map +1 -1
  148. package/dist/components/solid.d.cts +4 -35
  149. package/dist/components/solid.d.ts +4 -35
  150. package/dist/components/solid.js +9 -9
  151. package/dist/components/solid.js.map +1 -1
  152. package/dist/components/svelte.cjs +2 -2
  153. package/dist/components/svelte.cjs.map +1 -1
  154. package/dist/components/svelte.d.cts +5 -36
  155. package/dist/components/svelte.d.ts +5 -36
  156. package/dist/components/svelte.js +9 -9
  157. package/dist/components/svelte.js.map +1 -1
  158. package/dist/components/svg.js +1 -1
  159. package/dist/components/text.js +2 -2
  160. package/dist/components/timeline.js +3 -3
  161. package/dist/components/transitions.js +1 -1
  162. package/dist/components/ui.cjs +16 -75
  163. package/dist/components/ui.cjs.map +1 -1
  164. package/dist/components/ui.css +0 -1
  165. package/dist/components/ui.d.cts +3 -18
  166. package/dist/components/ui.d.ts +3 -18
  167. package/dist/components/ui.js +21 -79
  168. package/dist/components/ui.js.map +1 -1
  169. package/dist/components/vue.cjs +2 -2
  170. package/dist/components/vue.cjs.map +1 -1
  171. package/dist/components/vue.d.cts +5 -36
  172. package/dist/components/vue.d.ts +5 -36
  173. package/dist/components/vue.js +9 -9
  174. package/dist/components/vue.js.map +1 -1
  175. package/dist/components/webgl.js +1 -1
  176. package/dist/components/widgets.cjs +542 -61
  177. package/dist/components/widgets.cjs.map +1 -1
  178. package/dist/components/widgets.d.cts +79 -2
  179. package/dist/components/widgets.d.ts +79 -2
  180. package/dist/components/widgets.js +542 -67
  181. package/dist/components/widgets.js.map +1 -1
  182. package/dist/components.cjs +1 -3
  183. package/dist/components.cjs.map +1 -1
  184. package/dist/components.css +0 -2
  185. package/dist/components.d.cts +6 -39
  186. package/dist/components.d.ts +6 -39
  187. package/dist/components.js +12 -12
  188. package/dist/components.umd.js +2 -2
  189. package/dist/components.umd.js.map +1 -1
  190. package/dist/index.js +2 -2
  191. package/dist/widgets.umd.js +1 -1
  192. package/dist/widgets.umd.js.map +1 -1
  193. package/docs/ROADMAP.md +12 -12
  194. package/docs/accessibility.md +2 -2
  195. package/docs/components.md +38 -2
  196. package/docs/frameworks-ssr.md +4 -4
  197. package/docs/hybrid-apps.md +2 -2
  198. package/docs/upgrading-7.md +11 -1
  199. package/docs/windows-apps.md +1 -1
  200. package/package.json +131 -1
  201. package/dist/chunks/gpu-C2D4T9Q-.cjs.map +0 -1
  202. package/dist/chunks/gpu-DPhMkJq6.js.map +0 -1
  203. package/dist/chunks/index-tags-DucKMQr_.js.map +0 -1
  204. package/dist/chunks/index-tags-wv0R_vkO.cjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,36 @@ 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
+
24
+ ## [7.0.0] - 2026-10-08
25
+
26
+ ### ⚠️ Breaking — removed (deprecated in 6.9; `npx usa-codemod-7 --write src`)
27
+ - `registerFx2()` → `registerEffectPacks()`; `FX2_PACKS` → `EFFECT_PACKS`.
28
+ - `registerGpuEffects` / `registerTextEffects3` / `registerLightEffects` / `register3dEffects` / `registerMorphEffects2` / `registerTransitionEffects2` / `registerWeatherEffects` / `registerPhysicsEffects2` → `registerGpuPack` / `registerTextPack` / `registerLightPack` / `register3dPack` / `registerMorphPack` / `registerTransitionsPack` / `registerWeatherPack` / `registerPhysicsPack`.
29
+ - `<usa-tooltip>` (`defineTooltip`) → `<usa-tip>` (`defineTip`, 6.6); `<usa-toggle>` (`defineToggle`) → `<usa-switch>` (`defineSwitch`, 6.7). Docs, framework examples and the showcase use the new tags.
30
+
31
+ ### Added
32
+ - **WebGPU backend** for shader backgrounds: `backend: 'auto'` now tries WebGPU first (the GLSL body is translated by `glslToWgsl()`, or a spec ships `wgsl`), then WebGL2, then Canvas 2D; `el.dataset.usaBackend` = `webgpu` / `webgl2` / `canvas`. New exports `supportsWebGPU()`, `glslToWgsl()`, `wgslModule()`, `webgpuBackground()`, `WGSL_HEAD`.
33
+ - **Per-pack entries**: `motionary/fx` (every pack) and `motionary/fx/gpu`, `/fx/text`, `/fx/light`, `/fx/3d`, `/fx/morph`, `/fx/transitions`, `/fx/weather`, `/fx/physics`, `/fx/focus`, `/fx/marketplace` (same builds as `motionary/components/fx-*`, which keep working).
34
+ - **docs/ROADMAP.md** replaced by the post-7.0 roadmap (v7.1 → v8.0).
35
+ - npm: `motionary@7.0.0` and the `use-scroll-animate@7.0.0` alias are published with the `latest` tag.
36
+
37
+ ### Upgrading
38
+ - See [docs/upgrading-7.md](./docs/upgrading-7.md). Everything else (browser baseline, `<usa-player>` JSON, every 6.x widget API) is unchanged.
39
+
10
40
  ## [6.9.0] - 2026-10-08
11
41
 
12
42
  ### Added
package/README.md CHANGED
@@ -149,14 +149,14 @@ Import one category (`motionary/components/cards`), everything (`motionary/compo
149
149
  |---|---|
150
150
  | **Scroll reveal** (`/components/reveal`) | `<usa-reveal>` · `<usa-stagger>` · `<usa-scroll-progress>` · `<usa-scrolly>` |
151
151
  | **Text** (`/components/text`) | `<usa-typewriter>` · `<usa-split-text>` · `<usa-scramble>` · `<usa-counter>` · `<usa-shimmer-text>` · `<usa-text-rotate>` · `<usa-wave-text>` · `<usa-glitch>` · `<usa-gradient-text>` · `<usa-handwriting>` · `<usa-scroll-highlight>` |
152
- | **Interaction** (`/components/interaction`) | `<usa-ripple>` · `<usa-magnetic>` · `<usa-tilt>` · `<usa-spotlight>` · `<usa-press>` · `<usa-toggle>` |
152
+ | **Interaction** (`/components/interaction`) | `<usa-ripple>` · `<usa-magnetic>` · `<usa-tilt>` · `<usa-spotlight>` · `<usa-press>` · `<usa-switch>` |
153
153
  | **Feedback** (`/components/feedback`) | `<usa-spinner>` · `<usa-skeleton>` · `<usa-progress>` · `<usa-toaster>` · `<usa-check>` |
154
154
  | **Backgrounds** (`/components/background`) | `<usa-aurora>` · `<usa-particles>` · `<usa-grain>` · `<usa-marquee>` · `<usa-acrylic>` · `<usa-grid-glow>` · `<usa-blobs>` · `<usa-water-ripple>` · `<usa-dot-network>` |
155
155
  | **Transitions** (`/components/transitions`) | `<usa-dialog>` · `<usa-accordion>` · `<usa-view-switch>` |
156
156
  | **Spring & physics** (`/components/physics`) | `<usa-spring>` · `<usa-draggable>` · `<usa-overscroll>` |
157
157
  | **Cards** (`/components/cards`) | `<usa-card>` · `<usa-card-stack>` · `<usa-sticky-stack>` · `<usa-carousel-3d>` |
158
158
  | **Click & buttons** (`/components/click`) | `<usa-click>` · `<usa-button>` · `<usa-icon-morph>` · `<usa-like>` · `<usa-hold>` · `<usa-double-tap>` · `<usa-checkbox>` |
159
- | **UI kit** (`/components/ui`) | `<usa-tabs>` · `<usa-drawer>` · `<usa-bottom-sheet>` · `<usa-pull-refresh>` · `<usa-fab>` · `<usa-navbar>` · `<usa-slider>` · `<usa-rating>` · `<usa-tooltip>` · `<usa-popover>` · `<usa-badge>` · `<usa-avatar-stack>` |
159
+ | **UI kit** (`/components/ui`) | `<usa-tabs>` · `<usa-drawer>` · `<usa-bottom-sheet>` · `<usa-pull-refresh>` · `<usa-fab>` · `<usa-navbar>` · `<usa-slider>` · `<usa-rating>` · `<usa-popover>` · `<usa-badge>` · `<usa-avatar-stack>` |
160
160
  | **Page-wide** (`/components/page`) | `<usa-cursor>` · `<usa-fullpage>` · `<usa-loading-bar>` · `<usa-back-to-top>` · `<usa-ambient>` · `<usa-splash>` · `<usa-auto-skeleton>` · `<usa-motion-switch>` |
161
161
  | **Timeline** (`/components/timeline`) | `<usa-timeline>` |
162
162
  | **Gestures** (`/components/gesture`) | `<usa-swipeable>` · `<usa-pinch-zoom>` |
package/README_ja.md CHANGED
@@ -147,14 +147,14 @@ export class Hero {}
147
147
  |---|---|
148
148
  | **スクロール表示** (`/components/reveal`) | `<usa-reveal>` · `<usa-stagger>` · `<usa-scroll-progress>` · `<usa-scrolly>` |
149
149
  | **テキスト** (`/components/text`) | `<usa-typewriter>` · `<usa-split-text>` · `<usa-scramble>` · `<usa-counter>` · `<usa-shimmer-text>` · `<usa-text-rotate>` · `<usa-wave-text>` · `<usa-glitch>` · `<usa-gradient-text>` · `<usa-handwriting>` · `<usa-scroll-highlight>` |
150
- | **インタラクション** (`/components/interaction`) | `<usa-ripple>` · `<usa-magnetic>` · `<usa-tilt>` · `<usa-spotlight>` · `<usa-press>` · `<usa-toggle>` |
150
+ | **インタラクション** (`/components/interaction`) | `<usa-ripple>` · `<usa-magnetic>` · `<usa-tilt>` · `<usa-spotlight>` · `<usa-press>` · `<usa-switch>` |
151
151
  | **フィードバック** (`/components/feedback`) | `<usa-spinner>` · `<usa-skeleton>` · `<usa-progress>` · `<usa-toaster>` · `<usa-check>` |
152
152
  | **背景** (`/components/background`) | `<usa-aurora>` · `<usa-particles>` · `<usa-grain>` · `<usa-marquee>` · `<usa-acrylic>` · `<usa-grid-glow>` · `<usa-blobs>` · `<usa-water-ripple>` · `<usa-dot-network>` |
153
153
  | **トランジション** (`/components/transitions`) | `<usa-dialog>` · `<usa-accordion>` · `<usa-view-switch>` |
154
154
  | **バネ・物理** (`/components/physics`) | `<usa-spring>` · `<usa-draggable>` · `<usa-overscroll>` |
155
155
  | **カード** (`/components/cards`) | `<usa-card>` · `<usa-card-stack>` · `<usa-sticky-stack>` · `<usa-carousel-3d>` |
156
156
  | **クリック・ボタン** (`/components/click`) | `<usa-click>` · `<usa-button>` · `<usa-icon-morph>` · `<usa-like>` · `<usa-hold>` · `<usa-double-tap>` · `<usa-checkbox>` |
157
- | **UI キット** (`/components/ui`) | `<usa-tabs>` · `<usa-drawer>` · `<usa-bottom-sheet>` · `<usa-pull-refresh>` · `<usa-fab>` · `<usa-navbar>` · `<usa-slider>` · `<usa-rating>` · `<usa-tooltip>` · `<usa-popover>` · `<usa-badge>` · `<usa-avatar-stack>` |
157
+ | **UI キット** (`/components/ui`) | `<usa-tabs>` · `<usa-drawer>` · `<usa-bottom-sheet>` · `<usa-pull-refresh>` · `<usa-fab>` · `<usa-navbar>` · `<usa-slider>` · `<usa-rating>` · `<usa-popover>` · `<usa-badge>` · `<usa-avatar-stack>` |
158
158
  | **ページ全体** (`/components/page`) | `<usa-cursor>` · `<usa-fullpage>` · `<usa-loading-bar>` · `<usa-back-to-top>` · `<usa-ambient>` · `<usa-splash>` · `<usa-auto-skeleton>` · `<usa-motion-switch>` |
159
159
  | **タイムライン** (`/components/timeline`) | `<usa-timeline>` |
160
160
  | **ジェスチャー** (`/components/gesture`) | `<usa-swipeable>` · `<usa-pinch-zoom>` |
package/README_zh.md CHANGED
@@ -147,14 +147,14 @@ export class Hero {}
147
147
  |---|---|
148
148
  | **滚动揭示** (`/components/reveal`) | `<usa-reveal>` · `<usa-stagger>` · `<usa-scroll-progress>` · `<usa-scrolly>` |
149
149
  | **文字** (`/components/text`) | `<usa-typewriter>` · `<usa-split-text>` · `<usa-scramble>` · `<usa-counter>` · `<usa-shimmer-text>` · `<usa-text-rotate>` · `<usa-wave-text>` · `<usa-glitch>` · `<usa-gradient-text>` · `<usa-handwriting>` · `<usa-scroll-highlight>` |
150
- | **交互** (`/components/interaction`) | `<usa-ripple>` · `<usa-magnetic>` · `<usa-tilt>` · `<usa-spotlight>` · `<usa-press>` · `<usa-toggle>` |
150
+ | **交互** (`/components/interaction`) | `<usa-ripple>` · `<usa-magnetic>` · `<usa-tilt>` · `<usa-spotlight>` · `<usa-press>` · `<usa-switch>` |
151
151
  | **反馈** (`/components/feedback`) | `<usa-spinner>` · `<usa-skeleton>` · `<usa-progress>` · `<usa-toaster>` · `<usa-check>` |
152
152
  | **背景与装饰** (`/components/background`) | `<usa-aurora>` · `<usa-particles>` · `<usa-grain>` · `<usa-marquee>` · `<usa-acrylic>` · `<usa-grid-glow>` · `<usa-blobs>` · `<usa-water-ripple>` · `<usa-dot-network>` |
153
153
  | **转场** (`/components/transitions`) | `<usa-dialog>` · `<usa-accordion>` · `<usa-view-switch>` |
154
154
  | **弹簧与物理** (`/components/physics`) | `<usa-spring>` · `<usa-draggable>` · `<usa-overscroll>` |
155
155
  | **卡片** (`/components/cards`) | `<usa-card>` · `<usa-card-stack>` · `<usa-sticky-stack>` · `<usa-carousel-3d>` |
156
156
  | **点击与按钮** (`/components/click`) | `<usa-click>` · `<usa-button>` · `<usa-icon-morph>` · `<usa-like>` · `<usa-hold>` · `<usa-double-tap>` · `<usa-checkbox>` |
157
- | **UI 组件** (`/components/ui`) | `<usa-tabs>` · `<usa-drawer>` · `<usa-bottom-sheet>` · `<usa-pull-refresh>` · `<usa-fab>` · `<usa-navbar>` · `<usa-slider>` · `<usa-rating>` · `<usa-tooltip>` · `<usa-popover>` · `<usa-badge>` · `<usa-avatar-stack>` |
157
+ | **UI 组件** (`/components/ui`) | `<usa-tabs>` · `<usa-drawer>` · `<usa-bottom-sheet>` · `<usa-pull-refresh>` · `<usa-fab>` · `<usa-navbar>` · `<usa-slider>` · `<usa-rating>` · `<usa-popover>` · `<usa-badge>` · `<usa-avatar-stack>` |
158
158
  | **整页** (`/components/page`) | `<usa-cursor>` · `<usa-fullpage>` · `<usa-loading-bar>` · `<usa-back-to-top>` · `<usa-ambient>` · `<usa-splash>` · `<usa-auto-skeleton>` · `<usa-motion-switch>` |
159
159
  | **时间线** (`/components/timeline`) | `<usa-timeline>` |
160
160
  | **手势** (`/components/gesture`) | `<usa-swipeable>` · `<usa-pinch-zoom>` |
@@ -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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"}