feat: add basic audio player

This commit is contained in:
MAZE 2023-10-06 16:58:26 +03:30
parent c9e8bd41fd
commit 5a7a58e883
4 changed files with 61 additions and 6 deletions

View file

@ -1,20 +1,31 @@
import { useState, useEffect } from 'react';
import { useSound } from '@/hooks/use-sound';
import { cn } from '@/helpers/styles';
import styles from './sound.module.css';
interface SoundProps {
sound: { label: string; src: string };
label: string;
src: string;
}
export function Sound({ sound }: SoundProps) {
export function Sound({ label, src }: SoundProps) {
const [isSelected, setIsSelected] = useState(false);
const [volume, setVolume] = useState(0.5);
const sound = useSound(src, { loop: true, volume });
useEffect(() => {
if (!isSelected) setVolume(0.5);
}, [isSelected]);
if (!isSelected) {
sound?.pause();
setVolume(0.5);
}
if (isSelected) {
sound?.play();
}
}, [isSelected, sound]);
return (
<div
@ -22,8 +33,9 @@ export function Sound({ sound }: SoundProps) {
onClick={() => setIsSelected(prev => !prev)}
onKeyDown={() => setIsSelected(prev => !prev)}
>
<h3>{sound.label}</h3>
<h3>{label}</h3>
<input
autoComplete="off"
disabled={!isSelected}
max={100}
min={0}

View file

@ -10,7 +10,7 @@ export function Sounds({ sounds }: SoundsProps) {
return (
<div className={styles.sounds}>
{sounds.map(sound => (
<Sound key={sound.label} sound={sound} />
<Sound key={sound.label} {...sound} />
))}
</div>
);

32
src/hooks/use-sound.ts Normal file
View file

@ -0,0 +1,32 @@
import { useMemo, useEffect } from 'react';
import { useSSR } from './use-ssr';
export function useSound(
src: string,
options: { volume?: number; loop?: boolean } = {},
): HTMLAudioElement | null {
const { isBrowser } = useSSR();
const sound = useMemo<HTMLAudioElement | null>(() => {
let sound: HTMLAudioElement | null = null;
if (isBrowser) {
sound = new Audio(src);
sound.preload = 'none';
}
return sound;
}, [src, isBrowser]);
useEffect(() => {
if (sound)
sound.loop = typeof options.loop === 'boolean' ? options.loop : false;
}, [sound, options.loop]);
useEffect(() => {
if (sound)
sound.volume = typeof options.volume === 'number' ? options.volume : 0.5;
}, [sound, options.volume]);
return sound;
}

11
src/hooks/use-ssr.ts Normal file
View file

@ -0,0 +1,11 @@
export function useSSR() {
const isDOM =
typeof window !== 'undefined' &&
window.document &&
window.document.documentElement;
return {
isBrowser: isDOM,
isServer: !isDOM,
};
}