import React, { useEffect, useMemo, useState } from 'react'; import { createPortal } from 'react-dom'; import { DEFAULT_NPC_GROUP_COLOR } from '../../shared/npcs/npcGroups'; import type { ProjectNpcGroup } from '../../shared/types'; import editorStyles from '../editor/EditorApp.module.css'; import { useEditorI18n } from '../editor/i18n/EditorI18nContext'; import { Button, Input } from '../shared/ui/controls'; import styles from './NpcGroupModal.module.css'; type NpcGroupModalProps = { open: boolean; initial: ProjectNpcGroup | null; siblingNames: string[]; onClose: () => void; onSave: (input: { name: string; color: string }) => Promise; }; function normalizeName(input: string): string { return input.trim().toLowerCase(); } export function NpcGroupModal({ open, initial, siblingNames, onClose, onSave }: NpcGroupModalProps) { const { t } = useEditorI18n(); const [name, setName] = useState(''); const [color, setColor] = useState(DEFAULT_NPC_GROUP_COLOR); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); useEffect(() => { if (!open) return; setName(initial?.name ?? ''); setColor(initial?.color ?? DEFAULT_NPC_GROUP_COLOR); setSaving(false); setError(null); }, [initial, open]); useEffect(() => { if (!open) return; const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey); }, [onClose, open]); const trimmed = name.trim(); const nameOk = trimmed.length >= 1; const nameDup = useMemo(() => { if (!nameOk) return false; const key = normalizeName(trimmed); const except = normalizeName(initial?.name ?? ''); return siblingNames.some((n) => { const nk = normalizeName(n); return nk === key && nk !== except; }); }, [initial?.name, nameOk, siblingNames, trimmed]); const canSave = nameOk && !nameDup && !saving; if (!open) return null; return createPortal( <>
{t('npcs.groupName')}
setColor(e.target.value)} aria-label={t('npcs.groupColor')} />
{!nameOk ?
{t('npcs.groupNameRequired')}
: null} {nameDup ?
{t('npcs.groupNameDup')}
: null}
{error ?
{error}
: null}
, document.body, ); }