actually have a more usable way in mind
This commit is contained in:
parent
89ecd65999
commit
584eb559bd
32
archive/number-state-input.tsx
Normal file
32
archive/number-state-input.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
interface StateInputProps<T> {
|
||||
state: PrimitiveAtom<T>;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const NumberStateInput: FC<StateInputProps<number | null>> = (
|
||||
props: StateInputProps<number | null>
|
||||
) => {
|
||||
const { state, className } = props;
|
||||
const [number, setNumber] = useAtom(state);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(e: ChangeEvent<HTMLInputElement>) => {
|
||||
const re = /^\d*$/;
|
||||
const v = e.target.value;
|
||||
if (v === '') {
|
||||
setNumber(null);
|
||||
} else if (re.test(v)) {
|
||||
setNumber(parseInt(v));
|
||||
}
|
||||
},
|
||||
[setNumber]
|
||||
);
|
||||
|
||||
return (
|
||||
<input
|
||||
className={className}
|
||||
value={number ?? ''}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
);
|
||||
};
|
@ -16,6 +16,3 @@ type DrawMode = 'line' | 'trash' | 'grid';
|
||||
export const lineColorState = atom<string>(COLORS[0]!);
|
||||
|
||||
export const drawModeState = atom<DrawMode>('line');
|
||||
|
||||
export const drawGridWidthState = atom<number | null>(4);
|
||||
export const drawGridHeightState = atom<number | null>(4);
|
||||
|
@ -1,12 +1,6 @@
|
||||
import { ChangeEvent, FC, useCallback } from 'react';
|
||||
import { PrimitiveAtom, useAtom, WritableAtom } from 'jotai';
|
||||
import {
|
||||
COLORS,
|
||||
drawGridHeightState,
|
||||
drawGridWidthState,
|
||||
drawModeState,
|
||||
lineColorState,
|
||||
} from '../../atoms';
|
||||
import { PrimitiveAtom, useAtom } from 'jotai';
|
||||
import { COLORS, drawModeState, lineColorState } from '../../atoms';
|
||||
|
||||
import './grid-config.scss';
|
||||
|
||||
@ -46,16 +40,14 @@ const GridIcon = (
|
||||
<svg
|
||||
className="icon"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="12"
|
||||
height="12"
|
||||
viewBox="0 0 12 12"
|
||||
viewBox="0 0 24 13"
|
||||
>
|
||||
<line x1="0" y1="0" x2="12" y2="0" stroke="#ffffff" strokeWidth="2" />
|
||||
<line x1="0" y1="6" x2="12" y2="6" stroke="#ffffff" strokeWidth="2" />
|
||||
<line x1="0" y1="12" x2="12" y2="12" stroke="#ffffff" strokeWidth="2" />
|
||||
<line x1="0" y1="0" x2="0" y2="12" stroke="#ffffff" strokeWidth="2" />
|
||||
<line x1="6" y1="0" x2="6" y2="12" stroke="#ffffff" strokeWidth="2" />
|
||||
<line x1="12" y1="0" x2="12" y2="12" stroke="#ffffff" strokeWidth="2" />
|
||||
<line x1="5" y1="0" x2="18" y2="0" stroke="#ffffff" strokeWidth="4" />
|
||||
<line x1="5" y1="7" x2="18" y2="7" stroke="#ffffff" strokeWidth="2" />
|
||||
<line x1="5" y1="13" x2="18" y2="13" stroke="#ffffff" strokeWidth="4" />
|
||||
<line x1="5" y1="0" x2="5" y2="13" stroke="#ffffff" strokeWidth="2" />
|
||||
<line x1="11" y1="0" x2="11" y2="13" stroke="#ffffff" strokeWidth="2" />
|
||||
<line x1="17" y1="0" x2="17" y2="13" stroke="#ffffff" strokeWidth="2" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
@ -84,39 +76,6 @@ const ColorOption: FC<ColorOptionProps> = (props: ColorOptionProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
interface StateInputProps<T> {
|
||||
state: PrimitiveAtom<T>;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const NumberStateInput: FC<StateInputProps<number | null>> = (
|
||||
props: StateInputProps<number | null>
|
||||
) => {
|
||||
const { state, className } = props;
|
||||
const [number, setNumber] = useAtom(state);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(e: ChangeEvent<HTMLInputElement>) => {
|
||||
const re = /^\d*$/;
|
||||
const v = e.target.value;
|
||||
if (v === '') {
|
||||
setNumber(null);
|
||||
} else if (re.test(v)) {
|
||||
setNumber(parseInt(v));
|
||||
}
|
||||
},
|
||||
[setNumber]
|
||||
);
|
||||
|
||||
return (
|
||||
<input
|
||||
className={className}
|
||||
value={number ?? ''}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const ColorConfig: FC = () => (
|
||||
<div className="color-options">
|
||||
{COLORS.map((color) => (
|
||||
@ -130,8 +89,7 @@ const ModeConfig: FC = () => {
|
||||
|
||||
const lineClassName = drawMode === 'line' ? 'option active' : 'option';
|
||||
const trashClassName = drawMode === 'trash' ? 'option active' : 'option';
|
||||
const gridClassName =
|
||||
drawMode === 'grid' ? 'option active grid' : 'option grid';
|
||||
const gridClassName = drawMode === 'grid' ? 'option active' : 'option';
|
||||
return (
|
||||
<>
|
||||
<div className="tool-options">
|
||||
@ -147,22 +105,11 @@ const ModeConfig: FC = () => {
|
||||
>
|
||||
{TrashIcon}
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid-options">
|
||||
<div
|
||||
className={gridClassName}
|
||||
onClick={() => setDrawMode('grid')}
|
||||
>
|
||||
{GridIcon}
|
||||
<NumberStateInput
|
||||
className="grid-size width"
|
||||
state={drawGridWidthState}
|
||||
/>
|
||||
<span className="x">x</span>
|
||||
<NumberStateInput
|
||||
className="grid-size height"
|
||||
state={drawGridHeightState}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
@ -181,7 +181,14 @@ const Grid: FC = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const point = snapToGrid(mousePoint, GAP);
|
||||
let point;
|
||||
if (userDrawMode === 'grid') {
|
||||
// snap to the thick grid
|
||||
point = snapToGrid(mousePoint, GAP * 6);
|
||||
} else {
|
||||
// snap to the thin grid for line / trash
|
||||
point = snapToGrid(mousePoint, GAP);
|
||||
}
|
||||
|
||||
if (lodash.isEqual(userStartPoint, point)) {
|
||||
setUserStartPoint(null);
|
||||
@ -249,6 +256,12 @@ const Grid: FC = () => {
|
||||
|
||||
// ctrl+z/ctrl+y for undo/redo
|
||||
const onUndo = useCallback(() => {
|
||||
if (!lodash.isNull(userStartPoint)) {
|
||||
// if the user has a start point, just cancel the pending line
|
||||
setUserStartPoint(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const action = userActions[userActions.length - 1];
|
||||
if (!action) return;
|
||||
|
||||
@ -264,7 +277,7 @@ const Grid: FC = () => {
|
||||
}
|
||||
setUserActions(userActions.slice(0, -1));
|
||||
setUserRedoActions([...userRedoActions, action]);
|
||||
}, [userLines, userActions, userRedoActions]);
|
||||
}, [userLines, userActions, userRedoActions, userStartPoint]);
|
||||
|
||||
const onRedo = useCallback(() => {
|
||||
const action = userRedoActions[userRedoActions.length - 1];
|
||||
@ -341,6 +354,7 @@ const Grid: FC = () => {
|
||||
strokeWidth="2"
|
||||
/>
|
||||
);
|
||||
// TODO: grid mode
|
||||
} else {
|
||||
console.assert(userDrawMode === 'trash');
|
||||
return (
|
||||
|
Loading…
Reference in New Issue
Block a user