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, useRef, useEffect } from "preact/hooks"; import clsx from "clsx"; import { CharacterEditor } from "./character-editor"; import { LocationEditor } from "./location-editor"; import { ChaptersEditor } from "./chapters-editor"; import { LoreEditor } from "./lore-editor"; import { useInputCallback } from "@common/hooks/useInputCallback"; import Prompt from "../utils/prompt"; const TABS: { id: Tab; label: string; right?: boolean }[] = [ { id: "story", label: "Story" }, { id: "chapters", label: "Chapters" }, { id: "lore", label: "Lore" }, { id: "characters", label: "Characters" }, { id: "locations", label: "Locations" }, { id: "scratchpad", label: "Scratchpad", right: true }, { id: "prompt", label: "Prompt" }, ]; export const Editor = () => { const appState = useAppState(); const { currentStory, dispatch } = appState; const handleInput = useInputCallback((text: string) => { if (!currentStory) return; dispatch({ type: 'EDIT_STORY', id: currentStory.id, text }); }, [currentStory?.id]); const handleScratchpadInput = useInputCallback((text: string) => { if (!currentStory) return; dispatch({ type: 'EDIT_SCRATCHPAD', id: currentStory.id, text }); }, [currentStory?.id]); const handleTabChange = (tab: Tab) => { if (!currentStory) return; dispatch({ type: 'SET_CURRENT_TAB', id: currentStory.id, tab, }); }; const contentRef = useRef(null); useEffect(() => { if (contentRef.current) { contentRef.current.scrollTop = contentRef.current.scrollHeight; } }, [currentStory?.id, currentStory?.currentTab]); const storyValue = useMemo(() => { if (!currentStory) return ''; const { text, lastEditedText } = currentStory; if (!lastEditedText) return highlight(text); const idx = text.lastIndexOf(lastEditedText); if (idx === -1) return highlight(text); const marked = text.slice(0, idx) + '' + lastEditedText + '' + text.slice(idx + lastEditedText.length); return highlight(marked); }, [currentStory?.text, currentStory?.lastEditedText]); const promptPreview = useMemo(() => { if (currentStory?.currentTab !== 'prompt') return ''; const text = Prompt.formatSystemPrompt(appState); return highlight(text, false); }, [currentStory?.currentTab, appState]); if (!currentStory) { return
; } return (
{currentStory.title}
{currentStory.currentTab === "story" && ( )} {currentStory.currentTab === "lore" && ( )} {currentStory.currentTab === "characters" && ( )} {currentStory.currentTab === "locations" && ( )} {currentStory.currentTab === "chapters" && ( )} {currentStory.currentTab === "scratchpad" && ( )} {currentStory.currentTab === "prompt" && (
)}
{TABS.map((tab) => ( ))}
); };