react-board-drawing-hook 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +246 -0
- package/dist/index.d.mts +254 -0
- package/dist/index.d.ts +254 -0
- package/dist/index.js +1524 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1505 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/useBoardDrawing.ts","../src/types/board.ts","../src/types/websocket.ts","../src/adapters/native-websocket-adapter.ts","../src/adapters/socket-io-adapter.ts","../src/index.ts"],"names":["userId","userName"],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\r\nimport {\r\n\ttype BoardObject,\r\n\ttype DrawingTool,\r\n\ttype InteractionMode,\r\n\ttype Point,\r\n\ttype ResizeHandle,\r\n\tCANVAS_HEIGHT,\r\n\tCANVAS_WIDTH,\r\n\tcanEditObject,\r\n\tclampObjectToCanvas,\r\n\tgenerateObjectId,\r\n\tisPointInObject,\r\n\tresizeImageWithAspectRatio,\r\n\tresizeLineObject,\r\n\tresizeObjectFree,\r\n} from '../types/board';\r\nimport { BoardEventHandlers, BoardWebSocketService } from '../types/websocket';\r\n\r\nexport interface UseBoardDrawingProps {\r\n\tboardId: string | number;\r\n\tuserId: number;\r\n\tuserName: string;\r\n\tcanvasRef: React.RefObject<HTMLCanvasElement | null>;\r\n\twebSocketService: BoardWebSocketService;\r\n\tonObjectsUpdated?: (objects: BoardObject[]) => void;\r\n\tonObjectLocked?: (objectId: string, userId: number, userName: string) => void;\r\n\tonObjectUnlocked?: (objectId: string) => void;\r\n\tonUserJoined?: (userId: number, userName: string) => void;\r\n\tonUserLeft?: (userId: number, userName: string) => void;\r\n\tconfig?: {\r\n\t\tenableKeyboardShortcuts?: boolean;\r\n\t\tenableGlobalListeners?: boolean;\r\n\t\tmaxImageSize?: number;\r\n\t\tdefaultColors?: {\r\n\t\t\tstroke?: string;\r\n\t\t\tfill?: string;\r\n\t\t\tlineWidth?: number;\r\n\t\t\tfontSize?: number;\r\n\t\t};\r\n\t};\r\n}\r\n\r\nexport const useBoardDrawing = ({\r\n\tboardId,\r\n\tuserId,\r\n\tuserName,\r\n\tcanvasRef,\r\n\twebSocketService,\r\n\tonObjectLocked,\r\n\tonObjectUnlocked,\r\n\tonUserJoined,\r\n\tonUserLeft,\r\n\tconfig = {},\r\n}: UseBoardDrawingProps) => {\r\n\tconst {\r\n\t\tenableKeyboardShortcuts = true,\r\n\t\tenableGlobalListeners = true,\r\n\t\tmaxImageSize = 400,\r\n\t\tdefaultColors = {},\r\n\t} = config;\r\n\r\n\tconst {\r\n\t\tstroke: defaultStroke = '#000000',\r\n\t\tfill: defaultFill = '#4F46E5',\r\n\t\tlineWidth: defaultLineWidth = 3,\r\n\t\tfontSize: defaultFontSize = 24,\r\n\t} = defaultColors;\r\n\r\n\t// State\r\n\tconst [tool, setTool] = useState<DrawingTool>('select');\r\n\tconst [color, setColor] = useState(defaultStroke);\r\n\tconst [fillColor, setFillColor] = useState(defaultFill);\r\n\tconst [lineWidth, setLineWidth] = useState(defaultLineWidth);\r\n\tconst [fontSize, setFontSize] = useState(defaultFontSize);\r\n\tconst [isDrawing, setIsDrawing] = useState(false);\r\n\tconst [selectedObjectId, setSelectedObjectId] = useState<string | null>(null);\r\n\tconst [interactionMode, setInteractionMode] =\r\n\t\tuseState<InteractionMode>('none');\r\n\tconst [activeResizeHandle, setActiveResizeHandle] =\r\n\t\tuseState<ResizeHandle | null>(null);\r\n\tconst [objects, setObjects] = useState<BoardObject[]>([]);\r\n\tconst [usersOnline, setUsersOnline] = useState<\r\n\t\tArray<{ id: number; name: string }>\r\n\t>([]);\r\n\tconst [isConnected, setIsConnected] = useState(false);\r\n\tconst [editingTextId, setEditingTextId] = useState<string | null>(null);\r\n\r\n\t// Refs\r\n\tconst drawingStartRef = useRef<Point | null>(null);\r\n\tconst currentPointsRef = useRef<Point[]>([]);\r\n\tconst tempObjectRef = useRef<BoardObject | null>(null);\r\n\tconst originalObjectStateRef = useRef<{\r\n\t\tobj: BoardObject;\r\n\t\tcenterX: number;\r\n\t\tcenterY: number;\r\n\t} | null>(null);\r\n\tconst rotationStartRef = useRef<number>(0);\r\n\tconst imageCacheRef = useRef<Map<string, HTMLImageElement>>(new Map());\r\n\r\n\t// Helper: Get canvas coordinates\r\n\tconst getCanvasCoordinates = useCallback(\r\n\t\t(clientX: number, clientY: number): Point => {\r\n\t\t\tif (!canvasRef.current) return { x: 0, y: 0 };\r\n\r\n\t\t\tconst canvas = canvasRef.current;\r\n\t\t\tconst rect = canvas.getBoundingClientRect();\r\n\t\t\tconst scaleX = canvas.width / rect.width;\r\n\t\t\tconst scaleY = canvas.height / rect.height;\r\n\r\n\t\t\treturn {\r\n\t\t\t\tx: (clientX - rect.left) * scaleX,\r\n\t\t\t\ty: (clientY - rect.top) * scaleY,\r\n\t\t\t};\r\n\t\t},\r\n\t\t[canvasRef],\r\n\t);\r\n\r\n\t// Helper: Get object center\r\n\tconst getObjectCenter = useCallback((obj: BoardObject): Point => {\r\n\t\treturn {\r\n\t\t\tx: obj.x + obj.width / 2,\r\n\t\t\ty: obj.y + obj.height / 2,\r\n\t\t};\r\n\t}, []);\r\n\r\n\t// Helper: Find object at point\r\n\tconst findObjectAtPoint = useCallback(\r\n\t\t(x: number, y: number): BoardObject | null => {\r\n\t\t\tfor (let i = objects.length - 1; i >= 0; i--) {\r\n\t\t\t\tconst obj = objects[i];\r\n\t\t\t\tif (isPointInObject(x, y, obj, userId)) {\r\n\t\t\t\t\treturn obj;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn null;\r\n\t\t},\r\n\t\t[objects, userId],\r\n\t);\r\n\r\n\t// Helper: Find handle at point\r\n\tconst findHandleAtPoint = useCallback(\r\n\t\t(x: number, y: number, obj: BoardObject): ResizeHandle | null => {\r\n\t\t\tif (obj.type === 'pencil') return null;\r\n\r\n\t\t\tconst centerX = obj.x + obj.width / 2;\r\n\t\t\tconst centerY = obj.y + obj.height / 2;\r\n\t\t\tconst rad = (-obj.rotation * Math.PI) / 180;\r\n\t\t\tconst cos = Math.cos(rad);\r\n\t\t\tconst sin = Math.sin(rad);\r\n\r\n\t\t\tconst dx = x - centerX;\r\n\t\t\tconst dy = y - centerY;\r\n\t\t\tconst localX = centerX + (dx * cos - dy * sin);\r\n\t\t\tconst localY = centerY + (dx * sin + dy * cos);\r\n\r\n\t\t\t// Check rotation handle\r\n\t\t\tconst rotationHandle = {\r\n\t\t\t\tx: centerX,\r\n\t\t\t\ty: centerY - obj.height / 2 - 35,\r\n\t\t\t};\r\n\r\n\t\t\tconst dxRot = localX - rotationHandle.x;\r\n\t\t\tconst dyRot = localY - rotationHandle.y;\r\n\t\t\tif (Math.hypot(dxRot, dyRot) <= 12) {\r\n\t\t\t\treturn 'rotate';\r\n\t\t\t}\r\n\r\n\t\t\t// Check resize handles\r\n\t\t\tconst handles: Record<Exclude<ResizeHandle, 'rotate'>, Point> = {\r\n\t\t\t\tnw: { x: obj.x, y: obj.y },\r\n\t\t\t\tn: { x: obj.x + obj.width / 2, y: obj.y },\r\n\t\t\t\tne: { x: obj.x + obj.width, y: obj.y },\r\n\t\t\t\te: { x: obj.x + obj.width, y: obj.y + obj.height / 2 },\r\n\t\t\t\tse: { x: obj.x + obj.width, y: obj.y + obj.height },\r\n\t\t\t\ts: { x: obj.x + obj.width / 2, y: obj.y + obj.height },\r\n\t\t\t\tsw: { x: obj.x, y: obj.y + obj.height },\r\n\t\t\t\tw: { x: obj.x, y: obj.y + obj.height / 2 },\r\n\t\t\t};\r\n\r\n\t\t\tfor (const [handle, point] of Object.entries(handles)) {\r\n\t\t\t\tconst hDx = localX - point.x;\r\n\t\t\t\tconst hDy = localY - point.y;\r\n\t\t\t\tif (Math.hypot(hDx, hDy) <= 8) {\r\n\t\t\t\t\treturn handle as ResizeHandle;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\treturn null;\r\n\t\t},\r\n\t\t[],\r\n\t);\r\n\r\n\t// WebSocket effect\r\n\tuseEffect(() => {\r\n\t\tconst handlers: BoardEventHandlers = {\r\n\t\t\tonConnectionChange: setIsConnected,\r\n\t\t\tonObjectLocked: (objectId, lockedBy, lockedByName) => {\r\n\t\t\t\tsetObjects(prev =>\r\n\t\t\t\t\tprev.map(obj =>\r\n\t\t\t\t\t\tobj.id === objectId\r\n\t\t\t\t\t\t\t? { ...obj, locked_by: lockedBy, locked_by_name: lockedByName }\r\n\t\t\t\t\t\t\t: obj,\r\n\t\t\t\t\t),\r\n\t\t\t\t);\r\n\t\t\t\tonObjectLocked?.(objectId, lockedBy, lockedByName);\r\n\t\t\t},\r\n\t\t\tonObjectUnlocked: objectId => {\r\n\t\t\t\tsetObjects(prev =>\r\n\t\t\t\t\tprev.map(obj =>\r\n\t\t\t\t\t\tobj.id === objectId\r\n\t\t\t\t\t\t\t? { ...obj, locked_by: null, locked_by_name: null }\r\n\t\t\t\t\t\t\t: obj,\r\n\t\t\t\t\t),\r\n\t\t\t\t);\r\n\t\t\t\tonObjectUnlocked?.(objectId);\r\n\t\t\t},\r\n\t\t\tonObjectCreated: object => {\r\n\t\t\t\tsetObjects(prev => {\r\n\t\t\t\t\tif (prev.some(o => o.id === object.id)) return prev;\r\n\t\t\t\t\treturn [...prev, object];\r\n\t\t\t\t});\r\n\t\t\t},\r\n\t\t\tonObjectUpdated: object => {\r\n\t\t\t\tsetObjects(prev =>\r\n\t\t\t\t\tprev.map(obj => (obj.id === object.id ? object : obj)),\r\n\t\t\t\t);\r\n\t\t\t},\r\n\t\t\tonObjectDeleted: objectId => {\r\n\t\t\t\tsetObjects(prev => prev.filter(obj => obj.id !== objectId));\r\n\t\t\t\tif (selectedObjectId === objectId) {\r\n\t\t\t\t\tsetSelectedObjectId(null);\r\n\t\t\t\t\tsetInteractionMode('none');\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tonUserJoined: (joinedUserId, joinedUserName) => {\r\n\t\t\t\tsetUsersOnline(prev => [\r\n\t\t\t\t\t...prev.filter(u => u.id !== joinedUserId),\r\n\t\t\t\t\t{ id: joinedUserId, name: joinedUserName },\r\n\t\t\t\t]);\r\n\t\t\t\tonUserJoined?.(joinedUserId, joinedUserName);\r\n\t\t\t},\r\n\t\t\tonUserLeft: (leftUserId, leftUserName) => {\r\n\t\t\t\tsetUsersOnline(prev => prev.filter(u => u.id !== leftUserId));\r\n\t\t\t\tonUserLeft?.(leftUserId, leftUserName);\r\n\t\t\t},\r\n\t\t\tonError: error => {\r\n\t\t\t\tconsole.error('[BoardDrawing]', error);\r\n\t\t\t},\r\n\t\t};\r\n\r\n\t\twebSocketService.setEventHandlers(handlers);\r\n\t\twebSocketService.connect(boardId, userId, userName);\r\n\r\n\t\treturn () => {\r\n\t\t\twebSocketService.disconnect();\r\n\t\t};\r\n\t}, [\r\n\t\tboardId,\r\n\t\tuserId,\r\n\t\tuserName,\r\n\t\twebSocketService,\r\n\t\tselectedObjectId,\r\n\t\tonObjectLocked,\r\n\t\tonObjectUnlocked,\r\n\t\tonUserJoined,\r\n\t\tonUserLeft,\r\n\t]);\r\n\r\n\t// Drawing functions\r\n\tconst drawObject = useCallback(\r\n\t\t(ctx: CanvasRenderingContext2D, obj: BoardObject, isSelected: boolean) => {\r\n\t\t\tctx.save();\r\n\r\n\t\t\tif (obj.rotation !== 0) {\r\n\t\t\t\tconst centerX = obj.x + obj.width / 2;\r\n\t\t\t\tconst centerY = obj.y + obj.height / 2;\r\n\t\t\t\tctx.translate(centerX, centerY);\r\n\t\t\t\tctx.rotate((obj.rotation * Math.PI) / 180);\r\n\t\t\t\tctx.translate(-centerX, -centerY);\r\n\t\t\t}\r\n\r\n\t\t\tif (isSelected) {\r\n\t\t\t\tctx.strokeStyle = '#3B82F6';\r\n\t\t\t\tctx.lineWidth = 2;\r\n\t\t\t\tctx.setLineDash([5, 5]);\r\n\t\t\t\tctx.strokeRect(obj.x - 5, obj.y - 5, obj.width + 10, obj.height + 10);\r\n\t\t\t\tctx.setLineDash([]);\r\n\t\t\t}\r\n\r\n\t\t\tctx.strokeStyle = obj.strokeColor || obj.color || defaultStroke;\r\n\t\t\tctx.fillStyle = obj.fillColor || 'transparent';\r\n\t\t\tctx.lineWidth = obj.strokeWidth || defaultLineWidth;\r\n\r\n\t\t\tswitch (obj.type) {\r\n\t\t\t\tcase 'rectangle':\r\n\t\t\t\t\tif (obj.fillColor) ctx.fillRect(obj.x, obj.y, obj.width, obj.height);\r\n\t\t\t\t\tctx.strokeRect(obj.x, obj.y, obj.width, obj.height);\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'circle':\r\n\t\t\t\t\tctx.beginPath();\r\n\t\t\t\t\tctx.ellipse(\r\n\t\t\t\t\t\tobj.x + obj.width / 2,\r\n\t\t\t\t\t\tobj.y + obj.height / 2,\r\n\t\t\t\t\t\tobj.width / 2,\r\n\t\t\t\t\t\tobj.height / 2,\r\n\t\t\t\t\t\t0,\r\n\t\t\t\t\t\t0,\r\n\t\t\t\t\t\tMath.PI * 2,\r\n\t\t\t\t\t);\r\n\t\t\t\t\tif (obj.fillColor) ctx.fill();\r\n\t\t\t\t\tctx.stroke();\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'line':\r\n\t\t\t\t\tif (obj.x2 !== undefined && obj.y2 !== undefined) {\r\n\t\t\t\t\t\tctx.beginPath();\r\n\t\t\t\t\t\tctx.moveTo(obj.x, obj.y);\r\n\t\t\t\t\t\tctx.lineTo(obj.x2, obj.y2);\r\n\t\t\t\t\t\tctx.stroke();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'pencil':\r\n\t\t\t\t\tif (obj.points && obj.points.length > 0) {\r\n\t\t\t\t\t\tctx.beginPath();\r\n\t\t\t\t\t\tctx.moveTo(obj.points[0].x, obj.points[0].y);\r\n\t\t\t\t\t\tfor (let i = 1; i < obj.points.length; i++) {\r\n\t\t\t\t\t\t\tctx.lineTo(obj.points[i].x, obj.points[i].y);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tctx.stroke();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'text':\r\n\t\t\t\t\tif (obj.content) {\r\n\t\t\t\t\t\tctx.fillStyle = obj.color || defaultStroke;\r\n\t\t\t\t\t\tctx.font = `${obj.fontSize || defaultFontSize}px Arial, sans-serif`;\r\n\t\t\t\t\t\tctx.textBaseline = 'top';\r\n\t\t\t\t\t\tctx.fillText(obj.content, obj.x, obj.y);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'image':\r\n\t\t\t\t\tif (obj.imageUrl) {\r\n\t\t\t\t\t\tconst img = imageCacheRef.current.get(obj.imageUrl);\r\n\t\t\t\t\t\tif (img?.complete) {\r\n\t\t\t\t\t\t\tctx.drawImage(img, obj.x, obj.y, obj.width, obj.height);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tctx.restore();\r\n\r\n\t\t\t// Draw lock label\r\n\t\t\tif (obj.locked_by && obj.locked_by !== userId) {\r\n\t\t\t\tctx.save();\r\n\t\t\t\tctx.font = '12px Arial, sans-serif';\r\n\t\t\t\tctx.fillStyle = 'rgba(249, 115, 22, 0.9)';\r\n\t\t\t\tconst text = `🔒 ${obj.locked_by_name || 'Locked'}`;\r\n\t\t\t\tconst metrics = ctx.measureText(text);\r\n\t\t\t\tconst padding = 8;\r\n\t\t\t\tconst boxWidth = metrics.width + padding * 2;\r\n\t\t\t\tconst boxHeight = 24;\r\n\t\t\t\tconst centerX = obj.x + obj.width / 2;\r\n\r\n\t\t\t\t// @ts-ignore - roundRect is defined below\r\n\t\t\t\tctx.roundRect(\r\n\t\t\t\t\tcenterX - boxWidth / 2,\r\n\t\t\t\t\tobj.y - boxHeight - 5,\r\n\t\t\t\t\tboxWidth,\r\n\t\t\t\t\tboxHeight,\r\n\t\t\t\t\t4,\r\n\t\t\t\t);\r\n\t\t\t\tctx.fill();\r\n\r\n\t\t\t\tctx.fillStyle = 'white';\r\n\t\t\t\tctx.font = '12px Arial, sans-serif';\r\n\t\t\t\tctx.textAlign = 'center';\r\n\t\t\t\tctx.textBaseline = 'middle';\r\n\t\t\t\tctx.fillText(text, centerX, obj.y - boxHeight / 2 - 5);\r\n\t\t\t\tctx.restore();\r\n\t\t\t}\r\n\t\t},\r\n\t\t[defaultStroke, defaultLineWidth, defaultFontSize, userId],\r\n\t);\r\n\r\n\tconst drawResizeHandles = useCallback(\r\n\t\t(ctx: CanvasRenderingContext2D, obj: BoardObject) => {\r\n\t\t\tif (obj.type === 'pencil') return;\r\n\r\n\t\t\tctx.save();\r\n\r\n\t\t\tif (obj.rotation !== 0) {\r\n\t\t\t\tconst centerX = obj.x + obj.width / 2;\r\n\t\t\t\tconst centerY = obj.y + obj.height / 2;\r\n\t\t\t\tctx.translate(centerX, centerY);\r\n\t\t\t\tctx.rotate((obj.rotation * Math.PI) / 180);\r\n\t\t\t\tctx.translate(-centerX, -centerY);\r\n\t\t\t}\r\n\r\n\t\t\tctx.fillStyle = '#3B82F6';\r\n\t\t\tctx.strokeStyle = '#FFFFFF';\r\n\t\t\tctx.lineWidth = 2;\r\n\r\n\t\t\tconst handles = [\r\n\t\t\t\t{ x: obj.x - 4, y: obj.y - 4 },\r\n\t\t\t\t{ x: obj.x + obj.width / 2 - 4, y: obj.y - 4 },\r\n\t\t\t\t{ x: obj.x + obj.width - 4, y: obj.y - 4 },\r\n\t\t\t\t{ x: obj.x + obj.width - 4, y: obj.y + obj.height / 2 - 4 },\r\n\t\t\t\t{ x: obj.x + obj.width - 4, y: obj.y + obj.height - 4 },\r\n\t\t\t\t{ x: obj.x + obj.width / 2 - 4, y: obj.y + obj.height - 4 },\r\n\t\t\t\t{ x: obj.x - 4, y: obj.y + obj.height - 4 },\r\n\t\t\t\t{ x: obj.x - 4, y: obj.y + obj.height / 2 - 4 },\r\n\t\t\t];\r\n\r\n\t\t\thandles.forEach(handle => {\r\n\t\t\t\tctx.beginPath();\r\n\t\t\t\tctx.rect(handle.x, handle.y, 8, 8);\r\n\t\t\t\tctx.fill();\r\n\t\t\t\tctx.stroke();\r\n\t\t\t});\r\n\r\n\t\t\tctx.restore();\r\n\t\t},\r\n\t\t[],\r\n\t);\r\n\r\n\tconst drawRotationHandle = useCallback(\r\n\t\t(ctx: CanvasRenderingContext2D, obj: BoardObject) => {\r\n\t\t\tif (obj.type === 'pencil') return;\r\n\r\n\t\t\tconst centerX = obj.x + obj.width / 2;\r\n\t\t\tctx.save();\r\n\r\n\t\t\tif (obj.rotation !== 0) {\r\n\t\t\t\tconst centerY = obj.y + obj.height / 2;\r\n\t\t\t\tctx.translate(centerX, centerY);\r\n\t\t\t\tctx.rotate((obj.rotation * Math.PI) / 180);\r\n\t\t\t\tctx.translate(-centerX, -centerY);\r\n\t\t\t}\r\n\r\n\t\t\tconst handleX = centerX;\r\n\t\t\tconst handleY = obj.y - 35;\r\n\r\n\t\t\tctx.strokeStyle = '#3B82F6';\r\n\t\t\tctx.lineWidth = 1;\r\n\t\t\tctx.setLineDash([2, 2]);\r\n\t\t\tctx.beginPath();\r\n\t\t\tctx.moveTo(centerX, obj.y);\r\n\t\t\tctx.lineTo(handleX, handleY);\r\n\t\t\tctx.stroke();\r\n\t\t\tctx.setLineDash([]);\r\n\r\n\t\t\tctx.fillStyle = '#3B82F6';\r\n\t\t\tctx.strokeStyle = '#FFFFFF';\r\n\t\t\tctx.lineWidth = 2;\r\n\t\t\tctx.beginPath();\r\n\t\t\tctx.arc(handleX, handleY, 8, 0, Math.PI * 2);\r\n\t\t\tctx.fill();\r\n\t\t\tctx.stroke();\r\n\r\n\t\t\tctx.fillStyle = '#FFFFFF';\r\n\t\t\tctx.font = '12px Arial';\r\n\t\t\tctx.textAlign = 'center';\r\n\t\t\tctx.textBaseline = 'middle';\r\n\t\t\tctx.fillText('↻', handleX, handleY);\r\n\r\n\t\t\tctx.restore();\r\n\t\t},\r\n\t\t[],\r\n\t);\r\n\r\n\tconst redrawCanvas = useCallback(() => {\r\n\t\tconst canvas = canvasRef.current;\r\n\t\tif (!canvas) return;\r\n\r\n\t\tconst ctx = canvas.getContext('2d');\r\n\t\tif (!ctx) return;\r\n\r\n\t\tctx.clearRect(0, 0, canvas.width, canvas.height);\r\n\r\n\t\tobjects.forEach(obj => {\r\n\t\t\tif (obj.id === editingTextId) return;\r\n\t\t\tconst isSelected = obj.id === selectedObjectId;\r\n\t\t\tdrawObject(ctx, obj, isSelected);\r\n\t\t});\r\n\r\n\t\tif (tempObjectRef.current) {\r\n\t\t\tdrawObject(ctx, tempObjectRef.current, false);\r\n\t\t}\r\n\r\n\t\tif (selectedObjectId) {\r\n\t\t\tconst obj = objects.find(o => o.id === selectedObjectId);\r\n\t\t\tif (obj && canEditObject(obj, userId) && obj.type !== 'pencil') {\r\n\t\t\t\tdrawResizeHandles(ctx, obj);\r\n\t\t\t\tdrawRotationHandle(ctx, obj);\r\n\t\t\t}\r\n\t\t}\r\n\t}, [\r\n\t\tcanvasRef,\r\n\t\tobjects,\r\n\t\tselectedObjectId,\r\n\t\teditingTextId,\r\n\t\tuserId,\r\n\t\tdrawObject,\r\n\t\tdrawResizeHandles,\r\n\t\tdrawRotationHandle,\r\n\t]);\r\n\r\n\tuseEffect(() => {\r\n\t\tredrawCanvas();\r\n\t}, [redrawCanvas]);\r\n\r\n\t// Mouse handlers\r\n\tconst handleMouseDown = useCallback(\r\n\t\t(e: React.MouseEvent<HTMLCanvasElement>) => {\r\n\t\t\te.preventDefault();\r\n\t\t\tconst { x, y } = getCanvasCoordinates(e.clientX, e.clientY);\r\n\r\n\t\t\tif (tool === 'select') {\r\n\t\t\t\tif (selectedObjectId) {\r\n\t\t\t\t\tconst selectedObj = objects.find(o => o.id === selectedObjectId);\r\n\t\t\t\t\tif (selectedObj) {\r\n\t\t\t\t\t\tconst handle = findHandleAtPoint(x, y, selectedObj);\r\n\t\t\t\t\t\tif (handle) {\r\n\t\t\t\t\t\t\tif (handle === 'rotate') {\r\n\t\t\t\t\t\t\t\tsetInteractionMode('rotate');\r\n\t\t\t\t\t\t\t\tsetActiveResizeHandle('rotate');\r\n\t\t\t\t\t\t\t\tconst center = getObjectCenter(selectedObj);\r\n\t\t\t\t\t\t\t\trotationStartRef.current =\r\n\t\t\t\t\t\t\t\t\t(Math.atan2(y - center.y, x - center.x) * 180) / Math.PI -\r\n\t\t\t\t\t\t\t\t\tselectedObj.rotation;\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\tsetInteractionMode('resize');\r\n\t\t\t\t\t\t\t\tsetActiveResizeHandle(handle);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\toriginalObjectStateRef.current = {\r\n\t\t\t\t\t\t\t\tobj: { ...selectedObj },\r\n\t\t\t\t\t\t\t\tcenterX: selectedObj.x + selectedObj.width / 2,\r\n\t\t\t\t\t\t\t\tcenterY: selectedObj.y + selectedObj.height / 2,\r\n\t\t\t\t\t\t\t};\r\n\t\t\t\t\t\t\twebSocketService.lockObject(selectedObjectId);\r\n\t\t\t\t\t\t\tdrawingStartRef.current = { x, y };\r\n\t\t\t\t\t\t\tsetIsDrawing(true);\r\n\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst object = findObjectAtPoint(x, y);\r\n\t\t\t\tif (object) {\r\n\t\t\t\t\tif (selectedObjectId && selectedObjectId !== object.id) {\r\n\t\t\t\t\t\twebSocketService.unlockObject(selectedObjectId);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsetSelectedObjectId(object.id);\r\n\t\t\t\t\twebSocketService.lockObject(object.id);\r\n\t\t\t\t\tsetInteractionMode('move');\r\n\t\t\t\t\toriginalObjectStateRef.current = {\r\n\t\t\t\t\t\tobj: { ...object },\r\n\t\t\t\t\t\tcenterX: object.x + object.width / 2,\r\n\t\t\t\t\t\tcenterY: object.y + object.height / 2,\r\n\t\t\t\t\t};\r\n\t\t\t\t\tdrawingStartRef.current = { x, y };\r\n\t\t\t\t\tsetIsDrawing(true);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tif (selectedObjectId) {\r\n\t\t\t\t\t\twebSocketService.unlockObject(selectedObjectId);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsetSelectedObjectId(null);\r\n\t\t\t\t\tsetInteractionMode('none');\r\n\t\t\t\t}\r\n\t\t\t} else if (tool === 'eraser') {\r\n\t\t\t\tconst object = findObjectAtPoint(x, y);\r\n\t\t\t\tif (object) {\r\n\t\t\t\t\twebSocketService.deleteObject(object.id);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tsetInteractionMode('draw');\r\n\t\t\t\tdrawingStartRef.current = { x, y };\r\n\t\t\t\tcurrentPointsRef.current = [{ x, y }];\r\n\t\t\t\tsetIsDrawing(true);\r\n\r\n\t\t\t\tif (tool === 'pencil') {\r\n\t\t\t\t\ttempObjectRef.current = {\r\n\t\t\t\t\t\tid: `temp_${Date.now()}`,\r\n\t\t\t\t\t\ttype: 'pencil',\r\n\t\t\t\t\t\tx,\r\n\t\t\t\t\t\ty,\r\n\t\t\t\t\t\twidth: 0,\r\n\t\t\t\t\t\theight: 0,\r\n\t\t\t\t\t\trotation: 0,\r\n\t\t\t\t\t\tpoints: [{ x, y }],\r\n\t\t\t\t\t\tstrokeColor: color,\r\n\t\t\t\t\t\tstrokeWidth: lineWidth,\r\n\t\t\t\t\t\tlocked_by: null,\r\n\t\t\t\t\t\tlocked_by_name: null,\r\n\t\t\t\t\t};\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t\t[\r\n\t\t\ttool,\r\n\t\t\tcolor,\r\n\t\t\tlineWidth,\r\n\t\t\tuserId,\r\n\t\t\tselectedObjectId,\r\n\t\t\tobjects,\r\n\t\t\tgetCanvasCoordinates,\r\n\t\t\tfindObjectAtPoint,\r\n\t\t\tfindHandleAtPoint,\r\n\t\t\tgetObjectCenter,\r\n\t\t\twebSocketService,\r\n\t\t],\r\n\t);\r\n\r\n\tconst handleMouseMove = useCallback(\r\n\t\t(e: React.MouseEvent<HTMLCanvasElement>) => {\r\n\t\t\tconst { x, y } = getCanvasCoordinates(e.clientX, e.clientY);\r\n\r\n\t\t\tif (!isDrawing && tool === 'select' && canvasRef.current) {\r\n\t\t\t\tlet cursor = 'default';\r\n\t\t\t\tif (selectedObjectId) {\r\n\t\t\t\t\tconst obj = objects.find(o => o.id === selectedObjectId);\r\n\t\t\t\t\tif (obj && obj.type !== 'pencil') {\r\n\t\t\t\t\t\tconst handle = findHandleAtPoint(x, y, obj);\r\n\t\t\t\t\t\tif (handle) {\r\n\t\t\t\t\t\t\tswitch (handle) {\r\n\t\t\t\t\t\t\t\tcase 'nw':\r\n\t\t\t\t\t\t\t\tcase 'se':\r\n\t\t\t\t\t\t\t\t\tcursor = 'nwse-resize';\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\tcase 'ne':\r\n\t\t\t\t\t\t\t\tcase 'sw':\r\n\t\t\t\t\t\t\t\t\tcursor = 'nesw-resize';\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\tcase 'n':\r\n\t\t\t\t\t\t\t\tcase 's':\r\n\t\t\t\t\t\t\t\t\tcursor = 'ns-resize';\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\tcase 'e':\r\n\t\t\t\t\t\t\t\tcase 'w':\r\n\t\t\t\t\t\t\t\t\tcursor = 'ew-resize';\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t\tcase 'rotate':\r\n\t\t\t\t\t\t\t\t\tcursor = 'grab';\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (cursor === 'default') {\r\n\t\t\t\t\tconst object = findObjectAtPoint(x, y);\r\n\t\t\t\t\tif (object) cursor = 'move';\r\n\t\t\t\t}\r\n\t\t\t\tcanvasRef.current.style.cursor = cursor;\r\n\t\t\t}\r\n\r\n\t\t\tif (!isDrawing) return;\r\n\r\n\t\t\tif (\r\n\t\t\t\tinteractionMode === 'move' &&\r\n\t\t\t\tselectedObjectId &&\r\n\t\t\t\toriginalObjectStateRef.current\r\n\t\t\t) {\r\n\t\t\t\tconst deltaX = x - (drawingStartRef.current?.x || 0);\r\n\t\t\t\tconst deltaY = y - (drawingStartRef.current?.y || 0);\r\n\r\n\t\t\t\tsetObjects(prev =>\r\n\t\t\t\t\tprev.map(obj => {\r\n\t\t\t\t\t\tif (obj.id === selectedObjectId) {\r\n\t\t\t\t\t\t\tconst original = originalObjectStateRef.current!.obj;\r\n\t\t\t\t\t\t\tlet updated = {\r\n\t\t\t\t\t\t\t\t...obj,\r\n\t\t\t\t\t\t\t\tx: original.x + deltaX,\r\n\t\t\t\t\t\t\t\ty: original.y + deltaY,\r\n\t\t\t\t\t\t\t};\r\n\r\n\t\t\t\t\t\t\tif (\r\n\t\t\t\t\t\t\t\tobj.type === 'line' &&\r\n\t\t\t\t\t\t\t\tobj.x2 !== undefined &&\r\n\t\t\t\t\t\t\t\tobj.y2 !== undefined\r\n\t\t\t\t\t\t\t) {\r\n\t\t\t\t\t\t\t\tupdated.x2 = original.x2! + deltaX;\r\n\t\t\t\t\t\t\t\tupdated.y2 = original.y2! + deltaY;\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tif (obj.type === 'pencil' && obj.points) {\r\n\t\t\t\t\t\t\t\tupdated.points = original.points!.map(p => ({\r\n\t\t\t\t\t\t\t\t\tx: p.x + deltaX,\r\n\t\t\t\t\t\t\t\t\ty: p.y + deltaY,\r\n\t\t\t\t\t\t\t\t}));\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\treturn clampObjectToCanvas(updated);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\treturn obj;\r\n\t\t\t\t\t}),\r\n\t\t\t\t);\r\n\t\t\t} else if (\r\n\t\t\t\tinteractionMode === 'rotate' &&\r\n\t\t\t\tselectedObjectId &&\r\n\t\t\t\toriginalObjectStateRef.current\r\n\t\t\t) {\r\n\t\t\t\tconst center = originalObjectStateRef.current;\r\n\t\t\t\tconst currentAngle =\r\n\t\t\t\t\t(Math.atan2(y - center.centerY, x - center.centerX) * 180) / Math.PI;\r\n\t\t\t\tconst newRotation = currentAngle - rotationStartRef.current;\r\n\r\n\t\t\t\tsetObjects(prev =>\r\n\t\t\t\t\tprev.map(obj =>\r\n\t\t\t\t\t\tobj.id === selectedObjectId\r\n\t\t\t\t\t\t\t? { ...obj, rotation: newRotation }\r\n\t\t\t\t\t\t\t: obj,\r\n\t\t\t\t\t),\r\n\t\t\t\t);\r\n\t\t\t} else if (\r\n\t\t\t\tinteractionMode === 'resize' &&\r\n\t\t\t\tselectedObjectId &&\r\n\t\t\t\tactiveResizeHandle &&\r\n\t\t\t\toriginalObjectStateRef.current\r\n\t\t\t) {\r\n\t\t\t\tconst globalDeltaX = x - (drawingStartRef.current?.x || 0);\r\n\t\t\t\tconst globalDeltaY = y - (drawingStartRef.current?.y || 0);\r\n\t\t\t\tconst obj = objects.find(o => o.id === selectedObjectId);\r\n\t\t\t\tif (!obj) return;\r\n\r\n\t\t\t\tconst original = originalObjectStateRef.current.obj;\r\n\t\t\t\tconst rad = (-original.rotation * Math.PI) / 180;\r\n\t\t\t\tconst cos = Math.cos(rad);\r\n\t\t\t\tconst sin = Math.sin(rad);\r\n\r\n\t\t\t\tconst localDeltaX = globalDeltaX * cos - globalDeltaY * sin;\r\n\t\t\t\tconst localDeltaY = globalDeltaX * sin + globalDeltaY * cos;\r\n\r\n\t\t\t\tlet updated: BoardObject = obj;\r\n\r\n\t\t\t\tif (obj.type === 'line') {\r\n\t\t\t\t\tupdated = resizeLineObject(\r\n\t\t\t\t\t\tobj,\r\n\t\t\t\t\t\tactiveResizeHandle,\r\n\t\t\t\t\t\tlocalDeltaX,\r\n\t\t\t\t\t\tlocalDeltaY,\r\n\t\t\t\t\t\toriginal,\r\n\t\t\t\t\t);\r\n\t\t\t\t} else if (obj.type === 'image') {\r\n\t\t\t\t\tupdated = resizeImageWithAspectRatio(\r\n\t\t\t\t\t\tobj,\r\n\t\t\t\t\t\tactiveResizeHandle,\r\n\t\t\t\t\t\tlocalDeltaX,\r\n\t\t\t\t\t\tlocalDeltaY,\r\n\t\t\t\t\t\toriginal,\r\n\t\t\t\t\t);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tupdated = resizeObjectFree(\r\n\t\t\t\t\t\tobj,\r\n\t\t\t\t\t\tactiveResizeHandle,\r\n\t\t\t\t\t\tlocalDeltaX,\r\n\t\t\t\t\t\tlocalDeltaY,\r\n\t\t\t\t\t\toriginal,\r\n\t\t\t\t\t);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tsetObjects(prev =>\r\n\t\t\t\t\tprev.map(o => (o.id === selectedObjectId ? updated : o)),\r\n\t\t\t\t);\r\n\t\t\t} else if (interactionMode === 'draw' && drawingStartRef.current) {\r\n\t\t\t\tcurrentPointsRef.current.push({ x, y });\r\n\r\n\t\t\t\tif (tool === 'line') {\r\n\t\t\t\t\ttempObjectRef.current = {\r\n\t\t\t\t\t\tid: `temp_${Date.now()}`,\r\n\t\t\t\t\t\ttype: 'line',\r\n\t\t\t\t\t\tx: drawingStartRef.current.x,\r\n\t\t\t\t\t\ty: drawingStartRef.current.y,\r\n\t\t\t\t\t\twidth: Math.abs(x - drawingStartRef.current.x),\r\n\t\t\t\t\t\theight: Math.abs(y - drawingStartRef.current.y),\r\n\t\t\t\t\t\trotation: 0,\r\n\t\t\t\t\t\tstrokeColor: color,\r\n\t\t\t\t\t\tstrokeWidth: lineWidth,\r\n\t\t\t\t\t\tx2: x,\r\n\t\t\t\t\t\ty2: y,\r\n\t\t\t\t\t\tlocked_by: null,\r\n\t\t\t\t\t\tlocked_by_name: null,\r\n\t\t\t\t\t};\r\n\t\t\t\t} else if (tool === 'rectangle') {\r\n\t\t\t\t\ttempObjectRef.current = {\r\n\t\t\t\t\t\tid: `temp_${Date.now()}`,\r\n\t\t\t\t\t\ttype: 'rectangle',\r\n\t\t\t\t\t\tx: Math.min(drawingStartRef.current.x, x),\r\n\t\t\t\t\t\ty: Math.min(drawingStartRef.current.y, y),\r\n\t\t\t\t\t\twidth: Math.abs(x - drawingStartRef.current.x),\r\n\t\t\t\t\t\theight: Math.abs(y - drawingStartRef.current.y),\r\n\t\t\t\t\t\trotation: 0,\r\n\t\t\t\t\t\tstrokeColor: color,\r\n\t\t\t\t\t\tfillColor: fillColor,\r\n\t\t\t\t\t\tstrokeWidth: lineWidth,\r\n\t\t\t\t\t\tlocked_by: null,\r\n\t\t\t\t\t\tlocked_by_name: null,\r\n\t\t\t\t\t};\r\n\t\t\t\t} else if (tool === 'circle') {\r\n\t\t\t\t\tconst radius = Math.hypot(\r\n\t\t\t\t\t\tx - drawingStartRef.current.x,\r\n\t\t\t\t\t\ty - drawingStartRef.current.y,\r\n\t\t\t\t\t);\r\n\t\t\t\t\ttempObjectRef.current = {\r\n\t\t\t\t\t\tid: `temp_${Date.now()}`,\r\n\t\t\t\t\t\ttype: 'circle',\r\n\t\t\t\t\t\tx: drawingStartRef.current.x - radius,\r\n\t\t\t\t\t\ty: drawingStartRef.current.y - radius,\r\n\t\t\t\t\t\twidth: radius * 2,\r\n\t\t\t\t\t\theight: radius * 2,\r\n\t\t\t\t\t\trotation: 0,\r\n\t\t\t\t\t\tstrokeColor: color,\r\n\t\t\t\t\t\tfillColor: fillColor,\r\n\t\t\t\t\t\tstrokeWidth: lineWidth,\r\n\t\t\t\t\t\tlocked_by: null,\r\n\t\t\t\t\t\tlocked_by_name: null,\r\n\t\t\t\t\t};\r\n\t\t\t\t} else if (tool === 'pencil' && tempObjectRef.current) {\r\n\t\t\t\t\ttempObjectRef.current = {\r\n\t\t\t\t\t\t...tempObjectRef.current,\r\n\t\t\t\t\t\tpoints: [...currentPointsRef.current],\r\n\t\t\t\t\t};\r\n\t\t\t\t}\r\n\r\n\t\t\t\tredrawCanvas();\r\n\t\t\t}\r\n\t\t},\r\n\t\t[\r\n\t\t\tisDrawing,\r\n\t\t\ttool,\r\n\t\t\tcolor,\r\n\t\t\tfillColor,\r\n\t\t\tlineWidth,\r\n\t\t\tcanvasRef,\r\n\t\t\tselectedObjectId,\r\n\t\t\tinteractionMode,\r\n\t\t\tactiveResizeHandle,\r\n\t\t\tobjects,\r\n\t\t\tgetCanvasCoordinates,\r\n\t\t\tfindObjectAtPoint,\r\n\t\t\tfindHandleAtPoint,\r\n\t\t\tredrawCanvas,\r\n\t\t\twebSocketService,\r\n\t\t],\r\n\t);\r\n\r\n\tconst handleMouseUp = useCallback(\r\n\t\t(e: React.MouseEvent<HTMLCanvasElement>) => {\r\n\t\t\tif (!isDrawing) return;\r\n\r\n\t\t\tif (interactionMode === 'draw' && drawingStartRef.current) {\r\n\t\t\t\tconst { x, y } = getCanvasCoordinates(e.clientX, e.clientY);\r\n\t\t\t\tconst startX = drawingStartRef.current.x;\r\n\t\t\t\tconst startY = drawingStartRef.current.y;\r\n\t\t\t\tconst newId = generateObjectId();\r\n\t\t\t\tlet newObject: BoardObject | null = null;\r\n\r\n\t\t\t\tswitch (tool) {\r\n\t\t\t\t\tcase 'line':\r\n\t\t\t\t\t\tnewObject = clampObjectToCanvas({\r\n\t\t\t\t\t\t\tid: newId,\r\n\t\t\t\t\t\t\ttype: 'line',\r\n\t\t\t\t\t\t\tx: startX,\r\n\t\t\t\t\t\t\ty: startY,\r\n\t\t\t\t\t\t\twidth: Math.abs(x - startX),\r\n\t\t\t\t\t\t\theight: Math.abs(y - startY),\r\n\t\t\t\t\t\t\trotation: 0,\r\n\t\t\t\t\t\t\tstrokeColor: color,\r\n\t\t\t\t\t\t\tstrokeWidth: lineWidth,\r\n\t\t\t\t\t\t\tx2: x,\r\n\t\t\t\t\t\t\ty2: y,\r\n\t\t\t\t\t\t\tlocked_by: null,\r\n\t\t\t\t\t\t\tlocked_by_name: null,\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 'rectangle':\r\n\t\t\t\t\t\tnewObject = clampObjectToCanvas({\r\n\t\t\t\t\t\t\tid: newId,\r\n\t\t\t\t\t\t\ttype: 'rectangle',\r\n\t\t\t\t\t\t\tx: Math.min(startX, x),\r\n\t\t\t\t\t\t\ty: Math.min(startY, y),\r\n\t\t\t\t\t\t\twidth: Math.abs(x - startX),\r\n\t\t\t\t\t\t\theight: Math.abs(y - startY),\r\n\t\t\t\t\t\t\trotation: 0,\r\n\t\t\t\t\t\t\tstrokeColor: color,\r\n\t\t\t\t\t\t\tfillColor: fillColor,\r\n\t\t\t\t\t\t\tstrokeWidth: lineWidth,\r\n\t\t\t\t\t\t\tlocked_by: null,\r\n\t\t\t\t\t\t\tlocked_by_name: null,\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 'circle':\r\n\t\t\t\t\t\tconst radius = Math.hypot(x - startX, y - startY);\r\n\t\t\t\t\t\tnewObject = clampObjectToCanvas({\r\n\t\t\t\t\t\t\tid: newId,\r\n\t\t\t\t\t\t\ttype: 'circle',\r\n\t\t\t\t\t\t\tx: startX - radius,\r\n\t\t\t\t\t\t\ty: startY - radius,\r\n\t\t\t\t\t\t\twidth: radius * 2,\r\n\t\t\t\t\t\t\theight: radius * 2,\r\n\t\t\t\t\t\t\trotation: 0,\r\n\t\t\t\t\t\t\tstrokeColor: color,\r\n\t\t\t\t\t\t\tfillColor: fillColor,\r\n\t\t\t\t\t\t\tstrokeWidth: lineWidth,\r\n\t\t\t\t\t\t\tlocked_by: null,\r\n\t\t\t\t\t\t\tlocked_by_name: null,\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 'pencil':\r\n\t\t\t\t\t\tif (currentPointsRef.current.length > 0) {\r\n\t\t\t\t\t\t\tconst points = [...currentPointsRef.current];\r\n\t\t\t\t\t\t\tconst minX = Math.min(...points.map(p => p.x));\r\n\t\t\t\t\t\t\tconst minY = Math.min(...points.map(p => p.y));\r\n\t\t\t\t\t\t\tconst maxX = Math.max(...points.map(p => p.x));\r\n\t\t\t\t\t\t\tconst maxY = Math.max(...points.map(p => p.y));\r\n\r\n\t\t\t\t\t\t\tnewObject = clampObjectToCanvas({\r\n\t\t\t\t\t\t\t\tid: newId,\r\n\t\t\t\t\t\t\t\ttype: 'pencil',\r\n\t\t\t\t\t\t\t\tx: minX,\r\n\t\t\t\t\t\t\t\ty: minY,\r\n\t\t\t\t\t\t\t\twidth: Math.max(maxX - minX, 1),\r\n\t\t\t\t\t\t\t\theight: Math.max(maxY - minY, 1),\r\n\t\t\t\t\t\t\t\trotation: 0,\r\n\t\t\t\t\t\t\t\tpoints: points,\r\n\t\t\t\t\t\t\t\tstrokeColor: color,\r\n\t\t\t\t\t\t\t\tstrokeWidth: lineWidth,\r\n\t\t\t\t\t\t\t\tlocked_by: null,\r\n\t\t\t\t\t\t\t\tlocked_by_name: null,\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 'text':\r\n\t\t\t\t\t\tnewObject = clampObjectToCanvas({\r\n\t\t\t\t\t\t\tid: newId,\r\n\t\t\t\t\t\t\ttype: 'text',\r\n\t\t\t\t\t\t\tx: startX,\r\n\t\t\t\t\t\t\ty: startY,\r\n\t\t\t\t\t\t\twidth: 200,\r\n\t\t\t\t\t\t\theight: 50,\r\n\t\t\t\t\t\t\trotation: 0,\r\n\t\t\t\t\t\t\tcontent: 'Double click to edit',\r\n\t\t\t\t\t\t\tfontSize: fontSize,\r\n\t\t\t\t\t\t\tcolor: color,\r\n\t\t\t\t\t\t\tlocked_by: null,\r\n\t\t\t\t\t\t\tlocked_by_name: null,\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (newObject) {\r\n\t\t\t\t\tsetObjects(prev => [...prev, newObject!]);\r\n\t\t\t\t\twebSocketService.createObject(newObject);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tsetIsDrawing(false);\r\n\t\t\tsetInteractionMode('none');\r\n\t\t\tsetActiveResizeHandle(null);\r\n\t\t\tdrawingStartRef.current = null;\r\n\t\t\tcurrentPointsRef.current = [];\r\n\t\t\ttempObjectRef.current = null;\r\n\t\t\toriginalObjectStateRef.current = null;\r\n\t\t\trotationStartRef.current = 0;\r\n\t\t},\r\n\t\t[\r\n\t\t\tisDrawing,\r\n\t\t\tinteractionMode,\r\n\t\t\ttool,\r\n\t\t\tcolor,\r\n\t\t\tfillColor,\r\n\t\t\tlineWidth,\r\n\t\t\tfontSize,\r\n\t\t\tgetCanvasCoordinates,\r\n\t\t\twebSocketService,\r\n\t\t],\r\n\t);\r\n\r\n\tconst handleDoubleClick = useCallback(\r\n\t\t(e: React.MouseEvent<HTMLCanvasElement>) => {\r\n\t\t\tif (tool !== 'select') return;\r\n\r\n\t\t\tconst { x, y } = getCanvasCoordinates(e.clientX, e.clientY);\r\n\t\t\tconst object = findObjectAtPoint(x, y);\r\n\r\n\t\t\tif (object?.type === 'text' && canEditObject(object, userId)) {\r\n\t\t\t\tsetEditingTextId(object.id);\r\n\t\t\t\twebSocketService.lockObject(object.id);\r\n\t\t\t}\r\n\t\t},\r\n\t\t[tool, userId, getCanvasCoordinates, findObjectAtPoint, webSocketService],\r\n\t);\r\n\r\n\t// Keyboard shortcuts\r\n\tuseEffect(() => {\r\n\t\tif (!enableKeyboardShortcuts) return;\r\n\r\n\t\tconst handleKeyDown = (e: KeyboardEvent) => {\r\n\t\t\tif (editingTextId) {\r\n\t\t\t\tif (e.key === 'Escape') {\r\n\t\t\t\t\tsetEditingTextId(null);\r\n\t\t\t\t\twebSocketService.unlockObject(editingTextId);\r\n\t\t\t\t}\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tif (e.key === 'Delete' || e.key === 'Backspace') {\r\n\t\t\t\te.preventDefault();\r\n\t\t\t\tif (selectedObjectId) {\r\n\t\t\t\t\twebSocketService.deleteObject(selectedObjectId);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (e.key === 'Escape' && selectedObjectId) {\r\n\t\t\t\twebSocketService.unlockObject(selectedObjectId);\r\n\t\t\t\tsetSelectedObjectId(null);\r\n\t\t\t\tsetInteractionMode('none');\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\twindow.addEventListener('keydown', handleKeyDown);\r\n\t\treturn () => window.removeEventListener('keydown', handleKeyDown);\r\n\t}, [\r\n\t\tenableKeyboardShortcuts,\r\n\t\teditingTextId,\r\n\t\tselectedObjectId,\r\n\t\twebSocketService,\r\n\t]);\r\n\r\n\t// Global listeners\r\n\tuseEffect(() => {\r\n\t\tif (!enableGlobalListeners) return;\r\n\r\n\t\tconst handleBeforeUnload = () => {\r\n\t\t\tif (selectedObjectId) {\r\n\t\t\t\twebSocketService.unlockObject(selectedObjectId);\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\twindow.addEventListener('beforeunload', handleBeforeUnload);\r\n\t\treturn () => window.removeEventListener('beforeunload', handleBeforeUnload);\r\n\t}, [enableGlobalListeners, selectedObjectId, webSocketService]);\r\n\r\n\t// Public methods\r\n\tconst deleteSelectedObject = useCallback(() => {\r\n\t\tif (selectedObjectId) {\r\n\t\t\twebSocketService.deleteObject(selectedObjectId);\r\n\t\t}\r\n\t}, [selectedObjectId, webSocketService]);\r\n\r\n\tconst addImage = useCallback(\r\n\t\t(imageUrl: string) => {\r\n\t\t\tconst img = new Image();\r\n\t\t\timg.crossOrigin = 'anonymous';\r\n\t\t\timg.onload = () => {\r\n\t\t\t\tlet width = img.width;\r\n\t\t\t\tlet height = img.height;\r\n\r\n\t\t\t\tif (width > maxImageSize || height > maxImageSize) {\r\n\t\t\t\t\tif (width > height) {\r\n\t\t\t\t\t\twidth = maxImageSize;\r\n\t\t\t\t\t\theight = (maxImageSize / img.width) * img.height;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\theight = maxImageSize;\r\n\t\t\t\t\t\twidth = (maxImageSize / img.height) * img.width;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst newObject: BoardObject = clampObjectToCanvas({\r\n\t\t\t\t\tid: generateObjectId(),\r\n\t\t\t\t\ttype: 'image',\r\n\t\t\t\t\tx: CANVAS_WIDTH / 2 - width / 2,\r\n\t\t\t\t\ty: CANVAS_HEIGHT / 2 - height / 2,\r\n\t\t\t\t\twidth,\r\n\t\t\t\t\theight,\r\n\t\t\t\t\trotation: 0,\r\n\t\t\t\t\timageUrl,\r\n\t\t\t\t\taspectRatio: img.width / img.height,\r\n\t\t\t\t\tlocked_by: null,\r\n\t\t\t\t\tlocked_by_name: null,\r\n\t\t\t\t});\r\n\r\n\t\t\t\timageCacheRef.current.set(imageUrl, img);\r\n\t\t\t\tsetObjects(prev => [...prev, newObject]);\r\n\t\t\t\twebSocketService.createObject(newObject);\r\n\t\t\t};\r\n\t\t\timg.src = imageUrl;\r\n\t\t},\r\n\t\t[maxImageSize, webSocketService],\r\n\t);\r\n\r\n\tconst updateObjectContent = useCallback(\r\n\t\t(objectId: string, content: string) => {\r\n\t\t\tsetObjects(prev =>\r\n\t\t\t\tprev.map(obj => {\r\n\t\t\t\t\tif (obj.id === objectId) {\r\n\t\t\t\t\t\tconst updated = { ...obj, content };\r\n\t\t\t\t\t\twebSocketService.updateObject(updated);\r\n\t\t\t\t\t\treturn updated;\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn obj;\r\n\t\t\t\t}),\r\n\t\t\t);\r\n\t\t},\r\n\t\t[webSocketService],\r\n\t);\r\n\r\n\tconst clearCanvas = useCallback(() => {\r\n\t\tobjects.forEach(obj => {\r\n\t\t\twebSocketService.deleteObject(obj.id);\r\n\t\t});\r\n\t\tsetObjects([]);\r\n\t\tsetSelectedObjectId(null);\r\n\t}, [objects, webSocketService]);\r\n\r\n\tconst exportAsJSON = useCallback(() => {\r\n\t\treturn JSON.stringify(objects, null, 2);\r\n\t}, [objects]);\r\n\r\n\tconst importFromJSON = useCallback(\r\n\t\t(json: string) => {\r\n\t\t\ttry {\r\n\t\t\t\tconst imported = JSON.parse(json) as BoardObject[];\r\n\t\t\t\timported.forEach(obj => {\r\n\t\t\t\t\twebSocketService.createObject(obj);\r\n\t\t\t\t});\r\n\t\t\t\tsetObjects(prev => [...prev, ...imported]);\r\n\t\t\t} catch (error) {\r\n\t\t\t\tconsole.error('Failed to import objects:', error);\r\n\t\t\t}\r\n\t\t},\r\n\t\t[webSocketService],\r\n\t);\r\n\r\n\treturn {\r\n\t\t// State\r\n\t\ttool,\r\n\t\tcolor,\r\n\t\tfillColor,\r\n\t\tlineWidth,\r\n\t\tfontSize,\r\n\t\tisDrawing,\r\n\t\tselectedObjectId,\r\n\t\tinteractionMode,\r\n\t\tobjects,\r\n\t\tusersOnline,\r\n\t\tisConnected,\r\n\t\teditingTextId,\r\n\r\n\t\t// Setters\r\n\t\tsetTool,\r\n\t\tsetColor,\r\n\t\tsetFillColor,\r\n\t\tsetLineWidth,\r\n\t\tsetFontSize,\r\n\t\tsetSelectedObjectId,\r\n\t\tsetEditingTextId,\r\n\r\n\t\t// Handlers\r\n\t\thandleMouseDown,\r\n\t\thandleMouseMove,\r\n\t\thandleMouseUp,\r\n\t\thandleDoubleClick,\r\n\r\n\t\t// Methods\r\n\t\tdeleteSelectedObject,\r\n\t\taddImage,\r\n\t\tupdateObjectContent,\r\n\t\tclearCanvas,\r\n\t\texportAsJSON,\r\n\t\timportFromJSON,\r\n\r\n\t\t// Utils\r\n\t\tredrawCanvas,\r\n\t};\r\n};\r\n\r\n// Add roundRect to CanvasRenderingContext2D\r\nif (typeof CanvasRenderingContext2D !== 'undefined') {\r\n\tCanvasRenderingContext2D.prototype.roundRect = function (\r\n\t\tx: number,\r\n\t\ty: number,\r\n\t\tw: number,\r\n\t\th: number,\r\n\t\tr: number,\r\n\t) {\r\n\t\tif (w < 2 * r) r = w / 2;\r\n\t\tif (h < 2 * r) r = h / 2;\r\n\t\tthis.moveTo(x + r, y);\r\n\t\tthis.lineTo(x + w - r, y);\r\n\t\tthis.quadraticCurveTo(x + w, y, x + w, y + r);\r\n\t\tthis.lineTo(x + w, y + h - r);\r\n\t\tthis.quadraticCurveTo(x + w, y + h, x + w - r, y + h);\r\n\t\tthis.lineTo(x + r, y + h);\r\n\t\tthis.quadraticCurveTo(x, y + h, x, y + h - r);\r\n\t\tthis.lineTo(x, y + r);\r\n\t\tthis.quadraticCurveTo(x, y, x + r, y);\r\n\t\treturn this;\r\n\t};\r\n}\r\n\r\ndeclare global {\r\n\tinterface CanvasRenderingContext2D {\r\n\t\troundRect(\r\n\t\t\tx: number,\r\n\t\t\ty: number,\r\n\t\t\tw: number,\r\n\t\t\th: number,\r\n\t\t\tr: number,\r\n\t\t): CanvasRenderingContext2D;\r\n\t}\r\n}\r\n","// =============================================================================\r\n// ТИПЫ И ИНТЕРФЕЙСЫ ДЛЯ ИНТЕРАКТИВНОЙ ДОСКИ\r\n// =============================================================================\r\n\r\n/**\r\n * КОНСТАНТЫ ХОЛСТА\r\n */\r\nexport const CANVAS_WIDTH = 1600;\r\nexport const CANVAS_HEIGHT = 900;\r\n\r\n/**\r\n * ТИПЫ ОБЪЕКТОВ\r\n */\r\nexport type ObjectType =\r\n\t| 'text'\r\n\t| 'image'\r\n\t| 'rectangle'\r\n\t| 'circle'\r\n\t| 'line'\r\n\t| 'pencil';\r\n\r\n/**\r\n * ИНСТРУМЕНТЫ РИСОВАНИЯ\r\n */\r\nexport type DrawingTool =\r\n\t| 'select'\r\n\t| 'pencil'\r\n\t| 'line'\r\n\t| 'rectangle'\r\n\t| 'circle'\r\n\t| 'text'\r\n\t| 'eraser';\r\n\r\n/**\r\n * РЕЖИМЫ ВЗАИМОДЕЙСТВИЯ\r\n */\r\nexport type InteractionMode = 'none' | 'move' | 'rotate' | 'resize' | 'draw';\r\n\r\n/**\r\n * МАРКЕРЫ ИЗМЕНЕНИЯ РАЗМЕРА\r\n */\r\nexport type ResizeHandle =\r\n\t| 'nw'\r\n\t| 'ne'\r\n\t| 'sw'\r\n\t| 'se'\r\n\t| 'n'\r\n\t| 's'\r\n\t| 'e'\r\n\t| 'w'\r\n\t| 'rotate';\r\n\r\n/**\r\n * ТОЧКА НА ХОЛСТЕ\r\n */\r\nexport interface Point {\r\n\tx: number;\r\n\ty: number;\r\n}\r\n\r\n/**\r\n * ОБЪЕКТ НА ДОСКЕ (BoardObject)\r\n */\r\nexport interface BoardObject {\r\n\t// Базовые свойства\r\n\tid: string;\r\n\ttype: ObjectType;\r\n\tx: number;\r\n\ty: number;\r\n\twidth: number;\r\n\theight: number;\r\n\trotation: number;\r\n\r\n\t// Свойства блокировки\r\n\tlocked_by: number | null;\r\n\tlocked_by_name: string | null;\r\n\r\n\t// Свойства текста\r\n\tcontent?: string;\r\n\tfontSize?: number;\r\n\tcolor?: string;\r\n\r\n\t// Свойства изображения\r\n\timageUrl?: string;\r\n\taspectRatio?: number;\r\n\r\n\t// Свойства фигур\r\n\tfillColor?: string;\r\n\tstrokeColor?: string;\r\n\tstrokeWidth?: number;\r\n\r\n\t// Свойства линии\r\n\tx2?: number;\r\n\ty2?: number;\r\n\r\n\t// Свойства карандаша\r\n\tpoints?: Point[];\r\n\r\n\t// Служебные\r\n\tuserId?: number;\r\n\ttimestamp?: number;\r\n}\r\n\r\n// =============================================================================\r\n// УТИЛИТНЫЕ ФУНКЦИИ\r\n// =============================================================================\r\n\r\n/**\r\n * Ограничивает координаты объекта границами холста.\r\n */\r\nexport function clampObjectToCanvas(obj: BoardObject): BoardObject {\r\n\tconst result = { ...obj };\r\n\r\n\tresult.width = Math.max(result.width, 10);\r\n\tresult.height = Math.max(result.height, 10);\r\n\r\n\tresult.x = Math.max(0, Math.min(CANVAS_WIDTH - result.width, result.x));\r\n\tresult.y = Math.max(0, Math.min(CANVAS_HEIGHT - result.height, result.y));\r\n\r\n\tif (obj.type === 'line' && obj.x2 !== undefined && obj.y2 !== undefined) {\r\n\t\tresult.x2 = Math.max(0, Math.min(CANVAS_WIDTH, obj.x2));\r\n\t\tresult.y2 = Math.max(0, Math.min(CANVAS_HEIGHT, obj.y2));\r\n\t}\r\n\r\n\tif (obj.type === 'pencil' && obj.points) {\r\n\t\tresult.points = obj.points.map(point => ({\r\n\t\t\tx: Math.max(0, Math.min(CANVAS_WIDTH, point.x)),\r\n\t\t\ty: Math.max(0, Math.min(CANVAS_HEIGHT, point.y)),\r\n\t\t}));\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\n/**\r\n * Проверяет, может ли пользователь редактировать объект.\r\n */\r\nexport function canEditObject(obj: BoardObject, userId: number): boolean {\r\n\treturn obj.locked_by === null || obj.locked_by === userId;\r\n}\r\n\r\n/**\r\n * Генерирует уникальный ID для нового объекта.\r\n */\r\nexport function generateObjectId(): string {\r\n\treturn `obj_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\r\n}\r\n\r\n/**\r\n * Вращает точку вокруг центра на заданный угол.\r\n */\r\nexport function rotatePoint(\r\n\tx: number,\r\n\ty: number,\r\n\tcx: number,\r\n\tcy: number,\r\n\tangle: number,\r\n): { x: number; y: number } {\r\n\tconst rad = (angle * Math.PI) / 180;\r\n\tconst cos = Math.cos(rad);\r\n\tconst sin = Math.sin(rad);\r\n\tconst dx = x - cx;\r\n\tconst dy = y - cy;\r\n\treturn {\r\n\t\tx: cx + (dx * cos - dy * sin),\r\n\t\ty: cy + (dx * sin + dy * cos),\r\n\t};\r\n}\r\n\r\n/**\r\n * Изменяет размер изображения С СОХРАНЕНИЕМ ПРОПОРЦИЙ.\r\n */\r\nexport function resizeImageWithAspectRatio(\r\n\tobj: BoardObject,\r\n\thandle: ResizeHandle,\r\n\tdeltaX: number,\r\n\tdeltaY: number,\r\n\toriginal: BoardObject,\r\n): BoardObject {\r\n\tconst result = { ...obj };\r\n\tconst aspectRatio = original.aspectRatio || original.width / original.height;\r\n\r\n\tswitch (handle) {\r\n\t\tcase 'se':\r\n\t\t\tresult.width = Math.max(10, original.width + deltaX);\r\n\t\t\tresult.height = result.width / aspectRatio;\r\n\t\t\tbreak;\r\n\t\tcase 'sw':\r\n\t\t\tresult.width = Math.max(10, original.width - deltaX);\r\n\t\t\tresult.height = result.width / aspectRatio;\r\n\t\t\tresult.x = original.x + original.width - result.width;\r\n\t\t\tbreak;\r\n\t\tcase 'ne':\r\n\t\t\tresult.width = Math.max(10, original.width + deltaX);\r\n\t\t\tresult.height = result.width / aspectRatio;\r\n\t\t\tresult.y = original.y + original.height - result.height;\r\n\t\t\tbreak;\r\n\t\tcase 'nw':\r\n\t\t\tresult.width = Math.max(10, original.width - deltaX);\r\n\t\t\tresult.height = result.width / aspectRatio;\r\n\t\t\tresult.x = original.x + original.width - result.width;\r\n\t\t\tresult.y = original.y + original.height - result.height;\r\n\t\t\tbreak;\r\n\t\tcase 'e':\r\n\t\t\tresult.width = Math.max(10, original.width + deltaX);\r\n\t\t\tresult.height = result.width / aspectRatio;\r\n\t\t\tbreak;\r\n\t\tcase 'w':\r\n\t\t\tresult.width = Math.max(10, original.width - deltaX);\r\n\t\t\tresult.height = result.width / aspectRatio;\r\n\t\t\tresult.x = original.x + original.width - result.width;\r\n\t\t\tbreak;\r\n\t\tcase 's':\r\n\t\t\tresult.height = Math.max(10, original.height + deltaY);\r\n\t\t\tresult.width = result.height * aspectRatio;\r\n\t\t\tbreak;\r\n\t\tcase 'n':\r\n\t\t\tresult.height = Math.max(10, original.height - deltaY);\r\n\t\t\tresult.width = result.height * aspectRatio;\r\n\t\t\tresult.y = original.y + original.height - result.height;\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\treturn clampObjectToCanvas(result);\r\n}\r\n\r\n/**\r\n * СВОБОДНЫЙ РЕСАЙЗ С ПОДДЕРЖКОЙ ПЕРЕВОРОТА\r\n */\r\nexport function resizeObjectFree(\r\n\tobj: BoardObject,\r\n\thandle: ResizeHandle,\r\n\tdeltaX: number,\r\n\tdeltaY: number,\r\n\toriginal: BoardObject,\r\n): BoardObject {\r\n\tconst result = { ...obj };\r\n\r\n\tconst originalLeft = original.x;\r\n\tconst originalTop = original.y;\r\n\tconst originalRight = original.x + original.width;\r\n\tconst originalBottom = original.y + original.height;\r\n\r\n\tlet newLeft = originalLeft;\r\n\tlet newTop = originalTop;\r\n\tlet newRight = originalRight;\r\n\tlet newBottom = originalBottom;\r\n\r\n\tswitch (handle) {\r\n\t\tcase 'nw':\r\n\t\t\tnewLeft = originalLeft + deltaX;\r\n\t\t\tnewTop = originalTop + deltaY;\r\n\t\t\tbreak;\r\n\t\tcase 'n':\r\n\t\t\tnewTop = originalTop + deltaY;\r\n\t\t\tbreak;\r\n\t\tcase 'ne':\r\n\t\t\tnewRight = originalRight + deltaX;\r\n\t\t\tnewTop = originalTop + deltaY;\r\n\t\t\tbreak;\r\n\t\tcase 'e':\r\n\t\t\tnewRight = originalRight + deltaX;\r\n\t\t\tbreak;\r\n\t\tcase 'se':\r\n\t\t\tnewRight = originalRight + deltaX;\r\n\t\t\tnewBottom = originalBottom + deltaY;\r\n\t\t\tbreak;\r\n\t\tcase 's':\r\n\t\t\tnewBottom = originalBottom + deltaY;\r\n\t\t\tbreak;\r\n\t\tcase 'sw':\r\n\t\t\tnewLeft = originalLeft + deltaX;\r\n\t\t\tnewBottom = originalBottom + deltaY;\r\n\t\t\tbreak;\r\n\t\tcase 'w':\r\n\t\t\tnewLeft = originalLeft + deltaX;\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tconst finalLeft = Math.min(newLeft, newRight);\r\n\tconst finalRight = Math.max(newLeft, newRight);\r\n\tconst finalTop = Math.min(newTop, newBottom);\r\n\tconst finalBottom = Math.max(newTop, newBottom);\r\n\r\n\tconst finalWidth = finalRight - finalLeft;\r\n\tconst finalHeight = finalBottom - finalTop;\r\n\r\n\tconst minSize = 10;\r\n\r\n\tif (finalWidth < minSize) {\r\n\t\tconst center = (finalLeft + finalRight) / 2;\r\n\t\tresult.x = center - minSize / 2;\r\n\t\tresult.width = minSize;\r\n\t} else {\r\n\t\tresult.x = finalLeft;\r\n\t\tresult.width = finalWidth;\r\n\t}\r\n\r\n\tif (finalHeight < minSize) {\r\n\t\tconst center = (finalTop + finalBottom) / 2;\r\n\t\tresult.y = center - minSize / 2;\r\n\t\tresult.height = minSize;\r\n\t} else {\r\n\t\tresult.y = finalTop;\r\n\t\tresult.height = finalHeight;\r\n\t}\r\n\r\n\treturn clampObjectToCanvas(result);\r\n}\r\n\r\n/**\r\n * РЕСАЙЗ ЛИНИИ\r\n */\r\nexport function resizeLineObject(\r\n\tobj: BoardObject,\r\n\thandle: ResizeHandle,\r\n\tdeltaX: number,\r\n\tdeltaY: number,\r\n\toriginal: BoardObject,\r\n): BoardObject {\r\n\tconst result = { ...obj };\r\n\r\n\tconst x1 = original.x;\r\n\tconst y1 = original.y;\r\n\tconst x2 = original.x2 ?? original.x + original.width;\r\n\tconst y2 = original.y2 ?? original.y + original.height;\r\n\r\n\tlet newX1 = x1;\r\n\tlet newY1 = y1;\r\n\tlet newX2 = x2;\r\n\tlet newY2 = y2;\r\n\r\n\tswitch (handle) {\r\n\t\tcase 'nw':\r\n\t\tcase 'w':\r\n\t\tcase 'sw':\r\n\t\t\tnewX1 = x1 + deltaX;\r\n\t\t\tnewY1 = y1 + deltaY;\r\n\t\t\tbreak;\r\n\t\tcase 'ne':\r\n\t\tcase 'e':\r\n\t\tcase 'se':\r\n\t\t\tnewX2 = x2 + deltaX;\r\n\t\t\tnewY2 = y2 + deltaY;\r\n\t\t\tbreak;\r\n\t\tcase 'n':\r\n\t\t\tnewY1 = y1 + deltaY;\r\n\t\t\tbreak;\r\n\t\tcase 's':\r\n\t\t\tnewY2 = y2 + deltaY;\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tnewX1 = Math.max(0, Math.min(CANVAS_WIDTH, newX1));\r\n\tnewY1 = Math.max(0, Math.min(CANVAS_HEIGHT, newY1));\r\n\tnewX2 = Math.max(0, Math.min(CANVAS_WIDTH, newX2));\r\n\tnewY2 = Math.max(0, Math.min(CANVAS_HEIGHT, newY2));\r\n\r\n\tresult.x = newX1;\r\n\tresult.y = newY1;\r\n\tresult.x2 = newX2;\r\n\tresult.y2 = newY2;\r\n\tresult.width = Math.abs(newX2 - newX1);\r\n\tresult.height = Math.abs(newY2 - newY1);\r\n\r\n\treturn clampObjectToCanvas(result);\r\n}\r\n\r\n/**\r\n * Вычисляет границы объекта (Bounding Box).\r\n */\r\nexport function getObjectBoundingBox(obj: BoardObject): {\r\n\tminX: number;\r\n\tminY: number;\r\n\tmaxX: number;\r\n\tmaxY: number;\r\n} {\r\n\tlet minX = obj.x;\r\n\tlet minY = obj.y;\r\n\tlet maxX = obj.x + obj.width;\r\n\tlet maxY = obj.y + obj.height;\r\n\r\n\tif (obj.type === 'line' && obj.x2 !== undefined && obj.y2 !== undefined) {\r\n\t\tminX = Math.min(obj.x, obj.x2);\r\n\t\tminY = Math.min(obj.y, obj.y2);\r\n\t\tmaxX = Math.max(obj.x, obj.x2);\r\n\t\tmaxY = Math.max(obj.y, obj.y2);\r\n\t} else if (obj.type === 'pencil' && obj.points && obj.points.length > 0) {\r\n\t\tminX = Math.min(...obj.points.map(p => p.x));\r\n\t\tminY = Math.min(...obj.points.map(p => p.y));\r\n\t\tmaxX = Math.max(...obj.points.map(p => p.x));\r\n\t\tmaxY = Math.max(...obj.points.map(p => p.y));\r\n\t}\r\n\r\n\treturn { minX, minY, maxX, maxY };\r\n}\r\n\r\n/**\r\n * Проверка попадания точки в повернутый прямоугольник\r\n */\r\nexport function isPointInRotatedRectangle(\r\n\tx: number,\r\n\ty: number,\r\n\tobj: BoardObject,\r\n): boolean {\r\n\tif (obj.rotation === 0) {\r\n\t\treturn (\r\n\t\t\tx >= obj.x &&\r\n\t\t\tx <= obj.x + obj.width &&\r\n\t\t\ty >= obj.y &&\r\n\t\t\ty <= obj.y + obj.height\r\n\t\t);\r\n\t}\r\n\r\n\tconst centerX = obj.x + obj.width / 2;\r\n\tconst centerY = obj.y + obj.height / 2;\r\n\tconst rad = (-obj.rotation * Math.PI) / 180;\r\n\tconst cos = Math.cos(rad);\r\n\tconst sin = Math.sin(rad);\r\n\r\n\tconst dx = x - centerX;\r\n\tconst dy = y - centerY;\r\n\r\n\tconst rotatedX = dx * cos - dy * sin;\r\n\tconst rotatedY = dx * sin + dy * cos;\r\n\r\n\treturn (\r\n\t\tMath.abs(rotatedX) <= obj.width / 2 && Math.abs(rotatedY) <= obj.height / 2\r\n\t);\r\n}\r\n\r\n/**\r\n * Расстояние от точки до отрезка\r\n */\r\nexport function distanceToLine(\r\n\tpx: number,\r\n\tpy: number,\r\n\tx1: number,\r\n\ty1: number,\r\n\tx2: number,\r\n\ty2: number,\r\n): number {\r\n\tconst dx = x2 - x1;\r\n\tconst dy = y2 - y1;\r\n\tconst lengthSq = dx * dx + dy * dy;\r\n\r\n\tif (lengthSq === 0) {\r\n\t\treturn Math.hypot(px - x1, py - y1);\r\n\t}\r\n\r\n\tlet t = ((px - x1) * dx + (py - y1) * dy) / lengthSq;\r\n\tt = Math.max(0, Math.min(1, t));\r\n\r\n\tconst projX = x1 + t * dx;\r\n\tconst projY = y1 + t * dy;\r\n\r\n\treturn Math.hypot(px - projX, py - projY);\r\n}\r\n\r\n/**\r\n * Проверка попадания точки в объект\r\n */\r\nexport function isPointInObject(\r\n\tx: number,\r\n\ty: number,\r\n\tobj: BoardObject,\r\n\tuserId: number,\r\n): boolean {\r\n\tif (!canEditObject(obj, userId)) return false;\r\n\r\n\tif (obj.type === 'line' && obj.x2 !== undefined && obj.y2 !== undefined) {\r\n\t\tconst distance = distanceToLine(x, y, obj.x, obj.y, obj.x2, obj.y2);\r\n\t\treturn distance < (obj.strokeWidth || 2) + 5;\r\n\t}\r\n\r\n\tif (obj.type === 'pencil' && obj.points) {\r\n\t\tfor (let i = 0; i < obj.points.length - 1; i++) {\r\n\t\t\tconst distance = distanceToLine(\r\n\t\t\t\tx,\r\n\t\t\t\ty,\r\n\t\t\t\tobj.points[i].x,\r\n\t\t\t\tobj.points[i].y,\r\n\t\t\t\tobj.points[i + 1].x,\r\n\t\t\t\tobj.points[i + 1].y,\r\n\t\t\t);\r\n\t\t\tif (distance < (obj.strokeWidth || 2) + 5) return true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn isPointInRotatedRectangle(x, y, obj);\r\n}\r\n","import { BoardObject } from './board';\r\n\r\nexport interface BoardEventHandlers {\r\n\tonConnectionChange?: (connected: boolean) => void;\r\n\tonObjectLocked?: (objectId: string, userId: number, userName: string) => void;\r\n\tonObjectUnlocked?: (objectId: string) => void;\r\n\tonObjectCreated?: (object: BoardObject) => void;\r\n\tonObjectUpdated?: (object: BoardObject) => void;\r\n\tonObjectDeleted?: (objectId: string) => void;\r\n\tonUserJoined?: (userId: number, userName: string) => void;\r\n\tonUserLeft?: (userId: number, userName: string) => void;\r\n\tonError?: (error: Error, context?: any) => void;\r\n}\r\n\r\nexport interface BoardWebSocketService {\r\n\tconnect(boardId: string | number, userId: number, userName: string): void;\r\n\tdisconnect(): void;\r\n\tisConnected(): boolean;\r\n\r\n\tcreateObject(object: BoardObject): void;\r\n\tupdateObject(object: BoardObject): void;\r\n\tdeleteObject(objectId: string): void;\r\n\r\n\tlockObject(objectId: string): void;\r\n\tunlockObject(objectId: string): void;\r\n\r\n\tsetEventHandlers(handlers: BoardEventHandlers): void;\r\n}\r\n\r\nexport abstract class BaseWebSocketAdapter implements BoardWebSocketService {\r\n\tprotected handlers: BoardEventHandlers = {};\r\n\tprotected connected = false;\r\n\r\n\tabstract connect(\r\n\t\tboardId: string | number,\r\n\t\tuserId: number,\r\n\t\tuserName: string,\r\n\t): void;\r\n\tabstract disconnect(): void;\r\n\tabstract createObject(object: BoardObject): void;\r\n\tabstract updateObject(object: BoardObject): void;\r\n\tabstract deleteObject(objectId: string): void;\r\n\tabstract lockObject(objectId: string): void;\r\n\tabstract unlockObject(objectId: string): void;\r\n\r\n\tisConnected(): boolean {\r\n\t\treturn this.connected;\r\n\t}\r\n\r\n\tsetEventHandlers(handlers: BoardEventHandlers): void {\r\n\t\tthis.handlers = handlers;\r\n\t}\r\n\r\n\tprotected handleError(error: Error, context?: any): void {\r\n\t\tconsole.error('[BoardWebSocket]', error, context);\r\n\t\tthis.handlers.onError?.(error, context);\r\n\t}\r\n}\r\n","import { BoardObject } from '../types/board';\r\nimport { BaseWebSocketAdapter } from '../types/websocket';\r\n\r\ninterface WebSocketMessage {\r\n\ttype: string;\r\n\tpayload: any;\r\n\trequestId?: string;\r\n}\r\n\r\nexport class NativeWebSocketAdapter extends BaseWebSocketAdapter {\r\n\tprivate ws: WebSocket | null = null;\r\n\tprivate url: string;\r\n\tprivate reconnectAttempts = 0;\r\n\tprivate maxReconnectAttempts = 5;\r\n\tprivate reconnectTimeout = 1000;\r\n\r\n\tconstructor(url: string) {\r\n\t\tsuper();\r\n\t\tthis.url = url;\r\n\t}\r\n\r\n\tconnect(boardId: string | number, userId: number, userName: string): void {\r\n\t\ttry {\r\n\t\t\tconst wsUrl = new URL(this.url);\r\n\t\t\twsUrl.searchParams.append('boardId', String(boardId));\r\n\t\t\twsUrl.searchParams.append('userId', String(userId));\r\n\t\t\twsUrl.searchParams.append('userName', userName);\r\n\r\n\t\t\tthis.ws = new WebSocket(wsUrl.toString());\r\n\r\n\t\t\tthis.ws.onopen = () => {\r\n\t\t\t\tthis.connected = true;\r\n\t\t\t\tthis.reconnectAttempts = 0;\r\n\t\t\t\tthis.handlers.onConnectionChange?.(true);\r\n\t\t\t};\r\n\r\n\t\t\tthis.ws.onclose = () => {\r\n\t\t\t\tthis.connected = false;\r\n\t\t\t\tthis.handlers.onConnectionChange?.(false);\r\n\t\t\t\tthis.attemptReconnect(boardId, userId, userName);\r\n\t\t\t};\r\n\r\n\t\t\tthis.ws.onerror = () => {\r\n\t\t\t\tthis.handleError(new Error('WebSocket error'));\r\n\t\t\t};\r\n\r\n\t\t\tthis.ws.onmessage = event => {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tconst message: WebSocketMessage = JSON.parse(event.data);\r\n\t\t\t\t\tthis.handleMessage(message);\r\n\t\t\t\t} catch (error) {\r\n\t\t\t\t\tthis.handleError(error as Error);\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t} catch (error) {\r\n\t\t\tthis.handleError(error as Error);\r\n\t\t}\r\n\t}\r\n\r\n\tprivate attemptReconnect(\r\n\t\tboardId: string | number,\r\n\t\tuserId: number,\r\n\t\tuserName: string,\r\n\t): void {\r\n\t\tif (this.reconnectAttempts >= this.maxReconnectAttempts) {\r\n\t\t\tthis.handleError(new Error('Max reconnection attempts reached'));\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tthis.reconnectAttempts++;\r\n\t\tsetTimeout(() => {\r\n\t\t\tthis.connect(boardId, userId, userName);\r\n\t\t}, this.reconnectTimeout * this.reconnectAttempts);\r\n\t}\r\n\r\n\tprivate handleMessage(message: WebSocketMessage): void {\r\n\t\tswitch (message.type) {\r\n\t\t\tcase 'OBJECT_LOCKED':\r\n\t\t\t\tthis.handlers.onObjectLocked?.(\r\n\t\t\t\t\tmessage.payload.objectId,\r\n\t\t\t\t\tmessage.payload.userId,\r\n\t\t\t\t\tmessage.payload.userName,\r\n\t\t\t\t);\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'OBJECT_UNLOCKED':\r\n\t\t\t\tthis.handlers.onObjectUnlocked?.(message.payload.objectId);\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'OBJECT_CREATED':\r\n\t\t\t\tthis.handlers.onObjectCreated?.(message.payload);\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'OBJECT_UPDATED':\r\n\t\t\t\tthis.handlers.onObjectUpdated?.(message.payload);\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'OBJECT_DELETED':\r\n\t\t\t\tthis.handlers.onObjectDeleted?.(message.payload.objectId);\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'USER_JOINED':\r\n\t\t\t\tthis.handlers.onUserJoined?.(\r\n\t\t\t\t\tmessage.payload.userId,\r\n\t\t\t\t\tmessage.payload.userName,\r\n\t\t\t\t);\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'USER_LEFT':\r\n\t\t\t\tthis.handlers.onUserLeft?.(\r\n\t\t\t\t\tmessage.payload.userId,\r\n\t\t\t\t\tmessage.payload.userName,\r\n\t\t\t\t);\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tdisconnect(): void {\r\n\t\tif (this.ws) {\r\n\t\t\tthis.ws.close();\r\n\t\t\tthis.ws = null;\r\n\t\t\tthis.connected = false;\r\n\t\t}\r\n\t}\r\n\r\n\tprivate send(message: WebSocketMessage): void {\r\n\t\tif (this.ws?.readyState === WebSocket.OPEN) {\r\n\t\t\tthis.ws.send(JSON.stringify(message));\r\n\t\t}\r\n\t}\r\n\r\n\tcreateObject(object: BoardObject): void {\r\n\t\tthis.send({ type: 'OBJECT_CREATE', payload: object });\r\n\t}\r\n\r\n\tupdateObject(object: BoardObject): void {\r\n\t\tthis.send({ type: 'OBJECT_UPDATE', payload: object });\r\n\t}\r\n\r\n\tdeleteObject(objectId: string): void {\r\n\t\tthis.send({ type: 'OBJECT_DELETE', payload: { objectId } });\r\n\t}\r\n\r\n\tlockObject(objectId: string): void {\r\n\t\tthis.send({ type: 'OBJECT_LOCK', payload: { objectId } });\r\n\t}\r\n\r\n\tunlockObject(objectId: string): void {\r\n\t\tthis.send({ type: 'OBJECT_UNLOCK', payload: { objectId } });\r\n\t}\r\n}\r\n","import { io, Socket } from 'socket.io-client';\r\nimport { BoardObject } from '../types/board';\r\nimport { BaseWebSocketAdapter } from '../types/websocket';\r\n\r\nexport interface SocketIOAdapterConfig {\r\n\turl: string;\r\n\tpath?: string;\r\n\ttransports?: string[];\r\n\treconnection?: boolean;\r\n\treconnectionAttempts?: number;\r\n\treconnectionDelay?: number;\r\n}\r\n\r\nexport class SocketIOBoardAdapter extends BaseWebSocketAdapter {\r\n\tprivate socket: Socket | null = null;\r\n\tprivate config: SocketIOAdapterConfig;\r\n\r\n\tconstructor(config: SocketIOAdapterConfig) {\r\n\t\tsuper();\r\n\t\tthis.config = {\r\n\t\t\treconnection: true,\r\n\t\t\treconnectionAttempts: 5,\r\n\t\t\treconnectionDelay: 1000,\r\n\t\t\ttransports: ['websocket'],\r\n\t\t\t...config,\r\n\t\t};\r\n\t}\r\n\r\n\tconnect(boardId: string | number, userId: number, userName: string): void {\r\n\t\ttry {\r\n\t\t\tthis.socket = io(this.config.url, {\r\n\t\t\t\t...this.config,\r\n\t\t\t\tquery: { boardId, userId, userName },\r\n\t\t\t});\r\n\r\n\t\t\tthis.socket.on('connect', () => {\r\n\t\t\t\tthis.connected = true;\r\n\t\t\t\tthis.handlers.onConnectionChange?.(true);\r\n\t\t\t});\r\n\r\n\t\t\tthis.socket.on('disconnect', () => {\r\n\t\t\t\tthis.connected = false;\r\n\t\t\t\tthis.handlers.onConnectionChange?.(false);\r\n\t\t\t});\r\n\r\n\t\t\tthis.socket.on('error', error => {\r\n\t\t\t\tthis.handleError(new Error(error.message || 'Socket.IO error'));\r\n\t\t\t});\r\n\r\n\t\t\tthis.socket.on('object:locked', data => {\r\n\t\t\t\tthis.handlers.onObjectLocked?.(\r\n\t\t\t\t\tdata.objectId,\r\n\t\t\t\t\tdata.userId,\r\n\t\t\t\t\tdata.userName,\r\n\t\t\t\t);\r\n\t\t\t});\r\n\r\n\t\t\tthis.socket.on('object:unlocked', objectId => {\r\n\t\t\t\tthis.handlers.onObjectUnlocked?.(objectId);\r\n\t\t\t});\r\n\r\n\t\t\tthis.socket.on('object:created', object => {\r\n\t\t\t\tthis.handlers.onObjectCreated?.(object);\r\n\t\t\t});\r\n\r\n\t\t\tthis.socket.on('object:updated', object => {\r\n\t\t\t\tthis.handlers.onObjectUpdated?.(object);\r\n\t\t\t});\r\n\r\n\t\t\tthis.socket.on('object:deleted', objectId => {\r\n\t\t\t\tthis.handlers.onObjectDeleted?.(objectId);\r\n\t\t\t});\r\n\r\n\t\t\tthis.socket.on('user:joined', ({ userId, userName }) => {\r\n\t\t\t\tthis.handlers.onUserJoined?.(userId, userName);\r\n\t\t\t});\r\n\r\n\t\t\tthis.socket.on('user:left', ({ userId, userName }) => {\r\n\t\t\t\tthis.handlers.onUserLeft?.(userId, userName);\r\n\t\t\t});\r\n\t\t} catch (error) {\r\n\t\t\tthis.handleError(error as Error);\r\n\t\t}\r\n\t}\r\n\r\n\tdisconnect(): void {\r\n\t\tif (this.socket) {\r\n\t\t\tthis.socket.disconnect();\r\n\t\t\tthis.socket = null;\r\n\t\t\tthis.connected = false;\r\n\t\t}\r\n\t}\r\n\r\n\tcreateObject(object: BoardObject): void {\r\n\t\tthis.socket?.emit('object:create', object);\r\n\t}\r\n\r\n\tupdateObject(object: BoardObject): void {\r\n\t\tthis.socket?.emit('object:update', object);\r\n\t}\r\n\r\n\tdeleteObject(objectId: string): void {\r\n\t\tthis.socket?.emit('object:delete', objectId);\r\n\t}\r\n\r\n\tlockObject(objectId: string): void {\r\n\t\tthis.socket?.emit('object:lock', objectId);\r\n\t}\r\n\r\n\tunlockObject(objectId: string): void {\r\n\t\tthis.socket?.emit('object:unlock', objectId);\r\n\t}\r\n}\r\n","// Хук\r\nexport { useBoardDrawing } from './hooks/useBoardDrawing';\r\nexport type { UseBoardDrawingProps } from './hooks/useBoardDrawing';\r\n\r\n// Адаптеры\r\nexport { NativeWebSocketAdapter, SocketIOBoardAdapter } from './adapters';\r\nexport type { SocketIOAdapterConfig } from './adapters/socket-io-adapter';\r\n\r\n// Типы\r\nexport * from './types/board';\r\nexport * from './types/websocket';\r\n\r\n// Версия\r\nexport const VERSION = '1.0.0';\r\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-board-drawing-hook",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "🎨 Collaborative canvas drawing React hook with WebSocket support. Perfect for whiteboards, drawing apps, and real-time collaboration.",
|
|
5
|
+
"author": "Your Name <abeqirenume21@gmail.com>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/Joy/react-board-drawing-hook.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/Joy/react-board-drawing-hook#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Joy/react-board-drawing-hook/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"react",
|
|
17
|
+
"hook",
|
|
18
|
+
"canvas",
|
|
19
|
+
"drawing",
|
|
20
|
+
"whiteboard",
|
|
21
|
+
"collaborative",
|
|
22
|
+
"websocket",
|
|
23
|
+
"socket.io",
|
|
24
|
+
"real-time",
|
|
25
|
+
"typescript",
|
|
26
|
+
"board",
|
|
27
|
+
"draw",
|
|
28
|
+
"paint"
|
|
29
|
+
],
|
|
30
|
+
"main": "dist/index.js",
|
|
31
|
+
"module": "dist/index.mjs",
|
|
32
|
+
"types": "dist/index.d.ts",
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"README.md",
|
|
36
|
+
"LICENSE"
|
|
37
|
+
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsup",
|
|
40
|
+
"dev": "tsup --watch",
|
|
41
|
+
"clean": "rm -rf dist",
|
|
42
|
+
"type-check": "tsc --noEmit",
|
|
43
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
44
|
+
"test": "echo \"No tests yet\" && exit 0",
|
|
45
|
+
"preversion": "npm run clean && npm run build",
|
|
46
|
+
"version": "git add -A",
|
|
47
|
+
"postversion": "git push && git push --tags"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"react": ">=16.8.0",
|
|
51
|
+
"react-dom": ">=16.8.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@testing-library/react": "^14.0.0",
|
|
55
|
+
"@types/jest": "^29.5.0",
|
|
56
|
+
"@types/react": "^18.2.0",
|
|
57
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
58
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
59
|
+
"eslint": "^8.0.0",
|
|
60
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
61
|
+
"jest": "^29.5.0",
|
|
62
|
+
"jest-environment-jsdom": "^29.5.0",
|
|
63
|
+
"prettier": "^3.0.0",
|
|
64
|
+
"react": "^18.2.0",
|
|
65
|
+
"react-dom": "^18.2.0",
|
|
66
|
+
"socket.io-client": "^4.6.0",
|
|
67
|
+
"ts-jest": "^29.1.0",
|
|
68
|
+
"tsup": "^7.0.0",
|
|
69
|
+
"typescript": "^5.0.0"
|
|
70
|
+
},
|
|
71
|
+
"peerDependenciesMeta": {
|
|
72
|
+
"socket.io-client": {
|
|
73
|
+
"optional": true
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|