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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
import { GridComponent } from '@/components/grid/GridComponent';
import type { AnsiTermColor, Grid, GridCell } from '@/types/grid';
import {
type IZipper,
ListZipper,
} from '@emprespresso/pengueno';
import { useCallback, useState } from 'react';
export interface ChooseArtProps {
grid: Grid;
}
export const Paint: React.FC<ChooseArtProps> = ({ grid }) => {
const [selectedColor, setSelectedColor] = useState<AnsiTermColor>({
foreground: { r: 5, g: 5, b: 5 },
background: null,
});
const [history, setHistory] = useState<IZipper<Grid>>(
ListZipper.from([grid]),
);
const cellInteractionCallback = useCallback(
(cell: GridCell) => {
setHistory((currentHistory) => {
const currentGrid = currentHistory.read().get();
const newGrid = currentGrid.map((row) => [...row]); // Deep copy for current state
newGrid[cell.y][cell.x] = { ...cell, color: selectedColor };
return currentHistory.prepend(newGrid).previous().get();
});
},
[selectedColor],
);
return (
<div>
<GridComponent
grid={history.read().get()}
onCellInteract={cellInteractionCallback}
/>
<button
disabled={
!history
.next()
.flatMap((it) => it.read())
.present()
}
onClick={() => setHistory((history) => history.next().get())}
>
Undo
</button>
<button
disabled={
!history
.previous()
.flatMap((it) => it.read())
.present()
}
onClick={() =>
setHistory((history) => history.previous().get())
}
>
Redo
</button>
</div>
);
};
|