1
0
Fork 0
tsgames/src/games/storywriter/components/editors/chapters.tsx

69 lines
3.1 KiB
TypeScript

import { ContentEditable } from "@common/components/ContentEditable";
import { highlight } from "@common/highlight";
import { useMemo } from "preact/hooks";
import styles from "../../assets/chapters-editor.module.css";
import { useAppState } from "../../contexts/state";
import Chapters from "../../utils/chapters";
export const ChaptersEditor = () => {
const { currentWorld, currentStory, dispatch } = useAppState();
if (!currentStory) return null;
const parsed = useMemo(
() => Chapters.parseText(currentStory.text),
[currentStory.text]
);
if (parsed.length === 0) {
return (
<div class={styles.chaptersEditor}>
<p class={styles.empty}>No chapters yet. Use <code># Chapter Title</code> headers in your story to create chapters.</p>
</div>
);
}
return (
<div class={styles.chaptersEditor}>
{parsed.map((parsedChapter) => {
const chunks = Chapters.splitIntoChunks(parsedChapter.body);
const cachedChapter = (currentStory.chapters ?? []).find(c => c.header === parsedChapter.header)
?? Chapters.emptyChapter(parsedChapter.header);
return (
<div class={styles.chapterCard} key={parsedChapter.header || '__preamble__'}>
<div class={styles.chapterTitle}>
{parsedChapter.header ? parsedChapter.header.replace(/^# /, '') : '(Preamble)'}
</div>
{chunks.map((body, i) => {
const { hash, summary } = Chapters.lookupSummary(cachedChapter, body);
return (
<div class={styles.chunk} key={i}>
{chunks.length > 1 && (
<div class={styles.chunkHeader}>Part {i + 1}</div>
)}
<div class={styles.chunkPreview}>{body}</div>
<ContentEditable
autoLines
class={styles.summaryEditable}
value={highlight(summary ?? '')}
placeholder="Not summarized yet..."
onInput={(e) => dispatch({
type: 'STORE_CHAPTER_SUMMARY',
worldId: currentWorld!.id,
storyId: currentStory.id,
header: parsedChapter.header,
hash,
summary: (e.target as HTMLDivElement).textContent || '',
})}
/>
</div>
);
})}
</div>
);
})}
</div>
);
};