import * as React from 'react'; import {WaveSurferOptions} from 'wavesurfer.js'; import clsx from 'clsx'; import {getFormValues} from '@theoryofnekomata/formxtra'; export type WaveformCanvasDerivedElement = HTMLDivElement; export interface WaveformCanvasProps extends React.HTMLProps, Omit { audioRef?: React.Ref; } export const WaveformCanvas = React.forwardRef(({ className, children, controls, waveColor, progressColor, cursorColor, cursorWidth, barWidth, barGap, barRadius, barHeight, barAlign, minPxPerSec, peaks, duration, autoPlay, interact, hideScrollbar, audioRate, autoScroll, autoCenter, sampleRate, splitChannels, normalize, audioRef, ...etcProps }, forwardedRef) => { const [isPlaying, setIsPlaying] = React.useState(false); const defaultRef = React.useRef(null); const containerRef = forwardedRef ?? defaultRef; const waveSurferRef = React.useRef(null); const handleAction: React.FormEventHandler = (e) => { e.preventDefault(); const nativeEvent = e.nativeEvent as unknown as { submitter: HTMLElement }; const formData = getFormValues( e.currentTarget, { submitter: nativeEvent.submitter, } ); const actionName = formData['action'] as string; switch (actionName) { case 'togglePlayback': setIsPlaying((prev) => !prev); break; default: break; } }; React.useEffect(() => { if (!(typeof audioRef === 'object' && audioRef)) { return; } const { current: media } = audioRef; if (!media) { return; } if (!(typeof containerRef === 'object' && containerRef)) { return; } const { current: container } = containerRef; if (!container) { return; } const load = async (media: HTMLAudioElement, container: HTMLElement) => { const {default: WaveSurfer} = await import('wavesurfer.js'); const waveSurferInstance = WaveSurfer.create({ container, height: 'auto', autoplay: autoPlay, fillParent: true, waveColor, progressColor, cursorColor, barWidth, barGap, barRadius, barHeight, barAlign, minPxPerSec, peaks, duration, interact, hideScrollbar, audioRate, autoScroll, autoCenter, sampleRate, splitChannels, normalize, cursorWidth, plugins: [], media, }); waveSurferInstance.on('ready', () => { if (!container) { return; } while (container.children.length > 1) { container.removeChild(container.children[0]); } }); await waveSurferInstance.load(media.currentSrc); waveSurferInstance.setTime(media.currentTime); return waveSurferInstance; }; const { current: waveSurferCurrent } = waveSurferRef; load(media, container) .then((i) => { waveSurferRef.current = i; }) .catch((error) => { console.log(error); }); return () => { if (waveSurferCurrent) { (waveSurferCurrent as unknown as Record).destroy(); } if (container) { container.innerHTML = ''; } }; }, [ audioRef, autoPlay, waveColor, progressColor, cursorColor, barWidth, barGap, barRadius, barHeight, barAlign, minPxPerSec, peaks, duration, interact, hideScrollbar, audioRate, autoScroll, autoCenter, sampleRate, splitChannels, normalize, cursorWidth, containerRef, ]); return (
{controls && (
)}
); }); WaveformCanvas.displayName = 'WavesurferCanvas';