feat(control): spawn session NPCs and resize tokens in preview
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { ipcChannels } from '../../../shared/ipc/contracts';
|
||||
import type { NpcMapSpawnDragState } from '../../../shared/types';
|
||||
import { asNpcId } from '../../../shared/types/ids';
|
||||
import { getDndApi } from '../dndApi';
|
||||
|
||||
const EMPTY: NpcMapSpawnDragState = {
|
||||
dragging: false,
|
||||
npcId: null,
|
||||
hoverNx: null,
|
||||
hoverNy: null,
|
||||
};
|
||||
|
||||
export function useNpcMapSpawnDrag(): [
|
||||
NpcMapSpawnDragState,
|
||||
{
|
||||
beginDrag: (npcId: string) => Promise<void>;
|
||||
setHover: (nx: number | null, ny: number | null) => Promise<void>;
|
||||
commit: () => Promise<boolean>;
|
||||
cancel: () => Promise<void>;
|
||||
},
|
||||
] {
|
||||
const api = getDndApi();
|
||||
const [state, setState] = useState<NpcMapSpawnDragState>(EMPTY);
|
||||
|
||||
useEffect(() => {
|
||||
void api.invoke(ipcChannels.npcMapSpawn.getState, {}).then(({ state: s }) => {
|
||||
setState(s);
|
||||
});
|
||||
return api.on(ipcChannels.npcMapSpawn.stateChanged, ({ state: s }) => {
|
||||
setState(s);
|
||||
});
|
||||
}, [api]);
|
||||
|
||||
const apiWrap = useMemo(
|
||||
() => ({
|
||||
beginDrag: async (npcId: string) => {
|
||||
await api.invoke(ipcChannels.npcMapSpawn.beginDrag, { npcId: asNpcId(npcId) });
|
||||
},
|
||||
setHover: async (nx: number | null, ny: number | null) => {
|
||||
await api.invoke(ipcChannels.npcMapSpawn.setHover, { nx, ny });
|
||||
},
|
||||
commit: async () => {
|
||||
const res = await api.invoke(ipcChannels.npcMapSpawn.commit, {});
|
||||
return Boolean(res.spawned);
|
||||
},
|
||||
cancel: async () => {
|
||||
await api.invoke(ipcChannels.npcMapSpawn.cancel, {});
|
||||
},
|
||||
}),
|
||||
[api],
|
||||
);
|
||||
|
||||
return [state, apiWrap];
|
||||
}
|
||||
Reference in New Issue
Block a user