@fieldnotes/core 0.2.2 → 0.2.3
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/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +18 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/event-bus.ts","../src/core/state-serializer.ts","../src/core/auto-save.ts","../src/canvas/camera.ts","../src/canvas/background.ts","../src/canvas/input-handler.ts","../src/elements/element-store.ts","../src/elements/arrow-geometry.ts","../src/elements/stroke-smoothing.ts","../src/elements/element-renderer.ts","../src/elements/note-editor.ts","../src/tools/tool-manager.ts","../src/history/history-stack.ts","../src/history/commands.ts","../src/history/history-recorder.ts","../src/elements/create-id.ts","../src/elements/element-factory.ts","../src/canvas/viewport.ts","../src/tools/hand-tool.ts","../src/tools/pencil-tool.ts","../src/tools/eraser-tool.ts","../src/tools/arrow-handles.ts","../src/tools/select-tool.ts","../src/tools/arrow-tool.ts","../src/tools/note-tool.ts","../src/tools/image-tool.ts","../src/index.ts"],"sourcesContent":["type Listener<T> = (data: T) => void;\n\nexport class EventBus<TEvents extends { [K in keyof TEvents]: TEvents[K] }> {\n private listeners = new Map<keyof TEvents, Set<Listener<never>>>();\n\n on<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): () => void {\n const existing = this.listeners.get(event);\n if (existing) {\n existing.add(listener as Listener<never>);\n } else {\n const set = new Set<Listener<never>>([listener as Listener<never>]);\n this.listeners.set(event, set);\n }\n return () => this.off(event, listener);\n }\n\n off<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): void {\n this.listeners.get(event)?.delete(listener as Listener<never>);\n }\n\n emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void {\n this.listeners.get(event)?.forEach((listener) => listener(data as never));\n }\n\n clear(): void {\n this.listeners.clear();\n }\n}\n","import type { CanvasElement } from '../elements/types';\r\nimport type { Point } from './types';\r\n\r\nexport interface CanvasState {\r\n version: number;\r\n camera: {\r\n position: Point;\r\n zoom: number;\r\n };\r\n elements: CanvasElement[];\r\n}\r\n\r\nconst CURRENT_VERSION = 1;\r\n\r\nexport function exportState(\r\n elements: CanvasElement[],\r\n camera: { position: Point; zoom: number },\r\n): CanvasState {\r\n return {\r\n version: CURRENT_VERSION,\r\n camera: {\r\n position: { ...camera.position },\r\n zoom: camera.zoom,\r\n },\r\n elements: elements.map((el) => structuredClone(el)),\r\n };\r\n}\r\n\r\nexport function parseState(json: string): CanvasState {\r\n const data: unknown = JSON.parse(json);\r\n validateState(data);\r\n return data;\r\n}\r\n\r\nfunction validateState(data: unknown): asserts data is CanvasState {\r\n if (!data || typeof data !== 'object') {\r\n throw new Error('Invalid state: expected an object');\r\n }\r\n\r\n const obj = data as Record<string, unknown>;\r\n\r\n if (typeof obj['version'] !== 'number') {\r\n throw new Error('Invalid state: missing or invalid version');\r\n }\r\n\r\n if (!obj['camera'] || typeof obj['camera'] !== 'object') {\r\n throw new Error('Invalid state: missing camera');\r\n }\r\n\r\n const cam = obj['camera'] as Record<string, unknown>;\r\n if (!cam['position'] || typeof cam['position'] !== 'object') {\r\n throw new Error('Invalid state: missing camera.position');\r\n }\r\n\r\n const pos = cam['position'] as Record<string, unknown>;\r\n if (typeof pos['x'] !== 'number' || typeof pos['y'] !== 'number') {\r\n throw new Error('Invalid state: camera.position must have x and y numbers');\r\n }\r\n\r\n if (typeof cam['zoom'] !== 'number') {\r\n throw new Error('Invalid state: missing camera.zoom');\r\n }\r\n\r\n if (!Array.isArray(obj['elements'])) {\r\n throw new Error('Invalid state: elements must be an array');\r\n }\r\n\r\n for (const el of obj['elements'] as unknown[]) {\r\n validateElement(el);\r\n migrateElement(el as unknown as Record<string, unknown>);\r\n }\r\n}\r\n\r\nconst VALID_TYPES = new Set(['stroke', 'note', 'arrow', 'image', 'html']);\r\n\r\nfunction validateElement(el: unknown): asserts el is CanvasElement {\r\n if (!el || typeof el !== 'object') {\r\n throw new Error('Invalid element: expected an object');\r\n }\r\n\r\n const obj = el as Record<string, unknown>;\r\n\r\n if (typeof obj['id'] !== 'string') {\r\n throw new Error('Invalid element: missing id');\r\n }\r\n\r\n if (typeof obj['type'] !== 'string' || !VALID_TYPES.has(obj['type'])) {\r\n throw new Error(`Invalid element: unknown type \"${String(obj['type'])}\"`);\r\n }\r\n\r\n if (typeof obj['zIndex'] !== 'number') {\r\n throw new Error('Invalid element: missing zIndex');\r\n }\r\n}\r\n\r\nfunction migrateElement(obj: Record<string, unknown>): void {\r\n if (obj['type'] === 'arrow' && typeof obj['bend'] !== 'number') {\r\n obj['bend'] = 0;\r\n }\r\n\r\n if (obj['type'] === 'stroke' && Array.isArray(obj['points'])) {\r\n for (const pt of obj['points'] as Record<string, unknown>[]) {\r\n if (typeof pt['pressure'] !== 'number') {\r\n pt['pressure'] = 0.5;\r\n }\r\n }\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { Camera } from '../canvas/camera';\r\nimport { exportState, parseState } from './state-serializer';\r\nimport type { CanvasState } from './state-serializer';\r\n\r\nexport interface AutoSaveOptions {\r\n key?: string;\r\n debounceMs?: number;\r\n}\r\n\r\nconst DEFAULT_KEY = 'fieldnotes-autosave';\r\nconst DEFAULT_DEBOUNCE_MS = 1000;\r\n\r\nexport class AutoSave {\r\n private readonly key: string;\r\n private readonly debounceMs: number;\r\n private timerId: ReturnType<typeof setTimeout> | null = null;\r\n private unsubscribers: (() => void)[] = [];\r\n\r\n constructor(\r\n private readonly store: ElementStore,\r\n private readonly camera: Camera,\r\n options: AutoSaveOptions = {},\r\n ) {\r\n this.key = options.key ?? DEFAULT_KEY;\r\n this.debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\r\n }\r\n\r\n start(): void {\r\n const schedule = () => this.scheduleSave();\r\n\r\n this.unsubscribers = [\r\n this.store.on('add', schedule),\r\n this.store.on('remove', schedule),\r\n this.store.on('update', schedule),\r\n this.camera.onChange(schedule),\r\n ];\r\n }\r\n\r\n stop(): void {\r\n this.cancelPending();\r\n this.unsubscribers.forEach((fn) => fn());\r\n this.unsubscribers = [];\r\n }\r\n\r\n load(): CanvasState | null {\r\n if (typeof localStorage === 'undefined') return null;\r\n\r\n const json = localStorage.getItem(this.key);\r\n if (!json) return null;\r\n\r\n try {\r\n return parseState(json);\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n clear(): void {\r\n if (typeof localStorage === 'undefined') return;\r\n localStorage.removeItem(this.key);\r\n }\r\n\r\n private scheduleSave(): void {\r\n this.cancelPending();\r\n this.timerId = setTimeout(() => this.save(), this.debounceMs);\r\n }\r\n\r\n private cancelPending(): void {\r\n if (this.timerId !== null) {\r\n clearTimeout(this.timerId);\r\n this.timerId = null;\r\n }\r\n }\r\n\r\n private save(): void {\r\n if (typeof localStorage === 'undefined') return;\r\n\r\n const state = exportState(this.store.snapshot(), this.camera);\r\n localStorage.setItem(this.key, JSON.stringify(state));\r\n }\r\n}\r\n","import type { Point } from '../core/types';\n\nexport interface CameraOptions {\n minZoom?: number;\n maxZoom?: number;\n}\n\nconst DEFAULT_MIN_ZOOM = 0.1;\nconst DEFAULT_MAX_ZOOM = 10;\n\nexport class Camera {\n private x = 0;\n private y = 0;\n private z = 1;\n private readonly minZoom: number;\n private readonly maxZoom: number;\n private changeListeners = new Set<() => void>();\n\n constructor(options: CameraOptions = {}) {\n this.minZoom = options.minZoom ?? DEFAULT_MIN_ZOOM;\n this.maxZoom = options.maxZoom ?? DEFAULT_MAX_ZOOM;\n }\n\n get position(): Point {\n return { x: this.x, y: this.y };\n }\n\n get zoom(): number {\n return this.z;\n }\n\n pan(dx: number, dy: number): void {\n this.x += dx;\n this.y += dy;\n this.notifyChange();\n }\n\n moveTo(x: number, y: number): void {\n this.x = x;\n this.y = y;\n this.notifyChange();\n }\n\n setZoom(level: number): void {\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, level));\n this.notifyChange();\n }\n\n zoomAt(level: number, screenPoint: Point): void {\n const before = this.screenToWorld(screenPoint);\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, level));\n const after = this.screenToWorld(screenPoint);\n this.x += (after.x - before.x) * this.z;\n this.y += (after.y - before.y) * this.z;\n this.notifyChange();\n }\n\n screenToWorld(screen: Point): Point {\n return {\n x: (screen.x - this.x) / this.z,\n y: (screen.y - this.y) / this.z,\n };\n }\n\n worldToScreen(world: Point): Point {\n return {\n x: world.x * this.z + this.x,\n y: world.y * this.z + this.y,\n };\n }\n\n toCSSTransform(): string {\n return `translate3d(${this.x}px, ${this.y}px, 0) scale(${this.z})`;\n }\n\n onChange(listener: () => void): () => void {\n this.changeListeners.add(listener);\n return () => this.changeListeners.delete(listener);\n }\n\n private notifyChange(): void {\n this.changeListeners.forEach((fn) => fn());\n }\n}\n","import type { Camera } from './camera';\r\n\r\nexport type BackgroundPattern = 'dots' | 'grid' | 'none';\r\n\r\nexport interface BackgroundOptions {\r\n pattern?: BackgroundPattern;\r\n spacing?: number;\r\n color?: string;\r\n dotRadius?: number;\r\n lineWidth?: number;\r\n}\r\n\r\nconst MIN_PATTERN_SPACING = 16;\r\n\r\nconst DEFAULTS = {\r\n pattern: 'dots' as BackgroundPattern,\r\n spacing: 24,\r\n color: '#d0d0d0',\r\n dotRadius: 1,\r\n lineWidth: 0.5,\r\n};\r\n\r\nexport class Background {\r\n private readonly pattern: BackgroundPattern;\r\n private readonly spacing: number;\r\n private readonly color: string;\r\n private readonly dotRadius: number;\r\n private readonly lineWidth: number;\r\n\r\n constructor(options: BackgroundOptions = {}) {\r\n this.pattern = options.pattern ?? DEFAULTS.pattern;\r\n this.spacing = options.spacing ?? DEFAULTS.spacing;\r\n this.color = options.color ?? DEFAULTS.color;\r\n this.dotRadius = options.dotRadius ?? DEFAULTS.dotRadius;\r\n this.lineWidth = options.lineWidth ?? DEFAULTS.lineWidth;\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, camera: Camera): void {\r\n const { width, height } = ctx.canvas;\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n const cssWidth = width / dpr;\r\n const cssHeight = height / dpr;\r\n ctx.save();\r\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n ctx.clearRect(0, 0, cssWidth, cssHeight);\r\n\r\n if (this.pattern === 'dots') {\r\n this.renderDots(ctx, camera, cssWidth, cssHeight);\r\n } else if (this.pattern === 'grid') {\r\n this.renderGrid(ctx, camera, cssWidth, cssHeight);\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private adaptSpacing(baseSpacing: number, zoom: number): number {\r\n let spacing = baseSpacing * zoom;\r\n while (spacing < MIN_PATTERN_SPACING) {\r\n spacing *= 2;\r\n }\r\n return spacing;\r\n }\r\n\r\n private renderDots(\r\n ctx: CanvasRenderingContext2D,\r\n camera: Camera,\r\n width: number,\r\n height: number,\r\n ): void {\r\n const spacing = this.adaptSpacing(this.spacing, camera.zoom);\r\n const offsetX = camera.position.x % spacing;\r\n const offsetY = camera.position.y % spacing;\r\n const radius = this.dotRadius * Math.min(camera.zoom, 2);\r\n\r\n ctx.fillStyle = this.color;\r\n ctx.beginPath();\r\n\r\n for (let x = offsetX; x < width; x += spacing) {\r\n for (let y = offsetY; y < height; y += spacing) {\r\n ctx.moveTo(x + radius, y);\r\n ctx.arc(x, y, radius, 0, Math.PI * 2);\r\n }\r\n }\r\n\r\n ctx.fill();\r\n }\r\n\r\n private renderGrid(\r\n ctx: CanvasRenderingContext2D,\r\n camera: Camera,\r\n width: number,\r\n height: number,\r\n ): void {\r\n const spacing = this.adaptSpacing(this.spacing, camera.zoom);\r\n const offsetX = camera.position.x % spacing;\r\n const offsetY = camera.position.y % spacing;\r\n const lineW = this.lineWidth * Math.min(camera.zoom, 2);\r\n\r\n ctx.fillStyle = this.color;\r\n\r\n for (let x = offsetX; x < width; x += spacing) {\r\n ctx.fillRect(x, 0, lineW, height);\r\n }\r\n\r\n for (let y = offsetY; y < height; y += spacing) {\r\n ctx.fillRect(0, y, width, lineW);\r\n }\r\n }\r\n}\r\n","import type { Camera } from './camera';\r\nimport type { ToolManager } from '../tools/tool-manager';\r\nimport type { ToolContext, PointerState } from '../tools/types';\r\nimport type { SelectTool } from '../tools/select-tool';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport type { HistoryStack } from '../history/history-stack';\r\n\r\nconst ZOOM_SENSITIVITY = 0.001;\r\nconst MIDDLE_BUTTON = 1;\r\n\r\nexport interface InputHandlerOptions {\r\n toolManager?: ToolManager;\r\n toolContext?: ToolContext;\r\n historyRecorder?: HistoryRecorder;\r\n historyStack?: HistoryStack;\r\n}\r\n\r\nexport class InputHandler {\r\n private isPanning = false;\r\n private lastPointer = { x: 0, y: 0 };\r\n private spaceHeld = false;\r\n private activePointers = new Map<number, { x: number; y: number }>();\r\n private lastPinchDistance = 0;\r\n private lastPinchCenter = { x: 0, y: 0 };\r\n private toolManager: ToolManager | null;\r\n private toolContext: ToolContext | null;\r\n private historyRecorder: HistoryRecorder | null;\r\n private historyStack: HistoryStack | null;\r\n private isToolActive = false;\r\n private readonly abortController = new AbortController();\r\n\r\n constructor(\r\n private readonly element: HTMLElement,\r\n private readonly camera: Camera,\r\n options: InputHandlerOptions = {},\r\n ) {\r\n this.toolManager = options.toolManager ?? null;\r\n this.toolContext = options.toolContext ?? null;\r\n this.historyRecorder = options.historyRecorder ?? null;\r\n this.historyStack = options.historyStack ?? null;\r\n this.element.style.touchAction = 'none';\r\n this.bind();\r\n }\r\n\r\n setToolManager(toolManager: ToolManager, toolContext: ToolContext): void {\r\n this.toolManager = toolManager;\r\n this.toolContext = toolContext;\r\n }\r\n\r\n destroy(): void {\r\n this.abortController.abort();\r\n }\r\n\r\n private bind(): void {\r\n const opts = { signal: this.abortController.signal };\r\n\r\n this.element.addEventListener('wheel', this.onWheel, { ...opts, passive: false });\r\n this.element.addEventListener('pointerdown', this.onPointerDown, opts);\r\n this.element.addEventListener('pointermove', this.onPointerMove, opts);\r\n this.element.addEventListener('pointerup', this.onPointerUp, opts);\r\n this.element.addEventListener('pointerleave', this.onPointerUp, opts);\r\n this.element.addEventListener('pointercancel', this.onPointerUp, opts);\r\n window.addEventListener('keydown', this.onKeyDown, opts);\r\n window.addEventListener('keyup', this.onKeyUp, opts);\r\n }\r\n\r\n private onWheel = (e: WheelEvent): void => {\r\n e.preventDefault();\r\n const rect = this.element.getBoundingClientRect();\r\n const zoomFactor = 1 - e.deltaY * ZOOM_SENSITIVITY;\r\n const newZoom = this.camera.zoom * zoomFactor;\r\n this.camera.zoomAt(newZoom, {\r\n x: e.clientX - rect.left,\r\n y: e.clientY - rect.top,\r\n });\r\n };\r\n\r\n private onPointerDown = (e: PointerEvent): void => {\r\n this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });\r\n\r\n this.element.setPointerCapture?.(e.pointerId);\r\n\r\n if (this.activePointers.size === 2) {\r\n this.startPinch();\r\n this.cancelToolIfActive(e);\r\n return;\r\n }\r\n\r\n if (e.button === MIDDLE_BUTTON || (e.button === 0 && this.spaceHeld)) {\r\n this.isPanning = true;\r\n this.lastPointer = { x: e.clientX, y: e.clientY };\r\n return;\r\n }\r\n\r\n if (this.activePointers.size === 1 && e.button === 0) {\r\n this.dispatchToolDown(e);\r\n }\r\n };\r\n\r\n private onPointerMove = (e: PointerEvent): void => {\r\n if (this.activePointers.has(e.pointerId)) {\r\n this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });\r\n }\r\n\r\n if (this.activePointers.size === 2) {\r\n this.handlePinchMove();\r\n return;\r\n }\r\n\r\n if (this.isPanning) {\r\n const dx = e.clientX - this.lastPointer.x;\r\n const dy = e.clientY - this.lastPointer.y;\r\n this.lastPointer = { x: e.clientX, y: e.clientY };\r\n this.camera.pan(dx, dy);\r\n return;\r\n }\r\n\r\n if (this.isToolActive) {\r\n this.dispatchToolMove(e);\r\n } else if (this.activePointers.size === 0) {\r\n this.dispatchToolHover(e);\r\n }\r\n };\r\n\r\n private onPointerUp = (e: PointerEvent): void => {\r\n this.activePointers.delete(e.pointerId);\r\n\r\n if (this.activePointers.size < 2) {\r\n this.lastPinchDistance = 0;\r\n }\r\n\r\n if (this.isPanning && this.activePointers.size === 0) {\r\n this.isPanning = false;\r\n }\r\n\r\n if (this.isToolActive) {\r\n this.dispatchToolUp(e);\r\n this.isToolActive = false;\r\n }\r\n };\r\n\r\n private onKeyDown = (e: KeyboardEvent): void => {\r\n if ((e.target as HTMLElement)?.isContentEditable) return;\r\n\r\n if (e.key === ' ') {\r\n this.spaceHeld = true;\r\n }\r\n if (e.key === 'Delete' || e.key === 'Backspace') {\r\n this.deleteSelected();\r\n }\r\n if ((e.ctrlKey || e.metaKey) && e.key === 'z' && !e.shiftKey) {\r\n e.preventDefault();\r\n this.handleUndo();\r\n }\r\n if ((e.ctrlKey || e.metaKey) && (e.key === 'y' || (e.key === 'z' && e.shiftKey))) {\r\n e.preventDefault();\r\n this.handleRedo();\r\n }\r\n };\r\n\r\n private onKeyUp = (e: KeyboardEvent): void => {\r\n if (e.key === ' ') {\r\n this.spaceHeld = false;\r\n }\r\n };\r\n\r\n private startPinch(): void {\r\n this.isPanning = true;\r\n const [a, b] = this.getPinchPoints();\r\n this.lastPinchDistance = this.distance(a, b);\r\n this.lastPinchCenter = this.midpoint(a, b);\r\n this.lastPointer = { ...this.lastPinchCenter };\r\n }\r\n\r\n private handlePinchMove(): void {\r\n const [a, b] = this.getPinchPoints();\r\n const dist = this.distance(a, b);\r\n const center = this.midpoint(a, b);\r\n\r\n if (this.lastPinchDistance > 0) {\r\n const scale = dist / this.lastPinchDistance;\r\n const newZoom = this.camera.zoom * scale;\r\n this.camera.zoomAt(newZoom, center);\r\n }\r\n\r\n const dx = center.x - this.lastPointer.x;\r\n const dy = center.y - this.lastPointer.y;\r\n this.camera.pan(dx, dy);\r\n\r\n this.lastPinchDistance = dist;\r\n this.lastPinchCenter = center;\r\n this.lastPointer = { ...center };\r\n }\r\n\r\n private getPinchPoints(): [{ x: number; y: number }, { x: number; y: number }] {\r\n const pts = [...this.activePointers.values()];\r\n return [pts[0] ?? { x: 0, y: 0 }, pts[1] ?? { x: 0, y: 0 }];\r\n }\r\n\r\n private distance(a: { x: number; y: number }, b: { x: number; y: number }): number {\r\n const dx = a.x - b.x;\r\n const dy = a.y - b.y;\r\n return Math.sqrt(dx * dx + dy * dy);\r\n }\r\n\r\n private midpoint(\r\n a: { x: number; y: number },\r\n b: { x: number; y: number },\r\n ): { x: number; y: number } {\r\n return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\r\n }\r\n\r\n private toPointerState(e: PointerEvent): PointerState {\r\n const rect = this.element.getBoundingClientRect();\r\n return {\r\n x: e.clientX - rect.left,\r\n y: e.clientY - rect.top,\r\n pressure: e.pressure,\r\n };\r\n }\r\n\r\n private dispatchToolDown(e: PointerEvent): void {\r\n if (!this.toolManager || !this.toolContext) return;\r\n this.historyRecorder?.begin();\r\n this.isToolActive = true;\r\n this.toolManager.handlePointerDown(this.toPointerState(e), this.toolContext);\r\n }\r\n\r\n private dispatchToolMove(e: PointerEvent): void {\r\n if (!this.toolManager || !this.toolContext) return;\r\n this.toolManager.handlePointerMove(this.toPointerState(e), this.toolContext);\r\n }\r\n\r\n private dispatchToolHover(e: PointerEvent): void {\r\n if (!this.toolManager?.activeTool || !this.toolContext) return;\r\n const tool = this.toolManager.activeTool;\r\n if (tool.onHover) {\r\n tool.onHover(this.toPointerState(e), this.toolContext);\r\n }\r\n }\r\n\r\n private dispatchToolUp(e: PointerEvent): void {\r\n if (!this.toolManager || !this.toolContext) return;\r\n this.toolManager.handlePointerUp(this.toPointerState(e), this.toolContext);\r\n this.historyRecorder?.commit();\r\n }\r\n\r\n private deleteSelected(): void {\r\n if (!this.toolManager || !this.toolContext) return;\r\n const tool = this.toolManager.activeTool;\r\n if (tool?.name !== 'select') return;\r\n const selectTool = tool as SelectTool;\r\n const ids = selectTool.selectedIds;\r\n if (ids.length === 0) return;\r\n this.historyRecorder?.begin();\r\n for (const id of ids) {\r\n this.toolContext.store.remove(id);\r\n }\r\n this.historyRecorder?.commit();\r\n this.toolContext.requestRender();\r\n }\r\n\r\n private handleUndo(): void {\r\n if (!this.historyStack || !this.toolContext) return;\r\n this.historyRecorder?.pause();\r\n this.historyStack.undo(this.toolContext.store);\r\n this.historyRecorder?.resume();\r\n this.toolContext.requestRender();\r\n }\r\n\r\n private handleRedo(): void {\r\n if (!this.historyStack || !this.toolContext) return;\r\n this.historyRecorder?.pause();\r\n this.historyStack.redo(this.toolContext.store);\r\n this.historyRecorder?.resume();\r\n this.toolContext.requestRender();\r\n }\r\n\r\n private cancelToolIfActive(e: PointerEvent): void {\r\n if (this.isToolActive) {\r\n this.dispatchToolUp(e);\r\n this.isToolActive = false;\r\n }\r\n }\r\n}\r\n","import { EventBus } from '../core/event-bus';\nimport type { CanvasElement, ElementType } from './types';\n\nexport interface ElementUpdateEvent {\n previous: CanvasElement;\n current: CanvasElement;\n}\n\ninterface ElementStoreEvents {\n add: CanvasElement;\n remove: CanvasElement;\n update: ElementUpdateEvent;\n clear: null;\n}\n\nexport class ElementStore {\n private elements = new Map<string, CanvasElement>();\n private bus = new EventBus<ElementStoreEvents>();\n\n get count(): number {\n return this.elements.size;\n }\n\n getAll(): CanvasElement[] {\n return [...this.elements.values()].sort((a, b) => a.zIndex - b.zIndex);\n }\n\n getById(id: string): CanvasElement | undefined {\n return this.elements.get(id);\n }\n\n getElementsByType<T extends ElementType>(type: T): Extract<CanvasElement, { type: T }>[] {\n return this.getAll().filter(\n (el): el is Extract<CanvasElement, { type: T }> => el.type === type,\n );\n }\n\n add(element: CanvasElement): void {\n this.elements.set(element.id, element);\n this.bus.emit('add', element);\n }\n\n update(id: string, partial: Partial<CanvasElement>): void {\n const existing = this.elements.get(id);\n if (!existing) return;\n\n const updated = { ...existing, ...partial, id: existing.id, type: existing.type };\n this.elements.set(id, updated as CanvasElement);\n this.bus.emit('update', { previous: existing, current: updated as CanvasElement });\n }\n\n remove(id: string): void {\n const element = this.elements.get(id);\n if (!element) return;\n\n this.elements.delete(id);\n this.bus.emit('remove', element);\n }\n\n clear(): void {\n this.elements.clear();\n this.bus.emit('clear', null);\n }\n\n snapshot(): CanvasElement[] {\n return this.getAll().map((el) => ({ ...el }));\n }\n\n loadSnapshot(elements: CanvasElement[]): void {\n this.elements.clear();\n for (const el of elements) {\n this.elements.set(el.id, el);\n }\n }\n\n on<K extends keyof ElementStoreEvents>(\n event: K,\n listener: (data: ElementStoreEvents[K]) => void,\n ): () => void {\n return this.bus.on(event, listener);\n }\n}\n","import type { Point } from '../core/types';\n\ninterface Rect {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport function getArrowControlPoint(from: Point, to: Point, bend: number): Point {\n const midX = (from.x + to.x) / 2;\n const midY = (from.y + to.y) / 2;\n\n if (bend === 0) return { x: midX, y: midY };\n\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const len = Math.sqrt(dx * dx + dy * dy);\n\n if (len === 0) return { x: midX, y: midY };\n\n const perpX = -dy / len;\n const perpY = dx / len;\n\n return {\n x: midX + perpX * bend,\n y: midY + perpY * bend,\n };\n}\n\nexport function getArrowMidpoint(from: Point, to: Point, bend: number): Point {\n const cp = getArrowControlPoint(from, to, bend);\n return {\n x: 0.25 * from.x + 0.5 * cp.x + 0.25 * to.x,\n y: 0.25 * from.y + 0.5 * cp.y + 0.25 * to.y,\n };\n}\n\nexport function getBendFromPoint(from: Point, to: Point, dragPoint: Point): number {\n const midX = (from.x + to.x) / 2;\n const midY = (from.y + to.y) / 2;\n\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const len = Math.sqrt(dx * dx + dy * dy);\n\n if (len === 0) return 0;\n\n const perpX = -dy / len;\n const perpY = dx / len;\n\n return (dragPoint.x - midX) * perpX + (dragPoint.y - midY) * perpY;\n}\n\nexport function getArrowTangentAngle(from: Point, to: Point, bend: number, t: number): number {\n const cp = getArrowControlPoint(from, to, bend);\n\n const tangentX = 2 * (1 - t) * (cp.x - from.x) + 2 * t * (to.x - cp.x);\n const tangentY = 2 * (1 - t) * (cp.y - from.y) + 2 * t * (to.y - cp.y);\n\n return Math.atan2(tangentY, tangentX);\n}\n\nexport function isNearBezier(\n point: Point,\n from: Point,\n to: Point,\n bend: number,\n threshold: number,\n): boolean {\n if (bend === 0) return isNearLine(point, from, to, threshold);\n\n const cp = getArrowControlPoint(from, to, bend);\n const segments = 20;\n\n for (let i = 0; i < segments; i++) {\n const t0 = i / segments;\n const t1 = (i + 1) / segments;\n const a = bezierPoint(from, cp, to, t0);\n const b = bezierPoint(from, cp, to, t1);\n if (isNearLine(point, a, b, threshold)) return true;\n }\n\n return false;\n}\n\nexport function getArrowBounds(from: Point, to: Point, bend: number): Rect {\n if (bend === 0) {\n const minX = Math.min(from.x, to.x);\n const minY = Math.min(from.y, to.y);\n return {\n x: minX,\n y: minY,\n w: Math.abs(to.x - from.x),\n h: Math.abs(to.y - from.y),\n };\n }\n\n const cp = getArrowControlPoint(from, to, bend);\n const steps = 20;\n let minX = Math.min(from.x, to.x);\n let minY = Math.min(from.y, to.y);\n let maxX = Math.max(from.x, to.x);\n let maxY = Math.max(from.y, to.y);\n\n for (let i = 1; i < steps; i++) {\n const t = i / steps;\n const p = bezierPoint(from, cp, to, t);\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\n}\n\nfunction bezierPoint(from: Point, cp: Point, to: Point, t: number): Point {\n const mt = 1 - t;\n return {\n x: mt * mt * from.x + 2 * mt * t * cp.x + t * t * to.x,\n y: mt * mt * from.y + 2 * mt * t * cp.y + t * t * to.y,\n };\n}\n\nfunction isNearLine(point: Point, a: Point, b: Point, threshold: number): boolean {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const lenSq = dx * dx + dy * dy;\n\n if (lenSq === 0) {\n return Math.hypot(point.x - a.x, point.y - a.y) <= threshold;\n }\n\n const t = Math.max(0, Math.min(1, ((point.x - a.x) * dx + (point.y - a.y) * dy) / lenSq));\n const projX = a.x + t * dx;\n const projY = a.y + t * dy;\n return Math.hypot(point.x - projX, point.y - projY) <= threshold;\n}\n","import type { Point, StrokePoint } from '../core/types';\r\n\r\nexport interface CurveSegment {\r\n start: StrokePoint;\r\n cp1: Point;\r\n cp2: Point;\r\n end: StrokePoint;\r\n}\r\n\r\nconst MIN_PRESSURE_SCALE = 0.2;\r\n\r\nexport function pressureToWidth(pressure: number, baseWidth: number): number {\r\n return baseWidth * (MIN_PRESSURE_SCALE + (1 - MIN_PRESSURE_SCALE) * pressure);\r\n}\r\n\r\nexport function simplifyPoints(points: StrokePoint[], tolerance: number): StrokePoint[] {\r\n if (points.length <= 2) return points.slice();\r\n return rdp(points, 0, points.length - 1, tolerance);\r\n}\r\n\r\nfunction rdp(points: StrokePoint[], start: number, end: number, tolerance: number): StrokePoint[] {\r\n const first = points[start];\r\n const last = points[end];\r\n if (!first || !last) return [];\r\n\r\n if (end - start <= 1) return [first, last];\r\n\r\n let maxDist = 0;\r\n let maxIndex = start;\r\n\r\n for (let i = start + 1; i < end; i++) {\r\n const pt = points[i];\r\n if (!pt) continue;\r\n const dist = perpendicularDistance(pt, first, last);\r\n if (dist > maxDist) {\r\n maxDist = dist;\r\n maxIndex = i;\r\n }\r\n }\r\n\r\n if (maxDist <= tolerance) return [first, last];\r\n\r\n const left = rdp(points, start, maxIndex, tolerance);\r\n const right = rdp(points, maxIndex, end, tolerance);\r\n\r\n return left.concat(right.slice(1));\r\n}\r\n\r\nfunction perpendicularDistance(pt: Point, lineStart: Point, lineEnd: Point): number {\r\n const dx = lineEnd.x - lineStart.x;\r\n const dy = lineEnd.y - lineStart.y;\r\n const lenSq = dx * dx + dy * dy;\r\n\r\n if (lenSq === 0) {\r\n const ex = pt.x - lineStart.x;\r\n const ey = pt.y - lineStart.y;\r\n return Math.sqrt(ex * ex + ey * ey);\r\n }\r\n\r\n const num = Math.abs(dy * pt.x - dx * pt.y + lineEnd.x * lineStart.y - lineEnd.y * lineStart.x);\r\n return num / Math.sqrt(lenSq);\r\n}\r\n\r\nexport function smoothToSegments(points: StrokePoint[]): CurveSegment[] {\r\n if (points.length < 2) return [];\r\n\r\n if (points.length === 2) {\r\n const p0 = points[0];\r\n const p1 = points[1];\r\n if (!p0 || !p1) return [];\r\n const mx = (p0.x + p1.x) / 2;\r\n const my = (p0.y + p1.y) / 2;\r\n return [{ start: p0, cp1: { x: mx, y: my }, cp2: { x: mx, y: my }, end: p1 }];\r\n }\r\n\r\n const segments: CurveSegment[] = [];\r\n const n = points.length;\r\n\r\n for (let i = 0; i < n - 1; i++) {\r\n const p0 = points[Math.max(0, i - 1)];\r\n const p1 = points[i];\r\n const p2 = points[i + 1];\r\n const p3 = points[Math.min(n - 1, i + 2)];\r\n if (!p0 || !p1 || !p2 || !p3) continue;\r\n\r\n const cp1: Point = {\r\n x: p1.x + (p2.x - p0.x) / 6,\r\n y: p1.y + (p2.y - p0.y) / 6,\r\n };\r\n const cp2: Point = {\r\n x: p2.x - (p3.x - p1.x) / 6,\r\n y: p2.y - (p3.y - p1.y) / 6,\r\n };\r\n\r\n segments.push({ start: p1, cp1, cp2, end: p2 });\r\n }\r\n\r\n return segments;\r\n}\r\n","import type { CanvasElement, StrokeElement, ArrowElement } from './types';\r\nimport { getArrowControlPoint, getArrowTangentAngle } from './arrow-geometry';\r\nimport { smoothToSegments, pressureToWidth } from './stroke-smoothing';\r\n\r\nconst DOM_ELEMENT_TYPES = new Set(['note', 'image', 'html']);\r\nconst ARROWHEAD_LENGTH = 12;\r\nconst ARROWHEAD_ANGLE = Math.PI / 6;\r\n\r\nexport class ElementRenderer {\r\n isDomElement(element: CanvasElement): boolean {\r\n return DOM_ELEMENT_TYPES.has(element.type);\r\n }\r\n\r\n renderCanvasElement(ctx: CanvasRenderingContext2D, element: CanvasElement): void {\r\n switch (element.type) {\r\n case 'stroke':\r\n this.renderStroke(ctx, element);\r\n break;\r\n case 'arrow':\r\n this.renderArrow(ctx, element);\r\n break;\r\n }\r\n }\r\n\r\n private renderStroke(ctx: CanvasRenderingContext2D, stroke: StrokeElement): void {\r\n if (stroke.points.length < 2) return;\r\n\r\n ctx.save();\r\n ctx.translate(stroke.position.x, stroke.position.y);\r\n ctx.strokeStyle = stroke.color;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n ctx.globalAlpha = stroke.opacity;\r\n\r\n const segments = smoothToSegments(stroke.points);\r\n for (const seg of segments) {\r\n const w =\r\n (pressureToWidth(seg.start.pressure, stroke.width) +\r\n pressureToWidth(seg.end.pressure, stroke.width)) /\r\n 2;\r\n ctx.lineWidth = w;\r\n ctx.beginPath();\r\n ctx.moveTo(seg.start.x, seg.start.y);\r\n ctx.bezierCurveTo(seg.cp1.x, seg.cp1.y, seg.cp2.x, seg.cp2.y, seg.end.x, seg.end.y);\r\n ctx.stroke();\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private renderArrow(ctx: CanvasRenderingContext2D, arrow: ArrowElement): void {\r\n ctx.save();\r\n ctx.strokeStyle = arrow.color;\r\n ctx.lineWidth = arrow.width;\r\n ctx.lineCap = 'round';\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(arrow.from.x, arrow.from.y);\r\n\r\n if (arrow.bend !== 0) {\r\n const cp = getArrowControlPoint(arrow.from, arrow.to, arrow.bend);\r\n ctx.quadraticCurveTo(cp.x, cp.y, arrow.to.x, arrow.to.y);\r\n } else {\r\n ctx.lineTo(arrow.to.x, arrow.to.y);\r\n }\r\n ctx.stroke();\r\n\r\n this.renderArrowhead(ctx, arrow);\r\n ctx.restore();\r\n }\r\n\r\n private renderArrowhead(ctx: CanvasRenderingContext2D, arrow: ArrowElement): void {\r\n const angle = getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 1);\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(arrow.to.x, arrow.to.y);\r\n ctx.lineTo(\r\n arrow.to.x - ARROWHEAD_LENGTH * Math.cos(angle - ARROWHEAD_ANGLE),\r\n arrow.to.y - ARROWHEAD_LENGTH * Math.sin(angle - ARROWHEAD_ANGLE),\r\n );\r\n ctx.lineTo(\r\n arrow.to.x - ARROWHEAD_LENGTH * Math.cos(angle + ARROWHEAD_ANGLE),\r\n arrow.to.y - ARROWHEAD_LENGTH * Math.sin(angle + ARROWHEAD_ANGLE),\r\n );\r\n ctx.closePath();\r\n ctx.fillStyle = arrow.color;\r\n ctx.fill();\r\n }\r\n}\r\n","import type { ElementStore } from './element-store';\n\nexport class NoteEditor {\n private editingId: string | null = null;\n private editingNode: HTMLDivElement | null = null;\n private blurHandler: (() => void) | null = null;\n private keyHandler: ((e: KeyboardEvent) => void) | null = null;\n private pointerHandler: ((e: PointerEvent) => void) | null = null;\n private pendingEditId: string | null = null;\n\n get isEditing(): boolean {\n return this.editingId !== null;\n }\n\n get editingElementId(): string | null {\n return this.editingId;\n }\n\n startEditing(node: HTMLDivElement, elementId: string, store: ElementStore): void {\n if (this.editingId === elementId) return;\n\n if (this.editingId) {\n this.stopEditing(store);\n }\n\n this.pendingEditId = elementId;\n\n requestAnimationFrame(() => {\n if (this.pendingEditId !== elementId) return;\n this.pendingEditId = null;\n this.activateEditing(node, elementId, store);\n });\n }\n\n stopEditing(store: ElementStore): void {\n this.pendingEditId = null;\n\n if (!this.editingId || !this.editingNode) return;\n\n const text = this.editingNode.textContent ?? '';\n store.update(this.editingId, { text });\n\n this.editingNode.contentEditable = 'false';\n Object.assign(this.editingNode.style, {\n userSelect: 'none',\n cursor: 'default',\n });\n\n if (this.blurHandler) {\n this.editingNode.removeEventListener('blur', this.blurHandler);\n }\n if (this.keyHandler) {\n this.editingNode.removeEventListener('keydown', this.keyHandler);\n }\n if (this.pointerHandler) {\n this.editingNode.removeEventListener('pointerdown', this.pointerHandler);\n }\n\n this.editingId = null;\n this.editingNode = null;\n this.blurHandler = null;\n this.keyHandler = null;\n this.pointerHandler = null;\n }\n\n destroy(store: ElementStore): void {\n this.pendingEditId = null;\n if (this.isEditing) {\n this.stopEditing(store);\n }\n }\n\n private activateEditing(node: HTMLDivElement, elementId: string, store: ElementStore): void {\n this.editingId = elementId;\n this.editingNode = node;\n\n node.contentEditable = 'true';\n Object.assign(node.style, {\n userSelect: 'text',\n cursor: 'text',\n outline: 'none',\n });\n node.focus();\n\n const selection = window.getSelection?.();\n if (selection) {\n const range = document.createRange();\n range.selectNodeContents(node);\n range.collapse(false);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n\n this.blurHandler = () => this.stopEditing(store);\n this.keyHandler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n node.blur();\n }\n e.stopPropagation();\n };\n this.pointerHandler = (e: PointerEvent) => {\n e.stopPropagation();\n };\n\n node.addEventListener('blur', this.blurHandler);\n node.addEventListener('keydown', this.keyHandler);\n node.addEventListener('pointerdown', this.pointerHandler);\n }\n}\n","import type { Tool, ToolContext, PointerState } from './types';\r\n\r\nexport class ToolManager {\r\n private tools = new Map<string, Tool>();\r\n private current: Tool | null = null;\r\n private changeListeners = new Set<(name: string) => void>();\r\n\r\n get activeTool(): Tool | null {\r\n return this.current;\r\n }\r\n\r\n get toolNames(): string[] {\r\n return [...this.tools.keys()];\r\n }\r\n\r\n register(tool: Tool): void {\r\n this.tools.set(tool.name, tool);\r\n }\r\n\r\n getTool<T extends Tool = Tool>(name: string): T | undefined {\r\n return this.tools.get(name) as T | undefined;\r\n }\r\n\r\n setTool(name: string, ctx: ToolContext): void {\r\n const tool = this.tools.get(name);\r\n if (!tool) return;\r\n\r\n this.current?.onDeactivate?.(ctx);\r\n this.current = tool;\r\n this.current.onActivate?.(ctx);\r\n this.changeListeners.forEach((fn) => fn(name));\r\n }\r\n\r\n handlePointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.current?.onPointerDown(state, ctx);\r\n }\r\n\r\n handlePointerMove(state: PointerState, ctx: ToolContext): void {\r\n this.current?.onPointerMove(state, ctx);\r\n }\r\n\r\n handlePointerUp(state: PointerState, ctx: ToolContext): void {\r\n this.current?.onPointerUp(state, ctx);\r\n }\r\n\r\n onChange(listener: (name: string) => void): () => void {\r\n this.changeListeners.add(listener);\r\n return () => this.changeListeners.delete(listener);\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\nimport type { Command } from './types';\n\nexport interface HistoryStackOptions {\n maxSize?: number;\n}\n\nconst DEFAULT_MAX_SIZE = 100;\n\nexport class HistoryStack {\n private undoStack: Command[] = [];\n private redoStack: Command[] = [];\n private readonly maxSize: number;\n private changeListeners = new Set<() => void>();\n\n constructor(options: HistoryStackOptions = {}) {\n this.maxSize = options.maxSize ?? DEFAULT_MAX_SIZE;\n }\n\n get canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n get canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n get undoCount(): number {\n return this.undoStack.length;\n }\n\n get redoCount(): number {\n return this.redoStack.length;\n }\n\n push(command: Command): void {\n this.undoStack.push(command);\n this.redoStack = [];\n\n if (this.undoStack.length > this.maxSize) {\n this.undoStack.shift();\n }\n\n this.notifyChange();\n }\n\n undo(store: ElementStore): boolean {\n const command = this.undoStack.pop();\n if (!command) return false;\n\n command.undo(store);\n this.redoStack.push(command);\n this.notifyChange();\n return true;\n }\n\n redo(store: ElementStore): boolean {\n const command = this.redoStack.pop();\n if (!command) return false;\n\n command.execute(store);\n this.undoStack.push(command);\n this.notifyChange();\n return true;\n }\n\n clear(): void {\n this.undoStack = [];\n this.redoStack = [];\n this.notifyChange();\n }\n\n onChange(listener: () => void): () => void {\n this.changeListeners.add(listener);\n return () => this.changeListeners.delete(listener);\n }\n\n private notifyChange(): void {\n this.changeListeners.forEach((fn) => fn());\n }\n}\n","import type { CanvasElement } from '../elements/types';\nimport type { ElementStore } from '../elements/element-store';\nimport type { Command } from './types';\n\nexport class AddElementCommand implements Command {\n private readonly element: CanvasElement;\n\n constructor(element: CanvasElement) {\n this.element = { ...element };\n }\n\n execute(store: ElementStore): void {\n store.add(this.element);\n }\n\n undo(store: ElementStore): void {\n store.remove(this.element.id);\n }\n}\n\nexport class RemoveElementCommand implements Command {\n private readonly element: CanvasElement;\n\n constructor(element: CanvasElement) {\n this.element = { ...element };\n }\n\n execute(store: ElementStore): void {\n store.remove(this.element.id);\n }\n\n undo(store: ElementStore): void {\n store.add(this.element);\n }\n}\n\nexport class UpdateElementCommand implements Command {\n constructor(\n private readonly id: string,\n private readonly previous: CanvasElement,\n private readonly current: CanvasElement,\n ) {}\n\n execute(store: ElementStore): void {\n store.update(this.id, { ...this.current });\n }\n\n undo(store: ElementStore): void {\n store.update(this.id, { ...this.previous });\n }\n}\n\nexport class BatchCommand implements Command {\n readonly commands: readonly Command[];\n\n constructor(commands: Command[]) {\n this.commands = [...commands];\n }\n\n execute(store: ElementStore): void {\n for (const cmd of this.commands) {\n cmd.execute(store);\n }\n }\n\n undo(store: ElementStore): void {\n for (let i = this.commands.length - 1; i >= 0; i--) {\n this.commands[i]?.undo(store);\n }\n }\n}\n","import type { ElementStore } from '../elements/element-store';\nimport type { CanvasElement } from '../elements/types';\nimport type { Command } from './types';\nimport type { HistoryStack } from './history-stack';\nimport {\n AddElementCommand,\n RemoveElementCommand,\n UpdateElementCommand,\n BatchCommand,\n} from './commands';\n\nexport class HistoryRecorder {\n private recording = true;\n private transaction: Command[] | null = null;\n private updateSnapshots = new Map<string, CanvasElement>();\n private unsubscribers: (() => void)[];\n\n constructor(\n private readonly store: ElementStore,\n private readonly stack: HistoryStack,\n ) {\n this.unsubscribers = [\n store.on('add', (el) => this.onAdd(el)),\n store.on('remove', (el) => this.onRemove(el)),\n store.on('update', ({ previous, current }) => this.onUpdate(previous, current)),\n ];\n }\n\n pause(): void {\n this.recording = false;\n }\n\n resume(): void {\n this.recording = true;\n }\n\n begin(): void {\n this.transaction = [];\n this.updateSnapshots.clear();\n }\n\n commit(): void {\n if (!this.transaction) return;\n\n const finalCommands = this.flushUpdateSnapshots();\n const all = [...this.transaction, ...finalCommands];\n this.transaction = null;\n this.updateSnapshots.clear();\n\n if (all.length === 0) return;\n const first = all[0];\n this.stack.push(all.length === 1 && first ? first : new BatchCommand(all));\n }\n\n rollback(): void {\n this.transaction = null;\n this.updateSnapshots.clear();\n }\n\n destroy(): void {\n this.unsubscribers.forEach((fn) => fn());\n }\n\n private record(command: Command): void {\n if (this.transaction) {\n this.transaction.push(command);\n } else {\n this.stack.push(command);\n }\n }\n\n private onAdd(element: CanvasElement): void {\n if (!this.recording) return;\n this.record(new AddElementCommand(element));\n }\n\n private onRemove(element: CanvasElement): void {\n if (!this.recording) return;\n\n if (this.transaction && this.updateSnapshots.has(element.id)) {\n this.updateSnapshots.delete(element.id);\n }\n\n this.record(new RemoveElementCommand(element));\n }\n\n private onUpdate(previous: CanvasElement, current: CanvasElement): void {\n if (!this.recording) return;\n\n if (this.transaction) {\n if (!this.updateSnapshots.has(current.id)) {\n this.updateSnapshots.set(current.id, { ...previous });\n }\n } else {\n this.stack.push(new UpdateElementCommand(current.id, previous, current));\n }\n }\n\n private flushUpdateSnapshots(): Command[] {\n const commands: Command[] = [];\n for (const [id, previous] of this.updateSnapshots) {\n const current = this.store.getById(id);\n if (current) {\n commands.push(new UpdateElementCommand(id, previous, current));\n }\n }\n return commands;\n }\n}\n","let counter = 0;\n\nexport function createId(prefix: string): string {\n return `${prefix}_${Date.now().toString(36)}_${(counter++).toString(36)}`;\n}\n","import type { Point, Size, StrokePoint } from '../core/types';\r\nimport type { StrokeElement, NoteElement, ArrowElement, ImageElement, HtmlElement } from './types';\r\nimport { createId } from './create-id';\r\n\r\ninterface BaseDefaults {\r\n position?: Point;\r\n zIndex?: number;\r\n locked?: boolean;\r\n}\r\n\r\ninterface StrokeInput extends BaseDefaults {\r\n points: StrokePoint[];\r\n color?: string;\r\n width?: number;\r\n opacity?: number;\r\n}\r\n\r\ninterface NoteInput extends BaseDefaults {\r\n position: Point;\r\n size?: Size;\r\n text?: string;\r\n backgroundColor?: string;\r\n}\r\n\r\ninterface ArrowInput extends BaseDefaults {\r\n from: Point;\r\n to: Point;\r\n bend?: number;\r\n color?: string;\r\n width?: number;\r\n}\r\n\r\ninterface ImageInput extends BaseDefaults {\r\n position: Point;\r\n size: Size;\r\n src: string;\r\n}\r\n\r\ninterface HtmlInput extends BaseDefaults {\r\n position: Point;\r\n size: Size;\r\n}\r\n\r\nexport function createStroke(input: StrokeInput): StrokeElement {\r\n return {\r\n id: createId('stroke'),\r\n type: 'stroke',\r\n position: input.position ?? { x: 0, y: 0 },\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n points: input.points,\r\n color: input.color ?? '#000000',\r\n width: input.width ?? 2,\r\n opacity: input.opacity ?? 1,\r\n };\r\n}\r\n\r\nexport function createNote(input: NoteInput): NoteElement {\r\n return {\r\n id: createId('note'),\r\n type: 'note',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n size: input.size ?? { w: 200, h: 100 },\r\n text: input.text ?? '',\r\n backgroundColor: input.backgroundColor ?? '#ffeb3b',\r\n };\r\n}\r\n\r\nexport function createArrow(input: ArrowInput): ArrowElement {\r\n return {\r\n id: createId('arrow'),\r\n type: 'arrow',\r\n position: input.position ?? { x: 0, y: 0 },\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n from: input.from,\r\n to: input.to,\r\n bend: input.bend ?? 0,\r\n color: input.color ?? '#000000',\r\n width: input.width ?? 2,\r\n };\r\n}\r\n\r\nexport function createImage(input: ImageInput): ImageElement {\r\n return {\r\n id: createId('image'),\r\n type: 'image',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n size: input.size,\r\n src: input.src,\r\n };\r\n}\r\n\r\nexport function createHtmlElement(input: HtmlInput): HtmlElement {\r\n return {\r\n id: createId('html'),\r\n type: 'html',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n size: input.size,\r\n };\r\n}\r\n","import { Camera } from './camera';\r\nimport type { CameraOptions } from './camera';\r\nimport { InputHandler } from './input-handler';\r\nimport { Background } from './background';\r\nimport type { BackgroundOptions } from './background';\r\nimport { ElementStore } from '../elements/element-store';\r\nimport { ElementRenderer } from '../elements/element-renderer';\r\nimport { NoteEditor } from '../elements/note-editor';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { ToolManager } from '../tools/tool-manager';\r\nimport type { ToolContext } from '../tools/types';\r\nimport { HistoryStack } from '../history/history-stack';\r\nimport { HistoryRecorder } from '../history/history-recorder';\r\nimport { createImage, createHtmlElement } from '../elements/element-factory';\r\nimport { exportState, parseState } from '../core/state-serializer';\r\nimport type { CanvasState } from '../core/state-serializer';\r\n\r\nexport interface ViewportOptions {\r\n camera?: CameraOptions;\r\n background?: BackgroundOptions;\r\n}\r\n\r\nexport class Viewport {\r\n readonly camera: Camera;\r\n readonly store: ElementStore;\r\n readonly toolManager: ToolManager;\r\n readonly history: HistoryStack;\r\n readonly domLayer: HTMLDivElement;\r\n private readonly canvasEl: HTMLCanvasElement;\r\n private readonly wrapper: HTMLDivElement;\r\n private readonly unsubCamera: () => void;\r\n private readonly unsubStore: (() => void)[];\r\n private readonly inputHandler: InputHandler;\r\n private readonly background: Background;\r\n private readonly renderer: ElementRenderer;\r\n private readonly noteEditor: NoteEditor;\r\n private readonly historyRecorder: HistoryRecorder;\r\n readonly toolContext: ToolContext;\r\n private resizeObserver: ResizeObserver | null = null;\r\n private animFrameId = 0;\r\n private needsRender = true;\r\n private domNodes = new Map<string, HTMLDivElement>();\r\n private htmlContent = new Map<string, HTMLElement>();\r\n private interactingElementId: string | null = null;\r\n\r\n constructor(\r\n private readonly container: HTMLElement,\r\n options: ViewportOptions = {},\r\n ) {\r\n this.camera = new Camera(options.camera);\r\n this.background = new Background(options.background);\r\n this.store = new ElementStore();\r\n this.toolManager = new ToolManager();\r\n this.renderer = new ElementRenderer();\r\n this.noteEditor = new NoteEditor();\r\n this.history = new HistoryStack();\r\n this.historyRecorder = new HistoryRecorder(this.store, this.history);\r\n\r\n this.wrapper = this.createWrapper();\r\n this.canvasEl = this.createCanvas();\r\n this.domLayer = this.createDomLayer();\r\n\r\n this.wrapper.appendChild(this.canvasEl);\r\n this.wrapper.appendChild(this.domLayer);\r\n this.container.appendChild(this.wrapper);\r\n\r\n this.toolContext = {\r\n camera: this.camera,\r\n store: this.store,\r\n requestRender: () => this.requestRender(),\r\n switchTool: (name: string) => this.toolManager.setTool(name, this.toolContext),\r\n editElement: (id: string) => this.startEditingNote(id),\r\n setCursor: (cursor: string) => {\r\n this.wrapper.style.cursor = cursor;\r\n },\r\n };\r\n\r\n this.inputHandler = new InputHandler(this.wrapper, this.camera, {\r\n toolManager: this.toolManager,\r\n toolContext: this.toolContext,\r\n historyRecorder: this.historyRecorder,\r\n historyStack: this.history,\r\n });\r\n\r\n this.unsubCamera = this.camera.onChange(() => {\r\n this.applyCameraTransform();\r\n this.requestRender();\r\n });\r\n\r\n this.unsubStore = [\r\n this.store.on('add', () => this.requestRender()),\r\n this.store.on('remove', (el) => this.removeDomNode(el.id)),\r\n this.store.on('update', () => this.requestRender()),\r\n this.store.on('clear', () => this.clearDomNodes()),\r\n ];\r\n\r\n this.wrapper.addEventListener('dblclick', this.onDblClick);\r\n this.wrapper.addEventListener('dragover', this.onDragOver);\r\n this.wrapper.addEventListener('drop', this.onDrop);\r\n this.observeResize();\r\n this.syncCanvasSize();\r\n this.startRenderLoop();\r\n }\r\n\r\n get ctx(): CanvasRenderingContext2D | null {\r\n return this.canvasEl.getContext('2d');\r\n }\r\n\r\n requestRender(): void {\r\n this.needsRender = true;\r\n }\r\n\r\n exportState(): CanvasState {\r\n return exportState(this.store.snapshot(), this.camera);\r\n }\r\n\r\n exportJSON(): string {\r\n return JSON.stringify(this.exportState());\r\n }\r\n\r\n loadState(state: CanvasState): void {\r\n this.historyRecorder.pause();\r\n this.noteEditor.destroy(this.store);\r\n this.clearDomNodes();\r\n this.store.loadSnapshot(state.elements);\r\n this.history.clear();\r\n this.historyRecorder.resume();\r\n this.camera.moveTo(state.camera.position.x, state.camera.position.y);\r\n this.camera.setZoom(state.camera.zoom);\r\n }\r\n\r\n loadJSON(json: string): void {\r\n this.loadState(parseState(json));\r\n }\r\n\r\n undo(): boolean {\r\n this.historyRecorder.pause();\r\n const result = this.history.undo(this.store);\r\n this.historyRecorder.resume();\r\n if (result) this.requestRender();\r\n return result;\r\n }\r\n\r\n redo(): boolean {\r\n this.historyRecorder.pause();\r\n const result = this.history.redo(this.store);\r\n this.historyRecorder.resume();\r\n if (result) this.requestRender();\r\n return result;\r\n }\r\n\r\n addImage(src: string, position: { x: number; y: number }, size = { w: 300, h: 200 }): string {\r\n const image = createImage({ position, size, src });\r\n this.historyRecorder.begin();\r\n this.store.add(image);\r\n this.historyRecorder.commit();\r\n this.requestRender();\r\n return image.id;\r\n }\r\n\r\n addHtmlElement(\r\n dom: HTMLElement,\r\n position: { x: number; y: number },\r\n size = { w: 200, h: 150 },\r\n ): string {\r\n const el = createHtmlElement({ position, size });\r\n this.htmlContent.set(el.id, dom);\r\n this.historyRecorder.begin();\r\n this.store.add(el);\r\n this.historyRecorder.commit();\r\n this.requestRender();\r\n return el.id;\r\n }\r\n\r\n destroy(): void {\r\n cancelAnimationFrame(this.animFrameId);\r\n this.stopInteracting();\r\n this.noteEditor.destroy(this.store);\r\n this.historyRecorder.destroy();\r\n this.wrapper.removeEventListener('dblclick', this.onDblClick);\r\n this.wrapper.removeEventListener('dragover', this.onDragOver);\r\n this.wrapper.removeEventListener('drop', this.onDrop);\r\n this.inputHandler.destroy();\r\n this.unsubCamera();\r\n this.unsubStore.forEach((fn) => fn());\r\n this.resizeObserver?.disconnect();\r\n this.resizeObserver = null;\r\n this.wrapper.remove();\r\n }\r\n\r\n private startRenderLoop(): void {\r\n const loop = (): void => {\r\n if (this.needsRender) {\r\n this.render();\r\n this.needsRender = false;\r\n }\r\n this.animFrameId = requestAnimationFrame(loop);\r\n };\r\n this.animFrameId = requestAnimationFrame(loop);\r\n }\r\n\r\n private render(): void {\r\n const ctx = this.ctx;\r\n if (!ctx) return;\r\n\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n ctx.save();\r\n ctx.scale(dpr, dpr);\r\n\r\n this.background.render(ctx, this.camera);\r\n\r\n ctx.save();\r\n ctx.translate(this.camera.position.x, this.camera.position.y);\r\n ctx.scale(this.camera.zoom, this.camera.zoom);\r\n\r\n for (const element of this.store.getAll()) {\r\n if (this.renderer.isDomElement(element)) {\r\n this.syncDomNode(element);\r\n } else {\r\n this.renderer.renderCanvasElement(ctx, element);\r\n }\r\n }\r\n\r\n const activeTool = this.toolManager.activeTool;\r\n if (activeTool?.renderOverlay) {\r\n activeTool.renderOverlay(ctx);\r\n }\r\n\r\n ctx.restore();\r\n ctx.restore();\r\n }\r\n\r\n private startEditingNote(id: string): void {\r\n const element = this.store.getById(id);\r\n if (!element || element.type !== 'note') return;\r\n\r\n this.render();\r\n\r\n const node = this.domNodes.get(id);\r\n if (node) {\r\n this.noteEditor.startEditing(node, id, this.store);\r\n }\r\n }\r\n\r\n private onDblClick = (e: MouseEvent): void => {\r\n const el = document.elementFromPoint(e.clientX, e.clientY);\r\n\r\n const nodeEl = (el as HTMLElement | null)?.closest<HTMLDivElement>('[data-element-id]');\r\n if (nodeEl) {\r\n const elementId = nodeEl.dataset['elementId'];\r\n if (elementId) {\r\n const element = this.store.getById(elementId);\r\n if (element?.type === 'note') {\r\n this.startEditingNote(elementId);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n const rect = this.wrapper.getBoundingClientRect();\r\n const screen = { x: e.clientX - rect.left, y: e.clientY - rect.top };\r\n const world = this.camera.screenToWorld(screen);\r\n const hit = this.hitTestWorld(world);\r\n if (hit?.type === 'html') {\r\n this.startInteracting(hit.id);\r\n }\r\n };\r\n\r\n private hitTestWorld(world: { x: number; y: number }): CanvasElement | null {\r\n const elements = this.store.getAll().reverse();\r\n for (const el of elements) {\r\n if (!('size' in el)) continue;\r\n const { x, y } = el.position;\r\n const { w, h } = el.size;\r\n if (world.x >= x && world.x <= x + w && world.y >= y && world.y <= y + h) {\r\n return el;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n private startInteracting(id: string): void {\r\n this.stopInteracting();\r\n const node = this.domNodes.get(id);\r\n if (!node) return;\r\n\r\n this.interactingElementId = id;\r\n node.style.pointerEvents = 'auto';\r\n node.addEventListener('pointerdown', this.onInteractNodePointerDown);\r\n\r\n window.addEventListener('keydown', this.onInteractKeyDown);\r\n window.addEventListener('pointerdown', this.onInteractPointerDown);\r\n }\r\n\r\n stopInteracting(): void {\r\n if (!this.interactingElementId) return;\r\n\r\n const node = this.domNodes.get(this.interactingElementId);\r\n if (node) {\r\n node.style.pointerEvents = 'none';\r\n node.removeEventListener('pointerdown', this.onInteractNodePointerDown);\r\n }\r\n\r\n this.interactingElementId = null;\r\n window.removeEventListener('keydown', this.onInteractKeyDown);\r\n window.removeEventListener('pointerdown', this.onInteractPointerDown);\r\n }\r\n\r\n private onInteractNodePointerDown = (e: PointerEvent): void => {\r\n e.stopPropagation();\r\n };\r\n\r\n private onInteractKeyDown = (e: KeyboardEvent): void => {\r\n if (e.key === 'Escape') {\r\n this.stopInteracting();\r\n }\r\n };\r\n\r\n private onInteractPointerDown = (e: PointerEvent): void => {\r\n if (!this.interactingElementId) return;\r\n const target = e.target as HTMLElement | null;\r\n if (!target) return;\r\n\r\n const node = this.domNodes.get(this.interactingElementId);\r\n if (node && !node.contains(target)) {\r\n this.stopInteracting();\r\n }\r\n };\r\n\r\n private onDragOver = (e: DragEvent): void => {\r\n e.preventDefault();\r\n };\r\n\r\n private onDrop = (e: DragEvent): void => {\r\n e.preventDefault();\r\n const files = e.dataTransfer?.files;\r\n if (!files) return;\r\n\r\n const rect = this.wrapper.getBoundingClientRect();\r\n\r\n for (const file of files) {\r\n if (!file.type.startsWith('image/')) continue;\r\n\r\n const reader = new FileReader();\r\n reader.onload = () => {\r\n const src = reader.result;\r\n if (typeof src !== 'string') return;\r\n\r\n const screenPos = { x: e.clientX - rect.left, y: e.clientY - rect.top };\r\n const worldPos = this.camera.screenToWorld(screenPos);\r\n this.addImage(src, worldPos);\r\n };\r\n reader.readAsDataURL(file);\r\n }\r\n };\r\n\r\n private syncDomNode(element: CanvasElement): void {\r\n let node = this.domNodes.get(element.id);\r\n if (!node) {\r\n node = document.createElement('div');\r\n node.dataset['elementId'] = element.id;\r\n Object.assign(node.style, {\r\n position: 'absolute',\r\n pointerEvents: 'auto',\r\n });\r\n this.domLayer.appendChild(node);\r\n this.domNodes.set(element.id, node);\r\n }\r\n\r\n const size = 'size' in element ? element.size : null;\r\n Object.assign(node.style, {\r\n left: `${element.position.x}px`,\r\n top: `${element.position.y}px`,\r\n width: size ? `${size.w}px` : 'auto',\r\n height: size ? `${size.h}px` : 'auto',\r\n });\r\n\r\n this.renderDomContent(node, element);\r\n }\r\n\r\n private renderDomContent(node: HTMLDivElement, element: CanvasElement): void {\r\n if (element.type === 'note') {\r\n if (!node.dataset['initialized']) {\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n backgroundColor: element.backgroundColor,\r\n padding: '8px',\r\n borderRadius: '4px',\r\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\r\n fontSize: '14px',\r\n overflow: 'hidden',\r\n cursor: 'default',\r\n userSelect: 'none',\r\n wordWrap: 'break-word',\r\n });\r\n node.textContent = element.text || '';\r\n\r\n node.addEventListener('dblclick', (e) => {\r\n e.stopPropagation();\r\n const id = node.dataset['elementId'];\r\n if (id) this.startEditingNote(id);\r\n });\r\n }\r\n\r\n if (!this.noteEditor.isEditing || this.noteEditor.editingElementId !== element.id) {\r\n if (node.textContent !== element.text) {\r\n node.textContent = element.text || '';\r\n }\r\n node.style.backgroundColor = element.backgroundColor;\r\n }\r\n }\r\n\r\n if (element.type === 'image') {\r\n if (!node.dataset['initialized']) {\r\n node.dataset['initialized'] = 'true';\r\n const img = document.createElement('img');\r\n img.src = element.src;\r\n Object.assign(img.style, {\r\n width: '100%',\r\n height: '100%',\r\n objectFit: 'contain',\r\n pointerEvents: 'none',\r\n });\r\n img.draggable = false;\r\n node.appendChild(img);\r\n } else {\r\n const img = node.querySelector('img');\r\n if (img && img.src !== element.src) {\r\n img.src = element.src;\r\n }\r\n }\r\n }\r\n\r\n if (element.type === 'html' && !node.dataset['initialized']) {\r\n const content = this.htmlContent.get(element.id);\r\n if (content) {\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n overflow: 'hidden',\r\n pointerEvents: 'none',\r\n });\r\n node.appendChild(content);\r\n }\r\n }\r\n }\r\n\r\n private removeDomNode(id: string): void {\r\n this.htmlContent.delete(id);\r\n const node = this.domNodes.get(id);\r\n if (node) {\r\n node.remove();\r\n this.domNodes.delete(id);\r\n }\r\n this.requestRender();\r\n }\r\n\r\n private clearDomNodes(): void {\r\n this.domNodes.forEach((node) => node.remove());\r\n this.domNodes.clear();\r\n this.htmlContent.clear();\r\n this.requestRender();\r\n }\r\n\r\n private createWrapper(): HTMLDivElement {\r\n const el = document.createElement('div');\r\n Object.assign(el.style, {\r\n position: 'relative',\r\n width: '100%',\r\n height: '100%',\r\n overflow: 'hidden',\r\n });\r\n return el;\r\n }\r\n\r\n private createCanvas(): HTMLCanvasElement {\r\n const el = document.createElement('canvas');\r\n Object.assign(el.style, {\r\n position: 'absolute',\r\n top: '0',\r\n left: '0',\r\n width: '100%',\r\n height: '100%',\r\n });\r\n return el;\r\n }\r\n\r\n private createDomLayer(): HTMLDivElement {\r\n const el = document.createElement('div');\r\n Object.assign(el.style, {\r\n position: 'absolute',\r\n top: '0',\r\n left: '0',\r\n width: '100%',\r\n height: '100%',\r\n pointerEvents: 'none',\r\n transformOrigin: '0 0',\r\n });\r\n return el;\r\n }\r\n\r\n private applyCameraTransform(): void {\r\n this.domLayer.style.transform = this.camera.toCSSTransform();\r\n }\r\n\r\n private syncCanvasSize(): void {\r\n const rect = this.container.getBoundingClientRect();\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n this.canvasEl.width = rect.width * dpr;\r\n this.canvasEl.height = rect.height * dpr;\r\n this.requestRender();\r\n }\r\n\r\n private observeResize(): void {\r\n if (typeof ResizeObserver === 'undefined') return;\r\n this.resizeObserver = new ResizeObserver(() => this.syncCanvasSize());\r\n this.resizeObserver.observe(this.container);\r\n }\r\n}\r\n","import type { Tool, ToolContext, PointerState } from './types';\n\nexport class HandTool implements Tool {\n readonly name = 'hand';\n private panning = false;\n private lastScreen = { x: 0, y: 0 };\n\n onActivate(ctx: ToolContext): void {\n ctx.setCursor?.('grab');\n }\n\n onDeactivate(ctx: ToolContext): void {\n ctx.setCursor?.('default');\n }\n\n onPointerDown(state: PointerState, ctx: ToolContext): void {\n this.panning = true;\n this.lastScreen = { x: state.x, y: state.y };\n ctx.setCursor?.('grabbing');\n }\n\n onPointerMove(state: PointerState, ctx: ToolContext): void {\n if (!this.panning) return;\n const dx = state.x - this.lastScreen.x;\n const dy = state.y - this.lastScreen.y;\n this.lastScreen = { x: state.x, y: state.y };\n ctx.camera.pan(dx, dy);\n }\n\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\n this.panning = false;\n ctx.setCursor?.('grab');\n }\n}\n","import type { StrokePoint } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createStroke } from '../elements/element-factory';\r\nimport { simplifyPoints, smoothToSegments, pressureToWidth } from '../elements/stroke-smoothing';\r\n\r\nexport interface PencilToolOptions {\r\n color?: string;\r\n width?: number;\r\n smoothing?: number;\r\n}\r\n\r\nconst MIN_POINTS_FOR_STROKE = 2;\r\nconst DEFAULT_SMOOTHING = 1.5;\r\nconst DEFAULT_PRESSURE = 0.5;\r\n\r\nexport class PencilTool implements Tool {\r\n readonly name = 'pencil';\r\n private drawing = false;\r\n private points: StrokePoint[] = [];\r\n private color: string;\r\n private width: number;\r\n private smoothing: number;\r\n\r\n constructor(options: PencilToolOptions = {}) {\r\n this.color = options.color ?? '#000000';\r\n this.width = options.width ?? 2;\r\n this.smoothing = options.smoothing ?? DEFAULT_SMOOTHING;\r\n }\r\n\r\n onActivate(ctx: ToolContext): void {\r\n ctx.setCursor?.('crosshair');\r\n }\r\n\r\n onDeactivate(ctx: ToolContext): void {\r\n ctx.setCursor?.('default');\r\n }\r\n\r\n setOptions(options: PencilToolOptions): void {\r\n if (options.color !== undefined) this.color = options.color;\r\n if (options.width !== undefined) this.width = options.width;\r\n if (options.smoothing !== undefined) this.smoothing = options.smoothing;\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.drawing = true;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const pressure = state.pressure === 0 ? DEFAULT_PRESSURE : state.pressure;\r\n this.points = [{ x: world.x, y: world.y, pressure }];\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const pressure = state.pressure === 0 ? DEFAULT_PRESSURE : state.pressure;\r\n this.points.push({ x: world.x, y: world.y, pressure });\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.drawing = false;\r\n\r\n if (this.points.length < MIN_POINTS_FOR_STROKE) {\r\n this.points = [];\r\n return;\r\n }\r\n\r\n const simplified = simplifyPoints(this.points, this.smoothing);\r\n const stroke = createStroke({\r\n points: simplified,\r\n color: this.color,\r\n width: this.width,\r\n });\r\n ctx.store.add(stroke);\r\n this.points = [];\r\n ctx.requestRender();\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (!this.drawing || this.points.length < 2) return;\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.color;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n ctx.globalAlpha = 0.8;\r\n\r\n const segments = smoothToSegments(this.points);\r\n for (const seg of segments) {\r\n const w =\r\n (pressureToWidth(seg.start.pressure, this.width) +\r\n pressureToWidth(seg.end.pressure, this.width)) /\r\n 2;\r\n ctx.lineWidth = w;\r\n ctx.beginPath();\r\n ctx.moveTo(seg.start.x, seg.start.y);\r\n ctx.bezierCurveTo(seg.cp1.x, seg.cp1.y, seg.cp2.x, seg.cp2.y, seg.end.x, seg.end.y);\r\n ctx.stroke();\r\n }\r\n\r\n ctx.restore();\r\n }\r\n}\r\n","import type { Point } from '../core/types';\nimport type { Tool, ToolContext, PointerState } from './types';\nimport type { StrokeElement } from '../elements/types';\n\nexport interface EraserToolOptions {\n radius?: number;\n}\n\nconst DEFAULT_RADIUS = 20;\n\nfunction makeEraserCursor(radius: number): string {\n const size = radius * 2;\n const svg = `<svg xmlns='http://www.w3.org/2000/svg' width='${size}' height='${size}'><circle cx='${radius}' cy='${radius}' r='${radius - 1}' fill='none' stroke='%23666' stroke-width='1.5'/></svg>`;\n return `url(\"data:image/svg+xml,${svg}\") ${radius} ${radius}, crosshair`;\n}\n\nexport class EraserTool implements Tool {\n readonly name = 'eraser';\n private erasing = false;\n private readonly radius: number;\n private readonly cursor: string;\n\n constructor(options: EraserToolOptions = {}) {\n this.radius = options.radius ?? DEFAULT_RADIUS;\n this.cursor = makeEraserCursor(this.radius);\n }\n\n onActivate(ctx: ToolContext): void {\n ctx.setCursor?.(this.cursor);\n }\n\n onDeactivate(ctx: ToolContext): void {\n ctx.setCursor?.('default');\n }\n\n onPointerDown(state: PointerState, ctx: ToolContext): void {\n this.erasing = true;\n this.eraseAt(state, ctx);\n }\n\n onPointerMove(state: PointerState, ctx: ToolContext): void {\n if (!this.erasing) return;\n this.eraseAt(state, ctx);\n }\n\n onPointerUp(_state: PointerState, _ctx: ToolContext): void {\n this.erasing = false;\n }\n\n private eraseAt(state: PointerState, ctx: ToolContext): void {\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\n const strokes = ctx.store.getElementsByType('stroke');\n let erased = false;\n\n for (const stroke of strokes) {\n if (this.strokeIntersects(stroke, world)) {\n ctx.store.remove(stroke.id);\n erased = true;\n }\n }\n\n if (erased) ctx.requestRender();\n }\n\n private strokeIntersects(stroke: StrokeElement, point: Point): boolean {\n const radiusSq = this.radius * this.radius;\n return stroke.points.some((p) => {\n const dx = p.x + stroke.position.x - point.x;\n const dy = p.y + stroke.position.y - point.y;\n return dx * dx + dy * dy <= radiusSq;\n });\n }\n}\n","import type { Point } from '../core/types';\nimport type { ArrowElement } from '../elements/types';\nimport type { ToolContext } from './types';\nimport { getArrowMidpoint, getBendFromPoint } from '../elements/arrow-geometry';\n\nexport type ArrowHandle = 'start' | 'mid' | 'end';\n\nconst HANDLE_RADIUS = 5;\nconst HANDLE_HIT_PADDING = 4;\n\nconst ARROW_HANDLE_CURSORS: Record<ArrowHandle, string> = {\n start: 'crosshair',\n end: 'crosshair',\n mid: 'grab',\n};\n\nexport function getArrowHandleCursor(handle: ArrowHandle, active: boolean): string {\n if (handle === 'mid' && active) return 'grabbing';\n return ARROW_HANDLE_CURSORS[handle];\n}\n\nexport function getArrowHandlePositions(arrow: ArrowElement): [ArrowHandle, Point][] {\n const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);\n return [\n ['start', arrow.from],\n ['mid', mid],\n ['end', arrow.to],\n ];\n}\n\nexport function hitTestArrowHandles(\n world: Point,\n selectedIds: string[],\n ctx: ToolContext,\n): { elementId: string; handle: ArrowHandle } | null {\n if (selectedIds.length === 0) return null;\n\n const zoom = ctx.camera.zoom;\n const hitRadius = (HANDLE_RADIUS + HANDLE_HIT_PADDING) / zoom;\n\n for (const id of selectedIds) {\n const el = ctx.store.getById(id);\n if (!el || el.type !== 'arrow') continue;\n\n const handles = getArrowHandlePositions(el);\n for (const [handle, pos] of handles) {\n const dx = world.x - pos.x;\n const dy = world.y - pos.y;\n if (dx * dx + dy * dy <= hitRadius * hitRadius) {\n return { elementId: id, handle };\n }\n }\n }\n\n return null;\n}\n\nexport function applyArrowHandleDrag(\n handle: ArrowHandle,\n elementId: string,\n world: Point,\n ctx: ToolContext,\n): void {\n const el = ctx.store.getById(elementId);\n if (!el || el.type !== 'arrow') return;\n\n switch (handle) {\n case 'start':\n ctx.store.update(elementId, {\n from: { x: world.x, y: world.y },\n position: { x: world.x, y: world.y },\n });\n break;\n case 'end':\n ctx.store.update(elementId, {\n to: { x: world.x, y: world.y },\n });\n break;\n case 'mid': {\n const bend = getBendFromPoint(el.from, el.to, world);\n ctx.store.update(elementId, { bend });\n break;\n }\n }\n\n ctx.requestRender();\n}\n\nexport function renderArrowHandles(\n canvasCtx: CanvasRenderingContext2D,\n arrow: ArrowElement,\n zoom: number,\n): void {\n const radius = HANDLE_RADIUS / zoom;\n const handles = getArrowHandlePositions(arrow);\n\n canvasCtx.setLineDash([]);\n canvasCtx.lineWidth = 1.5 / zoom;\n\n for (const [handle, pos] of handles) {\n canvasCtx.fillStyle = handle === 'mid' ? '#2196F3' : '#ffffff';\n canvasCtx.strokeStyle = '#2196F3';\n\n canvasCtx.beginPath();\n canvasCtx.arc(pos.x, pos.y, radius, 0, Math.PI * 2);\n canvasCtx.fill();\n canvasCtx.stroke();\n }\n}\n","import type { Point } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { isNearBezier, getArrowBounds } from '../elements/arrow-geometry';\r\nimport {\r\n type ArrowHandle,\r\n hitTestArrowHandles,\r\n applyArrowHandleDrag,\r\n renderArrowHandles,\r\n getArrowHandleCursor,\r\n} from './arrow-handles';\r\n\r\ninterface Rect {\r\n x: number;\r\n y: number;\r\n w: number;\r\n h: number;\r\n}\r\ntype HandlePosition = 'nw' | 'ne' | 'sw' | 'se';\r\n\r\nconst HANDLE_SIZE = 8;\r\nconst HANDLE_HIT_PADDING = 4;\r\nconst SELECTION_PAD = 4;\r\nconst MIN_ELEMENT_SIZE = 20;\r\n\r\nconst HANDLE_CURSORS: Record<HandlePosition, string> = {\r\n nw: 'nwse-resize',\r\n se: 'nwse-resize',\r\n ne: 'nesw-resize',\r\n sw: 'nesw-resize',\r\n};\r\n\r\ntype Mode =\r\n | { type: 'idle' }\r\n | { type: 'dragging' }\r\n | { type: 'marquee'; start: Point }\r\n | { type: 'resizing'; elementId: string; handle: HandlePosition }\r\n | { type: 'arrow-handle'; elementId: string; handle: ArrowHandle };\r\n\r\nexport class SelectTool implements Tool {\r\n readonly name = 'select';\r\n private _selectedIds: string[] = [];\r\n private mode: Mode = { type: 'idle' };\r\n private lastWorld: Point = { x: 0, y: 0 };\r\n private currentWorld: Point = { x: 0, y: 0 };\r\n private ctx: ToolContext | null = null;\r\n\r\n get selectedIds(): string[] {\r\n return [...this._selectedIds];\r\n }\r\n\r\n get isMarqueeActive(): boolean {\r\n return this.mode.type === 'marquee';\r\n }\r\n\r\n onActivate(ctx: ToolContext): void {\r\n this.ctx = ctx;\r\n }\r\n\r\n onDeactivate(ctx: ToolContext): void {\r\n this._selectedIds = [];\r\n this.mode = { type: 'idle' };\r\n ctx.setCursor?.('default');\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.ctx = ctx;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.lastWorld = world;\r\n this.currentWorld = world;\r\n\r\n const arrowHit = hitTestArrowHandles(world, this._selectedIds, ctx);\r\n if (arrowHit) {\r\n this.mode = {\r\n type: 'arrow-handle',\r\n elementId: arrowHit.elementId,\r\n handle: arrowHit.handle,\r\n };\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n const resizeHit = this.hitTestResizeHandle(world, ctx);\r\n if (resizeHit) {\r\n const el = ctx.store.getById(resizeHit.elementId);\r\n if (el) {\r\n this.mode = {\r\n type: 'resizing',\r\n elementId: resizeHit.elementId,\r\n handle: resizeHit.handle,\r\n };\r\n ctx.requestRender();\r\n return;\r\n }\r\n }\r\n\r\n const hit = this.hitTest(world, ctx);\r\n if (hit) {\r\n const alreadySelected = this._selectedIds.includes(hit.id);\r\n if (!alreadySelected) {\r\n this._selectedIds = [hit.id];\r\n }\r\n this.mode = hit.locked ? { type: 'idle' } : { type: 'dragging' };\r\n } else {\r\n this._selectedIds = [];\r\n this.mode = { type: 'marquee', start: world };\r\n }\r\n\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.currentWorld = world;\r\n\r\n if (this.mode.type === 'arrow-handle') {\r\n ctx.setCursor?.(getArrowHandleCursor(this.mode.handle, true));\r\n applyArrowHandleDrag(this.mode.handle, this.mode.elementId, world, ctx);\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'resizing') {\r\n ctx.setCursor?.(HANDLE_CURSORS[this.mode.handle]);\r\n this.handleResize(world, ctx);\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'dragging' && this._selectedIds.length > 0) {\r\n ctx.setCursor?.('move');\r\n const dx = world.x - this.lastWorld.x;\r\n const dy = world.y - this.lastWorld.y;\r\n this.lastWorld = world;\r\n\r\n for (const id of this._selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || el.locked) continue;\r\n\r\n if (el.type === 'arrow') {\r\n ctx.store.update(id, {\r\n position: { x: el.position.x + dx, y: el.position.y + dy },\r\n from: { x: el.from.x + dx, y: el.from.y + dy },\r\n to: { x: el.to.x + dx, y: el.to.y + dy },\r\n });\r\n } else {\r\n ctx.store.update(id, {\r\n position: { x: el.position.x + dx, y: el.position.y + dy },\r\n });\r\n }\r\n }\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'marquee') {\r\n ctx.setCursor?.('crosshair');\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n this.updateHoverCursor(world, ctx);\r\n }\r\n\r\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\r\n if (this.mode.type === 'marquee') {\r\n const rect = this.getMarqueeRect();\r\n if (rect) {\r\n this._selectedIds = this.findElementsInRect(rect, ctx);\r\n }\r\n ctx.requestRender();\r\n }\r\n\r\n this.mode = { type: 'idle' };\r\n ctx.setCursor?.('default');\r\n }\r\n\r\n onHover(state: PointerState, ctx: ToolContext): void {\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.updateHoverCursor(world, ctx);\r\n }\r\n\r\n renderOverlay(canvasCtx: CanvasRenderingContext2D): void {\r\n this.renderMarquee(canvasCtx);\r\n this.renderSelectionBoxes(canvasCtx);\r\n }\r\n\r\n private updateHoverCursor(world: Point, ctx: ToolContext): void {\r\n const arrowHit = hitTestArrowHandles(world, this._selectedIds, ctx);\r\n if (arrowHit) {\r\n ctx.setCursor?.(getArrowHandleCursor(arrowHit.handle, false));\r\n return;\r\n }\r\n\r\n const resizeHit = this.hitTestResizeHandle(world, ctx);\r\n if (resizeHit) {\r\n ctx.setCursor?.(HANDLE_CURSORS[resizeHit.handle]);\r\n return;\r\n }\r\n\r\n const hit = this.hitTest(world, ctx);\r\n ctx.setCursor?.(hit ? 'move' : 'default');\r\n }\r\n\r\n private handleResize(world: Point, ctx: ToolContext): void {\r\n if (this.mode.type !== 'resizing') return;\r\n\r\n const el = ctx.store.getById(this.mode.elementId);\r\n if (!el || !('size' in el) || el.locked) return;\r\n\r\n const { handle } = this.mode;\r\n const dx = world.x - this.lastWorld.x;\r\n const dy = world.y - this.lastWorld.y;\r\n this.lastWorld = world;\r\n\r\n let { x, y, w, h } = { x: el.position.x, y: el.position.y, w: el.size.w, h: el.size.h };\r\n\r\n switch (handle) {\r\n case 'se':\r\n w += dx;\r\n h += dy;\r\n break;\r\n case 'sw':\r\n x += dx;\r\n w -= dx;\r\n h += dy;\r\n break;\r\n case 'ne':\r\n y += dy;\r\n w += dx;\r\n h -= dy;\r\n break;\r\n case 'nw':\r\n x += dx;\r\n y += dy;\r\n w -= dx;\r\n h -= dy;\r\n break;\r\n }\r\n\r\n if (w < MIN_ELEMENT_SIZE) {\r\n if (handle === 'nw' || handle === 'sw') x = el.position.x + el.size.w - MIN_ELEMENT_SIZE;\r\n w = MIN_ELEMENT_SIZE;\r\n }\r\n if (h < MIN_ELEMENT_SIZE) {\r\n if (handle === 'nw' || handle === 'ne') y = el.position.y + el.size.h - MIN_ELEMENT_SIZE;\r\n h = MIN_ELEMENT_SIZE;\r\n }\r\n\r\n ctx.store.update(this.mode.elementId, {\r\n position: { x, y },\r\n size: { w, h },\r\n });\r\n ctx.requestRender();\r\n }\r\n\r\n private hitTestResizeHandle(\r\n world: Point,\r\n ctx: ToolContext,\r\n ): { elementId: string; handle: HandlePosition } | null {\r\n if (this._selectedIds.length === 0) return null;\r\n\r\n const zoom = ctx.camera.zoom;\r\n const handleHalf = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / zoom;\r\n\r\n for (const id of this._selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || !('size' in el)) continue;\r\n\r\n const bounds = this.getElementBounds(el);\r\n if (!bounds) continue;\r\n\r\n const corners = this.getHandlePositions(bounds);\r\n for (const [handle, pos] of corners) {\r\n if (Math.abs(world.x - pos.x) <= handleHalf && Math.abs(world.y - pos.y) <= handleHalf) {\r\n return { elementId: id, handle };\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private getHandlePositions(bounds: Rect): [HandlePosition, Point][] {\r\n return [\r\n ['nw', { x: bounds.x, y: bounds.y }],\r\n ['ne', { x: bounds.x + bounds.w, y: bounds.y }],\r\n ['sw', { x: bounds.x, y: bounds.y + bounds.h }],\r\n ['se', { x: bounds.x + bounds.w, y: bounds.y + bounds.h }],\r\n ];\r\n }\r\n\r\n private renderMarquee(canvasCtx: CanvasRenderingContext2D): void {\r\n if (this.mode.type !== 'marquee') return;\r\n\r\n const rect = this.getMarqueeRect();\r\n if (!rect) return;\r\n\r\n canvasCtx.save();\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.fillStyle = 'rgba(33, 150, 243, 0.08)';\r\n canvasCtx.lineWidth = 1;\r\n canvasCtx.setLineDash([4, 4]);\r\n canvasCtx.strokeRect(rect.x, rect.y, rect.w, rect.h);\r\n canvasCtx.fillRect(rect.x, rect.y, rect.w, rect.h);\r\n canvasCtx.restore();\r\n }\r\n\r\n private renderSelectionBoxes(canvasCtx: CanvasRenderingContext2D): void {\r\n if (this._selectedIds.length === 0 || !this.ctx) return;\r\n\r\n const zoom = this.ctx.camera.zoom;\r\n const handleWorldSize = HANDLE_SIZE / zoom;\r\n\r\n canvasCtx.save();\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.lineWidth = 1.5 / zoom;\r\n canvasCtx.setLineDash([4 / zoom, 4 / zoom]);\r\n\r\n for (const id of this._selectedIds) {\r\n const el = this.ctx.store.getById(id);\r\n if (!el) continue;\r\n\r\n if (el.type === 'arrow') {\r\n renderArrowHandles(canvasCtx, el, zoom);\r\n continue;\r\n }\r\n\r\n const bounds = this.getElementBounds(el);\r\n if (!bounds) continue;\r\n\r\n const pad = SELECTION_PAD / zoom;\r\n canvasCtx.strokeRect(bounds.x - pad, bounds.y - pad, bounds.w + pad * 2, bounds.h + pad * 2);\r\n\r\n if ('size' in el) {\r\n canvasCtx.setLineDash([]);\r\n canvasCtx.fillStyle = '#ffffff';\r\n const corners = this.getHandlePositions(bounds);\r\n for (const [, pos] of corners) {\r\n canvasCtx.fillRect(\r\n pos.x - handleWorldSize / 2,\r\n pos.y - handleWorldSize / 2,\r\n handleWorldSize,\r\n handleWorldSize,\r\n );\r\n canvasCtx.strokeRect(\r\n pos.x - handleWorldSize / 2,\r\n pos.y - handleWorldSize / 2,\r\n handleWorldSize,\r\n handleWorldSize,\r\n );\r\n }\r\n canvasCtx.setLineDash([4 / zoom, 4 / zoom]);\r\n }\r\n }\r\n\r\n canvasCtx.restore();\r\n }\r\n\r\n private getMarqueeRect(): Rect | null {\r\n if (this.mode.type !== 'marquee') return null;\r\n\r\n const { start } = this.mode;\r\n const end = this.currentWorld;\r\n const x = Math.min(start.x, end.x);\r\n const y = Math.min(start.y, end.y);\r\n const w = Math.abs(end.x - start.x);\r\n const h = Math.abs(end.y - start.y);\r\n\r\n if (w === 0 && h === 0) return null;\r\n return { x, y, w, h };\r\n }\r\n\r\n private findElementsInRect(marquee: Rect, ctx: ToolContext): string[] {\r\n const ids: string[] = [];\r\n for (const el of ctx.store.getAll()) {\r\n const bounds = this.getElementBounds(el);\r\n if (bounds && this.rectsOverlap(marquee, bounds)) {\r\n ids.push(el.id);\r\n }\r\n }\r\n return ids;\r\n }\r\n\r\n private rectsOverlap(a: Rect, b: Rect): boolean {\r\n return a.x <= b.x + b.w && a.x + a.w >= b.x && a.y <= b.y + b.h && a.y + a.h >= b.y;\r\n }\r\n\r\n private getElementBounds(el: CanvasElement): Rect | null {\r\n if ('size' in el) {\r\n return { x: el.position.x, y: el.position.y, w: el.size.w, h: el.size.h };\r\n }\r\n if (el.type === 'stroke' && el.points.length > 0) {\r\n let minX = Infinity,\r\n minY = Infinity,\r\n maxX = -Infinity,\r\n maxY = -Infinity;\r\n for (const p of el.points) {\r\n const px = p.x + el.position.x;\r\n const py = p.y + el.position.y;\r\n if (px < minX) minX = px;\r\n if (py < minY) minY = py;\r\n if (px > maxX) maxX = px;\r\n if (py > maxY) maxY = py;\r\n }\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n }\r\n if (el.type === 'arrow') {\r\n return getArrowBounds(el.from, el.to, el.bend);\r\n }\r\n return null;\r\n }\r\n\r\n private hitTest(world: Point, ctx: ToolContext): CanvasElement | null {\r\n const elements = ctx.store.getAll().reverse();\r\n for (const el of elements) {\r\n if (this.isInsideBounds(world, el)) return el;\r\n }\r\n return null;\r\n }\r\n\r\n private isInsideBounds(point: Point, el: CanvasElement): boolean {\r\n if ('size' in el) {\r\n const s = el.size;\r\n return (\r\n point.x >= el.position.x &&\r\n point.x <= el.position.x + s.w &&\r\n point.y >= el.position.y &&\r\n point.y <= el.position.y + s.h\r\n );\r\n }\r\n\r\n if (el.type === 'stroke') {\r\n const HIT_RADIUS = 10;\r\n return el.points.some((p) => {\r\n const dx = p.x + el.position.x - point.x;\r\n const dy = p.y + el.position.y - point.y;\r\n return dx * dx + dy * dy <= HIT_RADIUS * HIT_RADIUS;\r\n });\r\n }\r\n\r\n if (el.type === 'arrow') {\r\n return isNearBezier(point, el.from, el.to, el.bend, 10);\r\n }\r\n\r\n return false;\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createArrow } from '../elements/element-factory';\r\n\r\nexport interface ArrowToolOptions {\r\n color?: string;\r\n width?: number;\r\n}\r\n\r\nexport class ArrowTool implements Tool {\r\n readonly name = 'arrow';\r\n private drawing = false;\r\n private start: Point = { x: 0, y: 0 };\r\n private end: Point = { x: 0, y: 0 };\r\n private color: string;\r\n private width: number;\r\n\r\n constructor(options: ArrowToolOptions = {}) {\r\n this.color = options.color ?? '#000000';\r\n this.width = options.width ?? 2;\r\n }\r\n\r\n setOptions(options: ArrowToolOptions): void {\r\n if (options.color !== undefined) this.color = options.color;\r\n if (options.width !== undefined) this.width = options.width;\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.drawing = true;\r\n this.start = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.end = { ...this.start };\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.end = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.drawing = false;\r\n\r\n if (this.start.x === this.end.x && this.start.y === this.end.y) return;\r\n\r\n const arrow = createArrow({\r\n from: this.start,\r\n to: this.end,\r\n color: this.color,\r\n width: this.width,\r\n });\r\n ctx.store.add(arrow);\r\n ctx.requestRender();\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (!this.drawing) return;\r\n if (this.start.x === this.end.x && this.start.y === this.end.y) return;\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.color;\r\n ctx.lineWidth = this.width;\r\n ctx.lineCap = 'round';\r\n ctx.globalAlpha = 0.6;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(this.start.x, this.start.y);\r\n ctx.lineTo(this.end.x, this.end.y);\r\n ctx.stroke();\r\n\r\n const angle = Math.atan2(this.end.y - this.start.y, this.end.x - this.start.x);\r\n const headLen = 12;\r\n const headAngle = Math.PI / 6;\r\n\r\n ctx.fillStyle = this.color;\r\n ctx.beginPath();\r\n ctx.moveTo(this.end.x, this.end.y);\r\n ctx.lineTo(\r\n this.end.x - headLen * Math.cos(angle - headAngle),\r\n this.end.y - headLen * Math.sin(angle - headAngle),\r\n );\r\n ctx.lineTo(\r\n this.end.x - headLen * Math.cos(angle + headAngle),\r\n this.end.y - headLen * Math.sin(angle + headAngle),\r\n );\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n}\r\n","import type { Size } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createNote } from '../elements/element-factory';\r\n\r\nexport interface NoteToolOptions {\r\n backgroundColor?: string;\r\n size?: Size;\r\n}\r\n\r\nexport class NoteTool implements Tool {\r\n readonly name = 'note';\r\n private backgroundColor: string;\r\n private size: Size;\r\n\r\n constructor(options: NoteToolOptions = {}) {\r\n this.backgroundColor = options.backgroundColor ?? '#ffeb3b';\r\n this.size = options.size ?? { w: 200, h: 100 };\r\n }\r\n\r\n setOptions(options: NoteToolOptions): void {\r\n if (options.backgroundColor !== undefined) this.backgroundColor = options.backgroundColor;\r\n if (options.size !== undefined) this.size = options.size;\r\n }\r\n\r\n onPointerDown(_state: PointerState, _ctx: ToolContext): void {\r\n // Note is placed on pointer up\r\n }\r\n\r\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\r\n // No drag behavior for note placement\r\n }\r\n\r\n onPointerUp(state: PointerState, ctx: ToolContext): void {\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const note = createNote({\r\n position: world,\r\n size: { ...this.size },\r\n backgroundColor: this.backgroundColor,\r\n });\r\n ctx.store.add(note);\r\n ctx.requestRender();\r\n\r\n ctx.switchTool?.('select');\r\n ctx.editElement?.(note.id);\r\n }\r\n}\r\n","import type { Size } from '../core/types';\nimport type { Tool, ToolContext, PointerState } from './types';\nimport { createImage } from '../elements/element-factory';\n\nexport interface ImageToolOptions {\n size?: Size;\n}\n\nexport class ImageTool implements Tool {\n readonly name = 'image';\n private size: Size;\n private src: string | null = null;\n\n constructor(options: ImageToolOptions = {}) {\n this.size = options.size ?? { w: 300, h: 200 };\n }\n\n setSrc(src: string): void {\n this.src = src;\n }\n\n onPointerDown(_state: PointerState, _ctx: ToolContext): void {\n // No action on pointer down — image is placed on pointer up\n }\n\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\n // No action on pointer move\n }\n\n onPointerUp(state: PointerState, ctx: ToolContext): void {\n if (!this.src) return;\n\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\n const image = createImage({\n position: world,\n size: { ...this.size },\n src: this.src,\n });\n ctx.store.add(image);\n ctx.requestRender();\n\n this.src = null;\n ctx.switchTool?.('select');\n }\n}\n","export const VERSION = '0.2.2';\r\n\r\nexport { EventBus } from './core/event-bus';\r\nexport type { Point, StrokePoint, Size, Bounds } from './core/types';\r\nexport { exportState, parseState } from './core/state-serializer';\r\nexport type { CanvasState } from './core/state-serializer';\r\nexport { AutoSave } from './core/auto-save';\r\nexport type { AutoSaveOptions } from './core/auto-save';\r\n\r\nexport { Camera } from './canvas/camera';\r\nexport type { CameraOptions } from './canvas/camera';\r\nexport { Background } from './canvas/background';\r\nexport type { BackgroundOptions, BackgroundPattern } from './canvas/background';\r\nexport { InputHandler } from './canvas/input-handler';\r\nexport { Viewport } from './canvas/viewport';\r\nexport type { ViewportOptions } from './canvas/viewport';\r\n\r\nexport { ElementStore } from './elements/element-store';\r\nexport type { ElementUpdateEvent } from './elements/element-store';\r\nexport { ElementRenderer } from './elements/element-renderer';\r\nexport { NoteEditor } from './elements/note-editor';\r\nexport { createId } from './elements/create-id';\r\nexport {\r\n createStroke,\r\n createNote,\r\n createArrow,\r\n createImage,\r\n createHtmlElement,\r\n} from './elements/element-factory';\r\nexport {\r\n getArrowControlPoint,\r\n getArrowMidpoint,\r\n getBendFromPoint,\r\n getArrowTangentAngle,\r\n isNearBezier,\r\n getArrowBounds,\r\n} from './elements/arrow-geometry';\r\nexport type {\r\n CanvasElement,\r\n ElementType,\r\n StrokeElement,\r\n NoteElement,\r\n ArrowElement,\r\n ImageElement,\r\n HtmlElement,\r\n} from './elements/types';\r\n\r\nexport type { Command } from './history/types';\r\nexport {\r\n AddElementCommand,\r\n RemoveElementCommand,\r\n UpdateElementCommand,\r\n BatchCommand,\r\n} from './history/commands';\r\nexport { HistoryStack } from './history/history-stack';\r\nexport type { HistoryStackOptions } from './history/history-stack';\r\nexport { HistoryRecorder } from './history/history-recorder';\r\n\r\nexport { ToolManager } from './tools/tool-manager';\r\nexport { HandTool } from './tools/hand-tool';\r\nexport { PencilTool } from './tools/pencil-tool';\r\nexport type { PencilToolOptions } from './tools/pencil-tool';\r\nexport { EraserTool } from './tools/eraser-tool';\r\nexport type { EraserToolOptions } from './tools/eraser-tool';\r\nexport { SelectTool } from './tools/select-tool';\r\nexport { ArrowTool } from './tools/arrow-tool';\r\nexport type { ArrowToolOptions } from './tools/arrow-tool';\r\nexport { NoteTool } from './tools/note-tool';\r\nexport type { NoteToolOptions } from './tools/note-tool';\r\nexport { ImageTool } from './tools/image-tool';\r\nexport type { ImageToolOptions } from './tools/image-tool';\r\nexport type { Tool, ToolContext, PointerState, ToolName } from './tools/types';\r\n"],"mappings":"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","names":["minX","minY","HANDLE_HIT_PADDING"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/event-bus.ts","../src/core/state-serializer.ts","../src/core/auto-save.ts","../src/canvas/camera.ts","../src/canvas/background.ts","../src/canvas/input-handler.ts","../src/elements/element-store.ts","../src/elements/arrow-geometry.ts","../src/elements/stroke-smoothing.ts","../src/elements/element-renderer.ts","../src/elements/note-editor.ts","../src/tools/tool-manager.ts","../src/history/history-stack.ts","../src/history/commands.ts","../src/history/history-recorder.ts","../src/elements/create-id.ts","../src/elements/element-factory.ts","../src/canvas/viewport.ts","../src/tools/hand-tool.ts","../src/tools/pencil-tool.ts","../src/tools/eraser-tool.ts","../src/tools/arrow-handles.ts","../src/tools/select-tool.ts","../src/tools/arrow-tool.ts","../src/tools/note-tool.ts","../src/tools/image-tool.ts","../src/index.ts"],"sourcesContent":["type Listener<T> = (data: T) => void;\n\nexport class EventBus<TEvents extends { [K in keyof TEvents]: TEvents[K] }> {\n private listeners = new Map<keyof TEvents, Set<Listener<never>>>();\n\n on<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): () => void {\n const existing = this.listeners.get(event);\n if (existing) {\n existing.add(listener as Listener<never>);\n } else {\n const set = new Set<Listener<never>>([listener as Listener<never>]);\n this.listeners.set(event, set);\n }\n return () => this.off(event, listener);\n }\n\n off<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): void {\n this.listeners.get(event)?.delete(listener as Listener<never>);\n }\n\n emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void {\n this.listeners.get(event)?.forEach((listener) => listener(data as never));\n }\n\n clear(): void {\n this.listeners.clear();\n }\n}\n","import type { CanvasElement } from '../elements/types';\r\nimport type { Point } from './types';\r\n\r\nexport interface CanvasState {\r\n version: number;\r\n camera: {\r\n position: Point;\r\n zoom: number;\r\n };\r\n elements: CanvasElement[];\r\n}\r\n\r\nconst CURRENT_VERSION = 1;\r\n\r\nexport function exportState(\r\n elements: CanvasElement[],\r\n camera: { position: Point; zoom: number },\r\n): CanvasState {\r\n return {\r\n version: CURRENT_VERSION,\r\n camera: {\r\n position: { ...camera.position },\r\n zoom: camera.zoom,\r\n },\r\n elements: elements.map((el) => structuredClone(el)),\r\n };\r\n}\r\n\r\nexport function parseState(json: string): CanvasState {\r\n const data: unknown = JSON.parse(json);\r\n validateState(data);\r\n return data;\r\n}\r\n\r\nfunction validateState(data: unknown): asserts data is CanvasState {\r\n if (!data || typeof data !== 'object') {\r\n throw new Error('Invalid state: expected an object');\r\n }\r\n\r\n const obj = data as Record<string, unknown>;\r\n\r\n if (typeof obj['version'] !== 'number') {\r\n throw new Error('Invalid state: missing or invalid version');\r\n }\r\n\r\n if (!obj['camera'] || typeof obj['camera'] !== 'object') {\r\n throw new Error('Invalid state: missing camera');\r\n }\r\n\r\n const cam = obj['camera'] as Record<string, unknown>;\r\n if (!cam['position'] || typeof cam['position'] !== 'object') {\r\n throw new Error('Invalid state: missing camera.position');\r\n }\r\n\r\n const pos = cam['position'] as Record<string, unknown>;\r\n if (typeof pos['x'] !== 'number' || typeof pos['y'] !== 'number') {\r\n throw new Error('Invalid state: camera.position must have x and y numbers');\r\n }\r\n\r\n if (typeof cam['zoom'] !== 'number') {\r\n throw new Error('Invalid state: missing camera.zoom');\r\n }\r\n\r\n if (!Array.isArray(obj['elements'])) {\r\n throw new Error('Invalid state: elements must be an array');\r\n }\r\n\r\n for (const el of obj['elements'] as unknown[]) {\r\n validateElement(el);\r\n migrateElement(el as unknown as Record<string, unknown>);\r\n }\r\n}\r\n\r\nconst VALID_TYPES = new Set(['stroke', 'note', 'arrow', 'image', 'html']);\r\n\r\nfunction validateElement(el: unknown): asserts el is CanvasElement {\r\n if (!el || typeof el !== 'object') {\r\n throw new Error('Invalid element: expected an object');\r\n }\r\n\r\n const obj = el as Record<string, unknown>;\r\n\r\n if (typeof obj['id'] !== 'string') {\r\n throw new Error('Invalid element: missing id');\r\n }\r\n\r\n if (typeof obj['type'] !== 'string' || !VALID_TYPES.has(obj['type'])) {\r\n throw new Error(`Invalid element: unknown type \"${String(obj['type'])}\"`);\r\n }\r\n\r\n if (typeof obj['zIndex'] !== 'number') {\r\n throw new Error('Invalid element: missing zIndex');\r\n }\r\n}\r\n\r\nfunction migrateElement(obj: Record<string, unknown>): void {\r\n if (obj['type'] === 'arrow' && typeof obj['bend'] !== 'number') {\r\n obj['bend'] = 0;\r\n }\r\n\r\n if (obj['type'] === 'stroke' && Array.isArray(obj['points'])) {\r\n for (const pt of obj['points'] as Record<string, unknown>[]) {\r\n if (typeof pt['pressure'] !== 'number') {\r\n pt['pressure'] = 0.5;\r\n }\r\n }\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { Camera } from '../canvas/camera';\r\nimport { exportState, parseState } from './state-serializer';\r\nimport type { CanvasState } from './state-serializer';\r\n\r\nexport interface AutoSaveOptions {\r\n key?: string;\r\n debounceMs?: number;\r\n}\r\n\r\nconst DEFAULT_KEY = 'fieldnotes-autosave';\r\nconst DEFAULT_DEBOUNCE_MS = 1000;\r\n\r\nexport class AutoSave {\r\n private readonly key: string;\r\n private readonly debounceMs: number;\r\n private timerId: ReturnType<typeof setTimeout> | null = null;\r\n private unsubscribers: (() => void)[] = [];\r\n\r\n constructor(\r\n private readonly store: ElementStore,\r\n private readonly camera: Camera,\r\n options: AutoSaveOptions = {},\r\n ) {\r\n this.key = options.key ?? DEFAULT_KEY;\r\n this.debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\r\n }\r\n\r\n start(): void {\r\n const schedule = () => this.scheduleSave();\r\n\r\n this.unsubscribers = [\r\n this.store.on('add', schedule),\r\n this.store.on('remove', schedule),\r\n this.store.on('update', schedule),\r\n this.camera.onChange(schedule),\r\n ];\r\n }\r\n\r\n stop(): void {\r\n this.cancelPending();\r\n this.unsubscribers.forEach((fn) => fn());\r\n this.unsubscribers = [];\r\n }\r\n\r\n load(): CanvasState | null {\r\n if (typeof localStorage === 'undefined') return null;\r\n\r\n const json = localStorage.getItem(this.key);\r\n if (!json) return null;\r\n\r\n try {\r\n return parseState(json);\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n clear(): void {\r\n if (typeof localStorage === 'undefined') return;\r\n localStorage.removeItem(this.key);\r\n }\r\n\r\n private scheduleSave(): void {\r\n this.cancelPending();\r\n this.timerId = setTimeout(() => this.save(), this.debounceMs);\r\n }\r\n\r\n private cancelPending(): void {\r\n if (this.timerId !== null) {\r\n clearTimeout(this.timerId);\r\n this.timerId = null;\r\n }\r\n }\r\n\r\n private save(): void {\r\n if (typeof localStorage === 'undefined') return;\r\n\r\n const state = exportState(this.store.snapshot(), this.camera);\r\n localStorage.setItem(this.key, JSON.stringify(state));\r\n }\r\n}\r\n","import type { Point } from '../core/types';\n\nexport interface CameraOptions {\n minZoom?: number;\n maxZoom?: number;\n}\n\nconst DEFAULT_MIN_ZOOM = 0.1;\nconst DEFAULT_MAX_ZOOM = 10;\n\nexport class Camera {\n private x = 0;\n private y = 0;\n private z = 1;\n private readonly minZoom: number;\n private readonly maxZoom: number;\n private changeListeners = new Set<() => void>();\n\n constructor(options: CameraOptions = {}) {\n this.minZoom = options.minZoom ?? DEFAULT_MIN_ZOOM;\n this.maxZoom = options.maxZoom ?? DEFAULT_MAX_ZOOM;\n }\n\n get position(): Point {\n return { x: this.x, y: this.y };\n }\n\n get zoom(): number {\n return this.z;\n }\n\n pan(dx: number, dy: number): void {\n this.x += dx;\n this.y += dy;\n this.notifyChange();\n }\n\n moveTo(x: number, y: number): void {\n this.x = x;\n this.y = y;\n this.notifyChange();\n }\n\n setZoom(level: number): void {\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, level));\n this.notifyChange();\n }\n\n zoomAt(level: number, screenPoint: Point): void {\n const before = this.screenToWorld(screenPoint);\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, level));\n const after = this.screenToWorld(screenPoint);\n this.x += (after.x - before.x) * this.z;\n this.y += (after.y - before.y) * this.z;\n this.notifyChange();\n }\n\n screenToWorld(screen: Point): Point {\n return {\n x: (screen.x - this.x) / this.z,\n y: (screen.y - this.y) / this.z,\n };\n }\n\n worldToScreen(world: Point): Point {\n return {\n x: world.x * this.z + this.x,\n y: world.y * this.z + this.y,\n };\n }\n\n toCSSTransform(): string {\n return `translate3d(${this.x}px, ${this.y}px, 0) scale(${this.z})`;\n }\n\n onChange(listener: () => void): () => void {\n this.changeListeners.add(listener);\n return () => this.changeListeners.delete(listener);\n }\n\n private notifyChange(): void {\n this.changeListeners.forEach((fn) => fn());\n }\n}\n","import type { Camera } from './camera';\r\n\r\nexport type BackgroundPattern = 'dots' | 'grid' | 'none';\r\n\r\nexport interface BackgroundOptions {\r\n pattern?: BackgroundPattern;\r\n spacing?: number;\r\n color?: string;\r\n dotRadius?: number;\r\n lineWidth?: number;\r\n}\r\n\r\nconst MIN_PATTERN_SPACING = 16;\r\n\r\nconst DEFAULTS = {\r\n pattern: 'dots' as BackgroundPattern,\r\n spacing: 24,\r\n color: '#d0d0d0',\r\n dotRadius: 1,\r\n lineWidth: 0.5,\r\n};\r\n\r\nexport class Background {\r\n private readonly pattern: BackgroundPattern;\r\n private readonly spacing: number;\r\n private readonly color: string;\r\n private readonly dotRadius: number;\r\n private readonly lineWidth: number;\r\n\r\n constructor(options: BackgroundOptions = {}) {\r\n this.pattern = options.pattern ?? DEFAULTS.pattern;\r\n this.spacing = options.spacing ?? DEFAULTS.spacing;\r\n this.color = options.color ?? DEFAULTS.color;\r\n this.dotRadius = options.dotRadius ?? DEFAULTS.dotRadius;\r\n this.lineWidth = options.lineWidth ?? DEFAULTS.lineWidth;\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, camera: Camera): void {\r\n const { width, height } = ctx.canvas;\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n const cssWidth = width / dpr;\r\n const cssHeight = height / dpr;\r\n ctx.save();\r\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n ctx.clearRect(0, 0, cssWidth, cssHeight);\r\n\r\n if (this.pattern === 'dots') {\r\n this.renderDots(ctx, camera, cssWidth, cssHeight);\r\n } else if (this.pattern === 'grid') {\r\n this.renderGrid(ctx, camera, cssWidth, cssHeight);\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private adaptSpacing(baseSpacing: number, zoom: number): number {\r\n let spacing = baseSpacing * zoom;\r\n while (spacing < MIN_PATTERN_SPACING) {\r\n spacing *= 2;\r\n }\r\n return spacing;\r\n }\r\n\r\n private renderDots(\r\n ctx: CanvasRenderingContext2D,\r\n camera: Camera,\r\n width: number,\r\n height: number,\r\n ): void {\r\n const spacing = this.adaptSpacing(this.spacing, camera.zoom);\r\n const offsetX = camera.position.x % spacing;\r\n const offsetY = camera.position.y % spacing;\r\n const radius = this.dotRadius * Math.min(camera.zoom, 2);\r\n\r\n ctx.fillStyle = this.color;\r\n ctx.beginPath();\r\n\r\n for (let x = offsetX; x < width; x += spacing) {\r\n for (let y = offsetY; y < height; y += spacing) {\r\n ctx.moveTo(x + radius, y);\r\n ctx.arc(x, y, radius, 0, Math.PI * 2);\r\n }\r\n }\r\n\r\n ctx.fill();\r\n }\r\n\r\n private renderGrid(\r\n ctx: CanvasRenderingContext2D,\r\n camera: Camera,\r\n width: number,\r\n height: number,\r\n ): void {\r\n const spacing = this.adaptSpacing(this.spacing, camera.zoom);\r\n const offsetX = camera.position.x % spacing;\r\n const offsetY = camera.position.y % spacing;\r\n const lineW = this.lineWidth * Math.min(camera.zoom, 2);\r\n\r\n ctx.fillStyle = this.color;\r\n\r\n for (let x = offsetX; x < width; x += spacing) {\r\n ctx.fillRect(x, 0, lineW, height);\r\n }\r\n\r\n for (let y = offsetY; y < height; y += spacing) {\r\n ctx.fillRect(0, y, width, lineW);\r\n }\r\n }\r\n}\r\n","import type { Camera } from './camera';\r\nimport type { ToolManager } from '../tools/tool-manager';\r\nimport type { ToolContext, PointerState } from '../tools/types';\r\nimport type { SelectTool } from '../tools/select-tool';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport type { HistoryStack } from '../history/history-stack';\r\n\r\nconst ZOOM_SENSITIVITY = 0.001;\r\nconst MIDDLE_BUTTON = 1;\r\n\r\nexport interface InputHandlerOptions {\r\n toolManager?: ToolManager;\r\n toolContext?: ToolContext;\r\n historyRecorder?: HistoryRecorder;\r\n historyStack?: HistoryStack;\r\n}\r\n\r\nexport class InputHandler {\r\n private isPanning = false;\r\n private lastPointer = { x: 0, y: 0 };\r\n private spaceHeld = false;\r\n private activePointers = new Map<number, { x: number; y: number }>();\r\n private lastPinchDistance = 0;\r\n private lastPinchCenter = { x: 0, y: 0 };\r\n private toolManager: ToolManager | null;\r\n private toolContext: ToolContext | null;\r\n private historyRecorder: HistoryRecorder | null;\r\n private historyStack: HistoryStack | null;\r\n private isToolActive = false;\r\n private readonly abortController = new AbortController();\r\n\r\n constructor(\r\n private readonly element: HTMLElement,\r\n private readonly camera: Camera,\r\n options: InputHandlerOptions = {},\r\n ) {\r\n this.toolManager = options.toolManager ?? null;\r\n this.toolContext = options.toolContext ?? null;\r\n this.historyRecorder = options.historyRecorder ?? null;\r\n this.historyStack = options.historyStack ?? null;\r\n this.element.style.touchAction = 'none';\r\n this.bind();\r\n }\r\n\r\n setToolManager(toolManager: ToolManager, toolContext: ToolContext): void {\r\n this.toolManager = toolManager;\r\n this.toolContext = toolContext;\r\n }\r\n\r\n destroy(): void {\r\n this.abortController.abort();\r\n }\r\n\r\n private bind(): void {\r\n const opts = { signal: this.abortController.signal };\r\n\r\n this.element.addEventListener('wheel', this.onWheel, { ...opts, passive: false });\r\n this.element.addEventListener('pointerdown', this.onPointerDown, opts);\r\n this.element.addEventListener('pointermove', this.onPointerMove, opts);\r\n this.element.addEventListener('pointerup', this.onPointerUp, opts);\r\n this.element.addEventListener('pointerleave', this.onPointerUp, opts);\r\n this.element.addEventListener('pointercancel', this.onPointerUp, opts);\r\n window.addEventListener('keydown', this.onKeyDown, opts);\r\n window.addEventListener('keyup', this.onKeyUp, opts);\r\n }\r\n\r\n private onWheel = (e: WheelEvent): void => {\r\n e.preventDefault();\r\n const rect = this.element.getBoundingClientRect();\r\n const zoomFactor = 1 - e.deltaY * ZOOM_SENSITIVITY;\r\n const newZoom = this.camera.zoom * zoomFactor;\r\n this.camera.zoomAt(newZoom, {\r\n x: e.clientX - rect.left,\r\n y: e.clientY - rect.top,\r\n });\r\n };\r\n\r\n private onPointerDown = (e: PointerEvent): void => {\r\n this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });\r\n\r\n this.element.setPointerCapture?.(e.pointerId);\r\n\r\n if (this.activePointers.size === 2) {\r\n this.startPinch();\r\n this.cancelToolIfActive(e);\r\n return;\r\n }\r\n\r\n if (e.button === MIDDLE_BUTTON || (e.button === 0 && this.spaceHeld)) {\r\n this.isPanning = true;\r\n this.lastPointer = { x: e.clientX, y: e.clientY };\r\n return;\r\n }\r\n\r\n if (this.activePointers.size === 1 && e.button === 0) {\r\n this.dispatchToolDown(e);\r\n }\r\n };\r\n\r\n private onPointerMove = (e: PointerEvent): void => {\r\n if (this.activePointers.has(e.pointerId)) {\r\n this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });\r\n }\r\n\r\n if (this.activePointers.size === 2) {\r\n this.handlePinchMove();\r\n return;\r\n }\r\n\r\n if (this.isPanning) {\r\n const dx = e.clientX - this.lastPointer.x;\r\n const dy = e.clientY - this.lastPointer.y;\r\n this.lastPointer = { x: e.clientX, y: e.clientY };\r\n this.camera.pan(dx, dy);\r\n return;\r\n }\r\n\r\n if (this.isToolActive) {\r\n this.dispatchToolMove(e);\r\n } else if (this.activePointers.size === 0) {\r\n this.dispatchToolHover(e);\r\n }\r\n };\r\n\r\n private onPointerUp = (e: PointerEvent): void => {\r\n this.activePointers.delete(e.pointerId);\r\n\r\n if (this.activePointers.size < 2) {\r\n this.lastPinchDistance = 0;\r\n }\r\n\r\n if (this.isPanning && this.activePointers.size === 0) {\r\n this.isPanning = false;\r\n }\r\n\r\n if (this.isToolActive) {\r\n this.dispatchToolUp(e);\r\n this.isToolActive = false;\r\n }\r\n };\r\n\r\n private onKeyDown = (e: KeyboardEvent): void => {\r\n if ((e.target as HTMLElement)?.isContentEditable) return;\r\n\r\n if (e.key === ' ') {\r\n this.spaceHeld = true;\r\n }\r\n if (e.key === 'Delete' || e.key === 'Backspace') {\r\n this.deleteSelected();\r\n }\r\n if ((e.ctrlKey || e.metaKey) && e.key === 'z' && !e.shiftKey) {\r\n e.preventDefault();\r\n this.handleUndo();\r\n }\r\n if ((e.ctrlKey || e.metaKey) && (e.key === 'y' || (e.key === 'z' && e.shiftKey))) {\r\n e.preventDefault();\r\n this.handleRedo();\r\n }\r\n };\r\n\r\n private onKeyUp = (e: KeyboardEvent): void => {\r\n if (e.key === ' ') {\r\n this.spaceHeld = false;\r\n }\r\n };\r\n\r\n private startPinch(): void {\r\n this.isPanning = true;\r\n const [a, b] = this.getPinchPoints();\r\n this.lastPinchDistance = this.distance(a, b);\r\n this.lastPinchCenter = this.midpoint(a, b);\r\n this.lastPointer = { ...this.lastPinchCenter };\r\n }\r\n\r\n private handlePinchMove(): void {\r\n const [a, b] = this.getPinchPoints();\r\n const dist = this.distance(a, b);\r\n const center = this.midpoint(a, b);\r\n\r\n if (this.lastPinchDistance > 0) {\r\n const scale = dist / this.lastPinchDistance;\r\n const newZoom = this.camera.zoom * scale;\r\n this.camera.zoomAt(newZoom, center);\r\n }\r\n\r\n const dx = center.x - this.lastPointer.x;\r\n const dy = center.y - this.lastPointer.y;\r\n this.camera.pan(dx, dy);\r\n\r\n this.lastPinchDistance = dist;\r\n this.lastPinchCenter = center;\r\n this.lastPointer = { ...center };\r\n }\r\n\r\n private getPinchPoints(): [{ x: number; y: number }, { x: number; y: number }] {\r\n const pts = [...this.activePointers.values()];\r\n return [pts[0] ?? { x: 0, y: 0 }, pts[1] ?? { x: 0, y: 0 }];\r\n }\r\n\r\n private distance(a: { x: number; y: number }, b: { x: number; y: number }): number {\r\n const dx = a.x - b.x;\r\n const dy = a.y - b.y;\r\n return Math.sqrt(dx * dx + dy * dy);\r\n }\r\n\r\n private midpoint(\r\n a: { x: number; y: number },\r\n b: { x: number; y: number },\r\n ): { x: number; y: number } {\r\n return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\r\n }\r\n\r\n private toPointerState(e: PointerEvent): PointerState {\r\n const rect = this.element.getBoundingClientRect();\r\n return {\r\n x: e.clientX - rect.left,\r\n y: e.clientY - rect.top,\r\n pressure: e.pressure,\r\n };\r\n }\r\n\r\n private dispatchToolDown(e: PointerEvent): void {\r\n if (!this.toolManager || !this.toolContext) return;\r\n this.historyRecorder?.begin();\r\n this.isToolActive = true;\r\n this.toolManager.handlePointerDown(this.toPointerState(e), this.toolContext);\r\n }\r\n\r\n private dispatchToolMove(e: PointerEvent): void {\r\n if (!this.toolManager || !this.toolContext) return;\r\n this.toolManager.handlePointerMove(this.toPointerState(e), this.toolContext);\r\n }\r\n\r\n private dispatchToolHover(e: PointerEvent): void {\r\n if (!this.toolManager?.activeTool || !this.toolContext) return;\r\n const tool = this.toolManager.activeTool;\r\n if (tool.onHover) {\r\n tool.onHover(this.toPointerState(e), this.toolContext);\r\n }\r\n }\r\n\r\n private dispatchToolUp(e: PointerEvent): void {\r\n if (!this.toolManager || !this.toolContext) return;\r\n this.toolManager.handlePointerUp(this.toPointerState(e), this.toolContext);\r\n this.historyRecorder?.commit();\r\n }\r\n\r\n private deleteSelected(): void {\r\n if (!this.toolManager || !this.toolContext) return;\r\n const tool = this.toolManager.activeTool;\r\n if (tool?.name !== 'select') return;\r\n const selectTool = tool as SelectTool;\r\n const ids = selectTool.selectedIds;\r\n if (ids.length === 0) return;\r\n this.historyRecorder?.begin();\r\n for (const id of ids) {\r\n this.toolContext.store.remove(id);\r\n }\r\n this.historyRecorder?.commit();\r\n this.toolContext.requestRender();\r\n }\r\n\r\n private handleUndo(): void {\r\n if (!this.historyStack || !this.toolContext) return;\r\n this.historyRecorder?.pause();\r\n this.historyStack.undo(this.toolContext.store);\r\n this.historyRecorder?.resume();\r\n this.toolContext.requestRender();\r\n }\r\n\r\n private handleRedo(): void {\r\n if (!this.historyStack || !this.toolContext) return;\r\n this.historyRecorder?.pause();\r\n this.historyStack.redo(this.toolContext.store);\r\n this.historyRecorder?.resume();\r\n this.toolContext.requestRender();\r\n }\r\n\r\n private cancelToolIfActive(e: PointerEvent): void {\r\n if (this.isToolActive) {\r\n this.dispatchToolUp(e);\r\n this.isToolActive = false;\r\n }\r\n }\r\n}\r\n","import { EventBus } from '../core/event-bus';\nimport type { CanvasElement, ElementType } from './types';\n\nexport interface ElementUpdateEvent {\n previous: CanvasElement;\n current: CanvasElement;\n}\n\ninterface ElementStoreEvents {\n add: CanvasElement;\n remove: CanvasElement;\n update: ElementUpdateEvent;\n clear: null;\n}\n\nexport class ElementStore {\n private elements = new Map<string, CanvasElement>();\n private bus = new EventBus<ElementStoreEvents>();\n\n get count(): number {\n return this.elements.size;\n }\n\n getAll(): CanvasElement[] {\n return [...this.elements.values()].sort((a, b) => a.zIndex - b.zIndex);\n }\n\n getById(id: string): CanvasElement | undefined {\n return this.elements.get(id);\n }\n\n getElementsByType<T extends ElementType>(type: T): Extract<CanvasElement, { type: T }>[] {\n return this.getAll().filter(\n (el): el is Extract<CanvasElement, { type: T }> => el.type === type,\n );\n }\n\n add(element: CanvasElement): void {\n this.elements.set(element.id, element);\n this.bus.emit('add', element);\n }\n\n update(id: string, partial: Partial<CanvasElement>): void {\n const existing = this.elements.get(id);\n if (!existing) return;\n\n const updated = { ...existing, ...partial, id: existing.id, type: existing.type };\n this.elements.set(id, updated as CanvasElement);\n this.bus.emit('update', { previous: existing, current: updated as CanvasElement });\n }\n\n remove(id: string): void {\n const element = this.elements.get(id);\n if (!element) return;\n\n this.elements.delete(id);\n this.bus.emit('remove', element);\n }\n\n clear(): void {\n this.elements.clear();\n this.bus.emit('clear', null);\n }\n\n snapshot(): CanvasElement[] {\n return this.getAll().map((el) => ({ ...el }));\n }\n\n loadSnapshot(elements: CanvasElement[]): void {\n this.elements.clear();\n for (const el of elements) {\n this.elements.set(el.id, el);\n }\n }\n\n on<K extends keyof ElementStoreEvents>(\n event: K,\n listener: (data: ElementStoreEvents[K]) => void,\n ): () => void {\n return this.bus.on(event, listener);\n }\n}\n","import type { Point } from '../core/types';\n\ninterface Rect {\n x: number;\n y: number;\n w: number;\n h: number;\n}\n\nexport function getArrowControlPoint(from: Point, to: Point, bend: number): Point {\n const midX = (from.x + to.x) / 2;\n const midY = (from.y + to.y) / 2;\n\n if (bend === 0) return { x: midX, y: midY };\n\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const len = Math.sqrt(dx * dx + dy * dy);\n\n if (len === 0) return { x: midX, y: midY };\n\n const perpX = -dy / len;\n const perpY = dx / len;\n\n return {\n x: midX + perpX * bend,\n y: midY + perpY * bend,\n };\n}\n\nexport function getArrowMidpoint(from: Point, to: Point, bend: number): Point {\n const cp = getArrowControlPoint(from, to, bend);\n return {\n x: 0.25 * from.x + 0.5 * cp.x + 0.25 * to.x,\n y: 0.25 * from.y + 0.5 * cp.y + 0.25 * to.y,\n };\n}\n\nexport function getBendFromPoint(from: Point, to: Point, dragPoint: Point): number {\n const midX = (from.x + to.x) / 2;\n const midY = (from.y + to.y) / 2;\n\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const len = Math.sqrt(dx * dx + dy * dy);\n\n if (len === 0) return 0;\n\n const perpX = -dy / len;\n const perpY = dx / len;\n\n return (dragPoint.x - midX) * perpX + (dragPoint.y - midY) * perpY;\n}\n\nexport function getArrowTangentAngle(from: Point, to: Point, bend: number, t: number): number {\n const cp = getArrowControlPoint(from, to, bend);\n\n const tangentX = 2 * (1 - t) * (cp.x - from.x) + 2 * t * (to.x - cp.x);\n const tangentY = 2 * (1 - t) * (cp.y - from.y) + 2 * t * (to.y - cp.y);\n\n return Math.atan2(tangentY, tangentX);\n}\n\nexport function isNearBezier(\n point: Point,\n from: Point,\n to: Point,\n bend: number,\n threshold: number,\n): boolean {\n if (bend === 0) return isNearLine(point, from, to, threshold);\n\n const cp = getArrowControlPoint(from, to, bend);\n const segments = 20;\n\n for (let i = 0; i < segments; i++) {\n const t0 = i / segments;\n const t1 = (i + 1) / segments;\n const a = bezierPoint(from, cp, to, t0);\n const b = bezierPoint(from, cp, to, t1);\n if (isNearLine(point, a, b, threshold)) return true;\n }\n\n return false;\n}\n\nexport function getArrowBounds(from: Point, to: Point, bend: number): Rect {\n if (bend === 0) {\n const minX = Math.min(from.x, to.x);\n const minY = Math.min(from.y, to.y);\n return {\n x: minX,\n y: minY,\n w: Math.abs(to.x - from.x),\n h: Math.abs(to.y - from.y),\n };\n }\n\n const cp = getArrowControlPoint(from, to, bend);\n const steps = 20;\n let minX = Math.min(from.x, to.x);\n let minY = Math.min(from.y, to.y);\n let maxX = Math.max(from.x, to.x);\n let maxY = Math.max(from.y, to.y);\n\n for (let i = 1; i < steps; i++) {\n const t = i / steps;\n const p = bezierPoint(from, cp, to, t);\n if (p.x < minX) minX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.x > maxX) maxX = p.x;\n if (p.y > maxY) maxY = p.y;\n }\n\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\n}\n\nfunction bezierPoint(from: Point, cp: Point, to: Point, t: number): Point {\n const mt = 1 - t;\n return {\n x: mt * mt * from.x + 2 * mt * t * cp.x + t * t * to.x,\n y: mt * mt * from.y + 2 * mt * t * cp.y + t * t * to.y,\n };\n}\n\nfunction isNearLine(point: Point, a: Point, b: Point, threshold: number): boolean {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const lenSq = dx * dx + dy * dy;\n\n if (lenSq === 0) {\n return Math.hypot(point.x - a.x, point.y - a.y) <= threshold;\n }\n\n const t = Math.max(0, Math.min(1, ((point.x - a.x) * dx + (point.y - a.y) * dy) / lenSq));\n const projX = a.x + t * dx;\n const projY = a.y + t * dy;\n return Math.hypot(point.x - projX, point.y - projY) <= threshold;\n}\n","import type { Point, StrokePoint } from '../core/types';\r\n\r\nexport interface CurveSegment {\r\n start: StrokePoint;\r\n cp1: Point;\r\n cp2: Point;\r\n end: StrokePoint;\r\n}\r\n\r\nconst MIN_PRESSURE_SCALE = 0.2;\r\n\r\nexport function pressureToWidth(pressure: number, baseWidth: number): number {\r\n return baseWidth * (MIN_PRESSURE_SCALE + (1 - MIN_PRESSURE_SCALE) * pressure);\r\n}\r\n\r\nexport function simplifyPoints(points: StrokePoint[], tolerance: number): StrokePoint[] {\r\n if (points.length <= 2) return points.slice();\r\n return rdp(points, 0, points.length - 1, tolerance);\r\n}\r\n\r\nfunction rdp(points: StrokePoint[], start: number, end: number, tolerance: number): StrokePoint[] {\r\n const first = points[start];\r\n const last = points[end];\r\n if (!first || !last) return [];\r\n\r\n if (end - start <= 1) return [first, last];\r\n\r\n let maxDist = 0;\r\n let maxIndex = start;\r\n\r\n for (let i = start + 1; i < end; i++) {\r\n const pt = points[i];\r\n if (!pt) continue;\r\n const dist = perpendicularDistance(pt, first, last);\r\n if (dist > maxDist) {\r\n maxDist = dist;\r\n maxIndex = i;\r\n }\r\n }\r\n\r\n if (maxDist <= tolerance) return [first, last];\r\n\r\n const left = rdp(points, start, maxIndex, tolerance);\r\n const right = rdp(points, maxIndex, end, tolerance);\r\n\r\n return left.concat(right.slice(1));\r\n}\r\n\r\nfunction perpendicularDistance(pt: Point, lineStart: Point, lineEnd: Point): number {\r\n const dx = lineEnd.x - lineStart.x;\r\n const dy = lineEnd.y - lineStart.y;\r\n const lenSq = dx * dx + dy * dy;\r\n\r\n if (lenSq === 0) {\r\n const ex = pt.x - lineStart.x;\r\n const ey = pt.y - lineStart.y;\r\n return Math.sqrt(ex * ex + ey * ey);\r\n }\r\n\r\n const num = Math.abs(dy * pt.x - dx * pt.y + lineEnd.x * lineStart.y - lineEnd.y * lineStart.x);\r\n return num / Math.sqrt(lenSq);\r\n}\r\n\r\nexport function smoothToSegments(points: StrokePoint[]): CurveSegment[] {\r\n if (points.length < 2) return [];\r\n\r\n if (points.length === 2) {\r\n const p0 = points[0];\r\n const p1 = points[1];\r\n if (!p0 || !p1) return [];\r\n const mx = (p0.x + p1.x) / 2;\r\n const my = (p0.y + p1.y) / 2;\r\n return [{ start: p0, cp1: { x: mx, y: my }, cp2: { x: mx, y: my }, end: p1 }];\r\n }\r\n\r\n const segments: CurveSegment[] = [];\r\n const n = points.length;\r\n\r\n for (let i = 0; i < n - 1; i++) {\r\n const p0 = points[Math.max(0, i - 1)];\r\n const p1 = points[i];\r\n const p2 = points[i + 1];\r\n const p3 = points[Math.min(n - 1, i + 2)];\r\n if (!p0 || !p1 || !p2 || !p3) continue;\r\n\r\n const cp1: Point = {\r\n x: p1.x + (p2.x - p0.x) / 6,\r\n y: p1.y + (p2.y - p0.y) / 6,\r\n };\r\n const cp2: Point = {\r\n x: p2.x - (p3.x - p1.x) / 6,\r\n y: p2.y - (p3.y - p1.y) / 6,\r\n };\r\n\r\n segments.push({ start: p1, cp1, cp2, end: p2 });\r\n }\r\n\r\n return segments;\r\n}\r\n","import type { CanvasElement, StrokeElement, ArrowElement } from './types';\r\nimport { getArrowControlPoint, getArrowTangentAngle } from './arrow-geometry';\r\nimport { smoothToSegments, pressureToWidth } from './stroke-smoothing';\r\n\r\nconst DOM_ELEMENT_TYPES = new Set(['note', 'image', 'html']);\r\nconst ARROWHEAD_LENGTH = 12;\r\nconst ARROWHEAD_ANGLE = Math.PI / 6;\r\n\r\nexport class ElementRenderer {\r\n isDomElement(element: CanvasElement): boolean {\r\n return DOM_ELEMENT_TYPES.has(element.type);\r\n }\r\n\r\n renderCanvasElement(ctx: CanvasRenderingContext2D, element: CanvasElement): void {\r\n switch (element.type) {\r\n case 'stroke':\r\n this.renderStroke(ctx, element);\r\n break;\r\n case 'arrow':\r\n this.renderArrow(ctx, element);\r\n break;\r\n }\r\n }\r\n\r\n private renderStroke(ctx: CanvasRenderingContext2D, stroke: StrokeElement): void {\r\n if (stroke.points.length < 2) return;\r\n\r\n ctx.save();\r\n ctx.translate(stroke.position.x, stroke.position.y);\r\n ctx.strokeStyle = stroke.color;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n ctx.globalAlpha = stroke.opacity;\r\n\r\n const segments = smoothToSegments(stroke.points);\r\n for (const seg of segments) {\r\n const w =\r\n (pressureToWidth(seg.start.pressure, stroke.width) +\r\n pressureToWidth(seg.end.pressure, stroke.width)) /\r\n 2;\r\n ctx.lineWidth = w;\r\n ctx.beginPath();\r\n ctx.moveTo(seg.start.x, seg.start.y);\r\n ctx.bezierCurveTo(seg.cp1.x, seg.cp1.y, seg.cp2.x, seg.cp2.y, seg.end.x, seg.end.y);\r\n ctx.stroke();\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private renderArrow(ctx: CanvasRenderingContext2D, arrow: ArrowElement): void {\r\n ctx.save();\r\n ctx.strokeStyle = arrow.color;\r\n ctx.lineWidth = arrow.width;\r\n ctx.lineCap = 'round';\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(arrow.from.x, arrow.from.y);\r\n\r\n if (arrow.bend !== 0) {\r\n const cp = getArrowControlPoint(arrow.from, arrow.to, arrow.bend);\r\n ctx.quadraticCurveTo(cp.x, cp.y, arrow.to.x, arrow.to.y);\r\n } else {\r\n ctx.lineTo(arrow.to.x, arrow.to.y);\r\n }\r\n ctx.stroke();\r\n\r\n this.renderArrowhead(ctx, arrow);\r\n ctx.restore();\r\n }\r\n\r\n private renderArrowhead(ctx: CanvasRenderingContext2D, arrow: ArrowElement): void {\r\n const angle = getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 1);\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(arrow.to.x, arrow.to.y);\r\n ctx.lineTo(\r\n arrow.to.x - ARROWHEAD_LENGTH * Math.cos(angle - ARROWHEAD_ANGLE),\r\n arrow.to.y - ARROWHEAD_LENGTH * Math.sin(angle - ARROWHEAD_ANGLE),\r\n );\r\n ctx.lineTo(\r\n arrow.to.x - ARROWHEAD_LENGTH * Math.cos(angle + ARROWHEAD_ANGLE),\r\n arrow.to.y - ARROWHEAD_LENGTH * Math.sin(angle + ARROWHEAD_ANGLE),\r\n );\r\n ctx.closePath();\r\n ctx.fillStyle = arrow.color;\r\n ctx.fill();\r\n }\r\n}\r\n","import type { ElementStore } from './element-store';\n\nexport class NoteEditor {\n private editingId: string | null = null;\n private editingNode: HTMLDivElement | null = null;\n private blurHandler: (() => void) | null = null;\n private keyHandler: ((e: KeyboardEvent) => void) | null = null;\n private pointerHandler: ((e: PointerEvent) => void) | null = null;\n private pendingEditId: string | null = null;\n\n get isEditing(): boolean {\n return this.editingId !== null;\n }\n\n get editingElementId(): string | null {\n return this.editingId;\n }\n\n startEditing(node: HTMLDivElement, elementId: string, store: ElementStore): void {\n if (this.editingId === elementId) return;\n\n if (this.editingId) {\n this.stopEditing(store);\n }\n\n this.pendingEditId = elementId;\n\n requestAnimationFrame(() => {\n if (this.pendingEditId !== elementId) return;\n this.pendingEditId = null;\n this.activateEditing(node, elementId, store);\n });\n }\n\n stopEditing(store: ElementStore): void {\n this.pendingEditId = null;\n\n if (!this.editingId || !this.editingNode) return;\n\n const text = this.editingNode.textContent ?? '';\n store.update(this.editingId, { text });\n\n this.editingNode.contentEditable = 'false';\n Object.assign(this.editingNode.style, {\n userSelect: 'none',\n cursor: 'default',\n });\n\n if (this.blurHandler) {\n this.editingNode.removeEventListener('blur', this.blurHandler);\n }\n if (this.keyHandler) {\n this.editingNode.removeEventListener('keydown', this.keyHandler);\n }\n if (this.pointerHandler) {\n this.editingNode.removeEventListener('pointerdown', this.pointerHandler);\n }\n\n this.editingId = null;\n this.editingNode = null;\n this.blurHandler = null;\n this.keyHandler = null;\n this.pointerHandler = null;\n }\n\n destroy(store: ElementStore): void {\n this.pendingEditId = null;\n if (this.isEditing) {\n this.stopEditing(store);\n }\n }\n\n private activateEditing(node: HTMLDivElement, elementId: string, store: ElementStore): void {\n this.editingId = elementId;\n this.editingNode = node;\n\n node.contentEditable = 'true';\n Object.assign(node.style, {\n userSelect: 'text',\n cursor: 'text',\n outline: 'none',\n });\n node.focus();\n\n const selection = window.getSelection?.();\n if (selection) {\n const range = document.createRange();\n range.selectNodeContents(node);\n range.collapse(false);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n\n this.blurHandler = () => this.stopEditing(store);\n this.keyHandler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n node.blur();\n }\n e.stopPropagation();\n };\n this.pointerHandler = (e: PointerEvent) => {\n e.stopPropagation();\n };\n\n node.addEventListener('blur', this.blurHandler);\n node.addEventListener('keydown', this.keyHandler);\n node.addEventListener('pointerdown', this.pointerHandler);\n }\n}\n","import type { Tool, ToolContext, PointerState } from './types';\r\n\r\nexport class ToolManager {\r\n private tools = new Map<string, Tool>();\r\n private current: Tool | null = null;\r\n private changeListeners = new Set<(name: string) => void>();\r\n\r\n get activeTool(): Tool | null {\r\n return this.current;\r\n }\r\n\r\n get toolNames(): string[] {\r\n return [...this.tools.keys()];\r\n }\r\n\r\n register(tool: Tool): void {\r\n this.tools.set(tool.name, tool);\r\n }\r\n\r\n getTool<T extends Tool = Tool>(name: string): T | undefined {\r\n return this.tools.get(name) as T | undefined;\r\n }\r\n\r\n setTool(name: string, ctx: ToolContext): void {\r\n const tool = this.tools.get(name);\r\n if (!tool) return;\r\n\r\n this.current?.onDeactivate?.(ctx);\r\n this.current = tool;\r\n this.current.onActivate?.(ctx);\r\n this.changeListeners.forEach((fn) => fn(name));\r\n }\r\n\r\n handlePointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.current?.onPointerDown(state, ctx);\r\n }\r\n\r\n handlePointerMove(state: PointerState, ctx: ToolContext): void {\r\n this.current?.onPointerMove(state, ctx);\r\n }\r\n\r\n handlePointerUp(state: PointerState, ctx: ToolContext): void {\r\n this.current?.onPointerUp(state, ctx);\r\n }\r\n\r\n onChange(listener: (name: string) => void): () => void {\r\n this.changeListeners.add(listener);\r\n return () => this.changeListeners.delete(listener);\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\nimport type { Command } from './types';\n\nexport interface HistoryStackOptions {\n maxSize?: number;\n}\n\nconst DEFAULT_MAX_SIZE = 100;\n\nexport class HistoryStack {\n private undoStack: Command[] = [];\n private redoStack: Command[] = [];\n private readonly maxSize: number;\n private changeListeners = new Set<() => void>();\n\n constructor(options: HistoryStackOptions = {}) {\n this.maxSize = options.maxSize ?? DEFAULT_MAX_SIZE;\n }\n\n get canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n get canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n get undoCount(): number {\n return this.undoStack.length;\n }\n\n get redoCount(): number {\n return this.redoStack.length;\n }\n\n push(command: Command): void {\n this.undoStack.push(command);\n this.redoStack = [];\n\n if (this.undoStack.length > this.maxSize) {\n this.undoStack.shift();\n }\n\n this.notifyChange();\n }\n\n undo(store: ElementStore): boolean {\n const command = this.undoStack.pop();\n if (!command) return false;\n\n command.undo(store);\n this.redoStack.push(command);\n this.notifyChange();\n return true;\n }\n\n redo(store: ElementStore): boolean {\n const command = this.redoStack.pop();\n if (!command) return false;\n\n command.execute(store);\n this.undoStack.push(command);\n this.notifyChange();\n return true;\n }\n\n clear(): void {\n this.undoStack = [];\n this.redoStack = [];\n this.notifyChange();\n }\n\n onChange(listener: () => void): () => void {\n this.changeListeners.add(listener);\n return () => this.changeListeners.delete(listener);\n }\n\n private notifyChange(): void {\n this.changeListeners.forEach((fn) => fn());\n }\n}\n","import type { CanvasElement } from '../elements/types';\nimport type { ElementStore } from '../elements/element-store';\nimport type { Command } from './types';\n\nexport class AddElementCommand implements Command {\n private readonly element: CanvasElement;\n\n constructor(element: CanvasElement) {\n this.element = { ...element };\n }\n\n execute(store: ElementStore): void {\n store.add(this.element);\n }\n\n undo(store: ElementStore): void {\n store.remove(this.element.id);\n }\n}\n\nexport class RemoveElementCommand implements Command {\n private readonly element: CanvasElement;\n\n constructor(element: CanvasElement) {\n this.element = { ...element };\n }\n\n execute(store: ElementStore): void {\n store.remove(this.element.id);\n }\n\n undo(store: ElementStore): void {\n store.add(this.element);\n }\n}\n\nexport class UpdateElementCommand implements Command {\n constructor(\n private readonly id: string,\n private readonly previous: CanvasElement,\n private readonly current: CanvasElement,\n ) {}\n\n execute(store: ElementStore): void {\n store.update(this.id, { ...this.current });\n }\n\n undo(store: ElementStore): void {\n store.update(this.id, { ...this.previous });\n }\n}\n\nexport class BatchCommand implements Command {\n readonly commands: readonly Command[];\n\n constructor(commands: Command[]) {\n this.commands = [...commands];\n }\n\n execute(store: ElementStore): void {\n for (const cmd of this.commands) {\n cmd.execute(store);\n }\n }\n\n undo(store: ElementStore): void {\n for (let i = this.commands.length - 1; i >= 0; i--) {\n this.commands[i]?.undo(store);\n }\n }\n}\n","import type { ElementStore } from '../elements/element-store';\nimport type { CanvasElement } from '../elements/types';\nimport type { Command } from './types';\nimport type { HistoryStack } from './history-stack';\nimport {\n AddElementCommand,\n RemoveElementCommand,\n UpdateElementCommand,\n BatchCommand,\n} from './commands';\n\nexport class HistoryRecorder {\n private recording = true;\n private transaction: Command[] | null = null;\n private updateSnapshots = new Map<string, CanvasElement>();\n private unsubscribers: (() => void)[];\n\n constructor(\n private readonly store: ElementStore,\n private readonly stack: HistoryStack,\n ) {\n this.unsubscribers = [\n store.on('add', (el) => this.onAdd(el)),\n store.on('remove', (el) => this.onRemove(el)),\n store.on('update', ({ previous, current }) => this.onUpdate(previous, current)),\n ];\n }\n\n pause(): void {\n this.recording = false;\n }\n\n resume(): void {\n this.recording = true;\n }\n\n begin(): void {\n this.transaction = [];\n this.updateSnapshots.clear();\n }\n\n commit(): void {\n if (!this.transaction) return;\n\n const finalCommands = this.flushUpdateSnapshots();\n const all = [...this.transaction, ...finalCommands];\n this.transaction = null;\n this.updateSnapshots.clear();\n\n if (all.length === 0) return;\n const first = all[0];\n this.stack.push(all.length === 1 && first ? first : new BatchCommand(all));\n }\n\n rollback(): void {\n this.transaction = null;\n this.updateSnapshots.clear();\n }\n\n destroy(): void {\n this.unsubscribers.forEach((fn) => fn());\n }\n\n private record(command: Command): void {\n if (this.transaction) {\n this.transaction.push(command);\n } else {\n this.stack.push(command);\n }\n }\n\n private onAdd(element: CanvasElement): void {\n if (!this.recording) return;\n this.record(new AddElementCommand(element));\n }\n\n private onRemove(element: CanvasElement): void {\n if (!this.recording) return;\n\n if (this.transaction && this.updateSnapshots.has(element.id)) {\n this.updateSnapshots.delete(element.id);\n }\n\n this.record(new RemoveElementCommand(element));\n }\n\n private onUpdate(previous: CanvasElement, current: CanvasElement): void {\n if (!this.recording) return;\n\n if (this.transaction) {\n if (!this.updateSnapshots.has(current.id)) {\n this.updateSnapshots.set(current.id, { ...previous });\n }\n } else {\n this.stack.push(new UpdateElementCommand(current.id, previous, current));\n }\n }\n\n private flushUpdateSnapshots(): Command[] {\n const commands: Command[] = [];\n for (const [id, previous] of this.updateSnapshots) {\n const current = this.store.getById(id);\n if (current) {\n commands.push(new UpdateElementCommand(id, previous, current));\n }\n }\n return commands;\n }\n}\n","let counter = 0;\n\nexport function createId(prefix: string): string {\n return `${prefix}_${Date.now().toString(36)}_${(counter++).toString(36)}`;\n}\n","import type { Point, Size, StrokePoint } from '../core/types';\r\nimport type { StrokeElement, NoteElement, ArrowElement, ImageElement, HtmlElement } from './types';\r\nimport { createId } from './create-id';\r\n\r\ninterface BaseDefaults {\r\n position?: Point;\r\n zIndex?: number;\r\n locked?: boolean;\r\n}\r\n\r\ninterface StrokeInput extends BaseDefaults {\r\n points: StrokePoint[];\r\n color?: string;\r\n width?: number;\r\n opacity?: number;\r\n}\r\n\r\ninterface NoteInput extends BaseDefaults {\r\n position: Point;\r\n size?: Size;\r\n text?: string;\r\n backgroundColor?: string;\r\n}\r\n\r\ninterface ArrowInput extends BaseDefaults {\r\n from: Point;\r\n to: Point;\r\n bend?: number;\r\n color?: string;\r\n width?: number;\r\n}\r\n\r\ninterface ImageInput extends BaseDefaults {\r\n position: Point;\r\n size: Size;\r\n src: string;\r\n}\r\n\r\ninterface HtmlInput extends BaseDefaults {\r\n position: Point;\r\n size: Size;\r\n}\r\n\r\nexport function createStroke(input: StrokeInput): StrokeElement {\r\n return {\r\n id: createId('stroke'),\r\n type: 'stroke',\r\n position: input.position ?? { x: 0, y: 0 },\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n points: input.points,\r\n color: input.color ?? '#000000',\r\n width: input.width ?? 2,\r\n opacity: input.opacity ?? 1,\r\n };\r\n}\r\n\r\nexport function createNote(input: NoteInput): NoteElement {\r\n return {\r\n id: createId('note'),\r\n type: 'note',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n size: input.size ?? { w: 200, h: 100 },\r\n text: input.text ?? '',\r\n backgroundColor: input.backgroundColor ?? '#ffeb3b',\r\n };\r\n}\r\n\r\nexport function createArrow(input: ArrowInput): ArrowElement {\r\n return {\r\n id: createId('arrow'),\r\n type: 'arrow',\r\n position: input.position ?? { x: 0, y: 0 },\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n from: input.from,\r\n to: input.to,\r\n bend: input.bend ?? 0,\r\n color: input.color ?? '#000000',\r\n width: input.width ?? 2,\r\n };\r\n}\r\n\r\nexport function createImage(input: ImageInput): ImageElement {\r\n return {\r\n id: createId('image'),\r\n type: 'image',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n size: input.size,\r\n src: input.src,\r\n };\r\n}\r\n\r\nexport function createHtmlElement(input: HtmlInput): HtmlElement {\r\n return {\r\n id: createId('html'),\r\n type: 'html',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n size: input.size,\r\n };\r\n}\r\n","import { Camera } from './camera';\r\nimport type { CameraOptions } from './camera';\r\nimport { InputHandler } from './input-handler';\r\nimport { Background } from './background';\r\nimport type { BackgroundOptions } from './background';\r\nimport { ElementStore } from '../elements/element-store';\r\nimport { ElementRenderer } from '../elements/element-renderer';\r\nimport { NoteEditor } from '../elements/note-editor';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { ToolManager } from '../tools/tool-manager';\r\nimport type { ToolContext } from '../tools/types';\r\nimport { HistoryStack } from '../history/history-stack';\r\nimport { HistoryRecorder } from '../history/history-recorder';\r\nimport { createImage, createHtmlElement } from '../elements/element-factory';\r\nimport { exportState, parseState } from '../core/state-serializer';\r\nimport type { CanvasState } from '../core/state-serializer';\r\n\r\nexport interface ViewportOptions {\r\n camera?: CameraOptions;\r\n background?: BackgroundOptions;\r\n}\r\n\r\nexport class Viewport {\r\n readonly camera: Camera;\r\n readonly store: ElementStore;\r\n readonly toolManager: ToolManager;\r\n readonly history: HistoryStack;\r\n readonly domLayer: HTMLDivElement;\r\n private readonly canvasEl: HTMLCanvasElement;\r\n private readonly wrapper: HTMLDivElement;\r\n private readonly unsubCamera: () => void;\r\n private readonly unsubStore: (() => void)[];\r\n private readonly inputHandler: InputHandler;\r\n private readonly background: Background;\r\n private readonly renderer: ElementRenderer;\r\n private readonly noteEditor: NoteEditor;\r\n private readonly historyRecorder: HistoryRecorder;\r\n readonly toolContext: ToolContext;\r\n private resizeObserver: ResizeObserver | null = null;\r\n private animFrameId = 0;\r\n private needsRender = true;\r\n private domNodes = new Map<string, HTMLDivElement>();\r\n private htmlContent = new Map<string, HTMLElement>();\r\n private interactingElementId: string | null = null;\r\n\r\n constructor(\r\n private readonly container: HTMLElement,\r\n options: ViewportOptions = {},\r\n ) {\r\n this.camera = new Camera(options.camera);\r\n this.background = new Background(options.background);\r\n this.store = new ElementStore();\r\n this.toolManager = new ToolManager();\r\n this.renderer = new ElementRenderer();\r\n this.noteEditor = new NoteEditor();\r\n this.history = new HistoryStack();\r\n this.historyRecorder = new HistoryRecorder(this.store, this.history);\r\n\r\n this.wrapper = this.createWrapper();\r\n this.canvasEl = this.createCanvas();\r\n this.domLayer = this.createDomLayer();\r\n\r\n this.wrapper.appendChild(this.canvasEl);\r\n this.wrapper.appendChild(this.domLayer);\r\n this.container.appendChild(this.wrapper);\r\n\r\n this.toolContext = {\r\n camera: this.camera,\r\n store: this.store,\r\n requestRender: () => this.requestRender(),\r\n switchTool: (name: string) => this.toolManager.setTool(name, this.toolContext),\r\n editElement: (id: string) => this.startEditingNote(id),\r\n setCursor: (cursor: string) => {\r\n this.wrapper.style.cursor = cursor;\r\n },\r\n };\r\n\r\n this.inputHandler = new InputHandler(this.wrapper, this.camera, {\r\n toolManager: this.toolManager,\r\n toolContext: this.toolContext,\r\n historyRecorder: this.historyRecorder,\r\n historyStack: this.history,\r\n });\r\n\r\n this.unsubCamera = this.camera.onChange(() => {\r\n this.applyCameraTransform();\r\n this.requestRender();\r\n });\r\n\r\n this.unsubStore = [\r\n this.store.on('add', () => this.requestRender()),\r\n this.store.on('remove', (el) => this.removeDomNode(el.id)),\r\n this.store.on('update', () => this.requestRender()),\r\n this.store.on('clear', () => this.clearDomNodes()),\r\n ];\r\n\r\n this.wrapper.addEventListener('dblclick', this.onDblClick);\r\n this.wrapper.addEventListener('dragover', this.onDragOver);\r\n this.wrapper.addEventListener('drop', this.onDrop);\r\n this.observeResize();\r\n this.syncCanvasSize();\r\n this.startRenderLoop();\r\n }\r\n\r\n get ctx(): CanvasRenderingContext2D | null {\r\n return this.canvasEl.getContext('2d');\r\n }\r\n\r\n requestRender(): void {\r\n this.needsRender = true;\r\n }\r\n\r\n exportState(): CanvasState {\r\n return exportState(this.store.snapshot(), this.camera);\r\n }\r\n\r\n exportJSON(): string {\r\n return JSON.stringify(this.exportState());\r\n }\r\n\r\n loadState(state: CanvasState): void {\r\n this.historyRecorder.pause();\r\n this.noteEditor.destroy(this.store);\r\n this.clearDomNodes();\r\n this.store.loadSnapshot(state.elements);\r\n this.history.clear();\r\n this.historyRecorder.resume();\r\n this.camera.moveTo(state.camera.position.x, state.camera.position.y);\r\n this.camera.setZoom(state.camera.zoom);\r\n }\r\n\r\n loadJSON(json: string): void {\r\n this.loadState(parseState(json));\r\n }\r\n\r\n undo(): boolean {\r\n this.historyRecorder.pause();\r\n const result = this.history.undo(this.store);\r\n this.historyRecorder.resume();\r\n if (result) this.requestRender();\r\n return result;\r\n }\r\n\r\n redo(): boolean {\r\n this.historyRecorder.pause();\r\n const result = this.history.redo(this.store);\r\n this.historyRecorder.resume();\r\n if (result) this.requestRender();\r\n return result;\r\n }\r\n\r\n addImage(src: string, position: { x: number; y: number }, size = { w: 300, h: 200 }): string {\r\n const image = createImage({ position, size, src });\r\n this.historyRecorder.begin();\r\n this.store.add(image);\r\n this.historyRecorder.commit();\r\n this.requestRender();\r\n return image.id;\r\n }\r\n\r\n addHtmlElement(\r\n dom: HTMLElement,\r\n position: { x: number; y: number },\r\n size = { w: 200, h: 150 },\r\n ): string {\r\n const el = createHtmlElement({ position, size });\r\n this.htmlContent.set(el.id, dom);\r\n this.historyRecorder.begin();\r\n this.store.add(el);\r\n this.historyRecorder.commit();\r\n this.requestRender();\r\n return el.id;\r\n }\r\n\r\n destroy(): void {\r\n cancelAnimationFrame(this.animFrameId);\r\n this.stopInteracting();\r\n this.noteEditor.destroy(this.store);\r\n this.historyRecorder.destroy();\r\n this.wrapper.removeEventListener('dblclick', this.onDblClick);\r\n this.wrapper.removeEventListener('dragover', this.onDragOver);\r\n this.wrapper.removeEventListener('drop', this.onDrop);\r\n this.inputHandler.destroy();\r\n this.unsubCamera();\r\n this.unsubStore.forEach((fn) => fn());\r\n this.resizeObserver?.disconnect();\r\n this.resizeObserver = null;\r\n this.wrapper.remove();\r\n }\r\n\r\n private startRenderLoop(): void {\r\n const loop = (): void => {\r\n if (this.needsRender) {\r\n this.render();\r\n this.needsRender = false;\r\n }\r\n this.animFrameId = requestAnimationFrame(loop);\r\n };\r\n this.animFrameId = requestAnimationFrame(loop);\r\n }\r\n\r\n private render(): void {\r\n const ctx = this.ctx;\r\n if (!ctx) return;\r\n\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n ctx.save();\r\n ctx.scale(dpr, dpr);\r\n\r\n this.background.render(ctx, this.camera);\r\n\r\n ctx.save();\r\n ctx.translate(this.camera.position.x, this.camera.position.y);\r\n ctx.scale(this.camera.zoom, this.camera.zoom);\r\n\r\n for (const element of this.store.getAll()) {\r\n if (this.renderer.isDomElement(element)) {\r\n this.syncDomNode(element);\r\n } else {\r\n this.renderer.renderCanvasElement(ctx, element);\r\n }\r\n }\r\n\r\n const activeTool = this.toolManager.activeTool;\r\n if (activeTool?.renderOverlay) {\r\n activeTool.renderOverlay(ctx);\r\n }\r\n\r\n ctx.restore();\r\n ctx.restore();\r\n }\r\n\r\n private startEditingNote(id: string): void {\r\n const element = this.store.getById(id);\r\n if (!element || element.type !== 'note') return;\r\n\r\n this.render();\r\n\r\n const node = this.domNodes.get(id);\r\n if (node) {\r\n this.noteEditor.startEditing(node, id, this.store);\r\n }\r\n }\r\n\r\n private onDblClick = (e: MouseEvent): void => {\r\n const el = document.elementFromPoint(e.clientX, e.clientY);\r\n\r\n const nodeEl = (el as HTMLElement | null)?.closest<HTMLDivElement>('[data-element-id]');\r\n if (nodeEl) {\r\n const elementId = nodeEl.dataset['elementId'];\r\n if (elementId) {\r\n const element = this.store.getById(elementId);\r\n if (element?.type === 'note') {\r\n this.startEditingNote(elementId);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n const rect = this.wrapper.getBoundingClientRect();\r\n const screen = { x: e.clientX - rect.left, y: e.clientY - rect.top };\r\n const world = this.camera.screenToWorld(screen);\r\n const hit = this.hitTestWorld(world);\r\n if (hit?.type === 'html') {\r\n this.startInteracting(hit.id);\r\n }\r\n };\r\n\r\n private hitTestWorld(world: { x: number; y: number }): CanvasElement | null {\r\n const elements = this.store.getAll().reverse();\r\n for (const el of elements) {\r\n if (!('size' in el)) continue;\r\n const { x, y } = el.position;\r\n const { w, h } = el.size;\r\n if (world.x >= x && world.x <= x + w && world.y >= y && world.y <= y + h) {\r\n return el;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n private startInteracting(id: string): void {\r\n this.stopInteracting();\r\n const node = this.domNodes.get(id);\r\n if (!node) return;\r\n\r\n this.interactingElementId = id;\r\n node.style.pointerEvents = 'auto';\r\n node.addEventListener('pointerdown', this.onInteractNodePointerDown);\r\n\r\n window.addEventListener('keydown', this.onInteractKeyDown);\r\n window.addEventListener('pointerdown', this.onInteractPointerDown);\r\n }\r\n\r\n stopInteracting(): void {\r\n if (!this.interactingElementId) return;\r\n\r\n const node = this.domNodes.get(this.interactingElementId);\r\n if (node) {\r\n node.style.pointerEvents = 'none';\r\n node.removeEventListener('pointerdown', this.onInteractNodePointerDown);\r\n }\r\n\r\n this.interactingElementId = null;\r\n window.removeEventListener('keydown', this.onInteractKeyDown);\r\n window.removeEventListener('pointerdown', this.onInteractPointerDown);\r\n }\r\n\r\n private onInteractNodePointerDown = (e: PointerEvent): void => {\r\n e.stopPropagation();\r\n };\r\n\r\n private onInteractKeyDown = (e: KeyboardEvent): void => {\r\n if (e.key === 'Escape') {\r\n this.stopInteracting();\r\n }\r\n };\r\n\r\n private onInteractPointerDown = (e: PointerEvent): void => {\r\n if (!this.interactingElementId) return;\r\n const target = e.target as HTMLElement | null;\r\n if (!target) return;\r\n\r\n const node = this.domNodes.get(this.interactingElementId);\r\n if (node && !node.contains(target)) {\r\n this.stopInteracting();\r\n }\r\n };\r\n\r\n private onDragOver = (e: DragEvent): void => {\r\n e.preventDefault();\r\n };\r\n\r\n private onDrop = (e: DragEvent): void => {\r\n e.preventDefault();\r\n const files = e.dataTransfer?.files;\r\n if (!files) return;\r\n\r\n const rect = this.wrapper.getBoundingClientRect();\r\n\r\n for (const file of files) {\r\n if (!file.type.startsWith('image/')) continue;\r\n\r\n const reader = new FileReader();\r\n reader.onload = () => {\r\n const src = reader.result;\r\n if (typeof src !== 'string') return;\r\n\r\n const screenPos = { x: e.clientX - rect.left, y: e.clientY - rect.top };\r\n const worldPos = this.camera.screenToWorld(screenPos);\r\n this.addImage(src, worldPos);\r\n };\r\n reader.readAsDataURL(file);\r\n }\r\n };\r\n\r\n private syncDomNode(element: CanvasElement): void {\r\n let node = this.domNodes.get(element.id);\r\n if (!node) {\r\n node = document.createElement('div');\r\n node.dataset['elementId'] = element.id;\r\n Object.assign(node.style, {\r\n position: 'absolute',\r\n pointerEvents: 'auto',\r\n });\r\n this.domLayer.appendChild(node);\r\n this.domNodes.set(element.id, node);\r\n }\r\n\r\n const size = 'size' in element ? element.size : null;\r\n Object.assign(node.style, {\r\n left: `${element.position.x}px`,\r\n top: `${element.position.y}px`,\r\n width: size ? `${size.w}px` : 'auto',\r\n height: size ? `${size.h}px` : 'auto',\r\n });\r\n\r\n this.renderDomContent(node, element);\r\n }\r\n\r\n private renderDomContent(node: HTMLDivElement, element: CanvasElement): void {\r\n if (element.type === 'note') {\r\n if (!node.dataset['initialized']) {\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n backgroundColor: element.backgroundColor,\r\n padding: '8px',\r\n borderRadius: '4px',\r\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\r\n fontSize: '14px',\r\n overflow: 'hidden',\r\n cursor: 'default',\r\n userSelect: 'none',\r\n wordWrap: 'break-word',\r\n });\r\n node.textContent = element.text || '';\r\n\r\n node.addEventListener('dblclick', (e) => {\r\n e.stopPropagation();\r\n const id = node.dataset['elementId'];\r\n if (id) this.startEditingNote(id);\r\n });\r\n }\r\n\r\n if (!this.noteEditor.isEditing || this.noteEditor.editingElementId !== element.id) {\r\n if (node.textContent !== element.text) {\r\n node.textContent = element.text || '';\r\n }\r\n node.style.backgroundColor = element.backgroundColor;\r\n }\r\n }\r\n\r\n if (element.type === 'image') {\r\n if (!node.dataset['initialized']) {\r\n node.dataset['initialized'] = 'true';\r\n const img = document.createElement('img');\r\n img.src = element.src;\r\n Object.assign(img.style, {\r\n width: '100%',\r\n height: '100%',\r\n objectFit: 'contain',\r\n pointerEvents: 'none',\r\n });\r\n img.draggable = false;\r\n node.appendChild(img);\r\n } else {\r\n const img = node.querySelector('img');\r\n if (img && img.src !== element.src) {\r\n img.src = element.src;\r\n }\r\n }\r\n }\r\n\r\n if (element.type === 'html' && !node.dataset['initialized']) {\r\n const content = this.htmlContent.get(element.id);\r\n if (content) {\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n overflow: 'hidden',\r\n pointerEvents: 'none',\r\n });\r\n node.appendChild(content);\r\n }\r\n }\r\n }\r\n\r\n private removeDomNode(id: string): void {\r\n this.htmlContent.delete(id);\r\n const node = this.domNodes.get(id);\r\n if (node) {\r\n node.remove();\r\n this.domNodes.delete(id);\r\n }\r\n this.requestRender();\r\n }\r\n\r\n private clearDomNodes(): void {\r\n this.domNodes.forEach((node) => node.remove());\r\n this.domNodes.clear();\r\n this.htmlContent.clear();\r\n this.requestRender();\r\n }\r\n\r\n private createWrapper(): HTMLDivElement {\r\n const el = document.createElement('div');\r\n Object.assign(el.style, {\r\n position: 'relative',\r\n width: '100%',\r\n height: '100%',\r\n overflow: 'hidden',\r\n });\r\n return el;\r\n }\r\n\r\n private createCanvas(): HTMLCanvasElement {\r\n const el = document.createElement('canvas');\r\n Object.assign(el.style, {\r\n position: 'absolute',\r\n top: '0',\r\n left: '0',\r\n width: '100%',\r\n height: '100%',\r\n });\r\n return el;\r\n }\r\n\r\n private createDomLayer(): HTMLDivElement {\r\n const el = document.createElement('div');\r\n Object.assign(el.style, {\r\n position: 'absolute',\r\n top: '0',\r\n left: '0',\r\n width: '100%',\r\n height: '100%',\r\n pointerEvents: 'none',\r\n transformOrigin: '0 0',\r\n });\r\n return el;\r\n }\r\n\r\n private applyCameraTransform(): void {\r\n this.domLayer.style.transform = this.camera.toCSSTransform();\r\n }\r\n\r\n private syncCanvasSize(): void {\r\n const rect = this.container.getBoundingClientRect();\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n this.canvasEl.width = rect.width * dpr;\r\n this.canvasEl.height = rect.height * dpr;\r\n this.requestRender();\r\n }\r\n\r\n private observeResize(): void {\r\n if (typeof ResizeObserver === 'undefined') return;\r\n this.resizeObserver = new ResizeObserver(() => this.syncCanvasSize());\r\n this.resizeObserver.observe(this.container);\r\n }\r\n}\r\n","import type { Tool, ToolContext, PointerState } from './types';\n\nexport class HandTool implements Tool {\n readonly name = 'hand';\n private panning = false;\n private lastScreen = { x: 0, y: 0 };\n\n onActivate(ctx: ToolContext): void {\n ctx.setCursor?.('grab');\n }\n\n onDeactivate(ctx: ToolContext): void {\n ctx.setCursor?.('default');\n }\n\n onPointerDown(state: PointerState, ctx: ToolContext): void {\n this.panning = true;\n this.lastScreen = { x: state.x, y: state.y };\n ctx.setCursor?.('grabbing');\n }\n\n onPointerMove(state: PointerState, ctx: ToolContext): void {\n if (!this.panning) return;\n const dx = state.x - this.lastScreen.x;\n const dy = state.y - this.lastScreen.y;\n this.lastScreen = { x: state.x, y: state.y };\n ctx.camera.pan(dx, dy);\n }\n\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\n this.panning = false;\n ctx.setCursor?.('grab');\n }\n}\n","import type { StrokePoint } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createStroke } from '../elements/element-factory';\r\nimport { simplifyPoints, smoothToSegments, pressureToWidth } from '../elements/stroke-smoothing';\r\n\r\nexport interface PencilToolOptions {\r\n color?: string;\r\n width?: number;\r\n smoothing?: number;\r\n}\r\n\r\nconst MIN_POINTS_FOR_STROKE = 2;\r\nconst DEFAULT_SMOOTHING = 1.5;\r\nconst DEFAULT_PRESSURE = 0.5;\r\n\r\nexport class PencilTool implements Tool {\r\n readonly name = 'pencil';\r\n private drawing = false;\r\n private points: StrokePoint[] = [];\r\n private color: string;\r\n private width: number;\r\n private smoothing: number;\r\n\r\n constructor(options: PencilToolOptions = {}) {\r\n this.color = options.color ?? '#000000';\r\n this.width = options.width ?? 2;\r\n this.smoothing = options.smoothing ?? DEFAULT_SMOOTHING;\r\n }\r\n\r\n onActivate(ctx: ToolContext): void {\r\n ctx.setCursor?.('crosshair');\r\n }\r\n\r\n onDeactivate(ctx: ToolContext): void {\r\n ctx.setCursor?.('default');\r\n }\r\n\r\n setOptions(options: PencilToolOptions): void {\r\n if (options.color !== undefined) this.color = options.color;\r\n if (options.width !== undefined) this.width = options.width;\r\n if (options.smoothing !== undefined) this.smoothing = options.smoothing;\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.drawing = true;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const pressure = state.pressure === 0 ? DEFAULT_PRESSURE : state.pressure;\r\n this.points = [{ x: world.x, y: world.y, pressure }];\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const pressure = state.pressure === 0 ? DEFAULT_PRESSURE : state.pressure;\r\n this.points.push({ x: world.x, y: world.y, pressure });\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.drawing = false;\r\n\r\n if (this.points.length < MIN_POINTS_FOR_STROKE) {\r\n this.points = [];\r\n return;\r\n }\r\n\r\n const simplified = simplifyPoints(this.points, this.smoothing);\r\n const stroke = createStroke({\r\n points: simplified,\r\n color: this.color,\r\n width: this.width,\r\n });\r\n ctx.store.add(stroke);\r\n this.points = [];\r\n ctx.requestRender();\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (!this.drawing || this.points.length < 2) return;\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.color;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n ctx.globalAlpha = 0.8;\r\n\r\n const segments = smoothToSegments(this.points);\r\n for (const seg of segments) {\r\n const w =\r\n (pressureToWidth(seg.start.pressure, this.width) +\r\n pressureToWidth(seg.end.pressure, this.width)) /\r\n 2;\r\n ctx.lineWidth = w;\r\n ctx.beginPath();\r\n ctx.moveTo(seg.start.x, seg.start.y);\r\n ctx.bezierCurveTo(seg.cp1.x, seg.cp1.y, seg.cp2.x, seg.cp2.y, seg.end.x, seg.end.y);\r\n ctx.stroke();\r\n }\r\n\r\n ctx.restore();\r\n }\r\n}\r\n","import type { Point } from '../core/types';\nimport type { Tool, ToolContext, PointerState } from './types';\nimport type { StrokeElement } from '../elements/types';\n\nexport interface EraserToolOptions {\n radius?: number;\n}\n\nconst DEFAULT_RADIUS = 20;\n\nfunction makeEraserCursor(radius: number): string {\n const size = radius * 2;\n const svg = `<svg xmlns='http://www.w3.org/2000/svg' width='${size}' height='${size}'><circle cx='${radius}' cy='${radius}' r='${radius - 1}' fill='none' stroke='%23666' stroke-width='1.5'/></svg>`;\n return `url(\"data:image/svg+xml,${svg}\") ${radius} ${radius}, crosshair`;\n}\n\nexport class EraserTool implements Tool {\n readonly name = 'eraser';\n private erasing = false;\n private readonly radius: number;\n private readonly cursor: string;\n\n constructor(options: EraserToolOptions = {}) {\n this.radius = options.radius ?? DEFAULT_RADIUS;\n this.cursor = makeEraserCursor(this.radius);\n }\n\n onActivate(ctx: ToolContext): void {\n ctx.setCursor?.(this.cursor);\n }\n\n onDeactivate(ctx: ToolContext): void {\n ctx.setCursor?.('default');\n }\n\n onPointerDown(state: PointerState, ctx: ToolContext): void {\n this.erasing = true;\n this.eraseAt(state, ctx);\n }\n\n onPointerMove(state: PointerState, ctx: ToolContext): void {\n if (!this.erasing) return;\n this.eraseAt(state, ctx);\n }\n\n onPointerUp(_state: PointerState, _ctx: ToolContext): void {\n this.erasing = false;\n }\n\n private eraseAt(state: PointerState, ctx: ToolContext): void {\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\n const strokes = ctx.store.getElementsByType('stroke');\n let erased = false;\n\n for (const stroke of strokes) {\n if (this.strokeIntersects(stroke, world)) {\n ctx.store.remove(stroke.id);\n erased = true;\n }\n }\n\n if (erased) ctx.requestRender();\n }\n\n private strokeIntersects(stroke: StrokeElement, point: Point): boolean {\n const radiusSq = this.radius * this.radius;\n return stroke.points.some((p) => {\n const dx = p.x + stroke.position.x - point.x;\n const dy = p.y + stroke.position.y - point.y;\n return dx * dx + dy * dy <= radiusSq;\n });\n }\n}\n","import type { Point } from '../core/types';\nimport type { ArrowElement } from '../elements/types';\nimport type { ToolContext } from './types';\nimport { getArrowMidpoint, getBendFromPoint } from '../elements/arrow-geometry';\n\nexport type ArrowHandle = 'start' | 'mid' | 'end';\n\nconst HANDLE_RADIUS = 5;\nconst HANDLE_HIT_PADDING = 4;\n\nconst ARROW_HANDLE_CURSORS: Record<ArrowHandle, string> = {\n start: 'crosshair',\n end: 'crosshair',\n mid: 'grab',\n};\n\nexport function getArrowHandleCursor(handle: ArrowHandle, active: boolean): string {\n if (handle === 'mid' && active) return 'grabbing';\n return ARROW_HANDLE_CURSORS[handle];\n}\n\nexport function getArrowHandlePositions(arrow: ArrowElement): [ArrowHandle, Point][] {\n const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);\n return [\n ['start', arrow.from],\n ['mid', mid],\n ['end', arrow.to],\n ];\n}\n\nexport function hitTestArrowHandles(\n world: Point,\n selectedIds: string[],\n ctx: ToolContext,\n): { elementId: string; handle: ArrowHandle } | null {\n if (selectedIds.length === 0) return null;\n\n const zoom = ctx.camera.zoom;\n const hitRadius = (HANDLE_RADIUS + HANDLE_HIT_PADDING) / zoom;\n\n for (const id of selectedIds) {\n const el = ctx.store.getById(id);\n if (!el || el.type !== 'arrow') continue;\n\n const handles = getArrowHandlePositions(el);\n for (const [handle, pos] of handles) {\n const dx = world.x - pos.x;\n const dy = world.y - pos.y;\n if (dx * dx + dy * dy <= hitRadius * hitRadius) {\n return { elementId: id, handle };\n }\n }\n }\n\n return null;\n}\n\nexport function applyArrowHandleDrag(\n handle: ArrowHandle,\n elementId: string,\n world: Point,\n ctx: ToolContext,\n): void {\n const el = ctx.store.getById(elementId);\n if (!el || el.type !== 'arrow') return;\n\n switch (handle) {\n case 'start':\n ctx.store.update(elementId, {\n from: { x: world.x, y: world.y },\n position: { x: world.x, y: world.y },\n });\n break;\n case 'end':\n ctx.store.update(elementId, {\n to: { x: world.x, y: world.y },\n });\n break;\n case 'mid': {\n const bend = getBendFromPoint(el.from, el.to, world);\n ctx.store.update(elementId, { bend });\n break;\n }\n }\n\n ctx.requestRender();\n}\n\nexport function renderArrowHandles(\n canvasCtx: CanvasRenderingContext2D,\n arrow: ArrowElement,\n zoom: number,\n): void {\n const radius = HANDLE_RADIUS / zoom;\n const handles = getArrowHandlePositions(arrow);\n\n canvasCtx.setLineDash([]);\n canvasCtx.lineWidth = 1.5 / zoom;\n\n for (const [handle, pos] of handles) {\n canvasCtx.fillStyle = handle === 'mid' ? '#2196F3' : '#ffffff';\n canvasCtx.strokeStyle = '#2196F3';\n\n canvasCtx.beginPath();\n canvasCtx.arc(pos.x, pos.y, radius, 0, Math.PI * 2);\n canvasCtx.fill();\n canvasCtx.stroke();\n }\n}\n","import type { Point } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { isNearBezier, getArrowBounds } from '../elements/arrow-geometry';\r\nimport {\r\n type ArrowHandle,\r\n hitTestArrowHandles,\r\n applyArrowHandleDrag,\r\n renderArrowHandles,\r\n getArrowHandleCursor,\r\n} from './arrow-handles';\r\n\r\ninterface Rect {\r\n x: number;\r\n y: number;\r\n w: number;\r\n h: number;\r\n}\r\ntype HandlePosition = 'nw' | 'ne' | 'sw' | 'se';\r\n\r\nconst HANDLE_SIZE = 8;\r\nconst HANDLE_HIT_PADDING = 4;\r\nconst SELECTION_PAD = 4;\r\nconst MIN_ELEMENT_SIZE = 20;\r\n\r\nconst HANDLE_CURSORS: Record<HandlePosition, string> = {\r\n nw: 'nwse-resize',\r\n se: 'nwse-resize',\r\n ne: 'nesw-resize',\r\n sw: 'nesw-resize',\r\n};\r\n\r\ntype Mode =\r\n | { type: 'idle' }\r\n | { type: 'dragging' }\r\n | { type: 'marquee'; start: Point }\r\n | { type: 'resizing'; elementId: string; handle: HandlePosition }\r\n | { type: 'arrow-handle'; elementId: string; handle: ArrowHandle };\r\n\r\nexport class SelectTool implements Tool {\r\n readonly name = 'select';\r\n private _selectedIds: string[] = [];\r\n private mode: Mode = { type: 'idle' };\r\n private lastWorld: Point = { x: 0, y: 0 };\r\n private currentWorld: Point = { x: 0, y: 0 };\r\n private ctx: ToolContext | null = null;\r\n\r\n get selectedIds(): string[] {\r\n return [...this._selectedIds];\r\n }\r\n\r\n get isMarqueeActive(): boolean {\r\n return this.mode.type === 'marquee';\r\n }\r\n\r\n onActivate(ctx: ToolContext): void {\r\n this.ctx = ctx;\r\n }\r\n\r\n onDeactivate(ctx: ToolContext): void {\r\n this._selectedIds = [];\r\n this.mode = { type: 'idle' };\r\n ctx.setCursor?.('default');\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.ctx = ctx;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.lastWorld = world;\r\n this.currentWorld = world;\r\n\r\n const arrowHit = hitTestArrowHandles(world, this._selectedIds, ctx);\r\n if (arrowHit) {\r\n this.mode = {\r\n type: 'arrow-handle',\r\n elementId: arrowHit.elementId,\r\n handle: arrowHit.handle,\r\n };\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n const resizeHit = this.hitTestResizeHandle(world, ctx);\r\n if (resizeHit) {\r\n const el = ctx.store.getById(resizeHit.elementId);\r\n if (el) {\r\n this.mode = {\r\n type: 'resizing',\r\n elementId: resizeHit.elementId,\r\n handle: resizeHit.handle,\r\n };\r\n ctx.requestRender();\r\n return;\r\n }\r\n }\r\n\r\n const hit = this.hitTest(world, ctx);\r\n if (hit) {\r\n const alreadySelected = this._selectedIds.includes(hit.id);\r\n if (!alreadySelected) {\r\n this._selectedIds = [hit.id];\r\n }\r\n this.mode = hit.locked ? { type: 'idle' } : { type: 'dragging' };\r\n } else {\r\n this._selectedIds = [];\r\n this.mode = { type: 'marquee', start: world };\r\n }\r\n\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.currentWorld = world;\r\n\r\n if (this.mode.type === 'arrow-handle') {\r\n ctx.setCursor?.(getArrowHandleCursor(this.mode.handle, true));\r\n applyArrowHandleDrag(this.mode.handle, this.mode.elementId, world, ctx);\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'resizing') {\r\n ctx.setCursor?.(HANDLE_CURSORS[this.mode.handle]);\r\n this.handleResize(world, ctx);\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'dragging' && this._selectedIds.length > 0) {\r\n ctx.setCursor?.('move');\r\n const dx = world.x - this.lastWorld.x;\r\n const dy = world.y - this.lastWorld.y;\r\n this.lastWorld = world;\r\n\r\n for (const id of this._selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || el.locked) continue;\r\n\r\n if (el.type === 'arrow') {\r\n ctx.store.update(id, {\r\n position: { x: el.position.x + dx, y: el.position.y + dy },\r\n from: { x: el.from.x + dx, y: el.from.y + dy },\r\n to: { x: el.to.x + dx, y: el.to.y + dy },\r\n });\r\n } else {\r\n ctx.store.update(id, {\r\n position: { x: el.position.x + dx, y: el.position.y + dy },\r\n });\r\n }\r\n }\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'marquee') {\r\n ctx.setCursor?.('crosshair');\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n this.updateHoverCursor(world, ctx);\r\n }\r\n\r\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\r\n if (this.mode.type === 'marquee') {\r\n const rect = this.getMarqueeRect();\r\n if (rect) {\r\n this._selectedIds = this.findElementsInRect(rect, ctx);\r\n }\r\n ctx.requestRender();\r\n }\r\n\r\n this.mode = { type: 'idle' };\r\n ctx.setCursor?.('default');\r\n }\r\n\r\n onHover(state: PointerState, ctx: ToolContext): void {\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.updateHoverCursor(world, ctx);\r\n }\r\n\r\n renderOverlay(canvasCtx: CanvasRenderingContext2D): void {\r\n this.renderMarquee(canvasCtx);\r\n this.renderSelectionBoxes(canvasCtx);\r\n }\r\n\r\n private updateHoverCursor(world: Point, ctx: ToolContext): void {\r\n const arrowHit = hitTestArrowHandles(world, this._selectedIds, ctx);\r\n if (arrowHit) {\r\n ctx.setCursor?.(getArrowHandleCursor(arrowHit.handle, false));\r\n return;\r\n }\r\n\r\n const resizeHit = this.hitTestResizeHandle(world, ctx);\r\n if (resizeHit) {\r\n ctx.setCursor?.(HANDLE_CURSORS[resizeHit.handle]);\r\n return;\r\n }\r\n\r\n const hit = this.hitTest(world, ctx);\r\n ctx.setCursor?.(hit ? 'move' : 'default');\r\n }\r\n\r\n private handleResize(world: Point, ctx: ToolContext): void {\r\n if (this.mode.type !== 'resizing') return;\r\n\r\n const el = ctx.store.getById(this.mode.elementId);\r\n if (!el || !('size' in el) || el.locked) return;\r\n\r\n const { handle } = this.mode;\r\n const dx = world.x - this.lastWorld.x;\r\n const dy = world.y - this.lastWorld.y;\r\n this.lastWorld = world;\r\n\r\n let { x, y, w, h } = { x: el.position.x, y: el.position.y, w: el.size.w, h: el.size.h };\r\n\r\n switch (handle) {\r\n case 'se':\r\n w += dx;\r\n h += dy;\r\n break;\r\n case 'sw':\r\n x += dx;\r\n w -= dx;\r\n h += dy;\r\n break;\r\n case 'ne':\r\n y += dy;\r\n w += dx;\r\n h -= dy;\r\n break;\r\n case 'nw':\r\n x += dx;\r\n y += dy;\r\n w -= dx;\r\n h -= dy;\r\n break;\r\n }\r\n\r\n if (w < MIN_ELEMENT_SIZE) {\r\n if (handle === 'nw' || handle === 'sw') x = el.position.x + el.size.w - MIN_ELEMENT_SIZE;\r\n w = MIN_ELEMENT_SIZE;\r\n }\r\n if (h < MIN_ELEMENT_SIZE) {\r\n if (handle === 'nw' || handle === 'ne') y = el.position.y + el.size.h - MIN_ELEMENT_SIZE;\r\n h = MIN_ELEMENT_SIZE;\r\n }\r\n\r\n ctx.store.update(this.mode.elementId, {\r\n position: { x, y },\r\n size: { w, h },\r\n });\r\n ctx.requestRender();\r\n }\r\n\r\n private hitTestResizeHandle(\r\n world: Point,\r\n ctx: ToolContext,\r\n ): { elementId: string; handle: HandlePosition } | null {\r\n if (this._selectedIds.length === 0) return null;\r\n\r\n const zoom = ctx.camera.zoom;\r\n const handleHalf = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / zoom;\r\n\r\n for (const id of this._selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || !('size' in el)) continue;\r\n\r\n const bounds = this.getElementBounds(el);\r\n if (!bounds) continue;\r\n\r\n const corners = this.getHandlePositions(bounds);\r\n for (const [handle, pos] of corners) {\r\n if (Math.abs(world.x - pos.x) <= handleHalf && Math.abs(world.y - pos.y) <= handleHalf) {\r\n return { elementId: id, handle };\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private getHandlePositions(bounds: Rect): [HandlePosition, Point][] {\r\n return [\r\n ['nw', { x: bounds.x, y: bounds.y }],\r\n ['ne', { x: bounds.x + bounds.w, y: bounds.y }],\r\n ['sw', { x: bounds.x, y: bounds.y + bounds.h }],\r\n ['se', { x: bounds.x + bounds.w, y: bounds.y + bounds.h }],\r\n ];\r\n }\r\n\r\n private renderMarquee(canvasCtx: CanvasRenderingContext2D): void {\r\n if (this.mode.type !== 'marquee') return;\r\n\r\n const rect = this.getMarqueeRect();\r\n if (!rect) return;\r\n\r\n canvasCtx.save();\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.fillStyle = 'rgba(33, 150, 243, 0.08)';\r\n canvasCtx.lineWidth = 1;\r\n canvasCtx.setLineDash([4, 4]);\r\n canvasCtx.strokeRect(rect.x, rect.y, rect.w, rect.h);\r\n canvasCtx.fillRect(rect.x, rect.y, rect.w, rect.h);\r\n canvasCtx.restore();\r\n }\r\n\r\n private renderSelectionBoxes(canvasCtx: CanvasRenderingContext2D): void {\r\n if (this._selectedIds.length === 0 || !this.ctx) return;\r\n\r\n const zoom = this.ctx.camera.zoom;\r\n const handleWorldSize = HANDLE_SIZE / zoom;\r\n\r\n canvasCtx.save();\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.lineWidth = 1.5 / zoom;\r\n canvasCtx.setLineDash([4 / zoom, 4 / zoom]);\r\n\r\n for (const id of this._selectedIds) {\r\n const el = this.ctx.store.getById(id);\r\n if (!el) continue;\r\n\r\n if (el.type === 'arrow') {\r\n renderArrowHandles(canvasCtx, el, zoom);\r\n continue;\r\n }\r\n\r\n const bounds = this.getElementBounds(el);\r\n if (!bounds) continue;\r\n\r\n const pad = SELECTION_PAD / zoom;\r\n canvasCtx.strokeRect(bounds.x - pad, bounds.y - pad, bounds.w + pad * 2, bounds.h + pad * 2);\r\n\r\n if ('size' in el) {\r\n canvasCtx.setLineDash([]);\r\n canvasCtx.fillStyle = '#ffffff';\r\n const corners = this.getHandlePositions(bounds);\r\n for (const [, pos] of corners) {\r\n canvasCtx.fillRect(\r\n pos.x - handleWorldSize / 2,\r\n pos.y - handleWorldSize / 2,\r\n handleWorldSize,\r\n handleWorldSize,\r\n );\r\n canvasCtx.strokeRect(\r\n pos.x - handleWorldSize / 2,\r\n pos.y - handleWorldSize / 2,\r\n handleWorldSize,\r\n handleWorldSize,\r\n );\r\n }\r\n canvasCtx.setLineDash([4 / zoom, 4 / zoom]);\r\n }\r\n }\r\n\r\n canvasCtx.restore();\r\n }\r\n\r\n private getMarqueeRect(): Rect | null {\r\n if (this.mode.type !== 'marquee') return null;\r\n\r\n const { start } = this.mode;\r\n const end = this.currentWorld;\r\n const x = Math.min(start.x, end.x);\r\n const y = Math.min(start.y, end.y);\r\n const w = Math.abs(end.x - start.x);\r\n const h = Math.abs(end.y - start.y);\r\n\r\n if (w === 0 && h === 0) return null;\r\n return { x, y, w, h };\r\n }\r\n\r\n private findElementsInRect(marquee: Rect, ctx: ToolContext): string[] {\r\n const ids: string[] = [];\r\n for (const el of ctx.store.getAll()) {\r\n const bounds = this.getElementBounds(el);\r\n if (bounds && this.rectsOverlap(marquee, bounds)) {\r\n ids.push(el.id);\r\n }\r\n }\r\n return ids;\r\n }\r\n\r\n private rectsOverlap(a: Rect, b: Rect): boolean {\r\n return a.x <= b.x + b.w && a.x + a.w >= b.x && a.y <= b.y + b.h && a.y + a.h >= b.y;\r\n }\r\n\r\n private getElementBounds(el: CanvasElement): Rect | null {\r\n if ('size' in el) {\r\n return { x: el.position.x, y: el.position.y, w: el.size.w, h: el.size.h };\r\n }\r\n if (el.type === 'stroke' && el.points.length > 0) {\r\n let minX = Infinity,\r\n minY = Infinity,\r\n maxX = -Infinity,\r\n maxY = -Infinity;\r\n for (const p of el.points) {\r\n const px = p.x + el.position.x;\r\n const py = p.y + el.position.y;\r\n if (px < minX) minX = px;\r\n if (py < minY) minY = py;\r\n if (px > maxX) maxX = px;\r\n if (py > maxY) maxY = py;\r\n }\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n }\r\n if (el.type === 'arrow') {\r\n return getArrowBounds(el.from, el.to, el.bend);\r\n }\r\n return null;\r\n }\r\n\r\n private hitTest(world: Point, ctx: ToolContext): CanvasElement | null {\r\n const elements = ctx.store.getAll().reverse();\r\n for (const el of elements) {\r\n if (this.isInsideBounds(world, el)) return el;\r\n }\r\n return null;\r\n }\r\n\r\n private isInsideBounds(point: Point, el: CanvasElement): boolean {\r\n if ('size' in el) {\r\n const s = el.size;\r\n return (\r\n point.x >= el.position.x &&\r\n point.x <= el.position.x + s.w &&\r\n point.y >= el.position.y &&\r\n point.y <= el.position.y + s.h\r\n );\r\n }\r\n\r\n if (el.type === 'stroke') {\r\n const HIT_RADIUS = 10;\r\n return el.points.some((p) => {\r\n const dx = p.x + el.position.x - point.x;\r\n const dy = p.y + el.position.y - point.y;\r\n return dx * dx + dy * dy <= HIT_RADIUS * HIT_RADIUS;\r\n });\r\n }\r\n\r\n if (el.type === 'arrow') {\r\n return isNearBezier(point, el.from, el.to, el.bend, 10);\r\n }\r\n\r\n return false;\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createArrow } from '../elements/element-factory';\r\n\r\nexport interface ArrowToolOptions {\r\n color?: string;\r\n width?: number;\r\n}\r\n\r\nexport class ArrowTool implements Tool {\r\n readonly name = 'arrow';\r\n private drawing = false;\r\n private start: Point = { x: 0, y: 0 };\r\n private end: Point = { x: 0, y: 0 };\r\n private color: string;\r\n private width: number;\r\n\r\n constructor(options: ArrowToolOptions = {}) {\r\n this.color = options.color ?? '#000000';\r\n this.width = options.width ?? 2;\r\n }\r\n\r\n setOptions(options: ArrowToolOptions): void {\r\n if (options.color !== undefined) this.color = options.color;\r\n if (options.width !== undefined) this.width = options.width;\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.drawing = true;\r\n this.start = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.end = { ...this.start };\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.end = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.drawing = false;\r\n\r\n if (this.start.x === this.end.x && this.start.y === this.end.y) return;\r\n\r\n const arrow = createArrow({\r\n from: this.start,\r\n to: this.end,\r\n color: this.color,\r\n width: this.width,\r\n });\r\n ctx.store.add(arrow);\r\n ctx.requestRender();\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (!this.drawing) return;\r\n if (this.start.x === this.end.x && this.start.y === this.end.y) return;\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.color;\r\n ctx.lineWidth = this.width;\r\n ctx.lineCap = 'round';\r\n ctx.globalAlpha = 0.6;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(this.start.x, this.start.y);\r\n ctx.lineTo(this.end.x, this.end.y);\r\n ctx.stroke();\r\n\r\n const angle = Math.atan2(this.end.y - this.start.y, this.end.x - this.start.x);\r\n const headLen = 12;\r\n const headAngle = Math.PI / 6;\r\n\r\n ctx.fillStyle = this.color;\r\n ctx.beginPath();\r\n ctx.moveTo(this.end.x, this.end.y);\r\n ctx.lineTo(\r\n this.end.x - headLen * Math.cos(angle - headAngle),\r\n this.end.y - headLen * Math.sin(angle - headAngle),\r\n );\r\n ctx.lineTo(\r\n this.end.x - headLen * Math.cos(angle + headAngle),\r\n this.end.y - headLen * Math.sin(angle + headAngle),\r\n );\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n}\r\n","import type { Size } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createNote } from '../elements/element-factory';\r\n\r\nexport interface NoteToolOptions {\r\n backgroundColor?: string;\r\n size?: Size;\r\n}\r\n\r\nexport class NoteTool implements Tool {\r\n readonly name = 'note';\r\n private backgroundColor: string;\r\n private size: Size;\r\n\r\n constructor(options: NoteToolOptions = {}) {\r\n this.backgroundColor = options.backgroundColor ?? '#ffeb3b';\r\n this.size = options.size ?? { w: 200, h: 100 };\r\n }\r\n\r\n setOptions(options: NoteToolOptions): void {\r\n if (options.backgroundColor !== undefined) this.backgroundColor = options.backgroundColor;\r\n if (options.size !== undefined) this.size = options.size;\r\n }\r\n\r\n onPointerDown(_state: PointerState, _ctx: ToolContext): void {\r\n // Note is placed on pointer up\r\n }\r\n\r\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\r\n // No drag behavior for note placement\r\n }\r\n\r\n onPointerUp(state: PointerState, ctx: ToolContext): void {\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const note = createNote({\r\n position: world,\r\n size: { ...this.size },\r\n backgroundColor: this.backgroundColor,\r\n });\r\n ctx.store.add(note);\r\n ctx.requestRender();\r\n\r\n ctx.switchTool?.('select');\r\n ctx.editElement?.(note.id);\r\n }\r\n}\r\n","import type { Size } from '../core/types';\nimport type { Tool, ToolContext, PointerState } from './types';\nimport { createImage } from '../elements/element-factory';\n\nexport interface ImageToolOptions {\n size?: Size;\n}\n\nexport class ImageTool implements Tool {\n readonly name = 'image';\n private size: Size;\n private src: string | null = null;\n\n constructor(options: ImageToolOptions = {}) {\n this.size = options.size ?? { w: 300, h: 200 };\n }\n\n setSrc(src: string): void {\n this.src = src;\n }\n\n onPointerDown(_state: PointerState, _ctx: ToolContext): void {\n // No action on pointer down — image is placed on pointer up\n }\n\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\n // No action on pointer move\n }\n\n onPointerUp(state: PointerState, ctx: ToolContext): void {\n if (!this.src) return;\n\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\n const image = createImage({\n position: world,\n size: { ...this.size },\n src: this.src,\n });\n ctx.store.add(image);\n ctx.requestRender();\n\n this.src = null;\n ctx.switchTool?.('select');\n }\n}\n","export const VERSION = '0.2.3';\r\n\r\nexport { EventBus } from './core/event-bus';\r\nexport type { Point, StrokePoint, Size, Bounds } from './core/types';\r\nexport { exportState, parseState } from './core/state-serializer';\r\nexport type { CanvasState } from './core/state-serializer';\r\nexport { AutoSave } from './core/auto-save';\r\nexport type { AutoSaveOptions } from './core/auto-save';\r\n\r\nexport { Camera } from './canvas/camera';\r\nexport type { CameraOptions } from './canvas/camera';\r\nexport { Background } from './canvas/background';\r\nexport type { BackgroundOptions, BackgroundPattern } from './canvas/background';\r\nexport { InputHandler } from './canvas/input-handler';\r\nexport { Viewport } from './canvas/viewport';\r\nexport type { ViewportOptions } from './canvas/viewport';\r\n\r\nexport { ElementStore } from './elements/element-store';\r\nexport type { ElementUpdateEvent } from './elements/element-store';\r\nexport { ElementRenderer } from './elements/element-renderer';\r\nexport { NoteEditor } from './elements/note-editor';\r\nexport { createId } from './elements/create-id';\r\nexport {\r\n createStroke,\r\n createNote,\r\n createArrow,\r\n createImage,\r\n createHtmlElement,\r\n} from './elements/element-factory';\r\nexport {\r\n getArrowControlPoint,\r\n getArrowMidpoint,\r\n getBendFromPoint,\r\n getArrowTangentAngle,\r\n isNearBezier,\r\n getArrowBounds,\r\n} from './elements/arrow-geometry';\r\nexport type {\r\n CanvasElement,\r\n ElementType,\r\n StrokeElement,\r\n NoteElement,\r\n ArrowElement,\r\n ImageElement,\r\n HtmlElement,\r\n} from './elements/types';\r\n\r\nexport type { Command } from './history/types';\r\nexport {\r\n AddElementCommand,\r\n RemoveElementCommand,\r\n UpdateElementCommand,\r\n BatchCommand,\r\n} from './history/commands';\r\nexport { HistoryStack } from './history/history-stack';\r\nexport type { HistoryStackOptions } from './history/history-stack';\r\nexport { HistoryRecorder } from './history/history-recorder';\r\n\r\nexport { ToolManager } from './tools/tool-manager';\r\nexport { HandTool } from './tools/hand-tool';\r\nexport { PencilTool } from './tools/pencil-tool';\r\nexport type { PencilToolOptions } from './tools/pencil-tool';\r\nexport { EraserTool } from './tools/eraser-tool';\r\nexport type { EraserToolOptions } from './tools/eraser-tool';\r\nexport { SelectTool } from './tools/select-tool';\r\nexport { ArrowTool } from './tools/arrow-tool';\r\nexport type { ArrowToolOptions } from './tools/arrow-tool';\r\nexport { NoteTool } from './tools/note-tool';\r\nexport type { NoteToolOptions } from './tools/note-tool';\r\nexport { ImageTool } from './tools/image-tool';\r\nexport type { ImageToolOptions } from './tools/image-tool';\r\nexport type { Tool, ToolContext, PointerState, ToolName } from './tools/types';\r\n"],"mappings":"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","names":["minX","minY","HANDLE_HIT_PADDING"]}
|