motionary 7.0.0 → 7.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.
Files changed (94) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/chunks/audio-DcPvT2Kh.js +333 -0
  3. package/dist/chunks/audio-DcPvT2Kh.js.map +1 -0
  4. package/dist/chunks/audio-EXUoijsG.cjs +342 -0
  5. package/dist/chunks/audio-EXUoijsG.cjs.map +1 -0
  6. package/dist/chunks/{base-DchG4q_S.js → base-2-yYc93C.js} +2 -2
  7. package/dist/chunks/{base-DchG4q_S.js.map → base-2-yYc93C.js.map} +1 -1
  8. package/dist/chunks/{core-DVyTlo9Q.js → core-D5rU0CV6.js} +2 -2
  9. package/dist/chunks/{core-DVyTlo9Q.js.map → core-D5rU0CV6.js.map} +1 -1
  10. package/dist/chunks/{core-D2vF8kZb.js → core-DuO-AVXL.js} +2 -2
  11. package/dist/chunks/{core-D2vF8kZb.js.map → core-DuO-AVXL.js.map} +1 -1
  12. package/dist/chunks/{fx-DUMVKSvg.js → fx-CMxWNwH8.js} +2 -2
  13. package/dist/chunks/{fx-DUMVKSvg.js.map → fx-CMxWNwH8.js.map} +1 -1
  14. package/dist/chunks/{gpu-Bkw605Ds.js → gpu-DLPghVWr.js} +2 -2
  15. package/dist/chunks/{gpu-Bkw605Ds.js.map → gpu-DLPghVWr.js.map} +1 -1
  16. package/dist/chunks/{player-C-TwEEy6.js → player-DxvCYo7Q.js} +4 -4
  17. package/dist/chunks/{player-C-TwEEy6.js.map → player-DxvCYo7Q.js.map} +1 -1
  18. package/dist/chunks/{registry-D23neB4M.js → registry-CyKExAmE.js} +2 -2
  19. package/dist/chunks/{registry-D23neB4M.js.map → registry-CyKExAmE.js.map} +1 -1
  20. package/dist/chunks/{spring-BhoT09Qb.js → spring-BK8DiezC.js} +2 -2
  21. package/dist/chunks/{spring-BhoT09Qb.js.map → spring-BK8DiezC.js.map} +1 -1
  22. package/dist/chunks/{variants-C_hv_s23.js → variants-BQ6bhzn4.js} +2 -2
  23. package/dist/chunks/{variants-C_hv_s23.js.map → variants-BQ6bhzn4.js.map} +1 -1
  24. package/dist/components/a11y.js +2 -2
  25. package/dist/components/angular.js +7 -7
  26. package/dist/components/background.js +2 -2
  27. package/dist/components/bridge.js +1 -1
  28. package/dist/components/cards.js +2 -2
  29. package/dist/components/click.js +3 -3
  30. package/dist/components/depth.js +3 -3
  31. package/dist/components/effects.cjs +11 -336
  32. package/dist/components/effects.cjs.map +1 -1
  33. package/dist/components/effects.js +9 -333
  34. package/dist/components/effects.js.map +1 -1
  35. package/dist/components/feedback.js +1 -1
  36. package/dist/components/fx-3d.js +2 -2
  37. package/dist/components/fx-chart.cjs +158 -0
  38. package/dist/components/fx-chart.cjs.map +1 -0
  39. package/dist/components/fx-chart.d.cts +73 -0
  40. package/dist/components/fx-chart.d.ts +73 -0
  41. package/dist/components/fx-chart.js +154 -0
  42. package/dist/components/fx-chart.js.map +1 -0
  43. package/dist/components/fx-focus.js +2 -2
  44. package/dist/components/fx-gpu.js +3 -3
  45. package/dist/components/fx-light.js +2 -2
  46. package/dist/components/fx-morph.js +2 -2
  47. package/dist/components/fx-music.cjs +179 -0
  48. package/dist/components/fx-music.cjs.map +1 -0
  49. package/dist/components/fx-music.d.cts +102 -0
  50. package/dist/components/fx-music.d.ts +102 -0
  51. package/dist/components/fx-music.js +174 -0
  52. package/dist/components/fx-music.js.map +1 -0
  53. package/dist/components/fx-physics.js +2 -2
  54. package/dist/components/fx-text.js +2 -2
  55. package/dist/components/fx-transitions.js +3 -3
  56. package/dist/components/fx-weather.js +2 -2
  57. package/dist/components/fx.js +5 -5
  58. package/dist/components/fx2.cjs +14 -0
  59. package/dist/components/fx2.cjs.map +1 -1
  60. package/dist/components/fx2.d.cts +88 -1
  61. package/dist/components/fx2.d.ts +88 -1
  62. package/dist/components/fx2.js +14 -5
  63. package/dist/components/fx2.js.map +1 -1
  64. package/dist/components/gesture.js +4 -4
  65. package/dist/components/interaction.js +1 -1
  66. package/dist/components/layout.js +1 -1
  67. package/dist/components/marketplace.js +2 -2
  68. package/dist/components/packs.js +1 -1
  69. package/dist/components/page.js +3 -3
  70. package/dist/components/perf.js +2 -2
  71. package/dist/components/physics.js +3 -3
  72. package/dist/components/reveal.js +1 -1
  73. package/dist/components/solid.js +7 -7
  74. package/dist/components/svelte.js +7 -7
  75. package/dist/components/svg.js +1 -1
  76. package/dist/components/text.js +2 -2
  77. package/dist/components/timeline.js +3 -3
  78. package/dist/components/transitions.js +1 -1
  79. package/dist/components/ui.js +4 -4
  80. package/dist/components/vue.js +7 -7
  81. package/dist/components/webgl.js +1 -1
  82. package/dist/components/widgets.cjs +953 -61
  83. package/dist/components/widgets.cjs.map +1 -1
  84. package/dist/components/widgets.d.cts +143 -2
  85. package/dist/components/widgets.d.ts +143 -2
  86. package/dist/components/widgets.js +947 -67
  87. package/dist/components/widgets.js.map +1 -1
  88. package/dist/components.js +9 -9
  89. package/dist/index.js +2 -2
  90. package/dist/widgets.umd.js +1 -1
  91. package/dist/widgets.umd.js.map +1 -1
  92. package/docs/ROADMAP.md +2 -2
  93. package/docs/components.md +49 -0
  94. package/package.json +41 -1
