59 lines
1.8 KiB
TypeScript
59 lines
1.8 KiB
TypeScript
import { useState } from 'react';
|
|
import { CHARACTER_PRESETS, CUSTOM_CHARACTER_LABEL } from '../../../constants/characters';
|
|
import styles from '../RightPanel.module.css';
|
|
|
|
interface Props {
|
|
speaker: string;
|
|
portrait: string;
|
|
onSpeakerChange: (speaker: string, portrait: string) => void;
|
|
}
|
|
|
|
export function SpeakerField({ speaker, portrait, onSpeakerChange }: Props) {
|
|
const isPreset = CHARACTER_PRESETS.some(p => p.label === speaker);
|
|
const [isCustom, setIsCustom] = useState(!isPreset);
|
|
|
|
function handleSelect(e: React.ChangeEvent<HTMLSelectElement>) {
|
|
const val = e.target.value;
|
|
if (val === CUSTOM_CHARACTER_LABEL) {
|
|
setIsCustom(true);
|
|
onSpeakerChange(speaker, portrait);
|
|
} else {
|
|
setIsCustom(false);
|
|
const preset = CHARACTER_PRESETS.find(p => p.label === val);
|
|
onSpeakerChange(val, preset?.portrait ?? '');
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<label className={styles.label}>Speaker</label>
|
|
<select
|
|
className={styles.select}
|
|
value={isCustom ? CUSTOM_CHARACTER_LABEL : speaker}
|
|
onChange={handleSelect}
|
|
>
|
|
{CHARACTER_PRESETS.map(p => (
|
|
<option key={p.label} value={p.label}>{p.label}</option>
|
|
))}
|
|
<option value={CUSTOM_CHARACTER_LABEL}>{CUSTOM_CHARACTER_LABEL}</option>
|
|
</select>
|
|
{isCustom && (
|
|
<input
|
|
className={styles.input}
|
|
style={{ marginTop: 4 }}
|
|
value={speaker}
|
|
placeholder="Speaker name"
|
|
onChange={e => onSpeakerChange(e.target.value, portrait)}
|
|
/>
|
|
)}
|
|
<label className={styles.label} style={{ marginTop: 8 }}>Portrait path</label>
|
|
<input
|
|
className={styles.input}
|
|
value={portrait}
|
|
placeholder="resources/dialogue/portrait_..."
|
|
onChange={e => onSpeakerChange(speaker, e.target.value)}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|