@lucaismyname/ginger 0.0.30 → 0.0.32
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/README.md +140 -8
- package/dist/analyzer/liveAudioGraph.d.ts +14 -1
- package/dist/analyzer/liveAudioGraph.d.ts.map +1 -1
- package/dist/analyzer/useGingerLiveAnalyzer.d.ts +6 -0
- package/dist/analyzer/useGingerLiveAnalyzer.d.ts.map +1 -1
- package/dist/client.cjs +1 -1
- package/dist/client.js +40 -32
- package/dist/client.js.map +1 -1
- package/dist/context/GingerProvider.d.ts +1 -1
- package/dist/context/GingerProvider.d.ts.map +1 -1
- package/dist/core/playbackReducer.d.ts.map +1 -1
- package/dist/equalizer/index.cjs +2 -0
- package/dist/equalizer/index.cjs.map +1 -0
- package/dist/equalizer/index.d.ts +3 -0
- package/dist/equalizer/index.d.ts.map +1 -0
- package/dist/equalizer/index.js +52 -0
- package/dist/equalizer/index.js.map +1 -0
- package/dist/equalizer/useGingerEqualizer.d.ts +41 -0
- package/dist/equalizer/useGingerEqualizer.d.ts.map +1 -0
- package/dist/ginger-L2ZFgzH4.js +2223 -0
- package/dist/ginger-L2ZFgzH4.js.map +1 -0
- package/dist/ginger-NEcOSSJD.cjs +2 -0
- package/dist/ginger-NEcOSSJD.cjs.map +1 -0
- package/dist/hooks/useGingerChapterProgress.d.ts +14 -0
- package/dist/hooks/useGingerChapterProgress.d.ts.map +1 -0
- package/dist/hooks/useGingerKeyboardShortcuts.d.ts +6 -0
- package/dist/hooks/useGingerKeyboardShortcuts.d.ts.map +1 -1
- package/dist/hooks/useGingerPlaybackHistory.d.ts +26 -0
- package/dist/hooks/useGingerPlaybackHistory.d.ts.map +1 -0
- package/dist/hooks/useGingerSleepTimer.d.ts.map +1 -1
- package/dist/hooks/useGingerVolumeFade.d.ts +22 -0
- package/dist/hooks/useGingerVolumeFade.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +18 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -32
- package/dist/index.js.map +1 -1
- package/dist/liveAudioGraph-0cpHD_Ic.cjs +2 -0
- package/dist/liveAudioGraph-0cpHD_Ic.cjs.map +1 -0
- package/dist/liveAudioGraph-DvPaxBCP.js +105 -0
- package/dist/liveAudioGraph-DvPaxBCP.js.map +1 -0
- package/dist/remote/index.cjs +2 -0
- package/dist/remote/index.cjs.map +1 -0
- package/dist/remote/index.d.ts +5 -0
- package/dist/remote/index.d.ts.map +1 -0
- package/dist/remote/index.js +149 -0
- package/dist/remote/index.js.map +1 -0
- package/dist/remote/remoteProtocol.d.ts +28 -0
- package/dist/remote/remoteProtocol.d.ts.map +1 -0
- package/dist/remote/useGingerRemote.d.ts +35 -0
- package/dist/remote/useGingerRemote.d.ts.map +1 -0
- package/dist/selectors-BalBCc7X.js +127 -0
- package/dist/selectors-BalBCc7X.js.map +1 -0
- package/dist/selectors-YXnP8Y8g.cjs +2 -0
- package/dist/selectors-YXnP8Y8g.cjs.map +1 -0
- package/dist/spatial/index.cjs +2 -0
- package/dist/spatial/index.cjs.map +1 -0
- package/dist/spatial/index.d.ts +3 -0
- package/dist/spatial/index.d.ts.map +1 -0
- package/dist/spatial/index.js +59 -0
- package/dist/spatial/index.js.map +1 -0
- package/dist/spatial/useGingerSpatialAudio.d.ts +34 -0
- package/dist/spatial/useGingerSpatialAudio.d.ts.map +1 -0
- package/dist/spatial/useGingerSpatialAudio.test.d.ts +2 -0
- package/dist/spatial/useGingerSpatialAudio.test.d.ts.map +1 -0
- package/dist/store.d.ts +46 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/testing/index.cjs +1 -1
- package/dist/testing/index.js +1 -1
- package/dist/testing/mockWebAudio.d.ts +29 -1
- package/dist/testing/mockWebAudio.d.ts.map +1 -1
- package/dist/transcript/index.cjs +8 -0
- package/dist/transcript/index.cjs.map +1 -0
- package/dist/transcript/index.d.ts +5 -0
- package/dist/transcript/index.d.ts.map +1 -0
- package/dist/transcript/index.js +99 -0
- package/dist/transcript/index.js.map +1 -0
- package/dist/transcript/parseTranscript.d.ts +27 -0
- package/dist/transcript/parseTranscript.d.ts.map +1 -0
- package/dist/transcript/parseTranscript.test.d.ts +2 -0
- package/dist/transcript/parseTranscript.test.d.ts.map +1 -0
- package/dist/transcript/useGingerTranscriptSync.d.ts +23 -0
- package/dist/transcript/useGingerTranscriptSync.d.ts.map +1 -0
- package/dist/types.d.ts +30 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/useGinger-BXgia32v.cjs +2 -0
- package/dist/useGinger-BXgia32v.cjs.map +1 -0
- package/dist/useGinger-hpp2pAGY.js +48 -0
- package/dist/useGinger-hpp2pAGY.js.map +1 -0
- package/dist/useGingerChapterProgress-BdaalJvX.cjs +2 -0
- package/dist/useGingerChapterProgress-BdaalJvX.cjs.map +1 -0
- package/dist/useGingerChapterProgress-CZdv-HiI.js +322 -0
- package/dist/useGingerChapterProgress-CZdv-HiI.js.map +1 -0
- package/package.json +23 -3
- package/dist/ginger-DYlsaFGA.js +0 -2283
- package/dist/ginger-DYlsaFGA.js.map +0 -1
- package/dist/ginger-YDZhJqet.cjs +0 -2
- package/dist/ginger-YDZhJqet.cjs.map +0 -1
- package/dist/useNextTrackPrefetch-BZdly__j.js +0 -265
- package/dist/useNextTrackPrefetch-BZdly__j.js.map +0 -1
- package/dist/useNextTrackPrefetch-pBFiWDyx.cjs +0 -2
- package/dist/useNextTrackPrefetch-pBFiWDyx.cjs.map +0 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
function l(n, e) {
|
|
2
|
+
return e <= 0 ? 0 : Math.max(0, Math.min(e - 1, n));
|
|
3
|
+
}
|
|
4
|
+
function g(n, e) {
|
|
5
|
+
if (n.length <= 1) return [...n];
|
|
6
|
+
const r = n[e];
|
|
7
|
+
if (!r) return [...n];
|
|
8
|
+
const t = n.filter((i, u) => u !== e);
|
|
9
|
+
for (let i = t.length - 1; i > 0; i--) {
|
|
10
|
+
const u = Math.floor(Math.random() * (i + 1));
|
|
11
|
+
[t[i], t[u]] = [t[u], t[i]];
|
|
12
|
+
}
|
|
13
|
+
return [r, ...t];
|
|
14
|
+
}
|
|
15
|
+
function c(n) {
|
|
16
|
+
return n ? n.id != null && n.id !== "" ? `id:${n.id}` : `file:${n.fileUrl}` : "";
|
|
17
|
+
}
|
|
18
|
+
function x(n, e) {
|
|
19
|
+
var f, s;
|
|
20
|
+
if (!e) return 0;
|
|
21
|
+
const r = n.findIndex((o) => o === e);
|
|
22
|
+
if (r !== -1) return r;
|
|
23
|
+
const t = c(e);
|
|
24
|
+
if (!t) return 0;
|
|
25
|
+
const i = [];
|
|
26
|
+
for (let o = 0; o < n.length; o += 1)
|
|
27
|
+
c(n[o]) === t && i.push(o);
|
|
28
|
+
if (i.length === 0) return 0;
|
|
29
|
+
if (i.length === 1) return i[0];
|
|
30
|
+
const u = typeof globalThis < "u" && "process" in globalThis ? (s = (f = globalThis.process) == null ? void 0 : f.env) == null ? void 0 : s.NODE_ENV : void 0;
|
|
31
|
+
return u != null && u !== "production" && console.warn(
|
|
32
|
+
"[@lucaismyname/ginger] Ambiguous track identity: multiple queue rows share the same fileUrl without a unique `id`. Resolving to the first match."
|
|
33
|
+
), i[0];
|
|
34
|
+
}
|
|
35
|
+
function h(n, e, r) {
|
|
36
|
+
const t = [...n], i = Math.max(0, Math.min(t.length, r ?? t.length));
|
|
37
|
+
return t.splice(i, 0, e), t;
|
|
38
|
+
}
|
|
39
|
+
function M(n, e) {
|
|
40
|
+
if (e < 0 || e >= n.length) return [...n];
|
|
41
|
+
const r = [...n];
|
|
42
|
+
return r.splice(e, 1), r;
|
|
43
|
+
}
|
|
44
|
+
function b(n, e, r) {
|
|
45
|
+
if (e === r || e < 0 || e >= n.length || r < 0 || r >= n.length)
|
|
46
|
+
return [...n];
|
|
47
|
+
const t = [...n], [i] = t.splice(e, 1);
|
|
48
|
+
return i ? (t.splice(r, 0, i), t) : [...n];
|
|
49
|
+
}
|
|
50
|
+
function y(n, e, r) {
|
|
51
|
+
return h(n, r, Math.max(0, Math.min(n.length, e + 1)));
|
|
52
|
+
}
|
|
53
|
+
function v(n) {
|
|
54
|
+
const { tracks: e, currentIndex: r, repeatMode: t, playbackMode: i } = n, u = e.length;
|
|
55
|
+
return u === 0 ? { kind: "stop", nextIndex: 0 } : t === "one" ? { kind: "replay_same" } : i === "single" ? { kind: "stop", nextIndex: l(r, u) } : r < u - 1 ? { kind: "advance", nextIndex: r + 1 } : t === "all" ? { kind: "wrap", nextIndex: 0 } : { kind: "stop", nextIndex: l(r, u) };
|
|
56
|
+
}
|
|
57
|
+
function T(n) {
|
|
58
|
+
const { tracks: e, currentIndex: r, repeatMode: t, playbackMode: i } = n, u = e.length;
|
|
59
|
+
return u === 0 ? 0 : i === "single" ? l(r, u) : r < u - 1 ? r + 1 : t === "all" ? 0 : l(r, u);
|
|
60
|
+
}
|
|
61
|
+
function I(n) {
|
|
62
|
+
const { tracks: e, currentIndex: r, repeatMode: t, playbackMode: i } = n, u = e.length;
|
|
63
|
+
return u === 0 ? 0 : i === "single" ? l(r, u) : r > 0 ? r - 1 : t === "all" ? u - 1 : 0;
|
|
64
|
+
}
|
|
65
|
+
function w(n) {
|
|
66
|
+
return n === "off" ? "all" : n === "all" ? "one" : "off";
|
|
67
|
+
}
|
|
68
|
+
function m(n, e) {
|
|
69
|
+
return (n == null ? void 0 : n.artworkUrl) ?? e ?? void 0;
|
|
70
|
+
}
|
|
71
|
+
function p(n, e) {
|
|
72
|
+
return (n == null ? void 0 : n.album) ?? e ?? void 0;
|
|
73
|
+
}
|
|
74
|
+
function a(n) {
|
|
75
|
+
return n.tracks[n.currentIndex] ?? null;
|
|
76
|
+
}
|
|
77
|
+
function A(n) {
|
|
78
|
+
return n.errorMessage ? "error" : n.tracks.length === 0 ? "idle" : n.isBuffering ? "loading" : n.isPaused ? Number.isFinite(n.duration) && n.duration > 0 && n.currentTime >= n.duration - 0.05 ? "ended" : "paused" : "playing";
|
|
79
|
+
}
|
|
80
|
+
function d(n) {
|
|
81
|
+
var t;
|
|
82
|
+
const e = n.duration;
|
|
83
|
+
if (Number.isFinite(e) && e > 0) return e;
|
|
84
|
+
const r = (t = n.tracks[n.currentIndex]) == null ? void 0 : t.durationSeconds;
|
|
85
|
+
return typeof r == "number" && Number.isFinite(r) && r > 0 ? r : 0;
|
|
86
|
+
}
|
|
87
|
+
function N(n) {
|
|
88
|
+
const r = d(n) - n.currentTime;
|
|
89
|
+
return Number.isFinite(r) ? Math.max(0, r) : 0;
|
|
90
|
+
}
|
|
91
|
+
function k(n) {
|
|
92
|
+
const e = d(n);
|
|
93
|
+
return e > 0 ? Math.min(1, Math.max(0, n.currentTime / e)) : 0;
|
|
94
|
+
}
|
|
95
|
+
function U(n) {
|
|
96
|
+
var r;
|
|
97
|
+
const e = a(n);
|
|
98
|
+
return m(e, (r = n.playlistMeta) == null ? void 0 : r.artworkUrl);
|
|
99
|
+
}
|
|
100
|
+
function F(n) {
|
|
101
|
+
var r;
|
|
102
|
+
const e = a(n);
|
|
103
|
+
return p(e, (r = n.playlistMeta) == null ? void 0 : r.subtitle);
|
|
104
|
+
}
|
|
105
|
+
export {
|
|
106
|
+
U as a,
|
|
107
|
+
d as b,
|
|
108
|
+
T as c,
|
|
109
|
+
A as d,
|
|
110
|
+
N as e,
|
|
111
|
+
I as f,
|
|
112
|
+
a as g,
|
|
113
|
+
x as h,
|
|
114
|
+
l as i,
|
|
115
|
+
w as j,
|
|
116
|
+
y as k,
|
|
117
|
+
M as l,
|
|
118
|
+
b as m,
|
|
119
|
+
h as n,
|
|
120
|
+
m as o,
|
|
121
|
+
k as p,
|
|
122
|
+
v as q,
|
|
123
|
+
F as r,
|
|
124
|
+
g as s,
|
|
125
|
+
c as t
|
|
126
|
+
};
|
|
127
|
+
//# sourceMappingURL=selectors-BalBCc7X.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors-BalBCc7X.js","sources":["../src/core/queue.ts","../src/core/transitions.ts","../src/internal/selectors.ts"],"sourcesContent":["import type { Track } from \"../types\";\n\nexport function clampIndex(index: number, length: number): number {\n if (length <= 0) return 0;\n return Math.max(0, Math.min(length - 1, index));\n}\n\nexport function shuffleWithAnchor(tracks: Track[], anchorIndex: number): Track[] {\n if (tracks.length <= 1) return [...tracks];\n const anchor = tracks[anchorIndex];\n if (!anchor) return [...tracks];\n const rest = tracks.filter((_, i) => i !== anchorIndex);\n for (let i = rest.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [rest[i], rest[j]] = [rest[j]!, rest[i]!];\n }\n return [anchor, ...rest];\n}\n\nexport function trackIdentity(track: Track | null | undefined): string {\n if (!track) return \"\";\n return track.id != null && track.id !== \"\" ? `id:${track.id}` : `file:${track.fileUrl}`;\n}\n\nexport function findIndexByTrackIdentity(\n tracks: Track[],\n target: Track | null | undefined,\n): number {\n if (!target) return 0;\n const byRef = tracks.findIndex((t) => t === target);\n if (byRef !== -1) return byRef;\n\n const identity = trackIdentity(target);\n if (!identity) return 0;\n\n const matches: number[] = [];\n for (let i = 0; i < tracks.length; i += 1) {\n if (trackIdentity(tracks[i]) === identity) matches.push(i);\n }\n if (matches.length === 0) return 0;\n if (matches.length === 1) return matches[0]!;\n\n const nodeEnv =\n typeof globalThis !== \"undefined\" && \"process\" in globalThis\n ? (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV\n : undefined;\n if (nodeEnv != null && nodeEnv !== \"production\") {\n console.warn(\n \"[@lucaismyname/ginger] Ambiguous track identity: multiple queue rows share the same fileUrl without a unique `id`. Resolving to the first match.\",\n );\n }\n return matches[0]!;\n}\n\nexport function insertTrackAt(tracks: Track[], track: Track, index?: number): Track[] {\n const next = [...tracks];\n const at = Math.max(0, Math.min(next.length, index ?? next.length));\n next.splice(at, 0, track);\n return next;\n}\n\nexport function removeTrackAt(tracks: Track[], index: number): Track[] {\n if (index < 0 || index >= tracks.length) return [...tracks];\n const next = [...tracks];\n next.splice(index, 1);\n return next;\n}\n\nexport function moveTrack(tracks: Track[], fromIndex: number, toIndex: number): Track[] {\n if (\n fromIndex === toIndex ||\n fromIndex < 0 ||\n fromIndex >= tracks.length ||\n toIndex < 0 ||\n toIndex >= tracks.length\n ) {\n return [...tracks];\n }\n const next = [...tracks];\n const [item] = next.splice(fromIndex, 1);\n if (!item) return [...tracks];\n next.splice(toIndex, 0, item);\n return next;\n}\n\nexport function addNextTrack(tracks: Track[], currentIndex: number, track: Track): Track[] {\n return insertTrackAt(tracks, track, Math.max(0, Math.min(tracks.length, currentIndex + 1)));\n}\n","import type { GingerState, RepeatMode, Track } from \"../types\";\nimport { clampIndex } from \"./queue\";\n\n/** Fields used by next/prev/ended navigation; avoids coupling helpers to full `GingerState`. */\nexport type GingerPlaybackNavigationSlice = Pick<\n GingerState,\n \"tracks\" | \"currentIndex\" | \"repeatMode\" | \"playbackMode\"\n>;\n\nexport type EndedTransition =\n | { kind: \"replay_same\" }\n | { kind: \"advance\"; nextIndex: number }\n | { kind: \"wrap\"; nextIndex: number }\n | { kind: \"stop\"; nextIndex: number };\n\nexport function computeEndedTransition(state: GingerPlaybackNavigationSlice): EndedTransition {\n const { tracks, currentIndex, repeatMode, playbackMode } = state;\n const len = tracks.length;\n if (len === 0) return { kind: \"stop\", nextIndex: 0 };\n if (repeatMode === \"one\") return { kind: \"replay_same\" };\n if (playbackMode === \"single\") return { kind: \"stop\", nextIndex: clampIndex(currentIndex, len) };\n if (currentIndex < len - 1) return { kind: \"advance\", nextIndex: currentIndex + 1 };\n if (repeatMode === \"all\") return { kind: \"wrap\", nextIndex: 0 };\n return { kind: \"stop\", nextIndex: clampIndex(currentIndex, len) };\n}\n\nexport function computeNextIndex(state: GingerPlaybackNavigationSlice): number {\n const { tracks, currentIndex, repeatMode, playbackMode } = state;\n const len = tracks.length;\n if (len === 0) return 0;\n if (playbackMode === \"single\") return clampIndex(currentIndex, len);\n if (currentIndex < len - 1) return currentIndex + 1;\n if (repeatMode === \"all\") return 0;\n return clampIndex(currentIndex, len);\n}\n\nexport function computePrevIndex(state: GingerPlaybackNavigationSlice): number {\n const { tracks, currentIndex, repeatMode, playbackMode } = state;\n const len = tracks.length;\n if (len === 0) return 0;\n if (playbackMode === \"single\") return clampIndex(currentIndex, len);\n if (currentIndex > 0) return currentIndex - 1;\n if (repeatMode === \"all\") return len - 1;\n return 0;\n}\n\nexport function cycleRepeatMode(mode: RepeatMode): RepeatMode {\n if (mode === \"off\") return \"all\";\n if (mode === \"all\") return \"one\";\n return \"off\";\n}\n\nexport function resolveArtworkUrl(\n track: Track | null,\n playlistArtwork?: string | null,\n): string | undefined {\n return track?.artworkUrl ?? playlistArtwork ?? undefined;\n}\n\nexport function resolveAlbumLine(\n track: Track | null,\n playlistSubtitle?: string | null,\n): string | undefined {\n return track?.album ?? playlistSubtitle ?? undefined;\n}\n","import { resolveAlbumLine, resolveArtworkUrl } from \"../core/transitions\";\nimport type { GingerState, PlaybackUiState, Track } from \"../types\";\n\nexport function getCurrentTrack(state: GingerState): Track | null {\n const t = state.tracks[state.currentIndex];\n return t ?? null;\n}\n\nexport function derivePlaybackUiState(state: GingerState): PlaybackUiState {\n if (state.errorMessage) return \"error\";\n if (state.tracks.length === 0) return \"idle\";\n if (state.isBuffering) return \"loading\";\n if (!state.isPaused) return \"playing\";\n if (\n Number.isFinite(state.duration) &&\n state.duration > 0 &&\n state.currentTime >= state.duration - 0.05\n ) {\n return \"ended\";\n }\n return \"paused\";\n}\n\nexport function effectiveDuration(state: GingerState): number {\n const d = state.duration;\n if (Number.isFinite(d) && d > 0) return d;\n const hint = state.tracks[state.currentIndex]?.durationSeconds;\n if (typeof hint === \"number\" && Number.isFinite(hint) && hint > 0) return hint;\n return 0;\n}\n\nexport function effectiveRemaining(state: GingerState): number {\n const dur = effectiveDuration(state);\n const rem = dur - state.currentTime;\n return Number.isFinite(rem) ? Math.max(0, rem) : 0;\n}\n\nexport function progressFraction(state: GingerState): number {\n const dur = effectiveDuration(state);\n if (!(dur > 0)) return 0;\n return Math.min(1, Math.max(0, state.currentTime / dur));\n}\n\nexport function resolvedArtwork(state: GingerState): string | undefined {\n const track = getCurrentTrack(state);\n return resolveArtworkUrl(track, state.playlistMeta?.artworkUrl);\n}\n\nexport function resolvedAlbumLine(state: GingerState): string | undefined {\n const track = getCurrentTrack(state);\n return resolveAlbumLine(track, state.playlistMeta?.subtitle);\n}\n"],"names":["clampIndex","index","length","shuffleWithAnchor","tracks","anchorIndex","anchor","rest","_","i","j","trackIdentity","track","findIndexByTrackIdentity","target","_a","_b","byRef","t","identity","matches","nodeEnv","insertTrackAt","next","at","removeTrackAt","moveTrack","fromIndex","toIndex","item","addNextTrack","currentIndex","computeEndedTransition","state","repeatMode","playbackMode","len","computeNextIndex","computePrevIndex","cycleRepeatMode","mode","resolveArtworkUrl","playlistArtwork","resolveAlbumLine","playlistSubtitle","getCurrentTrack","derivePlaybackUiState","effectiveDuration","d","hint","effectiveRemaining","rem","progressFraction","dur","resolvedArtwork","resolvedAlbumLine"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";function l(n,e){return e<=0?0:Math.max(0,Math.min(e-1,n))}function p(n,e){if(n.length<=1)return[...n];const r=n[e];if(!r)return[...n];const t=n.filter((i,u)=>u!==e);for(let i=t.length-1;i>0;i--){const u=Math.floor(Math.random()*(i+1));[t[i],t[u]]=[t[u],t[i]]}return[r,...t]}function c(n){return n?n.id!=null&&n.id!==""?`id:${n.id}`:`file:${n.fileUrl}`:""}function g(n,e){var a,s;if(!e)return 0;const r=n.findIndex(o=>o===e);if(r!==-1)return r;const t=c(e);if(!t)return 0;const i=[];for(let o=0;o<n.length;o+=1)c(n[o])===t&&i.push(o);if(i.length===0)return 0;if(i.length===1)return i[0];const u=typeof globalThis<"u"&&"process"in globalThis?(s=(a=globalThis.process)==null?void 0:a.env)==null?void 0:s.NODE_ENV:void 0;return u!=null&&u!=="production"&&console.warn("[@lucaismyname/ginger] Ambiguous track identity: multiple queue rows share the same fileUrl without a unique `id`. Resolving to the first match."),i[0]}function h(n,e,r){const t=[...n],i=Math.max(0,Math.min(t.length,r??t.length));return t.splice(i,0,e),t}function x(n,e){if(e<0||e>=n.length)return[...n];const r=[...n];return r.splice(e,1),r}function v(n,e,r){if(e===r||e<0||e>=n.length||r<0||r>=n.length)return[...n];const t=[...n],[i]=t.splice(e,1);return i?(t.splice(r,0,i),t):[...n]}function y(n,e,r){return h(n,r,Math.max(0,Math.min(n.length,e+1)))}function M(n){const{tracks:e,currentIndex:r,repeatMode:t,playbackMode:i}=n,u=e.length;return u===0?{kind:"stop",nextIndex:0}:t==="one"?{kind:"replay_same"}:i==="single"?{kind:"stop",nextIndex:l(r,u)}:r<u-1?{kind:"advance",nextIndex:r+1}:t==="all"?{kind:"wrap",nextIndex:0}:{kind:"stop",nextIndex:l(r,u)}}function b(n){const{tracks:e,currentIndex:r,repeatMode:t,playbackMode:i}=n,u=e.length;return u===0?0:i==="single"?l(r,u):r<u-1?r+1:t==="all"?0:l(r,u)}function T(n){const{tracks:e,currentIndex:r,repeatMode:t,playbackMode:i}=n,u=e.length;return u===0?0:i==="single"?l(r,u):r>0?r-1:t==="all"?u-1:0}function I(n){return n==="off"?"all":n==="all"?"one":"off"}function m(n,e){return(n==null?void 0:n.artworkUrl)??e??void 0}function k(n,e){return(n==null?void 0:n.album)??e??void 0}function f(n){return n.tracks[n.currentIndex]??null}function A(n){return n.errorMessage?"error":n.tracks.length===0?"idle":n.isBuffering?"loading":n.isPaused?Number.isFinite(n.duration)&&n.duration>0&&n.currentTime>=n.duration-.05?"ended":"paused":"playing"}function d(n){var t;const e=n.duration;if(Number.isFinite(e)&&e>0)return e;const r=(t=n.tracks[n.currentIndex])==null?void 0:t.durationSeconds;return typeof r=="number"&&Number.isFinite(r)&&r>0?r:0}function w(n){const r=d(n)-n.currentTime;return Number.isFinite(r)?Math.max(0,r):0}function N(n){const e=d(n);return e>0?Math.min(1,Math.max(0,n.currentTime/e)):0}function U(n){var r;const e=f(n);return m(e,(r=n.playlistMeta)==null?void 0:r.artworkUrl)}function F(n){var r;const e=f(n);return k(e,(r=n.playlistMeta)==null?void 0:r.subtitle)}exports.addNextTrack=y;exports.clampIndex=l;exports.computeEndedTransition=M;exports.computeNextIndex=b;exports.computePrevIndex=T;exports.cycleRepeatMode=I;exports.derivePlaybackUiState=A;exports.effectiveDuration=d;exports.effectiveRemaining=w;exports.findIndexByTrackIdentity=g;exports.getCurrentTrack=f;exports.insertTrackAt=h;exports.moveTrack=v;exports.progressFraction=N;exports.removeTrackAt=x;exports.resolveArtworkUrl=m;exports.resolvedAlbumLine=F;exports.resolvedArtwork=U;exports.shuffleWithAnchor=p;exports.trackIdentity=c;
|
|
2
|
+
//# sourceMappingURL=selectors-YXnP8Y8g.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors-YXnP8Y8g.cjs","sources":["../src/core/queue.ts","../src/core/transitions.ts","../src/internal/selectors.ts"],"sourcesContent":["import type { Track } from \"../types\";\n\nexport function clampIndex(index: number, length: number): number {\n if (length <= 0) return 0;\n return Math.max(0, Math.min(length - 1, index));\n}\n\nexport function shuffleWithAnchor(tracks: Track[], anchorIndex: number): Track[] {\n if (tracks.length <= 1) return [...tracks];\n const anchor = tracks[anchorIndex];\n if (!anchor) return [...tracks];\n const rest = tracks.filter((_, i) => i !== anchorIndex);\n for (let i = rest.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [rest[i], rest[j]] = [rest[j]!, rest[i]!];\n }\n return [anchor, ...rest];\n}\n\nexport function trackIdentity(track: Track | null | undefined): string {\n if (!track) return \"\";\n return track.id != null && track.id !== \"\" ? `id:${track.id}` : `file:${track.fileUrl}`;\n}\n\nexport function findIndexByTrackIdentity(\n tracks: Track[],\n target: Track | null | undefined,\n): number {\n if (!target) return 0;\n const byRef = tracks.findIndex((t) => t === target);\n if (byRef !== -1) return byRef;\n\n const identity = trackIdentity(target);\n if (!identity) return 0;\n\n const matches: number[] = [];\n for (let i = 0; i < tracks.length; i += 1) {\n if (trackIdentity(tracks[i]) === identity) matches.push(i);\n }\n if (matches.length === 0) return 0;\n if (matches.length === 1) return matches[0]!;\n\n const nodeEnv =\n typeof globalThis !== \"undefined\" && \"process\" in globalThis\n ? (globalThis as { process?: { env?: { NODE_ENV?: string } } }).process?.env?.NODE_ENV\n : undefined;\n if (nodeEnv != null && nodeEnv !== \"production\") {\n console.warn(\n \"[@lucaismyname/ginger] Ambiguous track identity: multiple queue rows share the same fileUrl without a unique `id`. Resolving to the first match.\",\n );\n }\n return matches[0]!;\n}\n\nexport function insertTrackAt(tracks: Track[], track: Track, index?: number): Track[] {\n const next = [...tracks];\n const at = Math.max(0, Math.min(next.length, index ?? next.length));\n next.splice(at, 0, track);\n return next;\n}\n\nexport function removeTrackAt(tracks: Track[], index: number): Track[] {\n if (index < 0 || index >= tracks.length) return [...tracks];\n const next = [...tracks];\n next.splice(index, 1);\n return next;\n}\n\nexport function moveTrack(tracks: Track[], fromIndex: number, toIndex: number): Track[] {\n if (\n fromIndex === toIndex ||\n fromIndex < 0 ||\n fromIndex >= tracks.length ||\n toIndex < 0 ||\n toIndex >= tracks.length\n ) {\n return [...tracks];\n }\n const next = [...tracks];\n const [item] = next.splice(fromIndex, 1);\n if (!item) return [...tracks];\n next.splice(toIndex, 0, item);\n return next;\n}\n\nexport function addNextTrack(tracks: Track[], currentIndex: number, track: Track): Track[] {\n return insertTrackAt(tracks, track, Math.max(0, Math.min(tracks.length, currentIndex + 1)));\n}\n","import type { GingerState, RepeatMode, Track } from \"../types\";\nimport { clampIndex } from \"./queue\";\n\n/** Fields used by next/prev/ended navigation; avoids coupling helpers to full `GingerState`. */\nexport type GingerPlaybackNavigationSlice = Pick<\n GingerState,\n \"tracks\" | \"currentIndex\" | \"repeatMode\" | \"playbackMode\"\n>;\n\nexport type EndedTransition =\n | { kind: \"replay_same\" }\n | { kind: \"advance\"; nextIndex: number }\n | { kind: \"wrap\"; nextIndex: number }\n | { kind: \"stop\"; nextIndex: number };\n\nexport function computeEndedTransition(state: GingerPlaybackNavigationSlice): EndedTransition {\n const { tracks, currentIndex, repeatMode, playbackMode } = state;\n const len = tracks.length;\n if (len === 0) return { kind: \"stop\", nextIndex: 0 };\n if (repeatMode === \"one\") return { kind: \"replay_same\" };\n if (playbackMode === \"single\") return { kind: \"stop\", nextIndex: clampIndex(currentIndex, len) };\n if (currentIndex < len - 1) return { kind: \"advance\", nextIndex: currentIndex + 1 };\n if (repeatMode === \"all\") return { kind: \"wrap\", nextIndex: 0 };\n return { kind: \"stop\", nextIndex: clampIndex(currentIndex, len) };\n}\n\nexport function computeNextIndex(state: GingerPlaybackNavigationSlice): number {\n const { tracks, currentIndex, repeatMode, playbackMode } = state;\n const len = tracks.length;\n if (len === 0) return 0;\n if (playbackMode === \"single\") return clampIndex(currentIndex, len);\n if (currentIndex < len - 1) return currentIndex + 1;\n if (repeatMode === \"all\") return 0;\n return clampIndex(currentIndex, len);\n}\n\nexport function computePrevIndex(state: GingerPlaybackNavigationSlice): number {\n const { tracks, currentIndex, repeatMode, playbackMode } = state;\n const len = tracks.length;\n if (len === 0) return 0;\n if (playbackMode === \"single\") return clampIndex(currentIndex, len);\n if (currentIndex > 0) return currentIndex - 1;\n if (repeatMode === \"all\") return len - 1;\n return 0;\n}\n\nexport function cycleRepeatMode(mode: RepeatMode): RepeatMode {\n if (mode === \"off\") return \"all\";\n if (mode === \"all\") return \"one\";\n return \"off\";\n}\n\nexport function resolveArtworkUrl(\n track: Track | null,\n playlistArtwork?: string | null,\n): string | undefined {\n return track?.artworkUrl ?? playlistArtwork ?? undefined;\n}\n\nexport function resolveAlbumLine(\n track: Track | null,\n playlistSubtitle?: string | null,\n): string | undefined {\n return track?.album ?? playlistSubtitle ?? undefined;\n}\n","import { resolveAlbumLine, resolveArtworkUrl } from \"../core/transitions\";\nimport type { GingerState, PlaybackUiState, Track } from \"../types\";\n\nexport function getCurrentTrack(state: GingerState): Track | null {\n const t = state.tracks[state.currentIndex];\n return t ?? null;\n}\n\nexport function derivePlaybackUiState(state: GingerState): PlaybackUiState {\n if (state.errorMessage) return \"error\";\n if (state.tracks.length === 0) return \"idle\";\n if (state.isBuffering) return \"loading\";\n if (!state.isPaused) return \"playing\";\n if (\n Number.isFinite(state.duration) &&\n state.duration > 0 &&\n state.currentTime >= state.duration - 0.05\n ) {\n return \"ended\";\n }\n return \"paused\";\n}\n\nexport function effectiveDuration(state: GingerState): number {\n const d = state.duration;\n if (Number.isFinite(d) && d > 0) return d;\n const hint = state.tracks[state.currentIndex]?.durationSeconds;\n if (typeof hint === \"number\" && Number.isFinite(hint) && hint > 0) return hint;\n return 0;\n}\n\nexport function effectiveRemaining(state: GingerState): number {\n const dur = effectiveDuration(state);\n const rem = dur - state.currentTime;\n return Number.isFinite(rem) ? Math.max(0, rem) : 0;\n}\n\nexport function progressFraction(state: GingerState): number {\n const dur = effectiveDuration(state);\n if (!(dur > 0)) return 0;\n return Math.min(1, Math.max(0, state.currentTime / dur));\n}\n\nexport function resolvedArtwork(state: GingerState): string | undefined {\n const track = getCurrentTrack(state);\n return resolveArtworkUrl(track, state.playlistMeta?.artworkUrl);\n}\n\nexport function resolvedAlbumLine(state: GingerState): string | undefined {\n const track = getCurrentTrack(state);\n return resolveAlbumLine(track, state.playlistMeta?.subtitle);\n}\n"],"names":["clampIndex","index","length","shuffleWithAnchor","tracks","anchorIndex","anchor","rest","_","i","j","trackIdentity","track","findIndexByTrackIdentity","target","byRef","t","identity","matches","nodeEnv","_b","_a","insertTrackAt","next","at","removeTrackAt","moveTrack","fromIndex","toIndex","item","addNextTrack","currentIndex","computeEndedTransition","state","repeatMode","playbackMode","len","computeNextIndex","computePrevIndex","cycleRepeatMode","mode","resolveArtworkUrl","playlistArtwork","resolveAlbumLine","playlistSubtitle","getCurrentTrack","derivePlaybackUiState","effectiveDuration","d","hint","effectiveRemaining","rem","progressFraction","dur","resolvedArtwork","resolvedAlbumLine"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react"),d=require("../liveAudioGraph-0cpHD_Ic.cjs"),k=require("../useGinger-BXgia32v.cjs");function M(t,o,c,l){t.positionX.value=o,t.positionY.value=c,t.positionZ.value=l}function R(t,o,c,l){t.listener.positionX.value=o,t.listener.positionY.value=c,t.listener.positionZ.value=l}function q(t={}){const{enabled:o=!0,panningModel:c="HRTF",distanceModel:l="inverse",refDistance:g=1,position:S=[0,0,0],listenerPosition:A=[0,0,0]}=t,{audioRef:p}=k.useGinger(),[G,v]=r.useState(null),u=r.useRef(null),f=r.useRef(null),[P,h,m]=S,[b,y,C]=A;r.useEffect(()=>{const n=p.current;if(!(!n||typeof window>"u")){if(!o){d.setProcessingChain(n,[]),u.current=null,f.current=null;return}try{const e=d.attachLiveAnalyser(n,{fftSize:32,smoothingTimeConstant:0,minDecibels:-100,maxDecibels:0}),{context:s,id:i}=e,a=s.createPanner();a.panningModel=c,a.distanceModel=l,a.refDistance=g,M(a,P,h,m),R(s,b,y,C),u.current=a,f.current=s,d.setProcessingChain(n,[a]),d.detachLiveAnalyser(n,i),v(null)}catch(e){const s=e instanceof Error?e.message:"Failed to create spatial panner";v(s),u.current=null,f.current=null}return()=>{const e=p.current;e&&d.setProcessingChain(e,[]),u.current=null,f.current=null}}},[o,c,l,g,P,h,m,b,y,C,p]);const x=r.useCallback((n,e,s)=>{const i=u.current;i&&M(i,n,e,s)},[]),D=r.useCallback((n,e,s)=>{const i=f.current;i&&R(i,n,e,s)},[]),L=r.useCallback(n=>{const e=u.current;e&&(e.panningModel=n)},[]);return{setSourcePosition:x,setListenerPosition:D,setPanningModel:L,error:G}}exports.useGingerSpatialAudio=q;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/spatial/useGingerSpatialAudio.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n attachLiveAnalyser,\n detachLiveAnalyser,\n setProcessingChain,\n} from \"../analyzer/liveAudioGraph\";\nimport { useGinger } from \"../hooks/useGinger\";\n\n/** `[x, y, z]` in Web Audio space (meters). */\nexport type SpatialPosition = [number, number, number];\n\nexport type UseGingerSpatialAudioOptions = {\n /** When false, the panner is removed and the audio path is bypassed. Default: true. */\n enabled?: boolean;\n /** Default: `\"HRTF\"`. */\n panningModel?: PanningModelType;\n /** Default: `\"inverse\"`. */\n distanceModel?: DistanceModelType;\n /** Reference distance for attenuation. Default: `1`. */\n refDistance?: number;\n /** Source position. Default: `[0, 0, 0]`. */\n position?: SpatialPosition;\n /** Listener position. Default: `[0, 0, 0]`. */\n listenerPosition?: SpatialPosition;\n};\n\nexport type UseGingerSpatialAudioResult = {\n setSourcePosition: (x: number, y: number, z: number) => void;\n setListenerPosition: (x: number, y: number, z: number) => void;\n setPanningModel: (model: PanningModelType) => void;\n error: string | null;\n};\n\nfunction setPannerPosition(panner: PannerNode, x: number, y: number, z: number): void {\n panner.positionX.value = x;\n panner.positionY.value = y;\n panner.positionZ.value = z;\n}\n\nfunction setListenerXYZ(context: AudioContext, x: number, y: number, z: number): void {\n context.listener.positionX.value = x;\n context.listener.positionY.value = y;\n context.listener.positionZ.value = z;\n}\n\n/**\n * Inserts an HRTF `PannerNode` into the Web Audio graph for the active Ginger media element.\n *\n * Shares the same `AudioContext` as `useGingerEqualizer` / `useGingerLiveAnalyzer` — only one\n * `MediaElementAudioSourceNode` per element is allowed by the browser.\n *\n * ```ts\n * import { useGingerSpatialAudio } from \"@lucaismyname/ginger/spatial\";\n * ```\n */\nexport function useGingerSpatialAudio(\n options: UseGingerSpatialAudioOptions = {},\n): UseGingerSpatialAudioResult {\n const {\n enabled = true,\n panningModel = \"HRTF\",\n distanceModel = \"inverse\",\n refDistance = 1,\n position = [0, 0, 0],\n listenerPosition = [0, 0, 0],\n } = options;\n const { audioRef } = useGinger();\n const [error, setError] = useState<string | null>(null);\n\n const pannerRef = useRef<PannerNode | null>(null);\n const contextRef = useRef<AudioContext | null>(null);\n\n const [sx, sy, sz] = position;\n const [lx, ly, lz] = listenerPosition;\n\n useEffect(() => {\n const el = audioRef.current;\n if (!el || typeof window === \"undefined\") {\n return;\n }\n\n if (!enabled) {\n setProcessingChain(el, []);\n pannerRef.current = null;\n contextRef.current = null;\n return;\n }\n\n try {\n const attached = attachLiveAnalyser(el, {\n fftSize: 32,\n smoothingTimeConstant: 0,\n minDecibels: -100,\n maxDecibels: 0,\n });\n const { context, id: tempId } = attached;\n\n const panner = context.createPanner();\n panner.panningModel = panningModel;\n panner.distanceModel = distanceModel;\n panner.refDistance = refDistance;\n setPannerPosition(panner, sx, sy, sz);\n setListenerXYZ(context, lx, ly, lz);\n\n pannerRef.current = panner;\n contextRef.current = context;\n\n setProcessingChain(el, [panner]);\n detachLiveAnalyser(el, tempId);\n\n setError(null);\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"Failed to create spatial panner\";\n setError(msg);\n pannerRef.current = null;\n contextRef.current = null;\n }\n\n return () => {\n const element = audioRef.current;\n if (element) {\n setProcessingChain(element, []);\n }\n pannerRef.current = null;\n contextRef.current = null;\n };\n }, [enabled, panningModel, distanceModel, refDistance, sx, sy, sz, lx, ly, lz, audioRef]);\n\n const setSourcePosition = useCallback((x: number, y: number, z: number) => {\n const panner = pannerRef.current;\n if (panner) {\n setPannerPosition(panner, x, y, z);\n }\n }, []);\n\n const setListenerPosition = useCallback((x: number, y: number, z: number) => {\n const ctx = contextRef.current;\n if (ctx) {\n setListenerXYZ(ctx, x, y, z);\n }\n }, []);\n\n const setPanningModel = useCallback((model: PanningModelType) => {\n const panner = pannerRef.current;\n if (panner) {\n panner.panningModel = model;\n }\n }, []);\n\n return { setSourcePosition, setListenerPosition, setPanningModel, error };\n}\n"],"names":["setPannerPosition","panner","x","y","z","setListenerXYZ","context","useGingerSpatialAudio","options","enabled","panningModel","distanceModel","refDistance","position","listenerPosition","audioRef","useGinger","error","setError","useState","pannerRef","useRef","contextRef","sx","sy","sz","lx","ly","lz","useEffect","el","setProcessingChain","attached","attachLiveAnalyser","tempId","detachLiveAnalyser","msg","element","setSourcePosition","useCallback","setListenerPosition","ctx","setPanningModel","model"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/spatial/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,YAAY,EACV,eAAe,EACf,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { useState as X, useRef as R, useEffect as Y, useCallback as p } from "react";
|
|
2
|
+
import { s as d, a as Z, d as w } from "../liveAudioGraph-DvPaxBCP.js";
|
|
3
|
+
import { u as F } from "../useGinger-hpp2pAGY.js";
|
|
4
|
+
function b(t, o, i, c) {
|
|
5
|
+
t.positionX.value = o, t.positionY.value = i, t.positionZ.value = c;
|
|
6
|
+
}
|
|
7
|
+
function D(t, o, i, c) {
|
|
8
|
+
t.listener.positionX.value = o, t.listener.positionY.value = i, t.listener.positionZ.value = c;
|
|
9
|
+
}
|
|
10
|
+
function H(t = {}) {
|
|
11
|
+
const {
|
|
12
|
+
enabled: o = !0,
|
|
13
|
+
panningModel: i = "HRTF",
|
|
14
|
+
distanceModel: c = "inverse",
|
|
15
|
+
refDistance: m = 1,
|
|
16
|
+
position: L = [0, 0, 0],
|
|
17
|
+
listenerPosition: S = [0, 0, 0]
|
|
18
|
+
} = t, { audioRef: f } = F(), [z, g] = X(null), l = R(null), u = R(null), [v, P, h] = L, [y, M, x] = S;
|
|
19
|
+
Y(() => {
|
|
20
|
+
const e = f.current;
|
|
21
|
+
if (!(!e || typeof window > "u")) {
|
|
22
|
+
if (!o) {
|
|
23
|
+
d(e, []), l.current = null, u.current = null;
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const n = Z(e, {
|
|
28
|
+
fftSize: 32,
|
|
29
|
+
smoothingTimeConstant: 0,
|
|
30
|
+
minDecibels: -100,
|
|
31
|
+
maxDecibels: 0
|
|
32
|
+
}), { context: s, id: r } = n, a = s.createPanner();
|
|
33
|
+
a.panningModel = i, a.distanceModel = c, a.refDistance = m, b(a, v, P, h), D(s, y, M, x), l.current = a, u.current = s, d(e, [a]), w(e, r), g(null);
|
|
34
|
+
} catch (n) {
|
|
35
|
+
const s = n instanceof Error ? n.message : "Failed to create spatial panner";
|
|
36
|
+
g(s), l.current = null, u.current = null;
|
|
37
|
+
}
|
|
38
|
+
return () => {
|
|
39
|
+
const n = f.current;
|
|
40
|
+
n && d(n, []), l.current = null, u.current = null;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}, [o, i, c, m, v, P, h, y, M, x, f]);
|
|
44
|
+
const A = p((e, n, s) => {
|
|
45
|
+
const r = l.current;
|
|
46
|
+
r && b(r, e, n, s);
|
|
47
|
+
}, []), C = p((e, n, s) => {
|
|
48
|
+
const r = u.current;
|
|
49
|
+
r && D(r, e, n, s);
|
|
50
|
+
}, []), E = p((e) => {
|
|
51
|
+
const n = l.current;
|
|
52
|
+
n && (n.panningModel = e);
|
|
53
|
+
}, []);
|
|
54
|
+
return { setSourcePosition: A, setListenerPosition: C, setPanningModel: E, error: z };
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
H as useGingerSpatialAudio
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/spatial/useGingerSpatialAudio.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n attachLiveAnalyser,\n detachLiveAnalyser,\n setProcessingChain,\n} from \"../analyzer/liveAudioGraph\";\nimport { useGinger } from \"../hooks/useGinger\";\n\n/** `[x, y, z]` in Web Audio space (meters). */\nexport type SpatialPosition = [number, number, number];\n\nexport type UseGingerSpatialAudioOptions = {\n /** When false, the panner is removed and the audio path is bypassed. Default: true. */\n enabled?: boolean;\n /** Default: `\"HRTF\"`. */\n panningModel?: PanningModelType;\n /** Default: `\"inverse\"`. */\n distanceModel?: DistanceModelType;\n /** Reference distance for attenuation. Default: `1`. */\n refDistance?: number;\n /** Source position. Default: `[0, 0, 0]`. */\n position?: SpatialPosition;\n /** Listener position. Default: `[0, 0, 0]`. */\n listenerPosition?: SpatialPosition;\n};\n\nexport type UseGingerSpatialAudioResult = {\n setSourcePosition: (x: number, y: number, z: number) => void;\n setListenerPosition: (x: number, y: number, z: number) => void;\n setPanningModel: (model: PanningModelType) => void;\n error: string | null;\n};\n\nfunction setPannerPosition(panner: PannerNode, x: number, y: number, z: number): void {\n panner.positionX.value = x;\n panner.positionY.value = y;\n panner.positionZ.value = z;\n}\n\nfunction setListenerXYZ(context: AudioContext, x: number, y: number, z: number): void {\n context.listener.positionX.value = x;\n context.listener.positionY.value = y;\n context.listener.positionZ.value = z;\n}\n\n/**\n * Inserts an HRTF `PannerNode` into the Web Audio graph for the active Ginger media element.\n *\n * Shares the same `AudioContext` as `useGingerEqualizer` / `useGingerLiveAnalyzer` — only one\n * `MediaElementAudioSourceNode` per element is allowed by the browser.\n *\n * ```ts\n * import { useGingerSpatialAudio } from \"@lucaismyname/ginger/spatial\";\n * ```\n */\nexport function useGingerSpatialAudio(\n options: UseGingerSpatialAudioOptions = {},\n): UseGingerSpatialAudioResult {\n const {\n enabled = true,\n panningModel = \"HRTF\",\n distanceModel = \"inverse\",\n refDistance = 1,\n position = [0, 0, 0],\n listenerPosition = [0, 0, 0],\n } = options;\n const { audioRef } = useGinger();\n const [error, setError] = useState<string | null>(null);\n\n const pannerRef = useRef<PannerNode | null>(null);\n const contextRef = useRef<AudioContext | null>(null);\n\n const [sx, sy, sz] = position;\n const [lx, ly, lz] = listenerPosition;\n\n useEffect(() => {\n const el = audioRef.current;\n if (!el || typeof window === \"undefined\") {\n return;\n }\n\n if (!enabled) {\n setProcessingChain(el, []);\n pannerRef.current = null;\n contextRef.current = null;\n return;\n }\n\n try {\n const attached = attachLiveAnalyser(el, {\n fftSize: 32,\n smoothingTimeConstant: 0,\n minDecibels: -100,\n maxDecibels: 0,\n });\n const { context, id: tempId } = attached;\n\n const panner = context.createPanner();\n panner.panningModel = panningModel;\n panner.distanceModel = distanceModel;\n panner.refDistance = refDistance;\n setPannerPosition(panner, sx, sy, sz);\n setListenerXYZ(context, lx, ly, lz);\n\n pannerRef.current = panner;\n contextRef.current = context;\n\n setProcessingChain(el, [panner]);\n detachLiveAnalyser(el, tempId);\n\n setError(null);\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"Failed to create spatial panner\";\n setError(msg);\n pannerRef.current = null;\n contextRef.current = null;\n }\n\n return () => {\n const element = audioRef.current;\n if (element) {\n setProcessingChain(element, []);\n }\n pannerRef.current = null;\n contextRef.current = null;\n };\n }, [enabled, panningModel, distanceModel, refDistance, sx, sy, sz, lx, ly, lz, audioRef]);\n\n const setSourcePosition = useCallback((x: number, y: number, z: number) => {\n const panner = pannerRef.current;\n if (panner) {\n setPannerPosition(panner, x, y, z);\n }\n }, []);\n\n const setListenerPosition = useCallback((x: number, y: number, z: number) => {\n const ctx = contextRef.current;\n if (ctx) {\n setListenerXYZ(ctx, x, y, z);\n }\n }, []);\n\n const setPanningModel = useCallback((model: PanningModelType) => {\n const panner = pannerRef.current;\n if (panner) {\n panner.panningModel = model;\n }\n }, []);\n\n return { setSourcePosition, setListenerPosition, setPanningModel, error };\n}\n"],"names":["setPannerPosition","panner","x","y","z","setListenerXYZ","context","useGingerSpatialAudio","options","enabled","panningModel","distanceModel","refDistance","position","listenerPosition","audioRef","useGinger","error","setError","useState","pannerRef","useRef","contextRef","sx","sy","sz","lx","ly","lz","useEffect","el","setProcessingChain","attached","attachLiveAnalyser","tempId","detachLiveAnalyser","e","msg","element","setSourcePosition","useCallback","setListenerPosition","ctx","setPanningModel","model"],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** `[x, y, z]` in Web Audio space (meters). */
|
|
2
|
+
export type SpatialPosition = [number, number, number];
|
|
3
|
+
export type UseGingerSpatialAudioOptions = {
|
|
4
|
+
/** When false, the panner is removed and the audio path is bypassed. Default: true. */
|
|
5
|
+
enabled?: boolean;
|
|
6
|
+
/** Default: `"HRTF"`. */
|
|
7
|
+
panningModel?: PanningModelType;
|
|
8
|
+
/** Default: `"inverse"`. */
|
|
9
|
+
distanceModel?: DistanceModelType;
|
|
10
|
+
/** Reference distance for attenuation. Default: `1`. */
|
|
11
|
+
refDistance?: number;
|
|
12
|
+
/** Source position. Default: `[0, 0, 0]`. */
|
|
13
|
+
position?: SpatialPosition;
|
|
14
|
+
/** Listener position. Default: `[0, 0, 0]`. */
|
|
15
|
+
listenerPosition?: SpatialPosition;
|
|
16
|
+
};
|
|
17
|
+
export type UseGingerSpatialAudioResult = {
|
|
18
|
+
setSourcePosition: (x: number, y: number, z: number) => void;
|
|
19
|
+
setListenerPosition: (x: number, y: number, z: number) => void;
|
|
20
|
+
setPanningModel: (model: PanningModelType) => void;
|
|
21
|
+
error: string | null;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Inserts an HRTF `PannerNode` into the Web Audio graph for the active Ginger media element.
|
|
25
|
+
*
|
|
26
|
+
* Shares the same `AudioContext` as `useGingerEqualizer` / `useGingerLiveAnalyzer` — only one
|
|
27
|
+
* `MediaElementAudioSourceNode` per element is allowed by the browser.
|
|
28
|
+
*
|
|
29
|
+
* ```ts
|
|
30
|
+
* import { useGingerSpatialAudio } from "@lucaismyname/ginger/spatial";
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function useGingerSpatialAudio(options?: UseGingerSpatialAudioOptions): UseGingerSpatialAudioResult;
|
|
34
|
+
//# sourceMappingURL=useGingerSpatialAudio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useGingerSpatialAudio.d.ts","sourceRoot":"","sources":["../../src/spatial/useGingerSpatialAudio.ts"],"names":[],"mappings":"AAQA,+CAA+C;AAC/C,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEvD,MAAM,MAAM,4BAA4B,GAAG;IACzC,uFAAuF;IACvF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,yBAAyB;IACzB,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,4BAA4B;IAC5B,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,eAAe,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,iBAAiB,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,mBAAmB,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/D,eAAe,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAcF;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,GAAE,4BAAiC,GACzC,2BAA2B,CA6F7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useGingerSpatialAudio.test.d.ts","sourceRoot":"","sources":["../../src/spatial/useGingerSpatialAudio.test.tsx"],"names":[],"mappings":""}
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { clampPlaybackRate, clampVolume } from './core/playbackReducer';
|
|
2
|
+
import { GingerAction, GingerInitPayload, GingerState, PlaylistMeta, RepeatMode, Track } from './types';
|
|
3
|
+
export type GingerStoreOptions = {
|
|
4
|
+
tracks?: Track[];
|
|
5
|
+
currentIndex?: number;
|
|
6
|
+
playlistMeta?: PlaylistMeta | null;
|
|
7
|
+
isPaused?: boolean;
|
|
8
|
+
isShuffled?: boolean;
|
|
9
|
+
repeatMode?: RepeatMode;
|
|
10
|
+
playbackMode?: GingerState["playbackMode"];
|
|
11
|
+
volume?: number;
|
|
12
|
+
muted?: boolean;
|
|
13
|
+
playbackRate?: number;
|
|
14
|
+
};
|
|
15
|
+
export type GingerStore = {
|
|
16
|
+
/** Returns the current state snapshot. */
|
|
17
|
+
getState: () => GingerState;
|
|
18
|
+
/** Dispatch an action to update state. Synchronously updates state and notifies listeners. */
|
|
19
|
+
dispatch: (action: GingerAction) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Subscribe to state changes. The listener is called after every `dispatch` that produces
|
|
22
|
+
* a new state object. Returns an unsubscribe function.
|
|
23
|
+
*/
|
|
24
|
+
subscribe: (listener: (state: GingerState) => void) => () => void;
|
|
25
|
+
/** Convenience: re-initialise with a new set of init options (equivalent to `dispatch({ type: "INIT", ... })`). */
|
|
26
|
+
init: (payload: GingerInitPayload) => void;
|
|
27
|
+
/** Clamp helpers re-exported for convenience. */
|
|
28
|
+
clampVolume: typeof clampVolume;
|
|
29
|
+
clampPlaybackRate: typeof clampPlaybackRate;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Framework-agnostic store wrapping `gingerReducer`.
|
|
33
|
+
* Usable outside React — e.g. in Svelte, Vue, Node.js testing, or server-side rendering contexts.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* import { createGingerStore } from "@lucaismyname/ginger";
|
|
38
|
+
*
|
|
39
|
+
* const store = createGingerStore({ tracks: myTracks });
|
|
40
|
+
* const unsub = store.subscribe((state) => console.log(state.currentIndex));
|
|
41
|
+
* store.dispatch({ type: "NEXT" });
|
|
42
|
+
* unsub();
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function createGingerStore(options?: GingerStoreOptions): GingerStore;
|
|
46
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAqC,MAAM,wBAAwB,CAAC;AAC3G,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAE7G,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,YAAY,CAAC,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,WAAW,CAAC;IAC5B,8FAA8F;IAC9F,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IACzC;;;OAGG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IAClE,mHAAmH;IACnH,IAAI,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC3C,iDAAiD;IACjD,WAAW,EAAE,OAAO,WAAW,CAAC;IAChC,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;CAC7C,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,kBAAuB,GAAG,WAAW,CA2C/E"}
|
package/dist/testing/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Al=require("react/jsx-runtime"),Xi=require("react"),yt=require("react-dom"),Il=require("../ginger-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Al=require("react/jsx-runtime"),Xi=require("react"),yt=require("react-dom"),Il=require("../ginger-NEcOSSJD.cjs");function Pc(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const r in e)if(r!=="default"){const n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:()=>e[r]})}}return t.default=e,Object.freeze(t)}const ur=Pc(Xi);function Tc(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var wi={exports:{}},ne={};/**
|
|
2
2
|
* @license React
|
|
3
3
|
* react-dom-test-utils.production.min.js
|
|
4
4
|
*
|
package/dist/testing/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsxs as Rc, jsx as Pc } from "react/jsx-runtime";
|
|
|
2
2
|
import * as ur from "react";
|
|
3
3
|
import Us from "react";
|
|
4
4
|
import yt from "react-dom";
|
|
5
|
-
import { G as Ml } from "../ginger-
|
|
5
|
+
import { G as Ml } from "../ginger-L2ZFgzH4.js";
|
|
6
6
|
function Tc(e) {
|
|
7
7
|
return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
|
|
8
8
|
}
|
|
@@ -4,7 +4,7 @@ declare class MockAudioNode {
|
|
|
4
4
|
readonly connectCalls: MockAudioNode[];
|
|
5
5
|
disconnectCalls: number;
|
|
6
6
|
connect(node: MockAudioNode): MockAudioNode;
|
|
7
|
-
disconnect(): void;
|
|
7
|
+
disconnect(_node?: MockAudioNode): void;
|
|
8
8
|
}
|
|
9
9
|
export declare class MockAudioDestinationNode extends MockAudioNode {
|
|
10
10
|
}
|
|
@@ -21,16 +21,44 @@ export declare class MockAnalyserNode extends MockAudioNode {
|
|
|
21
21
|
getByteFrequencyData(array: Uint8Array): void;
|
|
22
22
|
getByteTimeDomainData(array: Uint8Array): void;
|
|
23
23
|
}
|
|
24
|
+
export declare class MockBiquadFilterNode extends MockAudioNode {
|
|
25
|
+
type: BiquadFilterType;
|
|
26
|
+
readonly frequency: {
|
|
27
|
+
value: number;
|
|
28
|
+
};
|
|
29
|
+
readonly gain: {
|
|
30
|
+
value: number;
|
|
31
|
+
};
|
|
32
|
+
readonly Q: {
|
|
33
|
+
value: number;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
declare class MockAudioParam {
|
|
37
|
+
value: number;
|
|
38
|
+
}
|
|
39
|
+
export declare class MockPannerNode extends MockAudioNode {
|
|
40
|
+
panningModel: PanningModelType;
|
|
41
|
+
distanceModel: DistanceModelType;
|
|
42
|
+
refDistance: number;
|
|
43
|
+
readonly positionX: MockAudioParam;
|
|
44
|
+
readonly positionY: MockAudioParam;
|
|
45
|
+
readonly positionZ: MockAudioParam;
|
|
46
|
+
}
|
|
24
47
|
export declare class MockAudioContext extends EventTarget {
|
|
25
48
|
readonly destination: MockAudioDestinationNode;
|
|
49
|
+
readonly listener: AudioListener;
|
|
26
50
|
readonly sources: MockMediaElementAudioSourceNode[];
|
|
27
51
|
readonly analysers: MockAnalyserNode[];
|
|
52
|
+
readonly biquadFilters: MockBiquadFilterNode[];
|
|
53
|
+
readonly panners: MockPannerNode[];
|
|
28
54
|
sampleRate: number;
|
|
29
55
|
state: MockAudioContextState;
|
|
30
56
|
closeCalls: number;
|
|
31
57
|
resumeCalls: number;
|
|
32
58
|
createMediaElementSource(element: HTMLAudioElement): MediaElementAudioSourceNode;
|
|
33
59
|
createAnalyser(): AnalyserNode;
|
|
60
|
+
createBiquadFilter(): BiquadFilterNode;
|
|
61
|
+
createPanner(): PannerNode;
|
|
34
62
|
resume(): Promise<void>;
|
|
35
63
|
close(): Promise<void>;
|
|
36
64
|
setStateForTest(nextState: MockAudioContextState): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mockWebAudio.d.ts","sourceRoot":"","sources":["../../src/testing/mockWebAudio.ts"],"names":[],"mappings":"AAAA,KAAK,qBAAqB,GAAG,iBAAiB,CAAC;AAE/C,cAAM,aAAa;IACjB,QAAQ,CAAC,WAAW,EAAE,aAAa,EAAE,CAAM;IAC3C,QAAQ,CAAC,YAAY,EAAE,aAAa,EAAE,CAAM;IAC5C,eAAe,SAAK;IAEpB,OAAO,CAAC,IAAI,EAAE,aAAa;IAM3B,UAAU;
|
|
1
|
+
{"version":3,"file":"mockWebAudio.d.ts","sourceRoot":"","sources":["../../src/testing/mockWebAudio.ts"],"names":[],"mappings":"AAAA,KAAK,qBAAqB,GAAG,iBAAiB,CAAC;AAE/C,cAAM,aAAa;IACjB,QAAQ,CAAC,WAAW,EAAE,aAAa,EAAE,CAAM;IAC3C,QAAQ,CAAC,YAAY,EAAE,aAAa,EAAE,CAAM;IAC5C,eAAe,SAAK;IAEpB,OAAO,CAAC,IAAI,EAAE,aAAa;IAM3B,UAAU,CAAC,KAAK,CAAC,EAAE,aAAa;CAIjC;AAED,qBAAa,wBAAyB,SAAQ,aAAa;CAAG;AAE9D,qBAAa,+BAAgC,SAAQ,aAAa;IACpD,QAAQ,CAAC,YAAY,EAAE,gBAAgB;gBAA9B,YAAY,EAAE,gBAAgB;CAGpD;AAED,qBAAa,gBAAiB,SAAQ,aAAa;IACjD,OAAO,SAAQ;IACf,qBAAqB,SAAO;IAC5B,WAAW,SAAQ;IACnB,WAAW,SAAO;IAElB,IAAI,iBAAiB,WAEpB;IAED,oBAAoB,CAAC,KAAK,EAAE,UAAU;IAMtC,qBAAqB,CAAC,KAAK,EAAE,UAAU;CAKxC;AAED,qBAAa,oBAAqB,SAAQ,aAAa;IACrD,IAAI,EAAE,gBAAgB,CAAa;IACnC,QAAQ,CAAC,SAAS;;MAAmB;IACrC,QAAQ,CAAC,IAAI;;MAAgB;IAC7B,QAAQ,CAAC,CAAC;;MAAgB;CAC3B;AAED,cAAM,cAAc;IAClB,KAAK,SAAK;CACX;AAQD,qBAAa,cAAe,SAAQ,aAAa;IAC/C,YAAY,EAAE,gBAAgB,CAAU;IACxC,aAAa,EAAE,iBAAiB,CAAa;IAC7C,WAAW,SAAK;IAChB,QAAQ,CAAC,SAAS,iBAAwB;IAC1C,QAAQ,CAAC,SAAS,iBAAwB;IAC1C,QAAQ,CAAC,SAAS,iBAAwB;CAC3C;AAED,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,CAAC,WAAW,2BAAkC;IACtD,QAAQ,CAAC,QAAQ,EAAyC,aAAa,CAAC;IACxE,QAAQ,CAAC,OAAO,EAAE,+BAA+B,EAAE,CAAM;IACzD,QAAQ,CAAC,SAAS,EAAE,gBAAgB,EAAE,CAAM;IAC5C,QAAQ,CAAC,aAAa,EAAE,oBAAoB,EAAE,CAAM;IACpD,QAAQ,CAAC,OAAO,EAAE,cAAc,EAAE,CAAM;IAExC,UAAU,SAAU;IACpB,KAAK,EAAE,qBAAqB,CAAa;IACzC,UAAU,SAAK;IACf,WAAW,SAAK;IAEhB,wBAAwB,CAAC,OAAO,EAAE,gBAAgB,GAGpB,2BAA2B;IAGzD,cAAc,IAGkB,YAAY;IAG5C,kBAAkB,IAGY,gBAAgB;IAG9C,YAAY,IAGkB,UAAU;IAGlC,MAAM;IAON,KAAK;IAKX,eAAe,CAAC,SAAS,EAAE,qBAAqB;CAKjD;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,mBAAmB,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,oBAAoB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,0BAA0B,EAAE,MAAM,MAAM,CAAC;IACzC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,wBAAgB,mBAAmB,IAAI,mBAAmB,CAgFzD"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("react"),v=require("../GingerSplitContexts-C7puo0M7.cjs");function h(n){return n.replace(/<[^>]+>/g,"").trim()}function T(n){const r=n.trim().replace(",",".").split(":");if(r.length===3){const s=Number(r[0]),t=Number(r[1]),c=Number(r[2]);return[s,t,c].every(Number.isFinite)?s*3600+t*60+c:Number.NaN}if(r.length===2){const s=Number(r[0]),t=Number(r[1]);return[s,t].every(Number.isFinite)?s*60+t:Number.NaN}return Number.NaN}function S(n){const i=n.indexOf("-->");if(i<0)return null;const r=n.slice(0,i).trim(),t=n.slice(i+3).trim().match(/^(\S+)/);return t?{start:r,end:t[1]}:null}function N(n){const i=[],r=n.replace(/\r\n/g,`
|
|
2
|
+
`).split(/\n\s*\n/);for(const s of r){const t=s.split(`
|
|
3
|
+
`).map(a=>a.trim()).filter(a=>a.length>0);if(t.length===0)continue;let c=0;/^\d+$/.test(t[0])&&(c=1);const o=t[c];if(!o)continue;const e=S(o);if(!e)continue;const m=T(e.start),u=T(e.end);if(!Number.isFinite(m)||!Number.isFinite(u))continue;const l=t.slice(c+1),f=h(l.join(`
|
|
4
|
+
`));f&&i.push({startTime:m,endTime:u,text:f})}return i.sort((s,t)=>s.startTime-t.startTime)}function b(n){const i=[];let r=n.replace(/\r\n/g,`
|
|
5
|
+
`);if(r.startsWith("WEBVTT")){const t=r.search(/\n\s*\n/);r=t>=0?r.slice(t).trim():""}const s=r.split(/\n\s*\n/);for(const t of s){const o=t.split(`
|
|
6
|
+
`).map(p=>p.trimEnd());if(o.length===0||o[0].startsWith("NOTE")||o[0].startsWith("STYLE")||o[0].startsWith("REGION"))continue;let e=0,m,u=o[e];if(u.includes("-->")||(m=o[e],e+=1,u=o[e]),!(u!=null&&u.includes("-->")))continue;const l=S(u);if(!l)continue;const f=T(l.start),a=T(l.end);if(!Number.isFinite(f)||!Number.isFinite(a))continue;const F=o.slice(e+1).filter(p=>p.trim().length>0),g=h(F.join(`
|
|
7
|
+
`));g&&i.push({startTime:f,endTime:a,text:g,...m?{id:m}:{}})}return i.sort((t,c)=>t.startTime-c.startTime)}function y(n){return n.trimStart().startsWith("WEBVTT")?b(n):N(n)}function x(n,i){return i==="vtt"?b(n):i==="srt"?N(n):y(n)}function W(n){const{transcript:i,format:r="auto"}=n,{currentTime:s}=v.useGingerMedia(),t=d.useMemo(()=>Array.isArray(i)?[...i].filter(e=>Number.isFinite(e.startTime)&&Number.isFinite(e.endTime)&&e.startTime>=0&&e.endTime>=e.startTime).sort((e,m)=>e.startTime-m.startTime):x(i,r),[i,r]),c=d.useMemo(()=>{for(let e=t.length-1;e>=0;e-=1)if(s>=t[e].startTime)return e;return-1},[s,t]),o=d.useMemo(()=>t.filter(e=>s>=e.startTime&&s<e.endTime),[s,t]);return{cues:t,activeIndex:c,activeCue:c>=0?t[c]??null:null,activeCues:o}}exports.parseSrt=N;exports.parseTimestampToSeconds=T;exports.parseTranscriptAuto=y;exports.parseVtt=b;exports.useGingerTranscriptSync=W;
|
|
8
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/transcript/parseTranscript.ts","../../src/transcript/useGingerTranscriptSync.ts"],"sourcesContent":["/**\n * A single timed transcript cue (SRT / WebVTT).\n */\nexport type TranscriptCue = {\n /** Start time in seconds. */\n startTime: number;\n /** End time in seconds. */\n endTime: number;\n text: string;\n /** Present for WebVTT cues that declare an identifier line. */\n id?: string;\n};\n\nfunction stripHtmlTags(text: string): string {\n return text.replace(/<[^>]+>/g, \"\").trim();\n}\n\n/** Parse `HH:MM:SS.mmm` / `HH:MM:SS,mmm` / `MM:SS.mmm` (WebVTT) to seconds. */\nexport function parseTimestampToSeconds(raw: string): number {\n const t = raw.trim().replace(\",\", \".\");\n const segs = t.split(\":\");\n if (segs.length === 3) {\n const h = Number(segs[0]);\n const m = Number(segs[1]);\n const sec = Number(segs[2]);\n if (![h, m, sec].every(Number.isFinite)) return Number.NaN;\n return h * 3600 + m * 60 + sec;\n }\n if (segs.length === 2) {\n const m = Number(segs[0]);\n const sec = Number(segs[1]);\n if (![m, sec].every(Number.isFinite)) return Number.NaN;\n return m * 60 + sec;\n }\n return Number.NaN;\n}\n\nfunction parseTimingLine(line: string): { start: string; end: string } | null {\n const arrow = line.indexOf(\"-->\");\n if (arrow < 0) return null;\n const start = line.slice(0, arrow).trim();\n const rest = line.slice(arrow + 3).trim();\n const endMatch = rest.match(/^(\\S+)/);\n if (!endMatch) return null;\n return { start, end: endMatch[1]! };\n}\n\n/**\n * Parse SubRip (`.srt`) content into ordered cues.\n */\nexport function parseSrt(srt: string): TranscriptCue[] {\n const cues: TranscriptCue[] = [];\n const blocks = srt.replace(/\\r\\n/g, \"\\n\").split(/\\n\\s*\\n/);\n\n for (const block of blocks) {\n const lines = block\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter((l) => l.length > 0);\n if (lines.length === 0) continue;\n\n let i = 0;\n if (/^\\d+$/.test(lines[0]!)) {\n i = 1;\n }\n const timingLine = lines[i];\n if (!timingLine) continue;\n const times = parseTimingLine(timingLine);\n if (!times) continue;\n const startTime = parseTimestampToSeconds(times.start);\n const endTime = parseTimestampToSeconds(times.end);\n if (!Number.isFinite(startTime) || !Number.isFinite(endTime)) continue;\n const textLines = lines.slice(i + 1);\n const text = stripHtmlTags(textLines.join(\"\\n\"));\n if (!text) continue;\n cues.push({ startTime, endTime, text });\n }\n\n return cues.sort((a, b) => a.startTime - b.startTime);\n}\n\n/**\n * Parse WebVTT (`.vtt`) content into ordered cues. Ignores `NOTE` blocks and region/style headers.\n */\nexport function parseVtt(vtt: string): TranscriptCue[] {\n const cues: TranscriptCue[] = [];\n let body = vtt.replace(/\\r\\n/g, \"\\n\");\n if (body.startsWith(\"WEBVTT\")) {\n const firstBlank = body.search(/\\n\\s*\\n/);\n body = firstBlank >= 0 ? body.slice(firstBlank).trim() : \"\";\n }\n\n const blocks = body.split(/\\n\\s*\\n/);\n\n for (const block of blocks) {\n const rawLines = block.split(\"\\n\");\n const lines = rawLines.map((l) => l.trimEnd());\n if (lines.length === 0) continue;\n if (\n lines[0]!.startsWith(\"NOTE\") ||\n lines[0]!.startsWith(\"STYLE\") ||\n lines[0]!.startsWith(\"REGION\")\n ) {\n continue;\n }\n\n let i = 0;\n let id: string | undefined;\n let timingLine = lines[i]!;\n if (!timingLine.includes(\"-->\")) {\n id = lines[i]!;\n i += 1;\n timingLine = lines[i]!;\n }\n if (!timingLine?.includes(\"-->\")) continue;\n\n const times = parseTimingLine(timingLine);\n if (!times) continue;\n const startTime = parseTimestampToSeconds(times.start);\n const endTime = parseTimestampToSeconds(times.end);\n if (!Number.isFinite(startTime) || !Number.isFinite(endTime)) continue;\n\n const textLines = lines.slice(i + 1).filter((l) => l.trim().length > 0);\n const text = stripHtmlTags(textLines.join(\"\\n\"));\n if (!text) continue;\n cues.push({ startTime, endTime, text, ...(id ? { id } : {}) });\n }\n\n return cues.sort((a, b) => a.startTime - b.startTime);\n}\n\n/**\n * Auto-detect format: WebVTT if the string starts with `WEBVTT`, otherwise SRT.\n */\nexport function parseTranscriptAuto(input: string): TranscriptCue[] {\n const trimmed = input.trimStart();\n if (trimmed.startsWith(\"WEBVTT\")) {\n return parseVtt(input);\n }\n return parseSrt(input);\n}\n","import { useMemo } from \"react\";\nimport { useGingerMedia } from \"../context/GingerSplitContexts\";\nimport { type TranscriptCue, parseSrt, parseTranscriptAuto, parseVtt } from \"./parseTranscript\";\n\nexport type UseGingerTranscriptSyncOptions = {\n transcript: string | TranscriptCue[];\n /** Default: `\"auto\"` (WEBVTT header → VTT, else SRT). Ignored when `transcript` is a cue array. */\n format?: \"vtt\" | \"srt\" | \"auto\";\n};\n\nexport type GingerTranscriptSyncState = {\n cues: TranscriptCue[];\n /** Last cue index where `startTime <= currentTime` (same scan as lyrics sync). */\n activeIndex: number;\n activeCue: TranscriptCue | null;\n /** All cues active at `currentTime` (`startTime <= t < endTime`), including overlaps. */\n activeCues: TranscriptCue[];\n};\n\nfunction parseString(transcript: string, format: \"vtt\" | \"srt\" | \"auto\"): TranscriptCue[] {\n if (format === \"vtt\") return parseVtt(transcript);\n if (format === \"srt\") return parseSrt(transcript);\n return parseTranscriptAuto(transcript);\n}\n\n/**\n * Syncs SRT / WebVTT transcript cues to the current Ginger playback time.\n *\n * ```ts\n * import { useGingerTranscriptSync } from \"@lucaismyname/ginger/transcript\";\n * ```\n */\nexport function useGingerTranscriptSync(\n options: UseGingerTranscriptSyncOptions,\n): GingerTranscriptSyncState {\n const { transcript, format = \"auto\" } = options;\n const { currentTime } = useGingerMedia();\n\n const cues = useMemo(() => {\n if (Array.isArray(transcript)) {\n return [...transcript]\n .filter(\n (c) =>\n Number.isFinite(c.startTime) &&\n Number.isFinite(c.endTime) &&\n c.startTime >= 0 &&\n c.endTime >= c.startTime,\n )\n .sort((a, b) => a.startTime - b.startTime);\n }\n return parseString(transcript, format);\n }, [transcript, format]);\n\n const activeIndex = useMemo(() => {\n for (let i = cues.length - 1; i >= 0; i -= 1) {\n if (currentTime >= cues[i]!.startTime) return i;\n }\n return -1;\n }, [currentTime, cues]);\n\n const activeCues = useMemo(() => {\n return cues.filter((c) => currentTime >= c.startTime && currentTime < c.endTime);\n }, [currentTime, cues]);\n\n return {\n cues,\n activeIndex,\n activeCue: activeIndex >= 0 ? (cues[activeIndex] ?? null) : null,\n activeCues,\n };\n}\n"],"names":["stripHtmlTags","text","parseTimestampToSeconds","raw","segs","h","m","sec","parseTimingLine","line","arrow","start","endMatch","parseSrt","srt","cues","blocks","block","lines","l","i","timingLine","times","startTime","endTime","textLines","a","b","parseVtt","vtt","body","firstBlank","id","parseTranscriptAuto","input","parseString","transcript","format","useGingerTranscriptSync","options","currentTime","useGingerMedia","useMemo","c","activeIndex","activeCues"],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { parseSrt, parseTimestampToSeconds, parseTranscriptAuto, parseVtt, } from './parseTranscript';
|
|
2
|
+
export type { TranscriptCue } from './parseTranscript';
|
|
3
|
+
export { useGingerTranscriptSync } from './useGingerTranscriptSync';
|
|
4
|
+
export type { GingerTranscriptSyncState, UseGingerTranscriptSyncOptions, } from './useGingerTranscriptSync';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transcript/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,uBAAuB,EACvB,mBAAmB,EACnB,QAAQ,GACT,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,YAAY,EACV,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,2BAA2B,CAAC"}
|