@@ -1,14 +1,16 @@
1
1
  import { registerBuiltinEffects } from './fx.js';
2
2
  import { P as PALETTE, o as overlay, a as all, b as origin, s as spawn, r as rand, f as fxLayer } from '../chunks/shared-CkKHWrtJ.js';
3
- import { d as defineStory, a as definePlayer } from '../chunks/player-C-TwEEy6.js';
4
- export { A as ANIMATION_FORMAT, S as STORY_TEMPLATES, c as createPlayer, f as formatCount, n as normalizeAnimation, s as storyProgress } from '../chunks/player-C-TwEEy6.js';
3
+ import { d as defineStory, a as definePlayer } from '../chunks/player-DxvCYo7Q.js';
4
+ export { A as ANIMATION_FORMAT, S as STORY_TEMPLATES, c as createPlayer, f as formatCount, n as normalizeAnimation, s as storyProgress } from '../chunks/player-DxvCYo7Q.js';
5
5
  import { c as canvasBackground, h as hexRgb, G as GENERATIVE_FX } from '../chunks/generative-2LhxG5BJ.js';
6
6
  export { n as noise2 } from '../chunks/generative-2LhxG5BJ.js';
7
- import { playEffect, bindEffect, registerEffects } from '../chunks/registry-D23neB4M.js';
8
- import { y as defineElement, p as prefersReducedMotion, v as adoptStyles } from '../chunks/base-DchG4q_S.js';
7
+ import { A as AUDIO_FX, d as defineAudio } from '../chunks/audio-DcPvT2Kh.js';
8
+ export { b as bindBeat, c as createBeatDetector, a as disableAudio, e as enableAudio, g as getAudio, o as onBeat } from '../chunks/audio-DcPvT2Kh.js';
9
+ import { playEffect, bindEffect, registerEffects } from '../chunks/registry-CyKExAmE.js';
10
+ import { u as defineElement, x as adoptStyles } from '../chunks/base-2-yYc93C.js';
9
11
  import { applyMotionTokens, motionTokensToVars, mergeMotionTokens } from './tokens.js';
