);
}
// ── MediaPlayer ───────────────────────────────────────────────────────────────
const HIDE_DELAY = 2500;
interface MediaPlayerProps {
src: string;
kind: "audio" | "video";
mime?: string;
poster?: string;
autoplay?: boolean;
startTime?: number;
onPlayStateChange?: (playing: boolean) => void;
onTimeUpdate?: (time: number, duration: number) => void;
/** Fired when the media reaches its end — the queue's advance hook. */
onEnded?: () => void;
/** Fired when the element fails to load or decode. For expiring stream URLs
* this is the signal to re-resolve. */
onError?: () => void;
/** "waveform" (default) decodes peaks from the source; "progress" draws a
* slim seek bar and never fetches the media a second time. */
trackStyle?: "waveform" | "progress";
seekRef?: { current: ((t: number) => void) | null };
toggleRef?: { current: (() => void) | null };
}
export function MediaPlayer(
{
src,
kind,
mime,
poster,
autoplay,
startTime,
onPlayStateChange,
onTimeUpdate,
onEnded,
onError,
trackStyle = "waveform",
seekRef,
toggleRef,
}: MediaPlayerProps,
) {
const mediaRef = useRef