@lucaismyname/ginger 0.0.11 → 0.0.13
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 +12 -1
- package/dist/client.cjs +1 -1
- package/dist/client.js +2 -2
- package/dist/components/controls/Controls.d.ts +6 -6
- package/dist/components/controls/Controls.d.ts.map +1 -1
- package/dist/components/controls/Controls.test.d.ts +2 -0
- package/dist/components/controls/Controls.test.d.ts.map +1 -0
- package/dist/components/current/texts.test.d.ts +2 -0
- package/dist/components/current/texts.test.d.ts.map +1 -0
- package/dist/context/GingerProvider.test.d.ts +2 -0
- package/dist/context/GingerProvider.test.d.ts.map +1 -0
- package/dist/core/playbackReducer.d.ts.map +1 -1
- package/dist/ginger-DYoHDn8T.cjs +2 -0
- package/dist/ginger-DYoHDn8T.cjs.map +1 -0
- package/dist/ginger-Dntdd6zH.js +1599 -0
- package/dist/ginger-Dntdd6zH.js.map +1 -0
- package/dist/hooks/useSeekDrag.d.ts +3 -0
- package/dist/hooks/useSeekDrag.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +2 -2
- package/dist/internal/formatTime.test.d.ts +2 -0
- package/dist/internal/formatTime.test.d.ts.map +1 -0
- package/dist/internal/selectors.test.d.ts +2 -0
- package/dist/internal/selectors.test.d.ts.map +1 -0
- package/dist/media/useMediaSession.d.ts.map +1 -1
- package/dist/testing/index.cjs +1 -1
- package/dist/testing/index.js +1 -1
- package/dist/testing/setup.d.ts +2 -0
- package/dist/testing/setup.d.ts.map +1 -0
- package/dist/useSeekDrag-DBzoym0-.cjs +2 -0
- package/dist/useSeekDrag-DBzoym0-.cjs.map +1 -0
- package/dist/useSeekDrag-jLsYA-uG.js +174 -0
- package/dist/useSeekDrag-jLsYA-uG.js.map +1 -0
- package/dist/waveform/index.cjs +1 -1
- package/dist/waveform/index.cjs.map +1 -1
- package/dist/waveform/index.js +15 -13
- package/dist/waveform/index.js.map +1 -1
- package/dist/waveform/useAudioPeaks.d.ts.map +1 -1
- package/package.json +2 -1
- package/dist/ginger-CBPwykB4.js +0 -1570
- package/dist/ginger-CBPwykB4.js.map +0 -1
- package/dist/ginger-CNiuqxwJ.cjs +0 -2
- package/dist/ginger-CNiuqxwJ.cjs.map +0 -1
- package/dist/useSeekDrag-V2H6HaTl.cjs +0 -2
- package/dist/useSeekDrag-V2H6HaTl.cjs.map +0 -1
- package/dist/useSeekDrag-vWJhNLxp.js +0 -174
- package/dist/useSeekDrag-vWJhNLxp.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ginger-CNiuqxwJ.cjs","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 ...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 type={type} aria-label={b.ariaLabel} onClick={b.toggle} {...rest}>\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\", ...rest }: RepeatProps) {\n const { repeatMode, cycleRepeat } = useGingerPlayback();\n const locale = useGingerLocale();\n const label = locale.repeat[repeatMode];\n return (\n <button type={type} aria-label={label} onClick={cycleRepeat} {...rest}>\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\", ...rest }: NextProps) {\n const { next } = useGingerPlayback();\n const locale = useGingerLocale();\n return (\n <button type={type} aria-label={locale.nextTrack} onClick={next} {...rest}>\n {children}\n </button>\n );\n}\nNext.displayName = \"Ginger.Control.Next\";\n\nexport type PreviousProps = ButtonHTMLAttributes<HTMLButtonElement>;\nexport function Previous({ type = \"button\", children = \"Previous\", ...rest }: PreviousProps) {\n const { prev } = useGingerPlayback();\n const locale = useGingerLocale();\n return (\n <button type={type} aria-label={locale.previousTrack} onClick={prev} {...rest}>\n {children}\n </button>\n );\n}\nPrevious.displayName = \"Ginger.Control.Previous\";\n\nexport type ShuffleProps = ButtonHTMLAttributes<HTMLButtonElement>;\nexport function Shuffle({ type = \"button\", children = \"Shuffle\", ...rest }: ShuffleProps) {\n const { isShuffled, toggleShuffle } = useGingerPlayback();\n const locale = useGingerLocale();\n return (\n <button\n type={type}\n aria-pressed={isShuffled}\n aria-label={locale.shuffle}\n onClick={toggleShuffle}\n {...rest}\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 ...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 type={type}\n aria-pressed={muted}\n aria-label={muted ? locale.unmute : locale.mute}\n onClick={toggleMute}\n {...rest}\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 return state;\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 toMediaMetadata(state: GingerState): MediaMetadataInit {\n const track = state.tracks[state.currentIndex];\n if (!track) return { title: \"Unknown track\" };\n return {\n title: track.title,\n artist: track.artist,\n album: track.album,\n artwork: track.artworkUrl ? [{ src: track.artworkUrl }] : undefined,\n };\n}\n\nexport function useMediaSessionBridge(\n enabled: boolean,\n state: GingerState,\n actions: MediaSessionBridgeActions,\n): void {\n useEffect(() => {\n if (!enabled || typeof navigator === \"undefined\" || !(\"mediaSession\" in navigator)) return;\n const mediaSession = navigator.mediaSession;\n mediaSession.metadata = new MediaMetadata(toMediaMetadata(state));\n mediaSession.playbackState = state.isPaused ? \"paused\" : \"playing\";\n\n try {\n mediaSession.setActionHandler(\"play\", actions.play);\n mediaSession.setActionHandler(\"pause\", actions.pause);\n mediaSession.setActionHandler(\"nexttrack\", actions.next);\n mediaSession.setActionHandler(\"previoustrack\", actions.prev);\n mediaSession.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\n return () => {\n try {\n mediaSession.setActionHandler(\"play\", null);\n mediaSession.setActionHandler(\"pause\", null);\n mediaSession.setActionHandler(\"nexttrack\", null);\n mediaSession.setActionHandler(\"previoustrack\", null);\n mediaSession.setActionHandler(\"seekto\", null);\n } catch {\n // Ignore platforms that do not support clearing handlers.\n }\n };\n }, [enabled, state, 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","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","onClick","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","toMediaMetadata","useMediaSessionBridge","enabled","actions","mediaSession","details","defaultProviderStyle","GingerProvider","initialTracks","initialIndex","initialPlaylistMeta","initialShuffle","initialRepeatMode","initialPlaybackMode","initialPaused","initialVolume","initialMuted","initialPlaybackRate","initialStateKey","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"),f=require("./GingerSplitContexts-Bze1Bqe2.cjs"),k=require("./ginger-CNiuqxwJ.cjs");function P(){const t=f.useGingerPlayback(),e=f.useGingerMedia();return a.useMemo(()=>{const r=f.gingerStateFromContextValues(t,e);return{state:r,currentTrack:k.getCurrentTrack(r),playbackUi:k.derivePlaybackUiState(r),duration:k.effectiveDuration(r),remaining:k.effectiveRemaining(r),progress:k.progressFraction(r),artworkUrl:k.resolvedArtwork(r),albumLine:k.resolvedAlbumLine(r),play:t.play,pause:t.pause,togglePlayPause:t.togglePlayPause,seek:e.seek,setVolume:e.setVolume,setMuted:e.setMuted,toggleMute:e.toggleMute,setPlaybackRate:e.setPlaybackRate,next:t.next,prev:t.prev,setRepeatMode:t.setRepeatMode,cycleRepeat:t.cycleRepeat,toggleShuffle:t.toggleShuffle,setQueue:t.setQueue,insertTrackAt:t.insertTrackAt,removeTrackAt:t.removeTrackAt,moveTrack:t.moveTrack,enqueueNext:t.enqueueNext,playTrackAt:t.playTrackAt,selectTrackAt:t.selectTrackAt,setPlaylistMeta:t.setPlaylistMeta,init:t.init,audioRef:e.audioRef,dispatch:t.dispatch}},[t,e])}function M(t=!0,e={}){const{togglePlayPause:r,next:s,prev:i}=f.useGingerPlayback(),{toggleMute:u}=f.useGingerMedia(),n=e.mute;a.useEffect(()=>{if(!t||typeof window>"u")return;const c=(e.playPause??" ").toLowerCase(),o=(e.next??"ArrowRight").toLowerCase(),l=(e.previous??"ArrowLeft").toLowerCase(),d=(e.mute??"m").toLowerCase(),p=g=>{const m=g.target;if(m&&["INPUT","TEXTAREA","SELECT"].includes(m.tagName))return;const y=g.key.toLowerCase();y===c?(g.preventDefault(),r()):y===o?(g.preventDefault(),s()):y===l?(g.preventDefault(),i()):y===d&&n!==void 0&&(g.preventDefault(),u())};return window.addEventListener("keydown",p),()=>window.removeEventListener("keydown",p)},[e.next,e.playPause,e.previous,t,n,s,i,u,r])}function L(){const{tracks:t,currentIndex:e}=f.useGingerPlayback(),{currentTime:r,seek:s}=f.useGingerMedia(),i=a.useMemo(()=>{var c;return[...((c=t[e])==null?void 0:c.chapters)??[]].filter(o=>o&&Number.isFinite(o.startSeconds)&&o.startSeconds>=0).sort((o,l)=>o.startSeconds-l.startSeconds)},[e,t]),u=a.useMemo(()=>{if(i.length===0)return-1;for(let n=i.length-1;n>=0;n-=1)if(r>=i[n].startSeconds)return n;return-1},[r,i]);return{list:i,activeIndex:u,active:u>=0?i[u]??null:null,seekTo:n=>{const c=i[n];c&&s(c.startSeconds)}}}const v=/\[(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?\]/g;function T(t){const e=[];for(const r of t.split(/\r?\n/)){const s=[...r.matchAll(v)];if(s.length===0)continue;const i=r.replace(v,"").trim();for(const u of s){const n=Number(u[1]??0),c=Number(u[2]??0),o=Number((u[3]??"0").padEnd(3,"0")),l=n*60+c+o/1e3;Number.isFinite(l)&&l>=0&&e.push({time:l,text:i})}}return e.sort((r,s)=>r.time-s.time)}function h(){const{tracks:t,currentIndex:e}=f.useGingerPlayback(),{currentTime:r}=f.useGingerMedia(),s=t[e],i=a.useMemo(()=>s?Array.isArray(s.lyricsTimed)&&s.lyricsTimed.length>0?[...s.lyricsTimed].filter(n=>Number.isFinite(n.time)&&n.time>=0).sort((n,c)=>n.time-c.time):typeof s.lyrics=="string"?T(s.lyrics):[]:[],[s]),u=a.useMemo(()=>{for(let n=i.length-1;n>=0;n-=1)if(r>=i[n].time)return n;return-1},[r,i]);return{lines:i,activeIndex:u,activeLine:u>=0?i[u]??null:null}}function G(t){const{durationMs:e,stopAfterTracks:r,respectPause:s=!0,enabled:i=!0,onFire:u}=t,{currentIndex:n,pause:c,isPaused:o}=f.useGingerPlayback(),l=a.useRef(r??0),d=a.useRef(n);a.useEffect(()=>{l.current=r??0},[r]),a.useEffect(()=>{if(!i||!e||e<=0||s&&o)return;const p=setTimeout(()=>{c(),u==null||u()},e);return()=>clearTimeout(p)},[e,i,o,u,c,s]),a.useEffect(()=>{if(!i||!r||r<=0)return;const p=d.current;d.current=n,n!==p&&(l.current-=1,l.current<=0&&(c(),u==null||u()))},[n,i,u,c,r])}function S(t=!1){const e=f.useGingerState(),r=a.useRef(e);a.useEffect(()=>{if(!t||typeof console>"u")return;const s=r.current;s!==e&&console.debug("[ginger]",{from:{currentIndex:s.currentIndex,isPaused:s.isPaused,currentTime:s.currentTime,repeatMode:s.repeatMode},to:{currentIndex:e.currentIndex,isPaused:e.isPaused,currentTime:e.currentTime,repeatMode:e.repeatMode}}),r.current=e},[t,e])}function x(t){return Math.max(0,Math.min(1,t))}function w(t){const{seek:e}=f.useGingerMedia(),[r,s]=a.useState(0),[i,u]=a.useState(!1),n=a.useCallback(c=>{if(!(t>0))return;const o=c.currentTarget,l=o.getBoundingClientRect(),d=m=>{const y=x((m-l.left)/l.width);s(y),e(y*t)};u(!0),o.setPointerCapture(c.pointerId),d(c.clientX);const p=m=>d(m.clientX),g=m=>{d(m.clientX),u(!1),o.releasePointerCapture(c.pointerId),o.removeEventListener("pointermove",p),o.removeEventListener("pointerup",g),o.removeEventListener("pointercancel",g)};o.addEventListener("pointermove",p),o.addEventListener("pointerup",g),o.addEventListener("pointercancel",g)},[t,e]);return{fraction:r,isDragging:i,onPointerDown:n}}exports.parseLrc=T;exports.useGinger=P;exports.useGingerChapters=L;exports.useGingerDebugLog=S;exports.useGingerKeyboardShortcuts=M;exports.useGingerLyricsSync=h;exports.useGingerSleepTimer=G;exports.useSeekDrag=w;
|
|
2
|
-
//# sourceMappingURL=useSeekDrag-V2H6HaTl.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useSeekDrag-V2H6HaTl.cjs","sources":["../src/hooks/useGinger.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","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 = (bindings.mute ?? \"m\").toLowerCase();\n\n const onKeyDown = (event: KeyboardEvent) => {\n const target = event.target as HTMLElement | null;\n if (target && [\"INPUT\", \"TEXTAREA\", \"SELECT\"].includes(target.tagName)) 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 (key === muteKey && muteBinding !== undefined) {\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 } from \"../context/GingerSplitContexts\";\n\nexport type SeekDragState = {\n fraction: 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 { seek } = useGingerMedia();\n const [fraction, setFraction] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\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, isDragging, onPointerDown };\n}\n"],"names":["useGinger","pb","useGingerPlayback","md","useGingerMedia","useMemo","state","gingerStateFromContextValues","getCurrentTrack","derivePlaybackUiState","effectiveDuration","effectiveRemaining","progressFraction","resolvedArtwork","resolvedAlbumLine","useGingerKeyboardShortcuts","enabled","bindings","togglePlayPause","next","prev","toggleMute","muteBinding","useEffect","playPause","nextKey","prevKey","muteKey","onKeyDown","event","target","key","useGingerChapters","tracks","currentIndex","currentTime","seek","list","_a","item","a","b","activeIndex","i","index","chapter","lrcTag","parseLrc","lrc","lines","rawLine","matches","text","m","minutes","seconds","millis","time","useGingerLyricsSync","currentTrack","line","useGingerSleepTimer","options","durationMs","stopAfterTracks","respectPause","onFire","pause","isPaused","remainingTracksRef","useRef","prevIndexRef","id","useGingerDebugLog","useGingerState","prevRef","clamp01","value","useSeekDrag","duration","fraction","setFraction","useState","isDragging","setIsDragging","onPointerDown","useCallback","rect","update","clientX","ratio","onMove","moveEvent","onUp","upEvent"],"mappings":"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"}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { useMemo as y, useEffect as g, useRef as T, useState as P, useCallback as x } from "react";
|
|
2
|
-
import { b as k, u as v, g as L, c as w } from "./GingerSplitContexts-4YZ-OJ9V.js";
|
|
3
|
-
import { r as M, h as A, p as S, i as R, j as E, b as I, k as b } from "./ginger-CBPwykB4.js";
|
|
4
|
-
function U() {
|
|
5
|
-
const t = k(), e = v();
|
|
6
|
-
return y(
|
|
7
|
-
() => {
|
|
8
|
-
const r = L(t, e);
|
|
9
|
-
return {
|
|
10
|
-
state: r,
|
|
11
|
-
currentTrack: b(r),
|
|
12
|
-
playbackUi: I(r),
|
|
13
|
-
duration: E(r),
|
|
14
|
-
remaining: R(r),
|
|
15
|
-
progress: S(r),
|
|
16
|
-
artworkUrl: A(r),
|
|
17
|
-
albumLine: M(r),
|
|
18
|
-
play: t.play,
|
|
19
|
-
pause: t.pause,
|
|
20
|
-
togglePlayPause: t.togglePlayPause,
|
|
21
|
-
seek: e.seek,
|
|
22
|
-
setVolume: e.setVolume,
|
|
23
|
-
setMuted: e.setMuted,
|
|
24
|
-
toggleMute: e.toggleMute,
|
|
25
|
-
setPlaybackRate: e.setPlaybackRate,
|
|
26
|
-
next: t.next,
|
|
27
|
-
prev: t.prev,
|
|
28
|
-
setRepeatMode: t.setRepeatMode,
|
|
29
|
-
cycleRepeat: t.cycleRepeat,
|
|
30
|
-
toggleShuffle: t.toggleShuffle,
|
|
31
|
-
setQueue: t.setQueue,
|
|
32
|
-
insertTrackAt: t.insertTrackAt,
|
|
33
|
-
removeTrackAt: t.removeTrackAt,
|
|
34
|
-
moveTrack: t.moveTrack,
|
|
35
|
-
enqueueNext: t.enqueueNext,
|
|
36
|
-
playTrackAt: t.playTrackAt,
|
|
37
|
-
selectTrackAt: t.selectTrackAt,
|
|
38
|
-
setPlaylistMeta: t.setPlaylistMeta,
|
|
39
|
-
init: t.init,
|
|
40
|
-
audioRef: e.audioRef,
|
|
41
|
-
dispatch: t.dispatch
|
|
42
|
-
};
|
|
43
|
-
},
|
|
44
|
-
[t, e]
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
function X(t = !0, e = {}) {
|
|
48
|
-
const { togglePlayPause: r, next: s, prev: a } = k(), { toggleMute: o } = v(), n = e.mute;
|
|
49
|
-
g(() => {
|
|
50
|
-
if (!t || typeof window > "u") return;
|
|
51
|
-
const i = (e.playPause ?? " ").toLowerCase(), c = (e.next ?? "ArrowRight").toLowerCase(), u = (e.previous ?? "ArrowLeft").toLowerCase(), p = (e.mute ?? "m").toLowerCase(), f = (l) => {
|
|
52
|
-
const d = l.target;
|
|
53
|
-
if (d && ["INPUT", "TEXTAREA", "SELECT"].includes(d.tagName)) return;
|
|
54
|
-
const m = l.key.toLowerCase();
|
|
55
|
-
m === i ? (l.preventDefault(), r()) : m === c ? (l.preventDefault(), s()) : m === u ? (l.preventDefault(), a()) : m === p && n !== void 0 && (l.preventDefault(), o());
|
|
56
|
-
};
|
|
57
|
-
return window.addEventListener("keydown", f), () => window.removeEventListener("keydown", f);
|
|
58
|
-
}, [e.next, e.playPause, e.previous, t, n, s, a, o, r]);
|
|
59
|
-
}
|
|
60
|
-
function F() {
|
|
61
|
-
const { tracks: t, currentIndex: e } = k(), { currentTime: r, seek: s } = v(), a = y(() => {
|
|
62
|
-
var i;
|
|
63
|
-
return [...((i = t[e]) == null ? void 0 : i.chapters) ?? []].filter((c) => c && Number.isFinite(c.startSeconds) && c.startSeconds >= 0).sort((c, u) => c.startSeconds - u.startSeconds);
|
|
64
|
-
}, [e, t]), o = y(() => {
|
|
65
|
-
if (a.length === 0) return -1;
|
|
66
|
-
for (let n = a.length - 1; n >= 0; n -= 1)
|
|
67
|
-
if (r >= a[n].startSeconds) return n;
|
|
68
|
-
return -1;
|
|
69
|
-
}, [r, a]);
|
|
70
|
-
return {
|
|
71
|
-
list: a,
|
|
72
|
-
activeIndex: o,
|
|
73
|
-
active: o >= 0 ? a[o] ?? null : null,
|
|
74
|
-
seekTo: (n) => {
|
|
75
|
-
const i = a[n];
|
|
76
|
-
i && s(i.startSeconds);
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
const h = /\[(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?\]/g;
|
|
81
|
-
function C(t) {
|
|
82
|
-
const e = [];
|
|
83
|
-
for (const r of t.split(/\r?\n/)) {
|
|
84
|
-
const s = [...r.matchAll(h)];
|
|
85
|
-
if (s.length === 0) continue;
|
|
86
|
-
const a = r.replace(h, "").trim();
|
|
87
|
-
for (const o of s) {
|
|
88
|
-
const n = Number(o[1] ?? 0), i = Number(o[2] ?? 0), c = Number((o[3] ?? "0").padEnd(3, "0")), u = n * 60 + i + c / 1e3;
|
|
89
|
-
Number.isFinite(u) && u >= 0 && e.push({ time: u, text: a });
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return e.sort((r, s) => r.time - s.time);
|
|
93
|
-
}
|
|
94
|
-
function V() {
|
|
95
|
-
const { tracks: t, currentIndex: e } = k(), { currentTime: r } = v(), s = t[e], a = y(() => s ? Array.isArray(s.lyricsTimed) && s.lyricsTimed.length > 0 ? [...s.lyricsTimed].filter((n) => Number.isFinite(n.time) && n.time >= 0).sort((n, i) => n.time - i.time) : typeof s.lyrics == "string" ? C(s.lyrics) : [] : [], [s]), o = y(() => {
|
|
96
|
-
for (let n = a.length - 1; n >= 0; n -= 1)
|
|
97
|
-
if (r >= a[n].time) return n;
|
|
98
|
-
return -1;
|
|
99
|
-
}, [r, a]);
|
|
100
|
-
return {
|
|
101
|
-
lines: a,
|
|
102
|
-
activeIndex: o,
|
|
103
|
-
activeLine: o >= 0 ? a[o] ?? null : null
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
function q(t) {
|
|
107
|
-
const { durationMs: e, stopAfterTracks: r, respectPause: s = !0, enabled: a = !0, onFire: o } = t, { currentIndex: n, pause: i, isPaused: c } = k(), u = T(r ?? 0), p = T(n);
|
|
108
|
-
g(() => {
|
|
109
|
-
u.current = r ?? 0;
|
|
110
|
-
}, [r]), g(() => {
|
|
111
|
-
if (!a || !e || e <= 0 || s && c) return;
|
|
112
|
-
const f = setTimeout(() => {
|
|
113
|
-
i(), o == null || o();
|
|
114
|
-
}, e);
|
|
115
|
-
return () => clearTimeout(f);
|
|
116
|
-
}, [e, a, c, o, i, s]), g(() => {
|
|
117
|
-
if (!a || !r || r <= 0) return;
|
|
118
|
-
const f = p.current;
|
|
119
|
-
p.current = n, n !== f && (u.current -= 1, u.current <= 0 && (i(), o == null || o()));
|
|
120
|
-
}, [n, a, o, i, r]);
|
|
121
|
-
}
|
|
122
|
-
function B(t = !1) {
|
|
123
|
-
const e = w(), r = T(e);
|
|
124
|
-
g(() => {
|
|
125
|
-
if (!t || typeof console > "u") return;
|
|
126
|
-
const s = r.current;
|
|
127
|
-
s !== e && console.debug("[ginger]", {
|
|
128
|
-
from: {
|
|
129
|
-
currentIndex: s.currentIndex,
|
|
130
|
-
isPaused: s.isPaused,
|
|
131
|
-
currentTime: s.currentTime,
|
|
132
|
-
repeatMode: s.repeatMode
|
|
133
|
-
},
|
|
134
|
-
to: {
|
|
135
|
-
currentIndex: e.currentIndex,
|
|
136
|
-
isPaused: e.isPaused,
|
|
137
|
-
currentTime: e.currentTime,
|
|
138
|
-
repeatMode: e.repeatMode
|
|
139
|
-
}
|
|
140
|
-
}), r.current = e;
|
|
141
|
-
}, [t, e]);
|
|
142
|
-
}
|
|
143
|
-
function D(t) {
|
|
144
|
-
return Math.max(0, Math.min(1, t));
|
|
145
|
-
}
|
|
146
|
-
function Q(t) {
|
|
147
|
-
const { seek: e } = v(), [r, s] = P(0), [a, o] = P(!1), n = x(
|
|
148
|
-
(i) => {
|
|
149
|
-
if (!(t > 0)) return;
|
|
150
|
-
const c = i.currentTarget, u = c.getBoundingClientRect(), p = (d) => {
|
|
151
|
-
const m = D((d - u.left) / u.width);
|
|
152
|
-
s(m), e(m * t);
|
|
153
|
-
};
|
|
154
|
-
o(!0), c.setPointerCapture(i.pointerId), p(i.clientX);
|
|
155
|
-
const f = (d) => p(d.clientX), l = (d) => {
|
|
156
|
-
p(d.clientX), o(!1), c.releasePointerCapture(i.pointerId), c.removeEventListener("pointermove", f), c.removeEventListener("pointerup", l), c.removeEventListener("pointercancel", l);
|
|
157
|
-
};
|
|
158
|
-
c.addEventListener("pointermove", f), c.addEventListener("pointerup", l), c.addEventListener("pointercancel", l);
|
|
159
|
-
},
|
|
160
|
-
[t, e]
|
|
161
|
-
);
|
|
162
|
-
return { fraction: r, isDragging: a, onPointerDown: n };
|
|
163
|
-
}
|
|
164
|
-
export {
|
|
165
|
-
F as a,
|
|
166
|
-
B as b,
|
|
167
|
-
X as c,
|
|
168
|
-
V as d,
|
|
169
|
-
q as e,
|
|
170
|
-
Q as f,
|
|
171
|
-
C as p,
|
|
172
|
-
U as u
|
|
173
|
-
};
|
|
174
|
-
//# sourceMappingURL=useSeekDrag-vWJhNLxp.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useSeekDrag-vWJhNLxp.js","sources":["../src/hooks/useGinger.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","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 = (bindings.mute ?? \"m\").toLowerCase();\n\n const onKeyDown = (event: KeyboardEvent) => {\n const target = event.target as HTMLElement | null;\n if (target && [\"INPUT\", \"TEXTAREA\", \"SELECT\"].includes(target.tagName)) 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 (key === muteKey && muteBinding !== undefined) {\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 } from \"../context/GingerSplitContexts\";\n\nexport type SeekDragState = {\n fraction: 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 { seek } = useGingerMedia();\n const [fraction, setFraction] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\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, isDragging, onPointerDown };\n}\n"],"names":["useGinger","pb","useGingerPlayback","md","useGingerMedia","useMemo","state","gingerStateFromContextValues","getCurrentTrack","derivePlaybackUiState","effectiveDuration","effectiveRemaining","progressFraction","resolvedArtwork","resolvedAlbumLine","useGingerKeyboardShortcuts","enabled","bindings","togglePlayPause","next","prev","toggleMute","muteBinding","useEffect","playPause","nextKey","prevKey","muteKey","onKeyDown","event","target","key","useGingerChapters","tracks","currentIndex","currentTime","seek","list","_a","item","a","b","activeIndex","i","index","chapter","lrcTag","parseLrc","lrc","lines","rawLine","matches","text","m","minutes","seconds","millis","time","useGingerLyricsSync","currentTrack","line","useGingerSleepTimer","options","durationMs","stopAfterTracks","respectPause","onFire","pause","isPaused","remainingTracksRef","useRef","prevIndexRef","id","useGingerDebugLog","useGingerState","prevRef","clamp01","value","useSeekDrag","duration","fraction","setFraction","useState","isDragging","setIsDragging","onPointerDown","useCallback","rect","update","clientX","ratio","onMove","moveEvent","onUp","upEvent"],"mappings":"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"}
|