10
- import '../chunks/core-DVyTlo9Q.js';
11
- import '../chunks/fx-DUMVKSvg.js';
12
+ import '../chunks/core-D5rU0CV6.js';
13
+ import '../chunks/fx-CMxWNwH8.js';
12
14
 
13
15
  const CARD_FX = [
14
16
  {
@@ -575,332 +577,6 @@ const PAGE_FX = [
575
577
  },
576
578
  ];
577
579
 
578
- let actx = null;
579
- let current = null;
580
- const mediaSources = new WeakMap();
581
- /** The running analyser, if `enableAudio()` was called. */
582
- const getAudio = () => current;
583
- function audioContext() {
584
- const AC = globalThis.AudioContext || globalThis.webkitAudioContext;
585
- if (!AC)
586
- throw new Error('[motionary] Web Audio is not available');
587
- if (!actx || actx.state === 'closed')
588
- actx = new AC();
589
- return actx;
590
- }
591
- /**
592
- * Start analysing `input` and make it the source of every sound-reactive
593
- * effect. Call from a user gesture. Replaces a previous source.
594
- */
595
- async function enableAudio(input = 'mic', opts = {}) {
596
- current?.stop();
597
- const ac = audioContext();
598
- if (ac.state === 'suspended')
599
- await ac.resume().catch(() => undefined);
600
- const analyser = ac.createAnalyser();
601
- analyser.fftSize = opts.fftSize || 512;
602
- analyser.smoothingTimeConstant = opts.smoothing ?? 0.8;
603
- let src;
604
- let release = () => { };
605
- const media = typeof input === 'string' && input !== 'mic' ? document.querySelector(input) : input;
606
- if (media === 'mic') {
607
- const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
608
- src = ac.createMediaStreamSource(stream);
609
- src.connect(analyser); // never to the speakers: no feedback
610
- release = () => stream.getTracks().forEach((t) => t.stop());
611
- }
612
- else if (media && typeof media.play === 'function') {
613
- const m = media;
614
- let node = mediaSources.get(m);
615
- if (!node)
616
- mediaSources.set(m, (node = ac.createMediaElementSource(m)));
617
- try {
618
- node.disconnect();
619
- }
620
- catch {
621
- /* not connected */
622
- }
623
- src = node;
624
- src.connect(analyser);
625
- analyser.connect(ac.destination);
626
- release = () => {
627
- try {
628
- node.disconnect();
629
- }
630
- catch {
631
- /* already */
632
- }
633
- node.connect(ac.destination); // keep the media audible
634
- };
635
- if (m.paused)
636
- await m.play()?.catch?.(() => undefined);
637
- }
638
- else if (media && typeof media.getTracks === 'function') {
639
- src = ac.createMediaStreamSource(media);
640
- src.connect(analyser);
641
- }
642
- else
643
- throw new Error(`[motionary] enableAudio: no audio source for ${String(input)}`);
644
- const freq = new Uint8Array(analyser.frequencyBinCount);
645
- const wave = new Uint8Array(analyser.fftSize);
646
- const self = {
647
- context: ac,
648
- analyser,
649
- sample: () => {
650
- analyser.getByteFrequencyData(freq);
651
- analyser.getByteTimeDomainData(wave);
652
- let sq = 0;
653
- for (let i = 0; i < wave.length; i++)
654
- sq += ((wave[i] - 128) / 128) ** 2;
655
- const n = Math.max(1, Math.round(freq.length * 0.08));
656
- let b = 0;
657
- for (let i = 0; i < n; i++)
658
- b += freq[i];
659
- return { level: Math.min(1, Math.sqrt(sq / wave.length) * 2), bass: b / n / 255, freq, wave };
660
- },
661
- stop: () => {
662
- if (current === self) {
663
- current = null;
664
- if (raf && typeof cancelAnimationFrame === 'function')
665
- cancelAnimationFrame(raf);
666
- raf = 0;
667
- }
668
- try {
669
- src.disconnect();
670
- analyser.disconnect();
671
- }
672
- catch {
673
- /* already */
674
- }
675
- release();
676
- setVars(0, 0);
677
- },
678
- };
679
- current = self;
680
- kick();
681
- return self;
682
- }
683
- /** Stop the current audio source (if any). */
684
- function disableAudio() {
685
- current?.stop();
686
- }
687
- /** A pure beat detector: feed it energy (0–1) and a timestamp per frame; it answers "beat?". */
688
- function createBeatDetector(o = {}) {
689
- const { threshold = 1.35, cooldown = 250, history = 43, floor = 0.08 } = o;
690
- const hist = [];
691
- let last = -Infinity;
692
- return (energy, now) => {
693
- const avg = hist.length ? hist.reduce((a, b) => a + b, 0) / hist.length : energy;
694
- const ready = hist.length >= 8;
695
- hist.push(energy);
696
- if (hist.length > history)
697
- hist.shift();
698
- if (ready && energy > floor && energy > avg * threshold && now - last >= cooldown) {
699
- last = now;
700
- return true;
701
- }
702
- return false;
703
- };
704
- }
705
- const listeners = new Set();
706
- let raf = 0;
707
- function setVars(level, bass) {
708
- if (typeof document === 'undefined')
709
- return;
710
- const s = document.documentElement.style;
711
- s.setProperty('--usa-audio-level', level.toFixed(3));
712
- s.setProperty('--usa-audio-bass', bass.toFixed(3));
713
- }
714
- function loop(now) {
715
- raf = 0;
716
- if (!current)
717
- return;
718
- const { level, bass } = current.sample();
719
- const reduced = prefersReducedMotion();
720
- setVars(reduced ? 0 : level, reduced ? 0 : bass);
721
- for (const l of Array.from(listeners))
722
- if (l.detect(bass, now))
723
- l.cb({ energy: bass, time: now });
724
- kick();
725
- }
726
- function kick() {
727
- if (!raf && current && typeof requestAnimationFrame === 'function')
728
- raf = requestAnimationFrame(loop);
729
- }
730
- /** Call `cb` on every detected beat of the current audio source. Returns an unsubscribe. */
731
- function onBeat(cb, o = {}) {
732
- const l = { detect: createBeatDetector(o), cb };
733
- listeners.add(l);
734
- kick();
735
- return () => void listeners.delete(l);
736
- }
737
- /** Play the registered effect `name` on `el` at every beat (not under reduced motion). Returns an unbind. */
738
- function bindBeat(el, name, options = {}) {
739
- const { threshold, cooldown, history, floor, ...fx } = options;
740
- return onBeat(() => {
741
- if (!prefersReducedMotion())
742
- playEffect(el, name, fx).catch(() => undefined);
743
- }, { threshold, cooldown, history, floor });
744
- }
745
- // --- visual effects ----------------------------------------------------------
746
- /** The current sample, or a gentle synthetic one while no audio is enabled. */
747
- function read(t, bins) {
748
- if (current)
749
- return { ...current.sample(), idle: false };
750
- const freq = new Uint8Array(bins);
751
- const wave = new Uint8Array(bins * 2);
752
- for (let i = 0; i < bins; i++)
753
- freq[i] = 70 + 50 * Math.sin(t * 2 + i * 0.35) * Math.cos(t * 0.7 + i * 0.11) * (1 - i / bins);
754
- for (let i = 0; i < wave.length; i++)
755
- wave[i] = 128 + 22 * Math.sin(t * 3 + i * 0.12);
756
- return { level: 0.25 + 0.1 * Math.sin(t * 2), bass: 0.35 + 0.2 * Math.sin(t * 2.4), freq, wave, idle: true };
757
- }
758
- const audioFx = (name, description, defaults, spec) => ({
759
- name,
760
- kind: 'background',
761
- description,
762
- reduced: 'skip',
763
- defaults: { colors: PALETTE, background: '#0b0d12', speed: 1, quality: 1, ...defaults },
764
- run: (el, o, ctx) => canvasBackground(el, ctx, spec, o),
765
- });
766
- const AUDIO_FX = [
767
- audioFx('spectrum-bars', 'Frequency bars dance to the audio (mirror them with `mirror: true`).', { bars: 48, gap: 2, mirror: false }, {
768
- draw: ({ ctx, w, h, t, o }) => {
769
- ctx.fillStyle = o.background;
770
- ctx.fillRect(0, 0, w, h);
771
- const s = read(t, o.bars);
772
- const per = Math.max(1, Math.floor((s.freq.length * 0.7) / o.bars));
773
- const bw = w / o.bars;
774
- for (let i = 0; i < o.bars; i++) {
775
- let v = 0;
776
- for (let k = 0; k < per; k++)
777
- v += s.freq[Math.min(s.freq.length - 1, i * per + k)];
778
- const bh = (v / per / 255) * h * (o.mirror ? 0.5 : 0.9);
779
- ctx.fillStyle = o.colors[i % o.colors.length];
780
- 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);
781
- }
782
- },
783
- }),
784
- audioFx('pulse-ring', 'Glowing rings pulse with the bass.', { rings: 3, color: '#7c5cff' }, {
785
- draw: ({ ctx, w, h, t, o }) => {
786
- ctx.fillStyle = o.background;
787
- ctx.fillRect(0, 0, w, h);
788
- const s = read(t, 32);
789
- const [r, g, b] = hexRgb(o.color);
790
- const base = Math.min(w, h) * 0.18;
791
- for (let i = 0; i < o.rings; i++) {
792
- const rad = base * (1 + i * 0.55) * (1 + s.bass * 0.6);
793
- ctx.strokeStyle = `rgba(${r},${g},${b},${(0.9 - i * 0.25) * (0.4 + s.level)})`;
794
- ctx.lineWidth = 3 + s.bass * 10 - i;
795
- ctx.beginPath();
796
- ctx.arc(w / 2, h / 2, rad, 0, Math.PI * 2);
797
- ctx.stroke();
798
- }
799
- },
800
- }),
801
- audioFx('wave-ring', 'The live waveform wrapped into a circle.', { color: '#22d3ee', amplitude: 0.35 }, {
802
- draw: ({ ctx, w, h, t, o }) => {
803
- ctx.fillStyle = o.background;
804
- ctx.fillRect(0, 0, w, h);
805
- const s = read(t, 64);
806
- const n = s.wave.length;
807
- const base = Math.min(w, h) * 0.28;
808
- ctx.strokeStyle = o.color;
809
- ctx.lineWidth = 2;
810
- ctx.beginPath();
811
- for (let i = 0; i <= n; i++) {
812
- const a = (i / n) * Math.PI * 2;
813
- const rad = base * (1 + ((s.wave[i % n] - 128) / 128) * o.amplitude * 2);
814
- const x = w / 2 + Math.cos(a) * rad;
815
- const y = h / 2 + Math.sin(a) * rad;
816
- if (i)
817
- ctx.lineTo(x, y);
818
- else
819
- ctx.moveTo(x, y);
820
- }
821
- ctx.closePath();
822
- ctx.stroke();
823
- },
824
- }),
825
- ];
826
- /**
827
- * `<usa-audio source="#track | mic" label="…">` — a toggle button (yours, as
828
- * `[data-audio-toggle]`, or one it renders) that enables the audio source on
829
- * click; children with `data-usa-beat="effect"` play that effect on every
830
- * beat (`data-usa-beat-options` JSON; `threshold` / `cooldown` attributes).
831
- * Emits `usa-beat` and `usa-audio-error`.
832
- */
833
- function defineAudio(tag = 'usa-audio') {
834
- return defineElement(tag, (Base) => class UsaAudio extends Base {
835
- constructor() {
836
- super(...arguments);
837
- this.active = false;
838
- this.audio = null;
839
- this.off = null;
840
- }
841
- static get observedAttributes() {
842
- return ['source'];
843
- }
844
- button() {
845
- let b = this.querySelector('[data-audio-toggle]');
846
- if (!b) {
847
- b = document.createElement('button');
848
- b.type = 'button';
849
- b.setAttribute('data-audio-toggle', '');
850
- b.textContent = this.str('label', '🔊 Enable sound-reactive effects');
851
- this.prepend(b);
852
- this.onCleanup(() => b.remove());
853
- }
854
- return b;
855
- }
856
- async toggle() {
857
- const b = this.button();
858
- if (this.active)
859
- return this.stop();
860
- try {
861
- this.audio = await enableAudio(this.str('source', 'mic'));
862
- this.active = true;
863
- this.removeAttribute('data-audio-error');
864
- b.setAttribute('aria-pressed', 'true');
865
- this.off = onBeat((d) => {
866
- this.dispatchEvent(new CustomEvent('usa-beat', { detail: d, bubbles: true }));
867
- if (prefersReducedMotion())
868
- return;
869
- this.querySelectorAll('[data-usa-beat]').forEach((el) => {
870
- let opts = {};
871
- try {
872
- opts = JSON.parse(el.dataset.usaBeatOptions || '{}') || {};
873
- }
874
- catch {
875
- /* ignore bad JSON */
876
- }
877
- playEffect(el, el.dataset.usaBeat || 'pulse', opts).catch(() => undefined);
878
- });
879
- }, { threshold: this.num('threshold', 1.35), cooldown: this.num('cooldown', 250) });
880
- }
881
- catch (err) {
882
- this.setAttribute('data-audio-error', '');
883
- this.dispatchEvent(new CustomEvent('usa-audio-error', { detail: { error: err }, bubbles: true }));
884
- }
885
- }
886
- stop() {
887
- this.off?.();
888
- this.off = null;
889
- if (this.audio && current === this.audio)
890
- this.audio.stop();
891
- this.audio = null;
892
- this.active = false;
893
- this.querySelector('[data-audio-toggle]')?.setAttribute('aria-pressed', 'false');
894
- }
895
- mount() {
896
- const b = this.button();
897
- b.setAttribute('aria-pressed', 'false');
898
- this.listen(b, 'click', () => void this.toggle());
899
- this.onCleanup(() => this.stop());
900
- }
901
- }, { id: 'usa-audio', text: 'usa-audio{display:block}usa-audio[data-audio-error] [data-audio-toggle]{outline:2px solid #ff5c8a}' });
902
- }
903
-
904
580
  const touchOk = (e, o) => o.touch || e.pointerType !== 'touch';
