diff --git a/frontend/src/index.css b/frontend/src/index.css index cc6b757..66ef541 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -544,6 +544,25 @@ button:disabled { opacity: 0.45; cursor: default; transform: none; box-shadow: n white-space: pre-wrap; word-break: break-word; } +/* Recursive script-state value tree */ +.jv-string { color: var(--text); } +.jv-number { color: var(--player); } +.jv-bool { color: var(--accent-bright); } +.jv-null { color: var(--text-dim); font-style: italic; } +.jv-empty { color: var(--text-dim); } +.jv-tree { display: inline-block; vertical-align: top; max-width: 100%; } +.jv-toggle { + background: none; border: none; padding: 0; cursor: pointer; + font-family: inherit; font-size: 0.72rem; color: var(--text-dim); +} +.jv-toggle:hover { color: var(--accent-bright); } +.jv-children { + list-style: none; margin: 2px 0 2px 0; padding-left: 12px; + border-left: 1px solid var(--border); +} +.jv-children li { padding: 2px 0; word-break: break-word; } +.jv-key { color: var(--accent); margin-right: 6px; } +.jv-key::after { content: ':'; color: var(--text-dim); } @keyframes panel-in { from { opacity: 0; transform: translateX(16px); } to { opacity: 1; transform: none; } diff --git a/frontend/src/pages/Play.jsx b/frontend/src/pages/Play.jsx index f889f70..0f38946 100644 --- a/frontend/src/pages/Play.jsx +++ b/frontend/src/pages/Play.jsx @@ -392,6 +392,41 @@ function ScriptsPanel({ advId }) { ) } +// Renders one script-state value: primitives inline (typed/coloured), and +// objects/arrays as a collapsible, indented tree — recursing into nesting so +// deep state shows structure instead of a flat JSON blob. +function StateValue({ value }) { + if (value === null || value === undefined) return null + if (typeof value === 'boolean') return {String(value)} + if (typeof value === 'number') return {value} + if (typeof value === 'string') return {value} + if (Array.isArray(value)) return [i, v])} empty="[ ]" /> + if (typeof value === 'object') return + return {String(value)} +} + +function StateTree({ entries, empty }) { + const [open, setOpen] = useState(true) + if (entries.length === 0) return {empty} + return ( +
+ + {open && ( +
    + {entries.map(([k, v]) => ( +
  • + {k} + +
  • + ))} +
+ )} +
+ ) +} + // Collapsible left rail showing the scripting `state` object — every variable // scripts read/write via state.x, refreshed after each turn. function StatusDrawer({ advId, refreshKey }) { @@ -433,9 +468,7 @@ function StatusDrawer({ advId, refreshKey }) { {entries.map(([k, v]) => (
  • {k} - - {typeof v === 'string' ? v : JSON.stringify(v, null, 2)} - +
  • ))}