@lucaismyname/ginger 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/dist/audio/GingerPlayer.d.ts +9 -0
  3. package/dist/audio/GingerPlayer.d.ts.map +1 -0
  4. package/dist/components/controls/Controls.d.ts +38 -0
  5. package/dist/components/controls/Controls.d.ts.map +1 -0
  6. package/dist/components/current/Artwork.d.ts +10 -0
  7. package/dist/components/current/Artwork.d.ts.map +1 -0
  8. package/dist/components/current/FileUrl.d.ts +10 -0
  9. package/dist/components/current/FileUrl.d.ts.map +1 -0
  10. package/dist/components/current/Lyrics.d.ts +12 -0
  11. package/dist/components/current/Lyrics.d.ts.map +1 -0
  12. package/dist/components/current/Playback.d.ts +17 -0
  13. package/dist/components/current/Playback.d.ts.map +1 -0
  14. package/dist/components/current/QueueMeta.d.ts +31 -0
  15. package/dist/components/current/QueueMeta.d.ts.map +1 -0
  16. package/dist/components/current/Time.d.ts +38 -0
  17. package/dist/components/current/Time.d.ts.map +1 -0
  18. package/dist/components/current/Year.d.ts +9 -0
  19. package/dist/components/current/Year.d.ts.map +1 -0
  20. package/dist/components/current/createTextDisplay.d.ts +8 -0
  21. package/dist/components/current/createTextDisplay.d.ts.map +1 -0
  22. package/dist/components/current/index.d.ts +9 -0
  23. package/dist/components/current/index.d.ts.map +1 -0
  24. package/dist/components/current/texts.d.ts +10 -0
  25. package/dist/components/current/texts.d.ts.map +1 -0
  26. package/dist/components/playlist/GingerPlaylist.d.ts +13 -0
  27. package/dist/components/playlist/GingerPlaylist.d.ts.map +1 -0
  28. package/dist/components/queue/QueueDisplay.d.ts +14 -0
  29. package/dist/components/queue/QueueDisplay.d.ts.map +1 -0
  30. package/dist/context/GingerContext.d.ts +27 -0
  31. package/dist/context/GingerContext.d.ts.map +1 -0
  32. package/dist/context/GingerProvider.d.ts +3 -0
  33. package/dist/context/GingerProvider.d.ts.map +1 -0
  34. package/dist/core/playbackReducer.d.ts +11 -0
  35. package/dist/core/playbackReducer.d.ts.map +1 -0
  36. package/dist/core/queue.d.ts +5 -0
  37. package/dist/core/queue.d.ts.map +1 -0
  38. package/dist/core/transitions.d.ts +20 -0
  39. package/dist/core/transitions.d.ts.map +1 -0
  40. package/dist/ginger.d.ts +52 -0
  41. package/dist/ginger.d.ts.map +1 -0
  42. package/dist/hooks/useGinger.d.ts +27 -0
  43. package/dist/hooks/useGinger.d.ts.map +1 -0
  44. package/dist/index.cjs +2 -0
  45. package/dist/index.cjs.map +1 -0
  46. package/dist/index.d.ts +13 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +897 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/internal/formatTime.d.ts +2 -0
  51. package/dist/internal/formatTime.d.ts.map +1 -0
  52. package/dist/internal/selectors.d.ts +9 -0
  53. package/dist/internal/selectors.d.ts.map +1 -0
  54. package/dist/types.d.ts +141 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/package.json +45 -0
