@lucaismyname/ginger 0.0.24 → 0.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/GingerSplitContexts-BzBExb95.js.map +1 -1
- package/dist/GingerSplitContexts-C7puo0M7.cjs.map +1 -1
- package/dist/analyzer/liveAudioGraph.d.ts.map +1 -1
- package/dist/analyzer/useGingerLiveAnalyzer.d.ts.map +1 -1
- package/dist/audio/GingerPlayer.d.ts.map +1 -1
- package/dist/client.cjs +1 -1
- package/dist/client.js +2 -2
- package/dist/components/controls/Controls.d.ts +6 -3
- package/dist/components/controls/Controls.d.ts.map +1 -1
- package/dist/components/current/Artwork.d.ts.map +1 -1
- package/dist/components/current/Chapters.d.ts +1 -1
- package/dist/components/current/Chapters.d.ts.map +1 -1
- package/dist/components/current/FileUrl.d.ts +1 -1
- package/dist/components/current/FileUrl.d.ts.map +1 -1
- package/dist/components/current/Lyrics.d.ts +1 -1
- package/dist/components/current/Lyrics.d.ts.map +1 -1
- package/dist/components/current/LyricsSynced.d.ts +1 -1
- package/dist/components/current/LyricsSynced.d.ts.map +1 -1
- package/dist/components/current/Playback.d.ts +1 -1
- package/dist/components/current/Playback.d.ts.map +1 -1
- package/dist/components/current/QueueMeta.d.ts +1 -1
- package/dist/components/current/QueueMeta.d.ts.map +1 -1
- package/dist/components/current/Time.d.ts.map +1 -1
- package/dist/components/current/Year.d.ts.map +1 -1
- package/dist/components/current/createTextDisplay.d.ts.map +1 -1
- package/dist/components/current/texts.d.ts.map +1 -1
- package/dist/components/playlist/GingerPlaylist.d.ts.map +1 -1
- package/dist/components/queue/QueueDisplay.d.ts +1 -1
- package/dist/components/queue/QueueDisplay.d.ts.map +1 -1
- package/dist/context/GingerContext.d.ts.map +1 -1
- package/dist/context/GingerLocaleContext.d.ts.map +1 -1
- package/dist/context/GingerProvider.d.ts.map +1 -1
- package/dist/context/GingerSplitContexts.d.ts.map +1 -1
- package/dist/core/playbackReducer.d.ts.map +1 -1
- package/dist/core/queue.d.ts.map +1 -1
- package/dist/core/transitions.d.ts.map +1 -1
- package/dist/{ginger-BoNnuade.js → ginger-DE4TKdCR.js} +950 -894
- package/dist/ginger-DE4TKdCR.js.map +1 -0
- package/dist/ginger-yY4Y5liv.cjs +2 -0
- package/dist/ginger-yY4Y5liv.cjs.map +1 -0
- package/dist/ginger.d.ts +1 -1
- package/dist/ginger.d.ts.map +1 -1
- package/dist/hooks/useControlBindings.d.ts.map +1 -1
- package/dist/hooks/useGinger.d.ts.map +1 -1
- package/dist/hooks/useGingerKeyboardShortcuts.d.ts.map +1 -1
- package/dist/hooks/useGingerLyricsSync.d.ts.map +1 -1
- package/dist/hooks/useSeekDrag.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +2 -2
- package/dist/internal/selectors.d.ts.map +1 -1
- package/dist/testing/helpers.d.ts.map +1 -1
- package/dist/testing/index.cjs +1 -1
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.js +1 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/{useNextTrackPrefetch-CaTRhYHd.cjs → useNextTrackPrefetch-Cs4A1oFv.cjs} +2 -2
- package/dist/useNextTrackPrefetch-Cs4A1oFv.cjs.map +1 -0
- package/dist/{useNextTrackPrefetch-BUx0bK_a.js → useNextTrackPrefetch-eR_p__O2.js} +53 -45
- package/dist/useNextTrackPrefetch-eR_p__O2.js.map +1 -0
- package/dist/waveform/analyzeAudioFile.d.ts.map +1 -1
- package/dist/waveform/index.cjs +1 -1
- package/dist/waveform/index.cjs.map +1 -1
- package/dist/waveform/index.js +91 -84
- package/dist/waveform/index.js.map +1 -1
- package/dist/waveform/useAudioFileAnalysis.d.ts.map +1 -1
- package/dist/waveform/useAudioPeaks.d.ts.map +1 -1
- package/package.json +4 -4
- package/dist/ginger-BKmH7kWx.cjs +0 -2
- package/dist/ginger-BKmH7kWx.cjs.map +0 -1
- package/dist/ginger-BoNnuade.js.map +0 -1
- package/dist/useNextTrackPrefetch-BUx0bK_a.js.map +0 -1
- package/dist/useNextTrackPrefetch-CaTRhYHd.cjs.map +0 -1
package/dist/waveform/index.js
CHANGED
|
@@ -1,31 +1,38 @@
|
|
|
1
|
-
import { useState as
|
|
2
|
-
function D(
|
|
3
|
-
const [r,
|
|
1
|
+
import { useState as y, useEffect as x } from "react";
|
|
2
|
+
function D(a, t = 64) {
|
|
3
|
+
const [r, e] = y({
|
|
4
4
|
peaks: [],
|
|
5
5
|
isLoading: !1,
|
|
6
6
|
error: null
|
|
7
7
|
});
|
|
8
|
-
return
|
|
9
|
-
if (!
|
|
10
|
-
|
|
8
|
+
return x(() => {
|
|
9
|
+
if (!a) {
|
|
10
|
+
e({ peaks: [], isLoading: !1, error: null });
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
13
|
let o = !1;
|
|
14
|
-
return
|
|
14
|
+
return e((n) => ({ ...n, isLoading: !0, error: null })), (async () => {
|
|
15
15
|
try {
|
|
16
|
-
const n = await fetch(
|
|
17
|
-
if (!n.ok)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
for (let
|
|
23
|
-
i =
|
|
24
|
-
|
|
16
|
+
const n = await fetch(a);
|
|
17
|
+
if (!n.ok)
|
|
18
|
+
throw new Error(`Fetch failed: ${n.status} ${n.statusText}`);
|
|
19
|
+
const l = await n.arrayBuffer(), s = new AudioContext();
|
|
20
|
+
try {
|
|
21
|
+
const f = (await s.decodeAudioData(l)).getChannelData(0), w = Math.max(1, Math.floor(f.length / t)), u = [];
|
|
22
|
+
for (let h = 0; h < t; h += 1) {
|
|
23
|
+
let i = 0;
|
|
24
|
+
const d = h * w, m = Math.min(f.length, d + w);
|
|
25
|
+
for (let c = d; c < m; c += 1)
|
|
26
|
+
i = Math.max(i, Math.abs(f[c] ?? 0));
|
|
27
|
+
u.push(i);
|
|
28
|
+
}
|
|
29
|
+
o || e({ peaks: u, isLoading: !1, error: null });
|
|
30
|
+
} finally {
|
|
31
|
+
await s.close().catch(() => {
|
|
32
|
+
});
|
|
25
33
|
}
|
|
26
|
-
await s.close(), o || a({ peaks: u, isLoading: !1, error: null });
|
|
27
34
|
} catch (n) {
|
|
28
|
-
o ||
|
|
35
|
+
o || e({
|
|
29
36
|
peaks: [],
|
|
30
37
|
isLoading: !1,
|
|
31
38
|
error: n instanceof Error ? n.message : "Failed to decode peaks"
|
|
@@ -34,22 +41,22 @@ function D(e, t = 64) {
|
|
|
34
41
|
})(), () => {
|
|
35
42
|
o = !0;
|
|
36
43
|
};
|
|
37
|
-
}, [t,
|
|
44
|
+
}, [t, a]), r;
|
|
38
45
|
}
|
|
39
|
-
function A(
|
|
40
|
-
const r =
|
|
46
|
+
function A(a, t) {
|
|
47
|
+
const r = a.length;
|
|
41
48
|
if (r !== t.length || r < 2 || r & r - 1)
|
|
42
49
|
throw new Error("fftInPlace: length must be equal powers of 2 >= 2");
|
|
43
|
-
let
|
|
50
|
+
let e = 0;
|
|
44
51
|
for (let o = 0; o < r - 1; o += 1) {
|
|
45
|
-
if (o <
|
|
46
|
-
const l =
|
|
47
|
-
|
|
52
|
+
if (o < e) {
|
|
53
|
+
const l = a[o], s = t[o];
|
|
54
|
+
a[o] = a[e], t[o] = t[e], a[e] = l, t[e] = s;
|
|
48
55
|
}
|
|
49
56
|
let n = r >> 1;
|
|
50
|
-
for (; n <=
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
for (; n <= e; )
|
|
58
|
+
e -= n, n >>= 1;
|
|
59
|
+
e += n;
|
|
53
60
|
}
|
|
54
61
|
for (let o = 2; o <= r; o <<= 1) {
|
|
55
62
|
const n = -2 * Math.PI / o, l = Math.cos(n), s = Math.sin(n);
|
|
@@ -57,62 +64,62 @@ function A(e, t) {
|
|
|
57
64
|
let f = 1, w = 0;
|
|
58
65
|
const u = o >> 1;
|
|
59
66
|
for (let h = 0; h < u; h += 1) {
|
|
60
|
-
const i = g + h, d = i + u, m = f *
|
|
61
|
-
|
|
67
|
+
const i = g + h, d = i + u, m = f * a[d] - w * t[d], c = f * t[d] + w * a[d];
|
|
68
|
+
a[d] = a[i] - m, t[d] = t[i] - c, a[i] = a[i] + m, t[i] = t[i] + c;
|
|
62
69
|
const M = f * l - w * s, p = f * s + w * l;
|
|
63
70
|
f = M, w = p;
|
|
64
71
|
}
|
|
65
72
|
}
|
|
66
73
|
}
|
|
67
74
|
}
|
|
68
|
-
function F(
|
|
69
|
-
const t =
|
|
75
|
+
function F(a) {
|
|
76
|
+
const t = a.length;
|
|
70
77
|
if (t < 2 || t & t - 1)
|
|
71
78
|
throw new Error("realFftMagnitudes: length must be a power of 2 >= 2");
|
|
72
|
-
const r = new Float64Array(t),
|
|
73
|
-
for (let n = 0; n < t; n += 1) r[n] =
|
|
74
|
-
A(r,
|
|
79
|
+
const r = new Float64Array(t), e = new Float64Array(t);
|
|
80
|
+
for (let n = 0; n < t; n += 1) r[n] = a[n];
|
|
81
|
+
A(r, e);
|
|
75
82
|
const o = new Float64Array(t >> 1);
|
|
76
83
|
for (let n = 0; n < t >> 1; n += 1)
|
|
77
|
-
o[n] = Math.hypot(r[n],
|
|
84
|
+
o[n] = Math.hypot(r[n], e[n]);
|
|
78
85
|
return o;
|
|
79
86
|
}
|
|
80
|
-
function L(
|
|
81
|
-
const t = new Float64Array(
|
|
82
|
-
if (
|
|
87
|
+
function L(a) {
|
|
88
|
+
const t = new Float64Array(a);
|
|
89
|
+
if (a === 1)
|
|
83
90
|
return t[0] = 1, t;
|
|
84
|
-
const r =
|
|
85
|
-
for (let
|
|
86
|
-
t[
|
|
91
|
+
const r = a - 1;
|
|
92
|
+
for (let e = 0; e < a; e += 1)
|
|
93
|
+
t[e] = 0.5 * (1 - Math.cos(2 * Math.PI * e / r));
|
|
87
94
|
return t;
|
|
88
95
|
}
|
|
89
|
-
function C(
|
|
90
|
-
const t = 2 ** Math.round(Math.log2(
|
|
96
|
+
function C(a) {
|
|
97
|
+
const t = 2 ** Math.round(Math.log2(a));
|
|
91
98
|
return Math.min(8192, Math.max(32, t));
|
|
92
99
|
}
|
|
93
|
-
function k(
|
|
94
|
-
const { numberOfChannels: t, length: r } =
|
|
100
|
+
function k(a) {
|
|
101
|
+
const { numberOfChannels: t, length: r } = a;
|
|
95
102
|
if (t === 1)
|
|
96
|
-
return
|
|
97
|
-
const
|
|
103
|
+
return a.getChannelData(0);
|
|
104
|
+
const e = new Float32Array(r), o = 1 / t;
|
|
98
105
|
for (let n = 0; n < t; n += 1) {
|
|
99
|
-
const l =
|
|
106
|
+
const l = a.getChannelData(n);
|
|
100
107
|
for (let s = 0; s < r; s += 1)
|
|
101
|
-
|
|
108
|
+
e[s] += l[s] * o;
|
|
102
109
|
}
|
|
103
|
-
return
|
|
110
|
+
return e;
|
|
104
111
|
}
|
|
105
|
-
function B(
|
|
106
|
-
if (t === "mix") return k(
|
|
107
|
-
const r = Math.max(0, Math.min(
|
|
108
|
-
return
|
|
112
|
+
function B(a, t) {
|
|
113
|
+
if (t === "mix") return k(a);
|
|
114
|
+
const r = Math.max(0, Math.min(a.numberOfChannels - 1, t));
|
|
115
|
+
return a.getChannelData(r);
|
|
109
116
|
}
|
|
110
|
-
function E(
|
|
111
|
-
const
|
|
117
|
+
function E(a, t, r) {
|
|
118
|
+
const e = [], o = a.length;
|
|
112
119
|
if (o === 0) {
|
|
113
120
|
for (let l = 0; l < t; l += 1)
|
|
114
|
-
|
|
115
|
-
return
|
|
121
|
+
e.push(Array.from({ length: r }, () => 0));
|
|
122
|
+
return e;
|
|
116
123
|
}
|
|
117
124
|
const n = o / t;
|
|
118
125
|
for (let l = 0; l < t; l += 1) {
|
|
@@ -121,17 +128,17 @@ function E(e, t, r) {
|
|
|
121
128
|
const i = Math.floor(g + h * u), d = Math.min(f, Math.floor(g + (h + 1) * u));
|
|
122
129
|
let m = 0;
|
|
123
130
|
for (let c = i; c < d; c += 1)
|
|
124
|
-
m = Math.max(m, Math.abs(
|
|
131
|
+
m = Math.max(m, Math.abs(a[c] ?? 0));
|
|
125
132
|
s.push(m);
|
|
126
133
|
}
|
|
127
|
-
|
|
134
|
+
e.push(s);
|
|
128
135
|
}
|
|
129
|
-
return
|
|
136
|
+
return e;
|
|
130
137
|
}
|
|
131
|
-
function S(
|
|
138
|
+
function S(a, t, r, e) {
|
|
132
139
|
const o = [];
|
|
133
140
|
let n = 1e-12;
|
|
134
|
-
const l =
|
|
141
|
+
const l = a.length, s = C(r), g = s >> 1, f = Math.min(e, g), w = L(s);
|
|
135
142
|
if (l < s) {
|
|
136
143
|
for (let u = 0; u < t; u += 1)
|
|
137
144
|
o.push(Array.from({ length: f }, () => 0));
|
|
@@ -140,7 +147,7 @@ function S(e, t, r, a) {
|
|
|
140
147
|
for (let u = 0; u < t; u += 1) {
|
|
141
148
|
const h = t <= 1 ? 0 : Math.min(Math.floor(u * (l - s) / (t - 1)), l - s), i = new Float64Array(s);
|
|
142
149
|
for (let c = 0; c < s; c += 1)
|
|
143
|
-
i[c] = (
|
|
150
|
+
i[c] = (a[h + c] ?? 0) * (w[c] ?? 0);
|
|
144
151
|
const d = F(i), m = [];
|
|
145
152
|
for (let c = 0; c < f; c += 1) {
|
|
146
153
|
const M = d[c] ?? 0;
|
|
@@ -150,10 +157,10 @@ function S(e, t, r, a) {
|
|
|
150
157
|
}
|
|
151
158
|
return { rows: o, maxMag: n };
|
|
152
159
|
}
|
|
153
|
-
function b(
|
|
154
|
-
const r = Math.max(1, t.timeSlices ?? 128),
|
|
155
|
-
duration:
|
|
156
|
-
sampleRate:
|
|
160
|
+
function b(a, t = {}) {
|
|
161
|
+
const r = Math.max(1, t.timeSlices ?? 128), e = Math.max(1, t.samplesPerSlice ?? 8), o = !!t.spectrogram, n = t.fftSize ?? 1024, l = Math.max(1, t.frequencyBins ?? 256), s = t.channel ?? 0, g = B(a, s), f = E(g, r, e), w = {
|
|
162
|
+
duration: a.duration,
|
|
163
|
+
sampleRate: a.sampleRate,
|
|
157
164
|
amplitudeGrid: f
|
|
158
165
|
};
|
|
159
166
|
if (o) {
|
|
@@ -162,43 +169,43 @@ function b(e, t = {}) {
|
|
|
162
169
|
}
|
|
163
170
|
return w;
|
|
164
171
|
}
|
|
165
|
-
async function z(
|
|
166
|
-
const r = await fetch(
|
|
172
|
+
async function z(a, t = {}) {
|
|
173
|
+
const r = await fetch(a);
|
|
167
174
|
if (!r.ok)
|
|
168
175
|
throw new Error(`Fetch failed: ${r.status} ${r.statusText}`);
|
|
169
|
-
const
|
|
176
|
+
const e = await r.arrayBuffer(), o = window.AudioContext ?? window.webkitAudioContext;
|
|
170
177
|
if (!o)
|
|
171
178
|
throw new Error("Web Audio API is not available");
|
|
172
179
|
const n = new o();
|
|
173
180
|
try {
|
|
174
|
-
const l = await n.decodeAudioData(
|
|
181
|
+
const l = await n.decodeAudioData(e.slice(0));
|
|
175
182
|
return b(l, t);
|
|
176
183
|
} finally {
|
|
177
184
|
await n.close();
|
|
178
185
|
}
|
|
179
186
|
}
|
|
180
|
-
function I(
|
|
181
|
-
const [r,
|
|
187
|
+
function I(a, t = {}) {
|
|
188
|
+
const [r, e] = y({
|
|
182
189
|
data: null,
|
|
183
190
|
isLoading: !1,
|
|
184
191
|
error: null
|
|
185
192
|
});
|
|
186
|
-
return
|
|
187
|
-
if (!
|
|
188
|
-
|
|
193
|
+
return x(() => {
|
|
194
|
+
if (!a) {
|
|
195
|
+
e({ data: null, isLoading: !1, error: null });
|
|
189
196
|
return;
|
|
190
197
|
}
|
|
191
198
|
if (typeof window > "u") {
|
|
192
|
-
|
|
199
|
+
e({ data: null, isLoading: !1, error: null });
|
|
193
200
|
return;
|
|
194
201
|
}
|
|
195
202
|
let o = !1;
|
|
196
|
-
return
|
|
203
|
+
return e((n) => ({ ...n, isLoading: !0, error: null })), (async () => {
|
|
197
204
|
try {
|
|
198
|
-
const n = await z(
|
|
199
|
-
o ||
|
|
205
|
+
const n = await z(a, t);
|
|
206
|
+
o || e({ data: n, isLoading: !1, error: null });
|
|
200
207
|
} catch (n) {
|
|
201
|
-
o ||
|
|
208
|
+
o || e({
|
|
202
209
|
data: null,
|
|
203
210
|
isLoading: !1,
|
|
204
211
|
error: n instanceof Error ? n.message : "Failed to analyze audio file"
|
|
@@ -208,7 +215,7 @@ function I(e, t = {}) {
|
|
|
208
215
|
o = !0;
|
|
209
216
|
};
|
|
210
217
|
}, [
|
|
211
|
-
|
|
218
|
+
a,
|
|
212
219
|
t.timeSlices,
|
|
213
220
|
t.samplesPerSlice,
|
|
214
221
|
t.spectrogram,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/waveform/useAudioPeaks.ts","../../src/internal/fft.ts","../../src/waveform/analyzeAudioFile.ts","../../src/waveform/useAudioFileAnalysis.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nexport type UseAudioPeaksState = {\n peaks: number[];\n isLoading: boolean;\n error: string | null;\n};\n\nexport function useAudioPeaks(fileUrl: string | null | undefined, buckets = 64): UseAudioPeaksState {\n const [state, setState] = useState<UseAudioPeaksState>({\n peaks: [],\n isLoading: false,\n error: null,\n });\n\n useEffect(() => {\n if (!fileUrl) {\n setState({ peaks: [], isLoading: false, error: null });\n return;\n }\n let cancelled = false;\n setState((prev) => ({ ...prev, isLoading: true, error: null }));\n void (async () => {\n try {\n const response = await fetch(fileUrl);\n if (!response.ok) throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);\n const buffer = await response.arrayBuffer();\n const audioContext = new AudioContext();\n const audioBuffer = await audioContext.decodeAudioData(buffer);\n const channel = audioBuffer.getChannelData(0);\n const step = Math.max(1, Math.floor(channel.length / buckets));\n const peaks: number[] = [];\n for (let i = 0; i < buckets; i += 1) {\n let max = 0;\n const start = i * step;\n const end = Math.min(channel.length, start + step);\n for (let j = start; j < end; j += 1) {\n max = Math.max(max, Math.abs(channel[j] ?? 0));\n }\n peaks.push(max);\n }\n await audioContext.close();\n if (!cancelled) {\n setState({ peaks, isLoading: false, error: null });\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n peaks: [],\n isLoading: false,\n error: error instanceof Error ? error.message : \"Failed to decode peaks\",\n });\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [buckets, fileUrl]);\n\n return state;\n}\n","/** In-place radix-2 Cooley–Tukey FFT; `length` must be a power of 2 and >= 2. */\nexport function fftInPlace(re: Float64Array, im: Float64Array): void {\n const n = re.length;\n if (n !== im.length || n < 2 || (n & (n - 1)) !== 0) {\n throw new Error(\"fftInPlace: length must be equal powers of 2 >= 2\");\n }\n\n let j = 0;\n for (let i = 0; i < n - 1; i += 1) {\n if (i < j) {\n const tr = re[i]!;\n const ti = im[i]!;\n re[i] = re[j]!;\n im[i] = im[j]!;\n re[j] = tr;\n im[j] = ti;\n }\n let k = n >> 1;\n while (k <= j) {\n j -= k;\n k >>= 1;\n }\n j += k;\n }\n\n for (let len = 2; len <= n; len <<= 1) {\n const ang = (-2 * Math.PI) / len;\n const wlenR = Math.cos(ang);\n const wlenI = Math.sin(ang);\n for (let i = 0; i < n; i += len) {\n let wr = 1;\n let wi = 0;\n const half = len >> 1;\n for (let k = 0; k < half; k += 1) {\n const u = i + k;\n const v = u + half;\n const tr = wr * re[v]! - wi * im[v]!;\n const ti = wr * im[v]! + wi * re[v]!;\n re[v] = re[u]! - tr;\n im[v] = im[u]! - ti;\n re[u] = re[u]! + tr;\n im[u] = im[u]! + ti;\n const nwr = wr * wlenR - wi * wlenI;\n const nwi = wr * wlenI + wi * wlenR;\n wr = nwr;\n wi = nwi;\n }\n }\n }\n}\n\n/** Magnitude spectrum for real input: length `n` (power of 2). Returns `n/2` magnitudes for bins 0..n/2-1. */\nexport function realFftMagnitudes(samples: Float64Array): Float64Array {\n const n = samples.length;\n if (n < 2 || (n & (n - 1)) !== 0) {\n throw new Error(\"realFftMagnitudes: length must be a power of 2 >= 2\");\n }\n const re = new Float64Array(n);\n const im = new Float64Array(n);\n for (let i = 0; i < n; i += 1) re[i] = samples[i]!;\n fftInPlace(re, im);\n const out = new Float64Array(n >> 1);\n for (let k = 0; k < n >> 1; k += 1) {\n out[k] = Math.hypot(re[k]!, im[k]!);\n }\n return out;\n}\n\nexport function hanningWindow(length: number): Float64Array {\n const w = new Float64Array(length);\n if (length === 1) {\n w[0] = 1;\n return w;\n }\n const denom = length - 1;\n for (let i = 0; i < length; i += 1) {\n w[i] = 0.5 * (1 - Math.cos((2 * Math.PI * i) / denom));\n }\n return w;\n}\n\nexport function clampFftSize(n: number): number {\n const p = 2 ** Math.round(Math.log2(n));\n return Math.min(8192, Math.max(32, p));\n}\n","import { clampFftSize, hanningWindow, realFftMagnitudes } from \"../internal/fft\";\n\nexport type AnalyzeAudioFileOptions = {\n /** Number of time rows in the amplitude grid (and spectrogram if enabled). Default 128. */\n timeSlices?: number;\n /** Sub-buckets per time slice for the amplitude grid. Default 8. */\n samplesPerSlice?: number;\n /** When true, include `spectrogram` using windowed FFT per time slice. Default false. */\n spectrogram?: boolean;\n /** FFT length for spectrogram (power of 2). Default 1024. */\n fftSize?: number;\n /** Number of frequency bins to keep per row (first bins; capped by fftSize/2). Default 256. */\n frequencyBins?: number;\n /** Channel index, or `\"mix\"` for equal mix of all channels. Default 0. */\n channel?: number | \"mix\";\n};\n\nexport type AudioFileAnalysis = {\n duration: number;\n sampleRate: number;\n /** Peak amplitudes in [0, 1]: `timeSlices` rows × `samplesPerSlice` columns. */\n amplitudeGrid: number[][];\n /** Optional magnitude spectrogram rows, each length `frequencyBins`, normalized to [0, 1] globally. */\n spectrogram?: number[][];\n};\n\nfunction mixChannels(buffer: AudioBuffer): Float32Array {\n const { numberOfChannels, length } = buffer;\n if (numberOfChannels === 1) {\n return buffer.getChannelData(0);\n }\n const out = new Float32Array(length);\n const scale = 1 / numberOfChannels;\n for (let c = 0; c < numberOfChannels; c += 1) {\n const ch = buffer.getChannelData(c);\n for (let i = 0; i < length; i += 1) {\n out[i] += ch[i]! * scale;\n }\n }\n return out;\n}\n\nfunction getChannel(buffer: AudioBuffer, channel: number | \"mix\"): Float32Array {\n if (channel === \"mix\") return mixChannels(buffer);\n const idx = Math.max(0, Math.min(buffer.numberOfChannels - 1, channel));\n return buffer.getChannelData(idx);\n}\n\nfunction buildAmplitudeGrid(\n channel: Float32Array,\n timeSlices: number,\n samplesPerSlice: number,\n): number[][] {\n const grid: number[][] = [];\n const len = channel.length;\n if (len === 0) {\n for (let t = 0; t < timeSlices; t += 1) {\n grid.push(Array.from({ length: samplesPerSlice }, () => 0));\n }\n return grid;\n }\n\n const segmentLen = len / timeSlices;\n\n for (let t = 0; t < timeSlices; t += 1) {\n const row: number[] = [];\n const segStart = Math.floor(t * segmentLen);\n const segEnd = Math.floor((t + 1) * segmentLen);\n const segLen = Math.max(1, segEnd - segStart);\n const subLen = segLen / samplesPerSlice;\n\n for (let s = 0; s < samplesPerSlice; s += 1) {\n const a = Math.floor(segStart + s * subLen);\n const b = Math.min(segEnd, Math.floor(segStart + (s + 1) * subLen));\n let peak = 0;\n for (let i = a; i < b; i += 1) {\n peak = Math.max(peak, Math.abs(channel[i] ?? 0));\n }\n row.push(peak);\n }\n grid.push(row);\n }\n return grid;\n}\n\nfunction buildSpectrogram(\n channel: Float32Array,\n timeSlices: number,\n fftSize: number,\n frequencyBins: number,\n): { rows: number[][]; maxMag: number } {\n const rows: number[][] = [];\n let maxMag = 1e-12;\n const len = channel.length;\n const n = clampFftSize(fftSize);\n const half = n >> 1;\n const bins = Math.min(frequencyBins, half);\n const window = hanningWindow(n);\n\n if (len < n) {\n for (let t = 0; t < timeSlices; t += 1) {\n rows.push(Array.from({ length: bins }, () => 0));\n }\n return { rows, maxMag: 1 };\n }\n\n for (let t = 0; t < timeSlices; t += 1) {\n const start =\n timeSlices <= 1\n ? 0\n : Math.min(Math.floor((t * (len - n)) / (timeSlices - 1)), len - n);\n const frame = new Float64Array(n);\n for (let i = 0; i < n; i += 1) {\n frame[i] = (channel[start + i] ?? 0) * (window[i] ?? 0);\n }\n const mags = realFftMagnitudes(frame);\n const row: number[] = [];\n for (let k = 0; k < bins; k += 1) {\n const v = mags[k] ?? 0;\n row.push(v);\n maxMag = Math.max(maxMag, v);\n }\n rows.push(row);\n }\n\n return { rows, maxMag };\n}\n\n/**\n * Decodes an `AudioBuffer` into visualization-friendly grids (no network).\n */\nexport function analyzeAudioBuffer(buffer: AudioBuffer, options: AnalyzeAudioFileOptions = {}): AudioFileAnalysis {\n const timeSlices = Math.max(1, options.timeSlices ?? 128);\n const samplesPerSlice = Math.max(1, options.samplesPerSlice ?? 8);\n const wantSpec = Boolean(options.spectrogram);\n const fftSize = options.fftSize ?? 1024;\n const frequencyBins = Math.max(1, options.frequencyBins ?? 256);\n const channel = options.channel ?? 0;\n\n const data = getChannel(buffer, channel);\n const amplitudeGrid = buildAmplitudeGrid(data, timeSlices, samplesPerSlice);\n\n const result: AudioFileAnalysis = {\n duration: buffer.duration,\n sampleRate: buffer.sampleRate,\n amplitudeGrid,\n };\n\n if (wantSpec) {\n const { rows, maxMag } = buildSpectrogram(data, timeSlices, fftSize, frequencyBins);\n const norm = maxMag > 0 ? 1 / maxMag : 1;\n result.spectrogram = rows.map((row) => row.map((v) => v * norm));\n }\n\n return result;\n}\n\n/**\n * Fetches a URL, decodes audio to an `AudioBuffer`, runs {@link analyzeAudioBuffer}, then closes the temporary `AudioContext`.\n */\nexport async function analyzeAudioFile(\n fileUrl: string,\n options: AnalyzeAudioFileOptions = {},\n): Promise<AudioFileAnalysis> {\n const response = await fetch(fileUrl);\n if (!response.ok) {\n throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);\n }\n const raw = await response.arrayBuffer();\n const Context = window.AudioContext ?? (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!Context) {\n throw new Error(\"Web Audio API is not available\");\n }\n const audioContext = new Context();\n try {\n const buffer = await audioContext.decodeAudioData(raw.slice(0));\n return analyzeAudioBuffer(buffer, options);\n } finally {\n await audioContext.close();\n }\n}\n","import { useEffect, useState } from \"react\";\nimport { analyzeAudioFile, type AnalyzeAudioFileOptions, type AudioFileAnalysis } from \"./analyzeAudioFile\";\n\nexport type UseAudioFileAnalysisState = {\n data: AudioFileAnalysis | null;\n isLoading: boolean;\n error: string | null;\n};\n\nexport function useAudioFileAnalysis(\n fileUrl: string | null | undefined,\n options: AnalyzeAudioFileOptions = {},\n): UseAudioFileAnalysisState {\n const [state, setState] = useState<UseAudioFileAnalysisState>({\n data: null,\n isLoading: false,\n error: null,\n });\n\n useEffect(() => {\n if (!fileUrl) {\n setState({ data: null, isLoading: false, error: null });\n return;\n }\n if (typeof window === \"undefined\") {\n setState({ data: null, isLoading: false, error: null });\n return;\n }\n\n let cancelled = false;\n setState((prev) => ({ ...prev, isLoading: true, error: null }));\n\n void (async () => {\n try {\n const data = await analyzeAudioFile(fileUrl, options);\n if (!cancelled) {\n setState({ data, isLoading: false, error: null });\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n isLoading: false,\n error: error instanceof Error ? error.message : \"Failed to analyze audio file\",\n });\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [\n fileUrl,\n options.timeSlices,\n options.samplesPerSlice,\n options.spectrogram,\n options.fftSize,\n options.frequencyBins,\n options.channel,\n ]);\n\n return state;\n}\n"],"names":["useAudioPeaks","fileUrl","buckets","state","setState","useState","useEffect","cancelled","prev","response","buffer","audioContext","channel","step","peaks","i","max","start","end","j","error","fftInPlace","re","im","n","tr","ti","k","len","ang","wlenR","wlenI","wr","wi","half","u","v","nwr","nwi","realFftMagnitudes","samples","out","hanningWindow","length","w","denom","clampFftSize","p","mixChannels","numberOfChannels","scale","c","ch","getChannel","idx","buildAmplitudeGrid","timeSlices","samplesPerSlice","grid","t","segmentLen","row","segStart","segEnd","subLen","s","a","b","peak","buildSpectrogram","fftSize","frequencyBins","rows","maxMag","bins","window","frame","mags","analyzeAudioBuffer","options","wantSpec","data","amplitudeGrid","result","norm","analyzeAudioFile","raw","Context","useAudioFileAnalysis"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/waveform/useAudioPeaks.ts","../../src/internal/fft.ts","../../src/waveform/analyzeAudioFile.ts","../../src/waveform/useAudioFileAnalysis.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nexport type UseAudioPeaksState = {\n peaks: number[];\n isLoading: boolean;\n error: string | null;\n};\n\nexport function useAudioPeaks(\n fileUrl: string | null | undefined,\n buckets = 64,\n): UseAudioPeaksState {\n const [state, setState] = useState<UseAudioPeaksState>({\n peaks: [],\n isLoading: false,\n error: null,\n });\n\n useEffect(() => {\n if (!fileUrl) {\n setState({ peaks: [], isLoading: false, error: null });\n return;\n }\n let cancelled = false;\n setState((prev) => ({ ...prev, isLoading: true, error: null }));\n void (async () => {\n try {\n const response = await fetch(fileUrl);\n if (!response.ok)\n throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);\n const buffer = await response.arrayBuffer();\n const audioContext = new AudioContext();\n try {\n const audioBuffer = await audioContext.decodeAudioData(buffer);\n const channel = audioBuffer.getChannelData(0);\n const step = Math.max(1, Math.floor(channel.length / buckets));\n const peaks: number[] = [];\n for (let i = 0; i < buckets; i += 1) {\n let max = 0;\n const start = i * step;\n const end = Math.min(channel.length, start + step);\n for (let j = start; j < end; j += 1) {\n max = Math.max(max, Math.abs(channel[j] ?? 0));\n }\n peaks.push(max);\n }\n if (!cancelled) {\n setState({ peaks, isLoading: false, error: null });\n }\n } finally {\n await audioContext.close().catch(() => {});\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n peaks: [],\n isLoading: false,\n error: error instanceof Error ? error.message : \"Failed to decode peaks\",\n });\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [buckets, fileUrl]);\n\n return state;\n}\n","/** In-place radix-2 Cooley–Tukey FFT; `length` must be a power of 2 and >= 2. */\nexport function fftInPlace(re: Float64Array, im: Float64Array): void {\n const n = re.length;\n if (n !== im.length || n < 2 || (n & (n - 1)) !== 0) {\n throw new Error(\"fftInPlace: length must be equal powers of 2 >= 2\");\n }\n\n let j = 0;\n for (let i = 0; i < n - 1; i += 1) {\n if (i < j) {\n const tr = re[i]!;\n const ti = im[i]!;\n re[i] = re[j]!;\n im[i] = im[j]!;\n re[j] = tr;\n im[j] = ti;\n }\n let k = n >> 1;\n while (k <= j) {\n j -= k;\n k >>= 1;\n }\n j += k;\n }\n\n for (let len = 2; len <= n; len <<= 1) {\n const ang = (-2 * Math.PI) / len;\n const wlenR = Math.cos(ang);\n const wlenI = Math.sin(ang);\n for (let i = 0; i < n; i += len) {\n let wr = 1;\n let wi = 0;\n const half = len >> 1;\n for (let k = 0; k < half; k += 1) {\n const u = i + k;\n const v = u + half;\n const tr = wr * re[v]! - wi * im[v]!;\n const ti = wr * im[v]! + wi * re[v]!;\n re[v] = re[u]! - tr;\n im[v] = im[u]! - ti;\n re[u] = re[u]! + tr;\n im[u] = im[u]! + ti;\n const nwr = wr * wlenR - wi * wlenI;\n const nwi = wr * wlenI + wi * wlenR;\n wr = nwr;\n wi = nwi;\n }\n }\n }\n}\n\n/** Magnitude spectrum for real input: length `n` (power of 2). Returns `n/2` magnitudes for bins 0..n/2-1. */\nexport function realFftMagnitudes(samples: Float64Array): Float64Array {\n const n = samples.length;\n if (n < 2 || (n & (n - 1)) !== 0) {\n throw new Error(\"realFftMagnitudes: length must be a power of 2 >= 2\");\n }\n const re = new Float64Array(n);\n const im = new Float64Array(n);\n for (let i = 0; i < n; i += 1) re[i] = samples[i]!;\n fftInPlace(re, im);\n const out = new Float64Array(n >> 1);\n for (let k = 0; k < n >> 1; k += 1) {\n out[k] = Math.hypot(re[k]!, im[k]!);\n }\n return out;\n}\n\nexport function hanningWindow(length: number): Float64Array {\n const w = new Float64Array(length);\n if (length === 1) {\n w[0] = 1;\n return w;\n }\n const denom = length - 1;\n for (let i = 0; i < length; i += 1) {\n w[i] = 0.5 * (1 - Math.cos((2 * Math.PI * i) / denom));\n }\n return w;\n}\n\nexport function clampFftSize(n: number): number {\n const p = 2 ** Math.round(Math.log2(n));\n return Math.min(8192, Math.max(32, p));\n}\n","import { clampFftSize, hanningWindow, realFftMagnitudes } from \"../internal/fft\";\n\nexport type AnalyzeAudioFileOptions = {\n /** Number of time rows in the amplitude grid (and spectrogram if enabled). Default 128. */\n timeSlices?: number;\n /** Sub-buckets per time slice for the amplitude grid. Default 8. */\n samplesPerSlice?: number;\n /** When true, include `spectrogram` using windowed FFT per time slice. Default false. */\n spectrogram?: boolean;\n /** FFT length for spectrogram (power of 2). Default 1024. */\n fftSize?: number;\n /** Number of frequency bins to keep per row (first bins; capped by fftSize/2). Default 256. */\n frequencyBins?: number;\n /** Channel index, or `\"mix\"` for equal mix of all channels. Default 0. */\n channel?: number | \"mix\";\n};\n\nexport type AudioFileAnalysis = {\n duration: number;\n sampleRate: number;\n /** Peak amplitudes in [0, 1]: `timeSlices` rows × `samplesPerSlice` columns. */\n amplitudeGrid: number[][];\n /** Optional magnitude spectrogram rows, each length `frequencyBins`, normalized to [0, 1] globally. */\n spectrogram?: number[][];\n};\n\nfunction mixChannels(buffer: AudioBuffer): Float32Array {\n const { numberOfChannels, length } = buffer;\n if (numberOfChannels === 1) {\n return buffer.getChannelData(0);\n }\n const out = new Float32Array(length);\n const scale = 1 / numberOfChannels;\n for (let c = 0; c < numberOfChannels; c += 1) {\n const ch = buffer.getChannelData(c);\n for (let i = 0; i < length; i += 1) {\n out[i] += ch[i]! * scale;\n }\n }\n return out;\n}\n\nfunction getChannel(buffer: AudioBuffer, channel: number | \"mix\"): Float32Array {\n if (channel === \"mix\") return mixChannels(buffer);\n const idx = Math.max(0, Math.min(buffer.numberOfChannels - 1, channel));\n return buffer.getChannelData(idx);\n}\n\nfunction buildAmplitudeGrid(\n channel: Float32Array,\n timeSlices: number,\n samplesPerSlice: number,\n): number[][] {\n const grid: number[][] = [];\n const len = channel.length;\n if (len === 0) {\n for (let t = 0; t < timeSlices; t += 1) {\n grid.push(Array.from({ length: samplesPerSlice }, () => 0));\n }\n return grid;\n }\n\n const segmentLen = len / timeSlices;\n\n for (let t = 0; t < timeSlices; t += 1) {\n const row: number[] = [];\n const segStart = Math.floor(t * segmentLen);\n const segEnd = Math.floor((t + 1) * segmentLen);\n const segLen = Math.max(1, segEnd - segStart);\n const subLen = segLen / samplesPerSlice;\n\n for (let s = 0; s < samplesPerSlice; s += 1) {\n const a = Math.floor(segStart + s * subLen);\n const b = Math.min(segEnd, Math.floor(segStart + (s + 1) * subLen));\n let peak = 0;\n for (let i = a; i < b; i += 1) {\n peak = Math.max(peak, Math.abs(channel[i] ?? 0));\n }\n row.push(peak);\n }\n grid.push(row);\n }\n return grid;\n}\n\nfunction buildSpectrogram(\n channel: Float32Array,\n timeSlices: number,\n fftSize: number,\n frequencyBins: number,\n): { rows: number[][]; maxMag: number } {\n const rows: number[][] = [];\n let maxMag = 1e-12;\n const len = channel.length;\n const n = clampFftSize(fftSize);\n const half = n >> 1;\n const bins = Math.min(frequencyBins, half);\n const window = hanningWindow(n);\n\n if (len < n) {\n for (let t = 0; t < timeSlices; t += 1) {\n rows.push(Array.from({ length: bins }, () => 0));\n }\n return { rows, maxMag: 1 };\n }\n\n for (let t = 0; t < timeSlices; t += 1) {\n const start =\n timeSlices <= 1 ? 0 : Math.min(Math.floor((t * (len - n)) / (timeSlices - 1)), len - n);\n const frame = new Float64Array(n);\n for (let i = 0; i < n; i += 1) {\n frame[i] = (channel[start + i] ?? 0) * (window[i] ?? 0);\n }\n const mags = realFftMagnitudes(frame);\n const row: number[] = [];\n for (let k = 0; k < bins; k += 1) {\n const v = mags[k] ?? 0;\n row.push(v);\n maxMag = Math.max(maxMag, v);\n }\n rows.push(row);\n }\n\n return { rows, maxMag };\n}\n\n/**\n * Decodes an `AudioBuffer` into visualization-friendly grids (no network).\n */\nexport function analyzeAudioBuffer(\n buffer: AudioBuffer,\n options: AnalyzeAudioFileOptions = {},\n): AudioFileAnalysis {\n const timeSlices = Math.max(1, options.timeSlices ?? 128);\n const samplesPerSlice = Math.max(1, options.samplesPerSlice ?? 8);\n const wantSpec = Boolean(options.spectrogram);\n const fftSize = options.fftSize ?? 1024;\n const frequencyBins = Math.max(1, options.frequencyBins ?? 256);\n const channel = options.channel ?? 0;\n\n const data = getChannel(buffer, channel);\n const amplitudeGrid = buildAmplitudeGrid(data, timeSlices, samplesPerSlice);\n\n const result: AudioFileAnalysis = {\n duration: buffer.duration,\n sampleRate: buffer.sampleRate,\n amplitudeGrid,\n };\n\n if (wantSpec) {\n const { rows, maxMag } = buildSpectrogram(data, timeSlices, fftSize, frequencyBins);\n const norm = maxMag > 0 ? 1 / maxMag : 1;\n result.spectrogram = rows.map((row) => row.map((v) => v * norm));\n }\n\n return result;\n}\n\n/**\n * Fetches a URL, decodes audio to an `AudioBuffer`, runs {@link analyzeAudioBuffer}, then closes the temporary `AudioContext`.\n */\nexport async function analyzeAudioFile(\n fileUrl: string,\n options: AnalyzeAudioFileOptions = {},\n): Promise<AudioFileAnalysis> {\n const response = await fetch(fileUrl);\n if (!response.ok) {\n throw new Error(`Fetch failed: ${response.status} ${response.statusText}`);\n }\n const raw = await response.arrayBuffer();\n const Context =\n window.AudioContext ??\n (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!Context) {\n throw new Error(\"Web Audio API is not available\");\n }\n const audioContext = new Context();\n try {\n const buffer = await audioContext.decodeAudioData(raw.slice(0));\n return analyzeAudioBuffer(buffer, options);\n } finally {\n await audioContext.close();\n }\n}\n","import { useEffect, useState } from \"react\";\nimport {\n type AnalyzeAudioFileOptions,\n type AudioFileAnalysis,\n analyzeAudioFile,\n} from \"./analyzeAudioFile\";\n\nexport type UseAudioFileAnalysisState = {\n data: AudioFileAnalysis | null;\n isLoading: boolean;\n error: string | null;\n};\n\nexport function useAudioFileAnalysis(\n fileUrl: string | null | undefined,\n options: AnalyzeAudioFileOptions = {},\n): UseAudioFileAnalysisState {\n const [state, setState] = useState<UseAudioFileAnalysisState>({\n data: null,\n isLoading: false,\n error: null,\n });\n\n useEffect(() => {\n if (!fileUrl) {\n setState({ data: null, isLoading: false, error: null });\n return;\n }\n if (typeof window === \"undefined\") {\n setState({ data: null, isLoading: false, error: null });\n return;\n }\n\n let cancelled = false;\n setState((prev) => ({ ...prev, isLoading: true, error: null }));\n\n void (async () => {\n try {\n const data = await analyzeAudioFile(fileUrl, options);\n if (!cancelled) {\n setState({ data, isLoading: false, error: null });\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n isLoading: false,\n error: error instanceof Error ? error.message : \"Failed to analyze audio file\",\n });\n }\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [\n fileUrl,\n options.timeSlices,\n options.samplesPerSlice,\n options.spectrogram,\n options.fftSize,\n options.frequencyBins,\n options.channel,\n ]);\n\n return state;\n}\n"],"names":["useAudioPeaks","fileUrl","buckets","state","setState","useState","useEffect","cancelled","prev","response","buffer","audioContext","channel","step","peaks","i","max","start","end","j","error","fftInPlace","re","im","n","tr","ti","k","len","ang","wlenR","wlenI","wr","wi","half","u","v","nwr","nwi","realFftMagnitudes","samples","out","hanningWindow","length","w","denom","clampFftSize","p","mixChannels","numberOfChannels","scale","c","ch","getChannel","idx","buildAmplitudeGrid","timeSlices","samplesPerSlice","grid","t","segmentLen","row","segStart","segEnd","subLen","s","a","b","peak","buildSpectrogram","fftSize","frequencyBins","rows","maxMag","bins","window","frame","mags","analyzeAudioBuffer","options","wantSpec","data","amplitudeGrid","result","norm","analyzeAudioFile","raw","Context","useAudioFileAnalysis"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAudioFileAnalysis.d.ts","sourceRoot":"","sources":["../../src/waveform/useAudioFileAnalysis.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"useAudioFileAnalysis.d.ts","sourceRoot":"","sources":["../../src/waveform/useAudioFileAnalysis.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EAEvB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,OAAO,GAAE,uBAA4B,GACpC,yBAAyB,CAmD3B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAudioPeaks.d.ts","sourceRoot":"","sources":["../../src/waveform/useAudioPeaks.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,wBAAgB,aAAa,
|
|
1
|
+
{"version":3,"file":"useAudioPeaks.d.ts","sourceRoot":"","sources":["../../src/waveform/useAudioPeaks.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,OAAO,SAAK,GACX,kBAAkB,CA0DpB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lucaismyname/ginger",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.26",
|
|
4
4
|
"description": "A headless React audio player",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"test:watch": "vitest",
|
|
46
46
|
"test:coverage": "vitest run --coverage",
|
|
47
47
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
48
|
-
"lint": "biome check src
|
|
49
|
-
"lint:fix": "biome check --write src
|
|
50
|
-
"format": "biome format --write src
|
|
48
|
+
"lint": "biome check src",
|
|
49
|
+
"lint:fix": "biome check --write src",
|
|
50
|
+
"format": "biome format --write src",
|
|
51
51
|
"docs:api": "typedoc --options typedoc.json",
|
|
52
52
|
"prepublishOnly": "npm run build"
|
|
53
53
|
},
|
package/dist/ginger-BKmH7kWx.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";const l=require("react/jsx-runtime"),f=require("react"),b=require("./GingerSplitContexts-C7puo0M7.cjs"),we=f.createContext(null);function _r(){const e=f.useContext(we);if(!e)throw new Error("Ginger components must be used within <Ginger.Provider>");return e}function Ne(e){const{buffered:r,duration:n}=e;return!(n>0)||r.length===0?0:Math.min(1,r.end(r.length-1)/n)}function Nr({className:e,style:r,preload:n="metadata",crossOrigin:a,respectReducedMotion:t=!1}){var I;const{audioRef:i,dispatch:u,state:s,notifyEnded:o}=_r(),c=((I=s.tracks[s.currentIndex])==null?void 0:I.fileUrl)??"",m=f.useRef({currentTime:-1,duration:-1,bufferedFraction:-1}),y=f.useRef(""),[x,k]=f.useState(!1);f.useEffect(()=>{if(!t||typeof window>"u")return;const p=window.matchMedia("(prefers-reduced-motion: reduce)"),E=()=>k(p.matches);return E(),p.addEventListener("change",E),()=>p.removeEventListener("change",E)},[t]);const v=(p,E=!1)=>{const P={currentTime:p.currentTime,duration:p.duration,bufferedFraction:Ne(p)},G=m.current,Me=x?.5:.25,O=Math.abs(P.currentTime-G.currentTime)>=Me||Math.abs(P.duration-G.duration)>=.01||Math.abs(P.bufferedFraction-G.bufferedFraction)>=.01;!E&&!O||(m.current=P,u({type:"MEDIA_TIME_UPDATE",payload:P}))};return f.useEffect(()=>{const p=i.current;p&&(p.volume=s.volume,p.muted=s.muted)},[i,s.volume,s.muted]),f.useEffect(()=>{const p=i.current;if(p){if(!c){p.removeAttribute("src"),m.current={currentTime:-1,duration:-1,bufferedFraction:-1},y.current!==""&&u({type:"MEDIA_SOURCE_CLEARED"}),y.current="";return}p.getAttribute("src")!==c&&(p.src=c,p.load(),m.current={currentTime:-1,duration:-1,bufferedFraction:-1}),y.current=c}},[i,u,s.currentIndex,s.tracks,c]),f.useEffect(()=>{const p=i.current;p&&(p.playbackRate=s.playbackRate)},[i,s.playbackRate,c]),l.jsx("audio",{ref:i,className:e,style:r,preload:n,crossOrigin:a,controls:!1,playsInline:!0,onTimeUpdate:p=>{v(p.currentTarget)},onLoadedMetadata:p=>{const E=p.currentTarget;m.current={currentTime:-1,duration:-1,bufferedFraction:-1},u({type:"MEDIA_LOADED_METADATA",payload:{duration:E.duration,bufferedFraction:Ne(E)}})},onSeeking:p=>v(p.currentTarget,!0),onSeeked:p=>v(p.currentTarget,!0),onEnded:()=>o(),onPlay:()=>u({type:"MEDIA_PLAY"}),onPause:()=>u({type:"MEDIA_PAUSE"}),onWaiting:()=>u({type:"MEDIA_WAITING"}),onCanPlay:()=>u({type:"MEDIA_CANPLAY"}),onProgress:p=>v(p.currentTarget,!0),onVolumeChange:p=>{const E=p.currentTarget;u({type:"MEDIA_VOLUME_SYNC",payload:{volume:E.volume,muted:E.muted}})},onError:()=>{var G;const p=i.current,E=(G=p==null?void 0:p.error)==null?void 0:G.code;u({type:"MEDIA_ERROR",payload:{message:E===1?"MEDIA_ERR_ABORTED":E===2?"MEDIA_ERR_NETWORK":E===3?"MEDIA_ERR_DECODE":E===4?"MEDIA_ERR_SRC_NOT_SUPPORTED":"MEDIA_ERR_UNKNOWN"}})}})}function S(e,r){return r<=0?0:Math.max(0,Math.min(r-1,e))}function De(e,r){if(e.length<=1)return[...e];const n=e[r];if(!n)return[...e];const a=e.filter((t,i)=>i!==r);for(let t=a.length-1;t>0;t--){const i=Math.floor(Math.random()*(t+1));[a[t],a[i]]=[a[i],a[t]]}return[n,...a]}function K(e){return e?e.id!=null&&e.id!==""?`id:${e.id}`:`file:${e.fileUrl}`:""}function Lr(e,r){var u,s;if(!r)return 0;const n=e.findIndex(o=>o===r);if(n!==-1)return n;const a=K(r);if(!a)return 0;const t=[];for(let o=0;o<e.length;o+=1)K(e[o])===a&&t.push(o);if(t.length===0)return 0;if(t.length===1)return t[0];const i=typeof globalThis<"u"&&"process"in globalThis?(s=(u=globalThis.process)==null?void 0:u.env)==null?void 0:s.NODE_ENV:void 0;return i!=null&&i!=="production"&&console.warn("[@lucaismyname/ginger] Ambiguous track identity: multiple queue rows share the same fileUrl without a unique `id`. Resolving to the first match."),t[0]}function Fe(e,r,n){const a=[...e],t=Math.max(0,Math.min(a.length,n??a.length));return a.splice(t,0,r),a}function wr(e,r){if(r<0||r>=e.length)return[...e];const n=[...e];return n.splice(r,1),n}function Dr(e,r,n){if(r===n||r<0||r>=e.length||n<0||n>=e.length)return[...e];const a=[...e],[t]=a.splice(r,1);return t?(a.splice(n,0,t),a):[...e]}function Fr(e,r,n){return Fe(e,n,Math.max(0,Math.min(e.length,r+1)))}function Ur(e){const{tracks:r,currentIndex:n,repeatMode:a,playbackMode:t}=e,i=r.length;return i===0?{kind:"stop",nextIndex:0}:a==="one"?{kind:"replay_same"}:t==="single"?{kind:"stop",nextIndex:S(n,i)}:n<i-1?{kind:"advance",nextIndex:n+1}:a==="all"?{kind:"wrap",nextIndex:0}:{kind:"stop",nextIndex:S(n,i)}}function Ue(e){const{tracks:r,currentIndex:n,repeatMode:a,playbackMode:t}=e,i=r.length;return i===0?0:t==="single"?S(n,i):n<i-1?n+1:a==="all"?0:S(n,i)}function Vr(e){const{tracks:r,currentIndex:n,repeatMode:a,playbackMode:t}=e,i=r.length;return i===0?0:t==="single"?S(n,i):n>0?n-1:a==="all"?i-1:0}function $r(e){return e==="off"?"all":e==="all"?"one":"off"}function Ve(e,r){return(e==null?void 0:e.artworkUrl)??r??void 0}function Br(e,r){return(e==null?void 0:e.album)??r??void 0}function j(e){return e.tracks[e.currentIndex]??null}function Ie(e){return e.errorMessage?"error":e.tracks.length===0?"idle":e.isBuffering?"loading":e.isPaused?Number.isFinite(e.duration)&&e.duration>0&&e.currentTime>=e.duration-.05?"ended":"paused":"playing"}function B(e){var a;const r=e.duration;if(Number.isFinite(r)&&r>0)return r;const n=(a=e.tracks[e.currentIndex])==null?void 0:a.durationSeconds;return typeof n=="number"&&Number.isFinite(n)&&n>0?n:0}function $e(e){const n=B(e)-e.currentTime;return Number.isFinite(n)?Math.max(0,n):0}function Pe(e){const r=B(e);return r>0?Math.min(1,Math.max(0,e.currentTime/r)):0}function Be(e){var n;const r=j(e);return Ve(r,(n=e.playlistMeta)==null?void 0:n.artworkUrl)}function Oe(e){var n;const r=j(e);return Br(r,(n=e.playlistMeta)==null?void 0:n.subtitle)}function F(e,r){function n(a){const t=b.useGingerState(),u=(r(t)??"").trim(),{className:s,style:o,fallback:c,empty:m,children:y}=a;if(!u){const x=m??c??null;return x?l.jsx("span",{className:s,style:o,children:x}):null}return y?l.jsx("span",{className:s,style:o,children:y(u,t)}):l.jsx("span",{className:s,style:o,children:u})}return n.displayName=e,n}function U(e,r){return F(e,n=>r(j(n)))}const Or=U("Ginger.Current.Title",e=>e==null?void 0:e.title),Yr=U("Ginger.Current.Artist",e=>e==null?void 0:e.artist),Qr=F("Ginger.Current.Album",e=>Oe(e)),Hr=U("Ginger.Current.Description",e=>e==null?void 0:e.description),Kr=F("Ginger.Current.Copyright",e=>{var n;const r=j(e);return(r==null?void 0:r.copyright)??((n=e.playlistMeta)==null?void 0:n.copyright)}),Xr=U("Ginger.Current.Genre",e=>e==null?void 0:e.genre),qr=U("Ginger.Current.Label",e=>e==null?void 0:e.label),zr=U("Ginger.Current.Isrc",e=>e==null?void 0:e.isrc),Wr=U("Ginger.Current.TrackNumber",e=>(e==null?void 0:e.trackNumber)!=null?String(e.trackNumber):void 0);function Ye({className:e,style:r,fallback:n,empty:a,children:t,format:i}){var c;const u=b.useGingerState(),s=(c=j(u))==null?void 0:c.year;if(typeof s!="number"||!Number.isFinite(s)){const m=a??n??null;return m?l.jsx("span",{className:e,style:r,children:m}):null}const o=i?i(s):String(s);return t?l.jsx("span",{className:e,style:r,children:t(o,u)}):l.jsx("span",{className:e,style:r,children:o})}Ye.displayName="Ginger.Current.Year";function Qe({className:e,style:r,fallback:n,empty:a,children:t,preserveWhitespace:i=!0}){var m;const u=b.useGingerState(),s=((m=j(u))==null?void 0:m.lyrics)??"",o=i?s.replace(/^\s+|\s+$/g,""):s.trim();if(!o){const y=a??n??null;return y?l.jsx("span",{className:e,style:r,children:y}):null}const c=i?{whiteSpace:"pre-wrap"}:void 0;return t?l.jsx("span",{className:e,style:{...c,...r},children:t(o,u)}):l.jsx("span",{className:e,style:{...c,...r},children:o})}Qe.displayName="Ginger.Current.Lyrics";const Le=/\[(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?\]/g;function He(e){const r=[];for(const n of e.split(/\r?\n/)){const a=[...n.matchAll(Le)];if(a.length===0)continue;const t=n.replace(Le,"").trim();for(const i of a){const u=Number(i[1]??0),s=Number(i[2]??0),o=Number((i[3]??"0").padEnd(3,"0")),c=u*60+s+o/1e3;Number.isFinite(c)&&c>=0&&r.push({time:c,text:t})}}return r.sort((n,a)=>n.time-a.time)}function Ke(){const{tracks:e,currentIndex:r}=b.useGingerPlayback(),{currentTime:n}=b.useGingerMedia(),a=e[r],t=f.useMemo(()=>a?Array.isArray(a.lyricsTimed)&&a.lyricsTimed.length>0?[...a.lyricsTimed].filter(u=>Number.isFinite(u.time)&&u.time>=0).sort((u,s)=>u.time-s.time):typeof a.lyrics=="string"?He(a.lyrics):[]:[],[a]),i=f.useMemo(()=>{for(let u=t.length-1;u>=0;u-=1)if(n>=t[u].time)return u;return-1},[n,t]);return{lines:t,activeIndex:i,activeLine:i>=0?t[i]??null:null}}function Ae({className:e,style:r,fallback:n,empty:a,unstyled:t=!1,activeClassName:i,lineClassName:u,children:s}){const o=b.useGingerState(),{lines:c,activeIndex:m}=Ke();if(c.length===0){const x=a??n??null;return x?l.jsx("span",{className:e,style:r,children:x}):null}const y=t?{}:{listStyle:"none",margin:0,padding:0,fontFamily:"var(--ginger-font-family, system-ui, sans-serif)",fontSize:"var(--ginger-font-size, 14px)",color:"var(--ginger-primary-color, #111827)"};return l.jsx("ul",{className:e,style:{...y,...r},"aria-label":"Synced lyrics",children:c.map((x,k)=>{const v=k===m;return l.jsx("li",{"aria-current":v?"true":void 0,"data-ginger-active":v||void 0,className:[u,v?i:void 0].filter(Boolean).join(" ")||void 0,style:t?void 0:{padding:"var(--ginger-playlist-row-padding, 4px 8px)",fontWeight:v?600:400,opacity:v?1:.75},children:s?s(x,k,v,o):x.text},`${x.time}-${k}`)})})}Ae.displayName="Ginger.Current.LyricsSynced";function Xe(){const{tracks:e,currentIndex:r}=b.useGingerPlayback(),{currentTime:n,seek:a}=b.useGingerMedia(),t=f.useMemo(()=>{var s;return[...((s=e[r])==null?void 0:s.chapters)??[]].filter(o=>o&&Number.isFinite(o.startSeconds)&&o.startSeconds>=0).sort((o,c)=>o.startSeconds-c.startSeconds)},[r,e]),i=f.useMemo(()=>{if(t.length===0)return-1;for(let u=t.length-1;u>=0;u-=1)if(n>=t[u].startSeconds)return u;return-1},[n,t]);return{list:t,activeIndex:i,active:i>=0?t[i]??null:null,seekTo:u=>{const s=t[u];s&&a(s.startSeconds)}}}function Q(e){if(!Number.isFinite(e)||e<0)return"0:00";const r=Math.floor(e%60);return`${Math.floor(e/60)}:${r.toString().padStart(2,"0")}`}function Re({className:e,style:r,fallback:n,empty:a,unstyled:t=!1,formatStart:i=Q,children:u}){const s=b.useGingerState(),{list:o,activeIndex:c,seekTo:m}=Xe();if(o.length===0){const x=a??n??null;return x?l.jsx("span",{className:e,style:r,children:x}):null}const y=t?{}:{listStyle:"none",margin:0,padding:0,fontFamily:"var(--ginger-font-family, system-ui, sans-serif)",fontSize:"var(--ginger-font-size, 14px)",color:"var(--ginger-primary-color, #111827)"};return l.jsx("ul",{className:e,style:{...y,...r},"aria-label":"Chapters",children:o.map((x,k)=>{const v=k===c;return l.jsx("li",{children:l.jsx("button",{type:"button","aria-current":v?"true":void 0,"data-ginger-active":v||void 0,onClick:()=>m(k),style:{width:t?void 0:"100%",textAlign:t?void 0:"left",border:t?void 0:"none",background:t?void 0:v?"var(--ginger-playlist-active-bg, rgba(17, 24, 39, 0.06))":"transparent",color:t?void 0:"inherit",font:t?void 0:"inherit",cursor:t?void 0:"pointer",padding:t?void 0:"var(--ginger-playlist-row-padding, 6px 8px)"},children:u?u(x,k,v,s):l.jsxs("span",{children:[l.jsx("span",{style:{opacity:.75,marginRight:"0.35em"},children:i(x.startSeconds)}),x.title]})})},`${x.startSeconds}-${x.title}`)})})}Re.displayName="Ginger.Current.Chapters";function qe({visible:e=!1,className:r,style:n,fallback:a,empty:t,children:i}){var o;const u=b.useGingerState();if(!e)return null;const s=((o=j(u))==null?void 0:o.fileUrl)??"";if(!s){const c=t??a??null;return c?l.jsx("span",{className:r,style:n,children:c}):null}return i?l.jsx("span",{className:r,style:n,children:i(s,u)}):l.jsx("span",{className:r,style:n,children:s})}qe.displayName="Ginger.Current.FileUrl";function ze({className:e,style:r,fallback:n,empty:a,sizes:t,loading:i,onError:u,decoding:s,unstyled:o=!1,imgStyle:c}){const m=b.useGingerState(),y=j(m),x=Be(m);if(!x){const v=a??n??null;return v?l.jsx("span",{className:e,style:r,children:v}):null}const k=[y==null?void 0:y.title,y==null?void 0:y.artist].filter(Boolean).join(" — ")||"Artwork";return l.jsx("div",{className:e,style:o?{...r}:{background:"var(--ginger-artwork-bg, transparent)",borderRadius:"var(--ginger-artwork-radius, 0)",overflow:"hidden",...r},children:l.jsx("img",{src:x,alt:k,sizes:t,loading:i,decoding:s,onError:u,style:{display:o?void 0:"block",width:o?void 0:"100%",height:o?void 0:"100%",objectFit:o?void 0:"cover",...c}})})}ze.displayName="Ginger.Current.Artwork";function We({base:e=0,className:r,style:n,fallback:a,empty:t,children:i}){const u=b.useGingerState();if(u.tracks.length===0){const c=t??a??null;return c?l.jsx("span",{className:r,style:n,children:c}):null}const o=String(u.currentIndex+e);return i?l.jsx("span",{className:r,style:n,children:i(o,u)}):l.jsx("span",{className:r,style:n,children:o})}We.displayName="Ginger.Current.QueueIndex";function Je({className:e,style:r,fallback:n,empty:a,children:t}){const i=b.useGingerState(),u=String(i.tracks.length);if(i.tracks.length===0){const s=a??n??null;return s?l.jsx("span",{className:e,style:r,children:s}):null}return t?l.jsx("span",{className:e,style:r,children:t(u,i)}):l.jsx("span",{className:e,style:r,children:u})}Je.displayName="Ginger.Current.QueueLength";function Ze({base:e=0,separator:r=" / ",className:n,style:a,fallback:t,empty:i,children:u}){const s=b.useGingerState(),o=s.tracks.length;if(o===0){const x=i??t??null;return x?l.jsx("span",{className:n,style:a,children:x}):null}const c=String(s.currentIndex+e),m=String(o),y=`${c}${r}${m}`;return u?l.jsx("span",{className:n,style:a,children:u({index:c,length:m,label:y},s)}):l.jsx("span",{className:n,style:a,children:y})}Ze.displayName="Ginger.Current.QueuePosition";function Ge(e,r,n){const{className:a,style:t,fallback:i,empty:u,children:s,format:o=Q}=n;if(!(e>=0)||!Number.isFinite(e)){const m=u??i??null;return m?l.jsx("span",{className:a,style:t,children:m}):null}const c=o(e);return s?l.jsx("span",{className:a,style:t,children:s(c,r)}):l.jsx("span",{className:a,style:t,children:c})}function er(e){const r=b.useGingerState();return Ge(r.currentTime,r,e)}er.displayName="Ginger.Current.Elapsed";function rr(e){const r=b.useGingerState();return Ge(B(r),r,e)}rr.displayName="Ginger.Current.Duration";function nr(e){const r=b.useGingerState();return Ge($e(r),r,e)}nr.displayName="Ginger.Current.Remaining";function tr({className:e,style:r,fallback:n,empty:a,children:t}){const i=b.useGingerState(),u=B(i),s=Pe(i);if(!(u>0)){const o=a??n??null;return o?l.jsx("span",{className:e,style:r,children:o}):null}return t?l.jsx("span",{className:e,style:r,children:t({fraction:s,currentTime:i.currentTime,duration:u},i)}):l.jsx("span",{className:e,style:r,children:`${Math.round(s*100)}%`})}tr.displayName="Ginger.Current.Progress";function ar({className:e,style:r,height:n=4,showBuffered:a=!1,unstyled:t=!1}){const i=b.useGingerState(),u=`${Math.round(Pe(i)*100)}%`,s=`${Math.round(Math.min(1,Math.max(0,i.bufferedFraction))*100)}%`;return l.jsxs("div",{className:e,style:t?{...r}:{width:"100%",height:n,background:"var(--ginger-muted-color, #e5e7eb)",borderRadius:999,overflow:"hidden",position:"relative",...r},"aria-hidden":!0,children:[a?l.jsx("div",{style:{position:t?void 0:"absolute",left:t?void 0:0,top:t?void 0:0,height:t?void 0:"100%",width:s,background:t?void 0:"var(--ginger-buffer-color, rgba(107, 114, 128, 0.35))"}}):null,l.jsx("div",{style:{position:t?void 0:"relative",width:u,height:t?void 0:"100%",background:t?void 0:"var(--ginger-primary-color, #111827)"}})]})}ar.displayName="Ginger.Current.TimeRail";function ir({className:e,style:r,height:n=4,unstyled:a=!1}){const t=b.useGingerState(),i=`${Math.round(Math.min(1,Math.max(0,t.bufferedFraction))*100)}%`;return l.jsx("div",{className:e,style:a?{...r}:{width:"100%",height:n,background:"var(--ginger-muted-color, #e5e7eb)",borderRadius:999,overflow:"hidden",...r},"aria-hidden":!0,children:l.jsx("div",{style:{width:i,height:a?void 0:"100%",background:a?void 0:"var(--ginger-buffer-color, rgba(107, 114, 128, 0.35))"}})})}ir.displayName="Ginger.Current.BufferRail";function ur({className:e,style:r,fallback:n,empty:a,children:t}){const i=b.useGingerState(),u=Ie(i);return t?l.jsx("span",{className:e,style:r,children:t(u,i)}):l.jsx("span",{className:e,style:r,children:u})}ur.displayName="Ginger.Current.PlaybackState";function sr({className:e,style:r,fallback:n,empty:a,live:t="polite",children:i}){const u=b.useGingerState(),s=u.errorMessage??"";if(!s){const o=a??n??null;return o?l.jsx("span",{className:e,style:r,children:o}):null}return i?l.jsx("span",{className:e,style:r,"aria-live":t,children:i(s,u)}):l.jsx("span",{className:e,style:r,"aria-live":t,children:s})}sr.displayName="Ginger.Current.ErrorMessage";const H={seek:"Seek",volume:"Volume",playbackSpeed:"Playback speed",nextTrack:"Next track",previousTrack:"Previous track",shuffle:"Shuffle",mute:"Mute",unmute:"Unmute",play:"Play",pause:"Pause",repeat:{off:"Repeat off",all:"Repeat all",one:"Repeat one"},playbackRateNormal:"1× normal",playbackRateTimes:e=>`${e}×`};function Jr(e){return e?{...H,...e,repeat:{...H.repeat,...e.repeat}}:H}const or=f.createContext(H);function Zr({locale:e,children:r}){const n=Jr(e);return l.jsx(or.Provider,{value:n,children:r})}function A(){return f.useContext(or)}function lr(){const e=b.useGingerPlayback(),r=b.useGingerMedia(),n=A(),a=f.useMemo(()=>b.gingerStateFromContextValues(e,r),[e,r]),t=B(a),i=t>0?a.currentTime:0,u=Number.isFinite(i)?i:0,s=t>0?`${Q(u)} of ${Q(t)}`:Q(u),o=c=>{r.seek(Number(c.currentTarget.value))};return{state:a,value:u,min:0,max:t>0?t:1,step:"any",ariaValueText:s,ariaLabel:n.seek,onSeekInput:o,onSeekChange:o}}function cr(){const e=b.useGingerPlayback(),r=b.useGingerMedia(),n=A(),a=f.useMemo(()=>b.gingerStateFromContextValues(e,r),[e,r]),t=i=>{r.setVolume(Number(i.currentTarget.value))};return{state:a,value:a.volume,min:0,max:1,step:"any",ariaValueText:`${Math.round(a.volume*100)}%`,ariaLabel:n.volume,onVolumeInput:t,onVolumeChange:t}}function dr(e){const r=b.useGingerPlayback(),n=A(),a=(e==null?void 0:e.playAriaLabel)??n.play,t=(e==null?void 0:e.pauseAriaLabel)??n.pause;return{isPaused:r.isPaused,toggle:r.togglePlayPause,ariaLabel:r.isPaused?a:t}}function fr({playLabel:e="Play",pauseLabel:r="Pause",playAriaLabel:n,pauseAriaLabel:a,children:t,type:i="button",onClick:u,...s}){const o=A(),c=typeof e=="string"?e:o.play,m=typeof r=="string"?r:o.pause,y=dr({playAriaLabel:n??c,pauseAriaLabel:a??m});return l.jsx("button",{...s,type:i,"aria-label":y.ariaLabel,onClick:x=>{y.toggle(),u==null||u(x)},children:t??(y.isPaused?e:r)})}fr.displayName="Ginger.Control.PlayPause";function gr({type:e="button",ariaLabel:r,onClick:n,...a}){const{repeatMode:t,cycleRepeat:i}=b.useGingerPlayback(),s=A().repeat[t];return l.jsx("button",{...a,type:e,"aria-label":r??s,onClick:o=>{i(),n==null||n(o)},children:s})}gr.displayName="Ginger.Control.Repeat";function pr({type:e="button",children:r="Next",ariaLabel:n,onClick:a,...t}){const{next:i}=b.useGingerPlayback(),u=A();return l.jsx("button",{...t,type:e,"aria-label":n??u.nextTrack,onClick:s=>{i(),a==null||a(s)},children:r})}pr.displayName="Ginger.Control.Next";function mr({type:e="button",children:r="Previous",ariaLabel:n,onClick:a,...t}){const{prev:i}=b.useGingerPlayback(),u=A();return l.jsx("button",{...t,type:e,"aria-label":n??u.previousTrack,onClick:s=>{i(),a==null||a(s)},children:r})}mr.displayName="Ginger.Control.Previous";function yr({type:e="button",children:r="Shuffle",ariaLabel:n,onClick:a,...t}){const{isShuffled:i,toggleShuffle:u}=b.useGingerPlayback(),s=A();return l.jsx("button",{...t,type:e,"aria-pressed":i,"aria-label":n??s.shuffle,onClick:o=>{u(),a==null||a(o)},children:r})}yr.displayName="Ginger.Control.Shuffle";function br({inputStyle:e,style:r,unstyled:n=!1,ariaLabel:a,...t}){const i=lr(),u=n?{...r,...e}:{width:"100%",...r,...e};return l.jsx("input",{...t,type:"range",min:i.min,max:i.max,step:i.step,value:i.value,"aria-label":a??i.ariaLabel,"aria-valuetext":i.ariaValueText,onInput:i.onSeekInput,onChange:i.onSeekChange,style:u})}br.displayName="Ginger.Control.SeekBar";function xr({inputStyle:e,style:r,unstyled:n=!1,ariaLabel:a,...t}){const i=cr(),u=n?{...r,...e}:{width:"100%",...r,...e};return l.jsx("input",{...t,type:"range",min:i.min,max:i.max,step:i.step,value:i.value,"aria-label":a??i.ariaLabel,"aria-valuetext":i.ariaValueText,onInput:i.onVolumeInput,onChange:i.onVolumeChange,style:u})}xr.displayName="Ginger.Control.Volume";function hr({ariaLabel:e,muteLabel:r,unmuteLabel:n,type:a="button",onClick:t,...i}){const{muted:u,toggleMute:s}=b.useGingerMedia(),o=A(),c=r??o.mute,m=n??o.unmute;return l.jsx("button",{...i,type:a,"aria-pressed":u,"aria-label":e??(u?o.unmute:o.mute),onClick:y=>{s(),t==null||t(y)},children:u?m:c})}hr.displayName="Ginger.Control.Mute";const en=[.5,.75,1,1.25,1.5,2];function vr({rates:e=en,style:r,ariaLabel:n,...a}){const{playbackRate:t,setPlaybackRate:i}=b.useGingerMedia(),u=A(),s=f.useMemo(()=>Array.from(new Set([...e,t])).sort((o,c)=>o-c),[e,t]);return l.jsx("select",{...a,"aria-label":n??u.playbackSpeed,value:String(t),style:r,onChange:o=>i(Number(o.currentTarget.value)),children:s.map(o=>l.jsx("option",{value:String(o),children:o===1?u.playbackRateNormal:u.playbackRateTimes(o)},o))})}vr.displayName="Ginger.Control.PlaybackRate";const Se=f.createContext(null);function rn(){const e=f.useContext(Se);if(!e)throw new Error("Ginger.Playlist.Track must be used inside <Ginger.Playlist>");return e}function kr({children:e,unstyled:r=!1,rowStyle:n,renderTrack:a,playOnSelect:t=!0,style:i,...u}){const{tracks:s,currentIndex:o,playTrackAt:c,selectTrackAt:m}=b.useGingerPlayback(),y=r?{...i}:{listStyle:"none",margin:0,padding:0,fontFamily:"var(--ginger-font-family, system-ui, sans-serif)",fontSize:"var(--ginger-font-size, 14px)",color:"var(--ginger-primary-color, #111827)",...i};return e!==void 0?l.jsx(Se.Provider,{value:{playOnSelect:t},children:l.jsx("ul",{style:y,...u,children:e})}):l.jsx(Se.Provider,{value:{playOnSelect:t},children:l.jsx("ul",{style:y,...u,children:s.map((k,v)=>{const I=v===o;return l.jsx("li",{children:l.jsx("button",{type:"button",onClick:()=>{t?c(v):m(v)},style:{width:r?void 0:"100%",textAlign:r?void 0:"left",border:r?void 0:"none",background:r?void 0:I?"var(--ginger-playlist-active-bg, rgba(17, 24, 39, 0.06))":"transparent",color:r?void 0:"inherit",font:r?void 0:"inherit",cursor:r?void 0:"pointer",padding:r?void 0:"var(--ginger-playlist-row-padding, 6px 8px)",...n},children:a?a(k,v,I):l.jsxs("span",{children:[k.title,k.artist?` — ${k.artist}`:""]})})},`${v}-${K(k)}`)})})})}kr.displayName="Ginger.Playlist";function Mr({index:e,unstyled:r=!1,className:n,style:a,children:t,liProps:i,onClick:u,...s}){const{playOnSelect:o}=rn(),{tracks:c,currentIndex:m,playTrackAt:y,selectTrackAt:x}=b.useGingerPlayback(),k=e===m,v=c[e],I=v!=null?l.jsxs("span",{children:[v.title,v.artist?` — ${v.artist}`:""]}):null;return l.jsx("li",{...i,children:l.jsx("button",{type:"button","aria-current":k?"true":void 0,"data-ginger-active":k||void 0,className:n,style:{width:r?void 0:"100%",textAlign:r?void 0:"left",border:r?void 0:"none",background:r?void 0:k?"var(--ginger-playlist-active-bg, rgba(17, 24, 39, 0.06))":"transparent",color:r?void 0:"inherit",font:r?void 0:"inherit",cursor:r?void 0:"pointer",padding:r?void 0:"var(--ginger-playlist-row-padding, 6px 8px)",...a},...s,onClick:p=>{u==null||u(p),!p.defaultPrevented&&(o?y(e):x(e))},children:t??I})})}Mr.displayName="Ginger.Playlist.Track";const nn=Object.assign(kr,{Track:Mr}),tn=F("Ginger.Queue.Title",e=>{var r;return(r=e.playlistMeta)==null?void 0:r.title}),an=F("Ginger.Queue.Subtitle",e=>{var r;return(r=e.playlistMeta)==null?void 0:r.subtitle}),un=F("Ginger.Queue.Description",e=>{var r;return(r=e.playlistMeta)==null?void 0:r.description}),sn=F("Ginger.Queue.Copyright",e=>{var r;return(r=e.playlistMeta)==null?void 0:r.copyright});function Tr({className:e,style:r,fallback:n,empty:a,unstyled:t=!1,imgStyle:i}){var c,m;const u=b.useGingerState(),s=(c=u.playlistMeta)==null?void 0:c.artworkUrl;if(!s){const y=a??n??null;return y?l.jsx("span",{className:e,style:r,children:y}):null}const o=((m=u.playlistMeta)==null?void 0:m.title)??"Playlist artwork";return l.jsx("span",{className:e,style:t?{...r}:{display:"inline-block",background:"var(--ginger-artwork-bg, #f3f4f6)",borderRadius:"var(--ginger-artwork-radius, 6px)",overflow:"hidden",...r},children:l.jsx("img",{src:s,alt:o,style:{display:t?void 0:"block",width:t?void 0:"100%",height:t?void 0:"100%",objectFit:t?void 0:"cover",...i}})})}Tr.displayName="Ginger.Queue.Artwork";function X(e){return Number.isFinite(e)?Math.min(1,Math.max(0,e)):1}function ke(e){return Number.isFinite(e)?Math.min(4,Math.max(.25,e)):1}const w={currentTime:0,duration:0,bufferedFraction:0,isBuffering:!1,errorMessage:null},on={...w,volume:1,muted:!1,playbackRate:1};function Er(e){const r=[...e.tracks];let n=S(e.currentIndex??0,r.length),a=null,t=r;return e.isShuffled&&r.length>1&&(a=[...r],t=De(r,n),n=0),{tracks:t,currentIndex:n,playbackMode:e.playbackMode??"playlist",isPaused:e.isPaused??!0,isShuffled:!!(e.isShuffled&&t.length>1),repeatMode:e.repeatMode??"off",originalTracks:a,playlistMeta:e.playlistMeta??null,...on,volume:X(e.volume??1),muted:e.muted??!1,playbackRate:ke(e.playbackRate??1)}}function ln(e,r){switch(r.type){case"INIT":{const{tracks:n,currentIndex:a,playlistMeta:t,isPaused:i,isShuffled:u,repeatMode:s,playbackMode:o,volume:c,muted:m,playbackRate:y}=r.payload;return Er({tracks:n,currentIndex:a,playlistMeta:t??null,isPaused:i??!0,isShuffled:u??!1,repeatMode:s??"off",playbackMode:o??"playlist",volume:c,muted:m,playbackRate:y})}case"SET_QUEUE":{const{tracks:n,currentIndex:a}=r.payload,t=[...n],i=S(a??e.currentIndex,t.length);return{...e,tracks:t,currentIndex:i,isShuffled:!1,originalTracks:null,...w}}case"INSERT_TRACK":{const n=r.payload.index??e.tracks.length,a=Fe(e.tracks,r.payload.track,n);if(r.payload.autoPlay){const i=S(n,a.length);return{...e,tracks:a,currentIndex:i,isShuffled:!1,originalTracks:null,isPaused:!1,...w}}const t=n<=e.currentIndex?e.currentIndex+1:e.currentIndex;return{...e,tracks:a,isShuffled:!1,originalTracks:null,currentIndex:S(t,a.length)}}case"REMOVE_TRACK":{const n=r.payload.index,a=wr(e.tracks,n),t=n<e.currentIndex?e.currentIndex-1:n===e.currentIndex?Math.min(e.currentIndex,Math.max(0,a.length-1)):e.currentIndex;return{...e,tracks:a,isShuffled:!1,originalTracks:null,currentIndex:S(t,a.length),...n===e.currentIndex?w:{}}}case"MOVE_TRACK":{const{fromIndex:n,toIndex:a}=r.payload,t=Dr(e.tracks,n,a);let i=e.currentIndex;return e.currentIndex===n?i=a:n<e.currentIndex&&a>=e.currentIndex?i-=1:n>e.currentIndex&&a<=e.currentIndex&&(i+=1),{...e,tracks:t,isShuffled:!1,originalTracks:null,currentIndex:S(i,t.length)}}case"ADD_NEXT":{const n=Fr(e.tracks,e.currentIndex,r.payload.track);return{...e,tracks:n,isShuffled:!1,originalTracks:null}}case"SET_INDEX":{const n=S(r.payload.index,e.tracks.length),a=r.payload.autoPlay,t=a===!0?!1:a===!1?!0:e.isPaused;return{...e,currentIndex:n,...w,isPaused:t}}case"PLAY":return{...e,isPaused:!1};case"PAUSE":return{...e,isPaused:!0};case"TOGGLE_PAUSE":return{...e,isPaused:!e.isPaused};case"SET_REPEAT":return{...e,repeatMode:r.payload};case"CYCLE_REPEAT":return{...e,repeatMode:$r(e.repeatMode)};case"TOGGLE_SHUFFLE":{if(e.tracks.length<=1)return{...e,isShuffled:!1,originalTracks:null};if(!e.isShuffled){const i=[...e.tracks],u=De(i,e.currentIndex);return{...e,isShuffled:!0,originalTracks:i,tracks:u,currentIndex:0}}const n=e.originalTracks?[...e.originalTracks]:[...e.tracks],a=e.tracks[e.currentIndex],t=Lr(n,a);return{...e,isShuffled:!1,originalTracks:null,tracks:n,currentIndex:S(t,n.length)}}case"NEXT":{const n=Ue(e),a=n===e.currentIndex;return{...e,currentIndex:n,...a?{}:w,isPaused:a?e.isPaused:!1}}case"PREV":{const n=Vr(e),a=n===e.currentIndex;return{...e,currentIndex:n,...a?{}:w,isPaused:a?e.isPaused:!1}}case"MEDIA_TIME_UPDATE":return{...e,currentTime:r.payload.currentTime,duration:Number.isFinite(r.payload.duration)?r.payload.duration:e.duration,bufferedFraction:r.payload.bufferedFraction,isBuffering:!1};case"MEDIA_LOADED_METADATA":return{...e,duration:Number.isFinite(r.payload.duration)?r.payload.duration:e.duration,bufferedFraction:r.payload.bufferedFraction,errorMessage:null};case"SET_PLAYLIST_META":return{...e,playlistMeta:r.payload};case"SET_PLAYBACK_MODE":return{...e,playbackMode:r.payload};case"MEDIA_ERROR":return{...e,errorMessage:r.payload.message,isPaused:!0,isBuffering:!1};case"MEDIA_WAITING":return{...e,isBuffering:!0};case"MEDIA_CANPLAY":return{...e,isBuffering:!1,errorMessage:null};case"MEDIA_PLAY":return{...e,isPaused:!1,isBuffering:!1};case"MEDIA_PAUSE":return{...e,isPaused:!0};case"RESET_MEDIA_TIMES":return{...e,currentTime:0,duration:0,bufferedFraction:0};case"MEDIA_SOURCE_CLEARED":return{...e,...w};case"SET_VOLUME":return{...e,volume:X(r.payload)};case"SET_MUTED":return{...e,muted:r.payload};case"TOGGLE_MUTE":return{...e,muted:!e.muted};case"SET_PLAYBACK_RATE":return{...e,playbackRate:ke(r.payload)};case"MEDIA_VOLUME_SYNC":{const{volume:n,muted:a}=r.payload,t=X(n);return t===e.volume&&a===e.muted?e:{...e,volume:t,muted:a}}default:return e}}function Ee(){return typeof navigator>"u"||!("mediaSession"in navigator)?null:navigator.mediaSession}function cn(e,r,n){var o;const a=r.tracks[r.currentIndex],t=a==null?void 0:a.title,i=a==null?void 0:a.artist,u=a==null?void 0:a.album,s=Ve(a,(o=r.playlistMeta)==null?void 0:o.artworkUrl);f.useEffect(()=>{const c=Ee();!e||!c||(c.metadata=new MediaMetadata({title:t??"Unknown track",artist:i,album:u,artwork:s?[{src:s}]:void 0}))},[e,t,i,u,s]),f.useEffect(()=>{const c=Ee();!e||!c||(c.playbackState=r.isPaused?"paused":"playing")},[e,r.isPaused]),f.useEffect(()=>{const c=Ee();if(!(!e||!c)){try{c.setActionHandler("play",n.play),c.setActionHandler("pause",n.pause),c.setActionHandler("nexttrack",n.next),c.setActionHandler("previoustrack",n.prev),c.setActionHandler("seekto",m=>{typeof m.seekTime=="number"&&Number.isFinite(m.seekTime)&&n.seek(m.seekTime)})}catch{}return()=>{try{c.setActionHandler("play",null),c.setActionHandler("pause",null),c.setActionHandler("nexttrack",null),c.setActionHandler("previoustrack",null),c.setActionHandler("seekto",null)}catch{}}}},[e,n])}const dn={"--ginger-primary-color":"#111827","--ginger-muted-color":"#6b7280","--ginger-font-size":"14px","--ginger-font-family":"system-ui, sans-serif","--ginger-playlist-row-padding":"6px 8px","--ginger-artwork-radius":"6px","--ginger-artwork-bg":"#f3f4f6","--ginger-playlist-active-bg":"rgba(17, 24, 39, 0.06)","--ginger-buffer-color":"rgba(107, 114, 128, 0.35)","--ginger-focus-ring":"0 0 0 2px rgba(59, 130, 246, 0.45)"};function fn({children:e,initialTracks:r=[],initialIndex:n=0,initialPlaylistMeta:a=null,initialShuffle:t=!1,initialRepeatMode:i="off",initialPlaybackMode:u="playlist",initialPaused:s=!0,initialVolume:o=1,initialMuted:c=!1,initialPlaybackRate:m=1,initialStateKey:y,locale:x,mediaSession:k=!1,beforePlay:v,onPlayBlocked:I,persistence:p,hydrateOnMount:E=!1,resumeOnTrackChange:P=!1,unstyled:G=!1,className:Me,style:O,onTrackChange:q,onPlay:z,onPause:W,onQueueEnd:J,onError:Z}){var _e;const D=f.useRef(null),[d,h]=f.useReducer(ln,void 0,()=>Er({tracks:r,currentIndex:n,playlistMeta:a,isPaused:s,isShuffled:t,repeatMode:i,playbackMode:u,volume:o,muted:c,playbackRate:m})),Ce=f.useRef(d),Te=f.useRef({tracks:r,currentIndex:n,playlistMeta:a,isPaused:s,isShuffled:t,repeatMode:i,playbackMode:u,volume:o,muted:c,playbackRate:m});Te.current={tracks:r,currentIndex:n,playlistMeta:a,isPaused:s,isShuffled:t,repeatMode:i,playbackMode:u,volume:o,muted:c,playbackRate:m};const Y=f.useRef(void 0);f.useEffect(()=>{if(y===void 0){Y.current=void 0;return}if(Y.current===void 0){Y.current=y;return}if(Y.current===y)return;Y.current=y;const g=Te.current;h({type:"INIT",payload:{tracks:g.tracks,currentIndex:g.currentIndex,playlistMeta:g.playlistMeta,isPaused:g.isPaused,isShuffled:g.isShuffled,repeatMode:g.repeatMode,playbackMode:g.playbackMode,volume:g.volume,muted:g.muted,playbackRate:g.playbackRate}})},[y,h]),f.useEffect(()=>{Ce.current=d},[d]);const je=d.tracks[d.currentIndex]??null;f.useEffect(()=>{q==null||q(je,d.currentIndex)},[je,d.currentIndex,q]),f.useEffect(()=>{d.errorMessage&&(Z==null||Z(d.errorMessage))},[d.errorMessage,Z]);const ee=f.useRef(void 0);f.useEffect(()=>{if(ee.current===void 0){ee.current=d.isPaused;return}ee.current!==d.isPaused&&(d.isPaused?W==null||W():z==null||z()),ee.current=d.isPaused},[d.isPaused,W,z]);const _=f.useCallback(()=>{h({type:"PLAY"})},[]),N=f.useCallback(()=>{var g;h({type:"PAUSE"}),(g=D.current)==null||g.pause()},[]),re=f.useCallback(()=>{d.isPaused?_():N()},[N,_,d.isPaused]),L=f.useCallback(g=>{const M=D.current;M&&Number.isFinite(g)&&(M.currentTime=Math.max(0,g))},[]),ne=f.useCallback(g=>{h({type:"SET_VOLUME",payload:X(g)})},[]),te=f.useCallback(g=>{h({type:"SET_MUTED",payload:g})},[]),ae=f.useCallback(()=>{h({type:"TOGGLE_MUTE"})},[]),ie=f.useCallback(g=>{h({type:"SET_PLAYBACK_RATE",payload:ke(g)})},[]),V=f.useCallback(()=>{h({type:"NEXT"})},[]),$=f.useCallback(()=>{h({type:"PREV"})},[]),ue=f.useCallback(g=>{h({type:"SET_REPEAT",payload:g})},[]),se=f.useCallback(()=>{h({type:"CYCLE_REPEAT"})},[]),oe=f.useCallback(()=>{h({type:"TOGGLE_SHUFFLE"})},[]),le=f.useCallback((g,M)=>{h({type:"SET_QUEUE",payload:{tracks:g,currentIndex:M}})},[]),ce=f.useCallback((g,M,T)=>{h({type:"INSERT_TRACK",payload:{track:g,index:M,autoPlay:T}})},[]),de=f.useCallback(g=>{h({type:"REMOVE_TRACK",payload:{index:g}})},[]),fe=f.useCallback((g,M)=>{h({type:"MOVE_TRACK",payload:{fromIndex:g,toIndex:M}})},[]),ge=f.useCallback(g=>{h({type:"ADD_NEXT",payload:{track:g}})},[]),pe=f.useCallback(g=>{h({type:"SET_INDEX",payload:{index:g,autoPlay:!0}})},[]),me=f.useCallback(g=>{h({type:"SET_INDEX",payload:{index:g,autoPlay:!1}})},[]),ye=f.useCallback(g=>{h({type:"SET_PLAYLIST_META",payload:g})},[]),be=f.useCallback(g=>{h({type:"SET_PLAYBACK_MODE",payload:g})},[]),xe=f.useCallback(g=>{h({type:"INIT",payload:g})},[]);f.useEffect(()=>{if(!p||!E)return;const g=p.get("ginger:volume"),M=p.get("ginger:muted"),T=p.get("ginger:playbackRate"),C=p.get("ginger:repeatMode"),ve=p.get("ginger:currentIndex"),R=Te.current;h({type:"INIT",payload:{tracks:R.tracks,playlistMeta:R.playlistMeta,isPaused:R.isPaused,isShuffled:R.isShuffled,playbackMode:R.playbackMode,currentIndex:typeof ve=="number"?ve:R.currentIndex,repeatMode:C==="off"||C==="all"||C==="one"?C:R.repeatMode,volume:typeof g=="number"?g:R.volume,muted:typeof M=="boolean"?M:R.muted,playbackRate:typeof T=="number"?T:R.playbackRate}})},[E,p]),f.useEffect(()=>{p&&(p.set("ginger:volume",d.volume),p.set("ginger:muted",d.muted),p.set("ginger:playbackRate",d.playbackRate),p.set("ginger:repeatMode",d.repeatMode),p.set("ginger:currentIndex",d.currentIndex))},[p,d.volume,d.muted,d.playbackRate,d.repeatMode,d.currentIndex]),f.useEffect(()=>{if(!p||!P)return;const g=d.tracks[d.currentIndex];if(!g)return;const M=`ginger:resume:${K(g)}`,T=p.get(M);typeof T=="number"&&Number.isFinite(T)&&L(T)},[p,P,d.currentIndex,d.tracks,L]),f.useEffect(()=>{if(!p||!P)return;const g=d.tracks[d.currentIndex];if(!g||!(d.currentTime>=0))return;const M=`ginger:resume:${K(g)}`,T=setTimeout(()=>p.set(M,d.currentTime),250);return()=>clearTimeout(T)},[p,P,d.currentIndex,d.tracks,d.currentTime]);const Sr=(_e=d.tracks[d.currentIndex])==null?void 0:_e.fileUrl;f.useEffect(()=>{const g=D.current;if(!g)return;if(d.isPaused){g.pause();return}let M=!1;return(async()=>{if(v){let T=!1;try{T=await v()}catch(C){const ve=C instanceof Error?C.message:"beforePlay rejected";h({type:"MEDIA_ERROR",payload:{message:ve}});return}if(!T){M||(h({type:"PAUSE"}),I==null||I());return}}M||g.play().catch(T=>{const C=T instanceof Error?T.message:typeof T=="string"?T:"Playback failed (e.g. autoplay blocked or unavailable source)";h({type:"MEDIA_ERROR",payload:{message:C}})})})(),()=>{M=!0}},[v,Sr,I,d.isPaused]);const he=f.useCallback(()=>{const g=Ur(Ce.current);if(g.kind==="replay_same"){const T=D.current;T&&(T.currentTime=0),h({type:"PLAY"});return}if(g.kind==="stop"){h({type:"PAUSE"}),J==null||J();return}const M=g.nextIndex;h({type:"SET_INDEX",payload:{index:M,autoPlay:!0}})},[J]),Ir=f.useMemo(()=>({play:_,pause:N,next:V,prev:$,seek:L}),[_,N,V,$,L]);cn(!!k,d,Ir);const Pr=x!=null&&x.seek&&/[\u0590-\u08FF]/.test(x.seek)?"rtl":"ltr",Ar=f.useMemo(()=>({state:d,dispatch:h,audioRef:D,notifyEnded:he,init:xe,play:_,pause:N,togglePlayPause:re,seek:L,setVolume:ne,setMuted:te,toggleMute:ae,setPlaybackRate:ie,next:V,prev:$,setRepeatMode:ue,cycleRepeat:se,toggleShuffle:oe,setQueue:le,insertTrackAt:ce,removeTrackAt:de,moveTrack:fe,enqueueNext:ge,playTrackAt:pe,selectTrackAt:me,setPlaylistMeta:ye,setPlaybackMode:be}),[se,h,xe,V,he,N,_,pe,ce,de,fe,ge,me,$,L,te,ie,le,ue,ye,be,ne,d,ae,re,oe]),Rr=f.useMemo(()=>({tracks:d.tracks,currentIndex:d.currentIndex,isPaused:d.isPaused,isShuffled:d.isShuffled,repeatMode:d.repeatMode,originalTracks:d.originalTracks,playlistMeta:d.playlistMeta,init:xe,play:_,pause:N,togglePlayPause:re,next:V,prev:$,setRepeatMode:ue,cycleRepeat:se,toggleShuffle:oe,playbackMode:d.playbackMode,setQueue:le,insertTrackAt:ce,removeTrackAt:de,moveTrack:fe,enqueueNext:ge,playTrackAt:pe,selectTrackAt:me,setPlaylistMeta:ye,setPlaybackMode:be,dispatch:h}),[d.tracks,d.currentIndex,d.isPaused,d.isShuffled,d.repeatMode,d.playbackMode,d.originalTracks,d.playlistMeta,xe,_,N,re,V,$,ue,se,oe,le,ce,de,fe,ge,pe,me,ye,be,h]),Gr=f.useMemo(()=>({currentTime:d.currentTime,duration:d.duration,bufferedFraction:d.bufferedFraction,isBuffering:d.isBuffering,errorMessage:d.errorMessage,volume:d.volume,muted:d.muted,playbackRate:d.playbackRate,seek:L,setVolume:ne,setMuted:te,toggleMute:ae,setPlaybackRate:ie,audioRef:D,notifyEnded:he,dispatch:h}),[d.currentTime,d.duration,d.bufferedFraction,d.isBuffering,d.errorMessage,d.volume,d.muted,d.playbackRate,L,ne,te,ae,ie,D,he,h]),Cr=Ie(d),jr=f.useMemo(()=>G?O:{...dn,...O},[O,G]);return l.jsx(Zr,{locale:x,children:l.jsx(b.GingerPlaybackContext.Provider,{value:Rr,children:l.jsx(b.GingerMediaContext.Provider,{value:Gr,children:l.jsx(we.Provider,{value:Ar,children:l.jsx("div",{className:Me,style:jr,"data-ginger-playback":Cr,dir:Pr,children:e})})})})})}const gn={Provider:fn,Player:Nr,Current:{Title:Or,Artist:Yr,Album:Qr,Description:Hr,Copyright:Kr,Genre:Xr,Label:qr,Isrc:zr,TrackNumber:Wr,Year:Ye,Lyrics:Qe,LyricsSynced:Ae,Chapters:Re,FileUrl:qe,Artwork:ze,QueueIndex:We,QueueLength:Je,QueuePosition:Ze,Elapsed:er,Duration:rr,Remaining:nr,Progress:tr,TimeRail:ar,BufferRail:ir,PlaybackState:ur,ErrorMessage:sr},Queue:{Title:tn,Subtitle:an,Description:un,Copyright:sn,Artwork:Tr},Control:{PlayPause:fr,Repeat:gr,Next:pr,Previous:mr,Shuffle:yr,SeekBar:br,Volume:xr,Mute:hr,PlaybackRate:vr},Playlist:nn};exports.Chapters=Re;exports.Ginger=gn;exports.LyricsSynced=Ae;exports.clampPlaybackRate=ke;exports.clampVolume=X;exports.computeNextIndex=Ue;exports.defaultGingerLocale=H;exports.derivePlaybackUiState=Ie;exports.effectiveDuration=B;exports.effectiveRemaining=$e;exports.getCurrentTrack=j;exports.parseLrc=He;exports.progressFraction=Pe;exports.resolvedAlbumLine=Oe;exports.resolvedArtwork=Be;exports.useGingerChapters=Xe;exports.useGingerLocale=A;exports.useGingerLyricsSync=Ke;exports.usePlayPauseBinding=dr;exports.useSeekBarBinding=lr;exports.useVolumeSlider=cr;
|
|
2
|
-
//# sourceMappingURL=ginger-BKmH7kWx.cjs.map
|