import { useState } from 'react'; import { LineNode } from '../../../types/dialogue'; import { useDialogueStore } from '../../../store/dialogueStore'; import { SpeakerField } from '../shared/SpeakerField'; import { AutoSaveTextArea } from '../shared/TextArea'; import { useValidation } from '../../../hooks/useValidation'; import styles from '../RightPanel.module.css'; interface Props { node: LineNode; dialogueId: string; } export function LineInspector({ node, dialogueId }: Props) { const { updateNode, deleteNode, file } = useDialogueStore(); const { issuesByNodeId } = useValidation(); const [showAdvanced, setShowAdvanced] = useState(false); const issues = issuesByNodeId[node.id] ?? []; const dialogue = file?.dialogues.find(d => d.id === dialogueId); const nodeIds = dialogue?.nodes.map(n => n.id) ?? []; function update(patch: Partial) { updateNode(dialogueId, node.id, patch); } function field(label: string, key: keyof LineNode, placeholder?: string) { const val = (node[key] as string) ?? ''; return (
update({ [key]: e.target.value } as Partial)} list={key === 'next' ? `nodelist-${node.id}` : undefined} /> {key === 'next' && ( {nodeIds.map(id => )}
); } return (
Line {node.id}
{issues.length > 0 && (
{issues.map((issue, i) => (
{issue.severity === 'error' ? 'âš ' : '!'} {issue.message}
))}
)} {field('Node ID', 'id')} update({ speaker: s, portrait: p })} /> update({ text: v })} /> {field('Next node', 'next', 'node_id')} {dialogue?.mobileMode && (
)} {showAdvanced && (
{field('questUnlock', 'questUnlock', 'quest_id')} {field('objectiveComplete', 'objectiveComplete', 'group.objective')} {field('objectiveVisible', 'objectiveVisible', 'group.objective')} {field('questFail', 'questFail', 'quest_id')} {field('questComplete', 'questComplete', 'quest_id')} {field('luaCallback', 'luaCallback', 'on_event_name')}
)}
); }