`frontend/src/pages/Play.jsx` was 2280 lines holding 27 components. It is now `frontend/src/pages/Play/`: `index.jsx` with the page component, five panels, two drawers, the reports, the take pager, the refresh dialog, and the shared formatting helpers. Every line moved verbatim. A coverage check confirms every non-blank line of the original appears exactly once, in order, across the twelve files, and a name-resolution check confirms every identifier each file references is defined or imported there, with no unused imports. The line split stranded a comment at six of the boundaries. A leading comment sits above the section it describes, so each cut left one at the end of the file before it. All six moved to the section they describe, rewritten in the house style. `usePlaySession.js` is not here. The page component still owns all of the session state. Moving eighteen `useState` calls and seven `useEffect` calls is a rewrite rather than a move, and no frontend test would catch a mistake in it today, so it waits for Stage 5. Four stand-in providers under `backend/tools/` now define `last_usage = None`. The turn engine reads that attribute after every call, and the fixtures never defined it, so `tools.tree_fixture` crashed. That break predates this branch. Verified by 549 passing tests, a clean `npm run lint` and `npm run build`, and by driving the Play screen: the story view, all five panels, both drawers including the world-state edit form, the branch map, the refresh dialog, and the take pager stepping onto a take that lives on another branch. No console errors. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Dix4oGV3njgWRdu7P9t6r
68 lines
2.4 KiB
JavaScript
68 lines
2.4 KiB
JavaScript
// Labels and formatting shared by the panels that report on a turn.
|
|
//
|
|
// `SECTION_COLORS` and `SECTION_FALLBACK` stay private. Read a color through
|
|
// `sectionColor`, so an unknown section gets the fallback rather than
|
|
// `undefined`.
|
|
|
|
const SECTION_LABELS = {
|
|
narrator: 'Narrator prompt',
|
|
script_context: 'Script context',
|
|
ai_instructions: 'AI Instructions',
|
|
plot_essentials: 'Plot Essentials',
|
|
story_summary: 'Story Summary',
|
|
used_memories: 'Used Memories (memory bank)',
|
|
world_state_guide: 'World State (stat guide)',
|
|
world_state: 'World State (RPG)',
|
|
world_state_rule: 'World State (reporting rule)',
|
|
world_lore: 'World Lore (story cards)',
|
|
history: 'Story history',
|
|
authors_note: "Author's Note",
|
|
recent_history: 'Recent history',
|
|
front_memory: 'Front memory',
|
|
length_hint: 'Length guidance',
|
|
world_state_reminder: 'World State (emit reminder)',
|
|
}
|
|
|
|
// One colour per context section, and the single source of truth for it: the
|
|
// token bar, the legend and each section's own header all read from here, so a
|
|
// slice of the bar and the text it stands for always carry the same colour.
|
|
// Related sections share a hue family but never an exact shade — in a stacked
|
|
// bar two identical colours read as one section.
|
|
const SECTION_COLORS = {
|
|
narrator: '#7d8fc9',
|
|
ai_instructions: '#9c8fd6',
|
|
plot_essentials: '#c97dc0',
|
|
script_context: '#d99ad0',
|
|
story_summary: '#7dc9a2',
|
|
used_memories: '#5fb8c9',
|
|
world_lore: '#c9b47d',
|
|
world_state: '#d79a63',
|
|
world_state_guide: '#b8834a',
|
|
world_state_rule: '#9d7a52',
|
|
world_state_reminder: '#8a6f52',
|
|
history: '#74748c',
|
|
recent_history: '#9d9db4',
|
|
authors_note: '#c97d7d',
|
|
front_memory: '#d99a9a',
|
|
length_hint: '#98a06b',
|
|
}
|
|
const SECTION_FALLBACK = '#6a6a78'
|
|
const sectionColor = (label) => SECTION_COLORS[label] || SECTION_FALLBACK
|
|
|
|
// Share of the prompt, rounded for glanceability. Sections too small to round
|
|
// to a whole percent still say so rather than showing a misleading 0%.
|
|
const pctLabel = (pct) => (pct > 0 && pct < 1 ? '<1%' : `${Math.round(pct)}%`)
|
|
|
|
const FIELD_LABELS = {
|
|
memory: 'Plot Essentials (Memory)',
|
|
authors_note: "Author's Note",
|
|
ai_instructions: 'AI Instructions',
|
|
}
|
|
|
|
function clip(text, n = 90) {
|
|
const one = (text || '').replace(/\s+/g, ' ').trim()
|
|
return one.length > n ? `${one.slice(0, n)}…` : (one || '(empty)')
|
|
}
|
|
|
|
export { SECTION_LABELS, sectionColor, pctLabel, FIELD_LABELS, clip }
|