diff --git a/src/components/sound/sound.tsx b/src/components/sound/sound.tsx index 02acc50..a435ba2 100644 --- a/src/components/sound/sound.tsx +++ b/src/components/sound/sound.tsx @@ -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 (
setIsSelected(prev => !prev)} onKeyDown={() => setIsSelected(prev => !prev)} > -

{sound.label}

+

{label}

{sounds.map(sound => ( - + ))}
); diff --git a/src/hooks/use-sound.ts b/src/hooks/use-sound.ts new file mode 100644 index 0000000..3ebe467 --- /dev/null +++ b/src/hooks/use-sound.ts @@ -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(() => { + 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; +} diff --git a/src/hooks/use-ssr.ts b/src/hooks/use-ssr.ts new file mode 100644 index 0000000..ef2f8c1 --- /dev/null +++ b/src/hooks/use-ssr.ts @@ -0,0 +1,11 @@ +export function useSSR() { + const isDOM = + typeof window !== 'undefined' && + window.document && + window.document.documentElement; + + return { + isBrowser: isDOM, + isServer: !isDOM, + }; +}