diff --git a/package.json b/package.json index 5d9daca..3fc5d13 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "1.0.0", "type": "module", "scripts": { - "start": "bun build/server.ts", + "start": "bun --hot build/server.ts", "bake": "bun build/build.ts", "test": "bun test" }, diff --git a/src/common/hooks/useInputCallback.ts b/src/common/hooks/useInputCallback.ts index eff731e..9dfa635 100644 --- a/src/common/hooks/useInputCallback.ts +++ b/src/common/hooks/useInputCallback.ts @@ -1,16 +1,6 @@ +import { extractString } from "@common/utils"; import { useCallback } from "preact/hooks"; -export function useInputCallback(callback: (value: string) => T, deps: any[]): ((value: string | Event) => T) { - return useCallback((e: Event | string) => { - if (typeof e === 'string') { - return callback(e); - } else { - const { target } = e; - if (target && 'value' in target && typeof target.value === 'string') { - return callback(target.value); - } - } - - return callback(''); - }, deps); -} \ No newline at end of file +export const useInputCallback = (callback: (value: string) => T, deps: any[]): ((value: string | Event) => T) => ( + useCallback((e: Event | string) => callback(extractString(e)), deps) +); diff --git a/src/common/hooks/useInputState.ts b/src/common/hooks/useInputState.ts index 41b10c3..e913cae 100644 --- a/src/common/hooks/useInputState.ts +++ b/src/common/hooks/useInputState.ts @@ -1,19 +1,11 @@ +import { extractString } from "@common/utils"; import { useCallback, useState } from "preact/hooks"; export const useInputState = (defaultValue = ''): [string, (e: Event | string) => void] => { const [value, setValue] = useState(defaultValue); const handleInput = useCallback((e: Event | string) => { - if (typeof e === 'string') { - setValue(e); - } else { - const { target } = e; - if (target && 'value' in target && typeof target.value === 'string') { - setValue(target.value); - } else if (target instanceof HTMLElement) { - setValue(target.innerHTML); - } - } + setValue(extractString(e)); }, []); return [value, handleInput]; diff --git a/src/common/utils.ts b/src/common/utils.ts index 5f0f907..353316f 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -160,3 +160,17 @@ export const formatTime = (seconds: number): string => { parts.push(timeStr); return parts.join(' '); }; + +export const extractString = (e: Event | string): string => { + if (typeof e === 'string') { + return e; + } else { + const { target } = e; + if (target && 'value' in target && typeof target.value === 'string') { + return target.value; + } else if (target instanceof HTMLElement) { + return target.innerHTML; + } + } + return ''; +} \ No newline at end of file diff --git a/src/games/storywriter/components/editors/character.tsx b/src/games/storywriter/components/editors/character.tsx index 9d7e014..e2967bf 100644 --- a/src/games/storywriter/components/editors/character.tsx +++ b/src/games/storywriter/components/editors/character.tsx @@ -4,6 +4,7 @@ import { useState } from "preact/hooks"; import styles from '../../assets/character-editor.module.css'; import { CharacterRole, useAppState, type Character } from "../../contexts/state"; import LLM from "../../utils/llm"; +import { extractString } from "@common/utils"; export const CharacterEditor = ({ visible }: { visible: boolean }) => { const { currentWorld, currentStory, mergedCharacters, dispatch, connection, model } = useAppState(); @@ -38,7 +39,10 @@ export const CharacterEditor = ({ visible }: { visible: boolean }) => { }); }; - const handleEditCharacter = (characterId: string, field: keyof Character, value: any) => { + const handleEditCharacter = (characterId: string, field: keyof Character, value: string[] | string | Event) => { + if (!Array.isArray(value)) { + value = extractString(value); + } dispatch({ type: 'EDIT_CHARACTER', worldId, @@ -71,14 +75,14 @@ export const CharacterEditor = ({ visible }: { visible: boolean }) => { setNewRelation({ ...newRelation, [characterId]: { name: '', relation: '' } }); }; - const handleEditRelation = (characterId: string, targetName: string, field: 'name' | 'relation', value: string) => { + const handleEditRelation = (characterId: string, targetName: string, field: 'name' | 'relation', value: string | Event) => { dispatch({ type: 'EDIT_CHARACTER_RELATION', worldId, storyId, characterId, targetName, - updates: { [field]: value }, + updates: { [field]: extractString(value) }, }); }; @@ -110,7 +114,8 @@ export const CharacterEditor = ({ visible }: { visible: boolean }) => { } }; - const handleNewRelationChange = (characterId: string, field: 'name' | 'relation', value: string) => { + const handleNewRelationChange = (characterId: string, field: 'name' | 'relation', value: string | Event) => { + value = extractString(value); const current = newRelation[characterId] || { name: '', relation: '' }; setNewRelation({ ...newRelation, [characterId]: { ...current, [field]: value } }); }; @@ -153,7 +158,7 @@ export const CharacterEditor = ({ visible }: { visible: boolean }) => { type="text" class={styles.nameInput} value={character.name} - onInput={(e) => handleEditCharacter(character.id, 'name', e.currentTarget.value)} + onInput={(e) => handleEditCharacter(character.id, 'name', e)} onFocus={(e) => e.currentTarget.select()} placeholder="Character name" /> @@ -191,7 +196,7 @@ export const CharacterEditor = ({ visible }: { visible: boolean }) => {