905
581
  /** A fixed, viewport-sized canvas in the fx layer, redrawn while `draw` returns true. */
906
582
  function overlayCanvas(draw) {
@@ -1689,5 +1365,5 @@ function registerAllEffects() {
1689
1365
  registerEffects(defs);
1690
1366
  }
1691
1367
 
1692
- export { AUDIO_FX, CARD_FX, CLICK_FX, CURSOR_FX, EFFECT_PACKS, GENERATIVE_FX, GESTURES, MICRO_FX, PAGE_FX, PHYSICS_FX, THEMES, THEME_FX, THEME_NAMES, THEME_ROLES, angleDelta, applyTheme, bindBeat, bindGesture, bounceKeyframes, bumpCount, canvasBackground, createBeatDetector, defineAudio, defineEffectElements, defineGestureFx, definePlayer, defineStory, defineTheme, disableAudio, enableAudio, flingVelocity, fxLayer, getAudio, hexRgb, onBeat, playThemeEffect, registerAllEffects, registerAudioEffects, registerCardClickEffects, registerCursorEffects, registerGenerativeEffects, registerMicroEffects, registerPageEffects, registerPhysicsEffects, solveSpring, springKeyframes, swapLabel, themeCss, themePreset, themeVars, togglePressed };
1368
+ export { AUDIO_FX, CARD_FX, CLICK_FX, CURSOR_FX, EFFECT_PACKS, GENERATIVE_FX, GESTURES, MICRO_FX, PAGE_FX, PHYSICS_FX, THEMES, THEME_FX, THEME_NAMES, THEME_ROLES, angleDelta, applyTheme, bindGesture, bounceKeyframes, bumpCount, canvasBackground, defineAudio, defineEffectElements, defineGestureFx, definePlayer, defineStory, defineTheme, flingVelocity, fxLayer, hexRgb, playThemeEffect, registerAllEffects, registerAudioEffects, registerCardClickEffects, registerCursorEffects, registerGenerativeEffects, registerMicroEffects, registerPageEffects, registerPhysicsEffects, solveSpring, springKeyframes, swapLabel, themeCss, themePreset, themeVars, togglePressed };
1693
1369
  //# sourceMappingURL=effects.js.map