1
0
Fork 0
tsgames/src/games/storywriter/components/editor.tsx

100 lines
3.3 KiB
TypeScript

import { ContentEditable } from "@common/components/ContentEditable";
import { highlight } from "@common/highlight";
import { useAppState, type Tab } from "../contexts/state";
import styles from '../assets/editor.module.css';
import { useMemo } from "preact/hooks";
import clsx from "clsx";
import { CharacterEditor } from "./character-editor";
import { LocationEditor } from "./location-editor";
import { ChaptersEditor } from "./chapters-editor";
import { useInputCallback } from "@common/hooks/useInputCallback";
const TABS: { id: Tab; label: string }[] = [
{ id: "story", label: "Story" },
{ id: "chapters", label: "Chapters" },
{ id: "lore", label: "Lore" },
{ id: "characters", label: "Characters" },
{ id: "locations", label: "Locations" },
];
export const Editor = () => {
const { currentStory, dispatch } = useAppState();
if (!currentStory) {
return <div class={styles.editor} />;
}
const handleInput = useInputCallback((text: string) => {
dispatch({
type: 'EDIT_STORY',
id: currentStory.id,
text,
});
}, []);
const handleLoreInput = useInputCallback((lore: string) => {
dispatch({
type: 'EDIT_LORE',
id: currentStory.id,
lore,
});
}, []);
const handleTabChange = (tab: Tab) => {
dispatch({
type: 'SET_CURRENT_TAB',
id: currentStory.id,
tab,
});
};
const storyValue = useMemo(() => highlight(currentStory.text), [currentStory.text]);
const loreValue = useMemo(() => highlight(currentStory.lore), [currentStory.lore]);
return (
<div class={styles.editor}>
<div class={styles.title}>
{currentStory.title}
</div>
<div class={styles.content}>
{currentStory.currentTab === "story" && (
<ContentEditable
class={styles.editable}
value={storyValue}
onInput={handleInput}
placeholder="Start writing your story..."
/>
)}
{currentStory.currentTab === "lore" && (
<ContentEditable
class={styles.editable}
value={loreValue}
onInput={handleLoreInput}
placeholder="Add lore, world-building details, and background information..."
/>
)}
{currentStory.currentTab === "characters" && (
<CharacterEditor />
)}
{currentStory.currentTab === "locations" && (
<LocationEditor />
)}
{currentStory.currentTab === "chapters" && (
<ChaptersEditor />
)}
</div>
<div class={styles.tabs}>
{TABS.map((tab) => (
<button
key={tab.id}
class={clsx(styles.tab, currentStory.currentTab === tab.id && styles.active)}
onClick={() => handleTabChange(tab.id)}
>
{tab.label}
</button>
))}
</div>
</div>
);
};