color selection

This commit is contained in:
Michael Peters 2024-01-27 14:30:06 -08:00
parent 0961ba41fd
commit 851e78bff3
7 changed files with 121 additions and 76 deletions

40
package-lock.json generated
View File

@ -12,7 +12,8 @@
"@uidotdev/usehooks": "^2.4.1", "@uidotdev/usehooks": "^2.4.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0",
"recoil": "^0.7.7"
}, },
"devDependencies": { "devDependencies": {
"@types/lodash": "^4.14.202", "@types/lodash": "^4.14.202",
@ -1776,6 +1777,11 @@
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true "dev": true
}, },
"node_modules/hamt_plus": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz",
"integrity": "sha512-t2JXKaehnMb9paaYA7J0BX8QQAY8lwfQ9Gjf4pg/mk4krt+cmwmU652HOoWonf+7+EQV97ARPMhhVgU1ra2GhA=="
},
"node_modules/handle-thing": { "node_modules/handle-thing": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
@ -3118,6 +3124,25 @@
"node": ">= 10.13.0" "node": ">= 10.13.0"
} }
}, },
"node_modules/recoil": {
"version": "0.7.7",
"resolved": "https://registry.npmjs.org/recoil/-/recoil-0.7.7.tgz",
"integrity": "sha512-8Og5KPQW9LwC577Vc7Ug2P0vQshkv1y3zG3tSSkWMqkWSwHmE+by06L8JtnGocjW6gcCvfwB3YtrJG6/tWivNQ==",
"dependencies": {
"hamt_plus": "1.0.2"
},
"peerDependencies": {
"react": ">=16.13.1"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/relateurl": { "node_modules/relateurl": {
"version": "0.2.7", "version": "0.2.7",
"resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
@ -5749,6 +5774,11 @@
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true "dev": true
}, },
"hamt_plus": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz",
"integrity": "sha512-t2JXKaehnMb9paaYA7J0BX8QQAY8lwfQ9Gjf4pg/mk4krt+cmwmU652HOoWonf+7+EQV97ARPMhhVgU1ra2GhA=="
},
"handle-thing": { "handle-thing": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
@ -6729,6 +6759,14 @@
"resolve": "^1.20.0" "resolve": "^1.20.0"
} }
}, },
"recoil": {
"version": "0.7.7",
"resolved": "https://registry.npmjs.org/recoil/-/recoil-0.7.7.tgz",
"integrity": "sha512-8Og5KPQW9LwC577Vc7Ug2P0vQshkv1y3zG3tSSkWMqkWSwHmE+by06L8JtnGocjW6gcCvfwB3YtrJG6/tWivNQ==",
"requires": {
"hamt_plus": "1.0.2"
}
},
"relateurl": { "relateurl": {
"version": "0.2.7", "version": "0.2.7",
"resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",

View File

@ -31,6 +31,7 @@
"@uidotdev/usehooks": "^2.4.1", "@uidotdev/usehooks": "^2.4.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0",
"recoil": "^0.7.7"
} }
} }

8
src/atoms.ts Normal file
View File

@ -0,0 +1,8 @@
import { atom } from 'recoil';
export const DEFAULT_COLOR = '#339ad6';
export const currentColorState = atom({
key: 'colorState',
default: DEFAULT_COLOR,
});

View File

@ -1,14 +1,14 @@
import { FC, useState } from 'react'; import { FC } from 'react';
import { RecoilRoot } from 'recoil';
import Grid from '../grid/grid'; import Grid from '../grid/grid';
import GridConfig from '../grid/grid-config'; import GridConfig from '../grid/grid-config';
const App: FC = () => { const App: FC = () => {
const [color, setColor] = useState('#ffffff');
return ( return (
<> <RecoilRoot>
<Grid /> <Grid />
<GridConfig color={color} setColor={setColor} /> <GridConfig />
</> </RecoilRoot>
); );
}; };

View File

@ -2,5 +2,38 @@
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
display: flex;
> * {
margin: 20px;
}
.color-config {
background-color: #000;
border-radius: 5px;
padding: 5px;
.color-options {
display: grid;
grid-template-columns: auto auto;
.color-option {
margin: 5px;
padding: 7px;
background-color: #283f56;
border: 2px solid #283f56;
border-radius: 5px;
&.active {
background-color: #265584;
border-color: #458bd1;
}
.sample {
width: 24px;
height: 13px;
border-radius: 3px;
}
}
}
}
} }

View File

