@lucaismyname/ginger 0.0.14 → 0.0.15
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 +4 -2
- package/dist/{GingerSplitContexts-4YZ-OJ9V.js → GingerSplitContexts-BzBExb95.js} +22 -21
- package/dist/GingerSplitContexts-BzBExb95.js.map +1 -0
- package/dist/GingerSplitContexts-C7puo0M7.cjs +2 -0
- package/dist/GingerSplitContexts-C7puo0M7.cjs.map +1 -0
- package/dist/audio/GingerPlayer.d.ts.map +1 -1
- package/dist/audio/GingerPlayer.test.d.ts +2 -0
- package/dist/audio/GingerPlayer.test.d.ts.map +1 -0
- package/dist/client.cjs +1 -1
- package/dist/client.js +3 -3
- package/dist/context/GingerContext.d.ts +2 -1
- package/dist/context/GingerContext.d.ts.map +1 -1
- package/dist/context/GingerProvider.d.ts.map +1 -1
- package/dist/context/GingerSplitContexts.d.ts +2 -1
- package/dist/context/GingerSplitContexts.d.ts.map +1 -1
- package/dist/core/playbackReducer.d.ts.map +1 -1
- package/dist/core/queue.d.ts.map +1 -1
- package/dist/experimental-gapless/index.cjs +1 -1
- package/dist/experimental-gapless/index.js +1 -1
- package/dist/ginger-BTPRqWHs.js +1621 -0
- package/dist/ginger-BTPRqWHs.js.map +1 -0
- package/dist/ginger-BiI69vrn.cjs +2 -0
- package/dist/ginger-BiI69vrn.cjs.map +1 -0
- package/dist/hooks/hooks.test.d.ts +2 -0
- package/dist/hooks/hooks.test.d.ts.map +1 -0
- package/dist/hooks/useGinger.d.ts +1 -0
- package/dist/hooks/useGinger.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +3 -3
- package/dist/media/useMediaSession.d.ts.map +1 -1
- package/dist/media/useMediaSession.test.d.ts +2 -0
- package/dist/media/useMediaSession.test.d.ts.map +1 -0
- package/dist/testing/helpers.d.ts +21 -0
- package/dist/testing/helpers.d.ts.map +1 -0
- package/dist/testing/index.cjs +19 -19
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.ts +2 -7
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +33 -4
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/renderGinger.d.ts +8 -0
- package/dist/testing/renderGinger.d.ts.map +1 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/{useSeekDrag-DkAJvf8H.js → useSeekDrag-Br1V0Vao.js} +32 -31
- package/dist/useSeekDrag-Br1V0Vao.js.map +1 -0
- package/dist/useSeekDrag-aS7uk26h.cjs +2 -0
- package/dist/useSeekDrag-aS7uk26h.cjs.map +1 -0
- package/package.json +4 -1
- package/dist/GingerSplitContexts-4YZ-OJ9V.js.map +0 -1
- package/dist/GingerSplitContexts-Bze1Bqe2.cjs +0 -2
- package/dist/GingerSplitContexts-Bze1Bqe2.cjs.map +0 -1
- package/dist/ginger-DYoHDn8T.cjs +0 -2
- package/dist/ginger-DYoHDn8T.cjs.map +0 -1
- package/dist/ginger-Dntdd6zH.js +0 -1599
- package/dist/ginger-Dntdd6zH.js.map +0 -1
- package/dist/useSeekDrag-Cc0wpC70.cjs +0 -2
- package/dist/useSeekDrag-Cc0wpC70.cjs.map +0 -1
- package/dist/useSeekDrag-DkAJvf8H.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ginger-Dntdd6zH.js","sources":["../src/context/GingerContext.tsx","../src/audio/GingerPlayer.tsx","../src/core/queue.ts","../src/core/transitions.ts","../src/internal/selectors.ts","../src/components/current/createTextDisplay.tsx","../src/components/current/texts.ts","../src/components/current/Year.tsx","../src/components/current/Lyrics.tsx","../src/components/current/FileUrl.tsx","../src/components/current/Artwork.tsx","../src/components/current/QueueMeta.tsx","../src/internal/formatTime.ts","../src/components/current/Time.tsx","../src/components/current/Playback.tsx","../src/context/GingerLocaleContext.tsx","../src/hooks/useControlBindings.ts","../src/components/controls/Controls.tsx","../src/components/playlist/GingerPlaylist.tsx","../src/components/queue/QueueDisplay.tsx","../src/core/playbackReducer.ts","../src/media/useMediaSession.ts","../src/context/GingerProvider.tsx","../src/ginger.ts"],"sourcesContent":["import { createContext, useContext, type Dispatch, type MutableRefObject } from \"react\";\nimport type { GingerAction, GingerInitPayload, GingerState, PlaylistMeta, RepeatMode, Track } from \"../types\";\n\nexport type GingerContextValue = {\n state: GingerState;\n dispatch: Dispatch<GingerAction>;\n audioRef: MutableRefObject<HTMLAudioElement | null>;\n notifyEnded: () => void;\n /** Full reset to match `createInitialState` / provider `initial*` props. */\n init: (payload: GingerInitPayload) => void;\n play: () => void;\n pause: () => void;\n togglePlayPause: () => void;\n seek: (timeSeconds: number) => void;\n setVolume: (volume: number) => void;\n setMuted: (muted: boolean) => void;\n toggleMute: () => void;\n setPlaybackRate: (rate: number) => void;\n next: () => void;\n prev: () => void;\n setRepeatMode: (mode: RepeatMode) => void;\n cycleRepeat: () => void;\n toggleShuffle: () => void;\n setQueue: (tracks: Track[], currentIndex?: number) => void;\n insertTrackAt: (track: Track, index?: number, autoPlay?: boolean) => void;\n removeTrackAt: (index: number) => void;\n moveTrack: (fromIndex: number, toIndex: number) => void;\n enqueueNext: (track: Track) => void;\n playTrackAt: (index: number) => void;\n selectTrackAt: (index: number) => void;\n setPlaylistMeta: (meta: PlaylistMeta | null) => void;\n};\n\nconst GingerContext = createContext<GingerContextValue | null>(null);\n\nexport function useGingerContext(): GingerContextValue {\n const ctx = useContext(GingerContext);\n if (!ctx) throw new Error(\"Ginger components must be used within <Ginger.Provider>\");\n return ctx;\n}\n\nexport { GingerContext };\n","import { useEffect, useRef, useState, type AudioHTMLAttributes, type CSSProperties } from \"react\";\nimport { useGingerContext } from \"../context/GingerContext\";\n\nexport type GingerPlayerProps = {\n className?: string;\n style?: CSSProperties;\n preload?: AudioHTMLAttributes<HTMLAudioElement>[\"preload\"];\n crossOrigin?: AudioHTMLAttributes<HTMLAudioElement>[\"crossOrigin\"];\n respectReducedMotion?: boolean;\n};\n\nfunction readBufferedFraction(el: HTMLAudioElement): number {\n const { buffered, duration } = el;\n if (!(duration > 0) || buffered.length === 0) return 0;\n return Math.min(1, buffered.end(buffered.length - 1) / duration);\n}\n\nexport function GingerPlayer({\n className,\n style,\n preload = \"metadata\",\n crossOrigin,\n respectReducedMotion = false,\n}: GingerPlayerProps) {\n const { audioRef, dispatch, state, notifyEnded } = useGingerContext();\n const url = state.tracks[state.currentIndex]?.fileUrl ?? \"\";\n const lastTimeSnapshotRef = useRef({\n currentTime: -1,\n duration: -1,\n bufferedFraction: -1,\n });\n\n const [reducedMotion, setReducedMotion] = useState(false);\n\n useEffect(() => {\n if (!respectReducedMotion || typeof window === \"undefined\") return;\n const mql = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n const sync = () => setReducedMotion(mql.matches);\n sync();\n mql.addEventListener(\"change\", sync);\n return () => mql.removeEventListener(\"change\", sync);\n }, [respectReducedMotion]);\n\n const syncTime = (el: HTMLAudioElement, force = false) => {\n const next = {\n currentTime: el.currentTime,\n duration: el.duration,\n bufferedFraction: readBufferedFraction(el),\n };\n const prev = lastTimeSnapshotRef.current;\n const timeThreshold = reducedMotion ? 0.5 : 0.25;\n const changedEnough =\n Math.abs(next.currentTime - prev.currentTime) >= timeThreshold ||\n Math.abs(next.duration - prev.duration) >= 0.01 ||\n Math.abs(next.bufferedFraction - prev.bufferedFraction) >= 0.01;\n if (!force && !changedEnough) return;\n lastTimeSnapshotRef.current = next;\n dispatch({\n type: \"MEDIA_TIME_UPDATE\",\n payload: next,\n });\n };\n\n useEffect(() => {\n const el = audioRef.current;\n if (!el) return;\n el.volume = state.volume;\n el.muted = state.muted;\n el.playbackRate = state.playbackRate;\n }, [audioRef, state.volume, state.muted, state.playbackRate]);\n\n useEffect(() => {\n const el = audioRef.current;\n if (!el) return;\n if (!url) {\n el.removeAttribute(\"src\");\n lastTimeSnapshotRef.current = { currentTime: -1, duration: -1, bufferedFraction: -1 };\n return;\n }\n if (el.getAttribute(\"src\") !== url) {\n el.src = url;\n el.load();\n lastTimeSnapshotRef.current = { currentTime: -1, duration: -1, bufferedFraction: -1 };\n }\n }, [audioRef, state.currentIndex, state.tracks, url]);\n\n return (\n <audio\n ref={audioRef}\n className={className}\n style={style}\n preload={preload}\n crossOrigin={crossOrigin}\n controls={false}\n playsInline\n onTimeUpdate={(e) => {\n syncTime(e.currentTarget);\n }}\n onLoadedMetadata={(e) => {\n const el = e.currentTarget;\n lastTimeSnapshotRef.current = { currentTime: -1, duration: -1, bufferedFraction: -1 };\n dispatch({\n type: \"MEDIA_LOADED_METADATA\",\n payload: {\n duration: el.duration,\n bufferedFraction: readBufferedFraction(el),\n },\n });\n }}\n onSeeking={(e) => syncTime(e.currentTarget, true)}\n onSeeked={(e) => syncTime(e.currentTarget, true)}\n onEnded={() => notifyEnded()}\n onPlay={() => dispatch({ type: \"MEDIA_PLAY\" })}\n onPause={() => dispatch({ type: \"MEDIA_PAUSE\" })}\n onWaiting={() => dispatch({ type: \"MEDIA_WAITING\" })}\n onCanPlay={() => dispatch({ type: \"MEDIA_CANPLAY\" })}\n onProgress={(e) => syncTime(e.currentTarget, true)}\n onVolumeChange={(e) => {\n const el = e.currentTarget;\n dispatch({\n type: \"MEDIA_VOLUME_SYNC\",\n payload: { volume: el.volume, muted: el.muted },\n });\n }}\n onError={() => {\n const el = audioRef.current;\n const code = el?.error?.code;\n const message =\n code === 1\n ? \"MEDIA_ERR_ABORTED\"\n : code === 2\n ? \"MEDIA_ERR_NETWORK\"\n : code === 3\n ? \"MEDIA_ERR_DECODE\"\n : code === 4\n ? \"MEDIA_ERR_SRC_NOT_SUPPORTED\"\n : \"MEDIA_ERR_UNKNOWN\";\n dispatch({ type: \"MEDIA_ERROR\", payload: { message } });\n }}\n />\n );\n}\n","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(tracks: Track[], target: Track | null | undefined): number {\n const identity = trackIdentity(target);\n if (!identity) return 0;\n const i = tracks.findIndex((track) => trackIdentity(track) === identity);\n return i === -1 ? 0 : i;\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\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: GingerState): 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: GingerState): 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: GingerState): 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(track: Track | null, playlistArtwork?: string | null): string | undefined {\n return track?.artworkUrl ?? playlistArtwork ?? undefined;\n}\n\nexport function resolveAlbumLine(track: Track | null, playlistSubtitle?: string | null): string | undefined {\n return track?.album ?? playlistSubtitle ?? undefined;\n}\n","import type { GingerState, PlaybackUiState, Track } from \"../types\";\nimport { resolveAlbumLine, resolveArtworkUrl } from \"../core/transitions\";\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","import type { ReactElement, ReactNode } from \"react\";\nimport type { DisplayBaseProps, GingerState, Track } from \"../../types\";\nimport { getCurrentTrack } from \"../../internal/selectors\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\n\nexport type TextDisplayProps = DisplayBaseProps & {\n children?: (value: string, state: GingerState) => ReactNode;\n};\n\nexport function createTextDisplay(\n displayName: string,\n select: (state: GingerState) => string | undefined,\n): (props: TextDisplayProps) => ReactElement | null {\n function Comp(props: TextDisplayProps) {\n const state = useGingerState();\n const raw = select(state) ?? \"\";\n const value = raw.trim();\n const { className, style, fallback, empty, children } = props;\n if (!value) {\n const node = empty ?? fallback ?? null;\n return node ? <span className={className} style={style}>{node}</span> : null;\n }\n if (children) return <span className={className} style={style}>{children(value, state)}</span>;\n return (\n <span className={className} style={style}>\n {value}\n </span>\n );\n }\n Comp.displayName = displayName;\n return Comp;\n}\n\nexport function createTrackFieldDisplay(\n displayName: string,\n select: (track: Track | null) => string | undefined,\n): (props: TextDisplayProps) => ReactElement | null {\n return createTextDisplay(displayName, (state) => select(getCurrentTrack(state)));\n}\n","import { createTextDisplay, createTrackFieldDisplay } from \"./createTextDisplay\";\nimport { getCurrentTrack, resolvedAlbumLine } from \"../../internal/selectors\";\n\nexport const Title = createTrackFieldDisplay(\"Ginger.Current.Title\", (t) => t?.title);\nexport const Artist = createTrackFieldDisplay(\"Ginger.Current.Artist\", (t) => t?.artist);\nexport const Album = createTextDisplay(\"Ginger.Current.Album\", (s) => resolvedAlbumLine(s));\nexport const Description = createTrackFieldDisplay(\"Ginger.Current.Description\", (t) => t?.description);\nexport const Copyright = createTextDisplay(\"Ginger.Current.Copyright\", (s) => {\n const t = getCurrentTrack(s);\n return t?.copyright ?? s.playlistMeta?.copyright;\n});\nexport const Genre = createTrackFieldDisplay(\"Ginger.Current.Genre\", (t) => t?.genre);\nexport const Label = createTrackFieldDisplay(\"Ginger.Current.Label\", (t) => t?.label);\nexport const Isrc = createTrackFieldDisplay(\"Ginger.Current.Isrc\", (t) => t?.isrc);\nexport const TrackNumber = createTrackFieldDisplay(\"Ginger.Current.TrackNumber\", (t) =>\n t?.trackNumber != null ? String(t.trackNumber) : undefined,\n);\n","import type { TextDisplayProps } from \"./createTextDisplay\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { getCurrentTrack } from \"../../internal/selectors\";\n\nexport type YearProps = TextDisplayProps & {\n format?: (year: number) => string;\n};\n\nexport function Year({ className, style, fallback, empty, children, format }: YearProps) {\n const state = useGingerState();\n const y = getCurrentTrack(state)?.year;\n if (typeof y !== \"number\" || !Number.isFinite(y)) {\n const node = empty ?? fallback ?? null;\n return node ? <span className={className} style={style}>{node}</span> : null;\n }\n const text = format ? format(y) : String(y);\n if (children) return <span className={className} style={style}>{children(text, state)}</span>;\n return (\n <span className={className} style={style}>\n {text}\n </span>\n );\n}\n\nYear.displayName = \"Ginger.Current.Year\";\n","import type { CSSProperties, ReactNode } from \"react\";\nimport type { DisplayBaseProps, GingerState } from \"../../types\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { getCurrentTrack } from \"../../internal/selectors\";\n\nexport type LyricsProps = DisplayBaseProps & {\n children?: (value: string, state: GingerState) => ReactNode;\n /** When true, preserves internal newlines; trims only leading/trailing whitespace */\n preserveWhitespace?: boolean;\n};\n\nexport function Lyrics({ className, style, fallback, empty, children, preserveWhitespace = true }: LyricsProps) {\n const state = useGingerState();\n const raw = getCurrentTrack(state)?.lyrics ?? \"\";\n const value = preserveWhitespace ? raw.replace(/^\\s+|\\s+$/g, \"\") : raw.trim();\n if (!value) {\n const node = empty ?? fallback ?? null;\n return node ? <span className={className} style={style}>{node}</span> : null;\n }\n const whiteStyle: CSSProperties | undefined = preserveWhitespace ? { whiteSpace: \"pre-wrap\" } : undefined;\n if (children) return <span className={className} style={{ ...whiteStyle, ...style }}>{children(value, state)}</span>;\n return (\n <span className={className} style={{ ...whiteStyle, ...style }}>\n {value}\n </span>\n );\n}\n\nLyrics.displayName = \"Ginger.Current.Lyrics\";\n","import type { TextDisplayProps } from \"./createTextDisplay\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { getCurrentTrack } from \"../../internal/selectors\";\n\nexport type FileUrlProps = TextDisplayProps & {\n /** When false (default), renders nothing unless you explicitly opt in */\n visible?: boolean;\n};\n\nexport function FileUrl({ visible = false, className, style, fallback, empty, children }: FileUrlProps) {\n const state = useGingerState();\n if (!visible) return null;\n const value = getCurrentTrack(state)?.fileUrl ?? \"\";\n if (!value) {\n const node = empty ?? fallback ?? null;\n return node ? <span className={className} style={style}>{node}</span> : null;\n }\n if (children) return <span className={className} style={style}>{children(value, state)}</span>;\n return (\n <span className={className} style={style}>\n {value}\n </span>\n );\n}\n\nFileUrl.displayName = \"Ginger.Current.FileUrl\";\n","import type { CSSProperties, ImgHTMLAttributes } from \"react\";\nimport type { DisplayBaseProps } from \"../../types\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { getCurrentTrack, resolvedArtwork } from \"../../internal/selectors\";\n\nexport type ArtworkProps = DisplayBaseProps &\n Pick<ImgHTMLAttributes<HTMLImageElement>, \"sizes\" | \"loading\" | \"onError\" | \"decoding\"> & {\n /** Remove default wrapper/image styles for fully custom layout. */\n unstyled?: boolean;\n imgStyle?: CSSProperties;\n };\n\nexport function Artwork({\n className,\n style,\n fallback,\n empty,\n sizes,\n loading,\n onError,\n decoding,\n unstyled = false,\n imgStyle,\n}: ArtworkProps) {\n const state = useGingerState();\n const track = getCurrentTrack(state);\n const src = resolvedArtwork(state);\n if (!src) {\n const node = empty ?? fallback ?? null;\n return node ? <span className={className} style={style}>{node}</span> : null;\n }\n const alt = [track?.title, track?.artist].filter(Boolean).join(\" — \") || \"Artwork\";\n return (\n <div\n className={className}\n style={\n unstyled\n ? { ...style }\n : {\n background: \"var(--ginger-artwork-bg, transparent)\",\n borderRadius: \"var(--ginger-artwork-radius, 0)\",\n overflow: \"hidden\",\n ...style,\n }\n }\n >\n <img\n src={src}\n alt={alt}\n sizes={sizes}\n loading={loading}\n decoding={decoding}\n onError={onError}\n style={{\n display: unstyled ? undefined : \"block\",\n width: unstyled ? undefined : \"100%\",\n height: unstyled ? undefined : \"100%\",\n objectFit: unstyled ? undefined : \"cover\",\n ...imgStyle,\n }}\n />\n </div>\n );\n}\n\nArtwork.displayName = \"Ginger.Current.Artwork\";\n","import type { ReactNode } from \"react\";\nimport type { DisplayBaseProps, GingerState } from \"../../types\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\n\nexport type QueueIndexProps = DisplayBaseProps & {\n base?: 0 | 1;\n children?: (value: string, state: GingerState) => ReactNode;\n};\n\nexport function QueueIndex({ base = 0, className, style, fallback, empty, children }: QueueIndexProps) {\n const state = useGingerState();\n const len = state.tracks.length;\n if (len === 0) {\n const node = empty ?? fallback ?? null;\n return node ? <span className={className} style={style}>{node}</span> : null;\n }\n const value = String(state.currentIndex + base);\n if (children) return <span className={className} style={style}>{children(value, state)}</span>;\n return (\n <span className={className} style={style}>\n {value}\n </span>\n );\n}\n\nQueueIndex.displayName = \"Ginger.Current.QueueIndex\";\n\nexport type QueueLengthProps = DisplayBaseProps & {\n children?: (value: string, state: GingerState) => ReactNode;\n};\n\nexport function QueueLength({ className, style, fallback, empty, children }: QueueLengthProps) {\n const state = useGingerState();\n const value = String(state.tracks.length);\n if (state.tracks.length === 0) {\n const node = empty ?? fallback ?? null;\n return node ? <span className={className} style={style}>{node}</span> : null;\n }\n if (children) return <span className={className} style={style}>{children(value, state)}</span>;\n return (\n <span className={className} style={style}>\n {value}\n </span>\n );\n}\n\nQueueLength.displayName = \"Ginger.Current.QueueLength\";\n\nexport type QueuePositionProps = DisplayBaseProps & {\n base?: 0 | 1;\n separator?: string;\n children?: (value: { index: string; length: string; label: string }, state: GingerState) => ReactNode;\n};\n\nexport function QueuePosition({\n base = 0,\n separator = \" / \",\n className,\n style,\n fallback,\n empty,\n children,\n}: QueuePositionProps) {\n const state = useGingerState();\n const len = state.tracks.length;\n if (len === 0) {\n const node = empty ?? fallback ?? null;\n return node ? <span className={className} style={style}>{node}</span> : null;\n }\n const index = String(state.currentIndex + base);\n const length = String(len);\n const label = `${index}${separator}${length}`;\n if (children)\n return (\n <span className={className} style={style}>\n {children({ index, length, label }, state)}\n </span>\n );\n return (\n <span className={className} style={style}>\n {label}\n </span>\n );\n}\n\nQueuePosition.displayName = \"Ginger.Current.QueuePosition\";\n","export function formatMmSs(seconds: number): string {\n if (!Number.isFinite(seconds) || seconds < 0) return \"0:00\";\n const s = Math.floor(seconds % 60);\n const m = Math.floor(seconds / 60);\n return `${m}:${s.toString().padStart(2, \"0\")}`;\n}\n","import type { ReactElement, ReactNode } from \"react\";\nimport type { DisplayBaseProps, GingerState } from \"../../types\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { effectiveDuration, effectiveRemaining, progressFraction } from \"../../internal/selectors\";\nimport { formatMmSs } from \"../../internal/formatTime\";\n\nexport type TimeTextProps = DisplayBaseProps & {\n format?: (seconds: number) => string;\n children?: (value: string, state: GingerState) => ReactNode;\n};\n\nfunction renderTime(\n valueSeconds: number,\n state: GingerState,\n props: TimeTextProps,\n): ReactElement | null {\n const { className, style, fallback, empty, children, format = formatMmSs } = props;\n if (!(valueSeconds >= 0) || !Number.isFinite(valueSeconds)) {\n const node = empty ?? fallback ?? null;\n return node ? <span className={className} style={style}>{node}</span> : null;\n }\n const text = format(valueSeconds);\n if (children) return <span className={className} style={style}>{children(text, state)}</span>;\n return (\n <span className={className} style={style}>\n {text}\n </span>\n );\n}\n\nexport function Elapsed(props: TimeTextProps) {\n const state = useGingerState();\n return renderTime(state.currentTime, state, props);\n}\n\nElapsed.displayName = \"Ginger.Current.Elapsed\";\n\nexport function Duration(props: TimeTextProps) {\n const state = useGingerState();\n return renderTime(effectiveDuration(state), state, props);\n}\n\nDuration.displayName = \"Ginger.Current.Duration\";\n\nexport function Remaining(props: TimeTextProps) {\n const state = useGingerState();\n return renderTime(effectiveRemaining(state), state, props);\n}\n\nRemaining.displayName = \"Ginger.Current.Remaining\";\n\nexport type ProgressProps = DisplayBaseProps & {\n children?: (value: { fraction: number; currentTime: number; duration: number }, state: GingerState) => ReactNode;\n};\n\nexport function Progress({ className, style, fallback, empty, children }: ProgressProps) {\n const state = useGingerState();\n const duration = effectiveDuration(state);\n const fraction = progressFraction(state);\n if (!(duration > 0)) {\n const node = empty ?? fallback ?? null;\n return node ? <span className={className} style={style}>{node}</span> : null;\n }\n if (children)\n return (\n <span className={className} style={style}>\n {children({ fraction, currentTime: state.currentTime, duration }, state)}\n </span>\n );\n return (\n <span className={className} style={style}>\n {`${Math.round(fraction * 100)}%`}\n </span>\n );\n}\n\nProgress.displayName = \"Ginger.Current.Progress\";\n\nexport type TimeRailProps = DisplayBaseProps & {\n /** 0-1 height in px for the rail */\n height?: number;\n /** When true, shows a buffered range behind the progress fill (uses `bufferedFraction`). */\n showBuffered?: boolean;\n /** Remove default rail styles and render only inline width values. */\n unstyled?: boolean;\n};\n\nexport function TimeRail({\n className,\n style,\n height = 4,\n showBuffered = false,\n unstyled = false,\n}: TimeRailProps) {\n const state = useGingerState();\n const progressPct = `${Math.round(progressFraction(state) * 100)}%`;\n const bufPct = `${Math.round(Math.min(1, Math.max(0, state.bufferedFraction)) * 100)}%`;\n return (\n <div\n className={className}\n style={\n unstyled\n ? { ...style }\n : {\n width: \"100%\",\n height,\n background: \"var(--ginger-muted-color, #e5e7eb)\",\n borderRadius: 999,\n overflow: \"hidden\",\n position: \"relative\",\n ...style,\n }\n }\n aria-hidden\n >\n {showBuffered ? (\n <div\n style={{\n position: unstyled ? undefined : \"absolute\",\n left: unstyled ? undefined : 0,\n top: unstyled ? undefined : 0,\n height: unstyled ? undefined : \"100%\",\n width: bufPct,\n background: unstyled ? undefined : \"var(--ginger-buffer-color, rgba(107, 114, 128, 0.35))\",\n }}\n />\n ) : null}\n <div\n style={{\n position: unstyled ? undefined : \"relative\",\n width: progressPct,\n height: unstyled ? undefined : \"100%\",\n background: unstyled ? undefined : \"var(--ginger-primary-color, #111827)\",\n }}\n />\n </div>\n );\n}\n\nTimeRail.displayName = \"Ginger.Current.TimeRail\";\n\nexport type BufferRailProps = DisplayBaseProps & {\n height?: number;\n /** Remove default rail styles and render only buffered width value. */\n unstyled?: boolean;\n};\n\n/** Buffered portion of the timeline (0…`bufferedFraction`); pair with `TimeRail` or use alone. */\nexport function BufferRail({ className, style, height = 4, unstyled = false }: BufferRailProps) {\n const state = useGingerState();\n const bufPct = `${Math.round(Math.min(1, Math.max(0, state.bufferedFraction)) * 100)}%`;\n return (\n <div\n className={className}\n style={\n unstyled\n ? { ...style }\n : {\n width: \"100%\",\n height,\n background: \"var(--ginger-muted-color, #e5e7eb)\",\n borderRadius: 999,\n overflow: \"hidden\",\n ...style,\n }\n }\n aria-hidden\n >\n <div\n style={{\n width: bufPct,\n height: unstyled ? undefined : \"100%\",\n background: unstyled ? undefined : \"var(--ginger-buffer-color, rgba(107, 114, 128, 0.35))\",\n }}\n />\n </div>\n );\n}\n\nBufferRail.displayName = \"Ginger.Current.BufferRail\";\n","import type { ReactNode } from \"react\";\nimport type { DisplayBaseProps, GingerState, PlaybackUiState } from \"../../types\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\nimport { derivePlaybackUiState } from \"../../internal/selectors\";\n\nexport type PlaybackStateProps = DisplayBaseProps & {\n children?: (value: PlaybackUiState, state: GingerState) => ReactNode;\n};\n\nexport function PlaybackState({ className, style, fallback, empty, children }: PlaybackStateProps) {\n const state = useGingerState();\n const value = derivePlaybackUiState(state);\n if (children) return <span className={className} style={style}>{children(value, state)}</span>;\n return (\n <span className={className} style={style}>\n {value}\n </span>\n );\n}\n\nPlaybackState.displayName = \"Ginger.Current.PlaybackState\";\n\nexport type ErrorMessageProps = DisplayBaseProps & {\n live?: \"polite\" | \"assertive\" | \"off\";\n children?: (value: string, state: GingerState) => ReactNode;\n};\n\nexport function ErrorMessage({ className, style, fallback, empty, live = \"polite\", children }: ErrorMessageProps) {\n const state = useGingerState();\n const value = state.errorMessage ?? \"\";\n if (!value) {\n const node = empty ?? fallback ?? null;\n return node ? <span className={className} style={style}>{node}</span> : null;\n }\n if (children) {\n return (\n <span className={className} style={style} aria-live={live}>\n {children(value, state)}\n </span>\n );\n }\n return (\n <span className={className} style={style} aria-live={live}>\n {value}\n </span>\n );\n}\n\nErrorMessage.displayName = \"Ginger.Current.ErrorMessage\";\n","import { createContext, useContext, type ReactNode } from \"react\";\nimport type { GingerLocaleMessages } from \"../types\";\n\nexport const defaultGingerLocale: GingerLocaleMessages = {\n seek: \"Seek\",\n volume: \"Volume\",\n playbackSpeed: \"Playback speed\",\n nextTrack: \"Next track\",\n previousTrack: \"Previous track\",\n shuffle: \"Shuffle\",\n mute: \"Mute\",\n unmute: \"Unmute\",\n play: \"Play\",\n pause: \"Pause\",\n repeat: {\n off: \"Repeat off\",\n all: \"Repeat all\",\n one: \"Repeat one\",\n },\n playbackRateNormal: \"1× normal\",\n playbackRateTimes: (rate) => `${rate}×`,\n};\n\nfunction mergeLocale(partial?: Partial<GingerLocaleMessages>): GingerLocaleMessages {\n if (!partial) return defaultGingerLocale;\n return {\n ...defaultGingerLocale,\n ...partial,\n repeat: { ...defaultGingerLocale.repeat, ...partial.repeat },\n };\n}\n\nconst GingerLocaleContext = createContext<GingerLocaleMessages>(defaultGingerLocale);\n\nexport function GingerLocaleProvider({\n locale,\n children,\n}: {\n locale?: Partial<GingerLocaleMessages>;\n children: ReactNode;\n}) {\n const value = mergeLocale(locale);\n return <GingerLocaleContext.Provider value={value}>{children}</GingerLocaleContext.Provider>;\n}\n\nexport function useGingerLocale(): GingerLocaleMessages {\n return useContext(GingerLocaleContext);\n}\n","import { useMemo } from \"react\";\nimport type { FormEvent } from \"react\";\nimport type { GingerState } from \"../types\";\nimport { gingerStateFromContextValues, useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\nimport { effectiveDuration } from \"../internal/selectors\";\nimport { formatMmSs } from \"../internal/formatTime\";\nimport { useGingerLocale } from \"../context/GingerLocaleContext\";\n\nexport type SeekBarBinding = {\n state: GingerState;\n value: number;\n min: number;\n max: number;\n step: \"any\";\n ariaValueText: string;\n ariaLabel: string;\n onSeekInput: (e: FormEvent<HTMLInputElement>) => void;\n onSeekChange: (e: FormEvent<HTMLInputElement>) => void;\n};\n\n/** Headless seek slider: bind return value to `<input type=\"range\" />` or your own component. */\nexport function useSeekBarBinding(): SeekBarBinding {\n const pb = useGingerPlayback();\n const md = useGingerMedia();\n const locale = useGingerLocale();\n const state = useMemo(() => gingerStateFromContextValues(pb, md), [pb, md]);\n const duration = effectiveDuration(state);\n const value = duration > 0 ? state.currentTime : 0;\n const numericValue = Number.isFinite(value) ? value : 0;\n const ariaValueText =\n duration > 0\n ? `${formatMmSs(numericValue)} of ${formatMmSs(duration)}`\n : formatMmSs(numericValue);\n\n const onSeekInput = (e: FormEvent<HTMLInputElement>) => {\n md.seek(Number(e.currentTarget.value));\n };\n\n return {\n state,\n value: numericValue,\n min: 0,\n max: duration > 0 ? duration : 1,\n step: \"any\",\n ariaValueText,\n ariaLabel: locale.seek,\n onSeekInput,\n onSeekChange: onSeekInput,\n };\n}\n\nexport type VolumeBinding = {\n state: GingerState;\n value: number;\n min: number;\n max: number;\n step: \"any\";\n ariaValueText: string;\n ariaLabel: string;\n onVolumeInput: (e: FormEvent<HTMLInputElement>) => void;\n onVolumeChange: (e: FormEvent<HTMLInputElement>) => void;\n};\n\n/** Headless volume slider. */\nexport function useVolumeSlider(): VolumeBinding {\n const pb = useGingerPlayback();\n const md = useGingerMedia();\n const locale = useGingerLocale();\n const state = useMemo(() => gingerStateFromContextValues(pb, md), [pb, md]);\n\n const onVolumeInput = (e: FormEvent<HTMLInputElement>) => {\n md.setVolume(Number(e.currentTarget.value));\n };\n\n return {\n state,\n value: state.volume,\n min: 0,\n max: 1,\n step: \"any\",\n ariaValueText: `${Math.round(state.volume * 100)}%`,\n ariaLabel: locale.volume,\n onVolumeInput,\n onVolumeChange: onVolumeInput,\n };\n}\n\nexport type PlayPauseBinding = {\n isPaused: boolean;\n toggle: () => void;\n /** Resolved aria label for the button’s *next* action (play vs pause). */\n ariaLabel: string;\n};\n\n/** Headless play/pause control; use with `playAriaLabel` / `pauseAriaLabel` from locale or custom strings. */\nexport function usePlayPauseBinding(options?: {\n playAriaLabel?: string;\n pauseAriaLabel?: string;\n}): PlayPauseBinding {\n const pb = useGingerPlayback();\n const locale = useGingerLocale();\n const playL = options?.playAriaLabel ?? locale.play;\n const pauseL = options?.pauseAriaLabel ?? locale.pause;\n return {\n isPaused: pb.isPaused,\n toggle: pb.togglePlayPause,\n ariaLabel: pb.isPaused ? playL : pauseL,\n };\n}\n","import { useMemo } from \"react\";\nimport type {\n ButtonHTMLAttributes,\n CSSProperties,\n InputHTMLAttributes,\n ReactNode,\n SelectHTMLAttributes,\n} from \"react\";\nimport { useGingerLocale } from \"../../context/GingerLocaleContext\";\nimport { useGingerMedia, useGingerPlayback } from \"../../context/GingerSplitContexts\";\nimport { usePlayPauseBinding, useSeekBarBinding, useVolumeSlider } from \"../../hooks/useControlBindings\";\n\nexport type PlayPauseProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n /** Optional labels; still headless—defaults are text for a11y */\n playLabel?: ReactNode;\n pauseLabel?: ReactNode;\n /** Screen-reader label when paused (playing would start); defaults to match `playLabel` when it is a string */\n playAriaLabel?: string;\n /** Screen-reader label when playing (action would pause); defaults to match `pauseLabel` when it is a string */\n pauseAriaLabel?: string;\n};\n\nexport function PlayPause({\n playLabel = \"Play\",\n pauseLabel = \"Pause\",\n playAriaLabel,\n pauseAriaLabel,\n type = \"button\",\n onClick,\n ...rest\n}: PlayPauseProps) {\n const locale = useGingerLocale();\n const defaultPlayAria = typeof playLabel === \"string\" ? playLabel : locale.play;\n const defaultPauseAria = typeof pauseLabel === \"string\" ? pauseLabel : locale.pause;\n const b = usePlayPauseBinding({\n playAriaLabel: playAriaLabel ?? defaultPlayAria,\n pauseAriaLabel: pauseAriaLabel ?? defaultPauseAria,\n });\n return (\n <button\n {...rest}\n type={type}\n aria-label={b.ariaLabel}\n onClick={(e) => { b.toggle(); onClick?.(e); }}\n >\n {b.isPaused ? playLabel : pauseLabel}\n </button>\n );\n}\n\nPlayPause.displayName = \"Ginger.Control.PlayPause\";\n\nexport type RepeatProps = ButtonHTMLAttributes<HTMLButtonElement>;\n\nexport function Repeat({ type = \"button\", onClick, ...rest }: RepeatProps) {\n const { repeatMode, cycleRepeat } = useGingerPlayback();\n const locale = useGingerLocale();\n const label = locale.repeat[repeatMode];\n return (\n <button {...rest} type={type} aria-label={label} onClick={(e) => { cycleRepeat(); onClick?.(e); }}>\n {label}\n </button>\n );\n}\n\nRepeat.displayName = \"Ginger.Control.Repeat\";\n\nexport type NextProps = ButtonHTMLAttributes<HTMLButtonElement>;\nexport function Next({ type = \"button\", children = \"Next\", onClick, ...rest }: NextProps) {\n const { next } = useGingerPlayback();\n const locale = useGingerLocale();\n return (\n <button {...rest} type={type} aria-label={locale.nextTrack} onClick={(e) => { next(); onClick?.(e); }}>\n {children}\n </button>\n );\n}\nNext.displayName = \"Ginger.Control.Next\";\n\nexport type PreviousProps = ButtonHTMLAttributes<HTMLButtonElement>;\nexport function Previous({ type = \"button\", children = \"Previous\", onClick, ...rest }: PreviousProps) {\n const { prev } = useGingerPlayback();\n const locale = useGingerLocale();\n return (\n <button {...rest} type={type} aria-label={locale.previousTrack} onClick={(e) => { prev(); onClick?.(e); }}>\n {children}\n </button>\n );\n}\nPrevious.displayName = \"Ginger.Control.Previous\";\n\nexport type ShuffleProps = ButtonHTMLAttributes<HTMLButtonElement>;\nexport function Shuffle({ type = \"button\", children = \"Shuffle\", onClick, ...rest }: ShuffleProps) {\n const { isShuffled, toggleShuffle } = useGingerPlayback();\n const locale = useGingerLocale();\n return (\n <button\n {...rest}\n type={type}\n aria-pressed={isShuffled}\n aria-label={locale.shuffle}\n onClick={(e) => { toggleShuffle(); onClick?.(e); }}\n >\n {children}\n </button>\n );\n}\nShuffle.displayName = \"Ginger.Control.Shuffle\";\n\nexport type SeekBarProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\" | \"value\" | \"onChange\" | \"onInput\" | \"min\" | \"max\" | \"step\"\n> & {\n /** Remove default width style for fully custom styling. */\n unstyled?: boolean;\n inputStyle?: CSSProperties;\n};\n\nexport function SeekBar({ inputStyle, style, unstyled = false, ...rest }: SeekBarProps) {\n const b = useSeekBarBinding();\n const mergedStyle = unstyled ? { ...style, ...inputStyle } : { width: \"100%\", ...style, ...inputStyle };\n return (\n <input\n {...rest}\n type=\"range\"\n min={b.min}\n max={b.max}\n step={b.step}\n value={b.value}\n aria-label={b.ariaLabel}\n aria-valuetext={b.ariaValueText}\n onInput={b.onSeekInput}\n onChange={b.onSeekChange}\n style={mergedStyle}\n />\n );\n}\n\nSeekBar.displayName = \"Ginger.Control.SeekBar\";\n\nexport type VolumeProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n \"type\" | \"value\" | \"onChange\" | \"onInput\" | \"min\" | \"max\" | \"step\"\n> & {\n /** Remove default width style for fully custom styling. */\n unstyled?: boolean;\n inputStyle?: CSSProperties;\n};\n\nexport function Volume({ inputStyle, style, unstyled = false, ...rest }: VolumeProps) {\n const b = useVolumeSlider();\n const mergedStyle = unstyled ? { ...style, ...inputStyle } : { width: \"100%\", ...style, ...inputStyle };\n return (\n <input\n {...rest}\n type=\"range\"\n min={b.min}\n max={b.max}\n step={b.step}\n value={b.value}\n aria-label={b.ariaLabel}\n aria-valuetext={b.ariaValueText}\n onInput={b.onVolumeInput}\n onChange={b.onVolumeChange}\n style={mergedStyle}\n />\n );\n}\n\nVolume.displayName = \"Ginger.Control.Volume\";\n\nexport type MuteProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n muteLabel?: ReactNode;\n unmuteLabel?: ReactNode;\n};\n\nexport function Mute({\n muteLabel,\n unmuteLabel,\n type = \"button\",\n onClick,\n ...rest\n}: MuteProps) {\n const { muted, toggleMute } = useGingerMedia();\n const locale = useGingerLocale();\n const m = muteLabel ?? locale.mute;\n const u = unmuteLabel ?? locale.unmute;\n return (\n <button\n {...rest}\n type={type}\n aria-pressed={muted}\n aria-label={muted ? locale.unmute : locale.mute}\n onClick={(e) => { toggleMute(); onClick?.(e); }}\n >\n {muted ? u : m}\n </button>\n );\n}\n\nMute.displayName = \"Ginger.Control.Mute\";\n\nconst defaultRates = [0.5, 0.75, 1, 1.25, 1.5, 2] as const;\n\nexport type PlaybackRateProps = Omit<SelectHTMLAttributes<HTMLSelectElement>, \"value\" | \"onChange\"> & {\n /** Playback speed options (default: 0.5 … 2) */\n rates?: readonly number[];\n};\n\nexport function PlaybackRate({ rates = defaultRates, style, ...rest }: PlaybackRateProps) {\n const { playbackRate, setPlaybackRate } = useGingerMedia();\n const locale = useGingerLocale();\n const options = useMemo(\n () => Array.from(new Set([...rates, playbackRate])).sort((a, b) => a - b),\n [rates, playbackRate],\n );\n return (\n <select\n {...rest}\n aria-label={locale.playbackSpeed}\n value={String(playbackRate)}\n style={style}\n onChange={(e) => setPlaybackRate(Number(e.currentTarget.value))}\n >\n {options.map((r) => (\n <option key={r} value={String(r)}>\n {r === 1 ? locale.playbackRateNormal : locale.playbackRateTimes(r)}\n </option>\n ))}\n </select>\n );\n}\n\nPlaybackRate.displayName = \"Ginger.Control.PlaybackRate\";\n","import {\n createContext,\n useContext,\n type ButtonHTMLAttributes,\n type CSSProperties,\n type HTMLAttributes,\n type LiHTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { useGingerPlayback } from \"../../context/GingerSplitContexts\";\nimport { trackIdentity } from \"../../core/queue\";\nimport type { Track } from \"../../types\";\n\nexport type GingerPlaylistConfig = {\n playOnSelect: boolean;\n};\n\nconst GingerPlaylistConfigContext = createContext<GingerPlaylistConfig | null>(null);\n\nfunction usePlaylistConfig(): GingerPlaylistConfig {\n const ctx = useContext(GingerPlaylistConfigContext);\n if (!ctx) {\n throw new Error(\"Ginger.Playlist.Track must be used inside <Ginger.Playlist>\");\n }\n return ctx;\n}\n\nexport type GingerPlaylistProps = Omit<HTMLAttributes<HTMLUListElement>, \"children\"> & {\n children?: ReactNode;\n /** Remove default list/row styles for fully custom playlist styling. */\n unstyled?: boolean;\n rowStyle?: CSSProperties;\n /**\n * Used only in **auto** mode (no custom `children`). Ignored when you pass custom `children`\n * (manual mode); use `Ginger.Playlist.Track` for each row instead.\n */\n renderTrack?: (track: Track, index: number, isActive: boolean) => ReactNode;\n /** When true (default), clicking a row selects that index and starts playback */\n playOnSelect?: boolean;\n};\n\n/**\n * - **Auto mode** (no `children`): maps `state.tracks` to rows (optional `renderTrack`).\n * - **Manual mode** (`children` defined): renders `<ul>{children}</ul>`; map `state.tracks` yourself\n * with `Ginger.Playlist.Track` for each index.\n */\nexport function GingerPlaylist({\n children,\n unstyled = false,\n rowStyle,\n renderTrack,\n playOnSelect = true,\n style,\n ...rest\n}: GingerPlaylistProps) {\n const { tracks, currentIndex, playTrackAt, selectTrackAt } = useGingerPlayback();\n\n const listStyle: CSSProperties = unstyled\n ? { ...style }\n : {\n listStyle: \"none\",\n margin: 0,\n padding: 0,\n fontFamily: \"var(--ginger-font-family, system-ui, sans-serif)\",\n fontSize: \"var(--ginger-font-size, 14px)\",\n color: \"var(--ginger-primary-color, #111827)\",\n ...style,\n };\n\n const manual = children !== undefined;\n\n if (manual) {\n return (\n <GingerPlaylistConfigContext.Provider value={{ playOnSelect }}>\n <ul style={listStyle} {...rest}>\n {children}\n </ul>\n </GingerPlaylistConfigContext.Provider>\n );\n }\n\n return (\n <GingerPlaylistConfigContext.Provider value={{ playOnSelect }}>\n <ul style={listStyle} {...rest}>\n {tracks.map((track, index) => {\n const active = index === currentIndex;\n return (\n <li key={`${index}-${trackIdentity(track)}`}>\n <button\n type=\"button\"\n onClick={() => {\n if (playOnSelect) playTrackAt(index);\n else selectTrackAt(index);\n }}\n style={{\n width: unstyled ? undefined : \"100%\",\n textAlign: unstyled ? undefined : \"left\",\n border: unstyled ? undefined : \"none\",\n background: unstyled\n ? undefined\n : active\n ? \"var(--ginger-playlist-active-bg, rgba(17, 24, 39, 0.06))\"\n : \"transparent\",\n color: unstyled ? undefined : \"inherit\",\n font: unstyled ? undefined : \"inherit\",\n cursor: unstyled ? undefined : \"pointer\",\n padding: unstyled ? undefined : \"var(--ginger-playlist-row-padding, 6px 8px)\",\n ...rowStyle,\n }}\n >\n {renderTrack ? (\n renderTrack(track, index, active)\n ) : (\n <span>\n {track.title}\n {track.artist ? ` — ${track.artist}` : \"\"}\n </span>\n )}\n </button>\n </li>\n );\n })}\n </ul>\n </GingerPlaylistConfigContext.Provider>\n );\n}\n\nGingerPlaylist.displayName = \"Ginger.Playlist\";\n\nexport type GingerPlaylistTrackProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"type\"> & {\n index: number;\n /** Remove default row button styles for fully custom styling. */\n unstyled?: boolean;\n /** Optional wrapper for the row; defaults to a plain `<li>` */\n liProps?: LiHTMLAttributes<HTMLLIElement>;\n};\n\nexport function GingerPlaylistTrack({\n index,\n unstyled = false,\n className,\n style,\n children,\n liProps,\n onClick,\n ...buttonRest\n}: GingerPlaylistTrackProps) {\n const { playOnSelect } = usePlaylistConfig();\n const { tracks, currentIndex, playTrackAt, selectTrackAt } = useGingerPlayback();\n const active = index === currentIndex;\n const track = tracks[index];\n const defaultLabel =\n track != null ? (\n <span>\n {track.title}\n {track.artist ? ` — ${track.artist}` : \"\"}\n </span>\n ) : null;\n\n return (\n <li {...liProps}>\n <button\n type=\"button\"\n aria-current={active ? \"true\" : undefined}\n data-ginger-active={active || undefined}\n className={className}\n style={{\n width: unstyled ? undefined : \"100%\",\n textAlign: unstyled ? undefined : \"left\",\n border: unstyled ? undefined : \"none\",\n background: unstyled\n ? undefined\n : active\n ? \"var(--ginger-playlist-active-bg, rgba(17, 24, 39, 0.06))\"\n : \"transparent\",\n color: unstyled ? undefined : \"inherit\",\n font: unstyled ? undefined : \"inherit\",\n cursor: unstyled ? undefined : \"pointer\",\n padding: unstyled ? undefined : \"var(--ginger-playlist-row-padding, 6px 8px)\",\n ...style,\n }}\n {...buttonRest}\n onClick={(e) => {\n onClick?.(e);\n if (e.defaultPrevented) return;\n if (playOnSelect) playTrackAt(index);\n else selectTrackAt(index);\n }}\n >\n {children ?? defaultLabel}\n </button>\n </li>\n );\n}\n\nGingerPlaylistTrack.displayName = \"Ginger.Playlist.Track\";\n\nexport const GingerPlaylistCompound = Object.assign(GingerPlaylist, {\n Track: GingerPlaylistTrack,\n});\n","import type { CSSProperties } from \"react\";\nimport type { DisplayBaseProps } from \"../../types\";\nimport { createTextDisplay } from \"../current/createTextDisplay\";\nimport { useGingerState } from \"../../context/GingerSplitContexts\";\n\nexport const Title = createTextDisplay(\"Ginger.Queue.Title\", (s) => s.playlistMeta?.title);\nexport const Subtitle = createTextDisplay(\"Ginger.Queue.Subtitle\", (s) => s.playlistMeta?.subtitle);\nexport const Description = createTextDisplay(\"Ginger.Queue.Description\", (s) => s.playlistMeta?.description);\nexport const Copyright = createTextDisplay(\"Ginger.Queue.Copyright\", (s) => s.playlistMeta?.copyright);\n\nexport type QueueArtworkProps = DisplayBaseProps & {\n /** Remove default wrapper/image styles for fully custom layout. */\n unstyled?: boolean;\n imgStyle?: CSSProperties;\n};\n\nexport function Artwork({ className, style, fallback, empty, unstyled = false, imgStyle }: QueueArtworkProps) {\n const state = useGingerState();\n const src = state.playlistMeta?.artworkUrl;\n if (!src) {\n const node = empty ?? fallback ?? null;\n return node ? <span className={className} style={style}>{node}</span> : null;\n }\n const alt = state.playlistMeta?.title ?? \"Playlist artwork\";\n return (\n <span\n className={className}\n style={\n unstyled\n ? { ...style }\n : {\n display: \"inline-block\",\n background: \"var(--ginger-artwork-bg, #f3f4f6)\",\n borderRadius: \"var(--ginger-artwork-radius, 6px)\",\n overflow: \"hidden\",\n ...style,\n }\n }\n >\n <img\n src={src}\n alt={alt}\n style={{\n display: unstyled ? undefined : \"block\",\n width: unstyled ? undefined : \"100%\",\n height: unstyled ? undefined : \"100%\",\n objectFit: unstyled ? undefined : \"cover\",\n ...imgStyle,\n }}\n />\n </span>\n );\n}\n\nArtwork.displayName = \"Ginger.Queue.Artwork\";\n","import type { GingerAction, GingerState, RepeatMode, Track } from \"../types\";\nimport {\n addNextTrack,\n clampIndex,\n findIndexByTrackIdentity,\n insertTrackAt,\n moveTrack,\n removeTrackAt,\n shuffleWithAnchor,\n} from \"./queue\";\nimport { computeNextIndex, computePrevIndex, cycleRepeatMode } from \"./transitions\";\n\nexport function clampVolume(v: number): number {\n if (!Number.isFinite(v)) return 1;\n return Math.min(1, Math.max(0, v));\n}\n\nexport function clampPlaybackRate(r: number): number {\n if (!Number.isFinite(r)) return 1;\n return Math.min(4, Math.max(0.25, r));\n}\n\n/** Reset when the active track / position changes; keeps volume / mute / speed */\nconst resetTimingOnly = {\n currentTime: 0,\n duration: 0,\n bufferedFraction: 0,\n isBuffering: false,\n errorMessage: null as string | null,\n};\n\nconst defaultMedia = {\n ...resetTimingOnly,\n volume: 1,\n muted: false,\n playbackRate: 1,\n};\n\nexport function createInitialState(params: {\n tracks: Track[];\n currentIndex?: number;\n playlistMeta?: GingerState[\"playlistMeta\"];\n isPaused?: boolean;\n isShuffled?: boolean;\n repeatMode?: RepeatMode;\n playbackMode?: GingerState[\"playbackMode\"];\n volume?: number;\n muted?: boolean;\n playbackRate?: number;\n}): GingerState {\n const tracks = [...params.tracks];\n let currentIndex = clampIndex(params.currentIndex ?? 0, tracks.length);\n let originalTracks: Track[] | null = null;\n let ordered = tracks;\n\n if (params.isShuffled && tracks.length > 1) {\n originalTracks = [...tracks];\n ordered = shuffleWithAnchor(tracks, currentIndex);\n currentIndex = 0;\n }\n\n return {\n tracks: ordered,\n currentIndex,\n playbackMode: params.playbackMode ?? \"playlist\",\n isPaused: params.isPaused ?? true,\n isShuffled: Boolean(params.isShuffled && ordered.length > 1),\n repeatMode: params.repeatMode ?? \"off\",\n originalTracks,\n playlistMeta: params.playlistMeta ?? null,\n ...defaultMedia,\n volume: clampVolume(params.volume ?? 1),\n muted: params.muted ?? false,\n playbackRate: clampPlaybackRate(params.playbackRate ?? 1),\n };\n}\n\nexport function gingerReducer(state: GingerState, action: GingerAction): GingerState {\n switch (action.type) {\n case \"INIT\": {\n const {\n tracks,\n currentIndex,\n playlistMeta,\n isPaused,\n isShuffled,\n repeatMode,\n playbackMode,\n volume,\n muted,\n playbackRate,\n } = action.payload;\n return createInitialState({\n tracks,\n currentIndex,\n playlistMeta: playlistMeta ?? null,\n isPaused: isPaused ?? true,\n isShuffled: isShuffled ?? false,\n repeatMode: repeatMode ?? \"off\",\n playbackMode: playbackMode ?? \"playlist\",\n volume,\n muted,\n playbackRate,\n });\n }\n case \"SET_QUEUE\": {\n const { tracks, currentIndex } = action.payload;\n const next = [...tracks];\n const idx = clampIndex(currentIndex ?? state.currentIndex, next.length);\n return {\n ...state,\n tracks: next,\n currentIndex: idx,\n isShuffled: false,\n originalTracks: null,\n ...resetTimingOnly,\n };\n }\n case \"INSERT_TRACK\": {\n const insertIndex = action.payload.index ?? state.tracks.length;\n const tracks = insertTrackAt(state.tracks, action.payload.track, insertIndex);\n if (action.payload.autoPlay) {\n const idx = clampIndex(insertIndex, tracks.length);\n return {\n ...state,\n tracks,\n currentIndex: idx,\n isShuffled: false,\n originalTracks: null,\n isPaused: false,\n ...resetTimingOnly,\n };\n }\n const currentIndex =\n insertIndex <= state.currentIndex ? state.currentIndex + 1 : state.currentIndex;\n return {\n ...state,\n tracks,\n isShuffled: false,\n originalTracks: null,\n currentIndex: clampIndex(currentIndex, tracks.length),\n };\n }\n case \"REMOVE_TRACK\": {\n const index = action.payload.index;\n const tracks = removeTrackAt(state.tracks, index);\n const currentIndex =\n index < state.currentIndex\n ? state.currentIndex - 1\n : index === state.currentIndex\n ? Math.min(state.currentIndex, Math.max(0, tracks.length - 1))\n : state.currentIndex;\n return {\n ...state,\n tracks,\n isShuffled: false,\n originalTracks: null,\n currentIndex: clampIndex(currentIndex, tracks.length),\n ...(index === state.currentIndex ? resetTimingOnly : {}),\n };\n }\n case \"MOVE_TRACK\": {\n const { fromIndex, toIndex } = action.payload;\n const tracks = moveTrack(state.tracks, fromIndex, toIndex);\n let currentIndex = state.currentIndex;\n if (state.currentIndex === fromIndex) currentIndex = toIndex;\n else if (fromIndex < state.currentIndex && toIndex >= state.currentIndex) currentIndex -= 1;\n else if (fromIndex > state.currentIndex && toIndex <= state.currentIndex) currentIndex += 1;\n return {\n ...state,\n tracks,\n isShuffled: false,\n originalTracks: null,\n currentIndex: clampIndex(currentIndex, tracks.length),\n };\n }\n case \"ADD_NEXT\": {\n const tracks = addNextTrack(state.tracks, state.currentIndex, action.payload.track);\n return {\n ...state,\n tracks,\n isShuffled: false,\n originalTracks: null,\n };\n }\n case \"SET_INDEX\": {\n const idx = clampIndex(action.payload.index, state.tracks.length);\n const ap = action.payload.autoPlay;\n const isPaused =\n ap === true ? false : ap === false ? true : state.isPaused;\n return {\n ...state,\n currentIndex: idx,\n ...resetTimingOnly,\n isPaused,\n };\n }\n case \"PLAY\":\n return { ...state, isPaused: false };\n case \"PAUSE\":\n return { ...state, isPaused: true };\n case \"TOGGLE_PAUSE\":\n return { ...state, isPaused: !state.isPaused };\n case \"SET_REPEAT\":\n return { ...state, repeatMode: action.payload };\n case \"CYCLE_REPEAT\":\n return { ...state, repeatMode: cycleRepeatMode(state.repeatMode) };\n case \"TOGGLE_SHUFFLE\": {\n if (state.tracks.length <= 1) return { ...state, isShuffled: false, originalTracks: null };\n if (!state.isShuffled) {\n const snapshot = [...state.tracks];\n const shuffled = shuffleWithAnchor(snapshot, state.currentIndex);\n return {\n ...state,\n isShuffled: true,\n originalTracks: snapshot,\n tracks: shuffled,\n currentIndex: 0,\n };\n }\n const restored = state.originalTracks ? [...state.originalTracks] : [...state.tracks];\n const current = state.tracks[state.currentIndex];\n const newIndex = findIndexByTrackIdentity(restored, current);\n return {\n ...state,\n isShuffled: false,\n originalTracks: null,\n tracks: restored,\n currentIndex: clampIndex(newIndex, restored.length),\n };\n }\n case \"NEXT\": {\n const nextIndex = computeNextIndex(state);\n const same = nextIndex === state.currentIndex;\n return {\n ...state,\n currentIndex: nextIndex,\n ...(same ? {} : resetTimingOnly),\n isPaused: same ? state.isPaused : false,\n };\n }\n case \"PREV\": {\n const prevIndex = computePrevIndex(state);\n const same = prevIndex === state.currentIndex;\n return {\n ...state,\n currentIndex: prevIndex,\n ...(same ? {} : resetTimingOnly),\n isPaused: same ? state.isPaused : false,\n };\n }\n case \"MEDIA_TIME_UPDATE\":\n return {\n ...state,\n currentTime: action.payload.currentTime,\n duration: Number.isFinite(action.payload.duration) ? action.payload.duration : state.duration,\n bufferedFraction: action.payload.bufferedFraction,\n isBuffering: false,\n };\n case \"MEDIA_LOADED_METADATA\":\n return {\n ...state,\n duration: Number.isFinite(action.payload.duration) ? action.payload.duration : state.duration,\n bufferedFraction: action.payload.bufferedFraction,\n errorMessage: null,\n };\n case \"SET_PLAYLIST_META\":\n return { ...state, playlistMeta: action.payload };\n case \"MEDIA_ERROR\":\n return {\n ...state,\n errorMessage: action.payload.message,\n isPaused: true,\n isBuffering: false,\n };\n case \"MEDIA_WAITING\":\n return { ...state, isBuffering: true };\n case \"MEDIA_CANPLAY\":\n return { ...state, isBuffering: false, errorMessage: null };\n case \"MEDIA_PLAY\":\n return { ...state, isPaused: false, isBuffering: false };\n case \"MEDIA_PAUSE\":\n return { ...state, isPaused: true };\n case \"RESET_MEDIA_TIMES\":\n return { ...state, currentTime: 0, duration: 0, bufferedFraction: 0 };\n case \"SET_VOLUME\":\n return { ...state, volume: clampVolume(action.payload) };\n case \"SET_MUTED\":\n return { ...state, muted: action.payload };\n case \"TOGGLE_MUTE\":\n return { ...state, muted: !state.muted };\n case \"SET_PLAYBACK_RATE\":\n return { ...state, playbackRate: clampPlaybackRate(action.payload) };\n case \"MEDIA_VOLUME_SYNC\": {\n const { volume, muted } = action.payload;\n const v = clampVolume(volume);\n if (v === state.volume && muted === state.muted) return state;\n return { ...state, volume: v, muted };\n }\n default: {\n const _exhaustive: never = action;\n void _exhaustive;\n return state;\n }\n }\n}\n","import { useEffect } from \"react\";\nimport type { GingerState } from \"../types\";\n\nexport type MediaSessionBridgeActions = {\n play: () => void;\n pause: () => void;\n next: () => void;\n prev: () => void;\n seek: (timeSeconds: number) => void;\n};\n\nfunction getMediaSession(): MediaSession | null {\n if (typeof navigator === \"undefined\" || !(\"mediaSession\" in navigator)) return null;\n return navigator.mediaSession;\n}\n\nexport function useMediaSessionBridge(\n enabled: boolean,\n state: GingerState,\n actions: MediaSessionBridgeActions,\n): void {\n const track = state.tracks[state.currentIndex];\n const title = track?.title;\n const artist = track?.artist;\n const album = track?.album;\n const artworkUrl = track?.artworkUrl;\n\n useEffect(() => {\n const ms = getMediaSession();\n if (!enabled || !ms) return;\n ms.metadata = new MediaMetadata({\n title: title ?? \"Unknown track\",\n artist,\n album,\n artwork: artworkUrl ? [{ src: artworkUrl }] : undefined,\n });\n }, [enabled, title, artist, album, artworkUrl]);\n\n useEffect(() => {\n const ms = getMediaSession();\n if (!enabled || !ms) return;\n ms.playbackState = state.isPaused ? \"paused\" : \"playing\";\n }, [enabled, state.isPaused]);\n\n useEffect(() => {\n const ms = getMediaSession();\n if (!enabled || !ms) return;\n try {\n ms.setActionHandler(\"play\", actions.play);\n ms.setActionHandler(\"pause\", actions.pause);\n ms.setActionHandler(\"nexttrack\", actions.next);\n ms.setActionHandler(\"previoustrack\", actions.prev);\n ms.setActionHandler(\"seekto\", (details) => {\n if (typeof details.seekTime === \"number\" && Number.isFinite(details.seekTime)) {\n actions.seek(details.seekTime);\n }\n });\n } catch {\n // Best-effort API support differs across browsers.\n }\n return () => {\n try {\n ms.setActionHandler(\"play\", null);\n ms.setActionHandler(\"pause\", null);\n ms.setActionHandler(\"nexttrack\", null);\n ms.setActionHandler(\"previoustrack\", null);\n ms.setActionHandler(\"seekto\", null);\n } catch {\n // Ignore platforms that do not support clearing handlers.\n }\n };\n }, [enabled, actions]);\n}\n","import {\n useCallback,\n useEffect,\n useMemo,\n useReducer,\n useRef,\n type CSSProperties,\n} from \"react\";\nimport { computeEndedTransition } from \"../core/transitions\";\nimport { clampPlaybackRate, clampVolume, gingerReducer, createInitialState } from \"../core/playbackReducer\";\nimport { trackIdentity } from \"../core/queue\";\nimport { derivePlaybackUiState } from \"../internal/selectors\";\nimport type { GingerInitPayload, GingerProviderProps, PlaylistMeta, RepeatMode, Track } from \"../types\";\nimport { useMediaSessionBridge } from \"../media/useMediaSession\";\nimport { GingerContext, type GingerContextValue } from \"./GingerContext\";\nimport { GingerLocaleProvider } from \"./GingerLocaleContext\";\nimport { GingerMediaContext, GingerPlaybackContext, type GingerMediaContextValue, type GingerPlaybackContextValue } from \"./GingerSplitContexts\";\n\nconst defaultProviderStyle: CSSProperties = {\n [\"--ginger-primary-color\" as string]: \"#111827\",\n [\"--ginger-muted-color\" as string]: \"#6b7280\",\n [\"--ginger-font-size\" as string]: \"14px\",\n [\"--ginger-font-family\" as string]: \"system-ui, sans-serif\",\n [\"--ginger-playlist-row-padding\" as string]: \"6px 8px\",\n [\"--ginger-artwork-radius\" as string]: \"6px\",\n [\"--ginger-artwork-bg\" as string]: \"#f3f4f6\",\n [\"--ginger-playlist-active-bg\" as string]: \"rgba(17, 24, 39, 0.06)\",\n [\"--ginger-buffer-color\" as string]: \"rgba(107, 114, 128, 0.35)\",\n [\"--ginger-focus-ring\" as string]: \"0 0 0 2px rgba(59, 130, 246, 0.45)\",\n};\n\nexport function GingerProvider({\n children,\n initialTracks = [],\n initialIndex = 0,\n initialPlaylistMeta = null,\n initialShuffle = false,\n initialRepeatMode = \"off\",\n initialPlaybackMode = \"playlist\",\n initialPaused = true,\n initialVolume = 1,\n initialMuted = false,\n initialPlaybackRate = 1,\n initialStateKey,\n locale,\n mediaSession = false,\n beforePlay,\n onPlayBlocked,\n persistence,\n hydrateOnMount = false,\n resumeOnTrackChange = false,\n unstyled = false,\n className,\n style,\n onTrackChange,\n onPlay,\n onPause,\n onQueueEnd,\n onError,\n}: GingerProviderProps) {\n const audioRef = useRef<HTMLAudioElement | null>(null);\n const [state, dispatch] = useReducer(\n gingerReducer,\n undefined,\n () =>\n createInitialState({\n tracks: initialTracks,\n currentIndex: initialIndex,\n playlistMeta: initialPlaylistMeta,\n isPaused: initialPaused,\n isShuffled: initialShuffle,\n repeatMode: initialRepeatMode,\n playbackMode: initialPlaybackMode,\n volume: initialVolume,\n muted: initialMuted,\n playbackRate: initialPlaybackRate,\n }),\n );\n const stateRef = useRef(state);\n\n const latestInitRef = useRef({\n tracks: initialTracks,\n currentIndex: initialIndex,\n playlistMeta: initialPlaylistMeta,\n isPaused: initialPaused,\n isShuffled: initialShuffle,\n repeatMode: initialRepeatMode,\n playbackMode: initialPlaybackMode,\n volume: initialVolume,\n muted: initialMuted,\n playbackRate: initialPlaybackRate,\n });\n latestInitRef.current = {\n tracks: initialTracks,\n currentIndex: initialIndex,\n playlistMeta: initialPlaylistMeta,\n isPaused: initialPaused,\n isShuffled: initialShuffle,\n repeatMode: initialRepeatMode,\n playbackMode: initialPlaybackMode,\n volume: initialVolume,\n muted: initialMuted,\n playbackRate: initialPlaybackRate,\n };\n\n const prevInitialStateKeyRef = useRef<typeof initialStateKey>(undefined);\n\n useEffect(() => {\n if (initialStateKey === undefined) {\n prevInitialStateKeyRef.current = undefined;\n return;\n }\n if (prevInitialStateKeyRef.current === undefined) {\n prevInitialStateKeyRef.current = initialStateKey;\n return;\n }\n if (prevInitialStateKeyRef.current === initialStateKey) return;\n prevInitialStateKeyRef.current = initialStateKey;\n const p = latestInitRef.current;\n dispatch({\n type: \"INIT\",\n payload: {\n tracks: p.tracks,\n currentIndex: p.currentIndex,\n playlistMeta: p.playlistMeta,\n isPaused: p.isPaused,\n isShuffled: p.isShuffled,\n repeatMode: p.repeatMode,\n playbackMode: p.playbackMode,\n volume: p.volume,\n muted: p.muted,\n playbackRate: p.playbackRate,\n },\n });\n }, [initialStateKey, dispatch]);\n\n useEffect(() => {\n stateRef.current = state;\n }, [state]);\n\n const currentTrack = state.tracks[state.currentIndex] ?? null;\n\n useEffect(() => {\n onTrackChange?.(currentTrack, state.currentIndex);\n }, [currentTrack, state.currentIndex, onTrackChange]);\n\n useEffect(() => {\n if (state.errorMessage) onError?.(state.errorMessage);\n }, [state.errorMessage, onError]);\n\n const prevPausedRef = useRef<boolean | undefined>(undefined);\n useEffect(() => {\n if (prevPausedRef.current === undefined) {\n prevPausedRef.current = state.isPaused;\n return;\n }\n if (prevPausedRef.current !== state.isPaused) {\n if (state.isPaused) onPause?.();\n else onPlay?.();\n }\n prevPausedRef.current = state.isPaused;\n }, [state.isPaused, onPause, onPlay]);\n\n const play = useCallback(() => {\n dispatch({ type: \"PLAY\" });\n }, []);\n\n const pause = useCallback(() => {\n dispatch({ type: \"PAUSE\" });\n audioRef.current?.pause();\n }, []);\n\n const togglePlayPause = useCallback(() => {\n if (state.isPaused) play();\n else pause();\n }, [pause, play, state.isPaused]);\n\n const seek = useCallback((timeSeconds: number) => {\n const el = audioRef.current;\n if (!el) return;\n if (!Number.isFinite(timeSeconds)) return;\n el.currentTime = Math.max(0, timeSeconds);\n }, []);\n\n const setVolume = useCallback((volume: number) => {\n dispatch({ type: \"SET_VOLUME\", payload: clampVolume(volume) });\n }, []);\n\n const setMuted = useCallback((muted: boolean) => {\n dispatch({ type: \"SET_MUTED\", payload: muted });\n }, []);\n\n const toggleMute = useCallback(() => {\n dispatch({ type: \"TOGGLE_MUTE\" });\n }, []);\n\n const setPlaybackRate = useCallback((rate: number) => {\n dispatch({ type: \"SET_PLAYBACK_RATE\", payload: clampPlaybackRate(rate) });\n }, []);\n\n const next = useCallback(() => {\n dispatch({ type: \"NEXT\" });\n }, []);\n\n const prev = useCallback(() => {\n dispatch({ type: \"PREV\" });\n }, []);\n\n const setRepeatMode = useCallback((mode: RepeatMode) => {\n dispatch({ type: \"SET_REPEAT\", payload: mode });\n }, []);\n\n const cycleRepeat = useCallback(() => {\n dispatch({ type: \"CYCLE_REPEAT\" });\n }, []);\n\n const toggleShuffle = useCallback(() => {\n dispatch({ type: \"TOGGLE_SHUFFLE\" });\n }, []);\n\n const setQueue = useCallback((tracks: Track[], currentIndex?: number) => {\n dispatch({ type: \"SET_QUEUE\", payload: { tracks, currentIndex } });\n }, []);\n\n const insertTrackAt = useCallback((track: Track, index?: number, autoPlay?: boolean) => {\n dispatch({ type: \"INSERT_TRACK\", payload: { track, index, autoPlay } });\n }, []);\n\n const removeTrackAt = useCallback((index: number) => {\n dispatch({ type: \"REMOVE_TRACK\", payload: { index } });\n }, []);\n\n const moveTrack = useCallback((fromIndex: number, toIndex: number) => {\n dispatch({ type: \"MOVE_TRACK\", payload: { fromIndex, toIndex } });\n }, []);\n\n const enqueueNext = useCallback((track: Track) => {\n dispatch({ type: \"ADD_NEXT\", payload: { track } });\n }, []);\n\n const playTrackAt = useCallback((index: number) => {\n dispatch({ type: \"SET_INDEX\", payload: { index, autoPlay: true } });\n }, []);\n\n const selectTrackAt = useCallback((index: number) => {\n dispatch({ type: \"SET_INDEX\", payload: { index, autoPlay: false } });\n }, []);\n\n const setPlaylistMeta = useCallback((meta: PlaylistMeta | null) => {\n dispatch({ type: \"SET_PLAYLIST_META\", payload: meta });\n }, []);\n\n const init = useCallback((payload: GingerInitPayload) => {\n dispatch({ type: \"INIT\", payload });\n }, []);\n\n useEffect(() => {\n if (!persistence || !hydrateOnMount) return;\n const volume = persistence.get(\"ginger:volume\");\n const muted = persistence.get(\"ginger:muted\");\n const playbackRate = persistence.get(\"ginger:playbackRate\");\n const repeatMode = persistence.get(\"ginger:repeatMode\");\n const currentIndex = persistence.get(\"ginger:currentIndex\");\n const p = latestInitRef.current;\n dispatch({\n type: \"INIT\",\n payload: {\n tracks: p.tracks,\n playlistMeta: p.playlistMeta,\n isPaused: p.isPaused,\n isShuffled: p.isShuffled,\n playbackMode: p.playbackMode,\n currentIndex: typeof currentIndex === \"number\" ? currentIndex : p.currentIndex,\n repeatMode: repeatMode === \"off\" || repeatMode === \"all\" || repeatMode === \"one\" ? repeatMode : p.repeatMode,\n volume: typeof volume === \"number\" ? volume : p.volume,\n muted: typeof muted === \"boolean\" ? muted : p.muted,\n playbackRate: typeof playbackRate === \"number\" ? playbackRate : p.playbackRate,\n },\n });\n }, [hydrateOnMount, persistence]);\n\n useEffect(() => {\n if (!persistence) return;\n persistence.set(\"ginger:volume\", state.volume);\n persistence.set(\"ginger:muted\", state.muted);\n persistence.set(\"ginger:playbackRate\", state.playbackRate);\n persistence.set(\"ginger:repeatMode\", state.repeatMode);\n persistence.set(\"ginger:currentIndex\", state.currentIndex);\n }, [persistence, state.volume, state.muted, state.playbackRate, state.repeatMode, state.currentIndex]);\n\n useEffect(() => {\n if (!persistence || !resumeOnTrackChange) return;\n const track = state.tracks[state.currentIndex];\n if (!track) return;\n const key = `ginger:resume:${trackIdentity(track)}`;\n const saved = persistence.get(key);\n if (typeof saved === \"number\" && Number.isFinite(saved)) {\n seek(saved);\n }\n }, [persistence, resumeOnTrackChange, state.currentIndex, state.tracks, seek]);\n\n useEffect(() => {\n if (!persistence || !resumeOnTrackChange) return;\n const track = state.tracks[state.currentIndex];\n if (!track || !(state.currentTime >= 0)) return;\n const key = `ginger:resume:${trackIdentity(track)}`;\n const id = setTimeout(() => persistence.set(key, state.currentTime), 250);\n return () => clearTimeout(id);\n }, [persistence, resumeOnTrackChange, state.currentIndex, state.tracks, state.currentTime]);\n\n const currentUrl = state.tracks[state.currentIndex]?.fileUrl;\n\n useEffect(() => {\n const el = audioRef.current;\n if (!el) return;\n if (state.isPaused) {\n el.pause();\n return;\n }\n let cancelled = false;\n void (async () => {\n if (beforePlay) {\n let allowed = false;\n try {\n allowed = await beforePlay();\n } catch (error) {\n const message = error instanceof Error ? error.message : \"beforePlay rejected\";\n dispatch({ type: \"MEDIA_ERROR\", payload: { message } });\n return;\n }\n if (!allowed) {\n if (!cancelled) {\n dispatch({ type: \"PAUSE\" });\n onPlayBlocked?.();\n }\n return;\n }\n }\n if (cancelled) return;\n void el.play().catch((e: unknown) => {\n const msg =\n e instanceof Error\n ? e.message\n : typeof e === \"string\"\n ? e\n : \"Playback failed (e.g. autoplay blocked or unavailable source)\";\n dispatch({ type: \"MEDIA_ERROR\", payload: { message: msg } });\n });\n })();\n return () => {\n cancelled = true;\n };\n }, [beforePlay, currentUrl, onPlayBlocked, state.isPaused]);\n\n const notifyEnded = useCallback(() => {\n const transition = computeEndedTransition(stateRef.current);\n if (transition.kind === \"replay_same\") {\n const el = audioRef.current;\n if (el) {\n el.currentTime = 0;\n }\n dispatch({ type: \"PLAY\" });\n return;\n }\n if (transition.kind === \"stop\") {\n dispatch({ type: \"PAUSE\" });\n onQueueEnd?.();\n return;\n }\n const nextIndex = transition.nextIndex;\n dispatch({ type: \"SET_INDEX\", payload: { index: nextIndex, autoPlay: true } });\n }, [onQueueEnd]);\n\n const mediaSessionActions = useMemo(\n () => ({ play, pause, next, prev, seek }),\n [play, pause, next, prev, seek],\n );\n useMediaSessionBridge(Boolean(mediaSession), state, mediaSessionActions);\n\n const providerDir = locale?.seek && /[\\u0590-\\u08FF]/.test(locale.seek) ? \"rtl\" : \"ltr\";\n\n const value = useMemo<GingerContextValue>(\n () => ({\n state,\n dispatch,\n audioRef,\n notifyEnded,\n init,\n play,\n pause,\n togglePlayPause,\n seek,\n setVolume,\n setMuted,\n toggleMute,\n setPlaybackRate,\n next,\n prev,\n setRepeatMode,\n cycleRepeat,\n toggleShuffle,\n setQueue,\n insertTrackAt,\n removeTrackAt,\n moveTrack,\n enqueueNext,\n playTrackAt,\n selectTrackAt,\n setPlaylistMeta,\n }),\n [\n cycleRepeat,\n dispatch,\n init,\n next,\n notifyEnded,\n pause,\n play,\n playTrackAt,\n insertTrackAt,\n removeTrackAt,\n moveTrack,\n enqueueNext,\n selectTrackAt,\n prev,\n seek,\n setMuted,\n setPlaybackRate,\n setQueue,\n setRepeatMode,\n setPlaylistMeta,\n setVolume,\n state,\n toggleMute,\n togglePlayPause,\n toggleShuffle,\n ],\n );\n\n const playbackValue = useMemo<GingerPlaybackContextValue>(\n () => ({\n tracks: state.tracks,\n currentIndex: state.currentIndex,\n isPaused: state.isPaused,\n isShuffled: state.isShuffled,\n repeatMode: state.repeatMode,\n originalTracks: state.originalTracks,\n playlistMeta: state.playlistMeta,\n init,\n play,\n pause,\n togglePlayPause,\n next,\n prev,\n setRepeatMode,\n cycleRepeat,\n toggleShuffle,\n playbackMode: state.playbackMode,\n setQueue,\n insertTrackAt,\n removeTrackAt,\n moveTrack,\n enqueueNext,\n playTrackAt,\n selectTrackAt,\n setPlaylistMeta,\n dispatch,\n }),\n [\n state.tracks,\n state.currentIndex,\n state.isPaused,\n state.isShuffled,\n state.repeatMode,\n state.playbackMode,\n state.originalTracks,\n state.playlistMeta,\n init,\n play,\n pause,\n togglePlayPause,\n next,\n prev,\n setRepeatMode,\n cycleRepeat,\n toggleShuffle,\n setQueue,\n insertTrackAt,\n removeTrackAt,\n moveTrack,\n enqueueNext,\n playTrackAt,\n selectTrackAt,\n setPlaylistMeta,\n dispatch,\n ],\n );\n\n const mediaValue = useMemo<GingerMediaContextValue>(\n () => ({\n currentTime: state.currentTime,\n duration: state.duration,\n bufferedFraction: state.bufferedFraction,\n isBuffering: state.isBuffering,\n errorMessage: state.errorMessage,\n volume: state.volume,\n muted: state.muted,\n playbackRate: state.playbackRate,\n seek,\n setVolume,\n setMuted,\n toggleMute,\n setPlaybackRate,\n audioRef,\n notifyEnded,\n dispatch,\n }),\n [\n state.currentTime,\n state.duration,\n state.bufferedFraction,\n state.isBuffering,\n state.errorMessage,\n state.volume,\n state.muted,\n state.playbackRate,\n seek,\n setVolume,\n setMuted,\n toggleMute,\n setPlaybackRate,\n audioRef,\n notifyEnded,\n dispatch,\n ],\n );\n\n const playbackUi = derivePlaybackUiState(state);\n\n const mergedStyle = useMemo(\n () => (unstyled ? style : { ...defaultProviderStyle, ...style }),\n [style, unstyled],\n );\n\n return (\n <GingerLocaleProvider locale={locale}>\n <GingerPlaybackContext.Provider value={playbackValue}>\n <GingerMediaContext.Provider value={mediaValue}>\n <GingerContext.Provider value={value}>\n <div\n className={className}\n style={mergedStyle}\n data-ginger-playback={playbackUi}\n dir={providerDir}\n >\n {children}\n </div>\n </GingerContext.Provider>\n </GingerMediaContext.Provider>\n </GingerPlaybackContext.Provider>\n </GingerLocaleProvider>\n );\n}\n","import { GingerPlayer } from \"./audio/GingerPlayer\";\nimport * as Current from \"./components/current\";\nimport * as Control from \"./components/controls/Controls\";\nimport { GingerPlaylistCompound } from \"./components/playlist/GingerPlaylist\";\nimport * as Queue from \"./components/queue/QueueDisplay\";\nimport { GingerProvider } from \"./context/GingerProvider\";\n\nexport const Ginger = {\n Provider: GingerProvider,\n Player: GingerPlayer,\n Current: {\n Title: Current.Title,\n Artist: Current.Artist,\n Album: Current.Album,\n Description: Current.Description,\n Copyright: Current.Copyright,\n Genre: Current.Genre,\n Label: Current.Label,\n Isrc: Current.Isrc,\n TrackNumber: Current.TrackNumber,\n Year: Current.Year,\n Lyrics: Current.Lyrics,\n FileUrl: Current.FileUrl,\n Artwork: Current.Artwork,\n QueueIndex: Current.QueueIndex,\n QueueLength: Current.QueueLength,\n QueuePosition: Current.QueuePosition,\n Elapsed: Current.Elapsed,\n Duration: Current.Duration,\n Remaining: Current.Remaining,\n Progress: Current.Progress,\n TimeRail: Current.TimeRail,\n BufferRail: Current.BufferRail,\n PlaybackState: Current.PlaybackState,\n ErrorMessage: Current.ErrorMessage,\n },\n Queue: {\n Title: Queue.Title,\n Subtitle: Queue.Subtitle,\n Description: Queue.Description,\n Copyright: Queue.Copyright,\n Artwork: Queue.Artwork,\n },\n Control: {\n PlayPause: Control.PlayPause,\n Repeat: Control.Repeat,\n Next: Control.Next,\n Previous: Control.Previous,\n Shuffle: Control.Shuffle,\n SeekBar: Control.SeekBar,\n Volume: Control.Volume,\n Mute: Control.Mute,\n PlaybackRate: Control.PlaybackRate,\n },\n Playlist: GingerPlaylistCompound,\n};\n"],"names":["GingerContext","createContext","useGingerContext","ctx","useContext","readBufferedFraction","el","buffered","duration","GingerPlayer","className","style","preload","crossOrigin","respectReducedMotion","audioRef","dispatch","state","notifyEnded","url","_a","lastTimeSnapshotRef","useRef","reducedMotion","setReducedMotion","useState","useEffect","mql","sync","syncTime","force","next","prev","timeThreshold","changedEnough","jsx","e","code","clampIndex","index","length","shuffleWithAnchor","tracks","anchorIndex","anchor","rest","_","i","j","trackIdentity","track","findIndexByTrackIdentity","target","identity","insertTrackAt","at","removeTrackAt","moveTrack","fromIndex","toIndex","item","addNextTrack","currentIndex","computeEndedTransition","repeatMode","playbackMode","len","computeNextIndex","computePrevIndex","cycleRepeatMode","mode","resolveArtworkUrl","playlistArtwork","resolveAlbumLine","playlistSubtitle","getCurrentTrack","derivePlaybackUiState","effectiveDuration","d","hint","effectiveRemaining","rem","progressFraction","dur","resolvedArtwork","resolvedAlbumLine","createTextDisplay","displayName","select","Comp","props","useGingerState","value","fallback","empty","children","node","createTrackFieldDisplay","Title","t","Artist","Album","s","Description","Copyright","Genre","Label","Isrc","TrackNumber","Year","format","y","text","Lyrics","preserveWhitespace","raw","whiteStyle","FileUrl","visible","Artwork","sizes","loading","onError","decoding","unstyled","imgStyle","src","alt","QueueIndex","base","QueueLength","QueuePosition","separator","label","formatMmSs","seconds","renderTime","valueSeconds","Elapsed","Duration","Remaining","Progress","fraction","TimeRail","height","showBuffered","progressPct","bufPct","jsxs","BufferRail","PlaybackState","ErrorMessage","live","defaultGingerLocale","rate","mergeLocale","partial","GingerLocaleContext","GingerLocaleProvider","locale","useGingerLocale","useSeekBarBinding","pb","useGingerPlayback","md","useGingerMedia","useMemo","gingerStateFromContextValues","numericValue","ariaValueText","onSeekInput","useVolumeSlider","onVolumeInput","usePlayPauseBinding","options","playL","pauseL","PlayPause","playLabel","pauseLabel","playAriaLabel","pauseAriaLabel","type","onClick","defaultPlayAria","defaultPauseAria","b","Repeat","cycleRepeat","Next","Previous","Shuffle","isShuffled","toggleShuffle","SeekBar","inputStyle","mergedStyle","Volume","Mute","muteLabel","unmuteLabel","muted","toggleMute","m","u","defaultRates","PlaybackRate","rates","playbackRate","setPlaybackRate","a","r","GingerPlaylistConfigContext","usePlaylistConfig","GingerPlaylist","rowStyle","renderTrack","playOnSelect","playTrackAt","selectTrackAt","listStyle","active","GingerPlaylistTrack","liProps","buttonRest","defaultLabel","GingerPlaylistCompound","Subtitle","_b","clampVolume","v","clampPlaybackRate","resetTimingOnly","defaultMedia","createInitialState","params","originalTracks","ordered","gingerReducer","action","playlistMeta","isPaused","volume","idx","insertIndex","ap","snapshot","shuffled","restored","current","newIndex","nextIndex","same","prevIndex","getMediaSession","useMediaSessionBridge","enabled","actions","title","artist","album","artworkUrl","ms","details","defaultProviderStyle","GingerProvider","initialTracks","initialIndex","initialPlaylistMeta","initialShuffle","initialRepeatMode","initialPlaybackMode","initialPaused","initialVolume","initialMuted","initialPlaybackRate","initialStateKey","mediaSession","beforePlay","onPlayBlocked","persistence","hydrateOnMount","resumeOnTrackChange","onTrackChange","onPlay","onPause","onQueueEnd","useReducer","stateRef","latestInitRef","prevInitialStateKeyRef","p","currentTrack","prevPausedRef","play","useCallback","pause","togglePlayPause","seek","timeSeconds","setVolume","setMuted","setRepeatMode","setQueue","autoPlay","enqueueNext","setPlaylistMeta","meta","init","payload","key","saved","id","currentUrl","cancelled","allowed","error","message","msg","transition","mediaSessionActions","providerDir","playbackValue","mediaValue","playbackUi","GingerPlaybackContext","GingerMediaContext","Ginger","Current.Title","Current.Artist","Current.Album","Current.Description","Current.Copyright","Current.Genre","Current.Label","Current.Isrc","Current.TrackNumber","Current.Year","Current.Lyrics","Current.FileUrl","Current.Artwork","Current.QueueIndex","Current.QueueLength","Current.QueuePosition","Current.Elapsed","Current.Duration","Current.Remaining","Current.Progress","Current.TimeRail","Current.BufferRail","Current.PlaybackState","Current.ErrorMessage","Queue.Title","Queue.Subtitle","Queue.Description","Queue.Copyright","Queue.Artwork","Control.PlayPause","Control.Repeat","Control.Next","Control.Previous","Control.Shuffle","Control.SeekBar","Control.Volume","Control.Mute","Control.PlaybackRate"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";const a=require("react"),d=require("./GingerSplitContexts-Bze1Bqe2.cjs"),R=require("./ginger-DYoHDn8T.cjs");function V(){const n=d.useGingerPlayback(),t=d.useGingerMedia();return a.useMemo(()=>{const e=d.gingerStateFromContextValues(n,t);return{state:e,currentTrack:R.getCurrentTrack(e),playbackUi:R.derivePlaybackUiState(e),duration:R.effectiveDuration(e),remaining:R.effectiveRemaining(e),progress:R.progressFraction(e),artworkUrl:R.resolvedArtwork(e),albumLine:R.resolvedAlbumLine(e),play:n.play,pause:n.pause,togglePlayPause:n.togglePlayPause,seek:t.seek,setVolume:t.setVolume,setMuted:t.setMuted,toggleMute:t.toggleMute,setPlaybackRate:t.setPlaybackRate,next:n.next,prev:n.prev,setRepeatMode:n.setRepeatMode,cycleRepeat:n.cycleRepeat,toggleShuffle:n.toggleShuffle,setQueue:n.setQueue,insertTrackAt:n.insertTrackAt,removeTrackAt:n.removeTrackAt,moveTrack:n.moveTrack,enqueueNext:n.enqueueNext,playTrackAt:n.playTrackAt,selectTrackAt:n.selectTrackAt,setPlaylistMeta:n.setPlaylistMeta,init:n.init,audioRef:t.audioRef,dispatch:n.dispatch}},[n,t])}const q=new WeakMap;function j(n){const t=2**Math.round(Math.log2(n));return Math.min(32768,Math.max(32,t))}function X(n,t){let e=q.get(n);if(!e){const i=window.AudioContext??window.webkitAudioContext;if(!i)throw new Error("Web Audio API is not available");const f=new i,k=f.createMediaElementSource(n);e={context:f,source:k,consumers:new Map,nextId:0},q.set(n,e)}const{context:s,source:o}=e,c=s.createAnalyser();c.fftSize=j(t.fftSize),c.smoothingTimeConstant=t.smoothingTimeConstant,c.minDecibels=t.minDecibels,c.maxDecibels=t.maxDecibels,o.connect(c);const r=e.consumers.size===0;r&&c.connect(s.destination);const u=e.nextId;return e.nextId+=1,e.consumers.set(u,{analyser:c,isPlaybackSink:r}),{id:u,context:s,analyser:c}}function N(n,t){const e=q.get(n);if(!e)return;const s=e.consumers.get(t);if(!s)return;const{analyser:o,isPlaybackSink:c}=s;if(o.disconnect(),e.consumers.delete(t),e.consumers.size===0){try{e.source.disconnect()}catch{}e.context.close(),q.delete(n);return}if(c){const r=e.consumers.values().next().value;r&&(r.analyser.connect(e.context.destination),r.isPlaybackSink=!0)}}const D=new Uint8Array(0),I=new Uint8Array(0);function J(n={}){const{enabled:t=!0,fftSize:e=2048,smoothingTimeConstant:s=.8,minDecibels:o=-100,maxDecibels:c=-30}=n,{audioRef:r,state:u}=V(),i=a.useMemo(()=>({fftSize:e,smoothingTimeConstant:s,minDecibels:o,maxDecibels:c}),[e,s,o,c]),[f,k]=a.useState(0),[g,l]=a.useState(null),[S,v]=a.useState(!1),[b,T]=a.useState({frequencyBinCount:0,sampleRate:0}),p=a.useRef(D),h=a.useRef(I),Q=a.useCallback(async()=>{const x=w.current;x&&x.state==="suspended"&&await x.resume()},[]),w=a.useRef(null),P=a.useRef(null);return a.useLayoutEffect(()=>{if(!t||typeof window>"u")return;let x=!1,C=null,E=null,G=0;const F=()=>{const m=w.current;m&&v(m.state==="suspended")},z=()=>{if(x)return;const m=P.current,A=p.current,y=h.current;m&&A.length>0&&y.length>0&&(m.getByteFrequencyData(A),m.getByteTimeDomainData(y),k(L=>L+1)),G=requestAnimationFrame(z)},B=()=>{const m=r.current;if(!m||x)return"no-element";try{const{id:A,context:y,analyser:L}=X(m,i);C=A,E=m,w.current=y,P.current=L,v(y.state==="suspended"),l(null),y.addEventListener("statechange",F);const M=L.frequencyBinCount,W=L.fftSize;return p.current=new Uint8Array(M),h.current=new Uint8Array(W),T({frequencyBinCount:M,sampleRate:y.sampleRate}),G=requestAnimationFrame(z),"ok"}catch(A){const y=A instanceof Error?A.message:"Failed to attach live analyser";return l(y),w.current=null,P.current=null,p.current=D,h.current=I,T({frequencyBinCount:0,sampleRate:0}),"error"}},U=B();if(U!=="ok"){let m=0;const A=120;let y=0;const L=()=>{if(x)return;const M=B();M==="ok"||M==="error"||(y+=1,!(y>=A)&&(m=requestAnimationFrame(L)))};return U==="no-element"&&(m=requestAnimationFrame(L)),()=>{var M;x=!0,cancelAnimationFrame(m),cancelAnimationFrame(G),C!=null&&E&&N(E,C),(M=w.current)==null||M.removeEventListener("statechange",F),w.current=null,P.current=null,p.current=D,h.current=I}}return()=>{var m;x=!0,cancelAnimationFrame(G),C!=null&&E&&N(E,C),(m=w.current)==null||m.removeEventListener("statechange",F),w.current=null,P.current=null,p.current=D,h.current=I,T({frequencyBinCount:0,sampleRate:0})}},[t,r,i,u.currentIndex]),{frequencyData:p.current,timeDomainData:h.current,frequencyBinCount:b.frequencyBinCount,sampleRate:b.sampleRate,isSuspended:S,error:g,resume:Q}}function O(n=!0,t={}){const{togglePlayPause:e,next:s,prev:o}=d.useGingerPlayback(),{toggleMute:c}=d.useGingerMedia(),r=t.mute;a.useEffect(()=>{if(!n||typeof window>"u")return;const u=(t.playPause??" ").toLowerCase(),i=(t.next??"ArrowRight").toLowerCase(),f=(t.previous??"ArrowLeft").toLowerCase(),k=r==null?void 0:r.toLowerCase(),g=l=>{const S=l.target;if(S&&(["INPUT","TEXTAREA","SELECT"].includes(S.tagName)||S.isContentEditable))return;const v=l.key.toLowerCase();v===u?(l.preventDefault(),e()):v===i?(l.preventDefault(),s()):v===f?(l.preventDefault(),o()):k&&v===k&&(l.preventDefault(),c())};return window.addEventListener("keydown",g),()=>window.removeEventListener("keydown",g)},[t.next,t.playPause,t.previous,n,r,s,o,c,e])}function Y(){const{tracks:n,currentIndex:t}=d.useGingerPlayback(),{currentTime:e,seek:s}=d.useGingerMedia(),o=a.useMemo(()=>{var u;return[...((u=n[t])==null?void 0:u.chapters)??[]].filter(i=>i&&Number.isFinite(i.startSeconds)&&i.startSeconds>=0).sort((i,f)=>i.startSeconds-f.startSeconds)},[t,n]),c=a.useMemo(()=>{if(o.length===0)return-1;for(let r=o.length-1;r>=0;r-=1)if(e>=o[r].startSeconds)return r;return-1},[e,o]);return{list:o,activeIndex:c,active:c>=0?o[c]??null:null,seekTo:r=>{const u=o[r];u&&s(u.startSeconds)}}}const K=/\[(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?\]/g;function H(n){const t=[];for(const e of n.split(/\r?\n/)){const s=[...e.matchAll(K)];if(s.length===0)continue;const o=e.replace(K,"").trim();for(const c of s){const r=Number(c[1]??0),u=Number(c[2]??0),i=Number((c[3]??"0").padEnd(3,"0")),f=r*60+u+i/1e3;Number.isFinite(f)&&f>=0&&t.push({time:f,text:o})}}return t.sort((e,s)=>e.time-s.time)}function Z(){const{tracks:n,currentIndex:t}=d.useGingerPlayback(),{currentTime:e}=d.useGingerMedia(),s=n[t],o=a.useMemo(()=>s?Array.isArray(s.lyricsTimed)&&s.lyricsTimed.length>0?[...s.lyricsTimed].filter(r=>Number.isFinite(r.time)&&r.time>=0).sort((r,u)=>r.time-u.time):typeof s.lyrics=="string"?H(s.lyrics):[]:[],[s]),c=a.useMemo(()=>{for(let r=o.length-1;r>=0;r-=1)if(e>=o[r].time)return r;return-1},[e,o]);return{lines:o,activeIndex:c,activeLine:c>=0?o[c]??null:null}}function _(n){const{durationMs:t,stopAfterTracks:e,respectPause:s=!0,enabled:o=!0,onFire:c}=n,{currentIndex:r,pause:u,isPaused:i}=d.useGingerPlayback(),f=a.useRef(e??0),k=a.useRef(r);a.useEffect(()=>{f.current=e??0},[e]),a.useEffect(()=>{if(!o||!t||t<=0||s&&i)return;const g=setTimeout(()=>{u(),c==null||c()},t);return()=>clearTimeout(g)},[t,o,i,c,u,s]),a.useEffect(()=>{if(!o||!e||e<=0)return;const g=k.current;k.current=r,r!==g&&(f.current-=1,f.current<=0&&(u(),c==null||c()))},[r,o,c,u,e])}function $(n=!1){const t=d.useGingerState(),e=a.useRef(t);a.useEffect(()=>{if(!n||typeof console>"u")return;const s=e.current;s!==t&&console.debug("[ginger]",{from:{currentIndex:s.currentIndex,isPaused:s.isPaused,currentTime:s.currentTime,repeatMode:s.repeatMode},to:{currentIndex:t.currentIndex,isPaused:t.isPaused,currentTime:t.currentTime,repeatMode:t.repeatMode}}),e.current=t},[n,t])}function ee(n){return Math.max(0,Math.min(1,n))}function te(n){const t=d.useGingerMedia(),e=d.useGingerPlayback(),{seek:s}=t,[o,c]=a.useState(0),[r,u]=a.useState(!1),i=R.progressFraction(d.gingerStateFromContextValues(e,t)),f=r?o:i,k=a.useCallback(g=>{if(!(n>0))return;const l=g.currentTarget,S=l.getBoundingClientRect(),v=p=>{const h=ee((p-S.left)/S.width);c(h),s(h*n)};u(!0),l.setPointerCapture(g.pointerId),v(g.clientX);const b=p=>v(p.clientX),T=p=>{v(p.clientX),u(!1),l.releasePointerCapture(g.pointerId),l.removeEventListener("pointermove",b),l.removeEventListener("pointerup",T),l.removeEventListener("pointercancel",T)};l.addEventListener("pointermove",b),l.addEventListener("pointerup",T),l.addEventListener("pointercancel",T)},[n,s]);return{fraction:o,displayFraction:f,isDragging:r,onPointerDown:k}}exports.attachLiveAnalyser=X;exports.detachLiveAnalyser=N;exports.parseLrc=H;exports.useGinger=V;exports.useGingerChapters=Y;exports.useGingerDebugLog=$;exports.useGingerKeyboardShortcuts=O;exports.useGingerLiveAnalyzer=J;exports.useGingerLyricsSync=Z;exports.useGingerSleepTimer=_;exports.useSeekDrag=te;
|
|
2
|
-
//# sourceMappingURL=useSeekDrag-Cc0wpC70.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useSeekDrag-Cc0wpC70.cjs","sources":["../src/hooks/useGinger.ts","../src/analyzer/liveAudioGraph.ts","../src/analyzer/useGingerLiveAnalyzer.ts","../src/hooks/useGingerKeyboardShortcuts.ts","../src/hooks/useGingerChapters.ts","../src/internal/lyrics.ts","../src/hooks/useGingerLyricsSync.ts","../src/hooks/useGingerSleepTimer.ts","../src/hooks/useGingerDebugLog.ts","../src/hooks/useSeekDrag.ts"],"sourcesContent":["import { useMemo } from \"react\";\nimport { gingerStateFromContextValues, useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\nimport {\n derivePlaybackUiState,\n effectiveDuration,\n effectiveRemaining,\n getCurrentTrack,\n progressFraction,\n resolvedAlbumLine,\n resolvedArtwork,\n} from \"../internal/selectors\";\n\nexport function useGinger() {\n const pb = useGingerPlayback();\n const md = useGingerMedia();\n\n return useMemo(\n () => {\n const state = gingerStateFromContextValues(pb, md);\n return {\n state,\n currentTrack: getCurrentTrack(state),\n playbackUi: derivePlaybackUiState(state),\n duration: effectiveDuration(state),\n remaining: effectiveRemaining(state),\n progress: progressFraction(state),\n artworkUrl: resolvedArtwork(state),\n albumLine: resolvedAlbumLine(state),\n play: pb.play,\n pause: pb.pause,\n togglePlayPause: pb.togglePlayPause,\n seek: md.seek,\n setVolume: md.setVolume,\n setMuted: md.setMuted,\n toggleMute: md.toggleMute,\n setPlaybackRate: md.setPlaybackRate,\n next: pb.next,\n prev: pb.prev,\n setRepeatMode: pb.setRepeatMode,\n cycleRepeat: pb.cycleRepeat,\n toggleShuffle: pb.toggleShuffle,\n setQueue: pb.setQueue,\n insertTrackAt: pb.insertTrackAt,\n removeTrackAt: pb.removeTrackAt,\n moveTrack: pb.moveTrack,\n enqueueNext: pb.enqueueNext,\n playTrackAt: pb.playTrackAt,\n selectTrackAt: pb.selectTrackAt,\n setPlaylistMeta: pb.setPlaylistMeta,\n init: pb.init,\n audioRef: md.audioRef,\n dispatch: pb.dispatch,\n };\n },\n [pb, md],\n );\n}\n","/** One MediaElementAudioSourceNode per HTMLAudioElement; multiple AnalyserNodes may tap the source. */\n\nexport type LiveAnalyserOptions = {\n fftSize: number;\n smoothingTimeConstant: number;\n minDecibels: number;\n maxDecibels: number;\n};\n\ntype Consumer = {\n analyser: AnalyserNode;\n /** This analyser is wired to `audioContext.destination` so the graph is audible. */\n isPlaybackSink: boolean;\n};\n\ntype ElementEntry = {\n context: AudioContext;\n source: MediaElementAudioSourceNode;\n consumers: Map<number, Consumer>;\n nextId: number;\n};\n\nconst entries = new WeakMap<HTMLAudioElement, ElementEntry>();\n\nfunction clampFftSize(n: number): number {\n const p = 2 ** Math.round(Math.log2(n));\n return Math.min(32768, Math.max(32, p));\n}\n\nexport function attachLiveAnalyser(\n element: HTMLAudioElement,\n options: LiveAnalyserOptions,\n): { id: number; context: AudioContext; analyser: AnalyserNode } {\n let entry = entries.get(element);\n if (!entry) {\n const Context = window.AudioContext ?? (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!Context) {\n throw new Error(\"Web Audio API is not available\");\n }\n const context = new Context();\n const source = context.createMediaElementSource(element);\n entry = { context, source, consumers: new Map(), nextId: 0 };\n entries.set(element, entry);\n }\n\n const { context, source } = entry;\n const analyser = context.createAnalyser();\n analyser.fftSize = clampFftSize(options.fftSize);\n analyser.smoothingTimeConstant = options.smoothingTimeConstant;\n analyser.minDecibels = options.minDecibels;\n analyser.maxDecibels = options.maxDecibels;\n\n source.connect(analyser);\n\n const isFirst = entry.consumers.size === 0;\n if (isFirst) {\n analyser.connect(context.destination);\n }\n\n const id = entry.nextId;\n entry.nextId += 1;\n entry.consumers.set(id, { analyser, isPlaybackSink: isFirst });\n\n return { id, context, analyser };\n}\n\nexport function detachLiveAnalyser(element: HTMLAudioElement, id: number): void {\n const entry = entries.get(element);\n if (!entry) return;\n\n const consumer = entry.consumers.get(id);\n if (!consumer) return;\n\n const { analyser, isPlaybackSink } = consumer;\n analyser.disconnect();\n entry.consumers.delete(id);\n\n if (entry.consumers.size === 0) {\n try {\n entry.source.disconnect();\n } catch {\n // ignore\n }\n void entry.context.close();\n entries.delete(element);\n return;\n }\n\n if (isPlaybackSink) {\n const first = entry.consumers.values().next().value as Consumer | undefined;\n if (first) {\n first.analyser.connect(entry.context.destination);\n first.isPlaybackSink = true;\n }\n }\n}\n","import { useCallback, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { useGinger } from \"../hooks/useGinger\";\nimport { attachLiveAnalyser, detachLiveAnalyser, type LiveAnalyserOptions } from \"./liveAudioGraph\";\n\nexport type UseGingerLiveAnalyzerOptions = {\n /** When false, the analyser is detached and no frames are read. Default true. */\n enabled?: boolean;\n fftSize?: number;\n smoothingTimeConstant?: number;\n minDecibels?: number;\n maxDecibels?: number;\n};\n\nexport type UseGingerLiveAnalyzerResult = {\n /** Byte frequency data (0–255); length equals `frequencyBinCount`. Updated each animation frame while enabled. */\n frequencyData: Uint8Array;\n /** Byte time-domain data (0–255); length equals `fftSize`. */\n timeDomainData: Uint8Array;\n frequencyBinCount: number;\n sampleRate: number;\n isSuspended: boolean;\n error: string | null;\n resume: () => Promise<void>;\n};\n\nconst emptyFreq = new Uint8Array(0);\nconst emptyTime = new Uint8Array(0);\n\nexport function useGingerLiveAnalyzer(options: UseGingerLiveAnalyzerOptions = {}): UseGingerLiveAnalyzerResult {\n const {\n enabled = true,\n fftSize = 2048,\n smoothingTimeConstant = 0.8,\n minDecibels = -100,\n maxDecibels = -30,\n } = options;\n\n const { audioRef, state } = useGinger();\n const opts = useMemo<LiveAnalyserOptions>(\n () => ({\n fftSize,\n smoothingTimeConstant,\n minDecibels,\n maxDecibels,\n }),\n [fftSize, smoothingTimeConstant, minDecibels, maxDecibels],\n );\n\n const [frame, setFrame] = useState(0);\n const [error, setError] = useState<string | null>(null);\n const [isSuspended, setIsSuspended] = useState(false);\n const [meta, setMeta] = useState({ frequencyBinCount: 0, sampleRate: 0 });\n\n const freqRef = useRef<Uint8Array>(emptyFreq);\n const timeRef = useRef<Uint8Array>(emptyTime);\n\n const resume = useCallback(async () => {\n const ctx = contextHolderRef.current;\n if (ctx && ctx.state === \"suspended\") {\n await ctx.resume();\n }\n }, []);\n\n const contextHolderRef = useRef<AudioContext | null>(null);\n const analyserHolderRef = useRef<AnalyserNode | null>(null);\n\n useLayoutEffect(() => {\n if (!enabled || typeof window === \"undefined\") {\n return;\n }\n\n let cancelled = false;\n let consumerId: number | null = null;\n let element: HTMLAudioElement | null = null;\n let rafId = 0;\n\n const onStateChange = () => {\n const ctx = contextHolderRef.current;\n if (ctx) setIsSuspended(ctx.state === \"suspended\");\n };\n\n const runLoop = () => {\n if (cancelled) return;\n const a = analyserHolderRef.current;\n const fq = freqRef.current;\n const td = timeRef.current;\n if (a && fq.length > 0 && td.length > 0) {\n a.getByteFrequencyData(fq as Uint8Array<ArrayBuffer>);\n a.getByteTimeDomainData(td as Uint8Array<ArrayBuffer>);\n setFrame((n) => n + 1);\n }\n rafId = requestAnimationFrame(runLoop);\n };\n\n type AttachOutcome = \"ok\" | \"no-element\" | \"error\";\n\n const attach = (): AttachOutcome => {\n const el = audioRef.current;\n if (!el || cancelled) return \"no-element\";\n try {\n const { id, context, analyser } = attachLiveAnalyser(el, opts);\n consumerId = id;\n element = el;\n contextHolderRef.current = context;\n analyserHolderRef.current = analyser;\n setIsSuspended(context.state === \"suspended\");\n setError(null);\n\n context.addEventListener(\"statechange\", onStateChange);\n\n const n = analyser.frequencyBinCount;\n const fft = analyser.fftSize;\n freqRef.current = new Uint8Array(n);\n timeRef.current = new Uint8Array(fft);\n setMeta({ frequencyBinCount: n, sampleRate: context.sampleRate });\n\n rafId = requestAnimationFrame(runLoop);\n return \"ok\";\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"Failed to attach live analyser\";\n setError(msg);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n setMeta({ frequencyBinCount: 0, sampleRate: 0 });\n return \"error\";\n }\n };\n\n const first = attach();\n if (first !== \"ok\") {\n let retryRaf = 0;\n const maxAttempts = 120;\n let attempts = 0;\n\n const retryLoop = () => {\n if (cancelled) return;\n const out = attach();\n if (out === \"ok\" || out === \"error\") return;\n attempts += 1;\n if (attempts >= maxAttempts) return;\n retryRaf = requestAnimationFrame(retryLoop);\n };\n\n if (first === \"no-element\") {\n retryRaf = requestAnimationFrame(retryLoop);\n }\n\n return () => {\n cancelled = true;\n cancelAnimationFrame(retryRaf);\n cancelAnimationFrame(rafId);\n if (consumerId != null && element) {\n detachLiveAnalyser(element, consumerId);\n }\n contextHolderRef.current?.removeEventListener(\"statechange\", onStateChange);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n };\n }\n\n return () => {\n cancelled = true;\n cancelAnimationFrame(rafId);\n if (consumerId != null && element) {\n detachLiveAnalyser(element, consumerId);\n }\n contextHolderRef.current?.removeEventListener(\"statechange\", onStateChange);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n setMeta({ frequencyBinCount: 0, sampleRate: 0 });\n };\n }, [enabled, audioRef, opts, state.currentIndex]);\n\n void frame;\n\n return {\n frequencyData: freqRef.current,\n timeDomainData: timeRef.current,\n frequencyBinCount: meta.frequencyBinCount,\n sampleRate: meta.sampleRate,\n isSuspended,\n error,\n resume,\n };\n}\n","import { useEffect } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerKeyboardShortcutBindings = {\n playPause?: string;\n next?: string;\n previous?: string;\n mute?: string;\n};\n\nexport function useGingerKeyboardShortcuts(\n enabled = true,\n bindings: GingerKeyboardShortcutBindings = {},\n): void {\n const { togglePlayPause, next, prev } = useGingerPlayback();\n const { toggleMute } = useGingerMedia();\n\n const muteBinding = bindings.mute;\n\n useEffect(() => {\n if (!enabled || typeof window === \"undefined\") return;\n const playPause = (bindings.playPause ?? \" \").toLowerCase();\n const nextKey = (bindings.next ?? \"ArrowRight\").toLowerCase();\n const prevKey = (bindings.previous ?? \"ArrowLeft\").toLowerCase();\n const muteKey = muteBinding?.toLowerCase();\n\n const onKeyDown = (event: KeyboardEvent) => {\n const target = event.target as HTMLElement | null;\n if (target && ([\"INPUT\", \"TEXTAREA\", \"SELECT\"].includes(target.tagName) || target.isContentEditable)) return;\n const key = event.key.toLowerCase();\n if (key === playPause) {\n event.preventDefault();\n togglePlayPause();\n } else if (key === nextKey) {\n event.preventDefault();\n next();\n } else if (key === prevKey) {\n event.preventDefault();\n prev();\n } else if (muteKey && key === muteKey) {\n event.preventDefault();\n toggleMute();\n }\n };\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, [bindings.next, bindings.playPause, bindings.previous, enabled, muteBinding, next, prev, toggleMute, togglePlayPause]);\n}\n","import { useMemo } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerChapter = {\n title: string;\n startSeconds: number;\n};\n\nexport type GingerChapterState = {\n list: GingerChapter[];\n activeIndex: number;\n active: GingerChapter | null;\n seekTo: (index: number) => void;\n};\n\nexport function useGingerChapters(): GingerChapterState {\n const { tracks, currentIndex } = useGingerPlayback();\n const { currentTime, seek } = useGingerMedia();\n\n const list = useMemo(() => {\n const chapters = tracks[currentIndex]?.chapters ?? [];\n return [...chapters]\n .filter((item) => item && Number.isFinite(item.startSeconds) && item.startSeconds >= 0)\n .sort((a, b) => a.startSeconds - b.startSeconds);\n }, [currentIndex, tracks]);\n\n const activeIndex = useMemo(() => {\n if (list.length === 0) return -1;\n for (let i = list.length - 1; i >= 0; i -= 1) {\n if (currentTime >= list[i]!.startSeconds) return i;\n }\n return -1;\n }, [currentTime, list]);\n\n return {\n list,\n activeIndex,\n active: activeIndex >= 0 ? list[activeIndex] ?? null : null,\n seekTo: (index: number) => {\n const chapter = list[index];\n if (chapter) seek(chapter.startSeconds);\n },\n };\n}\n","export type TimedLyricLine = {\n time: number;\n text: string;\n};\n\nconst lrcTag = /\\[(\\d{1,2}):(\\d{2})(?:\\.(\\d{1,3}))?\\]/g;\n\nexport function parseLrc(lrc: string): TimedLyricLine[] {\n const lines: TimedLyricLine[] = [];\n for (const rawLine of lrc.split(/\\r?\\n/)) {\n const matches = [...rawLine.matchAll(lrcTag)];\n if (matches.length === 0) continue;\n const text = rawLine.replace(lrcTag, \"\").trim();\n for (const m of matches) {\n const minutes = Number(m[1] ?? 0);\n const seconds = Number(m[2] ?? 0);\n const millis = Number((m[3] ?? \"0\").padEnd(3, \"0\"));\n const time = minutes * 60 + seconds + millis / 1000;\n if (Number.isFinite(time) && time >= 0) {\n lines.push({ time, text });\n }\n }\n }\n return lines.sort((a, b) => a.time - b.time);\n}\n","import { useMemo } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\nimport { parseLrc, type TimedLyricLine } from \"../internal/lyrics\";\n\nexport type GingerLyricsSyncState = {\n lines: TimedLyricLine[];\n activeIndex: number;\n activeLine: TimedLyricLine | null;\n};\n\nexport function useGingerLyricsSync(): GingerLyricsSyncState {\n const { tracks, currentIndex } = useGingerPlayback();\n const { currentTime } = useGingerMedia();\n const currentTrack = tracks[currentIndex];\n\n const lines = useMemo(() => {\n if (!currentTrack) return [];\n if (Array.isArray(currentTrack.lyricsTimed) && currentTrack.lyricsTimed.length > 0) {\n return [...currentTrack.lyricsTimed]\n .filter((line) => Number.isFinite(line.time) && line.time >= 0)\n .sort((a, b) => a.time - b.time);\n }\n if (typeof currentTrack.lyrics === \"string\") {\n return parseLrc(currentTrack.lyrics);\n }\n return [];\n }, [currentTrack]);\n\n const activeIndex = useMemo(() => {\n for (let i = lines.length - 1; i >= 0; i -= 1) {\n if (currentTime >= lines[i]!.time) return i;\n }\n return -1;\n }, [currentTime, lines]);\n\n return {\n lines,\n activeIndex,\n activeLine: activeIndex >= 0 ? lines[activeIndex] ?? null : null,\n };\n}\n","import { useEffect, useRef } from \"react\";\nimport { useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerSleepTimerOptions = {\n durationMs?: number;\n stopAfterTracks?: number;\n respectPause?: boolean;\n enabled?: boolean;\n onFire?: () => void;\n};\n\nexport function useGingerSleepTimer(options: GingerSleepTimerOptions): void {\n const { durationMs, stopAfterTracks, respectPause = true, enabled = true, onFire } = options;\n const { currentIndex, pause, isPaused } = useGingerPlayback();\n const remainingTracksRef = useRef(stopAfterTracks ?? 0);\n const prevIndexRef = useRef(currentIndex);\n\n useEffect(() => {\n remainingTracksRef.current = stopAfterTracks ?? 0;\n }, [stopAfterTracks]);\n\n useEffect(() => {\n if (!enabled || !durationMs || durationMs <= 0) return;\n if (respectPause && isPaused) return;\n const id = setTimeout(() => {\n pause();\n onFire?.();\n }, durationMs);\n return () => clearTimeout(id);\n }, [durationMs, enabled, isPaused, onFire, pause, respectPause]);\n\n useEffect(() => {\n if (!enabled || !stopAfterTracks || stopAfterTracks <= 0) return;\n const prev = prevIndexRef.current;\n prevIndexRef.current = currentIndex;\n if (currentIndex === prev) return;\n remainingTracksRef.current -= 1;\n if (remainingTracksRef.current <= 0) {\n pause();\n onFire?.();\n }\n }, [currentIndex, enabled, onFire, pause, stopAfterTracks]);\n}\n","import { useEffect, useRef } from \"react\";\nimport { useGingerState } from \"../context/GingerSplitContexts\";\n\nexport function useGingerDebugLog(enabled = false): void {\n const state = useGingerState();\n const prevRef = useRef(state);\n\n useEffect(() => {\n if (!enabled || typeof console === \"undefined\") return;\n const prev = prevRef.current;\n if (prev !== state) {\n console.debug(\"[ginger]\", {\n from: {\n currentIndex: prev.currentIndex,\n isPaused: prev.isPaused,\n currentTime: prev.currentTime,\n repeatMode: prev.repeatMode,\n },\n to: {\n currentIndex: state.currentIndex,\n isPaused: state.isPaused,\n currentTime: state.currentTime,\n repeatMode: state.repeatMode,\n },\n });\n }\n prevRef.current = state;\n }, [enabled, state]);\n}\n","import { useCallback, useState } from \"react\";\nimport type { PointerEvent as ReactPointerEvent } from \"react\";\nimport { useGingerMedia, useGingerPlayback, gingerStateFromContextValues } from \"../context/GingerSplitContexts\";\nimport { progressFraction } from \"../internal/selectors\";\n\nexport type SeekDragState = {\n /** Raw drag fraction — only updated during an active drag gesture. */\n fraction: number;\n /** Blended fraction: follows live playback when idle, drag position when dragging. */\n displayFraction: number;\n isDragging: boolean;\n onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n};\n\nfunction clamp01(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nexport function useSeekDrag(duration: number): SeekDragState {\n const media = useGingerMedia();\n const playback = useGingerPlayback();\n const { seek } = media;\n const [fraction, setFraction] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n\n const liveFraction = progressFraction(gingerStateFromContextValues(playback, media));\n const displayFraction = isDragging ? fraction : liveFraction;\n\n const onPointerDown = useCallback(\n (event: ReactPointerEvent<HTMLElement>) => {\n if (!(duration > 0)) return;\n const target = event.currentTarget;\n const rect = target.getBoundingClientRect();\n const update = (clientX: number) => {\n const ratio = clamp01((clientX - rect.left) / rect.width);\n setFraction(ratio);\n seek(ratio * duration);\n };\n setIsDragging(true);\n target.setPointerCapture(event.pointerId);\n update(event.clientX);\n const onMove = (moveEvent: PointerEvent) => update(moveEvent.clientX);\n const onUp = (upEvent: PointerEvent) => {\n update(upEvent.clientX);\n setIsDragging(false);\n target.releasePointerCapture(event.pointerId);\n target.removeEventListener(\"pointermove\", onMove);\n target.removeEventListener(\"pointerup\", onUp);\n target.removeEventListener(\"pointercancel\", onUp);\n };\n target.addEventListener(\"pointermove\", onMove);\n target.addEventListener(\"pointerup\", onUp);\n target.addEventListener(\"pointercancel\", onUp);\n },\n [duration, seek],\n );\n\n return { fraction, displayFraction, isDragging, onPointerDown };\n}\n"],"names":["useGinger","pb","useGingerPlayback","md","useGingerMedia","useMemo","state","gingerStateFromContextValues","getCurrentTrack","derivePlaybackUiState","effectiveDuration","effectiveRemaining","progressFraction","resolvedArtwork","resolvedAlbumLine","entries","clampFftSize","p","attachLiveAnalyser","element","options","entry","Context","context","source","analyser","isFirst","id","detachLiveAnalyser","consumer","isPlaybackSink","first","emptyFreq","emptyTime","useGingerLiveAnalyzer","enabled","fftSize","smoothingTimeConstant","minDecibels","maxDecibels","audioRef","opts","frame","setFrame","useState","error","setError","isSuspended","setIsSuspended","meta","setMeta","freqRef","useRef","timeRef","resume","useCallback","ctx","contextHolderRef","analyserHolderRef","useLayoutEffect","cancelled","consumerId","rafId","onStateChange","runLoop","a","fq","td","n","attach","el","fft","e","msg","retryRaf","maxAttempts","attempts","retryLoop","out","_a","useGingerKeyboardShortcuts","bindings","togglePlayPause","next","prev","toggleMute","muteBinding","useEffect","playPause","nextKey","prevKey","muteKey","onKeyDown","event","target","key","useGingerChapters","tracks","currentIndex","currentTime","seek","list","item","b","activeIndex","i","index","chapter","lrcTag","parseLrc","lrc","lines","rawLine","matches","text","m","minutes","seconds","millis","time","useGingerLyricsSync","currentTrack","line","useGingerSleepTimer","durationMs","stopAfterTracks","respectPause","onFire","pause","isPaused","remainingTracksRef","prevIndexRef","useGingerDebugLog","useGingerState","prevRef","clamp01","value","useSeekDrag","duration","media","playback","fraction","setFraction","isDragging","setIsDragging","liveFraction","displayFraction","onPointerDown","rect","update","clientX","ratio","onMove","moveEvent","onUp","upEvent"],"mappings":"yHAYO,SAASA,GAAY,CAC1B,MAAMC,EAAKC,EAAAA,kBAAA,EACLC,EAAKC,EAAAA,eAAA,EAEX,OAAOC,EAAAA,QACL,IAAM,CACJ,MAAMC,EAAQC,EAAAA,6BAA6BN,EAAIE,CAAE,EACjD,MAAO,CACL,MAAAG,EACA,aAAcE,EAAAA,gBAAgBF,CAAK,EACnC,WAAYG,EAAAA,sBAAsBH,CAAK,EACvC,SAAUI,EAAAA,kBAAkBJ,CAAK,EACjC,UAAWK,EAAAA,mBAAmBL,CAAK,EACnC,SAAUM,EAAAA,iBAAiBN,CAAK,EAChC,WAAYO,EAAAA,gBAAgBP,CAAK,EACjC,UAAWQ,EAAAA,kBAAkBR,CAAK,EAClC,KAAML,EAAG,KACT,MAAOA,EAAG,MACV,gBAAiBA,EAAG,gBACpB,KAAME,EAAG,KACT,UAAWA,EAAG,UACd,SAAUA,EAAG,SACb,WAAYA,EAAG,WACf,gBAAiBA,EAAG,gBACpB,KAAMF,EAAG,KACT,KAAMA,EAAG,KACT,cAAeA,EAAG,cAClB,YAAaA,EAAG,YAChB,cAAeA,EAAG,cAClB,SAAUA,EAAG,SACb,cAAeA,EAAG,cAClB,cAAeA,EAAG,cAClB,UAAWA,EAAG,UACd,YAAaA,EAAG,YAChB,YAAaA,EAAG,YAChB,cAAeA,EAAG,cAClB,gBAAiBA,EAAG,gBACpB,KAAMA,EAAG,KACT,SAAUE,EAAG,SACb,SAAUF,EAAG,QAAA,CAEjB,EACA,CAACA,EAAIE,CAAE,CAAA,CAEX,CClCA,MAAMY,MAAc,QAEpB,SAASC,EAAa,EAAmB,CACvC,MAAMC,EAAI,GAAK,KAAK,MAAM,KAAK,KAAK,CAAC,CAAC,EACtC,OAAO,KAAK,IAAI,MAAO,KAAK,IAAI,GAAIA,CAAC,CAAC,CACxC,CAEO,SAASC,EACdC,EACAC,EAC+D,CAC/D,IAAIC,EAAQN,EAAQ,IAAII,CAAO,EAC/B,GAAI,CAACE,EAAO,CACV,MAAMC,EAAU,OAAO,cAAiB,OAAmE,mBAC3G,GAAI,CAACA,EACH,MAAM,IAAI,MAAM,gCAAgC,EAElD,MAAMC,EAAU,IAAID,EACdE,EAASD,EAAQ,yBAAyBJ,CAAO,EACvDE,EAAQ,CAAE,QAAAE,EAAS,OAAAC,EAAQ,UAAW,IAAI,IAAO,OAAQ,CAAA,EACzDT,EAAQ,IAAII,EAASE,CAAK,CAC5B,CAEA,KAAM,CAAE,QAAAE,EAAS,OAAAC,CAAA,EAAWH,EACtBI,EAAWF,EAAQ,eAAA,EACzBE,EAAS,QAAUT,EAAaI,EAAQ,OAAO,EAC/CK,EAAS,sBAAwBL,EAAQ,sBACzCK,EAAS,YAAcL,EAAQ,YAC/BK,EAAS,YAAcL,EAAQ,YAE/BI,EAAO,QAAQC,CAAQ,EAEvB,MAAMC,EAAUL,EAAM,UAAU,OAAS,EACrCK,GACFD,EAAS,QAAQF,EAAQ,WAAW,EAGtC,MAAMI,EAAKN,EAAM,OACjB,OAAAA,EAAM,QAAU,EAChBA,EAAM,UAAU,IAAIM,EAAI,CAAE,SAAAF,EAAU,eAAgBC,EAAS,EAEtD,CAAE,GAAAC,EAAI,QAAAJ,EAAS,SAAAE,CAAA,CACxB,CAEO,SAASG,EAAmBT,EAA2BQ,EAAkB,CAC9E,MAAMN,EAAQN,EAAQ,IAAII,CAAO,EACjC,GAAI,CAACE,EAAO,OAEZ,MAAMQ,EAAWR,EAAM,UAAU,IAAIM,CAAE,EACvC,GAAI,CAACE,EAAU,OAEf,KAAM,CAAE,SAAAJ,EAAU,eAAAK,CAAA,EAAmBD,EAIrC,GAHAJ,EAAS,WAAA,EACTJ,EAAM,UAAU,OAAOM,CAAE,EAErBN,EAAM,UAAU,OAAS,EAAG,CAC9B,GAAI,CACFA,EAAM,OAAO,WAAA,CACf,MAAQ,CAER,CACKA,EAAM,QAAQ,MAAA,EACnBN,EAAQ,OAAOI,CAAO,EACtB,MACF,CAEA,GAAIW,EAAgB,CAClB,MAAMC,EAAQV,EAAM,UAAU,OAAA,EAAS,OAAO,MAC1CU,IACFA,EAAM,SAAS,QAAQV,EAAM,QAAQ,WAAW,EAChDU,EAAM,eAAiB,GAE3B,CACF,CCtEA,MAAMC,EAAY,IAAI,WAAW,CAAC,EAC5BC,EAAY,IAAI,WAAW,CAAC,EAE3B,SAASC,EAAsBd,EAAwC,GAAiC,CAC7G,KAAM,CACJ,QAAAe,EAAU,GACV,QAAAC,EAAU,KACV,sBAAAC,EAAwB,GACxB,YAAAC,EAAc,KACd,YAAAC,EAAc,GAAA,EACZnB,EAEE,CAAE,SAAAoB,EAAU,MAAAlC,CAAA,EAAUN,EAAA,EACtByC,EAAOpC,EAAAA,QACX,KAAO,CACL,QAAA+B,EACA,sBAAAC,EACA,YAAAC,EACA,YAAAC,CAAA,GAEF,CAACH,EAASC,EAAuBC,EAAaC,CAAW,CAAA,EAGrD,CAACG,EAAOC,CAAQ,EAAIC,EAAAA,SAAS,CAAC,EAC9B,CAACC,EAAOC,CAAQ,EAAIF,EAAAA,SAAwB,IAAI,EAChD,CAACG,EAAaC,CAAc,EAAIJ,EAAAA,SAAS,EAAK,EAC9C,CAACK,EAAMC,CAAO,EAAIN,EAAAA,SAAS,CAAE,kBAAmB,EAAG,WAAY,EAAG,EAElEO,EAAUC,EAAAA,OAAmBpB,CAAS,EACtCqB,EAAUD,EAAAA,OAAmBnB,CAAS,EAEtCqB,EAASC,EAAAA,YAAY,SAAY,CACrC,MAAMC,EAAMC,EAAiB,QACzBD,GAAOA,EAAI,QAAU,aACvB,MAAMA,EAAI,OAAA,CAEd,EAAG,CAAA,CAAE,EAECC,EAAmBL,EAAAA,OAA4B,IAAI,EACnDM,EAAoBN,EAAAA,OAA4B,IAAI,EAE1DO,OAAAA,EAAAA,gBAAgB,IAAM,CACpB,GAAI,CAACxB,GAAW,OAAO,OAAW,IAChC,OAGF,IAAIyB,EAAY,GACZC,EAA4B,KAC5B1C,EAAmC,KACnC2C,EAAQ,EAEZ,MAAMC,EAAgB,IAAM,CAC1B,MAAMP,EAAMC,EAAiB,QACzBD,GAAKR,EAAeQ,EAAI,QAAU,WAAW,CACnD,EAEMQ,EAAU,IAAM,CACpB,GAAIJ,EAAW,OACf,MAAMK,EAAIP,EAAkB,QACtBQ,EAAKf,EAAQ,QACbgB,EAAKd,EAAQ,QACXY,GAAKC,EAAG,OAAS,GAAKC,EAAG,OAAS,IACpCF,EAAE,qBAAqBC,CAA6B,EACpDD,EAAE,sBAAsBE,CAA6B,EACzDxB,EAAUyB,GAAMA,EAAI,CAAC,GAEvBN,EAAQ,sBAAsBE,CAAO,CACvC,EAIMK,EAAS,IAAqB,CAClC,MAAMC,EAAK9B,EAAS,QACpB,GAAI,CAAC8B,GAAMV,EAAW,MAAO,aAC7B,GAAI,CACF,KAAM,CAAE,GAAAjC,EAAI,QAAAJ,EAAS,SAAAE,GAAaP,EAAmBoD,EAAI7B,CAAI,EAC7DoB,EAAalC,EACbR,EAAUmD,EACVb,EAAiB,QAAUlC,EAC3BmC,EAAkB,QAAUjC,EAC5BuB,EAAezB,EAAQ,QAAU,WAAW,EAC5CuB,EAAS,IAAI,EAEbvB,EAAQ,iBAAiB,cAAewC,CAAa,EAErD,MAAMK,EAAI3C,EAAS,kBACb8C,EAAM9C,EAAS,QACrB,OAAA0B,EAAQ,QAAU,IAAI,WAAWiB,CAAC,EAClCf,EAAQ,QAAU,IAAI,WAAWkB,CAAG,EACpCrB,EAAQ,CAAE,kBAAmBkB,EAAG,WAAY7C,EAAQ,WAAY,EAEhEuC,EAAQ,sBAAsBE,CAAO,EAC9B,IACT,OAASQ,EAAG,CACV,MAAMC,EAAMD,aAAa,MAAQA,EAAE,QAAU,iCAC7C,OAAA1B,EAAS2B,CAAG,EACZhB,EAAiB,QAAU,KAC3BC,EAAkB,QAAU,KAC5BP,EAAQ,QAAUnB,EAClBqB,EAAQ,QAAUpB,EAClBiB,EAAQ,CAAE,kBAAmB,EAAG,WAAY,EAAG,EACxC,OACT,CACF,EAEMnB,EAAQsC,EAAA,EACd,GAAItC,IAAU,KAAM,CAClB,IAAI2C,EAAW,EACf,MAAMC,EAAc,IACpB,IAAIC,EAAW,EAEf,MAAMC,EAAY,IAAM,CACtB,GAAIjB,EAAW,OACf,MAAMkB,EAAMT,EAAA,EACRS,IAAQ,MAAQA,IAAQ,UAC5BF,GAAY,EACR,EAAAA,GAAYD,KAChBD,EAAW,sBAAsBG,CAAS,GAC5C,EAEA,OAAI9C,IAAU,eACZ2C,EAAW,sBAAsBG,CAAS,GAGrC,IAAM,OACXjB,EAAY,GACZ,qBAAqBc,CAAQ,EAC7B,qBAAqBZ,CAAK,EACtBD,GAAc,MAAQ1C,GACxBS,EAAmBT,EAAS0C,CAAU,GAExCkB,EAAAtB,EAAiB,UAAjB,MAAAsB,EAA0B,oBAAoB,cAAehB,GAC7DN,EAAiB,QAAU,KAC3BC,EAAkB,QAAU,KAC5BP,EAAQ,QAAUnB,EAClBqB,EAAQ,QAAUpB,CACpB,CACF,CAEA,MAAO,IAAM,OACX2B,EAAY,GACZ,qBAAqBE,CAAK,EACtBD,GAAc,MAAQ1C,GACxBS,EAAmBT,EAAS0C,CAAU,GAExCkB,EAAAtB,EAAiB,UAAjB,MAAAsB,EAA0B,oBAAoB,cAAehB,GAC7DN,EAAiB,QAAU,KAC3BC,EAAkB,QAAU,KAC5BP,EAAQ,QAAUnB,EAClBqB,EAAQ,QAAUpB,EAClBiB,EAAQ,CAAE,kBAAmB,EAAG,WAAY,EAAG,CACjD,CACF,EAAG,CAACf,EAASK,EAAUC,EAAMnC,EAAM,YAAY,CAAC,EAIzC,CACL,cAAe6C,EAAQ,QACvB,eAAgBE,EAAQ,QACxB,kBAAmBJ,EAAK,kBACxB,WAAYA,EAAK,WACjB,YAAAF,EACA,MAAAF,EACA,OAAAS,CAAA,CAEJ,CCpLO,SAAS0B,EACd7C,EAAU,GACV8C,EAA2C,CAAA,EACrC,CACN,KAAM,CAAE,gBAAAC,EAAiB,KAAAC,EAAM,KAAAC,CAAA,EAASlF,EAAAA,kBAAA,EAClC,CAAE,WAAAmF,CAAA,EAAejF,iBAAA,EAEjBkF,EAAcL,EAAS,KAE7BM,EAAAA,UAAU,IAAM,CACd,GAAI,CAACpD,GAAW,OAAO,OAAW,IAAa,OAC/C,MAAMqD,GAAaP,EAAS,WAAa,KAAK,YAAA,EACxCQ,GAAWR,EAAS,MAAQ,cAAc,YAAA,EAC1CS,GAAWT,EAAS,UAAY,aAAa,YAAA,EAC7CU,EAAUL,GAAA,YAAAA,EAAa,cAEvBM,EAAaC,GAAyB,CAC1C,MAAMC,EAASD,EAAM,OACrB,GAAIC,IAAW,CAAC,QAAS,WAAY,QAAQ,EAAE,SAASA,EAAO,OAAO,GAAKA,EAAO,mBAAoB,OACtG,MAAMC,EAAMF,EAAM,IAAI,YAAA,EAClBE,IAAQP,GACVK,EAAM,eAAA,EACNX,EAAA,GACSa,IAAQN,GACjBI,EAAM,eAAA,EACNV,EAAA,GACSY,IAAQL,GACjBG,EAAM,eAAA,EACNT,EAAA,GACSO,GAAWI,IAAQJ,IAC5BE,EAAM,eAAA,EACNR,EAAA,EAEJ,EACA,cAAO,iBAAiB,UAAWO,CAAS,EACrC,IAAM,OAAO,oBAAoB,UAAWA,CAAS,CAC9D,EAAG,CAACX,EAAS,KAAMA,EAAS,UAAWA,EAAS,SAAU9C,EAASmD,EAAaH,EAAMC,EAAMC,EAAYH,CAAe,CAAC,CAC1H,CChCO,SAASc,GAAwC,CACtD,KAAM,CAAE,OAAAC,EAAQ,aAAAC,CAAA,EAAiBhG,oBAAA,EAC3B,CAAE,YAAAiG,EAAa,KAAAC,CAAA,EAAShG,iBAAA,EAExBiG,EAAOhG,EAAAA,QAAQ,IAAM,OAEzB,MAAO,CAAC,KADS0E,EAAAkB,EAAOC,CAAY,IAAnB,YAAAnB,EAAsB,WAAY,CAAA,CAChC,EAChB,OAAQuB,GAASA,GAAQ,OAAO,SAASA,EAAK,YAAY,GAAKA,EAAK,cAAgB,CAAC,EACrF,KAAK,CAACrC,EAAGsC,IAAMtC,EAAE,aAAesC,EAAE,YAAY,CACnD,EAAG,CAACL,EAAcD,CAAM,CAAC,EAEnBO,EAAcnG,EAAAA,QAAQ,IAAM,CAChC,GAAIgG,EAAK,SAAW,EAAG,MAAO,GAC9B,QAASI,EAAIJ,EAAK,OAAS,EAAGI,GAAK,EAAGA,GAAK,EACzC,GAAIN,GAAeE,EAAKI,CAAC,EAAG,aAAc,OAAOA,EAEnD,MAAO,EACT,EAAG,CAACN,EAAaE,CAAI,CAAC,EAEtB,MAAO,CACL,KAAAA,EACA,YAAAG,EACA,OAAQA,GAAe,EAAIH,EAAKG,CAAW,GAAK,KAAO,KACvD,OAASE,GAAkB,CACzB,MAAMC,EAAUN,EAAKK,CAAK,EACtBC,GAASP,EAAKO,EAAQ,YAAY,CACxC,CAAA,CAEJ,CCtCA,MAAMC,EAAS,yCAER,SAASC,EAASC,EAA+B,CACtD,MAAMC,EAA0B,CAAA,EAChC,UAAWC,KAAWF,EAAI,MAAM,OAAO,EAAG,CACxC,MAAMG,EAAU,CAAC,GAAGD,EAAQ,SAASJ,CAAM,CAAC,EAC5C,GAAIK,EAAQ,SAAW,EAAG,SAC1B,MAAMC,EAAOF,EAAQ,QAAQJ,EAAQ,EAAE,EAAE,KAAA,EACzC,UAAWO,KAAKF,EAAS,CACvB,MAAMG,EAAU,OAAOD,EAAE,CAAC,GAAK,CAAC,EAC1BE,EAAU,OAAOF,EAAE,CAAC,GAAK,CAAC,EAC1BG,EAAS,QAAQH,EAAE,CAAC,GAAK,KAAK,OAAO,EAAG,GAAG,CAAC,EAC5CI,EAAOH,EAAU,GAAKC,EAAUC,EAAS,IAC3C,OAAO,SAASC,CAAI,GAAKA,GAAQ,GACnCR,EAAM,KAAK,CAAE,KAAAQ,EAAM,KAAAL,CAAA,CAAM,CAE7B,CACF,CACA,OAAOH,EAAM,KAAK,CAAC9C,EAAGsC,IAAMtC,EAAE,KAAOsC,EAAE,IAAI,CAC7C,CCdO,SAASiB,GAA6C,CAC3D,KAAM,CAAE,OAAAvB,EAAQ,aAAAC,CAAA,EAAiBhG,oBAAA,EAC3B,CAAE,YAAAiG,CAAA,EAAgB/F,iBAAA,EAClBqH,EAAexB,EAAOC,CAAY,EAElCa,EAAQ1G,EAAAA,QAAQ,IACfoH,EACD,MAAM,QAAQA,EAAa,WAAW,GAAKA,EAAa,YAAY,OAAS,EACxE,CAAC,GAAGA,EAAa,WAAW,EAChC,OAAQC,GAAS,OAAO,SAASA,EAAK,IAAI,GAAKA,EAAK,MAAQ,CAAC,EAC7D,KAAK,CAACzD,EAAGsC,IAAMtC,EAAE,KAAOsC,EAAE,IAAI,EAE/B,OAAOkB,EAAa,QAAW,SAC1BZ,EAASY,EAAa,MAAM,EAE9B,CAAA,EATmB,CAAA,EAUzB,CAACA,CAAY,CAAC,EAEXjB,EAAcnG,EAAAA,QAAQ,IAAM,CAChC,QAASoG,EAAIM,EAAM,OAAS,EAAGN,GAAK,EAAGA,GAAK,EAC1C,GAAIN,GAAeY,EAAMN,CAAC,EAAG,KAAM,OAAOA,EAE5C,MAAO,EACT,EAAG,CAACN,EAAaY,CAAK,CAAC,EAEvB,MAAO,CACL,MAAAA,EACA,YAAAP,EACA,WAAYA,GAAe,EAAIO,EAAMP,CAAW,GAAK,KAAO,IAAA,CAEhE,CC7BO,SAASmB,EAAoBvG,EAAwC,CAC1E,KAAM,CAAE,WAAAwG,EAAY,gBAAAC,EAAiB,aAAAC,EAAe,GAAM,QAAA3F,EAAU,GAAM,OAAA4F,GAAW3G,EAC/E,CAAE,aAAA8E,EAAc,MAAA8B,EAAO,SAAAC,CAAA,EAAa/H,EAAAA,kBAAA,EACpCgI,EAAqB9E,EAAAA,OAAOyE,GAAmB,CAAC,EAChDM,EAAe/E,EAAAA,OAAO8C,CAAY,EAExCX,EAAAA,UAAU,IAAM,CACd2C,EAAmB,QAAUL,GAAmB,CAClD,EAAG,CAACA,CAAe,CAAC,EAEpBtC,EAAAA,UAAU,IAAM,CAEd,GADI,CAACpD,GAAW,CAACyF,GAAcA,GAAc,GACzCE,GAAgBG,EAAU,OAC9B,MAAMtG,EAAK,WAAW,IAAM,CAC1BqG,EAAA,EACAD,GAAA,MAAAA,GACF,EAAGH,CAAU,EACb,MAAO,IAAM,aAAajG,CAAE,CAC9B,EAAG,CAACiG,EAAYzF,EAAS8F,EAAUF,EAAQC,EAAOF,CAAY,CAAC,EAE/DvC,EAAAA,UAAU,IAAM,CACd,GAAI,CAACpD,GAAW,CAAC0F,GAAmBA,GAAmB,EAAG,OAC1D,MAAMzC,EAAO+C,EAAa,QAC1BA,EAAa,QAAUjC,EACnBA,IAAiBd,IACrB8C,EAAmB,SAAW,EAC1BA,EAAmB,SAAW,IAChCF,EAAA,EACAD,GAAA,MAAAA,KAEJ,EAAG,CAAC7B,EAAc/D,EAAS4F,EAAQC,EAAOH,CAAe,CAAC,CAC5D,CCvCO,SAASO,EAAkBjG,EAAU,GAAa,CACvD,MAAM7B,EAAQ+H,EAAAA,eAAA,EACRC,EAAUlF,EAAAA,OAAO9C,CAAK,EAE5BiF,EAAAA,UAAU,IAAM,CACd,GAAI,CAACpD,GAAW,OAAO,QAAY,IAAa,OAChD,MAAMiD,EAAOkD,EAAQ,QACjBlD,IAAS9E,GACX,QAAQ,MAAM,WAAY,CACxB,KAAM,CACJ,aAAc8E,EAAK,aACnB,SAAUA,EAAK,SACf,YAAaA,EAAK,YAClB,WAAYA,EAAK,UAAA,EAEnB,GAAI,CACF,aAAc9E,EAAM,aACpB,SAAUA,EAAM,SAChB,YAAaA,EAAM,YACnB,WAAYA,EAAM,UAAA,CACpB,CACD,EAEHgI,EAAQ,QAAUhI,CACpB,EAAG,CAAC6B,EAAS7B,CAAK,CAAC,CACrB,CCdA,SAASiI,GAAQC,EAAuB,CACtC,OAAO,KAAK,IAAI,EAAG,KAAK,IAAI,EAAGA,CAAK,CAAC,CACvC,CAEO,SAASC,GAAYC,EAAiC,CAC3D,MAAMC,EAAQvI,EAAAA,eAAA,EACRwI,EAAW1I,EAAAA,kBAAA,EACX,CAAE,KAAAkG,GAASuC,EACX,CAACE,EAAUC,CAAW,EAAIlG,EAAAA,SAAS,CAAC,EACpC,CAACmG,EAAYC,CAAa,EAAIpG,EAAAA,SAAS,EAAK,EAE5CqG,EAAerI,EAAAA,iBAAiBL,EAAAA,6BAA6BqI,EAAUD,CAAK,CAAC,EAC7EO,EAAkBH,EAAaF,EAAWI,EAE1CE,EAAgB5F,EAAAA,YACnBsC,GAA0C,CACzC,GAAI,EAAE6C,EAAW,GAAI,OACrB,MAAM5C,EAASD,EAAM,cACfuD,EAAOtD,EAAO,sBAAA,EACduD,EAAUC,GAAoB,CAClC,MAAMC,EAAQhB,IAASe,EAAUF,EAAK,MAAQA,EAAK,KAAK,EACxDN,EAAYS,CAAK,EACjBnD,EAAKmD,EAAQb,CAAQ,CACvB,EACAM,EAAc,EAAI,EAClBlD,EAAO,kBAAkBD,EAAM,SAAS,EACxCwD,EAAOxD,EAAM,OAAO,EACpB,MAAM2D,EAAUC,GAA4BJ,EAAOI,EAAU,OAAO,EAC9DC,EAAQC,GAA0B,CACtCN,EAAOM,EAAQ,OAAO,EACtBX,EAAc,EAAK,EACnBlD,EAAO,sBAAsBD,EAAM,SAAS,EAC5CC,EAAO,oBAAoB,cAAe0D,CAAM,EAChD1D,EAAO,oBAAoB,YAAa4D,CAAI,EAC5C5D,EAAO,oBAAoB,gBAAiB4D,CAAI,CAClD,EACA5D,EAAO,iBAAiB,cAAe0D,CAAM,EAC7C1D,EAAO,iBAAiB,YAAa4D,CAAI,EACzC5D,EAAO,iBAAiB,gBAAiB4D,CAAI,CAC/C,EACA,CAAChB,EAAUtC,CAAI,CAAA,EAGjB,MAAO,CAAE,SAAAyC,EAAU,gBAAAK,EAAiB,WAAAH,EAAY,cAAAI,CAAA,CAClD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useSeekDrag-DkAJvf8H.js","sources":["../src/hooks/useGinger.ts","../src/analyzer/liveAudioGraph.ts","../src/analyzer/useGingerLiveAnalyzer.ts","../src/hooks/useGingerKeyboardShortcuts.ts","../src/hooks/useGingerChapters.ts","../src/internal/lyrics.ts","../src/hooks/useGingerLyricsSync.ts","../src/hooks/useGingerSleepTimer.ts","../src/hooks/useGingerDebugLog.ts","../src/hooks/useSeekDrag.ts"],"sourcesContent":["import { useMemo } from \"react\";\nimport { gingerStateFromContextValues, useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\nimport {\n derivePlaybackUiState,\n effectiveDuration,\n effectiveRemaining,\n getCurrentTrack,\n progressFraction,\n resolvedAlbumLine,\n resolvedArtwork,\n} from \"../internal/selectors\";\n\nexport function useGinger() {\n const pb = useGingerPlayback();\n const md = useGingerMedia();\n\n return useMemo(\n () => {\n const state = gingerStateFromContextValues(pb, md);\n return {\n state,\n currentTrack: getCurrentTrack(state),\n playbackUi: derivePlaybackUiState(state),\n duration: effectiveDuration(state),\n remaining: effectiveRemaining(state),\n progress: progressFraction(state),\n artworkUrl: resolvedArtwork(state),\n albumLine: resolvedAlbumLine(state),\n play: pb.play,\n pause: pb.pause,\n togglePlayPause: pb.togglePlayPause,\n seek: md.seek,\n setVolume: md.setVolume,\n setMuted: md.setMuted,\n toggleMute: md.toggleMute,\n setPlaybackRate: md.setPlaybackRate,\n next: pb.next,\n prev: pb.prev,\n setRepeatMode: pb.setRepeatMode,\n cycleRepeat: pb.cycleRepeat,\n toggleShuffle: pb.toggleShuffle,\n setQueue: pb.setQueue,\n insertTrackAt: pb.insertTrackAt,\n removeTrackAt: pb.removeTrackAt,\n moveTrack: pb.moveTrack,\n enqueueNext: pb.enqueueNext,\n playTrackAt: pb.playTrackAt,\n selectTrackAt: pb.selectTrackAt,\n setPlaylistMeta: pb.setPlaylistMeta,\n init: pb.init,\n audioRef: md.audioRef,\n dispatch: pb.dispatch,\n };\n },\n [pb, md],\n );\n}\n","/** One MediaElementAudioSourceNode per HTMLAudioElement; multiple AnalyserNodes may tap the source. */\n\nexport type LiveAnalyserOptions = {\n fftSize: number;\n smoothingTimeConstant: number;\n minDecibels: number;\n maxDecibels: number;\n};\n\ntype Consumer = {\n analyser: AnalyserNode;\n /** This analyser is wired to `audioContext.destination` so the graph is audible. */\n isPlaybackSink: boolean;\n};\n\ntype ElementEntry = {\n context: AudioContext;\n source: MediaElementAudioSourceNode;\n consumers: Map<number, Consumer>;\n nextId: number;\n};\n\nconst entries = new WeakMap<HTMLAudioElement, ElementEntry>();\n\nfunction clampFftSize(n: number): number {\n const p = 2 ** Math.round(Math.log2(n));\n return Math.min(32768, Math.max(32, p));\n}\n\nexport function attachLiveAnalyser(\n element: HTMLAudioElement,\n options: LiveAnalyserOptions,\n): { id: number; context: AudioContext; analyser: AnalyserNode } {\n let entry = entries.get(element);\n if (!entry) {\n const Context = window.AudioContext ?? (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!Context) {\n throw new Error(\"Web Audio API is not available\");\n }\n const context = new Context();\n const source = context.createMediaElementSource(element);\n entry = { context, source, consumers: new Map(), nextId: 0 };\n entries.set(element, entry);\n }\n\n const { context, source } = entry;\n const analyser = context.createAnalyser();\n analyser.fftSize = clampFftSize(options.fftSize);\n analyser.smoothingTimeConstant = options.smoothingTimeConstant;\n analyser.minDecibels = options.minDecibels;\n analyser.maxDecibels = options.maxDecibels;\n\n source.connect(analyser);\n\n const isFirst = entry.consumers.size === 0;\n if (isFirst) {\n analyser.connect(context.destination);\n }\n\n const id = entry.nextId;\n entry.nextId += 1;\n entry.consumers.set(id, { analyser, isPlaybackSink: isFirst });\n\n return { id, context, analyser };\n}\n\nexport function detachLiveAnalyser(element: HTMLAudioElement, id: number): void {\n const entry = entries.get(element);\n if (!entry) return;\n\n const consumer = entry.consumers.get(id);\n if (!consumer) return;\n\n const { analyser, isPlaybackSink } = consumer;\n analyser.disconnect();\n entry.consumers.delete(id);\n\n if (entry.consumers.size === 0) {\n try {\n entry.source.disconnect();\n } catch {\n // ignore\n }\n void entry.context.close();\n entries.delete(element);\n return;\n }\n\n if (isPlaybackSink) {\n const first = entry.consumers.values().next().value as Consumer | undefined;\n if (first) {\n first.analyser.connect(entry.context.destination);\n first.isPlaybackSink = true;\n }\n }\n}\n","import { useCallback, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { useGinger } from \"../hooks/useGinger\";\nimport { attachLiveAnalyser, detachLiveAnalyser, type LiveAnalyserOptions } from \"./liveAudioGraph\";\n\nexport type UseGingerLiveAnalyzerOptions = {\n /** When false, the analyser is detached and no frames are read. Default true. */\n enabled?: boolean;\n fftSize?: number;\n smoothingTimeConstant?: number;\n minDecibels?: number;\n maxDecibels?: number;\n};\n\nexport type UseGingerLiveAnalyzerResult = {\n /** Byte frequency data (0–255); length equals `frequencyBinCount`. Updated each animation frame while enabled. */\n frequencyData: Uint8Array;\n /** Byte time-domain data (0–255); length equals `fftSize`. */\n timeDomainData: Uint8Array;\n frequencyBinCount: number;\n sampleRate: number;\n isSuspended: boolean;\n error: string | null;\n resume: () => Promise<void>;\n};\n\nconst emptyFreq = new Uint8Array(0);\nconst emptyTime = new Uint8Array(0);\n\nexport function useGingerLiveAnalyzer(options: UseGingerLiveAnalyzerOptions = {}): UseGingerLiveAnalyzerResult {\n const {\n enabled = true,\n fftSize = 2048,\n smoothingTimeConstant = 0.8,\n minDecibels = -100,\n maxDecibels = -30,\n } = options;\n\n const { audioRef, state } = useGinger();\n const opts = useMemo<LiveAnalyserOptions>(\n () => ({\n fftSize,\n smoothingTimeConstant,\n minDecibels,\n maxDecibels,\n }),\n [fftSize, smoothingTimeConstant, minDecibels, maxDecibels],\n );\n\n const [frame, setFrame] = useState(0);\n const [error, setError] = useState<string | null>(null);\n const [isSuspended, setIsSuspended] = useState(false);\n const [meta, setMeta] = useState({ frequencyBinCount: 0, sampleRate: 0 });\n\n const freqRef = useRef<Uint8Array>(emptyFreq);\n const timeRef = useRef<Uint8Array>(emptyTime);\n\n const resume = useCallback(async () => {\n const ctx = contextHolderRef.current;\n if (ctx && ctx.state === \"suspended\") {\n await ctx.resume();\n }\n }, []);\n\n const contextHolderRef = useRef<AudioContext | null>(null);\n const analyserHolderRef = useRef<AnalyserNode | null>(null);\n\n useLayoutEffect(() => {\n if (!enabled || typeof window === \"undefined\") {\n return;\n }\n\n let cancelled = false;\n let consumerId: number | null = null;\n let element: HTMLAudioElement | null = null;\n let rafId = 0;\n\n const onStateChange = () => {\n const ctx = contextHolderRef.current;\n if (ctx) setIsSuspended(ctx.state === \"suspended\");\n };\n\n const runLoop = () => {\n if (cancelled) return;\n const a = analyserHolderRef.current;\n const fq = freqRef.current;\n const td = timeRef.current;\n if (a && fq.length > 0 && td.length > 0) {\n a.getByteFrequencyData(fq as Uint8Array<ArrayBuffer>);\n a.getByteTimeDomainData(td as Uint8Array<ArrayBuffer>);\n setFrame((n) => n + 1);\n }\n rafId = requestAnimationFrame(runLoop);\n };\n\n type AttachOutcome = \"ok\" | \"no-element\" | \"error\";\n\n const attach = (): AttachOutcome => {\n const el = audioRef.current;\n if (!el || cancelled) return \"no-element\";\n try {\n const { id, context, analyser } = attachLiveAnalyser(el, opts);\n consumerId = id;\n element = el;\n contextHolderRef.current = context;\n analyserHolderRef.current = analyser;\n setIsSuspended(context.state === \"suspended\");\n setError(null);\n\n context.addEventListener(\"statechange\", onStateChange);\n\n const n = analyser.frequencyBinCount;\n const fft = analyser.fftSize;\n freqRef.current = new Uint8Array(n);\n timeRef.current = new Uint8Array(fft);\n setMeta({ frequencyBinCount: n, sampleRate: context.sampleRate });\n\n rafId = requestAnimationFrame(runLoop);\n return \"ok\";\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"Failed to attach live analyser\";\n setError(msg);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n setMeta({ frequencyBinCount: 0, sampleRate: 0 });\n return \"error\";\n }\n };\n\n const first = attach();\n if (first !== \"ok\") {\n let retryRaf = 0;\n const maxAttempts = 120;\n let attempts = 0;\n\n const retryLoop = () => {\n if (cancelled) return;\n const out = attach();\n if (out === \"ok\" || out === \"error\") return;\n attempts += 1;\n if (attempts >= maxAttempts) return;\n retryRaf = requestAnimationFrame(retryLoop);\n };\n\n if (first === \"no-element\") {\n retryRaf = requestAnimationFrame(retryLoop);\n }\n\n return () => {\n cancelled = true;\n cancelAnimationFrame(retryRaf);\n cancelAnimationFrame(rafId);\n if (consumerId != null && element) {\n detachLiveAnalyser(element, consumerId);\n }\n contextHolderRef.current?.removeEventListener(\"statechange\", onStateChange);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n };\n }\n\n return () => {\n cancelled = true;\n cancelAnimationFrame(rafId);\n if (consumerId != null && element) {\n detachLiveAnalyser(element, consumerId);\n }\n contextHolderRef.current?.removeEventListener(\"statechange\", onStateChange);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n setMeta({ frequencyBinCount: 0, sampleRate: 0 });\n };\n }, [enabled, audioRef, opts, state.currentIndex]);\n\n void frame;\n\n return {\n frequencyData: freqRef.current,\n timeDomainData: timeRef.current,\n frequencyBinCount: meta.frequencyBinCount,\n sampleRate: meta.sampleRate,\n isSuspended,\n error,\n resume,\n };\n}\n","import { useEffect } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerKeyboardShortcutBindings = {\n playPause?: string;\n next?: string;\n previous?: string;\n mute?: string;\n};\n\nexport function useGingerKeyboardShortcuts(\n enabled = true,\n bindings: GingerKeyboardShortcutBindings = {},\n): void {\n const { togglePlayPause, next, prev } = useGingerPlayback();\n const { toggleMute } = useGingerMedia();\n\n const muteBinding = bindings.mute;\n\n useEffect(() => {\n if (!enabled || typeof window === \"undefined\") return;\n const playPause = (bindings.playPause ?? \" \").toLowerCase();\n const nextKey = (bindings.next ?? \"ArrowRight\").toLowerCase();\n const prevKey = (bindings.previous ?? \"ArrowLeft\").toLowerCase();\n const muteKey = muteBinding?.toLowerCase();\n\n const onKeyDown = (event: KeyboardEvent) => {\n const target = event.target as HTMLElement | null;\n if (target && ([\"INPUT\", \"TEXTAREA\", \"SELECT\"].includes(target.tagName) || target.isContentEditable)) return;\n const key = event.key.toLowerCase();\n if (key === playPause) {\n event.preventDefault();\n togglePlayPause();\n } else if (key === nextKey) {\n event.preventDefault();\n next();\n } else if (key === prevKey) {\n event.preventDefault();\n prev();\n } else if (muteKey && key === muteKey) {\n event.preventDefault();\n toggleMute();\n }\n };\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, [bindings.next, bindings.playPause, bindings.previous, enabled, muteBinding, next, prev, toggleMute, togglePlayPause]);\n}\n","import { useMemo } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerChapter = {\n title: string;\n startSeconds: number;\n};\n\nexport type GingerChapterState = {\n list: GingerChapter[];\n activeIndex: number;\n active: GingerChapter | null;\n seekTo: (index: number) => void;\n};\n\nexport function useGingerChapters(): GingerChapterState {\n const { tracks, currentIndex } = useGingerPlayback();\n const { currentTime, seek } = useGingerMedia();\n\n const list = useMemo(() => {\n const chapters = tracks[currentIndex]?.chapters ?? [];\n return [...chapters]\n .filter((item) => item && Number.isFinite(item.startSeconds) && item.startSeconds >= 0)\n .sort((a, b) => a.startSeconds - b.startSeconds);\n }, [currentIndex, tracks]);\n\n const activeIndex = useMemo(() => {\n if (list.length === 0) return -1;\n for (let i = list.length - 1; i >= 0; i -= 1) {\n if (currentTime >= list[i]!.startSeconds) return i;\n }\n return -1;\n }, [currentTime, list]);\n\n return {\n list,\n activeIndex,\n active: activeIndex >= 0 ? list[activeIndex] ?? null : null,\n seekTo: (index: number) => {\n const chapter = list[index];\n if (chapter) seek(chapter.startSeconds);\n },\n };\n}\n","export type TimedLyricLine = {\n time: number;\n text: string;\n};\n\nconst lrcTag = /\\[(\\d{1,2}):(\\d{2})(?:\\.(\\d{1,3}))?\\]/g;\n\nexport function parseLrc(lrc: string): TimedLyricLine[] {\n const lines: TimedLyricLine[] = [];\n for (const rawLine of lrc.split(/\\r?\\n/)) {\n const matches = [...rawLine.matchAll(lrcTag)];\n if (matches.length === 0) continue;\n const text = rawLine.replace(lrcTag, \"\").trim();\n for (const m of matches) {\n const minutes = Number(m[1] ?? 0);\n const seconds = Number(m[2] ?? 0);\n const millis = Number((m[3] ?? \"0\").padEnd(3, \"0\"));\n const time = minutes * 60 + seconds + millis / 1000;\n if (Number.isFinite(time) && time >= 0) {\n lines.push({ time, text });\n }\n }\n }\n return lines.sort((a, b) => a.time - b.time);\n}\n","import { useMemo } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\nimport { parseLrc, type TimedLyricLine } from \"../internal/lyrics\";\n\nexport type GingerLyricsSyncState = {\n lines: TimedLyricLine[];\n activeIndex: number;\n activeLine: TimedLyricLine | null;\n};\n\nexport function useGingerLyricsSync(): GingerLyricsSyncState {\n const { tracks, currentIndex } = useGingerPlayback();\n const { currentTime } = useGingerMedia();\n const currentTrack = tracks[currentIndex];\n\n const lines = useMemo(() => {\n if (!currentTrack) return [];\n if (Array.isArray(currentTrack.lyricsTimed) && currentTrack.lyricsTimed.length > 0) {\n return [...currentTrack.lyricsTimed]\n .filter((line) => Number.isFinite(line.time) && line.time >= 0)\n .sort((a, b) => a.time - b.time);\n }\n if (typeof currentTrack.lyrics === \"string\") {\n return parseLrc(currentTrack.lyrics);\n }\n return [];\n }, [currentTrack]);\n\n const activeIndex = useMemo(() => {\n for (let i = lines.length - 1; i >= 0; i -= 1) {\n if (currentTime >= lines[i]!.time) return i;\n }\n return -1;\n }, [currentTime, lines]);\n\n return {\n lines,\n activeIndex,\n activeLine: activeIndex >= 0 ? lines[activeIndex] ?? null : null,\n };\n}\n","import { useEffect, useRef } from \"react\";\nimport { useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerSleepTimerOptions = {\n durationMs?: number;\n stopAfterTracks?: number;\n respectPause?: boolean;\n enabled?: boolean;\n onFire?: () => void;\n};\n\nexport function useGingerSleepTimer(options: GingerSleepTimerOptions): void {\n const { durationMs, stopAfterTracks, respectPause = true, enabled = true, onFire } = options;\n const { currentIndex, pause, isPaused } = useGingerPlayback();\n const remainingTracksRef = useRef(stopAfterTracks ?? 0);\n const prevIndexRef = useRef(currentIndex);\n\n useEffect(() => {\n remainingTracksRef.current = stopAfterTracks ?? 0;\n }, [stopAfterTracks]);\n\n useEffect(() => {\n if (!enabled || !durationMs || durationMs <= 0) return;\n if (respectPause && isPaused) return;\n const id = setTimeout(() => {\n pause();\n onFire?.();\n }, durationMs);\n return () => clearTimeout(id);\n }, [durationMs, enabled, isPaused, onFire, pause, respectPause]);\n\n useEffect(() => {\n if (!enabled || !stopAfterTracks || stopAfterTracks <= 0) return;\n const prev = prevIndexRef.current;\n prevIndexRef.current = currentIndex;\n if (currentIndex === prev) return;\n remainingTracksRef.current -= 1;\n if (remainingTracksRef.current <= 0) {\n pause();\n onFire?.();\n }\n }, [currentIndex, enabled, onFire, pause, stopAfterTracks]);\n}\n","import { useEffect, useRef } from \"react\";\nimport { useGingerState } from \"../context/GingerSplitContexts\";\n\nexport function useGingerDebugLog(enabled = false): void {\n const state = useGingerState();\n const prevRef = useRef(state);\n\n useEffect(() => {\n if (!enabled || typeof console === \"undefined\") return;\n const prev = prevRef.current;\n if (prev !== state) {\n console.debug(\"[ginger]\", {\n from: {\n currentIndex: prev.currentIndex,\n isPaused: prev.isPaused,\n currentTime: prev.currentTime,\n repeatMode: prev.repeatMode,\n },\n to: {\n currentIndex: state.currentIndex,\n isPaused: state.isPaused,\n currentTime: state.currentTime,\n repeatMode: state.repeatMode,\n },\n });\n }\n prevRef.current = state;\n }, [enabled, state]);\n}\n","import { useCallback, useState } from \"react\";\nimport type { PointerEvent as ReactPointerEvent } from \"react\";\nimport { useGingerMedia, useGingerPlayback, gingerStateFromContextValues } from \"../context/GingerSplitContexts\";\nimport { progressFraction } from \"../internal/selectors\";\n\nexport type SeekDragState = {\n /** Raw drag fraction — only updated during an active drag gesture. */\n fraction: number;\n /** Blended fraction: follows live playback when idle, drag position when dragging. */\n displayFraction: number;\n isDragging: boolean;\n onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n};\n\nfunction clamp01(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nexport function useSeekDrag(duration: number): SeekDragState {\n const media = useGingerMedia();\n const playback = useGingerPlayback();\n const { seek } = media;\n const [fraction, setFraction] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n\n const liveFraction = progressFraction(gingerStateFromContextValues(playback, media));\n const displayFraction = isDragging ? fraction : liveFraction;\n\n const onPointerDown = useCallback(\n (event: ReactPointerEvent<HTMLElement>) => {\n if (!(duration > 0)) return;\n const target = event.currentTarget;\n const rect = target.getBoundingClientRect();\n const update = (clientX: number) => {\n const ratio = clamp01((clientX - rect.left) / rect.width);\n setFraction(ratio);\n seek(ratio * duration);\n };\n setIsDragging(true);\n target.setPointerCapture(event.pointerId);\n update(event.clientX);\n const onMove = (moveEvent: PointerEvent) => update(moveEvent.clientX);\n const onUp = (upEvent: PointerEvent) => {\n update(upEvent.clientX);\n setIsDragging(false);\n target.releasePointerCapture(event.pointerId);\n target.removeEventListener(\"pointermove\", onMove);\n target.removeEventListener(\"pointerup\", onUp);\n target.removeEventListener(\"pointercancel\", onUp);\n };\n target.addEventListener(\"pointermove\", onMove);\n target.addEventListener(\"pointerup\", onUp);\n target.addEventListener(\"pointercancel\", onUp);\n },\n [duration, seek],\n );\n\n return { fraction, displayFraction, isDragging, onPointerDown };\n}\n"],"names":["useGinger","pb","useGingerPlayback","md","useGingerMedia","useMemo","state","gingerStateFromContextValues","getCurrentTrack","derivePlaybackUiState","effectiveDuration","effectiveRemaining","progressFraction","resolvedArtwork","resolvedAlbumLine","entries","clampFftSize","p","attachLiveAnalyser","element","options","entry","Context","context","source","analyser","isFirst","id","detachLiveAnalyser","consumer","isPlaybackSink","first","emptyFreq","emptyTime","useGingerLiveAnalyzer","enabled","fftSize","smoothingTimeConstant","minDecibels","maxDecibels","audioRef","opts","frame","setFrame","useState","error","setError","isSuspended","setIsSuspended","meta","setMeta","freqRef","useRef","timeRef","resume","useCallback","ctx","contextHolderRef","analyserHolderRef","useLayoutEffect","cancelled","consumerId","rafId","onStateChange","runLoop","a","fq","td","n","attach","el","fft","e","msg","retryRaf","maxAttempts","attempts","retryLoop","out","_a","useGingerKeyboardShortcuts","bindings","togglePlayPause","next","prev","toggleMute","muteBinding","useEffect","playPause","nextKey","prevKey","muteKey","onKeyDown","event","target","key","useGingerChapters","tracks","currentIndex","currentTime","seek","list","item","b","activeIndex","i","index","chapter","lrcTag","parseLrc","lrc","lines","rawLine","matches","text","m","minutes","seconds","millis","time","useGingerLyricsSync","currentTrack","line","useGingerSleepTimer","durationMs","stopAfterTracks","respectPause","onFire","pause","isPaused","remainingTracksRef","prevIndexRef","useGingerDebugLog","useGingerState","prevRef","clamp01","value","useSeekDrag","duration","media","playback","fraction","setFraction","isDragging","setIsDragging","liveFraction","displayFraction","onPointerDown","rect","update","clientX","ratio","onMove","moveEvent","onUp","upEvent"],"mappings":"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"}
|