56 lines
2.7 KiB
JavaScript
56 lines
2.7 KiB
JavaScript
import React, { useState } from 'react';
|
|
|
|
const STEM_ICONS = {
|
|
vocal: '🎤', backing_vocals: '🎶', drums: '🥁', bass: '🎸',
|
|
guitar: '🎸', keyboard: '🎹', strings: '🎻', brass: '🎺',
|
|
woodwinds: '🪈', percussion: '🪘', synth: '🎛', fx: '✨',
|
|
};
|
|
|
|
const StemModal = ({ stems, onClose }) => {
|
|
const [playingStem, setPlayingStem] = useState(null);
|
|
|
|
if (!stems || Object.keys(stems).length === 0) return null;
|
|
|
|
return (
|
|
<div className="ms-modal-overlay" onClick={onClose}>
|
|
<div className="ms-modal ms-modal--wide" onClick={(e) => e.stopPropagation()}>
|
|
<div className="ms-modal__header">
|
|
<h3 className="ms-modal__title">12 Stems</h3>
|
|
<span className="ms-modal__subtitle">각 스템을 개별 재생 및 다운로드할 수 있습니다</span>
|
|
<button type="button" className="ms-modal__close" onClick={onClose}>✕</button>
|
|
</div>
|
|
<div className="ms-stem-grid">
|
|
{Object.entries(stems).map(([name, url]) => {
|
|
if (!url) return null;
|
|
const isPlaying = playingStem === name;
|
|
return (
|
|
<div key={name} className={`ms-stem-card ${isPlaying ? 'is-playing' : ''}`}>
|
|
<span className="ms-stem-card__icon">{STEM_ICONS[name] || '🎵'}</span>
|
|
<span className="ms-stem-card__name">{name.replace(/_/g, ' ')}</span>
|
|
<div className="ms-stem-card__actions">
|
|
<button
|
|
type="button"
|
|
className="ms-btn--icon"
|
|
onClick={() => setPlayingStem(isPlaying ? null : name)}
|
|
>
|
|
{isPlaying ? '■' : '▶'}
|
|
</button>
|
|
<a href={url} download className="ms-btn--icon" aria-label="다운로드">↓</a>
|
|
</div>
|
|
{isPlaying && (
|
|
<audio src={url} autoPlay onEnded={() => setPlayingStem(null)} />
|
|
)}
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
<div className="ms-modal__actions">
|
|
<button type="button" className="ms-btn ms-btn--ghost" onClick={onClose}>닫기</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default StemModal;
|