@cuemath/leap 3.3.25-af → 3.3.25-af-1

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.
@@ -1,9 +1,9 @@
1
- import { useRef as p, useCallback as c, useEffect as D } from "react";
2
- import { useAutoPlayPermission as L } from "../../../hooks/use-auto-play-permission/use-auto-play-permission.js";
3
- import { CircleSoundKeyMapper as h, SWIPE_SOUND_ORDER as I } from "./constants.js";
1
+ import { useRef as O, useCallback as a, useEffect as v } from "react";
2
+ import { useAutoPlayPermission as D } from "../../../hooks/use-auto-play-permission/use-auto-play-permission.js";
3
+ import { CircleSoundKeyMapper as L, SWIPE_SOUND_ORDER as p } from "./constants.js";
4
4
  import { CircleSoundKey as n } from "./use-circle-sounds-enums.js";
5
- let A = 0;
6
- const l = new (window.AudioContext || window.webkitAudioContext)(), T = {
5
+ let m = 0;
6
+ const l = new (window.AudioContext || window.webkitAudioContext)(), C = {
7
7
  [n.BACKGROUND]: null,
8
8
  [n.BACKGROUND_RUSHHOUR]: null,
9
9
  [n.TUTORIAL]: null,
@@ -32,78 +32,83 @@ const l = new (window.AudioContext || window.webkitAudioContext)(), T = {
32
32
  [n.KEEP_IT_UP]: null,
33
33
  [n.DOING_GREAT]: null,
34
34
  [n.ALL_DONE]: null
35
- }, i = {}, y = () => {
36
- const { canAutoPlayAudio: m } = L(), d = p(/* @__PURE__ */ new Set()), C = p({}), R = c(async (e) => {
37
- if (!T[e]) {
38
- const o = await (await fetch(h[e])).arrayBuffer(), t = await l.decodeAudioData(o);
39
- T[e] = t;
35
+ }, r = {}, N = () => {
36
+ const { canAutoPlayAudio: d } = D(), f = O(/* @__PURE__ */ new Set()), R = O({}), _ = a(async (e) => {
37
+ if (!C[e]) {
38
+ const o = await (await fetch(L[e])).arrayBuffer(), t = await l.decodeAudioData(o);
39
+ C[e] = t;
40
40
  }
41
- }, []), _ = async () => {
41
+ }, []), E = async () => {
42
42
  if (l.state === "suspended")
43
43
  try {
44
44
  await l.resume();
45
45
  } catch (e) {
46
46
  console.warn("Failed to resume AudioContext:", e);
47
47
  }
48
- }, w = (e) => {
48
+ }, I = (e) => {
49
49
  e.gain.setValueAtTime(0, l.currentTime), e.gain.linearRampToValueAtTime(1, l.currentTime + 0.5);
50
- }, P = (e, u) => {
50
+ }, w = (e, u) => {
51
51
  e.gain.setValueAtTime(e.gain.value, l.currentTime), e.gain.linearRampToValueAtTime(0, l.currentTime + 0.5);
52
52
  const o = setTimeout(() => {
53
53
  var t;
54
- (t = i[u]) == null || t.source.stop(), delete i[u];
54
+ (t = r[u]) == null || t.source.stop(), delete r[u];
55
55
  }, 500);
56
- C.current[u] = o;
57
- }, r = c(
56
+ R.current[u] = o;
57
+ }, i = a(
58
58
  async (e, u = !0, o = !1) => {
59
- await R(e);
60
- const t = T[e];
61
- if (!t || !m) return;
62
- const S = i[e];
63
- S && (S.source.stop(), delete i[e]);
64
- const s = l.createBufferSource(), a = l.createGain();
65
- s.buffer = t, s.loop = o, s.connect(a).connect(l.destination), u ? a.gain.setValueAtTime(1, l.currentTime) : w(a), s.start(), i[e] = { source: s, gainNode: a }, o || (s.onended = () => {
66
- var O;
67
- ((O = i[e]) == null ? void 0 : O.source) === s && delete i[e];
59
+ await E(), await _(e);
60
+ const t = C[e];
61
+ if (!t || !d) {
62
+ console.warn("Cannot play sound", e, { buffer: t, canPlayAudio: d });
63
+ return;
64
+ }
65
+ if (r[e] && o) {
66
+ console.log("Sound already playing:", e);
67
+ return;
68
+ }
69
+ const s = l.createBufferSource(), c = l.createGain();
70
+ s.buffer = t, s.loop = o, s.connect(c).connect(l.destination), u ? c.gain.setValueAtTime(1, l.currentTime) : I(c), s.start(), r[e] = { source: s, gainNode: c }, o || (s.onended = () => {
71
+ var S;
72
+ ((S = r[e]) == null ? void 0 : S.source) === s && delete r[e];
68
73
  });
69
74
  },
70
- [m, R]
71
- ), f = c(async (e, u = !0) => {
72
- const o = i[e];
73
- o && (u ? (o.source.stop(), delete i[e]) : P(o.gainNode, e));
74
- }, []), U = c(() => {
75
- const e = I[A] || n.SWIPE_01;
76
- A = (A + 1) % I.length, r(e);
77
- }, [r]), v = c(() => {
78
- r(n.TOGGLE);
79
- }, [r]), E = c(async () => {
80
- document.visibilityState === "visible" ? (await _(), d.current.forEach((e) => {
81
- r(e);
82
- }), d.current.clear()) : Object.keys(i).forEach((e) => {
83
- f(e, !0), d.current.add(e);
75
+ [d, _]
76
+ ), A = a(async (e, u = !0) => {
77
+ const o = r[e];
78
+ o && (u ? (o.source.stop(), delete r[e]) : w(o.gainNode, e));
79
+ }, []), P = a(() => {
80
+ const e = p[m] || n.SWIPE_01;
81
+ m = (m + 1) % p.length, i(e);
82
+ }, [i]), U = a(() => {
83
+ i(n.TOGGLE);
84
+ }, [i]), T = a(async () => {
85
+ document.visibilityState === "visible" ? (await E(), f.current.forEach((e) => {
86
+ i(e);
87
+ }), f.current.clear()) : Object.keys(r).forEach((e) => {
88
+ A(e, !0), f.current.add(e);
84
89
  });
85
- }, [r, f]);
86
- return D(() => {
90
+ }, [i, A]);
91
+ return v(() => {
87
92
  const e = ["pointerdown", "touchstart"], u = () => {
88
- _();
93
+ E();
89
94
  };
90
- document.addEventListener("visibilitychange", E), e.forEach((t) => {
95
+ document.addEventListener("visibilitychange", T), e.forEach((t) => {
91
96
  window.addEventListener(t, u, { once: !0 });
92
97
  });
93
- const o = C.current;
98
+ const o = R.current;
94
99
  return () => {
95
- document.removeEventListener("visibilitychange", E), e.forEach((t) => {
100
+ document.removeEventListener("visibilitychange", T), e.forEach((t) => {
96
101
  window.removeEventListener(t, u);
97
102
  }), Object.values(o).forEach((t) => clearTimeout(t));
98
103
  };
99
- }, [E]), {
100
- playSwipeSound: U,
101
- play: r,
102
- stop: f,
103
- playButtonSound: v
104
+ }, [T]), {
105
+ playSwipeSound: P,
106
+ play: i,
107
+ stop: A,
108
+ playButtonSound: U
104
109
  };
105
110
  };
106
111
  export {
107
- y as useCircleSounds
112
+ N as useCircleSounds
108
113
  };
109
114
  //# sourceMappingURL=use-circle-sounds.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-circle-sounds.js","sources":["../../../../../src/features/circle-games/hooks/use-circle-sounds/use-circle-sounds.ts"],"sourcesContent":["import type { TimeoutMap } from './use-circle-sound-types';\n\nimport { useCallback, useEffect, useRef } from 'react';\n\nimport { useAutoPlayPermission } from '../../../hooks/use-auto-play-permission/use-auto-play-permission';\nimport { CircleSoundKeyMapper, SWIPE_SOUND_ORDER } from './constants';\nimport { CircleSoundKey } from './use-circle-sounds-enums';\n\nlet swipeSoundIndex = 0;\nconst audioContext = new (window.AudioContext || window.webkitAudioContext)();\n\nconst bufferMapper: Record<CircleSoundKey, AudioBuffer | null> = {\n [CircleSoundKey.BACKGROUND]: null,\n [CircleSoundKey.BACKGROUND_RUSHHOUR]: null,\n [CircleSoundKey.TUTORIAL]: null,\n [CircleSoundKey.SWIPE_01]: null,\n [CircleSoundKey.SWIPE_02]: null,\n [CircleSoundKey.SWIPE_03]: null,\n [CircleSoundKey.SWIPE_04]: null,\n [CircleSoundKey.SWIPE_DOWN]: null,\n [CircleSoundKey.TOGGLE]: null,\n [CircleSoundKey.POINTS_AWARDED]: null,\n [CircleSoundKey.POINTS_ADDED]: null,\n [CircleSoundKey.GAME_CARD_CLICK]: null,\n [CircleSoundKey.CLOCK_IN]: null,\n [CircleSoundKey.CLOCK_OUT]: null,\n [CircleSoundKey.ACCURACY_IN]: null,\n [CircleSoundKey.ACCURACY_OUT]: null,\n [CircleSoundKey.STREAK_IN]: null,\n [CircleSoundKey.STREAK_OUT]: null,\n [CircleSoundKey.ACCURACY_INTRO]: null,\n [CircleSoundKey.ACCURACY_TARGET]: null,\n [CircleSoundKey.TIME_INTRO]: null,\n [CircleSoundKey.TIME_TARGET]: null,\n [CircleSoundKey.METER_FILL]: null,\n [CircleSoundKey.YOUR_SCORE]: null,\n [CircleSoundKey.HIGH_SCORE]: null,\n [CircleSoundKey.KEEP_IT_UP]: null,\n [CircleSoundKey.DOING_GREAT]: null,\n [CircleSoundKey.ALL_DONE]: null,\n};\n\ntype ActiveSound = {\n source: AudioBufferSourceNode;\n gainNode: GainNode;\n};\n\nconst activeSounds: Partial<Record<CircleSoundKey, ActiveSound>> = {};\n\nexport const useCircleSounds = () => {\n const { canAutoPlayAudio: canPlayAudio } = useAutoPlayPermission();\n\n const pausedSoundsRef = useRef<Set<CircleSoundKey>>(new Set());\n const timeoutRefs = useRef<TimeoutMap>({});\n\n const loadSound = useCallback(async (key: CircleSoundKey) => {\n if (!bufferMapper[key]) {\n const response = await fetch(CircleSoundKeyMapper[key]);\n const arrayBuffer = await response.arrayBuffer();\n const decoded = await audioContext.decodeAudioData(arrayBuffer);\n\n bufferMapper[key] = decoded;\n }\n }, []);\n\n const resumeAudioContext = async () => {\n if (audioContext.state === 'suspended') {\n try {\n await audioContext.resume();\n } catch (err) {\n // eslint-disable-next-line no-console\n console.warn('Failed to resume AudioContext:', err);\n }\n }\n };\n\n const fadeIn = (gainNode: GainNode) => {\n gainNode.gain.setValueAtTime(0, audioContext.currentTime);\n gainNode.gain.linearRampToValueAtTime(1, audioContext.currentTime + 0.5);\n };\n\n const fadeOut = (gainNode: GainNode, key: CircleSoundKey) => {\n gainNode.gain.setValueAtTime(gainNode.gain.value, audioContext.currentTime);\n gainNode.gain.linearRampToValueAtTime(0, audioContext.currentTime + 0.5);\n const timeout = setTimeout(() => {\n activeSounds[key]?.source.stop();\n delete activeSounds[key];\n }, 500);\n\n timeoutRefs.current[key] = timeout as unknown as number;\n };\n\n const play = useCallback(\n async (key: CircleSoundKey, immediately = true, loop = false) => {\n await loadSound(key);\n const buffer = bufferMapper[key];\n\n if (!buffer || !canPlayAudio) return;\n\n const existing = activeSounds[key];\n\n if (existing) {\n existing.source.stop();\n delete activeSounds[key];\n }\n\n const source = audioContext.createBufferSource();\n const gainNode = audioContext.createGain();\n\n source.buffer = buffer;\n source.loop = loop;\n source.connect(gainNode).connect(audioContext.destination);\n\n if (immediately) {\n gainNode.gain.setValueAtTime(1, audioContext.currentTime);\n } else {\n fadeIn(gainNode);\n }\n\n source.start();\n activeSounds[key] = { source, gainNode };\n\n // Clean up when finished if not looping\n if (!loop) {\n source.onended = () => {\n if (activeSounds[key]?.source === source) {\n delete activeSounds[key];\n }\n };\n }\n },\n [canPlayAudio, loadSound],\n );\n\n const stop = useCallback(async (key: CircleSoundKey, immediately = true) => {\n const sound = activeSounds[key];\n\n if (!sound) return;\n\n if (immediately) {\n sound.source.stop();\n delete activeSounds[key];\n } else {\n fadeOut(sound.gainNode, key);\n }\n }, []);\n\n const playSwipeSound = useCallback(() => {\n const key = SWIPE_SOUND_ORDER[swipeSoundIndex] || CircleSoundKey.SWIPE_01;\n\n swipeSoundIndex = (swipeSoundIndex + 1) % SWIPE_SOUND_ORDER.length;\n play(key);\n }, [play]);\n\n const playButtonSound = useCallback(() => {\n play(CircleSoundKey.TOGGLE);\n }, [play]);\n\n const handleVisibilityChange = useCallback(async () => {\n if (document.visibilityState === 'visible') {\n await resumeAudioContext();\n pausedSoundsRef.current.forEach(key => {\n play(key);\n });\n pausedSoundsRef.current.clear();\n } else {\n Object.keys(activeSounds).forEach(key => {\n stop(key as CircleSoundKey, true);\n pausedSoundsRef.current.add(key as CircleSoundKey);\n });\n }\n }, [play, stop]);\n\n useEffect(() => {\n const interactionEvents = ['pointerdown', 'touchstart'];\n const tryResume = () => {\n resumeAudioContext();\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n interactionEvents.forEach(event => {\n window.addEventListener(event, tryResume, { once: true });\n });\n\n const timeouts = timeoutRefs.current;\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n interactionEvents.forEach(event => {\n window.removeEventListener(event, tryResume);\n });\n Object.values(timeouts).forEach(id => clearTimeout(id));\n };\n }, [handleVisibilityChange]);\n\n return {\n playSwipeSound,\n play,\n stop,\n playButtonSound,\n };\n};\n"],"names":["swipeSoundIndex","audioContext","bufferMapper","CircleSoundKey","activeSounds","useCircleSounds","canPlayAudio","useAutoPlayPermission","pausedSoundsRef","useRef","timeoutRefs","loadSound","useCallback","key","arrayBuffer","CircleSoundKeyMapper","decoded","resumeAudioContext","err","fadeIn","gainNode","fadeOut","timeout","_a","play","immediately","loop","buffer","existing","source","stop","sound","playSwipeSound","SWIPE_SOUND_ORDER","playButtonSound","handleVisibilityChange","useEffect","interactionEvents","tryResume","event","timeouts","id"],"mappings":"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"}
1
+ {"version":3,"file":"use-circle-sounds.js","sources":["../../../../../src/features/circle-games/hooks/use-circle-sounds/use-circle-sounds.ts"],"sourcesContent":["import type { TimeoutMap } from './use-circle-sound-types';\n\nimport { useCallback, useEffect, useRef } from 'react';\n\nimport { useAutoPlayPermission } from '../../../hooks/use-auto-play-permission/use-auto-play-permission';\nimport { CircleSoundKeyMapper, SWIPE_SOUND_ORDER } from './constants';\nimport { CircleSoundKey } from './use-circle-sounds-enums';\n\nlet swipeSoundIndex = 0;\nconst audioContext = new (window.AudioContext || window.webkitAudioContext)();\n\nconst bufferMapper: Record<CircleSoundKey, AudioBuffer | null> = {\n [CircleSoundKey.BACKGROUND]: null,\n [CircleSoundKey.BACKGROUND_RUSHHOUR]: null,\n [CircleSoundKey.TUTORIAL]: null,\n [CircleSoundKey.SWIPE_01]: null,\n [CircleSoundKey.SWIPE_02]: null,\n [CircleSoundKey.SWIPE_03]: null,\n [CircleSoundKey.SWIPE_04]: null,\n [CircleSoundKey.SWIPE_DOWN]: null,\n [CircleSoundKey.TOGGLE]: null,\n [CircleSoundKey.POINTS_AWARDED]: null,\n [CircleSoundKey.POINTS_ADDED]: null,\n [CircleSoundKey.GAME_CARD_CLICK]: null,\n [CircleSoundKey.CLOCK_IN]: null,\n [CircleSoundKey.CLOCK_OUT]: null,\n [CircleSoundKey.ACCURACY_IN]: null,\n [CircleSoundKey.ACCURACY_OUT]: null,\n [CircleSoundKey.STREAK_IN]: null,\n [CircleSoundKey.STREAK_OUT]: null,\n [CircleSoundKey.ACCURACY_INTRO]: null,\n [CircleSoundKey.ACCURACY_TARGET]: null,\n [CircleSoundKey.TIME_INTRO]: null,\n [CircleSoundKey.TIME_TARGET]: null,\n [CircleSoundKey.METER_FILL]: null,\n [CircleSoundKey.YOUR_SCORE]: null,\n [CircleSoundKey.HIGH_SCORE]: null,\n [CircleSoundKey.KEEP_IT_UP]: null,\n [CircleSoundKey.DOING_GREAT]: null,\n [CircleSoundKey.ALL_DONE]: null,\n};\n\ntype ActiveSound = {\n source: AudioBufferSourceNode;\n gainNode: GainNode;\n};\n\nconst activeSounds: Partial<Record<CircleSoundKey, ActiveSound>> = {};\n\nexport const useCircleSounds = () => {\n const { canAutoPlayAudio: canPlayAudio } = useAutoPlayPermission();\n\n const pausedSoundsRef = useRef<Set<CircleSoundKey>>(new Set());\n const timeoutRefs = useRef<TimeoutMap>({});\n\n const loadSound = useCallback(async (key: CircleSoundKey) => {\n if (!bufferMapper[key]) {\n const response = await fetch(CircleSoundKeyMapper[key]);\n const arrayBuffer = await response.arrayBuffer();\n const decoded = await audioContext.decodeAudioData(arrayBuffer);\n\n bufferMapper[key] = decoded;\n }\n }, []);\n\n const resumeAudioContext = async () => {\n if (audioContext.state === 'suspended') {\n try {\n await audioContext.resume();\n } catch (err) {\n // eslint-disable-next-line no-console\n console.warn('Failed to resume AudioContext:', err);\n }\n }\n };\n\n const fadeIn = (gainNode: GainNode) => {\n gainNode.gain.setValueAtTime(0, audioContext.currentTime);\n gainNode.gain.linearRampToValueAtTime(1, audioContext.currentTime + 0.5);\n };\n\n const fadeOut = (gainNode: GainNode, key: CircleSoundKey) => {\n gainNode.gain.setValueAtTime(gainNode.gain.value, audioContext.currentTime);\n gainNode.gain.linearRampToValueAtTime(0, audioContext.currentTime + 0.5);\n const timeout = setTimeout(() => {\n activeSounds[key]?.source.stop();\n delete activeSounds[key];\n }, 500);\n\n timeoutRefs.current[key] = timeout as unknown as number;\n };\n\n const play = useCallback(\n async (key: CircleSoundKey, immediately = true, loop = false) => {\n await resumeAudioContext();\n await loadSound(key);\n const buffer = bufferMapper[key];\n\n if (!buffer || !canPlayAudio) {\n // eslint-disable-next-line no-console\n console.warn('Cannot play sound', key, { buffer, canPlayAudio });\n\n return;\n }\n\n if (activeSounds[key] && loop) {\n // eslint-disable-next-line no-console\n console.log('Sound already playing:', key);\n\n return;\n }\n\n const source = audioContext.createBufferSource();\n const gainNode = audioContext.createGain();\n\n source.buffer = buffer;\n source.loop = loop;\n source.connect(gainNode).connect(audioContext.destination);\n\n if (immediately) {\n gainNode.gain.setValueAtTime(1, audioContext.currentTime);\n } else {\n fadeIn(gainNode);\n }\n\n source.start();\n activeSounds[key] = { source, gainNode };\n\n if (!loop) {\n source.onended = () => {\n if (activeSounds[key]?.source === source) {\n delete activeSounds[key];\n }\n };\n }\n },\n [canPlayAudio, loadSound],\n );\n\n const stop = useCallback(async (key: CircleSoundKey, immediately = true) => {\n const sound = activeSounds[key];\n\n if (!sound) return;\n\n if (immediately) {\n sound.source.stop();\n delete activeSounds[key];\n } else {\n fadeOut(sound.gainNode, key);\n }\n }, []);\n\n const playSwipeSound = useCallback(() => {\n const key = SWIPE_SOUND_ORDER[swipeSoundIndex] || CircleSoundKey.SWIPE_01;\n\n swipeSoundIndex = (swipeSoundIndex + 1) % SWIPE_SOUND_ORDER.length;\n play(key);\n }, [play]);\n\n const playButtonSound = useCallback(() => {\n play(CircleSoundKey.TOGGLE);\n }, [play]);\n\n const handleVisibilityChange = useCallback(async () => {\n if (document.visibilityState === 'visible') {\n await resumeAudioContext();\n pausedSoundsRef.current.forEach(key => {\n play(key);\n });\n pausedSoundsRef.current.clear();\n } else {\n Object.keys(activeSounds).forEach(key => {\n stop(key as CircleSoundKey, true);\n pausedSoundsRef.current.add(key as CircleSoundKey);\n });\n }\n }, [play, stop]);\n\n useEffect(() => {\n const interactionEvents = ['pointerdown', 'touchstart'];\n const tryResume = () => {\n resumeAudioContext();\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n interactionEvents.forEach(event => {\n window.addEventListener(event, tryResume, { once: true });\n });\n\n const timeouts = timeoutRefs.current;\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n interactionEvents.forEach(event => {\n window.removeEventListener(event, tryResume);\n });\n Object.values(timeouts).forEach(id => clearTimeout(id));\n };\n }, [handleVisibilityChange]);\n\n return {\n playSwipeSound,\n play,\n stop,\n playButtonSound,\n };\n};\n"],"names":["swipeSoundIndex","audioContext","bufferMapper","CircleSoundKey","activeSounds","useCircleSounds","canPlayAudio","useAutoPlayPermission","pausedSoundsRef","useRef","timeoutRefs","loadSound","useCallback","key","arrayBuffer","CircleSoundKeyMapper","decoded","resumeAudioContext","err","fadeIn","gainNode","fadeOut","timeout","_a","play","immediately","loop","buffer","source","stop","sound","playSwipeSound","SWIPE_SOUND_ORDER","playButtonSound","handleVisibilityChange","useEffect","interactionEvents","tryResume","event","timeouts","id"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cuemath/leap",
3
- "version": "3.3.25-af",
3
+ "version": "3.3.25-af-1",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"