@cuemath/leap 3.1.25-hg3 → 3.1.25

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,108 +1,123 @@
1
- import { useCallback as s, useRef as _, useEffect as m } from "react";
2
- import { useAutoPlayPermission as P } from "../../../hooks/use-auto-play-permission/use-auto-play-permission.js";
3
- import { CircleSoundKeyMapper as U, SWIPE_SOUND_ORDER as R } from "./constants.js";
4
- import { fadeInSound as O, fadeOutSound as h } from "./helper.js";
5
- import { CircleSoundKey as t } from "./use-circle-sounds-enums.js";
6
- let i = 0;
7
- const c = {
8
- [t.BACKGROUND]: null,
9
- [t.BACKGROUND_RUSHHOUR]: null,
10
- [t.TUTORIAL]: null,
11
- [t.SWIPE_01]: null,
12
- [t.SWIPE_02]: null,
13
- [t.SWIPE_03]: null,
14
- [t.SWIPE_04]: null,
15
- [t.SWIPE_DOWN]: null,
16
- [t.TOGGLE]: null,
17
- [t.POINTS_AWARDED]: null,
18
- [t.POINTS_ADDED]: null,
19
- [t.GAME_CARD_CLICK]: null,
20
- [t.CLOCK_IN]: null,
21
- [t.CLOCK_OUT]: null,
22
- [t.ACCURACY_IN]: null,
23
- [t.ACCURACY_OUT]: null,
24
- [t.STREAK_IN]: null,
25
- [t.STREAK_OUT]: null,
26
- [t.ACCURACY_INTRO]: null,
27
- [t.ACCURACY_TARGET]: null,
28
- [t.TIME_INTRO]: null,
29
- [t.TIME_TARGET]: null,
30
- [t.METER_FILL]: null
31
- }, E = {}, K = () => {
32
- const { canAutoPlayAudio: C } = P(), A = s((n) => {
33
- if (!c[n]) {
34
- const u = new Audio(U[n]);
35
- c[n] = u;
1
+ import { useCallback as s, useRef as C, useEffect as A } from "react";
2
+ import { CircleSoundKeyMapper as O, SWIPE_SOUND_ORDER as S } from "./constants.js";
3
+ import { CircleSoundKey as e } from "./use-circle-sounds-enums.js";
4
+ let d = 0;
5
+ const o = {
6
+ [e.BACKGROUND]: null,
7
+ [e.BACKGROUND_RUSHHOUR]: null,
8
+ [e.TUTORIAL]: null,
9
+ [e.SWIPE_01]: null,
10
+ [e.SWIPE_02]: null,
11
+ [e.SWIPE_03]: null,
12
+ [e.SWIPE_04]: null,
13
+ [e.SWIPE_DOWN]: null,
14
+ [e.TOGGLE]: null,
15
+ [e.POINTS_AWARDED]: null,
16
+ [e.POINTS_ADDED]: null,
17
+ [e.GAME_CARD_CLICK]: null,
18
+ [e.CLOCK_IN]: null,
19
+ [e.CLOCK_OUT]: null,
20
+ [e.ACCURACY_IN]: null,
21
+ [e.ACCURACY_OUT]: null,
22
+ [e.STREAK_IN]: null,
23
+ [e.STREAK_OUT]: null,
24
+ [e.ACCURACY_INTRO]: null,
25
+ [e.ACCURACY_TARGET]: null,
26
+ [e.TIME_INTRO]: null,
27
+ [e.TIME_TARGET]: null,
28
+ [e.METER_FILL]: null
29
+ }, I = {}, G = () => {
30
+ const c = s((n) => {
31
+ if (!o[n]) {
32
+ const l = new Audio(O[n]);
33
+ o[n] = l;
36
34
  }
37
- }, []), a = _(/* @__PURE__ */ new Set()), o = _({}), r = s(
38
- (n, u = !0, l = !1) => {
39
- A(n);
40
- const e = c[n];
41
- if (!e || !C) return;
42
- if (l && (e.loop = l), o.current[n] && clearInterval(o.current[n]), !e.paused && e.currentTime > 0 && !e.ended) {
43
- if (u)
44
- e.volume = 1;
45
- else {
46
- const S = O(e);
47
- o.current[n] = S;
48
- }
49
- return e;
50
- }
51
- e.volume = u ? 1 : 0;
52
- const p = e.play();
53
- if (p && (E[n] = p), !u) {
54
- const S = O(e);
55
- o.current[n] = S;
35
+ }, []), f = C(/* @__PURE__ */ new Set()), r = C({}), p = s(() => {
36
+ document.visibilityState === "hidden" ? Object.keys(o).forEach((n) => {
37
+ const l = o[n];
38
+ l && !l.paused && (l.pause(), f.current.add(n));
39
+ }) : document.visibilityState === "visible" && (f.current.forEach((n) => {
40
+ const l = o[n];
41
+ l == null || l.play();
42
+ }), f.current.clear());
43
+ }, []);
44
+ A(() => {
45
+ document.addEventListener("visibilitychange", p);
46
+ const n = r.current;
47
+ return () => {
48
+ document.removeEventListener("visibilitychange", p);
49
+ for (const l of Object.values(n))
50
+ l != null && clearInterval(l);
51
+ };
52
+ }, [p]);
53
+ const _ = s(() => {
54
+ var l;
55
+ S.forEach((u) => {
56
+ c(u);
57
+ });
58
+ const n = S[d] || e.SWIPE_01;
59
+ d < S.length - 1 ? d++ : d = 0, (l = o[n]) == null || l.play();
60
+ }, [c]), m = s(() => {
61
+ var l;
62
+ return c(e.TOGGLE), (l = o[e.TOGGLE]) == null ? void 0 : l.play();
63
+ }, [c]), R = s(
64
+ (n, l = !0, u = !1) => {
65
+ c(n);
66
+ const t = o[n];
67
+ if (!t) return;
68
+ if (r.current[n] && clearInterval(r.current[n]), !t.paused && t.currentTime > 0 && !t.ended)
69
+ return t;
70
+ if (t.loop = u, l) {
71
+ t.volume = 1;
72
+ const i = t.play();
73
+ i && (I[n] = i);
74
+ return;
56
75
  }
57
- return e;
76
+ t.volume = 0;
77
+ const a = t.play();
78
+ I[n] = a;
79
+ const E = setInterval(() => {
80
+ if (!t) {
81
+ clearInterval(E);
82
+ return;
83
+ }
84
+ const i = t.volume || 0;
85
+ i < 1 ? t.volume = Math.min(i + 0.1, 1) : clearInterval(E);
86
+ }, 100);
87
+ return r.current[n] = E, t;
58
88
  },
59
- [A, C]
60
- ), d = s((n, u) => {
61
- const l = c[n];
62
- if (!l) return;
63
- if (o.current[n] && clearInterval(o.current[n]), u) {
64
- l.pause();
89
+ [c]
90
+ ), v = s((n, l) => {
91
+ const u = o[n];
92
+ if (!u) return;
93
+ if (r.current[n] && clearInterval(r.current[n]), l) {
94
+ u.pause();
65
95
  return;
66
96
  }
67
- const e = h(l);
68
- o.current[n] = e;
69
- }, []), f = s(
70
- (n, u = !0) => {
71
- var l;
72
- if (E[n] !== void 0) {
73
- (l = E[n]) == null || l.then(() => {
74
- d(n, u);
75
- }).catch((e) => {
76
- console.log("sound not playing", e);
97
+ let t = u.volume || 0;
98
+ const a = setInterval(() => {
99
+ t - 0.1 <= 0 ? (u.volume = 0, u.pause(), clearInterval(a)) : (t = t - 0.1, u.volume = t);
100
+ }, 100);
101
+ r.current[n] = a;
102
+ }, []), T = s(
103
+ (n, l = !0) => {
104
+ var u;
105
+ if (I[n] !== void 0) {
106
+ (u = I[n]) == null || u.then(() => {
107
+ v(n, l);
108
+ }).catch((t) => {
109
+ console.log("sound not playing", t);
77
110
  });
78
111
  return;
79
112
  }
80
- d(n, u);
113
+ v(n, l);
81
114
  },
82
- [d]
83
- ), T = s(() => {
84
- const n = R[i] || t.SWIPE_01;
85
- i < R.length - 1 ? i++ : i = 0, r(n);
86
- }, [r]), v = s(() => r(t.TOGGLE), [r]), I = s(() => {
87
- document.visibilityState === "hidden" && Object.keys(c).forEach((n) => {
88
- const u = c[n];
89
- u && !u.paused && (f(n, !0), a.current.add(n));
90
- }), document.visibilityState === "visible" && (a.current.forEach((n) => {
91
- r(n);
92
- }), a.current.clear());
93
- }, [r, f]);
94
- return m(() => {
95
- document.addEventListener("visibilitychange", I);
96
- const n = o.current;
97
- return () => {
98
- document.removeEventListener("visibilitychange", I), Object.values(n).forEach((u) => {
99
- u && clearInterval(u);
100
- });
101
- };
102
- }, [I]), { playSwipSound: T, play: r, stop: f, playButtonSound: v };
115
+ [v]
116
+ );
117
+ return { playSwipSound: _, play: R, stop: T, playButtonSound: m };
103
118
  };
104
119
  export {
105
- c as soundMapper,
106
- K as useCircleSounds
120
+ o as soundMapper,
121
+ G as useCircleSounds
107
122
  };
108
123
  //# 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 { fadeInSound, fadeOutSound } from './helper';\nimport { CircleSoundKey } from './use-circle-sounds-enums';\n\nlet swipeSoundIndex = 0;\n\nexport const soundMapper: Record<keyof typeof CircleSoundKeyMapper, null | HTMLAudioElement> = {\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};\n\nconst soundInstancePromise: Partial<Record<keyof typeof CircleSoundKeyMapper, Promise<void>>> = {};\n\nexport const useCircleSounds = () => {\n const { canAutoPlayAudio: canPlayAudio } = useAutoPlayPermission();\n\n const loadSound = useCallback((key: CircleSoundKey) => {\n if (!soundMapper[key]) {\n const loadedSound = new Audio(CircleSoundKeyMapper[key]);\n\n soundMapper[key] = loadedSound;\n }\n }, []);\n\n const pausedSoundsRef = useRef<Set<CircleSoundKey>>(new Set());\n const timeoutRefs = useRef<TimeoutMap>({});\n\n const play = useCallback(\n (key: CircleSoundKey, immediately: boolean = true, loop = false) => {\n loadSound(key);\n const soundInstance = soundMapper[key];\n\n if (!soundInstance || !canPlayAudio) return;\n\n // this makes sure that it keeps the default loop value at the time it was requested to be loaded\n // helps in visibility change where we only want to resume\n if (loop) {\n soundInstance.loop = loop;\n }\n\n if (timeoutRefs.current[key]) {\n clearInterval(timeoutRefs.current[key]);\n }\n\n // resume sound\n if (!soundInstance.paused && soundInstance.currentTime > 0 && !soundInstance.ended) {\n if (!immediately) {\n const intervalId = fadeInSound(soundInstance);\n\n timeoutRefs.current[key] = intervalId;\n } else {\n soundInstance.volume = 1;\n }\n\n return soundInstance;\n }\n\n // play sound\n soundInstance.volume = immediately ? 1 : 0;\n const promise = soundInstance.play();\n\n if (promise) {\n soundInstancePromise[key] = promise;\n }\n\n if (!immediately) {\n const intervalId = fadeInSound(soundInstance);\n\n timeoutRefs.current[key] = intervalId;\n }\n\n return soundInstance;\n },\n [loadSound, canPlayAudio],\n );\n\n const handleSoundStop = useCallback((key: CircleSoundKey, immediately: boolean) => {\n const soundInstance = soundMapper[key];\n\n if (!soundInstance) return;\n\n if (timeoutRefs.current[key]) {\n clearInterval(timeoutRefs.current[key]);\n }\n\n if (immediately) {\n soundInstance.pause();\n\n return;\n }\n\n const intervalId = fadeOutSound(soundInstance);\n\n timeoutRefs.current[key] = intervalId;\n }, []);\n\n const stop = useCallback(\n (key: CircleSoundKey, immediately: boolean = true) => {\n // if play returned a promise\n if (soundInstancePromise[key] !== undefined) {\n soundInstancePromise[key]\n ?.then(() => {\n handleSoundStop(key, immediately);\n })\n .catch(err => {\n // eslint-disable-next-line no-console\n console.log('sound not playing', err);\n });\n\n return;\n }\n\n handleSoundStop(key, immediately);\n },\n [handleSoundStop],\n );\n\n const playSwipSound = useCallback(() => {\n const key = SWIPE_SOUND_ORDER[swipeSoundIndex] || CircleSoundKey.SWIPE_01;\n\n if (swipeSoundIndex < SWIPE_SOUND_ORDER.length - 1) {\n swipeSoundIndex++;\n } else {\n swipeSoundIndex = 0;\n }\n\n play(key);\n }, [play]);\n\n const playButtonSound = useCallback(() => {\n const sound = play(CircleSoundKey.TOGGLE);\n\n return sound;\n }, [play]);\n\n const handleVisibilityChange = useCallback(() => {\n if (document.visibilityState === 'hidden') {\n (Object.keys(soundMapper) as CircleSoundKey[]).forEach(key => {\n const sound = soundMapper[key];\n\n if (sound && !sound.paused) {\n stop(key, true);\n pausedSoundsRef.current.add(key);\n }\n });\n }\n\n if (document.visibilityState === 'visible') {\n pausedSoundsRef.current.forEach(key => {\n play(key);\n });\n pausedSoundsRef.current.clear();\n }\n }, [play, stop]);\n\n useEffect(() => {\n document.addEventListener('visibilitychange', handleVisibilityChange);\n const timeouts = timeoutRefs.current;\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n Object.values(timeouts).forEach(id => {\n id && clearInterval(id);\n });\n };\n }, [handleVisibilityChange]);\n\n return { playSwipSound, play, stop, playButtonSound };\n};\n"],"names":["swipeSoundIndex","soundMapper","CircleSoundKey","soundInstancePromise","useCircleSounds","canPlayAudio","useAutoPlayPermission","loadSound","useCallback","key","loadedSound","CircleSoundKeyMapper","pausedSoundsRef","useRef","timeoutRefs","play","immediately","loop","soundInstance","intervalId","fadeInSound","promise","handleSoundStop","fadeOutSound","stop","_a","err","playSwipSound","SWIPE_SOUND_ORDER","playButtonSound","handleVisibilityChange","sound","useEffect","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 { CircleSoundKeyMapper, SWIPE_SOUND_ORDER } from './constants';\nimport { CircleSoundKey } from './use-circle-sounds-enums';\n\nlet swipeSoundIndex = 0;\n\nexport const soundMapper: Record<keyof typeof CircleSoundKeyMapper, null | HTMLAudioElement> = {\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};\n\nconst soundInstancePromise: Partial<Record<keyof typeof CircleSoundKeyMapper, Promise<void>>> = {};\n\nexport const useCircleSounds = () => {\n const loadSound = useCallback((key: CircleSoundKey) => {\n if (!soundMapper[key]) {\n const loadedSound = new Audio(CircleSoundKeyMapper[key]);\n\n soundMapper[key] = loadedSound;\n }\n }, []);\n\n const pausedSoundsRef = useRef<Set<CircleSoundKey>>(new Set());\n const timeoutRefs = useRef<TimeoutMap>({});\n\n const handleVisibilityChange = useCallback(() => {\n if (document.visibilityState === 'hidden') {\n (Object.keys(soundMapper) as CircleSoundKey[]).forEach(key => {\n const sound = soundMapper[key];\n\n if (sound && !sound.paused) {\n sound.pause();\n pausedSoundsRef.current.add(key);\n }\n });\n } else if (document.visibilityState === 'visible') {\n pausedSoundsRef.current.forEach(key => {\n const sound = soundMapper[key];\n\n sound?.play();\n });\n pausedSoundsRef.current.clear();\n }\n }, []);\n\n useEffect(() => {\n document.addEventListener('visibilitychange', handleVisibilityChange);\n const timeouts = timeoutRefs.current;\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n for (const id of Object.values(timeouts)) {\n if (id != null) clearInterval(id);\n }\n };\n }, [handleVisibilityChange]);\n\n const playSwipSound = useCallback(() => {\n SWIPE_SOUND_ORDER.forEach(key => {\n loadSound(key);\n });\n\n const key = SWIPE_SOUND_ORDER[swipeSoundIndex] || CircleSoundKey.SWIPE_01;\n\n if (swipeSoundIndex < SWIPE_SOUND_ORDER.length - 1) {\n swipeSoundIndex++;\n } else {\n swipeSoundIndex = 0;\n }\n soundMapper[key]?.play();\n }, [loadSound]);\n\n const playButtonSound = useCallback(() => {\n loadSound(CircleSoundKey.TOGGLE);\n const sound = soundMapper[CircleSoundKey.TOGGLE]?.play();\n\n return sound;\n }, [loadSound]);\n\n const play = useCallback(\n (key: CircleSoundKey, immediately: boolean = true, loop = false) => {\n loadSound(key);\n const soundInstance = soundMapper[key];\n\n if (!soundInstance) return;\n\n if (timeoutRefs.current[key]) {\n clearInterval(timeoutRefs.current[key]);\n }\n\n if (!soundInstance.paused && soundInstance.currentTime > 0 && !soundInstance.ended) {\n return soundInstance;\n }\n\n soundInstance.loop = loop;\n if (immediately) {\n soundInstance.volume = 1;\n const promise = soundInstance.play();\n\n if (promise) {\n soundInstancePromise[key] = promise;\n }\n\n return;\n }\n\n soundInstance.volume = 0;\n const promise = soundInstance.play();\n\n soundInstancePromise[key] = promise;\n\n const intervalId = setInterval(() => {\n if (!soundInstance) {\n clearInterval(intervalId);\n\n return;\n }\n\n const vol = soundInstance.volume || 0;\n\n if (vol < 1) {\n soundInstance.volume = Math.min(vol + 0.1, 1);\n } else {\n clearInterval(intervalId);\n }\n }, 100);\n\n timeoutRefs.current[key] = intervalId;\n\n return soundInstance;\n },\n [loadSound],\n );\n\n const handleSoundStop = useCallback((key: CircleSoundKey, immediately: boolean) => {\n const soundInstance = soundMapper[key];\n\n if (!soundInstance) return;\n\n if (timeoutRefs.current[key]) {\n clearInterval(timeoutRefs.current[key]);\n }\n\n if (immediately) {\n soundInstance.pause();\n\n return;\n }\n\n let vol = soundInstance.volume || 0;\n const intervalId = setInterval(() => {\n if (vol - 0.1 <= 0) {\n soundInstance.volume = 0;\n soundInstance.pause();\n clearInterval(intervalId);\n } else {\n vol = vol - 0.1;\n soundInstance.volume = vol;\n }\n }, 100);\n\n timeoutRefs.current[key] = intervalId;\n }, []);\n\n const stop = useCallback(\n (key: CircleSoundKey, immediately: boolean = true) => {\n // if play returned a promise\n if (soundInstancePromise[key] !== undefined) {\n soundInstancePromise[key]\n ?.then(() => {\n handleSoundStop(key, immediately);\n })\n .catch(err => {\n // eslint-disable-next-line no-console\n console.log('sound not playing', err);\n });\n\n return;\n }\n\n handleSoundStop(key, immediately);\n },\n [handleSoundStop],\n );\n\n return { playSwipSound, play, stop, playButtonSound };\n};\n"],"names":["swipeSoundIndex","soundMapper","CircleSoundKey","soundInstancePromise","useCircleSounds","loadSound","useCallback","key","loadedSound","CircleSoundKeyMapper","pausedSoundsRef","useRef","timeoutRefs","handleVisibilityChange","sound","useEffect","timeouts","id","playSwipSound","SWIPE_SOUND_ORDER","_a","playButtonSound","play","immediately","loop","soundInstance","promise","intervalId","vol","handleSoundStop","stop","err"],"mappings":"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"}
@@ -1,51 +1,53 @@
1
- import { jsxs as x, jsx as y } from "react/jsx-runtime";
2
- import { memo as D, useState as d, useRef as I, useCallback as f, useMemo as S, useEffect as w } from "react";
3
- import b from "./modal.js";
4
- import h from "./modal-context.js";
1
+ import { jsxs as y, jsx as D } from "react/jsx-runtime";
2
+ import { memo as I, useState as f, useRef as p, useCallback as u, useMemo as b, useEffect as k } from "react";
3
+ import h from "./modal.js";
4
+ import L from "./modal-context.js";
5
5
  import { lockScroll as R, unlockScroll as T } from "./modal-helpers.js";
6
- const $ = 500, g = D(({ children: p, modals: u, isUserAuthenticated: t }) => {
7
- const [o, M] = d(null), [m, C] = d(void 0), [r, i] = d(!1), l = I(void 0), v = f(
8
- (e, s, P) => {
9
- const c = u.find((E) => E.name === e);
10
- if (!c)
6
+ const $ = 500, g = I(({ children: C, modals: M, isUserAuthenticated: t }) => {
7
+ const [o, m] = f(null), [v, P] = f(void 0), [s, i] = f(!1), l = p(void 0), a = p(!1), w = u(
8
+ (e, r, S) => {
9
+ if (a.current)
10
+ return;
11
+ const d = M.find((x) => x.name === e);
12
+ if (!d)
11
13
  throw new Error(`Modal with name "${e}" not found`);
12
- if (c.isPrivate && !t)
14
+ if (d.isPrivate && !t)
13
15
  throw new Error(
14
16
  `Access violation: Modal "${e}" is private and user is not authenticated`
15
17
  );
16
- l.current = P, i(!1), M(c), C(s), R();
18
+ l.current = S, i(!1), m(d), P(r), R(), a.current = !0;
17
19
  },
18
- [t, u]
19
- ), n = f(() => {
20
- i(!0), T(), setTimeout(() => {
21
- M(null), i(!1);
20
+ [t, M]
21
+ ), n = u(() => {
22
+ i(!0), T(), a.current = !1, setTimeout(() => {
23
+ m(null), i(!1);
22
24
  }, $);
23
- }, []), k = S(
25
+ }, []), E = b(
24
26
  () => ({
25
27
  modal: o,
26
- modalParams: m,
27
- openModal: v,
28
+ modalParams: v,
29
+ openModal: w,
28
30
  closeModal: n,
29
- isClosing: r
31
+ isClosing: s
30
32
  }),
31
- [o, m, v, n, r]
32
- ), a = f(() => {
33
- var e, s;
34
- (o == null ? void 0 : o.isDismissable) !== !1 && !r && (n(), l.current && ((s = (e = l.current).onCloseModal) == null || s.call(e), l.current.onCloseModal = void 0));
35
- }, [o, n, r]);
36
- return w(() => {
33
+ [o, v, w, n, s]
34
+ ), c = u(() => {
35
+ var e, r;
36
+ (o == null ? void 0 : o.isDismissable) !== !1 && !s && (n(), l.current && ((r = (e = l.current).onCloseModal) == null || r.call(e), l.current.onCloseModal = void 0));
37
+ }, [o, n, s]);
38
+ return k(() => {
37
39
  !t && (o != null && o.isPrivate) && n();
38
- }, [t, o, n]), w(() => {
39
- const e = (s) => {
40
- s.key === "Escape" && a();
40
+ }, [t, o, n]), k(() => {
41
+ const e = (r) => {
42
+ r.key === "Escape" && c();
41
43
  };
42
44
  return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
43
- }, [a]), /* @__PURE__ */ x(h.Provider, { value: k, children: [
44
- p,
45
- o && /* @__PURE__ */ y(b, { modal: o, isClosing: r, onClose: a })
45
+ }, [c]), /* @__PURE__ */ y(L.Provider, { value: E, children: [
46
+ C,
47
+ o && /* @__PURE__ */ D(h, { modal: o, isClosing: s, onClose: c })
46
48
  ] });
47
- }), K = g;
49
+ }), N = g;
48
50
  export {
49
- K as default
51
+ N as default
50
52
  };
51
53
  //# sourceMappingURL=modal-provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"modal-provider.js","sources":["../../../../src/features/ui/modals/modal-provider.tsx"],"sourcesContent":["import type { IModal, IModalCallbacks, IModalContext, IModalProviderProps } from './modal-types';\nimport type { FC } from 'react';\n\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport Modal from './modal';\nimport ModalContext from './modal-context';\nimport { lockScroll, unlockScroll } from './modal-helpers';\n\nconst ANIMATION_DURATION_MS = 500; // Match the animation duration in modal.tsx\n\n/**\n * Provider component that manages modal state and provides modal context to child components\n */\nconst ModalProvider: FC<IModalProviderProps> = memo(({ children, modals, isUserAuthenticated }) => {\n const [modal, setModal] = useState<IModal | null>(null);\n const [modalParams, setModalParams] = useState<Record<string, unknown> | undefined>(undefined);\n const [isClosing, setIsClosing] = useState(false);\n const callbacksRef = useRef<IModalCallbacks | undefined>(undefined);\n /**\n * Opens a modal by name with optional parameters\n * Handles authentication check for private modals\n */\n const openModal = useCallback<IModalContext['openModal']>(\n (modalName, newModalParams, callbacks) => {\n const newModal = modals.find(m => m.name === modalName);\n\n if (!newModal) {\n throw new Error(`Modal with name \"${modalName}\" not found`);\n }\n\n if (newModal.isPrivate && !isUserAuthenticated) {\n throw new Error(\n `Access violation: Modal \"${modalName}\" is private and user is not authenticated`,\n );\n }\n\n callbacksRef.current = callbacks;\n setIsClosing(false);\n setModal(newModal);\n setModalParams(newModalParams as unknown as Record<string, unknown> | undefined);\n lockScroll(); // Lock scroll while preserving scrollbar width\n },\n [isUserAuthenticated, modals],\n );\n\n const closeModal = useCallback(() => {\n setIsClosing(true);\n // Wait for the animation to complete before removing the modal\n unlockScroll();\n setTimeout(() => {\n setModal(null);\n setIsClosing(false);\n }, ANIMATION_DURATION_MS);\n }, []);\n\n const modalContent = useMemo<IModalContext>(\n () => ({\n modal,\n modalParams,\n openModal,\n closeModal,\n isClosing,\n }),\n [modal, modalParams, openModal, closeModal, isClosing],\n );\n\n const onModalDismiss = useCallback(() => {\n if (modal?.isDismissable !== false && !isClosing) {\n closeModal();\n if (callbacksRef.current) {\n callbacksRef.current.onCloseModal?.();\n callbacksRef.current.onCloseModal = undefined; // Clear callback reference\n }\n }\n }, [modal, closeModal, isClosing]);\n\n useEffect(() => {\n if (!isUserAuthenticated && modal?.isPrivate) {\n // If the modal is private and user is not authenticated, close it\n closeModal();\n }\n }, [isUserAuthenticated, modal, closeModal]);\n\n // Handle ESC key\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onModalDismiss();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [onModalDismiss]);\n\n return (\n <ModalContext.Provider value={modalContent}>\n {children}\n {modal && <Modal modal={modal} isClosing={isClosing} onClose={onModalDismiss} />}\n </ModalContext.Provider>\n );\n});\n\nexport default ModalProvider;\n"],"names":["ANIMATION_DURATION_MS","ModalProvider","memo","children","modals","isUserAuthenticated","modal","setModal","useState","modalParams","setModalParams","isClosing","setIsClosing","callbacksRef","useRef","openModal","useCallback","modalName","newModalParams","callbacks","newModal","m","lockScroll","closeModal","unlockScroll","modalContent","useMemo","onModalDismiss","_b","_a","useEffect","handleKeyDown","e","jsxs","ModalContext","jsx","Modal","ModalProvider$1"],"mappings":";;;;;AASA,MAAMA,IAAwB,KAKxBC,IAAyCC,EAAK,CAAC,EAAE,UAAAC,GAAU,QAAAC,GAAQ,qBAAAC,QAA0B;AACjG,QAAM,CAACC,GAAOC,CAAQ,IAAIC,EAAwB,IAAI,GAChD,CAACC,GAAaC,CAAc,IAAIF,EAA8C,MAAS,GACvF,CAACG,GAAWC,CAAY,IAAIJ,EAAS,EAAK,GAC1CK,IAAeC,EAAoC,MAAS,GAK5DC,IAAYC;AAAA,IAChB,CAACC,GAAWC,GAAgBC,MAAc;AACxC,YAAMC,IAAWhB,EAAO,KAAK,CAAKiB,MAAAA,EAAE,SAASJ,CAAS;AAEtD,UAAI,CAACG;AACH,cAAM,IAAI,MAAM,oBAAoBH,CAAS,aAAa;AAGxD,UAAAG,EAAS,aAAa,CAACf;AACzB,cAAM,IAAI;AAAA,UACR,4BAA4BY,CAAS;AAAA,QAAA;AAIzC,MAAAJ,EAAa,UAAUM,GACvBP,EAAa,EAAK,GAClBL,EAASa,CAAQ,GACjBV,EAAeQ,CAAgE,GACpEI;IACb;AAAA,IACA,CAACjB,GAAqBD,CAAM;AAAA,EAAA,GAGxBmB,IAAaP,EAAY,MAAM;AACnC,IAAAJ,EAAa,EAAI,GAEJY,KACb,WAAW,MAAM;AACf,MAAAjB,EAAS,IAAI,GACbK,EAAa,EAAK;AAAA,OACjBZ,CAAqB;AAAA,EAC1B,GAAG,CAAE,CAAA,GAECyB,IAAeC;AAAA,IACnB,OAAO;AAAA,MACL,OAAApB;AAAA,MACA,aAAAG;AAAA,MACA,WAAAM;AAAA,MACA,YAAAQ;AAAA,MACA,WAAAZ;AAAA,IAAA;AAAA,IAEF,CAACL,GAAOG,GAAaM,GAAWQ,GAAYZ,CAAS;AAAA,EAAA,GAGjDgB,IAAiBX,EAAY,MAAM;;AACvC,KAAIV,KAAA,gBAAAA,EAAO,mBAAkB,MAAS,CAACK,MAC1BY,KACPV,EAAa,aACfe,KAAAC,IAAAhB,EAAa,SAAQ,iBAArB,QAAAe,EAAA,KAAAC,IACAhB,EAAa,QAAQ,eAAe;AAAA,EAGvC,GAAA,CAACP,GAAOiB,GAAYZ,CAAS,CAAC;AAEjC,SAAAmB,EAAU,MAAM;AACV,IAAA,CAACzB,MAAuBC,KAAA,QAAAA,EAAO,cAEtBiB;EAEZ,GAAA,CAAClB,GAAqBC,GAAOiB,CAAU,CAAC,GAG3CO,EAAU,MAAM;AACR,UAAAC,IAAgB,CAACC,MAAqB;AACtC,MAAAA,EAAE,QAAQ,YACGL;IACjB;AAGK,kBAAA,iBAAiB,WAAWI,CAAa,GAEzC,MAAM,OAAO,oBAAoB,WAAWA,CAAa;AAAA,EAAA,GAC/D,CAACJ,CAAc,CAAC,GAGhB,gBAAAM,EAAAC,EAAa,UAAb,EAAsB,OAAOT,GAC3B,UAAA;AAAA,IAAAtB;AAAA,IACAG,KAAU,gBAAA6B,EAAAC,GAAA,EAAM,OAAA9B,GAAc,WAAAK,GAAsB,SAASgB,GAAgB;AAAA,EAChF,EAAA,CAAA;AAEJ,CAAC,GAEDU,IAAepC;"}
1
+ {"version":3,"file":"modal-provider.js","sources":["../../../../src/features/ui/modals/modal-provider.tsx"],"sourcesContent":["import type { IModal, IModalCallbacks, IModalContext, IModalProviderProps } from './modal-types';\nimport type { FC } from 'react';\n\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport Modal from './modal';\nimport ModalContext from './modal-context';\nimport { lockScroll, unlockScroll } from './modal-helpers';\n\nconst ANIMATION_DURATION_MS = 500; // Match the animation duration in modal.tsx\n\n/**\n * Provider component that manages modal state and provides modal context to child components\n */\nconst ModalProvider: FC<IModalProviderProps> = memo(({ children, modals, isUserAuthenticated }) => {\n const [modal, setModal] = useState<IModal | null>(null);\n const [modalParams, setModalParams] = useState<Record<string, unknown> | undefined>(undefined);\n const [isClosing, setIsClosing] = useState(false);\n const callbacksRef = useRef<IModalCallbacks | undefined>(undefined);\n const isScrollLocked = useRef(false);\n\n /**\n * Early return if scroll is already locked\n * Opens a modal by name with optional parameters\n * Handles authentication check for private modals\n */\n const openModal = useCallback<IModalContext['openModal']>(\n (modalName, newModalParams, callbacks) => {\n if (isScrollLocked.current) {\n return;\n }\n\n const newModal = modals.find(m => m.name === modalName);\n\n if (!newModal) {\n throw new Error(`Modal with name \"${modalName}\" not found`);\n }\n\n if (newModal.isPrivate && !isUserAuthenticated) {\n throw new Error(\n `Access violation: Modal \"${modalName}\" is private and user is not authenticated`,\n );\n }\n\n callbacksRef.current = callbacks;\n setIsClosing(false);\n setModal(newModal);\n setModalParams(newModalParams as unknown as Record<string, unknown> | undefined);\n lockScroll();\n isScrollLocked.current = true;\n },\n [isUserAuthenticated, modals],\n );\n\n const closeModal = useCallback(() => {\n setIsClosing(true);\n unlockScroll();\n isScrollLocked.current = false;\n setTimeout(() => {\n setModal(null);\n setIsClosing(false);\n }, ANIMATION_DURATION_MS);\n }, []);\n\n const modalContent = useMemo<IModalContext>(\n () => ({\n modal,\n modalParams,\n openModal,\n closeModal,\n isClosing,\n }),\n [modal, modalParams, openModal, closeModal, isClosing],\n );\n\n const onModalDismiss = useCallback(() => {\n if (modal?.isDismissable !== false && !isClosing) {\n closeModal();\n if (callbacksRef.current) {\n callbacksRef.current.onCloseModal?.();\n callbacksRef.current.onCloseModal = undefined; // Clear callback reference\n }\n }\n }, [modal, closeModal, isClosing]);\n\n useEffect(() => {\n if (!isUserAuthenticated && modal?.isPrivate) {\n // If the modal is private and user is not authenticated, close it\n closeModal();\n }\n }, [isUserAuthenticated, modal, closeModal]);\n\n // Handle ESC key\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onModalDismiss();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [onModalDismiss]);\n\n return (\n <ModalContext.Provider value={modalContent}>\n {children}\n {modal && <Modal modal={modal} isClosing={isClosing} onClose={onModalDismiss} />}\n </ModalContext.Provider>\n );\n});\n\nexport default ModalProvider;\n"],"names":["ANIMATION_DURATION_MS","ModalProvider","memo","children","modals","isUserAuthenticated","modal","setModal","useState","modalParams","setModalParams","isClosing","setIsClosing","callbacksRef","useRef","isScrollLocked","openModal","useCallback","modalName","newModalParams","callbacks","newModal","m","lockScroll","closeModal","unlockScroll","modalContent","useMemo","onModalDismiss","_b","_a","useEffect","handleKeyDown","e","jsxs","ModalContext","jsx","Modal","ModalProvider$1"],"mappings":";;;;;AASA,MAAMA,IAAwB,KAKxBC,IAAyCC,EAAK,CAAC,EAAE,UAAAC,GAAU,QAAAC,GAAQ,qBAAAC,QAA0B;AACjG,QAAM,CAACC,GAAOC,CAAQ,IAAIC,EAAwB,IAAI,GAChD,CAACC,GAAaC,CAAc,IAAIF,EAA8C,MAAS,GACvF,CAACG,GAAWC,CAAY,IAAIJ,EAAS,EAAK,GAC1CK,IAAeC,EAAoC,MAAS,GAC5DC,IAAiBD,EAAO,EAAK,GAO7BE,IAAYC;AAAA,IAChB,CAACC,GAAWC,GAAgBC,MAAc;AACxC,UAAIL,EAAe;AACjB;AAGF,YAAMM,IAAWjB,EAAO,KAAK,CAAKkB,MAAAA,EAAE,SAASJ,CAAS;AAEtD,UAAI,CAACG;AACH,cAAM,IAAI,MAAM,oBAAoBH,CAAS,aAAa;AAGxD,UAAAG,EAAS,aAAa,CAAChB;AACzB,cAAM,IAAI;AAAA,UACR,4BAA4Ba,CAAS;AAAA,QAAA;AAIzC,MAAAL,EAAa,UAAUO,GACvBR,EAAa,EAAK,GAClBL,EAASc,CAAQ,GACjBX,EAAeS,CAAgE,GACpEI,KACXR,EAAe,UAAU;AAAA,IAC3B;AAAA,IACA,CAACV,GAAqBD,CAAM;AAAA,EAAA,GAGxBoB,IAAaP,EAAY,MAAM;AACnC,IAAAL,EAAa,EAAI,GACJa,KACbV,EAAe,UAAU,IACzB,WAAW,MAAM;AACf,MAAAR,EAAS,IAAI,GACbK,EAAa,EAAK;AAAA,OACjBZ,CAAqB;AAAA,EAC1B,GAAG,CAAE,CAAA,GAEC0B,IAAeC;AAAA,IACnB,OAAO;AAAA,MACL,OAAArB;AAAA,MACA,aAAAG;AAAA,MACA,WAAAO;AAAA,MACA,YAAAQ;AAAA,MACA,WAAAb;AAAA,IAAA;AAAA,IAEF,CAACL,GAAOG,GAAaO,GAAWQ,GAAYb,CAAS;AAAA,EAAA,GAGjDiB,IAAiBX,EAAY,MAAM;;AACvC,KAAIX,KAAA,gBAAAA,EAAO,mBAAkB,MAAS,CAACK,MAC1Ba,KACPX,EAAa,aACfgB,KAAAC,IAAAjB,EAAa,SAAQ,iBAArB,QAAAgB,EAAA,KAAAC,IACAjB,EAAa,QAAQ,eAAe;AAAA,EAGvC,GAAA,CAACP,GAAOkB,GAAYb,CAAS,CAAC;AAEjC,SAAAoB,EAAU,MAAM;AACV,IAAA,CAAC1B,MAAuBC,KAAA,QAAAA,EAAO,cAEtBkB;EAEZ,GAAA,CAACnB,GAAqBC,GAAOkB,CAAU,CAAC,GAG3CO,EAAU,MAAM;AACR,UAAAC,IAAgB,CAACC,MAAqB;AACtC,MAAAA,EAAE,QAAQ,YACGL;IACjB;AAGK,kBAAA,iBAAiB,WAAWI,CAAa,GAEzC,MAAM,OAAO,oBAAoB,WAAWA,CAAa;AAAA,EAAA,GAC/D,CAACJ,CAAc,CAAC,GAGhB,gBAAAM,EAAAC,EAAa,UAAb,EAAsB,OAAOT,GAC3B,UAAA;AAAA,IAAAvB;AAAA,IACAG,KAAU,gBAAA8B,EAAAC,GAAA,EAAM,OAAA/B,GAAc,WAAAK,GAAsB,SAASiB,GAAgB;AAAA,EAChF,EAAA,CAAA;AAEJ,CAAC,GAEDU,IAAerC;"}
package/dist/index.d.ts CHANGED
@@ -5778,7 +5778,7 @@ export declare const useCircleSounds: () => {
5778
5778
  playSwipSound: () => void;
5779
5779
  play: (key: CircleSoundKey, immediately?: boolean, loop?: boolean) => HTMLAudioElement | undefined;
5780
5780
  stop: (key: CircleSoundKey, immediately?: boolean) => void;
5781
- playButtonSound: () => HTMLAudioElement | undefined;
5781
+ playButtonSound: () => Promise<void> | undefined;
5782
5782
  };
5783
5783
 
5784
5784
  export declare const useClassTimeAlerts: ({ alertLevel, classStartedOn, classDuration, onUpdateClassTimeAlertConfig, }: IUseClassTimeAlerts) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cuemath/leap",
3
- "version": "3.1.25-hg3",
3
+ "version": "3.1.25",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -1,18 +0,0 @@
1
- const r = (e) => {
2
- const l = setInterval(() => {
3
- const t = e.volume || 0;
4
- t < 1 ? e.volume = Math.min(t + 0.1, 1) : clearInterval(l);
5
- }, 100);
6
- return l;
7
- }, v = (e) => {
8
- let l = e.volume || 0;
9
- const t = setInterval(() => {
10
- l - 0.1 <= 0 ? (e.volume = 0, e.pause(), clearInterval(t)) : (l = l - 0.1, e.volume = l);
11
- }, 100);
12
- return t;
13
- };
14
- export {
15
- r as fadeInSound,
16
- v as fadeOutSound
17
- };
18
- //# sourceMappingURL=helper.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"helper.js","sources":["../../../../../src/features/circle-games/hooks/use-circle-sounds/helper.ts"],"sourcesContent":["export const fadeInSound = (soundInstance: HTMLAudioElement) => {\n const intervalId = setInterval(() => {\n const vol = soundInstance.volume || 0;\n\n if (vol < 1) {\n soundInstance.volume = Math.min(vol + 0.1, 1);\n } else {\n clearInterval(intervalId);\n }\n }, 100);\n\n return intervalId;\n};\n\nexport const fadeOutSound = (soundInstance: HTMLAudioElement) => {\n let vol = soundInstance.volume || 0;\n const intervalId = setInterval(() => {\n if (vol - 0.1 <= 0) {\n soundInstance.volume = 0;\n soundInstance.pause();\n clearInterval(intervalId);\n } else {\n vol = vol - 0.1;\n soundInstance.volume = vol;\n }\n }, 100);\n\n return intervalId;\n};\n"],"names":["fadeInSound","soundInstance","intervalId","vol","fadeOutSound"],"mappings":"AAAa,MAAAA,IAAc,CAACC,MAAoC;AACxD,QAAAC,IAAa,YAAY,MAAM;AAC7B,UAAAC,IAAMF,EAAc,UAAU;AAEpC,IAAIE,IAAM,IACRF,EAAc,SAAS,KAAK,IAAIE,IAAM,KAAK,CAAC,IAE5C,cAAcD,CAAU;AAAA,KAEzB,GAAG;AAEC,SAAAA;AACT,GAEaE,IAAe,CAACH,MAAoC;AAC3D,MAAAE,IAAMF,EAAc,UAAU;AAC5B,QAAAC,IAAa,YAAY,MAAM;AAC/B,IAAAC,IAAM,OAAO,KACfF,EAAc,SAAS,GACvBA,EAAc,MAAM,GACpB,cAAcC,CAAU,MAExBC,IAAMA,IAAM,KACZF,EAAc,SAASE;AAAA,KAExB,GAAG;AAEC,SAAAD;AACT;"}