1a9f0f2557
Co-authored-by: Cursor <cursoragent@cursor.com>
57 lines
1.6 KiB
TypeScript
57 lines
1.6 KiB
TypeScript
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];
|
|
}
|