package/dist/index.js ADDED
@@ -0,0 +1,897 @@
1
+ import { jsx as s, jsxs as De } from "react/jsx-runtime";
2
+ import { useContext as Ne, createContext as we, useEffect as S, useRef as J, useReducer as Ue, useCallback as M, useMemo as D } from "react";
3
+ const re = we(null);
4
+ function g() {
5
+ const e = Ne(re);
6
+ if (!e) throw new Error("Ginger components must be used within <Ginger.Provider>");
7
+ return e;
8
+ }
9
+ function Z(e) {
10
+ const { buffered: r, duration: n } = e;
11
+ return !(n > 0) || r.length === 0 ? 0 : Math.min(1, r.end(r.length - 1) / n);
12
+ }
13
+ function Fe({ className: e, style: r, preload: n = "metadata", crossOrigin: t }) {
14
+ var d;
15
+ const { audioRef: i, dispatch: u, state: a, notifyEnded: l } = g(), c = ((d = a.tracks[a.currentIndex]) == null ? void 0 : d.fileUrl) ?? "";
16
+ return S(() => {
17
+ const o = i.current;
18
+ if (o) {
19
+ if (!c) {
20
+ o.removeAttribute("src");
21
+ return;
22
+ }
23
+ o.getAttribute("src") !== c && (o.src = c, o.load());
24
+ }
25
+ }, [i, a.currentIndex, a.tracks, c]), /* @__PURE__ */ s(
26
+ "audio",
27
+ {
28
+ ref: i,
29
+ className: e,
30
+ style: r,
31
+ preload: n,
32
+ crossOrigin: t,
33
+ controls: !1,
34
+ onTimeUpdate: (o) => {
35
+ const p = o.currentTarget;
36
+ u({
37
+ type: "MEDIA_TIME_UPDATE",
38
+ payload: {
39
+ currentTime: p.currentTime,
40
+ duration: p.duration,
41
+ bufferedFraction: Z(p)
42
+ }
43
+ });
44
+ },
45
+ onLoadedMetadata: (o) => {
46
+ const p = o.currentTarget;
47
+ u({
48
+ type: "MEDIA_LOADED_METADATA",
49
+ payload: {
50
+ duration: p.duration,
51
+ bufferedFraction: Z(p)
52
+ }
53
+ });
54
+ },
55
+ onEnded: () => l(),
56
+ onPlay: () => u({ type: "MEDIA_PLAY" }),
57
+ onPause: () => u({ type: "MEDIA_PAUSE" }),
58
+ onWaiting: () => u({ type: "MEDIA_WAITING" }),
59
+ onCanPlay: () => u({ type: "MEDIA_CANPLAY" }),
60
+ onError: () => {
61
+ var m;
62
+ const o = i.current, p = (m = o == null ? void 0 : o.error) == null ? void 0 : m.code;
63
+ u({ type: "MEDIA_ERROR", payload: { message: p === 1 ? "MEDIA_ERR_ABORTED" : p === 2 ? "MEDIA_ERR_NETWORK" : p === 3 ? "MEDIA_ERR_DECODE" : p === 4 ? "MEDIA_ERR_SRC_NOT_SUPPORTED" : "MEDIA_ERR_UNKNOWN" } });
64
+ }
65
+ }
66
+ );
67
+ }
68
+ function E(e, r) {
69
+ return r <= 0 ? 0 : Math.max(0, Math.min(r - 1, e));
70
+ }
71
+ function ne(e, r) {
72
+ if (e.length <= 1) return [...e];
73
+ const n = e[r];
74
+ if (!n) return [...e];
75
+ const t = e.filter((i, u) => u !== r);
76
+ for (let i = t.length - 1; i > 0; i--) {
77
+ const u = Math.floor(Math.random() * (i + 1));
78
+ [t[i], t[u]] = [t[u], t[i]];
79
+ }
80
+ return [n, ...t];
81
+ }
82
+ function Le(e, r) {
83
+ const n = e.findIndex((t) => t.fileUrl === r);
84
+ return n === -1 ? 0 : n;
85
+ }
86
+ function Qe(e) {
87
+ const { tracks: r, currentIndex: n, repeatMode: t } = e, i = r.length;
88
+ return i === 0 ? { kind: "stop", nextIndex: 0 } : t === "one" ? { kind: "replay_same" } : n < i - 1 ? { kind: "advance", nextIndex: n + 1 } : t === "all" ? { kind: "wrap", nextIndex: 0 } : { kind: "stop", nextIndex: E(n, i) };
89
+ }
90
+ function Be(e) {
91
+ const { tracks: r, currentIndex: n, repeatMode: t } = e, i = r.length;
92
+ return i === 0 ? 0 : n < i - 1 ? n + 1 : t === "all" ? 0 : E(n, i);
93
+ }
94
+ function $e(e) {
95
+ const { tracks: r, currentIndex: n, repeatMode: t } = e, i = r.length;
96
+ return i === 0 ? 0 : n > 0 ? n - 1 : t === "all" ? i - 1 : 0;
97
+ }
98
+ function Ye(e) {
99
+ return e === "off" ? "all" : e === "all" ? "one" : "off";
100
+ }
101
+ function Oe(e, r) {
102
+ return (e == null ? void 0 : e.artworkUrl) ?? r ?? void 0;
103
+ }
104
+ function je(e, r) {
105
+ return (e == null ? void 0 : e.album) ?? r ?? void 0;
106
+ }
107
+ function A(e) {
108
+ return e.tracks[e.currentIndex] ?? null;
109
+ }
110
+ function te(e) {
111
+ 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 - 0.05 ? "ended" : "paused" : "playing";
112
+ }
113
+ function R(e) {
114
+ var t;
115
+ const r = e.duration;
116
+ if (Number.isFinite(r) && r > 0) return r;
117
+ const n = (t = e.tracks[e.currentIndex]) == null ? void 0 : t.durationSeconds;
118
+ return typeof n == "number" && Number.isFinite(n) && n > 0 ? n : 0;
119
+ }
120
+ function ie(e) {
121
+ const n = R(e) - e.currentTime;
122
+ return Number.isFinite(n) ? Math.max(0, n) : 0;
123
+ }
124
+ function N(e) {
125
+ const r = R(e);
126
+ return r > 0 ? Math.min(1, Math.max(0, e.currentTime / r)) : 0;
127
+ }
128
+ function ue(e) {
129
+ var n;
130
+ const r = A(e);
131
+ return Oe(r, (n = e.playlistMeta) == null ? void 0 : n.artworkUrl);
132
+ }
133
+ function ae(e) {
134
+ var n;
135
+ const r = A(e);
136
+ return je(r, (n = e.playlistMeta) == null ? void 0 : n.subtitle);
137
+ }
138
+ function T(e, r) {
139
+ function n(t) {
140
+ const { state: i } = g(), a = (r(i) ?? "").trim(), { className: l, style: c, fallback: d, empty: o, children: p } = t;
141
+ if (!a) {
142
+ const b = o ?? d ?? null;
143
+ return b ? /* @__PURE__ */ s("span", { className: l, style: c, children: b }) : null;
144
+ }
145
+ return p ? /* @__PURE__ */ s("span", { className: l, style: c, children: p(a, i) }) : /* @__PURE__ */ s("span", { className: l, style: c, children: a });
146
+ }
147
+ return n.displayName = e, n;
148
+ }
149
+ function I(e, r) {
150
+ return T(e, (n) => r(A(n)));
151
+ }
152
+ const Ve = I("Ginger.Current.Title", (e) => e == null ? void 0 : e.title), Xe = I("Ginger.Current.Artist", (e) => e == null ? void 0 : e.artist), We = T("Ginger.Current.Album", (e) => ae(e)), ze = I("Ginger.Current.Description", (e) => e == null ? void 0 : e.description), qe = T("Ginger.Current.Copyright", (e) => {
153
+ var n;
154
+ const r = A(e);
155
+ return (r == null ? void 0 : r.copyright) ?? ((n = e.playlistMeta) == null ? void 0 : n.copyright);
156
+ }), He = I("Ginger.Current.Genre", (e) => e == null ? void 0 : e.genre), Ke = I("Ginger.Current.Label", (e) => e == null ? void 0 : e.label), Je = I("Ginger.Current.Isrc", (e) => e == null ? void 0 : e.isrc), Ze = I(
157
+ "Ginger.Current.TrackNumber",
158
+ (e) => (e == null ? void 0 : e.trackNumber) != null ? String(e.trackNumber) : void 0
159
+ );
160
+ function se({ className: e, style: r, fallback: n, empty: t, children: i, format: u }) {
161
+ var d;
162
+ const { state: a } = g(), l = (d = A(a)) == null ? void 0 : d.year;
163
+ if (typeof l != "number" || !Number.isFinite(l)) {
164
+ const o = t ?? n ?? null;
165
+ return o ? /* @__PURE__ */ s("span", { className: e, style: r, children: o }) : null;
166
+ }
167
+ const c = u ? u(l) : String(l);
168
+ return i ? /* @__PURE__ */ s("span", { className: e, style: r, children: i(c, a) }) : /* @__PURE__ */ s("span", { className: e, style: r, children: c });
169
+ }
170
+ se.displayName = "Ginger.Current.Year";
171
+ function le({ className: e, style: r, fallback: n, empty: t, children: i, preserveWhitespace: u = !0 }) {
172
+ var o;
173
+ const { state: a } = g(), l = ((o = A(a)) == null ? void 0 : o.lyrics) ?? "", c = u ? l.replace(/^\s+|\s+$/g, "") : l.trim();
174
+ if (!c) {
175
+ const p = t ?? n ?? null;
176
+ return p ? /* @__PURE__ */ s("span", { className: e, style: r, children: p }) : null;
177
+ }
178
+ const d = u ? { whiteSpace: "pre-wrap" } : void 0;
179
+ return i ? /* @__PURE__ */ s("span", { className: e, style: { ...d, ...r }, children: i(c, a) }) : /* @__PURE__ */ s("span", { className: e, style: { ...d, ...r }, children: c });
180
+ }
181
+ le.displayName = "Ginger.Current.Lyrics";
182
+ function oe({ visible: e = !1, className: r, style: n, fallback: t, empty: i, children: u }) {
183
+ var c;
184
+ const { state: a } = g();
185
+ if (!e) return null;
186
+ const l = ((c = A(a)) == null ? void 0 : c.fileUrl) ?? "";
187
+ if (!l) {
188
+ const d = i ?? t ?? null;
189
+ return d ? /* @__PURE__ */ s("span", { className: r, style: n, children: d }) : null;
190
+ }
191
+ return u ? /* @__PURE__ */ s("span", { className: r, style: n, children: u(l, a) }) : /* @__PURE__ */ s("span", { className: r, style: n, children: l });
192
+ }
193
+ oe.displayName = "Ginger.Current.FileUrl";
194
+ function ce({ className: e, style: r, fallback: n, empty: t, sizes: i, loading: u, onError: a, decoding: l, imgStyle: c }) {
195
+ const { state: d } = g(), o = A(d), p = ue(d);
196
+ if (!p) {
197
+ const m = t ?? n ?? null;
198
+ return m ? /* @__PURE__ */ s("span", { className: e, style: r, children: m }) : null;
199
+ }
200
+ const b = [o == null ? void 0 : o.title, o == null ? void 0 : o.artist].filter(Boolean).join(" — ") || "Artwork";
201
+ return /* @__PURE__ */ s(
202
+ "span",
203
+ {
204
+ className: e,
205
+ style: {
206
+ display: "inline-block",
207
+ background: "var(--ginger-artwork-bg, #f3f4f6)",
208
+ borderRadius: "var(--ginger-artwork-radius, 6px)",
209
+ overflow: "hidden",
210
+ ...r
211
+ },
212
+ children: /* @__PURE__ */ s(
213
+ "img",
214
+ {
215
+ src: p,
216
+ alt: b,
217
+ sizes: i,
218
+ loading: u,
219
+ decoding: l,
220
+ onError: a,
221
+ style: {
222
+ display: "block",
223
+ width: "100%",
224
+ height: "100%",
225
+ objectFit: "cover",
226
+ ...c
227
+ }
228
+ }
229
+ )
230
+ }
231
+ );
232
+ }
233
+ ce.displayName = "Ginger.Current.Artwork";
234
+ function de({ base: e = 0, className: r, style: n, fallback: t, empty: i, children: u }) {
235
+ const { state: a } = g();
236
+ if (a.tracks.length === 0) {
237
+ const d = i ?? t ?? null;
238
+ return d ? /* @__PURE__ */ s("span", { className: r, style: n, children: d }) : null;
239
+ }
240
+ const c = String(a.currentIndex + e);
241
+ return u ? /* @__PURE__ */ s("span", { className: r, style: n, children: u(c, a) }) : /* @__PURE__ */ s("span", { className: r, style: n, children: c });
242
+ }
243
+ de.displayName = "Ginger.Current.QueueIndex";
244
+ function fe({ className: e, style: r, fallback: n, empty: t, children: i }) {
245
+ const { state: u } = g(), a = String(u.tracks.length);
246
+ if (u.tracks.length === 0) {
247
+ const l = t ?? n ?? null;
248
+ return l ? /* @__PURE__ */ s("span", { className: e, style: r, children: l }) : null;
249
+ }
250
+ return i ? /* @__PURE__ */ s("span", { className: e, style: r, children: i(a, u) }) : /* @__PURE__ */ s("span", { className: e, style: r, children: a });
251
+ }
252
+ fe.displayName = "Ginger.Current.QueueLength";
253
+ function pe({
254
+ base: e = 0,
255
+ separator: r = " / ",
256
+ className: n,
257
+ style: t,
258
+ fallback: i,
259
+ empty: u,
260
+ children: a
261
+ }) {
262
+ const { state: l } = g(), c = l.tracks.length;
263
+ if (c === 0) {
264
+ const b = u ?? i ?? null;
265
+ return b ? /* @__PURE__ */ s("span", { className: n, style: t, children: b }) : null;
266
+ }
267
+ const d = String(l.currentIndex + e), o = String(c), p = `${d}${r}${o}`;
268
+ return a ? /* @__PURE__ */ s("span", { className: n, style: t, children: a({ index: d, length: o, label: p }, l) }) : /* @__PURE__ */ s("span", { className: n, style: t, children: p });
269
+ }
270
+ pe.displayName = "Ginger.Current.QueuePosition";
271
+ function er(e) {
272
+ if (!Number.isFinite(e) || e < 0) return "0:00";
273
+ const r = Math.floor(e % 60);
274
+ return `${Math.floor(e / 60)}:${r.toString().padStart(2, "0")}`;
275
+ }
276
+ function w(e, r, n) {
277
+ const { className: t, style: i, fallback: u, empty: a, children: l, format: c = er } = n;
278
+ if (!(e >= 0) || !Number.isFinite(e)) {
279
+ const o = a ?? u ?? null;
280
+ return o ? /* @__PURE__ */ s("span", { className: t, style: i, children: o }) : null;
281
+ }
282
+ const d = c(e);
283
+ return l ? /* @__PURE__ */ s("span", { className: t, style: i, children: l(d, r) }) : /* @__PURE__ */ s("span", { className: t, style: i, children: d });
284
+ }
285
+ function ge(e) {
286
+ const { state: r } = g();
287
+ return w(r.currentTime, r, e);
288
+ }
289
+ ge.displayName = "Ginger.Current.Elapsed";
290
+ function ye(e) {
291
+ const { state: r } = g();
292
+ return w(R(r), r, e);
293
+ }
294
+ ye.displayName = "Ginger.Current.Duration";
295
+ function he(e) {
296
+ const { state: r } = g();
297
+ return w(ie(r), r, e);
298
+ }
299
+ he.displayName = "Ginger.Current.Remaining";
300
+ function me({ className: e, style: r, fallback: n, empty: t, children: i }) {
301
+ const { state: u } = g(), a = R(u), l = N(u);
302
+ if (!(a > 0)) {
303
+ const c = t ?? n ?? null;
304
+ return c ? /* @__PURE__ */ s("span", { className: e, style: r, children: c }) : null;
305
+ }
306
+ return i ? /* @__PURE__ */ s("span", { className: e, style: r, children: i({ fraction: l, currentTime: u.currentTime, duration: a }, u) }) : /* @__PURE__ */ s("span", { className: e, style: r, children: `${Math.round(l * 100)}%` });
307
+ }
308
+ me.displayName = "Ginger.Current.Progress";
309
+ function Pe({ className: e, style: r, height: n = 4 }) {
310
+ const { state: t } = g(), i = `${Math.round(N(t) * 100)}%`;
311
+ return /* @__PURE__ */ s(
312
+ "div",
313
+ {
314
+ className: e,
315
+ style: {
316
+ width: "100%",
317
+ height: n,
318
+ background: "var(--ginger-muted-color, #e5e7eb)",
319
+ borderRadius: 999,
320
+ overflow: "hidden",
321
+ ...r
322
+ },
323
+ "aria-hidden": !0,
324
+ children: /* @__PURE__ */ s("div", { style: { width: i, height: "100%", background: "var(--ginger-primary-color, #111827)" } })
325
+ }
326
+ );
327
+ }
328
+ Pe.displayName = "Ginger.Current.TimeRail";
329
+ function Me({ className: e, style: r, fallback: n, empty: t, children: i }) {
330
+ const { state: u } = g(), a = te(u);
331
+ return i ? /* @__PURE__ */ s("span", { className: e, style: r, children: i(a, u) }) : /* @__PURE__ */ s("span", { className: e, style: r, children: a });
332
+ }
333
+ Me.displayName = "Ginger.Current.PlaybackState";
334
+ function be({ className: e, style: r, fallback: n, empty: t, children: i }) {
335
+ const { state: u } = g(), a = u.errorMessage ?? "";
336
+ if (!a) {
337
+ const l = t ?? n ?? null;
338
+ return l ? /* @__PURE__ */ s("span", { className: e, style: r, children: l }) : null;
339
+ }
340
+ return i ? /* @__PURE__ */ s("span", { className: e, style: r, children: i(a, u) }) : /* @__PURE__ */ s("span", { className: e, style: r, children: a });
341
+ }
342
+ be.displayName = "Ginger.Current.ErrorMessage";
343
+ function ke({ playLabel: e = "Play", pauseLabel: r = "Pause", type: n = "button", ...t }) {
344
+ const { state: i, togglePlayPause: u } = g();
345
+ return /* @__PURE__ */ s("button", { type: n, "aria-label": i.isPaused ? "Play" : "Pause", onClick: u, ...t, children: i.isPaused ? e : r });
346
+ }
347
+ ke.displayName = "Ginger.Control.PlayPause";
348
+ const ee = {
349
+ off: "Repeat off",
350
+ all: "Repeat all",
351
+ one: "Repeat one"
352
+ };
353
+ function xe({ type: e = "button", ...r }) {
354
+ const { state: n, cycleRepeat: t } = g();
355
+ return /* @__PURE__ */ s("button", { type: e, "aria-label": ee[n.repeatMode], onClick: t, ...r, children: ee[n.repeatMode] });
356
+ }
357
+ xe.displayName = "Ginger.Control.Repeat";
358
+ function Ae({ type: e = "button", children: r = "Next", ...n }) {
359
+ const { next: t } = g();
360
+ return /* @__PURE__ */ s("button", { type: e, "aria-label": "Next track", onClick: t, ...n, children: r });
361
+ }
362
+ Ae.displayName = "Ginger.Control.Next";
363
+ function Te({ type: e = "button", children: r = "Previous", ...n }) {
364
+ const { prev: t } = g();
365
+ return /* @__PURE__ */ s("button", { type: e, "aria-label": "Previous track", onClick: t, ...n, children: r });
366
+ }
367
+ Te.displayName = "Ginger.Control.Previous";
368
+ function Ie({ type: e = "button", children: r = "Shuffle", ...n }) {
369
+ const { state: t, toggleShuffle: i } = g();
370
+ return /* @__PURE__ */ s("button", { type: e, "aria-pressed": t.isShuffled, "aria-label": "Shuffle", onClick: i, ...n, children: r });
371
+ }
372
+ Ie.displayName = "Ginger.Control.Shuffle";
373
+ function Ee({ inputStyle: e, style: r, ...n }) {
374
+ const { state: t, seek: i } = g(), u = Number.isFinite(t.duration) && t.duration > 0 ? t.duration : 0, a = u > 0 ? t.currentTime : 0;
375
+ return /* @__PURE__ */ s(
376
+ "input",
377
+ {
378
+ type: "range",
379
+ min: 0,
380
+ max: u > 0 ? u : 1,
381
+ step: "any",
382
+ value: Number.isFinite(a) ? a : 0,
383
+ "aria-label": "Seek",
384
+ onChange: (l) => i(Number(l.currentTarget.value)),
385
+ style: { width: "100%", ...r, ...e },
386
+ ...n
387
+ }
388
+ );
389
+ }
390
+ Ee.displayName = "Ginger.Control.SeekBar";
391
+ function Se({
392
+ rowStyle: e,
393
+ renderTrack: r,
394
+ playOnSelect: n = !0,
395
+ style: t,
396
+ ...i
397
+ }) {
398
+ const { state: u, playTrackAt: a, selectTrackAt: l } = g();
399
+ return /* @__PURE__ */ s(
400
+ "ul",
401
+ {
402
+ style: {
403
+ listStyle: "none",
404
+ margin: 0,
405
+ padding: 0,
406
+ fontFamily: "var(--ginger-font-family, system-ui, sans-serif)",
407
+ fontSize: "var(--ginger-font-size, 14px)",
408
+ color: "var(--ginger-primary-color, #111827)",
409
+ ...t
410
+ },
411
+ ...i,
412
+ children: u.tracks.map((c, d) => {
413
+ const o = d === u.currentIndex;
414
+ return /* @__PURE__ */ s("li", { children: /* @__PURE__ */ s(
415
+ "button",
416
+ {
417
+ type: "button",
418
+ onClick: () => {
419
+ n ? a(d) : l(d);
420
+ },
421
+ style: {
422
+ width: "100%",
423
+ textAlign: "left",
424
+ border: "none",
425
+ background: o ? "rgba(17, 24, 39, 0.06)" : "transparent",
426
+ color: "inherit",
427
+ font: "inherit",
428
+ cursor: "pointer",
429
+ padding: "var(--ginger-playlist-row-padding, 6px 8px)",
430
+ ...e
431
+ },
432
+ children: r ? r(c, d, o) : /* @__PURE__ */ De("span", { children: [
433
+ c.title,
434
+ c.artist ? ` — ${c.artist}` : ""
435
+ ] })
436
+ }
437
+ ) }, `${c.fileUrl}-${d}`);
438
+ })
439
+ }
440
+ );
441
+ }
442
+ Se.displayName = "Ginger.Playlist";
443
+ const rr = T("Ginger.Queue.Title", (e) => {
444
+ var r;
445
+ return (r = e.playlistMeta) == null ? void 0 : r.title;
446
+ }), nr = T("Ginger.Queue.Subtitle", (e) => {
447
+ var r;
448
+ return (r = e.playlistMeta) == null ? void 0 : r.subtitle;
449
+ }), tr = T("Ginger.Queue.Description", (e) => {
450
+ var r;
451
+ return (r = e.playlistMeta) == null ? void 0 : r.description;
452
+ }), ir = T("Ginger.Queue.Copyright", (e) => {
453
+ var r;
454
+ return (r = e.playlistMeta) == null ? void 0 : r.copyright;
455
+ });
456
+ function ve({ className: e, style: r, fallback: n, empty: t, imgStyle: i }) {
457
+ var c, d;
458
+ const { state: u } = g(), a = (c = u.playlistMeta) == null ? void 0 : c.artworkUrl;
459
+ if (!a) {
460
+ const o = t ?? n ?? null;
461
+ return o ? /* @__PURE__ */ s("span", { className: e, style: r, children: o }) : null;
462
+ }
463
+ const l = ((d = u.playlistMeta) == null ? void 0 : d.title) ?? "Playlist artwork";
464
+ return /* @__PURE__ */ s(
465
+ "span",
466
+ {
467
+ className: e,
468
+ style: {
469
+ display: "inline-block",
470
+ background: "var(--ginger-artwork-bg, #f3f4f6)",
471
+ borderRadius: "var(--ginger-artwork-radius, 6px)",
472
+ overflow: "hidden",
473
+ ...r
474
+ },
475
+ children: /* @__PURE__ */ s(
476
+ "img",
477
+ {
478
+ src: a,
479
+ alt: l,
480
+ style: {
481
+ display: "block",
482
+ width: "100%",
483
+ height: "100%",
484
+ objectFit: "cover",
485
+ ...i
486
+ }
487
+ }
488
+ )
489
+ }
490
+ );
491
+ }
492
+ ve.displayName = "Ginger.Queue.Artwork";
493
+ const v = {
494
+ currentTime: 0,
495
+ duration: 0,
496
+ bufferedFraction: 0,
497
+ isBuffering: !1,
498
+ errorMessage: null
499
+ };
500
+ function Re(e) {
501
+ const r = [...e.tracks];
502
+ let n = E(e.currentIndex ?? 0, r.length), t = null, i = r;
503
+ return e.isShuffled && r.length > 1 && (t = [...r], i = ne(r, n), n = 0), {
504
+ tracks: i,
505
+ currentIndex: n,
506
+ isPaused: e.isPaused ?? !0,
507
+ isShuffled: !!(e.isShuffled && i.length > 1),
508
+ repeatMode: e.repeatMode ?? "off",
509
+ originalTracks: t,
510
+ playlistMeta: e.playlistMeta ?? null,
511
+ ...v
512
+ };
513
+ }
514
+ function ur(e, r) {
515
+ switch (r.type) {
516
+ case "INIT": {
517
+ const { tracks: n, currentIndex: t, playlistMeta: i, isPaused: u, isShuffled: a, repeatMode: l } = r.payload;
518
+ return Re({
519
+ tracks: n,
520
+ currentIndex: t,
521
+ playlistMeta: i ?? null,
522
+ isPaused: u ?? !0,
523
+ isShuffled: a ?? !1,
524
+ repeatMode: l ?? "off"
525
+ });
526
+ }
527
+ case "SET_QUEUE": {
528
+ const { tracks: n, currentIndex: t } = r.payload, i = [...n], u = E(t ?? e.currentIndex, i.length);
529
+ return {
530
+ ...e,
531
+ tracks: i,
532
+ currentIndex: u,
533
+ ...v
534
+ };
535
+ }
536
+ case "SET_INDEX": {
537
+ const n = E(r.payload.index, e.tracks.length), t = r.payload.autoPlay, i = t === !0 ? !1 : t === !1 ? !0 : e.isPaused;
538
+ return {
539
+ ...e,
540
+ currentIndex: n,
541
+ ...v,
542
+ isPaused: i
543
+ };
544
+ }
545
+ case "PLAY":
546
+ return { ...e, isPaused: !1 };
547
+ case "PAUSE":
548
+ return { ...e, isPaused: !0 };
549
+ case "TOGGLE_PAUSE":
550
+ return { ...e, isPaused: !e.isPaused };
551
+ case "SET_REPEAT":
552
+ return { ...e, repeatMode: r.payload };
553
+ case "CYCLE_REPEAT":
554
+ return { ...e, repeatMode: Ye(e.repeatMode) };
555
+ case "TOGGLE_SHUFFLE": {
556
+ if (e.tracks.length <= 1) return { ...e, isShuffled: !1, originalTracks: null };
557
+ if (!e.isShuffled) {
558
+ const a = [...e.tracks], l = ne(a, e.currentIndex);
559
+ return {
560
+ ...e,
561
+ isShuffled: !0,
562
+ originalTracks: a,
563
+ tracks: l,
564
+ currentIndex: 0
565
+ };
566
+ }
567
+ const n = e.originalTracks ? [...e.originalTracks] : [...e.tracks], t = e.tracks[e.currentIndex], i = (t == null ? void 0 : t.fileUrl) ?? "", u = Le(n, i);
568
+ return {
569
+ ...e,
570
+ isShuffled: !1,
571
+ originalTracks: null,
572
+ tracks: n,
573
+ currentIndex: E(u, n.length)
574
+ };
575
+ }
576
+ case "NEXT": {
577
+ const n = Be(e), t = n === e.currentIndex;
578
+ return {
579
+ ...e,
580
+ currentIndex: n,
581
+ ...t ? {} : v,
582
+ isPaused: t ? e.isPaused : !1
583
+ };
584
+ }
585
+ case "PREV": {
586
+ const n = $e(e), t = n === e.currentIndex;
587
+ return {
588
+ ...e,
589
+ currentIndex: n,
590
+ ...t ? {} : v,
591
+ isPaused: t ? e.isPaused : !1
592
+ };
593
+ }
594
+ case "MEDIA_TIME_UPDATE":
595
+ return {
596
+ ...e,
597
+ currentTime: r.payload.currentTime,
598
+ duration: Number.isFinite(r.payload.duration) ? r.payload.duration : e.duration,
599
+ bufferedFraction: r.payload.bufferedFraction,
600
+ isBuffering: !1
601
+ };
602
+ case "MEDIA_LOADED_METADATA":
603
+ return {
604
+ ...e,
605
+ duration: Number.isFinite(r.payload.duration) ? r.payload.duration : e.duration,
606
+ bufferedFraction: r.payload.bufferedFraction,
607
+ errorMessage: null
608
+ };
609
+ case "SET_PLAYLIST_META":
610
+ return { ...e, playlistMeta: r.payload };
611
+ case "MEDIA_ERROR":
612
+ return {
613
+ ...e,
614
+ errorMessage: r.payload.message,
615
+ isPaused: !0,
616
+ isBuffering: !1
617
+ };
618
+ case "MEDIA_WAITING":
619
+ return { ...e, isBuffering: !0 };
620
+ case "MEDIA_CANPLAY":
621
+ return { ...e, isBuffering: !1, errorMessage: null };
622
+ case "MEDIA_PLAY":
623
+ return { ...e, isPaused: !1, isBuffering: !1 };
624
+ case "MEDIA_PAUSE":
625
+ return { ...e, isPaused: !0 };
626
+ case "RESET_MEDIA_TIMES":
627
+ return { ...e, currentTime: 0, duration: 0, bufferedFraction: 0 };
628
+ default:
629
+ return e;
630
+ }
631
+ }
632
+ const ar = {
633
+ "--ginger-primary-color": "#111827",
634
+ "--ginger-muted-color": "#6b7280",
635
+ "--ginger-font-size": "14px",
636
+ "--ginger-font-family": "system-ui, sans-serif",
637
+ "--ginger-playlist-row-padding": "6px 8px",
638
+ "--ginger-artwork-radius": "6px",
639
+ "--ginger-artwork-bg": "#f3f4f6"
640
+ };
641
+ function sr({
642
+ children: e,
643
+ initialTracks: r = [],
644
+ initialIndex: n = 0,
645
+ initialPlaylistMeta: t = null,
646
+ initialShuffle: i = !1,
647
+ initialRepeatMode: u = "off",
648
+ initialPaused: a = !0,
649
+ className: l,
650
+ style: c,
651
+ onTrackChange: d,
652
+ onPlay: o,
653
+ onPause: p,
654
+ onQueueEnd: b,
655
+ onError: m
656
+ }) {
657
+ var K;
658
+ const k = J(null), [y, P] = Ue(
659
+ ur,
660
+ void 0,
661
+ () => Re({
662
+ tracks: r,
663
+ currentIndex: n,
664
+ playlistMeta: t,
665
+ isPaused: a,
666
+ isShuffled: i,
667
+ repeatMode: u
668
+ })
669
+ ), U = y.tracks[y.currentIndex] ?? null;
670
+ S(() => {
671
+ d == null || d(U, y.currentIndex);
672
+ }, [U, y.currentIndex, d]), S(() => {
673
+ y.errorMessage && (m == null || m(y.errorMessage));
674
+ }, [y.errorMessage, m]);
675
+ const C = J(void 0);
676
+ S(() => {
677
+ if (C.current === void 0) {
678
+ C.current = y.isPaused;
679
+ return;
680
+ }
681
+ C.current !== y.isPaused && (y.isPaused ? p == null || p() : o == null || o()), C.current = y.isPaused;
682
+ }, [y.isPaused, p, o]);
683
+ const G = M(() => {
684
+ var f;
685
+ P({ type: "PLAY" }), (f = k.current) == null || f.play().catch((h) => {
686
+ P({ type: "PAUSE" });
687
+ const x = h instanceof Error ? h.message : "Playback failed";
688
+ m == null || m(x);
689
+ });
690
+ }, [m]), _ = M(() => {
691
+ var f;
692
+ P({ type: "PAUSE" }), (f = k.current) == null || f.pause();
693
+ }, []), F = M(() => {
694
+ y.isPaused ? G() : _();
695
+ }, [_, G, y.isPaused]), L = M((f) => {
696
+ const h = k.current;
697
+ h && Number.isFinite(f) && (h.currentTime = Math.max(0, f));
698
+ }, []), Q = M((f) => {
699
+ const h = k.current;
700
+ h && (h.volume = Math.min(1, Math.max(0, f)));
701
+ }, []), B = M((f) => {
702
+ const h = k.current;
703
+ h && (h.muted = f);
704
+ }, []), $ = M(() => {
705
+ P({ type: "NEXT" });
706
+ }, []), Y = M(() => {
707
+ P({ type: "PREV" });
708
+ }, []), O = M((f) => {
709
+ P({ type: "SET_REPEAT", payload: f });
710
+ }, []), j = M(() => {
711
+ P({ type: "CYCLE_REPEAT" });
712
+ }, []), V = M(() => {
713
+ P({ type: "TOGGLE_SHUFFLE" });
714
+ }, []), X = M((f, h) => {
715
+ P({ type: "SET_QUEUE", payload: { tracks: f, currentIndex: h } });
716
+ }, []), W = M((f) => {
717
+ P({ type: "SET_INDEX", payload: { index: f, autoPlay: !0 } }), queueMicrotask(() => {
718
+ var h;
719
+ (h = k.current) == null || h.play().catch(() => {
720
+ });
721
+ });
722
+ }, []), z = M((f) => {
723
+ P({ type: "SET_INDEX", payload: { index: f, autoPlay: !1 } });
724
+ }, []), q = M((f) => {
725
+ P({ type: "SET_PLAYLIST_META", payload: f });
726
+ }, []), Ce = (K = y.tracks[y.currentIndex]) == null ? void 0 : K.fileUrl;
727
+ S(() => {
728
+ const f = k.current;
729
+ f && (y.isPaused ? f.pause() : f.play().catch((h) => {
730
+ P({ type: "PAUSE" });
731
+ const x = h instanceof Error ? h.message : "Playback failed";
732
+ m == null || m(x);
733
+ }));
734
+ }, [y.isPaused, Ce, m]);
735
+ const H = M(() => {
736
+ const f = Qe(y);
737
+ if (f.kind === "replay_same") {
738
+ const x = k.current;
739
+ x && (x.currentTime = 0, x.play().catch(() => {
740
+ })), P({ type: "PLAY" });
741
+ return;
742
+ }
743
+ if (f.kind === "stop") {
744
+ P({ type: "PAUSE" }), b == null || b();
745
+ return;
746
+ }
747
+ const h = f.nextIndex;
748
+ P({ type: "SET_INDEX", payload: { index: h, autoPlay: !0 } }), queueMicrotask(() => {
749
+ var x;
750
+ (x = k.current) == null || x.play().catch(() => {
751
+ });
752
+ });
753
+ }, [b, y]), Ge = D(
754
+ () => ({
755
+ state: y,
756
+ dispatch: P,
757
+ audioRef: k,
758
+ notifyEnded: H,
759
+ play: G,
760
+ pause: _,
761
+ togglePlayPause: F,
762
+ seek: L,
763
+ setVolume: Q,
764
+ setMuted: B,
765
+ next: $,
766
+ prev: Y,
767
+ setRepeatMode: O,
768
+ cycleRepeat: j,
769
+ toggleShuffle: V,
770
+ setQueue: X,
771
+ playTrackAt: W,
772
+ selectTrackAt: z,
773
+ setPlaylistMeta: q
774
+ }),
775
+ [
776
+ j,
777
+ P,
778
+ $,
779
+ H,
780
+ _,
781
+ G,
782
+ W,
783
+ z,
784
+ Y,
785
+ L,
786
+ B,
787
+ X,
788
+ O,
789
+ q,
790
+ Q,
791
+ y,
792
+ F,
793
+ V
794
+ ]
795
+ ), _e = D(() => ({ ...ar, ...c }), [c]);
796
+ return /* @__PURE__ */ s(re.Provider, { value: Ge, children: /* @__PURE__ */ s("div", { className: l, style: _e, children: e }) });
797
+ }
798
+ const cr = {
799
+ Provider: sr,
800
+ Player: Fe,
801
+ Current: {
802
+ Title: Ve,
803
+ Artist: Xe,
804
+ Album: We,
805
+ Description: ze,
806
+ Copyright: qe,
807
+ Genre: He,
808
+ Label: Ke,
809
+ Isrc: Je,
810
+ TrackNumber: Ze,
811
+ Year: se,
812
+ Lyrics: le,
813
+ FileUrl: oe,
814
+ Artwork: ce,
815
+ QueueIndex: de,
816
+ QueueLength: fe,
817
+ QueuePosition: pe,
818
+ Elapsed: ge,
819
+ Duration: ye,
820
+ Remaining: he,
821
+ Progress: me,
822
+ TimeRail: Pe,
823
+ PlaybackState: Me,
824
+ ErrorMessage: be
825
+ },
826
+ Queue: {
827
+ Title: rr,
828
+ Subtitle: nr,
829
+ Description: tr,
830
+ Copyright: ir,
831
+ Artwork: ve
832
+ },
833
+ Control: {
834
+ PlayPause: ke,
835
+ Repeat: xe,
836
+ Next: Ae,
837
+ Previous: Te,
838
+ Shuffle: Ie,
839
+ SeekBar: Ee
840
+ },
841
+ Playlist: Se
842
+ };
843
+ function dr() {
844
+ const e = g(), { state: r } = e;
845
+ return D(
846
+ () => ({
847
+ state: r,
848
+ currentTrack: A(r),
849
+ playbackUi: te(r),
850
+ duration: R(r),
851
+ remaining: ie(r),
852
+ progress: N(r),
853
+ artworkUrl: ue(r),
854
+ albumLine: ae(r),
855
+ play: e.play,
856
+ pause: e.pause,
857
+ togglePlayPause: e.togglePlayPause,
858
+ seek: e.seek,
859
+ setVolume: e.setVolume,
860
+ setMuted: e.setMuted,
861
+ next: e.next,
862
+ prev: e.prev,
863
+ setRepeatMode: e.setRepeatMode,
864
+ cycleRepeat: e.cycleRepeat,
865
+ toggleShuffle: e.toggleShuffle,
866
+ setQueue: e.setQueue,
867
+ playTrackAt: e.playTrackAt,
868
+ selectTrackAt: e.selectTrackAt,
869
+ setPlaylistMeta: e.setPlaylistMeta,
870
+ dispatch: e.dispatch
871
+ }),
872
+ [
873
+ e.cycleRepeat,
874
+ e.dispatch,
875
+ e.next,
876
+ e.pause,
877
+ e.play,
878
+ e.playTrackAt,
879
+ e.selectTrackAt,
880
+ e.prev,
881
+ e.seek,
882
+ e.setMuted,
883
+ e.setPlaylistMeta,
884
+ e.setQueue,
885
+ e.setRepeatMode,
886
+ e.setVolume,
887
+ e.togglePlayPause,
888
+ e.toggleShuffle,
889
+ r
890
+ ]
891
+ );
892
+ }
893
+ export {
894
+ cr as Ginger,
895
+ dr as useGinger
896
+ };
897
+ //# sourceMappingURL=index.js.map