diff --git a/package-lock.json b/package-lock.json index 6165d1f..6b14c46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,10 +10,12 @@ "dependencies": { "@flatten-js/core": "^1.6.1", "clsx": "^2.1.1", + "es-toolkit": "^1.16.0", "file-saver": "^2.0.5", "react": "^18.3.1", "react-dom": "^18.3.1", "teenyicons": "^0.4.1", + "undo-stacker": "^0.2.1", "vite-plugin-svgr": "^4.2.0" }, "devDependencies": { @@ -2384,6 +2386,15 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-toolkit": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.16.0.tgz", + "integrity": "sha512-eNJh3zF1KmAHRYd1D8rFi1cMFMCjrC6tumBfwuuZdSur97mED/ifyeBoGzxS11L4owCMx3XSmWTo6oxJQkdGng==", + "workspaces": [ + "docs", + "benchmarks" + ] + }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", @@ -4335,6 +4346,11 @@ "node": ">=14.17" } }, + "node_modules/undo-stacker": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/undo-stacker/-/undo-stacker-0.2.1.tgz", + "integrity": "sha512-wEFIuUlJtSB0Rt/LBxPqiZqKN2AMKqjdYIr2VTIPUPOEZxAOVE4zVY+z2b2yPBL1NvLW+Sm/kbCaqeWlINPZNA==" + }, "node_modules/update-browserslist-db": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", diff --git a/package.json b/package.json index d8a2dbb..87b5577 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,12 @@ "dependencies": { "@flatten-js/core": "^1.6.1", "clsx": "^2.1.1", + "es-toolkit": "^1.16.0", "file-saver": "^2.0.5", "react": "^18.3.1", "react-dom": "^18.3.1", "teenyicons": "^0.4.1", + "undo-stacker": "^0.2.1", "vite-plugin-svgr": "^4.2.0" }, "devDependencies": { diff --git a/src/App.consts.ts b/src/App.consts.ts index 78b3beb..6c81813 100644 --- a/src/App.consts.ts +++ b/src/App.consts.ts @@ -60,7 +60,7 @@ export const SNAP_POINT_SIZE = 15; * How long you need to hover over a snap point to make it a marked snap point that will show angle guides * in milliseconds */ -export const HOVERED_SNAP_POINT_TIME = 2000; +export const HOVERED_SNAP_POINT_TIME = 1000; /** * Maximum number of snap points that can be marked at the same time diff --git a/src/App.tsx b/src/App.tsx index f5df321..e55ad8d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,146 +2,6 @@ import './App.scss'; import { Toolbar } from './components/Toolbar.tsx'; function App() { - // const [activeTool, setActiveTool] = useState(Tool.Line); - // const [entities, setEntities] = useState([]); - // const [getActiveEntity(), setActiveEntity] = useState(null); - // const [shouldDrawCursor, setShouldDrawCursor] = useState(true); - // const [debugEntities] = useState([]); - // const [angleStep, setAngleStep] = useState(45); - // const [screenOffset, setScreenOffset] = useState(new Point(0, 0)); - // const [screenScale, setScreenScale] = useState(1); - // const [panStartLocation, setPanStartLocation] = useState(null); - - // computed - // const worldMouseLocation = screenToWorld( - // screenMouseLocation, - // screenOffset, - // screenScale, - // ); - - // /** - // * Entity snap point or intersection - // */ - // const [snapPoint, setSnapPoint] = useState(null); - // - // /** - // * Snap point on angle guide - // */ - // const [snapPointOnAngleGuide, setSnapPointOnAngleGuide] = - // useState(null); - // - // /** - // * Snap points that are hovered for a certain amount of time - // */ - // const [hoveredSnapPoints, setHoveredSnapPoints] = useState([]); - - /** - * Keep track of the hovered snap points - */ - // useEffect(() => { - // const watchSnapPointTimerId = setInterval(() => { - // trackHoveredSnapPoint( - // snapPoint, - // hoveredSnapPoints, - // setHoveredSnapPoints, - // SNAP_POINT_DISTANCE / screenScale, - // ); - // }, 100); - // return () => { - // clearInterval(watchSnapPointTimerId); - // }; - // }, [hoveredSnapPoints, snapPoint]); - - // /** - // * Redraw the canvas when the mouse moves or the window resizes - // */ - // useEffect(() => { - // const activeTool = getActiveTool(); - // const angleStep = getAngleStep(); - // const activeEntity = getActiveEntity(); - // const entities = getEntities(); - // const hoveredSnapPoints = getHoveredSnapPoints(); - // const worldMouseLocation = getWorldMouseLocation(); - // const screenScale = getScreenScale(); - // const screenOffset = getScreenOffset(); - // const shouldDrawCursor = getShouldDrawCursor(); - // const debugEntities = getDebugEntities(); - // - // const context: CanvasRenderingContext2D | null | undefined = - // canvas?.getContext('2d'); - // if (!context) return; - // - // const drawInfo: DrawInfo = { - // context, - // canvasSize, - // worldMouseLocation: worldMouseLocation, - // screenMouseLocation: screenMouseLocation, - // screenOffset, - // screenZoom: screenScale, - // }; - // let helperEntitiesTemp: Entity[] = []; - // let snapPointTemp: SnapPoint | null = null; - // let snapPointOnAngleGuideTemp: SnapPoint | null = null; - // if ([Tool.Line, Tool.Rectangle, Tool.Circle].includes(activeTool)) { - // // If you're in the progress of drawing a shape, show the angle guides and closest snap point - // let firstPoint: Point | null = null; - // if ( - // activeEntity && - // !activeEntity.getShape() && - // activeEntity.getFirstPoint() - // ) { - // firstPoint = activeEntity.getFirstPoint(); - // } - // const { angleGuides, entitySnapPoint, angleSnapPoint } = getDrawHelpers( - // entities, - // compact([ - // firstPoint, - // ...hoveredSnapPoints.map( - // hoveredSnapPoint => hoveredSnapPoint.snapPoint.point, - // ), - // ]), - // worldMouseLocation, - // angleStep, - // SNAP_POINT_DISTANCE / screenScale, - // ); - // helperEntitiesTemp = angleGuides; - // snapPointTemp = entitySnapPoint; - // snapPointOnAngleGuideTemp = angleSnapPoint; - // // setHelperEntities(angleGuides); - // // setSnapPoint(entitySnapPoint); - // // setSnapPointOnAngleGuide(angleSnapPoint); - // } - // draw( - // drawInfo, - // entities, - // debugEntities, - // helperEntitiesTemp, - // getActiveEntity(), - // snapPointTemp, - // snapPointOnAngleGuideTemp, - // hoveredSnapPoints, - // worldMouseLocation, - // shouldDrawCursor, - // ); - // }, [canvasRef, canvasSize, screenMouseLocation]); - - /** - * Show the angle guides and closest snap point when drawing a shape - */ - // useEffect(() => { - // - // }, [ - // // getActiveEntity(), - // activeTool, - // angleStep, - // // entities, - // // hoveredSnapPoints, - // // screenMouseLocation, - // // screenOffset, - // // screenScale, - // worldMouseLocation, - // ]); - return (
diff --git a/src/components/Toolbar.tsx b/src/components/Toolbar.tsx index dafac6d..63d5574 100644 --- a/src/components/Toolbar.tsx +++ b/src/components/Toolbar.tsx @@ -1,34 +1,33 @@ -import { FC, useCallback } from 'react'; +import { FC, useCallback, useState } from 'react'; import { IconName } from './icon.tsx'; import { Tool } from '../tools.ts'; import { DropdownButton } from './DropdownButton.tsx'; import { Button } from './Button.tsx'; import { - getActiveTool, - getAngleStep, getCanvasSize, getEntities, + redo, setActiveEntity, setActiveTool, setAngleStep, - setEntities, + setSelectedEntityIds, + undo, } from '../state.ts'; -import { deSelectEntities } from '../helpers/select-entities.ts'; import { convertEntitiesToSvgString } from '../helpers/export-entities-to-svg.ts'; import { saveAs } from 'file-saver'; interface ToolbarProps {} export const Toolbar: FC = () => { - const activeTool = getActiveTool(); - const angleStep = getAngleStep(); + const [activeToolLocal, setActiveToolLocal] = useState(Tool.Line); + const [angleStepLocal, setAngleStepLocal] = useState(45); const handleToolClick = useCallback((tool: Tool) => { console.log('set active tool: ', tool); - const entities = getEntities(); + setActiveToolLocal(tool); setActiveTool(tool); setActiveEntity(null); - setEntities(deSelectEntities(entities)); + setSelectedEntityIds([]); }, []); const handleExportClick = useCallback(() => { @@ -41,74 +40,86 @@ export const Toolbar: FC = () => { saveAs(blob, 'open-web-cad--drawing.svg'); }, []); + const handleAngleChanged = useCallback((angle: number) => { + setAngleStepLocal(angle); + setAngleStep(angle); + }, []); + return (