import { useState, useRef, useMemo } from 'react'; import { Search, Play, Square, AudioLines } from 'lucide-react'; import { Widget } from 'widgets/Widget'; import { Input } from '@/components/ui/input'; import { categories, allSounds } from './catalog-data'; import type { SoundAsset } from './types'; type ActiveCategory = 'all' | string; const formatName = (name: string) => name .split('-') .map((w) => w.charAt(0).toUpperCase() + w.slice(1)) .join(' '); const getCategoryLabel = (sound: SoundAsset): string => { const cat = categories.find((c) => c.sounds.includes(sound)); return cat?.label ?? ''; }; const SoundCard = ({ sound, isPlaying, onPlay, onStop, }: { sound: SoundAsset; isPlaying: boolean; onPlay: () => void; onStop: () => void; }) => ( ); export const Catalog = () => { const [search, setSearch] = useState(''); const [activeCategory, setActiveCategory] = useState('all'); const [playingId, setPlayingId] = useState(null); const audioRef = useRef(null); const filtered = useMemo(() => { const source = activeCategory === 'all' ? allSounds : (categories.find((c) => c.id === activeCategory)?.sounds ?? []); if (!search) return source; const q = search.toLowerCase(); return source.filter((s) => s.name.toLowerCase().includes(q)); }, [search, activeCategory]); const play = (sound: SoundAsset) => { if (audioRef.current) { audioRef.current.pause(); audioRef.current = null; } const audio = new Audio(sound.dataUri); audio.addEventListener('ended', () => setPlayingId(null)); audio.play(); audioRef.current = audio; setPlayingId(sound.name); }; const stop = () => { if (audioRef.current) { audioRef.current.pause(); audioRef.current = null; } setPlayingId(null); }; const tabs = [ { id: 'all' as const, label: 'All', count: allSounds.length }, ...categories.map((c) => ({ id: c.id, label: c.label, count: c.sounds.length })), ]; return (
setSearch(ev.target.value)} className="pl-9" />
{tabs.map((tab) => ( ))}
{filtered.length} sounds
{filtered.length === 0 &&

No sounds found.

}
{filtered.map((sound) => ( play(sound)} onStop={stop} /> ))}
CC0 licensed · Original audio by{' '} Kenney powered by soundcn
); };