-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathreducer.ts
More file actions
47 lines (43 loc) · 1.23 KB
/
reducer.ts
File metadata and controls
47 lines (43 loc) · 1.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import type { MouseEvent } from 'react';
export type State =
| { mode: 'view' }
| {
mode: 'atom-label-edit';
atomId: number;
atomCoords: { x: number; y: number };
};
export type Action =
| {
type: 'startEdit';
atomId: number;
event: MouseEvent;
}
| { type: 'stopEdit' };
/**
* Reducer for the editor state.
* @param state - The current state.
* @param action - The action to perform.
* @returns The new state.
*/
export function stateReducer(state: State, action: Action): State {
switch (action.type) {
case 'startEdit': {
// Ignore if we are already in edit mode
if (state.mode !== 'view') return state;
const { clientX, clientY } = action.event;
const target = action.event.target as SVGCircleElement;
const svg = target.closest('svg') as SVGElement;
const rect = svg.getBoundingClientRect();
const atomCoords = {
x: clientX - rect.x,
y: clientY - rect.y,
};
return { mode: 'atom-label-edit', atomId: action.atomId, atomCoords };
}
case 'stopEdit':
return { mode: 'view' };
default:
// @ts-expect-error action type narrowing
throw new Error(`Unknown action type: ${action.type}`);
}
}