feat(npcs): inspect cards, Show overlay, and optional external link

Clicking an NPC tile opens description cards (multi-select accordion); Show puts avatars on screen. Optional URL opens a webview tab. Avatar pan in the editor commits on pointer up.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ivan Fontosh
2026-08-19 10:42:57 +08:00
parent 1a9f0f2557
commit 0f4bb76b41
35 changed files with 1189 additions and 259 deletions
+40
View File
@@ -0,0 +1,40 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { asNpcId } from '../../shared/types/ids';
import { NpcsOverlayStore } from './npcsOverlayStore';
const a = asNpcId('npc_a');
const b = asNpcId('npc_b');
void test('NpcsOverlayStore: inspect is independent from overlay show', () => {
const store = new NpcsOverlayStore();
store.dispatch({ kind: 'inspect.toggle', npcId: a });
store.dispatch({ kind: 'inspect.show', npcId: b });
assert.deepEqual(store.getState().inspectNpcIds, [a, b]);
assert.equal(store.getState().inspectFocusNpcId, b);
assert.deepEqual(store.getState().activeNpcIds, []);
store.dispatch({ kind: 'show', npcId: a });
assert.deepEqual(store.getState().activeNpcIds, [a]);
assert.deepEqual(store.getState().inspectNpcIds, [a, b]);
store.dispatch({ kind: 'hide' });
assert.deepEqual(store.getState().activeNpcIds, []);
assert.deepEqual(store.getState().inspectNpcIds, [a, b]);
store.dispatch({ kind: 'inspect.toggle', npcId: a });
assert.deepEqual(store.getState().inspectNpcIds, [b]);
});
void test('NpcsOverlayStore: clear wipes inspect; ensureNpcStillExists prunes', () => {
const store = new NpcsOverlayStore();
store.dispatch({ kind: 'inspect.show', npcId: a });
store.dispatch({ kind: 'show', npcId: b });
store.ensureNpcStillExists(new Set([a]));
assert.deepEqual(store.getState().inspectNpcIds, [a]);
assert.deepEqual(store.getState().activeNpcIds, []);
store.clear();
assert.deepEqual(store.getState().inspectNpcIds, []);
});