@ -1,16 +1,16 @@
import { FC } from 'react'; import { FC } from 'react';
import { useRecoilState } from 'recoil';
import { currentColorState, DEFAULT_COLOR } from '../../atoms';
import './grid-config.scss'; import './grid-config.scss';
interface ColorOptionProps { interface ColorOptionProps {
color: string; color: string;
currentColor: string;
setCurrentColor: (newColor: string) => void;
} }
const ColorOption: FC<ColorOptionProps> = (props: ColorOptionProps) => { const ColorOption: FC<ColorOptionProps> = (props: ColorOptionProps) => {
const { color, currentColor, setCurrentColor } = props; const { color } = props;
const [currentColor, setCurrentColor] = useRecoilState(currentColorState);
return ( return (
<div <div
@ -19,77 +19,32 @@ const ColorOption: FC<ColorOptionProps> = (props: ColorOptionProps) => {
} }
onClick={() => setCurrentColor(color)} onClick={() => setCurrentColor(color)}
> >
{color} <div className="sample" style={{ backgroundColor: color }} />
</div> </div>
); );
}; };
interface ColorConfigProps { const ColorConfig: FC = () => {
color: string;
setColor: (newColor: string) => void;
}
const ColorConfig: FC<ColorConfigProps> = (props: ColorConfigProps) => {
const { color, setColor } = props;
return ( return (
<div className="color-config"> <div className="color-config">
<div>Color: {color}</div>
<div className="color-options"> <div className="color-options">
<ColorOption <ColorOption color={DEFAULT_COLOR} />
color="#ffffff" <ColorOption color="#d33b3d" />
currentColor={color} <ColorOption color="#3dd33b" />
setCurrentColor={setColor} <ColorOption color="#f1c40f" />
/> <ColorOption color="#d35400" />
<ColorOption <ColorOption color="#8e44ad" />
color="#ff0000" <ColorOption color="#eeeeee" />
currentColor={color} <ColorOption color="#95a5a6" />
setCurrentColor={setColor}
/>
<ColorOption
color="#00ff00"
currentColor={color}
setCurrentColor={setColor}
/>
<ColorOption
color="#3cccff"
currentColor={color}
setCurrentColor={setColor}
/>
<ColorOption
color="#eeee00"
currentColor={color}
setCurrentColor={setColor}
/>
<ColorOption
color="#ff8800"
currentColor={color}
setCurrentColor={setColor}
/>
<ColorOption
color="#ee66ee"
currentColor={color}
setCurrentColor={setColor}
/>
<ColorOption
color="#2e8c41"
currentColor={color}
setCurrentColor={setColor}
/>
</div> </div>
</div> </div>
); );
}; };
interface GridConfigProps { const GridConfig: FC = () => {
color: string;
setColor: (newColor: string) => void;
}
const GridConfig: FC<GridConfigProps> = (props: GridConfigProps) => {
const { color, setColor } = props;
return ( return (
<div className="grid-config"> <div className="grid-config">
<ColorConfig color={color} setColor={setColor} /> <ColorConfig />
</div> </div>
); );
}; };

View File

@ -12,6 +12,8 @@ import {
import './grid.scss'; import './grid.scss';
import * as lodash from 'lodash'; import * as lodash from 'lodash';
import { useRecoilValue } from 'recoil';
import { currentColorState } from '../../atoms';
interface Point { interface Point {
x: number; x: number;
@ -122,9 +124,10 @@ const Grid: FC = () => {
return lines_thin.concat(lines_thick); return lines_thin.concat(lines_thick);
}, [range, GAP]); }, [range, GAP]);
const [userLines, setUserLines] = useState<Range[]>([]); const [userLines, setUserLines] = useState<Line[]>([]);
const [userRedoLines, setUserRedoLines] = useState<Range[]>([]); const [userRedoLines, setUserRedoLines] = useState<Line[]>([]);
const [userStartPoint, setUserStartPoint] = useState<Point | null>(null); const [userStartPoint, setUserStartPoint] = useState<Point | null>(null);
const userLineColor = useRecoilValue(currentColorState);
// mouse clicks create lines // mouse clicks create lines
const onGridClick = useCallback( const onGridClick = useCallback(
@ -146,7 +149,7 @@ const Grid: FC = () => {
} }
const line = pointsToRange(userStartPoint, point); const line = pointsToRange(userStartPoint, point);
setUserLines([...userLines, line]); setUserLines([...userLines, { ...line, stroke: userLineColor }]);
if (event.shiftKey == false) { if (event.shiftKey == false) {
setUserStartPoint(null); setUserStartPoint(null);
@ -154,7 +157,14 @@ const Grid: FC = () => {
setUserStartPoint(point); setUserStartPoint(point);
} }
}, },
[userStartPoint, setUserStartPoint, setUserLines, GAP, mousePoint] [
userLineColor,
userStartPoint,
setUserStartPoint,
setUserLines,
GAP,
mousePoint,
]
); );
const onGridContextMenu = useCallback( const onGridContextMenu = useCallback(
@ -210,7 +220,7 @@ const Grid: FC = () => {
y1={userStartPoint.y} y1={userStartPoint.y}
x2={point.x} x2={point.x}
y2={point.y} y2={point.y}
stroke="#ff0000" stroke={userLineColor}
strokeWidth="2" strokeWidth="2"
/> />
); );
@ -223,7 +233,7 @@ const Grid: FC = () => {
cx={point.x} cx={point.x}
cy={point.y} cy={point.y}
r="3" r="3"
fill="#ff0000" fill={userLineColor}
/> />
); );
}, [userStartPoint, mousePoint]); }, [userStartPoint, mousePoint]);
@ -237,7 +247,7 @@ const Grid: FC = () => {
y1={line.y0} y1={line.y0}
x2={line.x1} x2={line.x1}
y2={line.y1} y2={line.y1}
stroke="#ff0000" stroke={line.stroke}
strokeWidth="2" strokeWidth="2"
/> />
)); ));