diff --git a/src/components/KonvaDrawingBoard.jsx b/src/components/KonvaDrawingBoard.jsx
index 675a4c9..d1bc89a 100644
--- a/src/components/KonvaDrawingBoard.jsx
+++ b/src/components/KonvaDrawingBoard.jsx
@@ -9,12 +9,19 @@ import {
MousePointerClick,
Save,
} from "lucide-react";
+import PenOptions from "./PenOptions";
-const DEFAULT_STROKE_COLOR = 'white';
+const DEFAULT_STROKE_COLOR = "white";
const DEFAULT_STROKE_WIDTH = 5;
const ERASER_STROKE_WIDTH = 20;
-function KonvaDrawingBoard({ initialStrokes, onSaveStroke, onSaveAllBoardContent, boardId, onClearAllStrokes }) {
+function KonvaDrawingBoard({
+ initialStrokes,
+ onSaveStroke,
+ onSaveAllBoardContent,
+ boardId,
+ onClearAllStrokes,
+}) {
const stageRef = useRef(null);
const containerRef = useRef(null);
const [tool, setTool] = useState("pen");
@@ -23,7 +30,9 @@ function KonvaDrawingBoard({ initialStrokes, onSaveStroke, onSaveAllBoardContent
const [stagePos, setStagePos] = useState({ x: 0, y: 0 });
const [stageScale, setStageScale] = useState(1);
const [containerSize, setContainerSize] = useState({ width: 0, height: 0 });
-
+ const [toolOptions, setToolOptions] = useState(false);
+ const [penColor, setPenColor] = useState("white");
+ const [penSize, setPenSize] = useState(5);
// --- Resizing the Stage when container size changes ---
const checkSize = useCallback(() => {
if (containerRef.current) {
@@ -36,17 +45,17 @@ function KonvaDrawingBoard({ initialStrokes, onSaveStroke, onSaveAllBoardContent
useEffect(() => {
checkSize();
- window.addEventListener('resize', checkSize);
- return () => window.removeEventListener('resize', checkSize);
+ window.addEventListener("resize", checkSize);
+ return () => window.removeEventListener("resize", checkSize);
}, [checkSize]);
// --- Load initial strokes ---
useEffect(() => {
const loadedLines = (initialStrokes || [])
- .filter(s => s.points && s.points.length > 0)
- .map(s => ({
+ .filter((s) => s.points && s.points.length > 0)
+ .map((s) => ({
id: s.id,
- points: typeof s.points === 'string' ? JSON.parse(s.points) : s.points,
+ points: typeof s.points === "string" ? JSON.parse(s.points) : s.points,
tool: s.tool || "pen",
color: s.color || DEFAULT_STROKE_COLOR,
strokeWidth: s.strokeWidth || DEFAULT_STROKE_WIDTH,
@@ -55,46 +64,55 @@ function KonvaDrawingBoard({ initialStrokes, onSaveStroke, onSaveAllBoardContent
}, [initialStrokes]);
// --- Drawing Event Handlers ---
- const handleMouseDown = useCallback((e) => {
- if (tool === "pan" || tool === "pointer") return;
- setIsDrawing(true);
- const stage = e.target.getStage();
- const pos = stage.getPointerPosition();
-
- //convert screen coordinates into stage coordinates
- const transform = stage.getAbsoluteTransform().copy();
- transform.invert();
- const relativePos = transform.point(pos);
- setLines((prevLines) => [
- ...prevLines,
- {
- tool,
- color: tool === "eraser" ? "black" : DEFAULT_STROKE_COLOR,
- strokeWidth: tool === "eraser" ? ERASER_STROKE_WIDTH : DEFAULT_STROKE_WIDTH,
- points: [relativePos.x, relativePos.y],
- id: Date.now() + Math.random(),
- },
- ]);
- }, [tool]);
-
- const handleMouseMove = useCallback((e) => {
- if (!isDrawing || tool === "pan" || tool === "pointer") return;
- const stage = stageRef.current;
- const point = stage.getPointerPosition();
-
- //convert screen coordinates into stage coordinates
- const transform = stage.getAbsoluteTransform().copy();
- transform.invert();
- const relativePos = transform.point(point);
-
- setLines((prevLines) => {
- const lastLine = { ...prevLines[prevLines.length - 1] };
- lastLine.points = lastLine.points.concat([relativePos.x, relativePos.y]);
- const newLines = [...prevLines];
- newLines[newLines.length - 1] = lastLine;
- return newLines;
- });
- }, [isDrawing, tool]);
+ const handleMouseDown = useCallback(
+ (e) => {
+ if (tool === "pan" || tool === "pointer") return;
+ setIsDrawing(true);
+ const stage = e.target.getStage();
+ const pos = stage.getPointerPosition();
+
+ //convert screen coordinates into stage coordinates
+ const transform = stage.getAbsoluteTransform().copy();
+ transform.invert();
+ const relativePos = transform.point(pos);
+ setLines((prevLines) => [
+ ...prevLines,
+ {
+ tool,
+ color: tool === "eraser" ? "black" : penColor,
+ strokeWidth: tool === "eraser" ? ERASER_STROKE_WIDTH : penSize,
+ points: [relativePos.x, relativePos.y],
+ id: Date.now() + Math.random(),
+ },
+ ]);
+ },
+ [tool]
+ );
+
+ const handleMouseMove = useCallback(
+ (e) => {
+ if (!isDrawing || tool === "pan" || tool === "pointer") return;
+ const stage = stageRef.current;
+ const point = stage.getPointerPosition();
+
+ //convert screen coordinates into stage coordinates
+ const transform = stage.getAbsoluteTransform().copy();
+ transform.invert();
+ const relativePos = transform.point(point);
+
+ setLines((prevLines) => {
+ const lastLine = { ...prevLines[prevLines.length - 1] };
+ lastLine.points = lastLine.points.concat([
+ relativePos.x,
+ relativePos.y,
+ ]);
+ const newLines = [...prevLines];
+ newLines[newLines.length - 1] = lastLine;
+ return newLines;
+ });
+ },
+ [isDrawing, tool]
+ );
const handleMouseUp = useCallback(async () => {
setIsDrawing(false);
@@ -114,17 +132,21 @@ function KonvaDrawingBoard({ initialStrokes, onSaveStroke, onSaveAllBoardContent
// --- Explicit Save Handler ---
const handleExplicitSave = useCallback(() => {
- if (onSaveAllBoardContent) {
- onSaveAllBoardContent(boardId, lines);
- alert("All changes saved!");
- } else {
- alert("Save feature not fully connected. Check console.");
- }
+ if (onSaveAllBoardContent) {
+ onSaveAllBoardContent(boardId, lines);
+ alert("All changes saved!");
+ } else {
+ alert("Save feature not fully connected. Check console.");
+ }
}, [onSaveAllBoardContent, boardId, lines]);
// --- Clear Canvas Function ---
const clearCanvas = useCallback(async () => {
- if (window.confirm("Are you sure you want to clear the entire canvas? This action cannot be undone.")) {
+ if (
+ window.confirm(
+ "Are you sure you want to clear the entire canvas? This action cannot be undone."
+ )
+ ) {
setLines([]); // Clear locally first for immediate feedback
await onClearAllStrokes(boardId);
alert("Canvas cleared permanently!");
@@ -132,7 +154,8 @@ function KonvaDrawingBoard({ initialStrokes, onSaveStroke, onSaveAllBoardContent
}, [boardId, onClearAllStrokes]);
// --- View Control Handlers (MOVED HERE) ---
- const handleWheel = useCallback((e) => { // <--- MOVED AND WRAPPED IN useCallback
+ const handleWheel = useCallback((e) => {
+ // <--- MOVED AND WRAPPED IN useCallback
e.evt.preventDefault();
const stage = stageRef.current;
if (!stage) return;
@@ -157,31 +180,84 @@ function KonvaDrawingBoard({ initialStrokes, onSaveStroke, onSaveAllBoardContent
});
}, []); // No external dependencies, stageRef is ref
- const handleDragEnd = useCallback((e) => { // <--- MOVED AND WRAPPED IN useCallback
+ const handleDragEnd = useCallback((e) => {
+ // <--- MOVED AND WRAPPED IN useCallback
setStagePos({
x: e.target.x(),
y: e.target.y(),
});
}, []);
- const resetView = useCallback(() => { // <--- MOVED AND WRAPPED IN useCallback
+ const resetView = useCallback(() => {
+ // <--- MOVED AND WRAPPED IN useCallback
setStagePos({ x: 0, y: 0 });
setStageScale(1);
}, []);
+ const handleToolClick = (toolName) => {
+ if (tool !== toolName) {
+ setTool(toolName);
+ setToolOptions(false);
+ } else if (tool === toolName) {
+ setToolOptions(!toolOptions);
+ }
+ };
return (
{/* Toolbar */}
-
-
-
-
+
+
+
+
-
+
-
+
+ {toolOptions && tool == "pen" && (
+
+ )}
+
{/* Canvas Area */}
{lines.map((line) => (
@@ -238,4 +333,4 @@ function KonvaDrawingBoard({ initialStrokes, onSaveStroke, onSaveAllBoardContent
);
}
-export default KonvaDrawingBoard;
\ No newline at end of file
+export default KonvaDrawingBoard;
diff --git a/src/components/PenOptions.jsx b/src/components/PenOptions.jsx
new file mode 100644
index 0000000..39fd6ba
--- /dev/null
+++ b/src/components/PenOptions.jsx
@@ -0,0 +1,93 @@
+ // src/components/KonvaDrawingBoard.jsx
+ import React, { useState, useRef, useEffect, useCallback } from "react";
+ import { Stage, Layer, Line, Rect } from "react-konva";
+ import {
+ Pencil,
+ Eraser,
+ Move,
+ RotateCcw,
+ MousePointerClick,
+ Save,
+ } from "lucide-react";
+
+ function PenOptions({currentColor, currentSize, onColorChange, onSizeChange}) {
+ const colors = [
+ { name: "White", value: "#ffffff" },
+ { name: "Black", value: "#000000" },
+ { name: "Red", value: "#ef4444" },
+ { name: "Blue", value: "#3b82f6" },
+ { name: "Green", value: "#22c55e" },
+ { name: "Yellow", value: "#eab308" },
+ { name: "Purple", value: "#a855f7" },
+ { name: "Orange", value: "#f97316" },
+ { name: "Pink", value: "#ec4899" },
+ { name: "Cyan", value: "#06b6d4" },
+ ];
+
+ const brushSizes = [
+ { name: "Extra Small", value: 2 },
+ { name: "Small", value: 5 },
+ { name: "Medium", value: 10 },
+ { name: "Large", value: 15 },
+ { name: "Extra Large", value: 20 },
+ { name: "Huge", value: 30 },
+ ];
+
+ return (
+
+
Pen Options
+
+ {/* Color Selection */}
+
+
Color:
+
+ {colors.map(color => (
+
+
+
+ {/* Brush Size Selection */}
+
+
Brush Size:
+
+ {brushSizes.map(size => (
+
+ ))}
+
+
+
+ );
+ }
+
+ export default PenOptions;