@fieldnotes/core 0.38.6 → 0.38.7

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/core/snap.ts","../src/elements/note-sanitizer.ts","../src/core/state-serializer.ts","../src/core/auto-save.ts","../src/canvas/camera.ts","../src/canvas/input-filter.ts","../src/elements/create-id.ts","../src/core/geometry.ts","../src/elements/arrow-geometry.ts","../src/elements/element-bounds.ts","../src/elements/bounds.ts","../src/canvas/keyboard-actions.ts","../src/canvas/shortcut-map.ts","../src/canvas/keyboard-handler.ts","../src/canvas/input-handler.ts","../src/canvas/background.ts","../src/core/event-bus.ts","../src/core/quadtree.ts","../src/elements/stroke-smoothing.ts","../src/elements/stroke-cache.ts","../src/elements/element-store.ts","../src/elements/rotate-canvas.ts","../src/elements/renderers/stroke-renderer.ts","../src/elements/shape-geometry.ts","../src/elements/renderers/shape-renderer.ts","../src/elements/arrow-render-cache.ts","../src/elements/arrow-binding.ts","../src/elements/renderers/arrow-renderer.ts","../src/elements/renderers/image-renderer.ts","../src/elements/hex-fill.ts","../src/elements/renderers/template-renderer.ts","../src/elements/grid-renderer.ts","../src/elements/element-renderer.ts","../src/elements/element-factory.ts","../src/elements/note-formatting.ts","../src/elements/note-toolbar.ts","../src/elements/note-editor.ts","../src/canvas/context-menu.ts","../src/canvas/viewport-dom.ts","../src/elements/arrow-label-editor.ts","../src/tools/tool-manager.ts","../src/history/history-stack.ts","../src/history/commands.ts","../src/history/layer-commands.ts","../src/history/history-recorder.ts","../src/canvas/note-canvas-renderer.ts","../src/canvas/export-image.ts","../src/layers/layer-manager.ts","../src/canvas/interact-mode.ts","../src/canvas/double-tap-detector.ts","../src/canvas/dom-node-manager.ts","../src/canvas/render-stats.ts","../src/canvas/render-loop.ts","../src/canvas/layer-cache.ts","../src/canvas/margin-viewport.ts","../src/elements/translate.ts","../src/elements/element-style.ts","../src/canvas/selection-ops.ts","../src/canvas/grid-controller.ts","../src/canvas/viewport-interactions.ts","../src/canvas/viewport.ts","../src/tools/hand-tool.ts","../src/tools/pencil-tool.ts","../src/elements/stroke-hit.ts","../src/elements/stroke-erase.ts","../src/tools/eraser-tool.ts","../src/elements/group.ts","../src/tools/arrow-handles.ts","../src/elements/snap-guides.ts","../src/tools/select-overlay.ts","../src/tools/select-hit.ts","../src/tools/select-resize.ts","../src/tools/select-tool.ts","../src/tools/arrow-tool.ts","../src/tools/note-tool.ts","../src/tools/text-tool.ts","../src/tools/image-tool.ts","../src/tools/shape-tool.ts","../src/tools/measure-tool.ts","../src/tools/template-tool.ts"],"sourcesContent":["export const VERSION = '0.38.6';\n\nexport type { Point, StrokePoint, Size, Bounds } from './core/types';\nexport { snapPoint, smartSnap, snapToHexCenter } from './core/snap';\nexport type { CanvasState } from './core/state-serializer';\nexport { AutoSave } from './core/auto-save';\nexport type { AutoSaveOptions } from './core/auto-save';\n\nexport { Camera } from './canvas/camera';\nexport type { CameraOptions, CameraChangeInfo } from './canvas/camera';\nexport type { BackgroundOptions, BackgroundPattern } from './canvas/background';\nexport type { ShortcutOptions, ShortcutBindings, ShortcutsApi } from './canvas/shortcut-map';\nexport { Viewport } from './canvas/viewport';\nexport type { ViewportOptions, GridInfo, AlignEdge, DistributeAxis } from './canvas/viewport';\nexport { exportImage } from './canvas/export-image';\nexport type { ExportImageOptions } from './canvas/export-image';\nexport type { RenderStatsSnapshot } from './canvas/render-stats';\n\nexport { ElementStore } from './elements/element-store';\nexport type { ElementUpdateEvent } from './elements/element-store';\nexport type { FontSizePreset } from './elements/note-toolbar';\nexport {\n toggleBold,\n toggleItalic,\n toggleUnderline,\n toggleStrikethrough,\n setFontSize,\n getActiveFormats,\n} from './elements/note-formatting';\nexport type { ActiveFormats } from './elements/note-formatting';\nexport {\n createStroke,\n createNote,\n createArrow,\n createImage,\n createHtmlElement,\n createText,\n createShape,\n createGrid,\n createTemplate,\n DEFAULT_NOTE_FONT_SIZE,\n} from './elements/element-factory';\nexport {\n getArrowControlPoint,\n getArrowMidpoint,\n getBendFromPoint,\n getArrowTangentAngle,\n isNearBezier,\n getArrowBounds,\n} from './elements/arrow-geometry';\nexport { getElementBounds, boundsIntersect } from './elements/element-bounds';\nexport { styleToPatch, getElementStyle } from './elements/element-style';\nexport type { ElementStyle } from './elements/element-style';\nexport { getElementsBoundingBox } from './elements/bounds';\nexport {\n getHexDistance,\n getHexCellsInRadius,\n getHexCellsInCone,\n getHexCellsInLine,\n getHexCellsInSquare,\n drawHexPath,\n} from './elements/hex-fill';\nexport type {\n Binding,\n CanvasElement,\n ElementType,\n StrokeElement,\n NoteElement,\n ArrowElement,\n ImageElement,\n HtmlElement,\n TextElement,\n ShapeElement,\n ShapeKind,\n GridElement,\n HexOrientation,\n TemplateElement,\n TemplateShape,\n} from './elements/types';\n\nexport type { Command } from './history/types';\nexport { HistoryStack } from './history/history-stack';\nexport type { HistoryStackOptions } from './history/history-stack';\n\nexport { ToolManager } from './tools/tool-manager';\nexport { HandTool } from './tools/hand-tool';\nexport { PencilTool } from './tools/pencil-tool';\nexport type { PencilToolOptions } from './tools/pencil-tool';\nexport { EraserTool } from './tools/eraser-tool';\nexport type { EraserToolOptions } from './tools/eraser-tool';\nexport { SelectTool } from './tools/select-tool';\nexport { ArrowTool } from './tools/arrow-tool';\nexport type { ArrowToolOptions } from './tools/arrow-tool';\nexport { NoteTool } from './tools/note-tool';\nexport type { NoteToolOptions } from './tools/note-tool';\nexport { TextTool } from './tools/text-tool';\nexport type { TextToolOptions } from './tools/text-tool';\nexport { ImageTool } from './tools/image-tool';\nexport type { ImageToolOptions } from './tools/image-tool';\nexport { ShapeTool } from './tools/shape-tool';\nexport type { ShapeToolOptions } from './tools/shape-tool';\nexport { MeasureTool } from './tools/measure-tool';\nexport type { MeasureToolOptions, Measurement } from './tools/measure-tool';\nexport { TemplateTool } from './tools/template-tool';\nexport type { TemplateToolOptions } from './tools/template-tool';\nexport type { Tool, ToolContext, PointerState, ToolName } from './tools/types';\n\nexport { LayerManager } from './layers/layer-manager';\nexport type { Layer } from './layers/types';\n","import type { Point } from './types';\r\nimport type { HexOrientation } from '../elements/types';\r\nimport type { ToolContext } from '../tools/types';\r\n\r\nexport function snapPoint(point: Point, gridSize: number): Point {\r\n return {\r\n x: Math.round(point.x / gridSize) * gridSize || 0,\r\n y: Math.round(point.y / gridSize) * gridSize || 0,\r\n };\r\n}\r\n\r\nexport function snapToHexCenter(\r\n point: Point,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point {\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * cellSize;\r\n const rowH = 1.5 * cellSize;\r\n const row = Math.round(point.y / rowH);\r\n const offsetX = row % 2 !== 0 ? hexW / 2 : 0;\r\n const col = Math.round((point.x - offsetX) / hexW);\r\n return { x: col * hexW + offsetX || 0, y: row * rowH || 0 };\r\n } else {\r\n const hexH = Math.sqrt(3) * cellSize;\r\n const colW = 1.5 * cellSize;\r\n const col = Math.round(point.x / colW);\r\n const offsetY = col % 2 !== 0 ? hexH / 2 : 0;\r\n const row = Math.round((point.y - offsetY) / hexH);\r\n return { x: col * colW || 0, y: row * hexH + offsetY || 0 };\r\n }\r\n}\r\n\r\nexport function smartSnap(point: Point, ctx: ToolContext): Point {\r\n if (!ctx.snapToGrid || !ctx.gridSize) return point;\r\n if (ctx.gridType === 'hex' && ctx.hexOrientation) {\r\n return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);\r\n }\r\n return snapPoint(point, ctx.gridSize);\r\n}\r\n","interface RunStyle {\r\n bold: boolean;\r\n italic: boolean;\r\n underline: boolean;\r\n strikethrough: boolean;\r\n fontSize: number;\r\n}\r\n\r\nexport interface StyledRun extends RunStyle {\r\n text: string;\r\n}\r\n\r\nconst BOLD_TAGS = new Set(['b', 'strong']);\r\nconst ITALIC_TAGS = new Set(['i', 'em']);\r\nconst UNDERLINE_TAGS = new Set(['u']);\r\nconst STRIKE_TAGS = new Set(['s', 'strike', 'del']);\r\nconst BLOCK_TAGS = new Set(['div']);\r\n\r\nexport function parseStyledRuns(html: string, baseFontSize: number): StyledRun[] {\r\n if (!html) return [];\r\n\r\n const doc = new DOMParser().parseFromString(html, 'text/html');\r\n const runs: StyledRun[] = [];\r\n const baseStyle: RunStyle = {\r\n bold: false,\r\n italic: false,\r\n underline: false,\r\n strikethrough: false,\r\n fontSize: baseFontSize,\r\n };\r\n\r\n walkNodes(doc.body, baseStyle, runs);\r\n return runs;\r\n}\r\n\r\nfunction walkNodes(node: Node, style: RunStyle, runs: StyledRun[]): void {\r\n for (const child of Array.from(node.childNodes)) {\r\n if (child.nodeType === Node.TEXT_NODE) {\r\n const text = child.textContent ?? '';\r\n if (text) {\r\n runs.push({ text, ...style });\r\n }\r\n continue;\r\n }\r\n\r\n if (child.nodeType !== Node.ELEMENT_NODE) continue;\r\n\r\n const el = child as Element;\r\n const tag = el.tagName.toLowerCase();\r\n\r\n if (tag === 'br') {\r\n runs.push({ text: '\\n', ...style });\r\n continue;\r\n }\r\n\r\n if (BLOCK_TAGS.has(tag) && runs.length > 0) {\r\n const lastRun = runs[runs.length - 1];\r\n if (lastRun && !lastRun.text.endsWith('\\n')) {\r\n runs.push({ text: '\\n', ...style });\r\n }\r\n }\r\n\r\n const childStyle = { ...style };\r\n if (BOLD_TAGS.has(tag)) childStyle.bold = true;\r\n if (ITALIC_TAGS.has(tag)) childStyle.italic = true;\r\n if (UNDERLINE_TAGS.has(tag)) childStyle.underline = true;\r\n if (STRIKE_TAGS.has(tag)) childStyle.strikethrough = true;\r\n\r\n if (tag === 'span') {\r\n const fontSize = (el as HTMLElement).style.fontSize;\r\n if (fontSize) {\r\n childStyle.fontSize = parseInt(fontSize, 10) || style.fontSize;\r\n }\r\n }\r\n\r\n walkNodes(el, childStyle, runs);\r\n }\r\n}\r\n\r\nconst ALLOWED_TAGS = new Set([\r\n 'b',\r\n 'strong',\r\n 'i',\r\n 'em',\r\n 'u',\r\n 's',\r\n 'strike',\r\n 'del',\r\n 'span',\r\n 'br',\r\n 'div',\r\n]);\r\n\r\nexport function sanitizeNoteHtml(html: string): string {\r\n if (!html) return '';\r\n\r\n const doc = new DOMParser().parseFromString(html, 'text/html');\r\n sanitizeNode(doc.body);\r\n return doc.body.innerHTML;\r\n}\r\n\r\nfunction sanitizeNode(node: Node): void {\r\n const children = Array.from(node.childNodes);\r\n\r\n for (const child of children) {\r\n if (child.nodeType === Node.TEXT_NODE) continue;\r\n\r\n if (child.nodeType !== Node.ELEMENT_NODE) {\r\n child.remove();\r\n continue;\r\n }\r\n\r\n const el = child as Element;\r\n const tag = el.tagName.toLowerCase();\r\n\r\n if (!ALLOWED_TAGS.has(tag)) {\r\n const fragment = document.createDocumentFragment();\r\n while (el.firstChild) {\r\n fragment.appendChild(el.firstChild);\r\n }\r\n node.replaceChild(fragment, el);\r\n sanitizeNode(node);\r\n return;\r\n }\r\n\r\n sanitizeAttributes(el, tag);\r\n sanitizeNode(el);\r\n }\r\n}\r\n\r\nexport function isNoteContentEmpty(html: string): boolean {\r\n if (!html) return true;\r\n const doc = new DOMParser().parseFromString(html, 'text/html');\r\n const text = doc.body.textContent ?? '';\r\n return text.replace(/\\u00a0/g, ' ').trim().length === 0;\r\n}\r\n\r\nfunction sanitizeAttributes(el: Element, tag: string): void {\r\n const attrs = Array.from(el.attributes);\r\n for (const attr of attrs) {\r\n if (tag === 'span' && attr.name === 'style') {\r\n const fontSize = (el as HTMLElement).style.fontSize;\r\n if (fontSize) {\r\n el.setAttribute('style', `font-size: ${fontSize};`);\r\n } else {\r\n el.removeAttribute('style');\r\n }\r\n continue;\r\n }\r\n el.removeAttribute(attr.name);\r\n }\r\n}\r\n","import type { CanvasElement } from '../elements/types';\r\nimport type { Point } from './types';\r\nimport type { Layer } from '../layers/types';\r\nimport { sanitizeNoteHtml } from '../elements/note-sanitizer';\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 layers?: Layer[];\r\n activeLayerId?: string;\r\n}\r\n\r\nconst CURRENT_VERSION = 2;\r\n\r\nexport function exportState(\r\n elements: CanvasElement[],\r\n camera: { position: Point; zoom: number },\r\n layers: Layer[] = [],\r\n activeLayerId?: string,\r\n): CanvasState {\r\n const state: CanvasState = {\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) => {\r\n const clone = structuredClone(el);\r\n if (clone.type === 'arrow') {\r\n delete clone.cachedControlPoint;\r\n }\r\n return clone;\r\n }),\r\n layers: layers.map((l) => ({ ...l })),\r\n };\r\n if (activeLayerId) state.activeLayerId = activeLayerId;\r\n return state;\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 cleanBindings(obj['elements'] as Record<string, unknown>[]);\r\n\r\n const layers = obj['layers'];\r\n if (!Array.isArray(layers) || layers.length === 0) {\r\n obj['layers'] = [\r\n {\r\n id: 'default-layer',\r\n name: 'Layer 1',\r\n visible: true,\r\n locked: false,\r\n order: 0,\r\n opacity: 1.0,\r\n },\r\n ];\r\n }\r\n}\r\n\r\nconst VALID_TYPES = new Set([\r\n 'stroke',\r\n 'note',\r\n 'arrow',\r\n 'image',\r\n 'html',\r\n 'text',\r\n 'shape',\r\n 'grid',\r\n 'template',\r\n]);\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 cleanBindings(elements: Record<string, unknown>[]): void {\r\n const ids = new Set(elements.map((el) => el['id'] as string));\r\n\r\n for (const el of elements) {\r\n if (el['type'] !== 'arrow') continue;\r\n\r\n const fromBinding = el['fromBinding'] as Record<string, unknown> | undefined;\r\n if (fromBinding && !ids.has(fromBinding['elementId'] as string)) {\r\n el['fromBinding'] = undefined;\r\n }\r\n\r\n const toBinding = el['toBinding'] as Record<string, unknown> | undefined;\r\n if (toBinding && !ids.has(toBinding['elementId'] as string)) {\r\n el['toBinding'] = undefined;\r\n }\r\n }\r\n}\r\n\r\nfunction migrateElement(obj: Record<string, unknown>): void {\r\n if (typeof obj['layerId'] !== 'string') {\r\n obj['layerId'] = 'default-layer';\r\n }\r\n\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 if (obj['type'] === 'shape' && typeof obj['shape'] !== 'string') {\r\n obj['shape'] = 'rectangle';\r\n }\r\n\r\n if (obj['type'] === 'note' && typeof obj['textColor'] !== 'string') {\r\n obj['textColor'] = '#000000';\r\n }\r\n\r\n if (obj['type'] === 'note' && typeof obj['text'] === 'string') {\r\n obj['text'] = sanitizeNoteHtml(obj['text']);\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { Camera } from '../canvas/camera';\r\nimport type { LayerManager } from '../layers/layer-manager';\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 layerManager?: LayerManager;\r\n onError?: (error: Error) => void;\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 readonly layerManager?: LayerManager;\r\n private timerId: ReturnType<typeof setTimeout> | null = null;\r\n private unsubscribers: (() => void)[] = [];\r\n private readonly onError?: (error: Error) => 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 this.layerManager = options.layerManager;\r\n this.onError = options.onError;\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 if (this.layerManager) {\r\n this.unsubscribers.push(this.layerManager.on('change', 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 layers = this.layerManager?.snapshot() ?? [];\r\n const state = exportState(this.store.snapshot(), this.camera, layers);\r\n try {\r\n localStorage.setItem(this.key, JSON.stringify(state));\r\n } catch (e) {\r\n console.warn('Auto-save failed: storage quota exceeded. State too large for localStorage.');\r\n this.onError?.(e instanceof Error ? e : new Error(String(e)));\r\n }\r\n }\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\n\r\nexport interface CameraOptions {\r\n minZoom?: number;\r\n maxZoom?: number;\r\n}\r\n\r\nexport interface CameraChangeInfo {\r\n panned: boolean;\r\n zoomed: boolean;\r\n}\r\n\r\nconst DEFAULT_MIN_ZOOM = 0.1;\r\nconst DEFAULT_MAX_ZOOM = 10;\r\n\r\nexport class Camera {\r\n private x = 0;\r\n private y = 0;\r\n private z = 1;\r\n private readonly minZoom: number;\r\n private readonly maxZoom: number;\r\n private changeListeners = new Set<(info: CameraChangeInfo) => void>();\r\n\r\n constructor(options: CameraOptions = {}) {\r\n this.minZoom = options.minZoom ?? DEFAULT_MIN_ZOOM;\r\n this.maxZoom = options.maxZoom ?? DEFAULT_MAX_ZOOM;\r\n }\r\n\r\n get position(): Point {\r\n return { x: this.x, y: this.y };\r\n }\r\n\r\n get zoom(): number {\r\n return this.z;\r\n }\r\n\r\n pan(dx: number, dy: number): void {\r\n this.x += dx;\r\n this.y += dy;\r\n this.notifyPan();\r\n }\r\n\r\n moveTo(x: number, y: number): void {\r\n this.x = x;\r\n this.y = y;\r\n this.notifyPan();\r\n }\r\n\r\n setZoom(level: number): void {\r\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, level));\r\n this.notifyZoom();\r\n }\r\n\r\n zoomAt(level: number, screenPoint: Point): void {\r\n const before = this.screenToWorld(screenPoint);\r\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, level));\r\n const after = this.screenToWorld(screenPoint);\r\n this.x += (after.x - before.x) * this.z;\r\n this.y += (after.y - before.y) * this.z;\r\n this.notifyPanAndZoom();\r\n }\r\n\r\n screenToWorld(screen: Point): Point {\r\n return {\r\n x: (screen.x - this.x) / this.z,\r\n y: (screen.y - this.y) / this.z,\r\n };\r\n }\r\n\r\n worldToScreen(world: Point): Point {\r\n return {\r\n x: world.x * this.z + this.x,\r\n y: world.y * this.z + this.y,\r\n };\r\n }\r\n\r\n getVisibleRect(canvasWidth: number, canvasHeight: number): Bounds {\r\n const topLeft = this.screenToWorld({ x: 0, y: 0 });\r\n const bottomRight = this.screenToWorld({ x: canvasWidth, y: canvasHeight });\r\n return {\r\n x: topLeft.x,\r\n y: topLeft.y,\r\n w: bottomRight.x - topLeft.x,\r\n h: bottomRight.y - topLeft.y,\r\n };\r\n }\r\n\r\n fitToContent(boundingBox: Bounds, canvasWidth: number, canvasHeight: number, padding = 40): void {\r\n if (boundingBox.w === 0 && boundingBox.h === 0) return;\r\n\r\n const scaleX = canvasWidth / (boundingBox.w + 2 * padding);\r\n const scaleY = canvasHeight / (boundingBox.h + 2 * padding);\r\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, Math.min(scaleX, scaleY)));\r\n this.x = (canvasWidth - boundingBox.w * this.z) / 2 - boundingBox.x * this.z;\r\n this.y = (canvasHeight - boundingBox.h * this.z) / 2 - boundingBox.y * this.z;\r\n this.notifyPanAndZoom();\r\n }\r\n\r\n toCSSTransform(): string {\r\n return `translate3d(${this.x}px, ${this.y}px, 0) scale(${this.z})`;\r\n }\r\n\r\n onChange(listener: (info: CameraChangeInfo) => void): () => void {\r\n this.changeListeners.add(listener);\r\n return () => this.changeListeners.delete(listener);\r\n }\r\n\r\n private notifyPan(): void {\r\n this.changeListeners.forEach((fn) => fn({ panned: true, zoomed: false }));\r\n }\r\n\r\n private notifyZoom(): void {\r\n this.changeListeners.forEach((fn) => fn({ panned: false, zoomed: true }));\r\n }\r\n\r\n private notifyPanAndZoom(): void {\r\n this.changeListeners.forEach((fn) => fn({ panned: true, zoomed: true }));\r\n }\r\n}\r\n","export type FilterAction = 'dispatch' | 'suppress' | 'defer';\r\n\r\nexport interface FilteredEvent {\r\n event: PointerEvent;\r\n action: FilterAction;\r\n}\r\n\r\nexport interface FilteredUpEvent extends FilteredEvent {\r\n pendingTap?: { x: number; y: number };\r\n}\r\n\r\nexport class InputFilter {\r\n private activePenId: number | null = null;\r\n private pendingTap: { pointerId: number; x: number; y: number } | null = null;\r\n\r\n static readonly MIN_MOVE_DISTANCE = 3;\r\n\r\n filterDown(e: PointerEvent): FilteredEvent {\r\n if (e.pointerType === 'pen') {\r\n this.activePenId = e.pointerId;\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n if (e.pointerType === 'touch' && this.activePenId !== null) {\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n if (e.pointerType === 'touch') {\r\n this.pendingTap = { pointerId: e.pointerId, x: e.clientX, y: e.clientY };\r\n return { event: e, action: 'defer' };\r\n }\r\n\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n filterMove(e: PointerEvent): FilteredEvent {\r\n if (e.pointerType === 'touch' && this.activePenId !== null) {\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {\r\n const dx = e.clientX - this.pendingTap.x;\r\n const dy = e.clientY - this.pendingTap.y;\r\n if (dx * dx + dy * dy > InputFilter.MIN_MOVE_DISTANCE * InputFilter.MIN_MOVE_DISTANCE) {\r\n this.pendingTap = null;\r\n return { event: e, action: 'dispatch' };\r\n }\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n filterUp(e: PointerEvent): FilteredUpEvent {\r\n if (e.pointerId === this.activePenId) {\r\n this.activePenId = null;\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n if (e.pointerType === 'touch' && this.activePenId !== null) {\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {\r\n const tap = { x: this.pendingTap.x, y: this.pendingTap.y };\r\n this.pendingTap = null;\r\n return { event: e, action: 'dispatch', pendingTap: tap };\r\n }\r\n\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n reset(): void {\r\n this.activePenId = null;\r\n this.pendingTap = null;\r\n }\r\n}\r\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, Bounds } from './types';\r\n\r\nexport function distSqToSegment(p: Point, a: Point, b: Point): number {\r\n const abx = b.x - a.x;\r\n const aby = b.y - a.y;\r\n const apx = p.x - a.x;\r\n const apy = p.y - a.y;\r\n const lenSq = abx * abx + aby * aby;\r\n if (lenSq === 0) {\r\n return apx * apx + apy * apy;\r\n }\r\n const t = Math.max(0, Math.min(1, (apx * abx + apy * aby) / lenSq));\r\n const dx = p.x - (a.x + t * abx);\r\n const dy = p.y - (a.y + t * aby);\r\n return dx * dx + dy * dy;\r\n}\r\n\r\nexport function rotatePoint(p: Point, center: Point, angle: number): Point {\r\n if (angle === 0) return p;\r\n const cos = Math.cos(angle);\r\n const sin = Math.sin(angle);\r\n const dx = p.x - center.x;\r\n const dy = p.y - center.y;\r\n return { x: center.x + dx * cos - dy * sin, y: center.y + dx * sin + dy * cos };\r\n}\r\n\r\nexport function rotatedAABB(bounds: Bounds, angle: number): Bounds {\r\n if (angle === 0) return bounds;\r\n const c = { x: bounds.x + bounds.w / 2, y: bounds.y + bounds.h / 2 };\r\n const corners = [\r\n { x: bounds.x, y: bounds.y },\r\n { x: bounds.x + bounds.w, y: bounds.y },\r\n { x: bounds.x + bounds.w, y: bounds.y + bounds.h },\r\n { x: bounds.x, y: bounds.y + bounds.h },\r\n ].map((p) => rotatePoint(p, c, angle));\r\n const xs = corners.map((p) => p.x);\r\n const ys = corners.map((p) => p.y);\r\n const minX = Math.min(...xs);\r\n const minY = Math.min(...ys);\r\n return { x: minX, y: minY, w: Math.max(...xs) - minX, h: Math.max(...ys) - minY };\r\n}\r\n\r\nexport function normalizeAngle(angle: number): number {\r\n const twoPi = Math.PI * 2;\r\n let a = angle % twoPi;\r\n if (a <= -Math.PI) a += twoPi;\r\n else if (a > Math.PI) a -= twoPi;\r\n return a;\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport { distSqToSegment } from '../core/geometry';\r\n\r\nexport function getArrowControlPoint(from: Point, to: Point, bend: number): Point {\r\n const midX = (from.x + to.x) / 2;\r\n const midY = (from.y + to.y) / 2;\r\n\r\n if (bend === 0) return { x: midX, y: midY };\r\n\r\n const dx = to.x - from.x;\r\n const dy = to.y - from.y;\r\n const len = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (len === 0) return { x: midX, y: midY };\r\n\r\n const perpX = -dy / len;\r\n const perpY = dx / len;\r\n\r\n return {\r\n x: midX + perpX * bend,\r\n y: midY + perpY * bend,\r\n };\r\n}\r\n\r\nexport function getArrowMidpoint(from: Point, to: Point, bend: number): Point {\r\n const cp = getArrowControlPoint(from, to, bend);\r\n return {\r\n x: 0.25 * from.x + 0.5 * cp.x + 0.25 * to.x,\r\n y: 0.25 * from.y + 0.5 * cp.y + 0.25 * to.y,\r\n };\r\n}\r\n\r\nexport function getBendFromPoint(from: Point, to: Point, dragPoint: Point): number {\r\n const midX = (from.x + to.x) / 2;\r\n const midY = (from.y + to.y) / 2;\r\n\r\n const dx = to.x - from.x;\r\n const dy = to.y - from.y;\r\n const len = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (len === 0) return 0;\r\n\r\n const perpX = -dy / len;\r\n const perpY = dx / len;\r\n\r\n return (dragPoint.x - midX) * perpX + (dragPoint.y - midY) * perpY;\r\n}\r\n\r\nexport function getArrowTangentAngle(from: Point, to: Point, bend: number, t: number): number {\r\n const cp = getArrowControlPoint(from, to, bend);\r\n\r\n const tangentX = 2 * (1 - t) * (cp.x - from.x) + 2 * t * (to.x - cp.x);\r\n const tangentY = 2 * (1 - t) * (cp.y - from.y) + 2 * t * (to.y - cp.y);\r\n\r\n return Math.atan2(tangentY, tangentX);\r\n}\r\n\r\nexport function isNearBezier(\r\n point: Point,\r\n from: Point,\r\n to: Point,\r\n bend: number,\r\n threshold: number,\r\n): boolean {\r\n if (bend === 0) return isNearLine(point, from, to, threshold);\r\n\r\n const cp = getArrowControlPoint(from, to, bend);\r\n const segments = 20;\r\n\r\n for (let i = 0; i < segments; i++) {\r\n const t0 = i / segments;\r\n const t1 = (i + 1) / segments;\r\n const a = bezierPoint(from, cp, to, t0);\r\n const b = bezierPoint(from, cp, to, t1);\r\n if (isNearLine(point, a, b, threshold)) return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\nexport function getArrowBounds(from: Point, to: Point, bend: number): Bounds {\r\n if (bend === 0) {\r\n const minX = Math.min(from.x, to.x);\r\n const minY = Math.min(from.y, to.y);\r\n return {\r\n x: minX,\r\n y: minY,\r\n w: Math.abs(to.x - from.x),\r\n h: Math.abs(to.y - from.y),\r\n };\r\n }\r\n\r\n const cp = getArrowControlPoint(from, to, bend);\r\n const steps = 20;\r\n let minX = Math.min(from.x, to.x);\r\n let minY = Math.min(from.y, to.y);\r\n let maxX = Math.max(from.x, to.x);\r\n let maxY = Math.max(from.y, to.y);\r\n\r\n for (let i = 1; i < steps; i++) {\r\n const t = i / steps;\r\n const p = bezierPoint(from, cp, to, t);\r\n if (p.x < minX) minX = p.x;\r\n if (p.y < minY) minY = p.y;\r\n if (p.x > maxX) maxX = p.x;\r\n if (p.y > maxY) maxY = p.y;\r\n }\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n\r\nfunction bezierPoint(from: Point, cp: Point, to: Point, t: number): Point {\r\n const mt = 1 - t;\r\n return {\r\n x: mt * mt * from.x + 2 * mt * t * cp.x + t * t * to.x,\r\n y: mt * mt * from.y + 2 * mt * t * cp.y + t * t * to.y,\r\n };\r\n}\r\n\r\nfunction isNearLine(point: Point, a: Point, b: Point, threshold: number): boolean {\r\n return distSqToSegment(point, a, b) <= threshold * threshold;\r\n}\r\n","import type { Bounds } from '../core/types';\r\nimport type { CanvasElement, TemplateElement } from './types';\r\nimport { getArrowControlPoint } from './arrow-geometry';\r\n\r\n// Cache stroke bounds via WeakMap.\r\n// May miss after ElementStore.update() creates new object via spread,\r\n// acceptable since stroke points never change after commit.\r\nconst strokeBoundsCache = new WeakMap<CanvasElement, Bounds>();\r\n\r\nexport function getElementBounds(element: CanvasElement): Bounds | null {\r\n if (element.type === 'grid') return null;\r\n\r\n if ('size' in element) {\r\n return {\r\n x: element.position.x,\r\n y: element.position.y,\r\n w: element.size.w,\r\n h: element.size.h,\r\n };\r\n }\r\n\r\n if (element.type === 'stroke') {\r\n if (element.points.length === 0) return null;\r\n\r\n const cached = strokeBoundsCache.get(element);\r\n if (cached) return cached;\r\n\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n\r\n for (const p of element.points) {\r\n const px = p.x + element.position.x;\r\n const py = p.y + element.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\r\n const bounds: Bounds = { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n strokeBoundsCache.set(element, bounds);\r\n return bounds;\r\n }\r\n\r\n if (element.type === 'arrow') {\r\n return getArrowBoundsAnalytical(element.from, element.to, element.bend);\r\n }\r\n\r\n if (element.type === 'template') {\r\n return getTemplateBounds(element);\r\n }\r\n\r\n return null;\r\n}\r\n\r\nfunction getArrowBoundsAnalytical(\r\n from: { x: number; y: number },\r\n to: { x: number; y: number },\r\n bend: number,\r\n): Bounds {\r\n if (bend === 0) {\r\n const minX = Math.min(from.x, to.x);\r\n const minY = Math.min(from.y, to.y);\r\n return {\r\n x: minX,\r\n y: minY,\r\n w: Math.abs(to.x - from.x),\r\n h: Math.abs(to.y - from.y),\r\n };\r\n }\r\n\r\n const cp = getArrowControlPoint(from, to, bend);\r\n\r\n let minX = Math.min(from.x, to.x);\r\n let maxX = Math.max(from.x, to.x);\r\n let minY = Math.min(from.y, to.y);\r\n let maxY = Math.max(from.y, to.y);\r\n\r\n // Analytical extrema for quadratic bezier: t = (P0 - P1) / (P0 - 2*P1 + P2)\r\n const tx = from.x - 2 * cp.x + to.x;\r\n if (tx !== 0) {\r\n const t = (from.x - cp.x) / tx;\r\n if (t > 0 && t < 1) {\r\n const mt = 1 - t;\r\n const x = mt * mt * from.x + 2 * mt * t * cp.x + t * t * to.x;\r\n if (x < minX) minX = x;\r\n if (x > maxX) maxX = x;\r\n }\r\n }\r\n\r\n const ty = from.y - 2 * cp.y + to.y;\r\n if (ty !== 0) {\r\n const t = (from.y - cp.y) / ty;\r\n if (t > 0 && t < 1) {\r\n const mt = 1 - t;\r\n const y = mt * mt * from.y + 2 * mt * t * cp.y + t * t * to.y;\r\n if (y < minY) minY = y;\r\n if (y > maxY) maxY = y;\r\n }\r\n }\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n\r\nfunction getTemplateBounds(el: TemplateElement): Bounds {\r\n const { x: cx, y: cy } = el.position;\r\n const r = el.radius;\r\n\r\n switch (el.templateShape) {\r\n case 'circle':\r\n return { x: cx - r, y: cy - r, w: 2 * r, h: 2 * r };\r\n\r\n case 'square':\r\n return { x: cx - r / 2, y: cy - r / 2, w: r, h: r };\r\n\r\n case 'cone': {\r\n const halfAngle = Math.atan(0.5);\r\n const tipX = cx;\r\n const tipY = cy;\r\n const leftX = cx + r * Math.cos(el.angle - halfAngle);\r\n const leftY = cy + r * Math.sin(el.angle - halfAngle);\r\n const rightX = cx + r * Math.cos(el.angle + halfAngle);\r\n const rightY = cy + r * Math.sin(el.angle + halfAngle);\r\n const farX = cx + r * Math.cos(el.angle);\r\n const farY = cy + r * Math.sin(el.angle);\r\n\r\n const xs = [tipX, leftX, rightX, farX];\r\n const ys = [tipY, leftY, rightY, farY];\r\n\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n\r\n for (let i = 0; i < xs.length; i++) {\r\n const px = xs[i];\r\n const py = ys[i];\r\n if (px !== undefined && px < minX) minX = px;\r\n if (px !== undefined && px > maxX) maxX = px;\r\n if (py !== undefined && py < minY) minY = py;\r\n if (py !== undefined && py > maxY) maxY = py;\r\n }\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n }\r\n\r\n case 'line': {\r\n const halfW = r / 12;\r\n const cos = Math.cos(el.angle);\r\n const sin = Math.sin(el.angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n\r\n const x0 = cx + perpX;\r\n const y0 = cy + perpY;\r\n const x1 = cx + r * cos + perpX;\r\n const y1 = cy + r * sin + perpY;\r\n const x2 = cx + r * cos - perpX;\r\n const y2 = cy + r * sin - perpY;\r\n const x3 = cx - perpX;\r\n const y3 = cy - perpY;\r\n\r\n const minX = Math.min(x0, x1, x2, x3);\r\n const minY = Math.min(y0, y1, y2, y3);\r\n const maxX = Math.max(x0, x1, x2, x3);\r\n const maxY = Math.max(y0, y1, y2, y3);\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n }\r\n }\r\n}\r\n\r\nexport function transferStrokeBounds(prev: CanvasElement, next: CanvasElement): void {\r\n if (prev.type !== 'stroke' || next.type !== 'stroke') return;\r\n if (prev.points !== next.points) return;\r\n if (prev.position.x !== next.position.x || prev.position.y !== next.position.y) return;\r\n const bounds = strokeBoundsCache.get(prev);\r\n if (bounds) strokeBoundsCache.set(next, bounds);\r\n}\r\n\r\nexport function boundsIntersect(a: Bounds, b: Bounds): 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","import type { Bounds } from '../core/types';\r\nimport type { CanvasElement } from './types';\r\nimport { getElementBounds } from './element-bounds';\r\n\r\nexport function getElementsBoundingBox(elements: CanvasElement[]): Bounds | null {\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n let found = false;\r\n\r\n for (const el of elements) {\r\n const b = getElementBounds(el);\r\n if (!b) continue;\r\n found = true;\r\n if (b.x < minX) minX = b.x;\r\n if (b.y < minY) minY = b.y;\r\n if (b.x + b.w > maxX) maxX = b.x + b.w;\r\n if (b.y + b.h > maxY) maxY = b.y + b.h;\r\n }\r\n\r\n if (!found) return null;\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n","import type { ToolManager } from '../tools/tool-manager';\r\nimport type { ToolContext } 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\nimport type { CanvasElement } from '../elements/types';\r\nimport type { Point } from '../core/types';\r\nimport { createId } from '../elements/create-id';\r\nimport { getElementsBoundingBox } from '../elements/bounds';\r\n\r\nexport interface KeyboardActionsDeps {\r\n getToolManager: () => ToolManager | null;\r\n getToolContext: () => ToolContext | null;\r\n getHistoryRecorder: () => HistoryRecorder | null;\r\n getHistoryStack: () => HistoryStack | null;\r\n isToolActive: () => boolean;\r\n fitToContent?: () => void;\r\n group?: () => void;\r\n ungroup?: () => void;\r\n toggleLock?: () => void;\r\n getLastPointerWorld?: () => Point | null;\r\n}\r\n\r\nexport class KeyboardActions {\r\n private clipboard: CanvasElement[] = [];\r\n private pasteCount = 0;\r\n private nudgeTimer: ReturnType<typeof setTimeout> | null = null;\r\n private nudgeTxId: number | null = null;\r\n\r\n constructor(private readonly deps: KeyboardActionsDeps) {}\r\n\r\n dispose(): void {\r\n this.flushPendingNudge();\r\n }\r\n\r\n private selectTool(): { tool: SelectTool; ctx: ToolContext } | null {\r\n const tm = this.deps.getToolManager();\r\n const ctx = this.deps.getToolContext();\r\n if (!tm || !ctx) return null;\r\n const tool = tm.activeTool;\r\n if (tool?.name !== 'select') return null;\r\n return { tool: tool as SelectTool, ctx };\r\n }\r\n\r\n nudge(dx: number, dy: number, byCell: boolean): boolean {\r\n if (this.deps.isToolActive()) return false;\r\n const sel = this.selectTool();\r\n if (!sel) return false;\r\n if (sel.tool.selectedIds.length === 0) return false;\r\n\r\n const step = byCell ? (sel.ctx.gridSize ?? 10) : 1;\r\n if (this.nudgeTimer === null) {\r\n const recorder = this.deps.getHistoryRecorder();\r\n recorder?.begin();\r\n this.nudgeTxId = recorder?.currentTransactionId ?? null;\r\n } else {\r\n clearTimeout(this.nudgeTimer);\r\n }\r\n const moved = sel.tool.nudgeSelection(dx * step, dy * step, sel.ctx);\r\n this.nudgeTimer = setTimeout(() => this.flushPendingNudge(), 400);\r\n return moved;\r\n }\r\n\r\n flushPendingNudge(): void {\r\n if (this.nudgeTimer === null) return;\r\n clearTimeout(this.nudgeTimer);\r\n this.nudgeTimer = null;\r\n const recorder = this.deps.getHistoryRecorder();\r\n if (this.nudgeTxId === null || recorder?.currentTransactionId === this.nudgeTxId) {\r\n recorder?.commit();\r\n }\r\n this.nudgeTxId = null;\r\n }\r\n\r\n deleteSelected(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const ids = sel.tool.selectedIds;\r\n if (ids.length === 0) return;\r\n const recorder = this.deps.getHistoryRecorder();\r\n recorder?.begin();\r\n for (const id of ids) {\r\n sel.ctx.store.remove(id);\r\n }\r\n recorder?.commit();\r\n sel.ctx.requestRender();\r\n }\r\n\r\n undo(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n const ctx = this.deps.getToolContext();\r\n const stack = this.deps.getHistoryStack();\r\n if (!stack || !ctx) return;\r\n const recorder = this.deps.getHistoryRecorder();\r\n recorder?.pause();\r\n stack.undo(ctx.store);\r\n recorder?.resume();\r\n ctx.requestRender();\r\n }\r\n\r\n redo(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n const ctx = this.deps.getToolContext();\r\n const stack = this.deps.getHistoryStack();\r\n if (!stack || !ctx) return;\r\n const recorder = this.deps.getHistoryRecorder();\r\n recorder?.pause();\r\n stack.redo(ctx.store);\r\n recorder?.resume();\r\n ctx.requestRender();\r\n }\r\n\r\n copy(): void {\r\n if (this.deps.isToolActive()) return;\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const ids = sel.tool.selectedIds;\r\n if (ids.length === 0) return;\r\n this.clipboard = [];\r\n for (const id of ids) {\r\n const el = sel.ctx.store.getById(id);\r\n if (el) this.clipboard.push(structuredClone(el));\r\n }\r\n this.pasteCount = 0;\r\n }\r\n\r\n cut(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.copy();\r\n this.deleteSelected();\r\n }\r\n\r\n hasClipboard(): boolean {\r\n return this.clipboard.length > 0;\r\n }\r\n\r\n paste(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n if (this.clipboard.length === 0) return;\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n\r\n const cursor = this.deps.getLastPointerWorld?.() ?? null;\r\n if (cursor) {\r\n const bbox = getElementsBoundingBox(this.clipboard);\r\n if (bbox) {\r\n const centerX = bbox.x + bbox.w / 2;\r\n const centerY = bbox.y + bbox.h / 2;\r\n this.insertClones(this.clipboard, { x: cursor.x - centerX, y: cursor.y - centerY }, sel);\r\n return;\r\n }\r\n }\r\n\r\n this.pasteCount++;\r\n this.insertClones(this.clipboard, { x: this.pasteCount * 20, y: this.pasteCount * 20 }, sel);\r\n }\r\n\r\n duplicate(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const source: CanvasElement[] = [];\r\n for (const id of sel.tool.selectedIds) {\r\n const el = sel.ctx.store.getById(id);\r\n if (el) source.push(el);\r\n }\r\n if (source.length === 0) return;\r\n this.insertClones(source, { x: 20, y: 20 }, sel);\r\n }\r\n\r\n deselect(): void {\r\n if (this.deps.isToolActive()) return;\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n if (sel.tool.selectedIds.length === 0) return;\r\n sel.tool.setSelection([]);\r\n sel.ctx.requestRender();\r\n }\r\n\r\n selectAll(): void {\r\n if (this.deps.isToolActive()) return;\r\n const tm = this.deps.getToolManager();\r\n const ctx = this.deps.getToolContext();\r\n if (!tm || !ctx) return;\r\n if (tm.activeTool?.name !== 'select') {\r\n ctx.switchTool?.('select');\r\n }\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const ids = sel.ctx.store\r\n .getAll()\r\n .filter(\r\n (el) =>\r\n !el.locked &&\r\n (sel.ctx.isLayerVisible?.(el.layerId) ?? true) &&\r\n !(sel.ctx.isLayerLocked?.(el.layerId) ?? false),\r\n )\r\n .map((el) => el.id);\r\n sel.tool.setSelection(ids);\r\n sel.ctx.requestRender();\r\n }\r\n\r\n zoomToFit(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.deps.fitToContent?.();\r\n }\r\n\r\n group(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.deps.group?.();\r\n }\r\n\r\n ungroup(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.deps.ungroup?.();\r\n }\r\n\r\n toggleLock(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.deps.toggleLock?.();\r\n }\r\n\r\n zOrder(operation: 'forward' | 'backward' | 'front' | 'back'): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const ids = sel.tool.selectedIds;\r\n if (ids.length === 0) return;\r\n const recorder = this.deps.getHistoryRecorder();\r\n recorder?.begin();\r\n for (const id of ids) {\r\n switch (operation) {\r\n case 'forward':\r\n sel.ctx.store.bringForward(id);\r\n break;\r\n case 'backward':\r\n sel.ctx.store.sendBackward(id);\r\n break;\r\n case 'front':\r\n sel.ctx.store.bringToFront(id);\r\n break;\r\n case 'back':\r\n sel.ctx.store.sendToBack(id);\r\n break;\r\n }\r\n }\r\n recorder?.commit();\r\n sel.ctx.requestRender();\r\n }\r\n\r\n private insertClones(\r\n source: CanvasElement[],\r\n offset: Point,\r\n sel: { tool: SelectTool; ctx: ToolContext },\r\n ): void {\r\n const idMap = new Map<string, string>();\r\n for (const el of source) {\r\n idMap.set(el.id, createId(el.type));\r\n }\r\n\r\n const groupIdMap = new Map<string, string>();\r\n for (const el of source) {\r\n if (el.groupId && !groupIdMap.has(el.groupId)) groupIdMap.set(el.groupId, createId('group'));\r\n }\r\n\r\n const newIds: string[] = [];\r\n const recorder = this.deps.getHistoryRecorder();\r\n recorder?.begin();\r\n\r\n for (const el of source) {\r\n const clone = structuredClone(el);\r\n const newId = idMap.get(el.id);\r\n if (!newId) continue;\r\n clone.id = newId;\r\n if (clone.groupId) clone.groupId = groupIdMap.get(clone.groupId) ?? clone.groupId;\r\n clone.position = { x: clone.position.x + offset.x, y: clone.position.y + offset.y };\r\n\r\n if (clone.type === 'arrow') {\r\n const arrow = clone;\r\n arrow.from = { x: arrow.from.x + offset.x, y: arrow.from.y + offset.y };\r\n arrow.to = { x: arrow.to.x + offset.x, y: arrow.to.y + offset.y };\r\n delete arrow.cachedControlPoint;\r\n\r\n if (arrow.fromBinding) {\r\n const newTarget = idMap.get(arrow.fromBinding.elementId);\r\n if (newTarget) {\r\n arrow.fromBinding = { elementId: newTarget };\r\n } else {\r\n delete arrow.fromBinding;\r\n }\r\n }\r\n if (arrow.toBinding) {\r\n const newTarget = idMap.get(arrow.toBinding.elementId);\r\n if (newTarget) {\r\n arrow.toBinding = { elementId: newTarget };\r\n } else {\r\n delete arrow.toBinding;\r\n }\r\n }\r\n }\r\n\r\n if (sel.ctx.activeLayerId) {\r\n clone.layerId = sel.ctx.activeLayerId;\r\n }\r\n\r\n sel.ctx.store.add(clone);\r\n newIds.push(clone.id);\r\n }\r\n\r\n recorder?.commit();\r\n sel.tool.setSelection(newIds);\r\n sel.ctx.requestRender();\r\n }\r\n}\r\n","export type ShortcutBindings = Record<string, string | string[] | null>;\r\n\r\nexport interface ShortcutOptions {\r\n scope?: 'focus' | 'window';\r\n bindings?: ShortcutBindings;\r\n}\r\n\r\nexport interface ShortcutsApi {\r\n rebind(action: string, bindings: string | string[] | null): void;\r\n disable(action: string): void;\r\n reset(action?: string): void;\r\n getBindings(): Record<string, string[]>;\r\n}\r\n\r\ninterface ParsedBinding {\r\n mod: boolean;\r\n ctrl: boolean;\r\n meta: boolean;\r\n shift: boolean;\r\n alt: boolean;\r\n key: string;\r\n digit: boolean;\r\n}\r\n\r\nconst DEFAULT_BINDINGS: readonly (readonly [string, readonly string[]])[] = [\r\n ['delete', ['delete', 'backspace']],\r\n ['deselect', ['escape']],\r\n ['undo', ['mod+z']],\r\n ['redo', ['mod+y', 'mod+shift+z']],\r\n ['select-all', ['mod+a']],\r\n ['copy', ['mod+c']],\r\n ['paste', ['mod+v']],\r\n ['duplicate', ['mod+d']],\r\n ['z-forward', [']']],\r\n ['z-backward', ['[']],\r\n ['z-front', ['mod+]']],\r\n ['z-back', ['mod+[']],\r\n ['zoom-fit', ['shift+1']],\r\n ['zoom-in', ['mod+=']],\r\n ['zoom-out', ['mod+-']],\r\n ['zoom-reset', ['mod+0']],\r\n ['group', ['mod+g']],\r\n ['ungroup', ['mod+shift+g']],\r\n ['cut', ['mod+x']],\r\n ['toggle-lock', ['mod+shift+l']],\r\n ['nudge-left', ['arrowleft']],\r\n ['nudge-right', ['arrowright']],\r\n ['nudge-up', ['arrowup']],\r\n ['nudge-down', ['arrowdown']],\r\n ['tool:select', ['v']],\r\n ['tool:hand', ['h']],\r\n ['tool:pencil', ['p']],\r\n ['tool:eraser', ['e']],\r\n ['tool:arrow', ['a']],\r\n ['tool:note', ['n']],\r\n ['tool:text', ['t']],\r\n ['tool:shape', ['s']],\r\n ['tool:measure', ['m']],\r\n ['tool:template', ['g']],\r\n];\r\n\r\nconst ALLOW_SHIFT = new Set(['nudge-left', 'nudge-right', 'nudge-up', 'nudge-down']);\r\nconst MODIFIERS = new Set(['mod', 'ctrl', 'meta', 'shift', 'alt']);\r\n\r\nfunction parseBinding(binding: string): ParsedBinding {\r\n const parts = binding.toLowerCase().split('+');\r\n const key = parts.pop();\r\n if (key === undefined || key.length === 0 || MODIFIERS.has(key)) {\r\n throw new Error(`Invalid shortcut binding \"${binding}\": missing key`);\r\n }\r\n const normalizedKey = key === 'space' ? ' ' : key;\r\n const parsed: ParsedBinding = {\r\n mod: false,\r\n ctrl: false,\r\n meta: false,\r\n shift: false,\r\n alt: false,\r\n key: normalizedKey,\r\n digit: /^[0-9]$/.test(normalizedKey),\r\n };\r\n for (const part of parts) {\r\n switch (part) {\r\n case 'mod':\r\n parsed.mod = true;\r\n break;\r\n case 'ctrl':\r\n parsed.ctrl = true;\r\n break;\r\n case 'meta':\r\n parsed.meta = true;\r\n break;\r\n case 'shift':\r\n parsed.shift = true;\r\n break;\r\n case 'alt':\r\n parsed.alt = true;\r\n break;\r\n default:\r\n throw new Error(`Invalid shortcut binding \"${binding}\": unknown modifier \"${part}\"`);\r\n }\r\n }\r\n if (parsed.mod && (parsed.ctrl || parsed.meta)) {\r\n throw new Error(\r\n `Invalid shortcut binding \"${binding}\": \"mod\" already means Ctrl or Cmd; don't combine it with ctrl/meta`,\r\n );\r\n }\r\n return parsed;\r\n}\r\n\r\nfunction bindingMatches(p: ParsedBinding, e: KeyboardEvent, allowShift: boolean): boolean {\r\n if (p.mod) {\r\n if (!e.ctrlKey && !e.metaKey) return false;\r\n } else if (e.ctrlKey !== p.ctrl || e.metaKey !== p.meta) {\r\n return false;\r\n }\r\n if (!allowShift && e.shiftKey !== p.shift) return false;\r\n if (e.altKey !== p.alt) return false;\r\n return p.digit ? e.code === `Digit${p.key}` : e.key.toLowerCase() === p.key;\r\n}\r\n\r\nfunction toArray(bindings: string | string[] | null): string[] {\r\n if (bindings === null) return [];\r\n return Array.isArray(bindings) ? [...bindings] : [bindings];\r\n}\r\n\r\nexport class ShortcutMap implements ShortcutsApi {\r\n private raw = new Map<string, string[]>();\r\n private parsed = new Map<string, ParsedBinding[]>();\r\n\r\n constructor(overrides?: ShortcutBindings) {\r\n this.applyDefaults();\r\n if (overrides) {\r\n for (const [action, bindings] of Object.entries(overrides)) {\r\n this.rebind(action, bindings);\r\n }\r\n }\r\n }\r\n\r\n /** First matching action in registration order wins when bindings conflict. */\r\n match(e: KeyboardEvent): string | null {\r\n for (const [action, parsedList] of this.parsed) {\r\n const allowShift = ALLOW_SHIFT.has(action);\r\n for (const p of parsedList) {\r\n if (bindingMatches(p, e, allowShift)) return action;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n rebind(action: string, bindings: string | string[] | null): void {\r\n const list = toArray(bindings);\r\n const parsedList = list.map(parseBinding);\r\n this.raw.set(action, list);\r\n this.parsed.set(action, parsedList);\r\n }\r\n\r\n disable(action: string): void {\r\n this.rebind(action, null);\r\n }\r\n\r\n reset(action?: string): void {\r\n if (action === undefined) {\r\n this.raw.clear();\r\n this.parsed.clear();\r\n this.applyDefaults();\r\n return;\r\n }\r\n const def = DEFAULT_BINDINGS.find(([name]) => name === action);\r\n if (def) {\r\n this.rebind(action, [...def[1]]);\r\n } else if (this.raw.has(action)) {\r\n this.raw.delete(action);\r\n this.parsed.delete(action);\r\n }\r\n }\r\n\r\n getBindings(): Record<string, string[]> {\r\n const out: Record<string, string[]> = {};\r\n for (const [action, list] of this.raw) {\r\n out[action] = [...list];\r\n }\r\n return out;\r\n }\r\n\r\n private applyDefaults(): void {\r\n for (const [action, bindings] of DEFAULT_BINDINGS) {\r\n this.rebind(action, [...bindings]);\r\n }\r\n }\r\n}\r\n","import type { Camera } from './camera';\nimport type { ToolContext } from '../tools/types';\nimport type { ShortcutOptions, ShortcutsApi } from './shortcut-map';\nimport { ShortcutMap } from './shortcut-map';\nimport type { KeyboardActions } from './keyboard-actions';\n\nconst ZOOM_STEP = 1.2;\n\nconst NUDGE_DELTAS: Record<string, readonly [number, number]> = {\n 'nudge-left': [-1, 0],\n 'nudge-right': [1, 0],\n 'nudge-up': [0, -1],\n 'nudge-down': [0, 1],\n};\n\nexport interface KeyboardHandlerDeps {\n element: HTMLElement;\n camera: Camera;\n actions: KeyboardActions;\n scope: 'focus' | 'window';\n shortcuts?: ShortcutOptions;\n abortSignal: AbortSignal;\n getToolContext: () => ToolContext | null;\n getIsToolActive: () => boolean;\n getLastPointerEvent: () => PointerEvent | null;\n setSpaceHeld: (v: boolean) => void;\n getActivePointerCount: () => number;\n dispatchToolHover: (e: PointerEvent) => void;\n}\n\nexport class KeyboardHandler {\n private readonly shortcutMap: ShortcutMap;\n\n constructor(private readonly deps: KeyboardHandlerDeps) {\n this.shortcutMap = new ShortcutMap(deps.shortcuts?.bindings);\n window.addEventListener('keydown', this.onKeyDown, { signal: deps.abortSignal });\n window.addEventListener('keyup', this.onKeyUp, { signal: deps.abortSignal });\n }\n\n get shortcuts(): ShortcutsApi {\n return this.shortcutMap;\n }\n\n private viewportCenter(): { x: number; y: number } {\n const rect = this.deps.element.getBoundingClientRect();\n return { x: rect.width / 2, y: rect.height / 2 };\n }\n\n private zoomByFactor(factor: number): void {\n this.deps.camera.zoomAt(this.deps.camera.zoom * factor, this.viewportCenter());\n }\n\n private zoomToLevel(level: number): void {\n this.deps.camera.zoomAt(level, this.viewportCenter());\n }\n\n onKeyDown = (e: KeyboardEvent): void => {\n const target = e.target as HTMLElement | null;\n if (target?.isContentEditable) return;\n const tag = target?.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return;\n if (!this.isInScope()) return;\n\n if (e.key === ' ') {\n this.deps.setSpaceHeld(true);\n }\n const action = this.shortcutMap.match(e);\n if (action !== null) {\n this.runAction(action, e);\n }\n };\n\n onKeyUp = (e: KeyboardEvent): void => {\n if (e.key === ' ') {\n this.deps.setSpaceHeld(false);\n if (this.deps.getActivePointerCount() === 0) {\n const lastPointerEvent = this.deps.getLastPointerEvent();\n if (lastPointerEvent) {\n this.deps.dispatchToolHover(lastPointerEvent);\n } else {\n this.deps.getToolContext()?.setCursor?.('default');\n }\n }\n }\n };\n\n runAction(action: string, e?: KeyboardEvent): void {\n switch (action) {\n case 'delete':\n e?.preventDefault();\n this.deps.actions.deleteSelected();\n return;\n case 'deselect':\n this.deps.actions.deselect();\n return;\n case 'undo':\n e?.preventDefault();\n this.deps.actions.undo();\n return;\n case 'redo':\n e?.preventDefault();\n this.deps.actions.redo();\n return;\n case 'select-all':\n e?.preventDefault();\n this.deps.actions.selectAll();\n return;\n case 'copy':\n e?.preventDefault();\n this.deps.actions.copy();\n return;\n case 'paste':\n e?.preventDefault();\n this.deps.actions.paste();\n return;\n case 'duplicate':\n e?.preventDefault();\n this.deps.actions.duplicate();\n return;\n case 'z-forward':\n e?.preventDefault();\n this.deps.actions.zOrder('forward');\n return;\n case 'z-backward':\n e?.preventDefault();\n this.deps.actions.zOrder('backward');\n return;\n case 'z-front':\n e?.preventDefault();\n this.deps.actions.zOrder('front');\n return;\n case 'z-back':\n e?.preventDefault();\n this.deps.actions.zOrder('back');\n return;\n case 'zoom-fit':\n e?.preventDefault();\n this.deps.actions.zoomToFit();\n return;\n case 'group':\n e?.preventDefault();\n this.deps.actions.group();\n return;\n case 'ungroup':\n e?.preventDefault();\n this.deps.actions.ungroup();\n return;\n case 'cut':\n e?.preventDefault();\n this.deps.actions.cut();\n return;\n case 'toggle-lock':\n e?.preventDefault();\n this.deps.actions.toggleLock();\n return;\n case 'zoom-in':\n e?.preventDefault();\n this.zoomByFactor(ZOOM_STEP);\n return;\n case 'zoom-out':\n e?.preventDefault();\n this.zoomByFactor(1 / ZOOM_STEP);\n return;\n case 'zoom-reset':\n e?.preventDefault();\n this.zoomToLevel(1);\n return;\n case 'nudge-left':\n case 'nudge-right':\n case 'nudge-up':\n case 'nudge-down': {\n const delta = NUDGE_DELTAS[action];\n if (delta && this.deps.actions.nudge(delta[0], delta[1], e?.shiftKey ?? false)) {\n e?.preventDefault();\n }\n return;\n }\n default:\n if (action.startsWith('tool:')) {\n if (this.deps.getIsToolActive()) return;\n e?.preventDefault();\n this.deps.getToolContext()?.switchTool?.(action.slice('tool:'.length));\n return;\n }\n console.warn(`[fieldnotes] unknown shortcut action \"${action}\"`);\n }\n }\n\n private isInScope(): boolean {\n if (this.deps.scope === 'window') return true;\n const active = document.activeElement;\n return active === this.deps.element || this.deps.element.contains(active);\n }\n}\n","import type { Point } from '../core/types';\nimport type { Camera } from './camera';\nimport type { ToolManager } from '../tools/tool-manager';\nimport type { ToolContext, PointerState } from '../tools/types';\nimport type { HistoryRecorder } from '../history/history-recorder';\nimport type { HistoryStack } from '../history/history-stack';\nimport type { ShortcutOptions, ShortcutsApi } from './shortcut-map';\nimport { InputFilter } from './input-filter';\nimport { KeyboardActions } from './keyboard-actions';\nimport { KeyboardHandler } from './keyboard-handler';\n\nconst ZOOM_SENSITIVITY = 0.001;\nconst MIDDLE_BUTTON = 1;\nconst LONG_PRESS_MS = 500;\n\nexport interface InputHandlerOptions {\n toolManager?: ToolManager;\n toolContext?: ToolContext;\n historyRecorder?: HistoryRecorder;\n historyStack?: HistoryStack;\n fitToContent?: () => void;\n group?: () => void;\n ungroup?: () => void;\n toggleLock?: () => void;\n openContextMenu?: (screenPos: Point, world: Point) => void;\n shortcuts?: ShortcutOptions;\n}\n\nexport class InputHandler {\n private isPanning = false;\n private lastPointer = { x: 0, y: 0 };\n private spaceHeld = false;\n private activePointers = new Map<number, { x: number; y: number }>();\n private lastPinchDistance = 0;\n private lastPinchCenter = { x: 0, y: 0 };\n private toolManager: ToolManager | null;\n private toolContext: ToolContext | null;\n private historyRecorder: HistoryRecorder | null;\n private historyStack: HistoryStack | null;\n private isToolActive = false;\n private lastPointerEvent: PointerEvent | null = null;\n private readonly inputFilter = new InputFilter();\n private deferredDown: PointerEvent | null = null;\n private longPressTimer: ReturnType<typeof setTimeout> | null = null;\n private longPressStart: { x: number; y: number } | null = null;\n private readonly abortController = new AbortController();\n private readonly actions: KeyboardActions;\n private readonly keyboard: KeyboardHandler;\n private readonly scope: 'focus' | 'window';\n private readonly openContextMenu?: (screenPos: Point, world: Point) => void;\n\n constructor(\n private readonly element: HTMLElement,\n private readonly camera: Camera,\n options: InputHandlerOptions = {},\n ) {\n this.toolManager = options.toolManager ?? null;\n this.toolContext = options.toolContext ?? null;\n this.historyRecorder = options.historyRecorder ?? null;\n this.historyStack = options.historyStack ?? null;\n this.actions = new KeyboardActions({\n getToolManager: () => this.toolManager,\n getToolContext: () => this.toolContext,\n getHistoryRecorder: () => this.historyRecorder,\n getHistoryStack: () => this.historyStack,\n isToolActive: () => this.isToolActive,\n fitToContent: options.fitToContent,\n group: options.group,\n ungroup: options.ungroup,\n toggleLock: options.toggleLock,\n getLastPointerWorld: () => this.lastPointerWorld(),\n });\n this.openContextMenu = options.openContextMenu;\n this.scope = options.shortcuts?.scope ?? 'focus';\n this.keyboard = new KeyboardHandler({\n element: this.element,\n camera: this.camera,\n actions: this.actions,\n scope: this.scope,\n shortcuts: options.shortcuts,\n abortSignal: this.abortController.signal,\n getToolContext: () => this.toolContext,\n getIsToolActive: () => this.isToolActive,\n getLastPointerEvent: () => this.lastPointerEvent,\n setSpaceHeld: (v) => {\n this.spaceHeld = v;\n },\n getActivePointerCount: () => this.activePointers.size,\n dispatchToolHover: (e) => this.dispatchToolHover(e),\n });\n this.element.style.touchAction = 'none';\n if (this.scope === 'focus') {\n this.element.tabIndex = 0;\n // Suppressed like other canvas SDKs; consumers needing a focus ring style their container.\n this.element.style.outline = 'none';\n }\n this.bind();\n }\n\n setToolManager(toolManager: ToolManager, toolContext: ToolContext): void {\n this.toolManager = toolManager;\n this.toolContext = toolContext;\n }\n\n flushPendingHistory(): void {\n this.actions.flushPendingNudge();\n }\n\n get shortcuts(): ShortcutsApi {\n return this.keyboard.shortcuts;\n }\n\n destroy(): void {\n this.actions.dispose();\n this.abortController.abort();\n this.inputFilter.reset();\n this.cancelLongPress();\n this.deferredDown = null;\n this.lastPointerEvent = null;\n if (this.scope === 'focus') {\n this.element.removeAttribute('tabindex');\n this.element.style.outline = '';\n }\n }\n\n private bind(): void {\n const opts = { signal: this.abortController.signal };\n\n this.element.addEventListener('wheel', this.onWheel, { ...opts, passive: false });\n this.element.addEventListener('pointerdown', this.onPointerDown, opts);\n this.element.addEventListener('pointermove', this.onPointerMove, opts);\n this.element.addEventListener('pointerup', this.onPointerUp, opts);\n this.element.addEventListener('pointerleave', this.onPointerLeave, opts);\n this.element.addEventListener('pointercancel', this.onPointerUp, opts);\n this.element.addEventListener('contextmenu', this.onContextMenu, opts);\n }\n\n private onWheel = (e: WheelEvent): void => {\n e.preventDefault();\n const rect = this.element.getBoundingClientRect();\n const zoomFactor = 1 - e.deltaY * ZOOM_SENSITIVITY;\n const newZoom = this.camera.zoom * zoomFactor;\n this.camera.zoomAt(newZoom, {\n x: e.clientX - rect.left,\n y: e.clientY - rect.top,\n });\n };\n\n private onPointerDown = (e: PointerEvent): void => {\n this.focusSelf();\n this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });\n\n this.element.setPointerCapture?.(e.pointerId);\n\n if (this.activePointers.size === 2) {\n this.cancelLongPress();\n this.startPinch();\n this.cancelToolIfActive(e);\n return;\n }\n\n if (e.button === MIDDLE_BUTTON || (e.button === 0 && this.spaceHeld)) {\n this.cancelLongPress();\n this.isPanning = true;\n this.lastPointer = { x: e.clientX, y: e.clientY };\n return;\n }\n\n if (\n this.activePointers.size === 1 &&\n (e.button === 0 || e.pointerType === 'touch' || e.pointerType === 'pen')\n ) {\n const result = this.inputFilter.filterDown(e);\n if (result.action === 'suppress') return;\n if (result.action === 'defer') {\n this.deferredDown = e;\n this.startLongPress(e);\n return;\n }\n this.dispatchToolDown(e);\n }\n };\n\n private onPointerMove = (e: PointerEvent): void => {\n this.lastPointerEvent = e;\n\n if (this.activePointers.has(e.pointerId)) {\n this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });\n }\n\n if (this.activePointers.size === 2) {\n this.handlePinchMove();\n return;\n }\n\n if (this.isPanning) {\n const dx = e.clientX - this.lastPointer.x;\n const dy = e.clientY - this.lastPointer.y;\n this.lastPointer = { x: e.clientX, y: e.clientY };\n this.camera.pan(dx, dy);\n return;\n }\n\n if (e.pointerType === 'pen' && !this.activePointers.has(e.pointerId)) {\n this.dispatchToolHover(e);\n } else if (this.isToolActive) {\n this.dispatchToolMove(e);\n } else if (this.deferredDown) {\n const result = this.inputFilter.filterMove(e);\n if (result.action === 'dispatch') {\n this.cancelLongPress();\n this.dispatchToolDown(this.deferredDown);\n this.deferredDown = null;\n this.dispatchToolMove(e);\n }\n } else if (this.activePointers.size === 0) {\n this.dispatchToolHover(e);\n }\n };\n\n private onPointerUp = (e: PointerEvent): void => {\n this.cancelLongPress();\n try {\n this.element.releasePointerCapture(e.pointerId);\n } catch {\n // Already released (e.g., pointercancel fired first)\n }\n this.activePointers.delete(e.pointerId);\n\n if (this.activePointers.size < 2) {\n this.lastPinchDistance = 0;\n }\n\n if (this.isPanning && this.activePointers.size === 0) {\n this.isPanning = false;\n }\n\n const upResult = this.inputFilter.filterUp(e);\n\n if (this.isToolActive) {\n this.dispatchToolUp(e);\n this.isToolActive = false;\n } else if (this.deferredDown && upResult.pendingTap) {\n this.dispatchToolDown(this.deferredDown);\n this.dispatchToolUp(e);\n this.deferredDown = null;\n } else {\n this.deferredDown = null;\n }\n };\n\n runAction(action: string, e?: KeyboardEvent): void {\n this.keyboard.runAction(action, e);\n }\n\n hasClipboard(): boolean {\n return this.actions.hasClipboard();\n }\n\n private startPinch(): void {\n this.cancelLongPress();\n this.inputFilter.reset();\n this.deferredDown = null;\n this.isPanning = true;\n const [a, b] = this.getPinchPoints();\n this.lastPinchDistance = this.distance(a, b);\n this.lastPinchCenter = this.midpoint(a, b);\n this.lastPointer = { ...this.lastPinchCenter };\n }\n\n private handlePinchMove(): void {\n const [a, b] = this.getPinchPoints();\n const dist = this.distance(a, b);\n const center = this.midpoint(a, b);\n\n if (this.lastPinchDistance > 0) {\n const scale = dist / this.lastPinchDistance;\n const newZoom = this.camera.zoom * scale;\n this.camera.zoomAt(newZoom, center);\n }\n\n const dx = center.x - this.lastPointer.x;\n const dy = center.y - this.lastPointer.y;\n this.camera.pan(dx, dy);\n\n this.lastPinchDistance = dist;\n this.lastPinchCenter = center;\n this.lastPointer = { ...center };\n }\n\n private getPinchPoints(): [{ x: number; y: number }, { x: number; y: number }] {\n const pts = [...this.activePointers.values()];\n return [pts[0] ?? { x: 0, y: 0 }, pts[1] ?? { x: 0, y: 0 }];\n }\n\n private distance(a: { x: number; y: number }, b: { x: number; y: number }): number {\n const dx = a.x - b.x;\n const dy = a.y - b.y;\n return Math.sqrt(dx * dx + dy * dy);\n }\n\n private midpoint(\n a: { x: number; y: number },\n b: { x: number; y: number },\n ): { x: number; y: number } {\n return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\n }\n\n private lastPointerWorld(): { x: number; y: number } | null {\n const e = this.lastPointerEvent;\n if (!e) return null;\n const rect = this.element.getBoundingClientRect();\n return this.camera.screenToWorld({ x: e.clientX - rect.left, y: e.clientY - rect.top });\n }\n\n private onContextMenu = (e: MouseEvent): void => {\n e.preventDefault();\n if (this.toolManager?.activeTool?.name !== 'select') return;\n const rect = this.element.getBoundingClientRect();\n const world = this.camera.screenToWorld({ x: e.clientX - rect.left, y: e.clientY - rect.top });\n this.openContextMenu?.({ x: e.clientX, y: e.clientY }, world);\n };\n\n private onPointerLeave = (e: PointerEvent): void => {\n this.lastPointerEvent = null;\n this.onPointerUp(e);\n };\n\n private toPointerState(e: PointerEvent): PointerState {\n const rect = this.element.getBoundingClientRect();\n return {\n x: e.clientX - rect.left,\n y: e.clientY - rect.top,\n pressure: e.pressure,\n pointerType: e.pointerType === 'touch' || e.pointerType === 'pen' ? e.pointerType : 'mouse',\n shiftKey: e.shiftKey,\n };\n }\n\n private dispatchToolDown(e: PointerEvent): void {\n if (!this.toolManager || !this.toolContext) return;\n this.actions.flushPendingNudge();\n this.historyRecorder?.begin();\n this.isToolActive = true;\n this.toolManager.handlePointerDown(this.toPointerState(e), this.toolContext);\n }\n\n private dispatchToolMove(e: PointerEvent): void {\n if (!this.toolManager || !this.toolContext) return;\n this.toolManager.handlePointerMove(this.toPointerState(e), this.toolContext);\n }\n\n private dispatchToolHover(e: PointerEvent): void {\n if (!this.toolManager?.activeTool || !this.toolContext) return;\n const tool = this.toolManager.activeTool;\n if (tool.onHover) {\n tool.onHover(this.toPointerState(e), this.toolContext);\n }\n }\n\n private dispatchToolUp(e: PointerEvent): void {\n if (!this.toolManager || !this.toolContext) return;\n this.toolManager.handlePointerUp(this.toPointerState(e), this.toolContext);\n this.historyRecorder?.commit();\n }\n\n private isInScope(): boolean {\n if (this.scope === 'window') return true;\n const active = document.activeElement;\n return active === this.element || this.element.contains(active);\n }\n\n private focusSelf(): void {\n if (this.scope !== 'focus' || this.isInScope()) return;\n this.element.focus({ preventScroll: true });\n }\n\n private cancelToolIfActive(e: PointerEvent): void {\n this.cancelLongPress();\n if (this.isToolActive) {\n this.dispatchToolUp(e);\n this.isToolActive = false;\n }\n this.deferredDown = null;\n }\n\n private startLongPress(e: PointerEvent): void {\n if (e.pointerType !== 'touch') return;\n if (this.toolManager?.activeTool?.name !== 'select') return;\n this.longPressStart = { x: e.clientX, y: e.clientY };\n this.longPressTimer = setTimeout(() => this.fireLongPress(), LONG_PRESS_MS);\n }\n\n private cancelLongPress(): void {\n if (this.longPressTimer !== null) {\n clearTimeout(this.longPressTimer);\n this.longPressTimer = null;\n }\n this.longPressStart = null;\n }\n\n private fireLongPress(): void {\n this.longPressTimer = null;\n if (!this.deferredDown || this.activePointers.size !== 1 || this.isPanning) return;\n const start = this.longPressStart;\n if (!start) return;\n const rect = this.element.getBoundingClientRect();\n const world = this.camera.screenToWorld({ x: start.x - rect.left, y: start.y - rect.top });\n this.deferredDown = null;\n this.openContextMenu?.({ x: start.x, y: start.y }, world);\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 private cachedCanvas: OffscreenCanvas | HTMLCanvasElement | null = null;\r\n private cachedCtx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null = null;\r\n private lastZoom = -1;\r\n private lastOffsetX = -Infinity;\r\n private lastOffsetY = -Infinity;\r\n private lastWidth = 0;\r\n private lastHeight = 0;\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\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 === 'none') {\r\n ctx.restore();\r\n return;\r\n }\r\n\r\n const spacing = this.adaptSpacing(this.spacing, camera.zoom);\r\n const keyZoom = camera.zoom;\r\n const keyX = Math.floor(camera.position.x % spacing);\r\n const keyY = Math.floor(camera.position.y % spacing);\r\n\r\n if (\r\n this.cachedCanvas !== null &&\r\n keyZoom === this.lastZoom &&\r\n keyX === this.lastOffsetX &&\r\n keyY === this.lastOffsetY &&\r\n cssWidth === this.lastWidth &&\r\n cssHeight === this.lastHeight\r\n ) {\r\n ctx.drawImage(this.cachedCanvas as CanvasImageSource, 0, 0);\r\n ctx.restore();\r\n return;\r\n }\r\n\r\n this.ensureCachedCanvas(cssWidth, cssHeight, dpr);\r\n\r\n if (this.cachedCtx === null) {\r\n // Fallback: render directly when offscreen canvas is unavailable (e.g. jsdom)\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 ctx.restore();\r\n return;\r\n }\r\n\r\n const offCtx = this.cachedCtx as CanvasRenderingContext2D;\r\n offCtx.clearRect(0, 0, cssWidth, cssHeight);\r\n if (this.pattern === 'dots') {\r\n this.renderDots(offCtx, camera, cssWidth, cssHeight);\r\n } else if (this.pattern === 'grid') {\r\n this.renderGrid(offCtx, camera, cssWidth, cssHeight);\r\n }\r\n\r\n this.lastZoom = keyZoom;\r\n this.lastOffsetX = keyX;\r\n this.lastOffsetY = keyY;\r\n this.lastWidth = cssWidth;\r\n this.lastHeight = cssHeight;\r\n\r\n ctx.drawImage(this.cachedCanvas as CanvasImageSource, 0, 0);\r\n ctx.restore();\r\n }\r\n\r\n private ensureCachedCanvas(cssWidth: number, cssHeight: number, dpr: number): void {\r\n if (\r\n this.cachedCanvas !== null &&\r\n this.lastWidth === cssWidth &&\r\n this.lastHeight === cssHeight\r\n ) {\r\n return;\r\n }\r\n\r\n const physWidth = Math.round(cssWidth * dpr);\r\n const physHeight = Math.round(cssHeight * dpr);\r\n\r\n if (typeof OffscreenCanvas !== 'undefined') {\r\n this.cachedCanvas = new OffscreenCanvas(physWidth, physHeight);\r\n } else if (typeof document !== 'undefined') {\r\n const el = document.createElement('canvas');\r\n el.width = physWidth;\r\n el.height = physHeight;\r\n this.cachedCanvas = el;\r\n } else {\r\n // No offscreen canvas support available; fall back to direct rendering\r\n this.cachedCanvas = null;\r\n this.cachedCtx = null;\r\n return;\r\n }\r\n\r\n const offCtx = this.cachedCanvas.getContext('2d');\r\n if (offCtx !== null) {\r\n (offCtx as CanvasRenderingContext2D).scale(dpr, dpr);\r\n }\r\n this.cachedCtx = offCtx as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;\r\n\r\n // Force re-render on next frame since canvas was recreated\r\n this.lastZoom = -1;\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","type Listener<T> = (data: T) => void;\r\n\r\nexport class EventBus<TEvents extends { [K in keyof TEvents]: TEvents[K] }> {\r\n private listeners = new Map<keyof TEvents, Set<Listener<never>>>();\r\n\r\n on<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): () => void {\r\n const existing = this.listeners.get(event);\r\n if (existing) {\r\n existing.add(listener as Listener<never>);\r\n } else {\r\n const set = new Set<Listener<never>>([listener as Listener<never>]);\r\n this.listeners.set(event, set);\r\n }\r\n return () => this.off(event, listener);\r\n }\r\n\r\n off<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): void {\r\n this.listeners.get(event)?.delete(listener as Listener<never>);\r\n }\r\n\r\n emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void {\r\n this.listeners.get(event)?.forEach((listener) => {\r\n try {\r\n listener(data as never);\r\n } catch (err) {\r\n console.error(`[fieldnotes] listener error for \"${String(event)}\"`, err);\r\n }\r\n });\r\n }\r\n\r\n clear(): void {\r\n this.listeners.clear();\r\n }\r\n}\r\n","import type { Bounds, Point } from './types';\r\n\r\ninterface Entry {\r\n id: string;\r\n bounds: Bounds;\r\n}\r\n\r\nconst MAX_ITEMS = 8;\r\nconst MAX_DEPTH = 8;\r\n\r\nfunction intersects(a: Bounds, b: Bounds): 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\nclass QuadNode {\r\n items: Entry[] = [];\r\n children: QuadNode[] | null = null;\r\n\r\n constructor(\r\n readonly bounds: Bounds,\r\n readonly depth: number,\r\n ) {}\r\n\r\n insert(entry: Entry): void {\r\n if (this.children) {\r\n const idx = this.getChildIndex(entry.bounds);\r\n if (idx !== -1) {\r\n const child = this.children[idx];\r\n if (child) child.insert(entry);\r\n return;\r\n }\r\n this.items.push(entry);\r\n return;\r\n }\r\n\r\n this.items.push(entry);\r\n\r\n if (this.items.length > MAX_ITEMS && this.depth < MAX_DEPTH) {\r\n this.split();\r\n }\r\n }\r\n\r\n remove(id: string): boolean {\r\n const idx = this.items.findIndex((e) => e.id === id);\r\n if (idx !== -1) {\r\n this.items.splice(idx, 1);\r\n return true;\r\n }\r\n\r\n if (this.children) {\r\n for (const child of this.children) {\r\n if (child.remove(id)) {\r\n this.collapseIfEmpty();\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n query(rect: Bounds, result: string[]): void {\r\n if (!intersects(this.bounds, rect)) return;\r\n\r\n for (const item of this.items) {\r\n if (intersects(item.bounds, rect)) {\r\n result.push(item.id);\r\n }\r\n }\r\n\r\n if (this.children) {\r\n for (const child of this.children) {\r\n child.query(rect, result);\r\n }\r\n }\r\n }\r\n\r\n private getChildIndex(itemBounds: Bounds): number {\r\n const midX = this.bounds.x + this.bounds.w / 2;\r\n const midY = this.bounds.y + this.bounds.h / 2;\r\n\r\n const left = itemBounds.x >= this.bounds.x && itemBounds.x + itemBounds.w <= midX;\r\n const right =\r\n itemBounds.x >= midX && itemBounds.x + itemBounds.w <= this.bounds.x + this.bounds.w;\r\n const top = itemBounds.y >= this.bounds.y && itemBounds.y + itemBounds.h <= midY;\r\n const bottom =\r\n itemBounds.y >= midY && itemBounds.y + itemBounds.h <= this.bounds.y + this.bounds.h;\r\n\r\n if (left && top) return 0;\r\n if (right && top) return 1;\r\n if (left && bottom) return 2;\r\n if (right && bottom) return 3;\r\n\r\n return -1;\r\n }\r\n\r\n private split(): void {\r\n const { x, y, w, h } = this.bounds;\r\n const halfW = w / 2;\r\n const halfH = h / 2;\r\n const d = this.depth + 1;\r\n\r\n this.children = [\r\n new QuadNode({ x, y, w: halfW, h: halfH }, d),\r\n new QuadNode({ x: x + halfW, y, w: halfW, h: halfH }, d),\r\n new QuadNode({ x, y: y + halfH, w: halfW, h: halfH }, d),\r\n new QuadNode({ x: x + halfW, y: y + halfH, w: halfW, h: halfH }, d),\r\n ];\r\n\r\n const remaining: Entry[] = [];\r\n for (const item of this.items) {\r\n const idx = this.getChildIndex(item.bounds);\r\n if (idx !== -1) {\r\n const target = this.children[idx];\r\n if (target) target.insert(item);\r\n } else {\r\n remaining.push(item);\r\n }\r\n }\r\n this.items = remaining;\r\n }\r\n\r\n private collapseIfEmpty(): void {\r\n if (!this.children) return;\r\n let totalItems = this.items.length;\r\n for (const child of this.children) {\r\n if (child.children) return;\r\n totalItems += child.items.length;\r\n }\r\n if (totalItems <= MAX_ITEMS) {\r\n for (const child of this.children) {\r\n this.items.push(...child.items);\r\n }\r\n this.children = null;\r\n }\r\n }\r\n}\r\n\r\nexport class Quadtree {\r\n private root: QuadNode;\r\n private _size = 0;\r\n private readonly worldBounds: Bounds;\r\n\r\n constructor(worldBounds: Bounds) {\r\n this.worldBounds = worldBounds;\r\n this.root = new QuadNode(worldBounds, 0);\r\n }\r\n\r\n get size(): number {\r\n return this._size;\r\n }\r\n\r\n insert(id: string, bounds: Bounds): void {\r\n this.root.insert({ id, bounds });\r\n this._size++;\r\n }\r\n\r\n remove(id: string): void {\r\n if (this.root.remove(id)) {\r\n this._size--;\r\n }\r\n }\r\n\r\n update(id: string, newBounds: Bounds): void {\r\n this.remove(id);\r\n this.insert(id, newBounds);\r\n }\r\n\r\n query(rect: Bounds): string[] {\r\n const result: string[] = [];\r\n this.root.query(rect, result);\r\n return result;\r\n }\r\n\r\n queryPoint(point: Point): string[] {\r\n return this.query({ x: point.x, y: point.y, w: 0, h: 0 });\r\n }\r\n\r\n clear(): void {\r\n this.root = new QuadNode(this.worldBounds, 0);\r\n this._size = 0;\r\n }\r\n}\r\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.4;\r\nconst MAX_PRESSURE_SCALE = 1.8;\r\n\r\nexport function pressureToWidth(pressure: number, baseWidth: number): number {\r\n return baseWidth * (MIN_PRESSURE_SCALE + (MAX_PRESSURE_SCALE - 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 } from './types';\r\nimport type { CurveSegment } from './stroke-smoothing';\r\nimport { smoothToSegments, pressureToWidth } from './stroke-smoothing';\r\n\r\nexport interface StrokeWidthBucket {\r\n width: number;\r\n path: Path2D;\r\n}\r\n\r\nexport interface StrokeRenderData {\r\n segments: CurveSegment[]; // always populated; used by hit-testing and the no-Path2D fallback\r\n widths: number[];\r\n buckets: StrokeWidthBucket[] | null; // null when Path2D is unavailable (jsdom / old browsers)\r\n}\r\n\r\n// Strokes are immutable after commit. If points ever become mutable,\r\n// this cache must be invalidated on store.update().\r\nconst cache = new WeakMap<StrokeElement, StrokeRenderData>();\r\n\r\nconst WIDTH_QUANTUM = 0.25;\r\n\r\nfunction buildWidthBuckets(segments: CurveSegment[], widths: number[]): StrokeWidthBucket[] | null {\r\n if (typeof Path2D === 'undefined') return null;\r\n const byWidth = new Map<number, Path2D>();\r\n for (let i = 0; i < segments.length; i++) {\r\n const seg = segments[i];\r\n const w = widths[i];\r\n if (!seg || w === undefined) continue;\r\n const q = Math.max(WIDTH_QUANTUM, Math.round(w / WIDTH_QUANTUM) * WIDTH_QUANTUM);\r\n let path = byWidth.get(q);\r\n if (!path) {\r\n path = new Path2D();\r\n byWidth.set(q, path);\r\n }\r\n // Each segment is an independent open sub-path; moveTo resets the pen between them.\r\n path.moveTo(seg.start.x, seg.start.y);\r\n path.bezierCurveTo(seg.cp1.x, seg.cp1.y, seg.cp2.x, seg.cp2.y, seg.end.x, seg.end.y);\r\n }\r\n return [...byWidth.entries()].map(([width, path]) => ({ width, path }));\r\n}\r\n\r\nexport function computeStrokeSegments(stroke: StrokeElement): StrokeRenderData {\r\n const segments = smoothToSegments(stroke.points);\r\n const widths: number[] = [];\r\n\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 widths.push(w);\r\n }\r\n\r\n const data: StrokeRenderData = { segments, widths, buckets: buildWidthBuckets(segments, widths) };\r\n cache.set(stroke, data);\r\n return data;\r\n}\r\n\r\nexport function getStrokeRenderData(stroke: StrokeElement): StrokeRenderData {\r\n const cached = cache.get(stroke);\r\n if (cached) return cached;\r\n return computeStrokeSegments(stroke);\r\n}\r\n\r\nexport function transferStrokeRenderData(prev: CanvasElement, next: CanvasElement): void {\r\n if (prev.type !== 'stroke' || next.type !== 'stroke') return;\r\n if (prev.points !== next.points) return;\r\n const data = cache.get(prev);\r\n if (data) cache.set(next, data);\r\n}\r\n","import { EventBus } from '../core/event-bus';\r\nimport type { Bounds, Point } from '../core/types';\r\nimport { Quadtree } from '../core/quadtree';\r\nimport { rotatedAABB } from '../core/geometry';\r\nimport { getElementBounds, transferStrokeBounds } from './element-bounds';\r\nimport { getArrowControlPoint } from './arrow-geometry';\r\nimport { sanitizeNoteHtml } from './note-sanitizer';\r\nimport { computeStrokeSegments, transferStrokeRenderData } from './stroke-cache';\r\nimport type { CanvasElement, ElementType } from './types';\r\n\r\nexport interface ElementUpdateEvent {\r\n previous: CanvasElement;\r\n current: CanvasElement;\r\n}\r\n\r\ninterface ElementStoreEvents {\r\n add: CanvasElement;\r\n remove: CanvasElement;\r\n update: ElementUpdateEvent;\r\n clear: null;\r\n}\r\n\r\nexport class ElementStore {\r\n private elements = new Map<string, CanvasElement>();\r\n private bus = new EventBus<ElementStoreEvents>();\r\n private layerOrderMap = new Map<string, number>();\r\n private spatialIndex = new Quadtree({ x: -100000, y: -100000, w: 200000, h: 200000 });\r\n private sortedCache: CanvasElement[] | null = null;\r\n private _versions = new Map<string, number>();\r\n\r\n get count(): number {\r\n return this.elements.size;\r\n }\r\n\r\n getVersion(id: string): number {\r\n return this._versions.get(id) ?? -1;\r\n }\r\n\r\n setLayerOrder(order: Map<string, number>): void {\r\n this.layerOrderMap = new Map(order);\r\n this.sortedCache = null;\r\n }\r\n\r\n getAll(): CanvasElement[] {\r\n if (this.sortedCache) return this.sortedCache;\r\n this.sortedCache = [...this.elements.values()].sort((a, b) => {\r\n const layerA = this.layerOrderMap.get(a.layerId) ?? 0;\r\n const layerB = this.layerOrderMap.get(b.layerId) ?? 0;\r\n if (layerA !== layerB) return layerA - layerB;\r\n return a.zIndex - b.zIndex;\r\n });\r\n return this.sortedCache;\r\n }\r\n\r\n getById(id: string): CanvasElement | undefined {\r\n return this.elements.get(id);\r\n }\r\n\r\n getElementsByType<T extends ElementType>(type: T): Extract<CanvasElement, { type: T }>[] {\r\n return this.getAll().filter(\r\n (el): el is Extract<CanvasElement, { type: T }> => el.type === type,\r\n );\r\n }\r\n\r\n // Spatial index stores the rotation-expanded AABB so rotated elements remain\r\n // broad-phase hit-test/marquee candidates; precise tests run against local bounds.\r\n private indexBounds(element: CanvasElement): Bounds | null {\r\n const bounds = getElementBounds(element);\r\n if (!bounds) return null;\r\n const angle = element.rotation ?? 0;\r\n return angle === 0 ? bounds : rotatedAABB(bounds, angle);\r\n }\r\n\r\n add(element: CanvasElement): void {\r\n this.sortedCache = null;\r\n this._versions.set(element.id, 0);\r\n this.elements.set(element.id, element);\r\n const bounds = this.indexBounds(element);\r\n if (bounds) this.spatialIndex.insert(element.id, bounds);\r\n this.bus.emit('add', element);\r\n }\r\n\r\n update(id: string, partial: Partial<CanvasElement>): void {\r\n const existing = this.elements.get(id);\r\n if (!existing) return;\r\n this.sortedCache = null;\r\n this._versions.set(id, (this._versions.get(id) ?? 0) + 1);\r\n\r\n // Shallow spread preserves the points array identity when `partial` omits points;\r\n // transferStrokeRenderData/transferStrokeBounds rely on that reference equality.\r\n const updated = {\r\n ...existing,\r\n ...partial,\r\n id: existing.id,\r\n type: existing.type,\r\n } as CanvasElement;\r\n\r\n if (updated.type === 'stroke' && existing.type === 'stroke') {\r\n transferStrokeRenderData(existing, updated);\r\n transferStrokeBounds(existing, updated);\r\n }\r\n\r\n if (updated.type === 'arrow') {\r\n const arrow = updated;\r\n arrow.cachedControlPoint = getArrowControlPoint(arrow.from, arrow.to, arrow.bend);\r\n }\r\n\r\n if (updated.type === 'note' && 'text' in partial) {\r\n updated.text = sanitizeNoteHtml(updated.text);\r\n }\r\n\r\n this.elements.set(id, updated);\r\n\r\n const newBounds = this.indexBounds(updated);\r\n if (newBounds) {\r\n this.spatialIndex.update(id, newBounds);\r\n }\r\n\r\n this.bus.emit('update', { previous: existing, current: updated });\r\n }\r\n\r\n remove(id: string): void {\r\n const element = this.elements.get(id);\r\n if (!element) return;\r\n this.sortedCache = null;\r\n this._versions.delete(id);\r\n\r\n this.elements.delete(id);\r\n this.spatialIndex.remove(id);\r\n this.bus.emit('remove', element);\r\n }\r\n\r\n clear(): void {\r\n this.sortedCache = null;\r\n this._versions.clear();\r\n this.elements.clear();\r\n this.spatialIndex.clear();\r\n this.bus.emit('clear', null);\r\n }\r\n\r\n snapshot(): CanvasElement[] {\r\n return this.getAll().map((el) => ({ ...el }));\r\n }\r\n\r\n loadSnapshot(elements: CanvasElement[]): void {\r\n this.sortedCache = null;\r\n this._versions.clear();\r\n this.elements.clear();\r\n this.spatialIndex.clear();\r\n for (const el of elements) {\r\n this.elements.set(el.id, el);\r\n this._versions.set(el.id, 0);\r\n const bounds = this.indexBounds(el);\r\n if (bounds) this.spatialIndex.insert(el.id, bounds);\r\n if (el.type === 'stroke') {\r\n computeStrokeSegments(el);\r\n }\r\n if (el.type === 'arrow' && el.bend !== 0 && !el.cachedControlPoint) {\r\n el.cachedControlPoint = getArrowControlPoint(el.from, el.to, el.bend);\r\n }\r\n }\r\n this.bus.emit('clear', null);\r\n for (const el of elements) {\r\n this.bus.emit('add', el);\r\n }\r\n }\r\n\r\n bringToFront(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const siblings = [...this.elements.values()].filter(\r\n (e) => e.layerId === el.layerId && e.id !== id,\r\n );\r\n if (siblings.length === 0) return;\r\n const maxZ = Math.max(...siblings.map((e) => e.zIndex));\r\n if (el.zIndex >= maxZ) return;\r\n this.update(id, { zIndex: maxZ + 1 });\r\n }\r\n\r\n sendToBack(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const siblings = [...this.elements.values()].filter(\r\n (e) => e.layerId === el.layerId && e.id !== id,\r\n );\r\n if (siblings.length === 0) return;\r\n const minZ = Math.min(...siblings.map((e) => e.zIndex));\r\n if (el.zIndex <= minZ) return;\r\n this.update(id, { zIndex: minZ - 1 });\r\n }\r\n\r\n bringForward(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const sorted = [...this.elements.values()]\r\n .filter((e) => e.layerId === el.layerId)\r\n .sort((a, b) => a.zIndex - b.zIndex);\r\n const idx = sorted.findIndex((e) => e.id === id);\r\n if (idx < 0 || idx >= sorted.length - 1) return;\r\n const next = sorted[idx + 1];\r\n if (!next) return;\r\n const myZ = el.zIndex;\r\n const nextZ = next.zIndex;\r\n this.update(id, { zIndex: nextZ });\r\n this.update(next.id, { zIndex: myZ });\r\n }\r\n\r\n sendBackward(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const sorted = [...this.elements.values()]\r\n .filter((e) => e.layerId === el.layerId)\r\n .sort((a, b) => a.zIndex - b.zIndex);\r\n const idx = sorted.findIndex((e) => e.id === id);\r\n if (idx <= 0) return;\r\n const prev = sorted[idx - 1];\r\n if (!prev) return;\r\n const myZ = el.zIndex;\r\n const prevZ = prev.zIndex;\r\n this.update(id, { zIndex: prevZ });\r\n this.update(prev.id, { zIndex: myZ });\r\n }\r\n\r\n queryRect(rect: Bounds): CanvasElement[] {\r\n const ids = this.spatialIndex.query(rect);\r\n const elements: CanvasElement[] = [];\r\n for (const id of ids) {\r\n const el = this.elements.get(id);\r\n if (el) elements.push(el);\r\n }\r\n return elements.sort((a, b) => {\r\n const layerA = this.layerOrderMap.get(a.layerId) ?? 0;\r\n const layerB = this.layerOrderMap.get(b.layerId) ?? 0;\r\n if (layerA !== layerB) return layerA - layerB;\r\n return a.zIndex - b.zIndex;\r\n });\r\n }\r\n\r\n queryPoint(point: Point): CanvasElement[] {\r\n return this.queryRect({ x: point.x, y: point.y, w: 0, h: 0 });\r\n }\r\n\r\n on<K extends keyof ElementStoreEvents>(\r\n event: K,\r\n listener: (data: ElementStoreEvents[K]) => void,\r\n ): () => void {\r\n return this.bus.on(event, listener);\r\n }\r\n\r\n onChange(listener: () => void): () => void {\r\n const unsubs = [\r\n this.bus.on('add', listener),\r\n this.bus.on('remove', listener),\r\n this.bus.on('update', listener),\r\n this.bus.on('clear', listener),\r\n ];\r\n return () => unsubs.forEach((fn) => fn());\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\n\r\nexport function withRotation(\r\n ctx: CanvasRenderingContext2D,\r\n el: { rotation?: number },\r\n center: Point,\r\n draw: () => void,\r\n): void {\r\n const angle = el.rotation ?? 0;\r\n if (angle === 0) {\r\n draw();\r\n return;\r\n }\r\n ctx.save();\r\n ctx.translate(center.x, center.y);\r\n ctx.rotate(angle);\r\n ctx.translate(-center.x, -center.y);\r\n draw();\r\n ctx.restore();\r\n}\r\n","import type { StrokeElement } from '../types';\r\nimport { getStrokeRenderData } from '../stroke-cache';\r\n\r\nexport function renderStroke(ctx: CanvasRenderingContext2D, stroke: StrokeElement): void {\r\n if (stroke.points.length < 2) return;\r\n\r\n ctx.save();\r\n if (stroke.blendMode) ctx.globalCompositeOperation = stroke.blendMode;\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 data = getStrokeRenderData(stroke);\r\n if (data.buckets) {\r\n for (const bucket of data.buckets) {\r\n ctx.lineWidth = bucket.width;\r\n ctx.stroke(bucket.path);\r\n }\r\n } else {\r\n for (let i = 0; i < data.segments.length; i++) {\r\n const seg = data.segments[i];\r\n const w = data.widths[i];\r\n if (!seg || w === undefined) continue;\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\r\n ctx.restore();\r\n}\r\n","import type { Point, Size } from '../core/types';\r\nimport type { ShapeElement } from './types';\r\n\r\n/** Inverse of lineEndpoints: two endpoints → a line shape's bbox + flip. */\r\nexport function lineFromEndpoints(a: Point, b: Point): { position: Point; size: Size; flip: boolean } {\r\n return {\r\n position: { x: Math.min(a.x, b.x), y: Math.min(a.y, b.y) },\r\n size: { w: Math.abs(b.x - a.x), h: Math.abs(b.y - a.y) },\r\n flip: (b.x > a.x) !== (b.y > a.y),\r\n };\r\n}\r\n\r\n/** The two segment endpoints of a 'line' shape, from its bbox + flip. */\r\nexport function lineEndpoints(shape: ShapeElement): [Point, Point] {\r\n const { x, y } = shape.position;\r\n const { w, h } = shape.size;\r\n return shape.flip\r\n ? [\r\n { x, y: y + h },\r\n { x: x + w, y },\r\n ]\r\n : [\r\n { x, y },\r\n { x: x + w, y: y + h },\r\n ];\r\n}\r\n","import type { ShapeElement } from '../types';\r\nimport { lineEndpoints } from '../shape-geometry';\r\n\r\nexport function renderShape(ctx: CanvasRenderingContext2D, shape: ShapeElement): void {\r\n ctx.save();\r\n\r\n if (shape.fillColor !== 'none' && shape.shape !== 'line') {\r\n ctx.fillStyle = shape.fillColor;\r\n fillShapePath(ctx, shape);\r\n }\r\n\r\n if (shape.strokeWidth > 0) {\r\n ctx.strokeStyle = shape.strokeColor;\r\n ctx.lineWidth = shape.strokeWidth;\r\n strokeShapePath(ctx, shape);\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nfunction fillShapePath(ctx: CanvasRenderingContext2D, shape: ShapeElement): void {\r\n switch (shape.shape) {\r\n case 'rectangle':\r\n ctx.fillRect(shape.position.x, shape.position.y, shape.size.w, shape.size.h);\r\n break;\r\n case 'ellipse': {\r\n const cx = shape.position.x + shape.size.w / 2;\r\n const cy = shape.position.y + shape.size.h / 2;\r\n ctx.beginPath();\r\n ctx.ellipse(cx, cy, shape.size.w / 2, shape.size.h / 2, 0, 0, Math.PI * 2);\r\n ctx.fill();\r\n break;\r\n }\r\n }\r\n}\r\n\r\nfunction strokeShapePath(ctx: CanvasRenderingContext2D, shape: ShapeElement): void {\r\n switch (shape.shape) {\r\n case 'rectangle':\r\n ctx.strokeRect(shape.position.x, shape.position.y, shape.size.w, shape.size.h);\r\n break;\r\n case 'ellipse': {\r\n const cx = shape.position.x + shape.size.w / 2;\r\n const cy = shape.position.y + shape.size.h / 2;\r\n ctx.beginPath();\r\n ctx.ellipse(cx, cy, shape.size.w / 2, shape.size.h / 2, 0, 0, Math.PI * 2);\r\n ctx.stroke();\r\n break;\r\n }\r\n case 'line': {\r\n const [a, b] = lineEndpoints(shape);\r\n ctx.lineCap = 'round';\r\n ctx.beginPath();\r\n ctx.moveTo(a.x, a.y);\r\n ctx.lineTo(b.x, b.y);\r\n ctx.stroke();\r\n break;\r\n }\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { ArrowElement } from './types';\r\nimport { getArrowControlPoint, getArrowTangentAngle } from './arrow-geometry';\r\n\r\nexport interface ArrowRenderGeometry {\r\n controlPoint: Point | null;\r\n tangentStart: number;\r\n tangentEnd: number;\r\n}\r\n\r\n// Intrinsic geometry only (from/to/bend). Binding-resolved endpoints are deliberately\r\n// NOT cached: bound targets can move without the arrow object being replaced.\r\nconst cache = new WeakMap<ArrowElement, ArrowRenderGeometry>();\r\n\r\nexport function getArrowRenderGeometry(arrow: ArrowElement): ArrowRenderGeometry {\r\n const hit = cache.get(arrow);\r\n if (hit) return hit;\r\n const geometry: ArrowRenderGeometry = {\r\n controlPoint:\r\n arrow.bend !== 0\r\n ? (arrow.cachedControlPoint ?? getArrowControlPoint(arrow.from, arrow.to, arrow.bend))\r\n : null,\r\n tangentStart: getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 0),\r\n tangentEnd: getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 1),\r\n };\r\n cache.set(arrow, geometry);\r\n return geometry;\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport type { ArrowElement, CanvasElement } from './types';\r\nimport type { ElementStore } from './element-store';\r\nimport { getArrowTangentAngle } from './arrow-geometry';\r\nimport { getElementBounds } from './element-bounds';\r\n\r\nconst BINDABLE_TYPES = new Set(['note', 'text', 'image', 'html', 'shape']);\r\n\r\nexport function isBindable(element: CanvasElement): boolean {\r\n return BINDABLE_TYPES.has(element.type);\r\n}\r\n\r\nexport function getElementCenter(element: CanvasElement): Point {\r\n if (!('size' in element)) {\r\n throw new Error(`getElementCenter: element type \"${element.type}\" has no size`);\r\n }\r\n return {\r\n x: element.position.x + element.size.w / 2,\r\n y: element.position.y + element.size.h / 2,\r\n };\r\n}\r\n\r\nexport function getEdgeIntersection(bounds: Bounds, outsidePoint: Point): Point {\r\n const cx = bounds.x + bounds.w / 2;\r\n const cy = bounds.y + bounds.h / 2;\r\n const dx = outsidePoint.x - cx;\r\n const dy = outsidePoint.y - cy;\r\n\r\n if (dx === 0 && dy === 0) return { x: cx, y: cy };\r\n\r\n const halfW = bounds.w / 2;\r\n const halfH = bounds.h / 2;\r\n\r\n const scaleX = dx !== 0 ? halfW / Math.abs(dx) : Infinity;\r\n const scaleY = dy !== 0 ? halfH / Math.abs(dy) : Infinity;\r\n const scale = Math.min(scaleX, scaleY);\r\n\r\n return {\r\n x: cx + dx * scale,\r\n y: cy + dy * scale,\r\n };\r\n}\r\n\r\nexport function findBindTarget(\r\n point: Point,\r\n store: ElementStore,\r\n threshold: number,\r\n excludeId?: string,\r\n filter?: (el: CanvasElement) => boolean,\r\n): CanvasElement | null {\r\n let closest: CanvasElement | null = null;\r\n let closestDist = Infinity;\r\n\r\n for (const el of store.getAll()) {\r\n if (!isBindable(el)) continue;\r\n if (excludeId && el.id === excludeId) continue;\r\n if (filter && !filter(el)) continue;\r\n\r\n const bounds = getElementBounds(el);\r\n if (!bounds) continue;\r\n\r\n const dist = distToBounds(point, bounds);\r\n if (dist <= threshold && dist < closestDist) {\r\n closest = el;\r\n closestDist = dist;\r\n }\r\n }\r\n\r\n return closest;\r\n}\r\n\r\nfunction distToBounds(point: Point, bounds: Bounds): number {\r\n const clampedX = Math.max(bounds.x, Math.min(point.x, bounds.x + bounds.w));\r\n const clampedY = Math.max(bounds.y, Math.min(point.y, bounds.y + bounds.h));\r\n return Math.hypot(point.x - clampedX, point.y - clampedY);\r\n}\r\n\r\nexport function findBoundArrows(elementId: string, store: ElementStore): ArrowElement[] {\r\n return store\r\n .getElementsByType('arrow')\r\n .filter((a) => a.fromBinding?.elementId === elementId || a.toBinding?.elementId === elementId);\r\n}\r\n\r\n/** Re-anchor every arrow bound to any of the moved non-arrow elements (each updated once). */\r\nexport function updateArrowsBoundToElements(movedIds: Iterable<string>, store: ElementStore): void {\r\n const movedNonArrowIds = new Set<string>();\r\n for (const id of movedIds) {\r\n const el = store.getById(id);\r\n if (el && el.type !== 'arrow') movedNonArrowIds.add(id);\r\n }\r\n if (movedNonArrowIds.size === 0) return;\r\n const updated = new Set<string>();\r\n for (const id of movedNonArrowIds) {\r\n for (const ba of findBoundArrows(id, store)) {\r\n if (updated.has(ba.id)) continue;\r\n updated.add(ba.id);\r\n const updates = updateBoundArrow(ba, store);\r\n if (updates) store.update(ba.id, updates);\r\n }\r\n }\r\n}\r\n\r\nexport function updateBoundArrow(\r\n arrow: ArrowElement,\r\n store: ElementStore,\r\n): Partial<ArrowElement> | null {\r\n if (!arrow.fromBinding && !arrow.toBinding) return null;\r\n\r\n const updates: Partial<ArrowElement> = {};\r\n\r\n if (arrow.fromBinding) {\r\n const el = store.getById(arrow.fromBinding.elementId);\r\n if (el) {\r\n const center = getElementCenter(el);\r\n updates.from = center;\r\n updates.position = center;\r\n }\r\n }\r\n\r\n if (arrow.toBinding) {\r\n const el = store.getById(arrow.toBinding.elementId);\r\n if (el) {\r\n updates.to = getElementCenter(el);\r\n }\r\n }\r\n\r\n return Object.keys(updates).length > 0 ? updates : null;\r\n}\r\n\r\nexport function clearStaleBindings(\r\n arrow: ArrowElement,\r\n store: ElementStore,\r\n): Partial<ArrowElement> | null {\r\n const updates: Partial<ArrowElement> = {};\r\n let hasUpdates = false;\r\n\r\n if (arrow.fromBinding && !store.getById(arrow.fromBinding.elementId)) {\r\n updates.fromBinding = undefined;\r\n hasUpdates = true;\r\n }\r\n\r\n if (arrow.toBinding && !store.getById(arrow.toBinding.elementId)) {\r\n updates.toBinding = undefined;\r\n hasUpdates = true;\r\n }\r\n\r\n return hasUpdates ? updates : null;\r\n}\r\n\r\nexport function unbindArrow(arrow: ArrowElement, store: ElementStore): Partial<ArrowElement> {\r\n const updates: Partial<ArrowElement> = {};\r\n\r\n if (arrow.fromBinding) {\r\n const el = store.getById(arrow.fromBinding.elementId);\r\n const bounds = el ? getElementBounds(el) : null;\r\n if (bounds) {\r\n const angle = getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 0);\r\n const rayTarget = {\r\n x: arrow.from.x + Math.cos(angle) * 1000,\r\n y: arrow.from.y + Math.sin(angle) * 1000,\r\n };\r\n const edge = getEdgeIntersection(bounds, rayTarget);\r\n updates.from = edge;\r\n updates.position = edge;\r\n }\r\n updates.fromBinding = undefined;\r\n }\r\n\r\n if (arrow.toBinding) {\r\n const el = store.getById(arrow.toBinding.elementId);\r\n const bounds = el ? getElementBounds(el) : null;\r\n if (bounds) {\r\n const angle = getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 1);\r\n // Reverse tangent direction — tangent at t=1 points away from curve body\r\n const rayTarget = {\r\n x: arrow.to.x - Math.cos(angle) * 1000,\r\n y: arrow.to.y - Math.sin(angle) * 1000,\r\n };\r\n updates.to = getEdgeIntersection(bounds, rayTarget);\r\n }\r\n updates.toBinding = undefined;\r\n }\r\n\r\n return updates;\r\n}\r\n","import type { ArrowElement } from '../types';\r\nimport type { ElementStore } from '../element-store';\r\nimport { getArrowRenderGeometry } from '../arrow-render-cache';\r\nimport { getArrowMidpoint } from '../arrow-geometry';\r\nimport { getEdgeIntersection } from '../arrow-binding';\r\nimport { getElementBounds } from '../element-bounds';\r\n\r\nconst ARROWHEAD_LENGTH = 12;\r\nconst ARROWHEAD_ANGLE = Math.PI / 6;\r\nconst ARROW_LABEL_FONT_SIZE = 14;\r\n\r\nexport function renderArrow(\r\n ctx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n store: ElementStore | null,\r\n labelEditingId: string | null,\r\n): void {\r\n const geometry = getArrowRenderGeometry(arrow);\r\n const { visualFrom, visualTo } = getVisualEndpoints(arrow, geometry, store);\r\n\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 if (arrow.fromBinding || arrow.toBinding) {\r\n ctx.setLineDash([8, 4]);\r\n }\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(visualFrom.x, visualFrom.y);\r\n\r\n if (arrow.bend !== 0) {\r\n const cp = geometry.controlPoint;\r\n if (cp) {\r\n ctx.quadraticCurveTo(cp.x, cp.y, visualTo.x, visualTo.y);\r\n }\r\n } else {\r\n ctx.lineTo(visualTo.x, visualTo.y);\r\n }\r\n ctx.stroke();\r\n\r\n renderArrowhead(ctx, arrow, visualTo, geometry.tangentEnd);\r\n ctx.restore();\r\n renderArrowLabel(ctx, arrow, labelEditingId);\r\n}\r\n\r\nfunction renderArrowLabel(\r\n ctx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n labelEditingId: string | null,\r\n): void {\r\n if (!arrow.label || arrow.label.length === 0) return;\r\n if (arrow.id === labelEditingId) return;\r\n const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);\r\n ctx.save();\r\n ctx.font = `${ARROW_LABEL_FONT_SIZE}px system-ui, sans-serif`;\r\n const metrics = ctx.measureText(arrow.label);\r\n const padX = 6;\r\n const padY = 4;\r\n const w = metrics.width + padX * 2;\r\n const h = ARROW_LABEL_FONT_SIZE + padY * 2;\r\n ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';\r\n ctx.beginPath();\r\n ctx.roundRect(mid.x - w / 2, mid.y - h / 2, w, h, 4);\r\n ctx.fill();\r\n ctx.fillStyle = '#1a1a1a';\r\n ctx.textAlign = 'center';\r\n ctx.textBaseline = 'middle';\r\n ctx.fillText(arrow.label, mid.x, mid.y);\r\n ctx.restore();\r\n}\r\n\r\nfunction renderArrowhead(\r\n ctx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n tip: { x: number; y: number },\r\n angle: number,\r\n): void {\r\n ctx.beginPath();\r\n ctx.moveTo(tip.x, tip.y);\r\n ctx.lineTo(\r\n tip.x - ARROWHEAD_LENGTH * Math.cos(angle - ARROWHEAD_ANGLE),\r\n tip.y - ARROWHEAD_LENGTH * Math.sin(angle - ARROWHEAD_ANGLE),\r\n );\r\n ctx.lineTo(\r\n tip.x - ARROWHEAD_LENGTH * Math.cos(angle + ARROWHEAD_ANGLE),\r\n tip.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\nfunction getVisualEndpoints(\r\n arrow: ArrowElement,\r\n geometry: ReturnType<typeof getArrowRenderGeometry>,\r\n store: ElementStore | null,\r\n): {\r\n visualFrom: { x: number; y: number };\r\n visualTo: { x: number; y: number };\r\n} {\r\n let visualFrom = arrow.from;\r\n let visualTo = arrow.to;\r\n\r\n if (!store) return { visualFrom, visualTo };\r\n\r\n if (arrow.fromBinding) {\r\n const el = store.getById(arrow.fromBinding.elementId);\r\n if (el) {\r\n const bounds = getElementBounds(el);\r\n if (bounds) {\r\n const tangentAngle = geometry.tangentStart;\r\n const rayTarget = {\r\n x: arrow.from.x + Math.cos(tangentAngle) * 1000,\r\n y: arrow.from.y + Math.sin(tangentAngle) * 1000,\r\n };\r\n visualFrom = getEdgeIntersection(bounds, rayTarget);\r\n }\r\n }\r\n }\r\n\r\n if (arrow.toBinding) {\r\n const el = store.getById(arrow.toBinding.elementId);\r\n if (el) {\r\n const bounds = getElementBounds(el);\r\n if (bounds) {\r\n const tangentAngle = geometry.tangentEnd;\r\n // Reverse tangent — at t=1 tangent points away from curve body,\r\n // but we need the ray from center back toward the curve\r\n const rayTarget = {\r\n x: arrow.to.x - Math.cos(tangentAngle) * 1000,\r\n y: arrow.to.y - Math.sin(tangentAngle) * 1000,\r\n };\r\n visualTo = getEdgeIntersection(bounds, rayTarget);\r\n }\r\n }\r\n }\r\n\r\n return { visualFrom, visualTo };\r\n}\r\n","import type { ImageElement } from '../types';\r\n\r\nexport function renderImage(\r\n ctx: CanvasRenderingContext2D,\r\n image: ImageElement,\r\n imageCache: Map<string, ImageBitmap | HTMLImageElement | 'failed'>,\r\n onImageLoad: (() => void) | null,\r\n onImageError: ((src: string, cause?: unknown) => void) | null,\r\n): void {\r\n if (imageCache.get(image.src) === 'failed') {\r\n renderImagePlaceholder(ctx, image);\r\n return;\r\n }\r\n const img = getImage(image.src, imageCache, onImageLoad, onImageError);\r\n if (!img) return;\r\n ctx.drawImage(\r\n img as CanvasImageSource,\r\n image.position.x,\r\n image.position.y,\r\n image.size.w,\r\n image.size.h,\r\n );\r\n}\r\n\r\nfunction renderImagePlaceholder(ctx: CanvasRenderingContext2D, image: ImageElement): void {\r\n const { x, y } = image.position;\r\n const { w, h } = image.size;\r\n ctx.save();\r\n ctx.fillStyle = '#eeeeee';\r\n ctx.fillRect(x, y, w, h);\r\n ctx.strokeStyle = '#bdbdbd';\r\n ctx.lineWidth = 1;\r\n ctx.strokeRect(x, y, w, h);\r\n\r\n const glyph = Math.min(24, w / 2, h / 2);\r\n const cx = x + w / 2;\r\n const cy = y + h / 2;\r\n ctx.strokeStyle = '#9e9e9e';\r\n ctx.lineWidth = 2;\r\n ctx.beginPath();\r\n ctx.arc(cx, cy, glyph / 2, 0, Math.PI * 2);\r\n ctx.moveTo(cx - glyph / 2, cy + glyph / 2);\r\n ctx.lineTo(cx + glyph / 2, cy - glyph / 2);\r\n ctx.stroke();\r\n ctx.restore();\r\n}\r\n\r\nfunction getImage(\r\n src: string,\r\n imageCache: Map<string, ImageBitmap | HTMLImageElement | 'failed'>,\r\n onImageLoad: (() => void) | null,\r\n onImageError: ((src: string, cause?: unknown) => void) | null,\r\n): ImageBitmap | HTMLImageElement | null {\r\n const cached = imageCache.get(src);\r\n if (cached) {\r\n if (cached === 'failed') return null;\r\n if (cached instanceof HTMLImageElement) return cached.complete ? cached : null;\r\n return cached;\r\n }\r\n\r\n const img = new Image();\r\n img.src = src;\r\n imageCache.set(src, img);\r\n img.onload = () => {\r\n onImageLoad?.();\r\n // Decode from already-loaded image in memory, not a re-fetch\r\n if (typeof createImageBitmap !== 'undefined') {\r\n createImageBitmap(img)\r\n .then((bitmap) => {\r\n imageCache.set(src, bitmap);\r\n onImageLoad?.();\r\n })\r\n .catch(() => {\r\n /* keep HTMLImageElement fallback — handles CORS rejection */\r\n });\r\n }\r\n };\r\n img.onerror = (event) => {\r\n // failed srcs stay failed for the session; pointing the element at a new src loads fresh\r\n imageCache.set(src, 'failed');\r\n onImageError?.(src, event);\r\n onImageLoad?.();\r\n };\r\n return null;\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { HexOrientation } from './types';\r\n\r\ninterface HexCoord {\r\n col: number;\r\n row: number;\r\n}\r\n\r\nfunction offsetToCube(\r\n col: number,\r\n row: number,\r\n orientation: HexOrientation,\r\n): { q: number; r: number } {\r\n if (orientation === 'pointy') {\r\n return { q: col - (row - (row & 1)) / 2, r: row };\r\n }\r\n return { q: col, r: row - (col - (col & 1)) / 2 };\r\n}\r\n\r\nfunction cubeToOffset(q: number, r: number, orientation: HexOrientation): HexCoord {\r\n if (orientation === 'pointy') {\r\n return { col: q + (r - (r & 1)) / 2, row: r };\r\n }\r\n return { col: q, row: r + (q - (q & 1)) / 2 };\r\n}\r\n\r\nfunction offsetToPixel(\r\n col: number,\r\n row: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point {\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * cellSize;\r\n const rowH = 1.5 * cellSize;\r\n const offsetX = row % 2 !== 0 ? hexW / 2 : 0;\r\n return { x: col * hexW + offsetX, y: row * rowH };\r\n }\r\n const hexH = Math.sqrt(3) * cellSize;\r\n const colW = 1.5 * cellSize;\r\n const offsetY = col % 2 !== 0 ? hexH / 2 : 0;\r\n return { x: col * colW, y: row * hexH + offsetY };\r\n}\r\n\r\nfunction pixelToOffset(\r\n x: number,\r\n y: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): HexCoord {\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * cellSize;\r\n const rowH = 1.5 * cellSize;\r\n const row = Math.round(y / rowH);\r\n const offsetX = row % 2 !== 0 ? hexW / 2 : 0;\r\n return { col: Math.round((x - offsetX) / hexW), row };\r\n }\r\n const hexH = Math.sqrt(3) * cellSize;\r\n const colW = 1.5 * cellSize;\r\n const col = Math.round(x / colW);\r\n const offsetY = col % 2 !== 0 ? hexH / 2 : 0;\r\n return { col, row: Math.round((y - offsetY) / hexH) };\r\n}\r\n\r\nfunction enumerateHexRing(\r\n centerQ: number,\r\n centerR: number,\r\n n: number,\r\n orientation: HexOrientation,\r\n cellSize: number,\r\n): Point[] {\r\n const cells: Point[] = [];\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n const absQ = centerQ + dq;\r\n const absR = centerR + dr;\r\n const off = cubeToOffset(absQ, absR, orientation);\r\n cells.push(offsetToPixel(off.col, off.row, cellSize, orientation));\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function getHexDistance(\r\n a: Point,\r\n b: Point,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): number {\r\n const offA = pixelToOffset(a.x, a.y, cellSize, orientation);\r\n const offB = pixelToOffset(b.x, b.y, cellSize, orientation);\r\n const cubeA = offsetToCube(offA.col, offA.row, orientation);\r\n const cubeB = offsetToCube(offB.col, offB.row, orientation);\r\n const dq = cubeA.q - cubeB.q;\r\n const dr = cubeA.r - cubeB.r;\r\n const ds = -dq - dr;\r\n return Math.max(Math.abs(dq), Math.abs(dr), Math.abs(ds));\r\n}\r\n\r\nexport function getHexCellsInRadius(\r\n center: Point,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n if (n <= 0) {\r\n return [offsetToPixel(off.col, off.row, cellSize, orientation)];\r\n }\r\n return enumerateHexRing(cube.q, cube.r, n, orientation, cellSize);\r\n}\r\n\r\nexport function getHexCellsInCone(\r\n center: Point,\r\n angle: number,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n const centerPixel = offsetToPixel(off.col, off.row, cellSize, orientation);\r\n\r\n if (n <= 0) return [centerPixel];\r\n\r\n const vertexOffset = orientation === 'pointy' ? Math.PI / 6 : 0;\r\n const step = Math.PI / 3;\r\n const snappedAngle = Math.round((angle - vertexOffset) / step) * step + vertexOffset;\r\n\r\n const halfAngle = Math.PI / 6 + 1e-6;\r\n const cells: Point[] = [centerPixel];\r\n\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n if (dq === 0 && dr === 0) continue;\r\n const absQ = cube.q + dq;\r\n const absR = cube.r + dr;\r\n const pixel = offsetToPixel(\r\n cubeToOffset(absQ, absR, orientation).col,\r\n cubeToOffset(absQ, absR, orientation).row,\r\n cellSize,\r\n orientation,\r\n );\r\n\r\n const dx = pixel.x - centerPixel.x;\r\n const dy = pixel.y - centerPixel.y;\r\n let diff = Math.atan2(dy, dx) - snappedAngle;\r\n if (diff > Math.PI) diff -= 2 * Math.PI;\r\n if (diff < -Math.PI) diff += 2 * Math.PI;\r\n\r\n if (Math.abs(diff) <= halfAngle) {\r\n cells.push(pixel);\r\n }\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function getHexCellsInLine(\r\n center: Point,\r\n angle: number,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n const centerPixel = offsetToPixel(off.col, off.row, cellSize, orientation);\r\n\r\n if (n <= 0) return [centerPixel];\r\n\r\n const vertexOffset = orientation === 'pointy' ? Math.PI / 6 : 0;\r\n const step = Math.PI / 3;\r\n const snappedAngle = Math.round((angle - vertexOffset) / step) * step + vertexOffset;\r\n\r\n const cos = Math.cos(snappedAngle);\r\n const sin = Math.sin(snappedAngle);\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const lineLength = n * snapUnit;\r\n const halfWidth = snapUnit * 0.5 + 1e-6;\r\n const cells: Point[] = [];\r\n\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n const absQ = cube.q + dq;\r\n const absR = cube.r + dr;\r\n const pixel = offsetToPixel(\r\n cubeToOffset(absQ, absR, orientation).col,\r\n cubeToOffset(absQ, absR, orientation).row,\r\n cellSize,\r\n orientation,\r\n );\r\n\r\n const dx = pixel.x - centerPixel.x;\r\n const dy = pixel.y - centerPixel.y;\r\n const along = dx * cos + dy * sin;\r\n const perp = Math.abs(-dx * sin + dy * cos);\r\n\r\n if (along >= -snapUnit * 0.1 && along <= lineLength + snapUnit * 0.1 && perp <= halfWidth) {\r\n cells.push(pixel);\r\n }\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function getHexCellsInSquare(\r\n center: Point,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n const centerPixel = offsetToPixel(off.col, off.row, cellSize, orientation);\r\n\r\n if (n <= 0) return [centerPixel];\r\n\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const halfSide = (n * snapUnit) / 2;\r\n const cells: Point[] = [];\r\n\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n const absQ = cube.q + dq;\r\n const absR = cube.r + dr;\r\n const pixel = offsetToPixel(\r\n cubeToOffset(absQ, absR, orientation).col,\r\n cubeToOffset(absQ, absR, orientation).row,\r\n cellSize,\r\n orientation,\r\n );\r\n\r\n if (\r\n Math.abs(pixel.x - centerPixel.x) <= halfSide &&\r\n Math.abs(pixel.y - centerPixel.y) <= halfSide\r\n ) {\r\n cells.push(pixel);\r\n }\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function drawHexPath(\r\n ctx: CanvasRenderingContext2D,\r\n cx: number,\r\n cy: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): void {\r\n const angleOffset = orientation === 'pointy' ? Math.PI / 6 : 0;\r\n ctx.moveTo(cx + cellSize * Math.cos(angleOffset), cy + cellSize * Math.sin(angleOffset));\r\n for (let i = 1; i < 6; i++) {\r\n const a = angleOffset + (Math.PI / 3) * i;\r\n ctx.lineTo(cx + cellSize * Math.cos(a), cy + cellSize * Math.sin(a));\r\n }\r\n ctx.closePath();\r\n}\r\n","import type { TemplateElement, HexOrientation } from '../types';\r\nimport type { ElementStore } from '../element-store';\r\nimport {\r\n getHexCellsInRadius,\r\n getHexCellsInCone,\r\n getHexCellsInLine,\r\n getHexCellsInSquare,\r\n drawHexPath,\r\n} from '../hex-fill';\r\n\r\nexport function renderTemplate(\r\n ctx: CanvasRenderingContext2D,\r\n template: TemplateElement,\r\n store: ElementStore | null,\r\n): void {\r\n const grid = store?.getElementsByType('grid')[0];\r\n if (grid && grid.gridType === 'hex') {\r\n renderHexTemplate(ctx, template, grid.cellSize, grid.hexOrientation);\r\n return;\r\n }\r\n\r\n renderGeometricTemplate(ctx, template);\r\n}\r\n\r\nfunction renderGeometricTemplate(ctx: CanvasRenderingContext2D, template: TemplateElement): void {\r\n const { x: cx, y: cy } = template.position;\r\n const r = template.radius;\r\n\r\n ctx.save();\r\n ctx.globalAlpha = template.opacity;\r\n ctx.fillStyle = template.fillColor;\r\n ctx.strokeStyle = template.strokeColor;\r\n ctx.lineWidth = template.strokeWidth;\r\n\r\n switch (template.templateShape) {\r\n case 'circle':\r\n ctx.beginPath();\r\n ctx.arc(cx, cy, r, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.stroke();\r\n if (template.radiusFeet != null && template.radiusFeet > 0) {\r\n renderRadiusMarker(ctx, cx, cy, r, template.radiusFeet);\r\n }\r\n break;\r\n\r\n case 'square':\r\n ctx.fillRect(cx - r / 2, cy - r / 2, r, r);\r\n ctx.strokeRect(cx - r / 2, cy - r / 2, r, r);\r\n break;\r\n\r\n case 'cone': {\r\n const halfAngle = Math.atan(0.5);\r\n ctx.beginPath();\r\n ctx.moveTo(cx, cy);\r\n ctx.arc(cx, cy, r, template.angle - halfAngle, template.angle + halfAngle);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n\r\n case 'line': {\r\n const halfW = r / 12;\r\n const cos = Math.cos(template.angle);\r\n const sin = Math.sin(template.angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(cx + perpX, cy + perpY);\r\n ctx.lineTo(cx + r * cos + perpX, cy + r * sin + perpY);\r\n ctx.lineTo(cx + r * cos - perpX, cy + r * sin - perpY);\r\n ctx.lineTo(cx - perpX, cy - perpY);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nfunction renderHexTemplate(\r\n ctx: CanvasRenderingContext2D,\r\n template: TemplateElement,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): void {\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const radiusCells = template.radius / snapUnit;\r\n const center = template.position;\r\n\r\n let cells: { x: number; y: number }[];\r\n switch (template.templateShape) {\r\n case 'circle':\r\n cells = getHexCellsInRadius(center, radiusCells, cellSize, orientation);\r\n break;\r\n case 'cone':\r\n cells = getHexCellsInCone(center, template.angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'line':\r\n cells = getHexCellsInLine(center, template.angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'square':\r\n cells = getHexCellsInSquare(center, radiusCells, cellSize, orientation);\r\n break;\r\n }\r\n\r\n ctx.save();\r\n ctx.globalAlpha = template.opacity;\r\n\r\n ctx.beginPath();\r\n for (const cell of cells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.fillStyle = template.fillColor;\r\n ctx.fill();\r\n\r\n ctx.beginPath();\r\n for (const cell of cells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.strokeStyle = template.strokeColor;\r\n ctx.lineWidth = template.strokeWidth;\r\n ctx.stroke();\r\n\r\n {\r\n ctx.globalAlpha = Math.min(template.opacity + 0.1, 1);\r\n ctx.beginPath();\r\n drawHexPath(ctx, center.x, center.y, cellSize, orientation);\r\n ctx.fillStyle = template.strokeColor;\r\n ctx.fill();\r\n ctx.strokeStyle = template.strokeColor;\r\n ctx.lineWidth = template.strokeWidth;\r\n ctx.stroke();\r\n }\r\n\r\n if (\r\n template.templateShape === 'circle' &&\r\n template.radiusFeet != null &&\r\n template.radiusFeet > 0\r\n ) {\r\n const r = template.radius;\r\n renderRadiusMarker(ctx, center.x, center.y, r, template.radiusFeet);\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nfunction renderRadiusMarker(\r\n ctx: CanvasRenderingContext2D,\r\n cx: number,\r\n cy: number,\r\n r: number,\r\n feet: number,\r\n): void {\r\n const markerColor = ctx.strokeStyle as string;\r\n\r\n ctx.save();\r\n ctx.globalAlpha = 1;\r\n\r\n ctx.beginPath();\r\n ctx.setLineDash([4, 4]);\r\n ctx.strokeStyle = markerColor;\r\n ctx.lineWidth = 1.5;\r\n ctx.moveTo(cx, cy);\r\n ctx.lineTo(cx + r, cy);\r\n ctx.stroke();\r\n ctx.setLineDash([]);\r\n\r\n const label = `${Math.round(feet)} ft`;\r\n const fontSize = Math.max(10, Math.min(14, r * 0.15));\r\n ctx.font = `bold ${fontSize}px system-ui, sans-serif`;\r\n ctx.textAlign = 'center';\r\n ctx.textBaseline = 'bottom';\r\n const textX = cx + r / 2;\r\n const textY = cy - 4;\r\n\r\n const metrics = ctx.measureText(label);\r\n const padX = 4;\r\n const padY = 2;\r\n const textW = metrics.width + padX * 2;\r\n const textH = fontSize + padY * 2;\r\n\r\n ctx.fillStyle = 'rgba(255, 255, 255, 0.85)';\r\n ctx.beginPath();\r\n ctx.roundRect(textX - textW / 2, textY - textH, textW, textH, 3);\r\n ctx.fill();\r\n\r\n ctx.fillStyle = markerColor;\r\n ctx.fillText(label, textX, textY - padY);\r\n\r\n ctx.restore();\r\n}\r\n","import type { HexOrientation } from './types';\r\n\r\nexport interface VisibleBounds {\r\n minX: number;\r\n minY: number;\r\n maxX: number;\r\n maxY: number;\r\n}\r\n\r\nexport interface SquareGridLines {\r\n verticals: number[];\r\n horizontals: number[];\r\n}\r\n\r\nexport function getSquareGridLines(bounds: VisibleBounds, cellSize: number): SquareGridLines {\r\n if (cellSize <= 0) return { verticals: [], horizontals: [] };\r\n\r\n const verticals: number[] = [];\r\n const startX = Math.floor(bounds.minX / cellSize) * cellSize;\r\n const endX = Math.ceil(bounds.maxX / cellSize) * cellSize;\r\n for (let x = startX; x <= endX; x += cellSize) {\r\n verticals.push(x);\r\n }\r\n\r\n const horizontals: number[] = [];\r\n const startY = Math.floor(bounds.minY / cellSize) * cellSize;\r\n const endY = Math.ceil(bounds.maxY / cellSize) * cellSize;\r\n for (let y = startY; y <= endY; y += cellSize) {\r\n horizontals.push(y);\r\n }\r\n\r\n return { verticals, horizontals };\r\n}\r\n\r\nexport interface HexVertex {\r\n x: number;\r\n y: number;\r\n}\r\n\r\nexport function getHexVertices(\r\n cx: number,\r\n cy: number,\r\n circumradius: number,\r\n orientation: HexOrientation,\r\n): HexVertex[] {\r\n const vertices: HexVertex[] = [];\r\n const angleOffset = orientation === 'pointy' ? -Math.PI / 2 : 0;\r\n for (let i = 0; i < 6; i++) {\r\n const angle = (Math.PI / 3) * i + angleOffset;\r\n vertices.push({\r\n x: cx + circumradius * Math.cos(angle),\r\n y: cy + circumradius * Math.sin(angle),\r\n });\r\n }\r\n return vertices;\r\n}\r\n\r\nexport function getHexCenters(\r\n bounds: VisibleBounds,\r\n circumradius: number,\r\n orientation: HexOrientation,\r\n): HexVertex[] {\r\n if (circumradius <= 0) return [];\r\n\r\n const centers: HexVertex[] = [];\r\n\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * circumradius;\r\n const hexH = 2 * circumradius;\r\n const rowH = hexH * 0.75;\r\n\r\n const startRow = Math.floor((bounds.minY - circumradius) / rowH);\r\n const endRow = Math.ceil((bounds.maxY + circumradius) / rowH);\r\n const startCol = Math.floor((bounds.minX - hexW) / hexW);\r\n const endCol = Math.ceil((bounds.maxX + hexW) / hexW);\r\n\r\n for (let row = startRow; row <= endRow; row++) {\r\n const offsetX = row % 2 !== 0 ? hexW / 2 : 0;\r\n for (let col = startCol; col <= endCol; col++) {\r\n centers.push({\r\n x: col * hexW + offsetX,\r\n y: row * rowH,\r\n });\r\n }\r\n }\r\n } else {\r\n const hexW = 2 * circumradius;\r\n const hexH = Math.sqrt(3) * circumradius;\r\n const colW = hexW * 0.75;\r\n\r\n const startCol = Math.floor((bounds.minX - circumradius) / colW);\r\n const endCol = Math.ceil((bounds.maxX + circumradius) / colW);\r\n const startRow = Math.floor((bounds.minY - hexH) / hexH);\r\n const endRow = Math.ceil((bounds.maxY + hexH) / hexH);\r\n\r\n for (let col = startCol; col <= endCol; col++) {\r\n const offsetY = col % 2 !== 0 ? hexH / 2 : 0;\r\n for (let row = startRow; row <= endRow; row++) {\r\n centers.push({\r\n x: col * colW,\r\n y: row * hexH + offsetY,\r\n });\r\n }\r\n }\r\n }\r\n\r\n return centers;\r\n}\r\n\r\nexport function renderSquareGrid(\r\n ctx: CanvasRenderingContext2D,\r\n bounds: VisibleBounds,\r\n cellSize: number,\r\n strokeColor: string,\r\n strokeWidth: number,\r\n opacity: number,\r\n): void {\r\n if (cellSize <= 0) return;\r\n\r\n const { verticals, horizontals } = getSquareGridLines(bounds, cellSize);\r\n\r\n ctx.save();\r\n ctx.strokeStyle = strokeColor;\r\n ctx.lineWidth = strokeWidth;\r\n ctx.globalAlpha = opacity;\r\n ctx.beginPath();\r\n\r\n for (const x of verticals) {\r\n ctx.moveTo(x, bounds.minY);\r\n ctx.lineTo(x, bounds.maxY);\r\n }\r\n for (const y of horizontals) {\r\n ctx.moveTo(bounds.minX, y);\r\n ctx.lineTo(bounds.maxX, y);\r\n }\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n}\r\n\r\nexport function renderHexGrid(\r\n ctx: CanvasRenderingContext2D,\r\n bounds: VisibleBounds,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n strokeColor: string,\r\n strokeWidth: number,\r\n opacity: number,\r\n): void {\r\n if (cellSize <= 0) return;\r\n\r\n // Precompute 6 vertex offsets once (12 trig calls total, not 12 per hex)\r\n const angleOffset = orientation === 'pointy' ? -Math.PI / 2 : 0;\r\n const ox0 = cellSize * Math.cos(angleOffset);\r\n const oy0 = cellSize * Math.sin(angleOffset);\r\n const ox1 = cellSize * Math.cos(Math.PI / 3 + angleOffset);\r\n const oy1 = cellSize * Math.sin(Math.PI / 3 + angleOffset);\r\n const ox2 = cellSize * Math.cos((2 * Math.PI) / 3 + angleOffset);\r\n const oy2 = cellSize * Math.sin((2 * Math.PI) / 3 + angleOffset);\r\n const ox3 = cellSize * Math.cos(Math.PI + angleOffset);\r\n const oy3 = cellSize * Math.sin(Math.PI + angleOffset);\r\n const ox4 = cellSize * Math.cos((4 * Math.PI) / 3 + angleOffset);\r\n const oy4 = cellSize * Math.sin((4 * Math.PI) / 3 + angleOffset);\r\n const ox5 = cellSize * Math.cos((5 * Math.PI) / 3 + angleOffset);\r\n const oy5 = cellSize * Math.sin((5 * Math.PI) / 3 + angleOffset);\r\n\r\n ctx.save();\r\n ctx.strokeStyle = strokeColor;\r\n ctx.lineWidth = strokeWidth;\r\n ctx.globalAlpha = opacity;\r\n ctx.beginPath();\r\n\r\n // Inline center iteration — zero allocations per hex\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * cellSize;\r\n const rowH = 1.5 * cellSize;\r\n\r\n const startRow = Math.floor((bounds.minY - cellSize) / rowH);\r\n const endRow = Math.ceil((bounds.maxY + cellSize) / rowH);\r\n const startCol = Math.floor((bounds.minX - hexW) / hexW);\r\n const endCol = Math.ceil((bounds.maxX + hexW) / hexW);\r\n\r\n for (let row = startRow; row <= endRow; row++) {\r\n const offX = row % 2 !== 0 ? hexW / 2 : 0;\r\n for (let col = startCol; col <= endCol; col++) {\r\n const cx = col * hexW + offX;\r\n const cy = row * rowH;\r\n ctx.moveTo(cx + ox0, cy + oy0);\r\n ctx.lineTo(cx + ox1, cy + oy1);\r\n ctx.lineTo(cx + ox2, cy + oy2);\r\n ctx.lineTo(cx + ox3, cy + oy3);\r\n ctx.lineTo(cx + ox4, cy + oy4);\r\n ctx.lineTo(cx + ox5, cy + oy5);\r\n ctx.closePath();\r\n }\r\n }\r\n } else {\r\n const hexH = Math.sqrt(3) * cellSize;\r\n const colW = 1.5 * cellSize;\r\n\r\n const startCol = Math.floor((bounds.minX - cellSize) / colW);\r\n const endCol = Math.ceil((bounds.maxX + cellSize) / colW);\r\n const startRow = Math.floor((bounds.minY - hexH) / hexH);\r\n const endRow = Math.ceil((bounds.maxY + hexH) / hexH);\r\n\r\n for (let col = startCol; col <= endCol; col++) {\r\n const offY = col % 2 !== 0 ? hexH / 2 : 0;\r\n for (let row = startRow; row <= endRow; row++) {\r\n const cx = col * colW;\r\n const cy = row * hexH + offY;\r\n ctx.moveTo(cx + ox0, cy + oy0);\r\n ctx.lineTo(cx + ox1, cy + oy1);\r\n ctx.lineTo(cx + ox2, cy + oy2);\r\n ctx.lineTo(cx + ox3, cy + oy3);\r\n ctx.lineTo(cx + ox4, cy + oy4);\r\n ctx.lineTo(cx + ox5, cy + oy5);\r\n ctx.closePath();\r\n }\r\n }\r\n }\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n}\r\n\r\nexport interface HexGridTile {\r\n canvas: HTMLCanvasElement | OffscreenCanvas;\r\n tileW: number;\r\n tileH: number;\r\n}\r\n\r\nexport function createHexGridTile(\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n strokeColor: string,\r\n strokeWidth: number,\r\n opacity: number,\r\n scale: number,\r\n): HexGridTile | null {\r\n let tileW: number;\r\n let tileH: number;\r\n if (orientation === 'pointy') {\r\n tileW = Math.sqrt(3) * cellSize;\r\n tileH = 3 * cellSize;\r\n } else {\r\n tileW = 3 * cellSize;\r\n tileH = Math.sqrt(3) * cellSize;\r\n }\r\n\r\n const pxW = Math.ceil(tileW * scale);\r\n const pxH = Math.ceil(tileH * scale);\r\n if (pxW <= 0 || pxH <= 0) return null;\r\n\r\n let canvas: HTMLCanvasElement | OffscreenCanvas;\r\n if (typeof OffscreenCanvas !== 'undefined') {\r\n canvas = new OffscreenCanvas(pxW, pxH);\r\n } else if (typeof document !== 'undefined') {\r\n const el = document.createElement('canvas');\r\n el.width = pxW;\r\n el.height = pxH;\r\n canvas = el;\r\n } else {\r\n return null;\r\n }\r\n\r\n const tc = canvas.getContext('2d') as CanvasRenderingContext2D | null;\r\n if (!tc) return null;\r\n\r\n tc.scale(scale, scale);\r\n tc.beginPath();\r\n tc.rect(0, 0, tileW, tileH);\r\n tc.clip();\r\n\r\n const angleOffset = orientation === 'pointy' ? -Math.PI / 2 : 0;\r\n const ox0 = cellSize * Math.cos(angleOffset);\r\n const oy0 = cellSize * Math.sin(angleOffset);\r\n const ox1 = cellSize * Math.cos(Math.PI / 3 + angleOffset);\r\n const oy1 = cellSize * Math.sin(Math.PI / 3 + angleOffset);\r\n const ox2 = cellSize * Math.cos((2 * Math.PI) / 3 + angleOffset);\r\n const oy2 = cellSize * Math.sin((2 * Math.PI) / 3 + angleOffset);\r\n const ox3 = cellSize * Math.cos(Math.PI + angleOffset);\r\n const oy3 = cellSize * Math.sin(Math.PI + angleOffset);\r\n const ox4 = cellSize * Math.cos((4 * Math.PI) / 3 + angleOffset);\r\n const oy4 = cellSize * Math.sin((4 * Math.PI) / 3 + angleOffset);\r\n const ox5 = cellSize * Math.cos((5 * Math.PI) / 3 + angleOffset);\r\n const oy5 = cellSize * Math.sin((5 * Math.PI) / 3 + angleOffset);\r\n\r\n tc.strokeStyle = strokeColor;\r\n tc.lineWidth = strokeWidth;\r\n tc.globalAlpha = opacity;\r\n tc.beginPath();\r\n\r\n if (orientation === 'pointy') {\r\n const hexW = tileW;\r\n const rowH = 1.5 * cellSize;\r\n for (let row = -1; row <= 3; row++) {\r\n const offX = row % 2 !== 0 ? hexW / 2 : 0;\r\n for (let col = -1; col <= 1; col++) {\r\n const cx = col * hexW + offX;\r\n const cy = row * rowH;\r\n tc.moveTo(cx + ox0, cy + oy0);\r\n tc.lineTo(cx + ox1, cy + oy1);\r\n tc.lineTo(cx + ox2, cy + oy2);\r\n tc.lineTo(cx + ox3, cy + oy3);\r\n tc.lineTo(cx + ox4, cy + oy4);\r\n tc.lineTo(cx + ox5, cy + oy5);\r\n tc.closePath();\r\n }\r\n }\r\n } else {\r\n const hexH = tileH;\r\n const colW = 1.5 * cellSize;\r\n for (let col = -1; col <= 3; col++) {\r\n const offY = col % 2 !== 0 ? hexH / 2 : 0;\r\n for (let row = -1; row <= 1; row++) {\r\n const cx = col * colW;\r\n const cy = row * hexH + offY;\r\n tc.moveTo(cx + ox0, cy + oy0);\r\n tc.lineTo(cx + ox1, cy + oy1);\r\n tc.lineTo(cx + ox2, cy + oy2);\r\n tc.lineTo(cx + ox3, cy + oy3);\r\n tc.lineTo(cx + ox4, cy + oy4);\r\n tc.lineTo(cx + ox5, cy + oy5);\r\n tc.closePath();\r\n }\r\n }\r\n }\r\n\r\n tc.stroke();\r\n return { canvas, tileW, tileH };\r\n}\r\n\r\nexport function renderHexGridTiled(\r\n ctx: CanvasRenderingContext2D,\r\n bounds: VisibleBounds,\r\n cellSize: number,\r\n tile: HexGridTile,\r\n): void {\r\n const { tileW, tileH } = tile;\r\n\r\n const startCol = Math.floor(bounds.minX / tileW) - 1;\r\n const endCol = Math.ceil(bounds.maxX / tileW) + 1;\r\n const startRow = Math.floor(bounds.minY / tileH) - 1;\r\n const endRow = Math.ceil(bounds.maxY / tileH) + 1;\r\n\r\n for (let row = startRow; row <= endRow; row++) {\r\n for (let col = startCol; col <= endCol; col++) {\r\n ctx.drawImage(tile.canvas as CanvasImageSource, col * tileW, row * tileH, tileW, tileH);\r\n }\r\n }\r\n}\r\n","import type { CanvasElement, GridElement } from './types';\r\nimport { getElementBounds } from './element-bounds';\r\nimport { withRotation } from './rotate-canvas';\r\nimport { renderStroke } from './renderers/stroke-renderer';\r\nimport { renderShape } from './renderers/shape-renderer';\r\nimport { renderArrow } from './renderers/arrow-renderer';\r\nimport { renderImage } from './renderers/image-renderer';\r\nimport { renderTemplate } from './renderers/template-renderer';\r\nimport type { ElementStore } from './element-store';\r\nimport {\r\n renderSquareGrid,\r\n renderHexGrid,\r\n createHexGridTile,\r\n renderHexGridTiled,\r\n} from './grid-renderer';\r\nimport type { HexGridTile } from './grid-renderer';\r\nimport type { HexOrientation } from './types';\r\nimport type { Camera } from '../canvas/camera';\r\n\r\nconst DOM_ELEMENT_TYPES = new Set(['note', 'html', 'text']);\r\n\r\nexport class ElementRenderer {\r\n private store: ElementStore | null = null;\r\n private imageCache = new Map<string, ImageBitmap | HTMLImageElement | 'failed'>();\r\n private onImageLoad: (() => void) | null = null;\r\n private onImageError: ((src: string, cause?: unknown) => void) | null = null;\r\n private camera: Camera | null = null;\r\n private canvasSize: { w: number; h: number } | null = null;\r\n private hexTileCache: HexGridTile | null = null;\r\n private hexTileCacheKey = '';\r\n private gridBoundsOverride: { minX: number; minY: number; maxX: number; maxY: number } | null =\r\n null;\r\n private labelEditingId: string | null = null;\r\n\r\n setStore(store: ElementStore): void {\r\n this.store = store;\r\n }\r\n\r\n setOnImageLoad(callback: () => void): void {\r\n this.onImageLoad = callback;\r\n }\r\n\r\n setOnImageError(callback: (src: string, cause?: unknown) => void): void {\r\n this.onImageError = callback;\r\n }\r\n\r\n setCamera(camera: Camera): void {\r\n this.camera = camera;\r\n }\r\n\r\n setCanvasSize(w: number, h: number): void {\r\n this.canvasSize = { w, h };\r\n }\r\n\r\n setGridBoundsOverride(\r\n bounds: { minX: number; minY: number; maxX: number; maxY: number } | null,\r\n ): void {\r\n this.gridBoundsOverride = bounds;\r\n }\r\n\r\n setLabelEditingId(id: string | null): void {\r\n this.labelEditingId = id;\r\n }\r\n\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 const b = getElementBounds(element);\r\n const c = b ? { x: b.x + b.w / 2, y: b.y + b.h / 2 } : element.position;\r\n withRotation(ctx, element, c, () => renderStroke(ctx, element));\r\n break;\r\n }\r\n case 'arrow':\r\n renderArrow(ctx, element, this.store, this.labelEditingId);\r\n break;\r\n case 'shape': {\r\n const b = getElementBounds(element);\r\n const c = b ? { x: b.x + b.w / 2, y: b.y + b.h / 2 } : element.position;\r\n withRotation(ctx, element, c, () => renderShape(ctx, element));\r\n break;\r\n }\r\n case 'image': {\r\n const b = getElementBounds(element);\r\n const c = b ? { x: b.x + b.w / 2, y: b.y + b.h / 2 } : element.position;\r\n withRotation(ctx, element, c, () =>\r\n renderImage(ctx, element, this.imageCache, this.onImageLoad, this.onImageError),\r\n );\r\n break;\r\n }\r\n case 'grid':\r\n this.renderGrid(ctx, element);\r\n break;\r\n case 'template':\r\n renderTemplate(ctx, element, this.store);\r\n break;\r\n }\r\n }\r\n\r\n private renderGrid(ctx: CanvasRenderingContext2D, grid: GridElement): void {\r\n const canvasSize = this.canvasSize;\r\n if (!canvasSize) return;\r\n\r\n const cam = this.camera;\r\n if (!cam) return;\r\n\r\n const bounds =\r\n this.gridBoundsOverride ??\r\n (() => {\r\n const topLeft = cam.screenToWorld({ x: 0, y: 0 });\r\n const bottomRight = cam.screenToWorld({ x: canvasSize.w, y: canvasSize.h });\r\n return {\r\n minX: topLeft.x,\r\n minY: topLeft.y,\r\n maxX: bottomRight.x,\r\n maxY: bottomRight.y,\r\n };\r\n })();\r\n\r\n if (grid.gridType === 'hex') {\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n const scale = cam.zoom * dpr;\r\n const tile = this.getHexTile(\r\n grid.cellSize,\r\n grid.hexOrientation,\r\n grid.strokeColor,\r\n grid.strokeWidth,\r\n grid.opacity,\r\n scale,\r\n );\r\n if (tile) {\r\n renderHexGridTiled(ctx, bounds, grid.cellSize, tile);\r\n } else {\r\n renderHexGrid(\r\n ctx,\r\n bounds,\r\n grid.cellSize,\r\n grid.hexOrientation,\r\n grid.strokeColor,\r\n grid.strokeWidth,\r\n grid.opacity,\r\n );\r\n }\r\n } else {\r\n renderSquareGrid(\r\n ctx,\r\n bounds,\r\n grid.cellSize,\r\n grid.strokeColor,\r\n grid.strokeWidth,\r\n grid.opacity,\r\n );\r\n }\r\n }\r\n\r\n private getHexTile(\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n strokeColor: string,\r\n strokeWidth: number,\r\n opacity: number,\r\n scale: number,\r\n ): HexGridTile | null {\r\n const key = `${cellSize}:${orientation}:${strokeColor}:${strokeWidth}:${opacity}:${scale}`;\r\n if (this.hexTileCacheKey === key && this.hexTileCache) {\r\n return this.hexTileCache;\r\n }\r\n const tile = createHexGridTile(cellSize, orientation, strokeColor, strokeWidth, opacity, scale);\r\n if (tile) {\r\n this.hexTileCache = tile;\r\n this.hexTileCacheKey = key;\r\n }\r\n return tile;\r\n }\r\n}\r\n","import type { Point, Size, StrokePoint } from '../core/types';\r\nimport type {\r\n Binding,\r\n StrokeElement,\r\n NoteElement,\r\n ArrowElement,\r\n ImageElement,\r\n HtmlElement,\r\n TextElement,\r\n ShapeElement,\r\n ShapeKind,\r\n GridElement,\r\n HexOrientation,\r\n TemplateElement,\r\n TemplateShape,\r\n} from './types';\r\nimport { createId } from './create-id';\r\nimport { getArrowControlPoint } from './arrow-geometry';\r\nimport { sanitizeNoteHtml } from './note-sanitizer';\r\n\r\nexport const DEFAULT_NOTE_FONT_SIZE = 18;\r\n\r\ninterface BaseDefaults {\r\n position?: Point;\r\n zIndex?: number;\r\n locked?: boolean;\r\n layerId?: string;\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 blendMode?: 'multiply';\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 textColor?: string;\r\n fontSize?: number;\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 fromBinding?: Binding;\r\n toBinding?: Binding;\r\n label?: string;\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 domId?: string;\r\n interactive?: boolean;\r\n}\r\n\r\ninterface TextInput extends BaseDefaults {\r\n position: Point;\r\n size?: Size;\r\n text?: string;\r\n fontSize?: number;\r\n color?: string;\r\n textAlign?: 'left' | 'center' | 'right';\r\n}\r\n\r\nexport function createStroke(input: StrokeInput): StrokeElement {\r\n const result: StrokeElement = {\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 layerId: input.layerId ?? '',\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 if (input.blendMode) result.blendMode = input.blendMode;\r\n return result;\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 layerId: input.layerId ?? '',\r\n size: input.size ?? { w: 200, h: 100 },\r\n text: sanitizeNoteHtml(input.text ?? ''),\r\n backgroundColor: input.backgroundColor ?? '#ffeb3b',\r\n textColor: input.textColor ?? '#000000',\r\n fontSize: input.fontSize ?? DEFAULT_NOTE_FONT_SIZE,\r\n };\r\n}\r\n\r\nexport function createArrow(input: ArrowInput): ArrowElement {\r\n const bend = input.bend ?? 0;\r\n const result: ArrowElement = {\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 layerId: input.layerId ?? '',\r\n from: input.from,\r\n to: input.to,\r\n bend,\r\n color: input.color ?? '#000000',\r\n width: input.width ?? 2,\r\n cachedControlPoint: getArrowControlPoint(input.from, input.to, bend),\r\n };\r\n if (input.fromBinding) result.fromBinding = input.fromBinding;\r\n if (input.toBinding) result.toBinding = input.toBinding;\r\n if (input.label !== undefined) result.label = input.label;\r\n return result;\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 layerId: input.layerId ?? '',\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 const el: HtmlElement = {\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 layerId: input.layerId ?? '',\r\n size: input.size,\r\n };\r\n if (input.domId) el.domId = input.domId;\r\n if (input.interactive) el.interactive = input.interactive;\r\n return el;\r\n}\r\n\r\ninterface ShapeInput extends BaseDefaults {\r\n position: Point;\r\n size: Size;\r\n shape?: ShapeKind;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n fillColor?: string;\r\n flip?: boolean;\r\n}\r\n\r\nexport function createShape(input: ShapeInput): ShapeElement {\r\n const result: ShapeElement = {\r\n id: createId('shape'),\r\n type: 'shape',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n shape: input.shape ?? 'rectangle',\r\n size: input.size,\r\n strokeColor: input.strokeColor ?? '#000000',\r\n strokeWidth: input.strokeWidth ?? 2,\r\n fillColor: input.fillColor ?? 'none',\r\n };\r\n if (input.flip) result.flip = input.flip;\r\n return result;\r\n}\r\n\r\ninterface GridInput extends BaseDefaults {\r\n gridType?: 'square' | 'hex';\r\n hexOrientation?: HexOrientation;\r\n cellSize?: number;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n}\r\n\r\nexport function createGrid(input: GridInput): GridElement {\r\n return {\r\n id: createId('grid'),\r\n type: 'grid',\r\n position: input.position ?? { x: 0, y: 0 },\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n gridType: input.gridType ?? 'square',\r\n hexOrientation: input.hexOrientation ?? 'pointy',\r\n cellSize: input.cellSize ?? 40,\r\n strokeColor: input.strokeColor ?? '#000000',\r\n strokeWidth: input.strokeWidth ?? 1,\r\n opacity: input.opacity ?? 1,\r\n };\r\n}\r\n\r\nexport function createText(input: TextInput): TextElement {\r\n return {\r\n id: createId('text'),\r\n type: 'text',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n size: input.size ?? { w: 200, h: 28 },\r\n text: input.text ?? '',\r\n fontSize: input.fontSize ?? 16,\r\n color: input.color ?? '#1a1a1a',\r\n textAlign: input.textAlign ?? 'left',\r\n };\r\n}\r\n\r\ninterface TemplateInput extends BaseDefaults {\r\n position: Point;\r\n templateShape: TemplateShape;\r\n radius: number;\r\n angle?: number;\r\n fillColor?: string;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n feetPerCell?: number;\r\n radiusFeet?: number;\r\n}\r\n\r\nexport function createTemplate(input: TemplateInput): TemplateElement {\r\n return {\r\n id: createId('template'),\r\n type: 'template',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n templateShape: input.templateShape,\r\n radius: input.radius,\r\n angle: input.angle ?? 0,\r\n fillColor: input.fillColor ?? 'rgba(255, 87, 34, 0.2)',\r\n strokeColor: input.strokeColor ?? '#FF5722',\r\n strokeWidth: input.strokeWidth ?? 2,\r\n opacity: input.opacity ?? 0.6,\r\n feetPerCell: input.feetPerCell,\r\n radiusFeet: input.radiusFeet,\r\n };\r\n}\r\n","export interface ActiveFormats {\r\n bold: boolean;\r\n italic: boolean;\r\n underline: boolean;\r\n strikethrough: boolean;\r\n}\r\n\r\nexport function toggleBold(): void {\r\n document.execCommand('bold');\r\n}\r\n\r\nexport function toggleItalic(): void {\r\n document.execCommand('italic');\r\n}\r\n\r\nexport function toggleUnderline(): void {\r\n document.execCommand('underline');\r\n}\r\n\r\nexport function toggleStrikethrough(): void {\r\n document.execCommand('strikeThrough');\r\n}\r\n\r\nexport function setFontSize(size: number): void {\r\n const sel = window.getSelection();\r\n if (!sel || sel.rangeCount === 0) return;\r\n\r\n const range = sel.getRangeAt(0);\r\n if (range.collapsed) return;\r\n\r\n const span = document.createElement('span');\r\n span.style.fontSize = `${size}px`;\r\n try {\r\n range.surroundContents(span);\r\n } catch {\r\n span.appendChild(range.extractContents());\r\n range.insertNode(span);\r\n }\r\n}\r\n\r\nexport function getActiveFormats(): ActiveFormats {\r\n const query = (cmd: string): boolean => {\r\n try {\r\n return document.queryCommandState(cmd);\r\n } catch {\r\n return false;\r\n }\r\n };\r\n\r\n return {\r\n bold: query('bold'),\r\n italic: query('italic'),\r\n underline: query('underline'),\r\n strikethrough: query('strikeThrough'),\r\n };\r\n}\r\n","import { DEFAULT_NOTE_FONT_SIZE } from './element-factory';\r\nimport { setFontSize, getActiveFormats } from './note-formatting';\r\n\r\nconst TOOLBAR_HEIGHT = 52;\r\nconst TOOLBAR_GAP = 4;\r\n\r\ninterface FormatButton {\r\n label: string;\r\n format: string;\r\n command: string;\r\n}\r\n\r\nconst FORMAT_BUTTONS: FormatButton[] = [\r\n { label: 'B', format: 'bold', command: 'bold' },\r\n { label: 'I', format: 'italic', command: 'italic' },\r\n { label: 'U', format: 'underline', command: 'underline' },\r\n { label: 'S', format: 'strikethrough', command: 'strikeThrough' },\r\n];\r\n\r\nexport interface FontSizePreset {\r\n label: string;\r\n size: number;\r\n}\r\n\r\nexport const DEFAULT_FONT_SIZE_PRESETS: FontSizePreset[] = [\r\n { label: 'Small', size: 14 },\r\n { label: 'Normal', size: 18 },\r\n { label: 'Large', size: 24 },\r\n { label: 'Heading', size: 32 },\r\n];\r\n\r\nexport class NoteToolbar {\r\n private el: HTMLDivElement | null = null;\r\n private anchor: HTMLElement | null = null;\r\n private selectionListener: (() => void) | null = null;\r\n private readonly fontSizePresets: FontSizePreset[];\r\n\r\n constructor(fontSizePresets?: FontSizePreset[]) {\r\n this.fontSizePresets = fontSizePresets ?? DEFAULT_FONT_SIZE_PRESETS;\r\n }\r\n\r\n show(anchor: HTMLElement): void {\r\n this.hide();\r\n this.anchor = anchor;\r\n this.el = this.createToolbarElement();\r\n document.body.appendChild(this.el);\r\n this.positionToolbar(anchor);\r\n this.selectionListener = () => this.updateActiveStates();\r\n document.addEventListener('selectionchange', this.selectionListener);\r\n }\r\n\r\n hide(): void {\r\n if (this.selectionListener) {\r\n document.removeEventListener('selectionchange', this.selectionListener);\r\n this.selectionListener = null;\r\n }\r\n if (this.el) {\r\n this.el.remove();\r\n this.el = null;\r\n }\r\n this.anchor = null;\r\n }\r\n\r\n getElement(): HTMLDivElement | null {\r\n return this.el;\r\n }\r\n\r\n updatePosition(anchor: HTMLElement): void {\r\n if (this.el) {\r\n this.positionToolbar(anchor);\r\n }\r\n }\r\n\r\n private createToolbarElement(): HTMLDivElement {\r\n const toolbar = document.createElement('div');\r\n toolbar.dataset['noteToolbar'] = '';\r\n Object.assign(toolbar.style, {\r\n position: 'fixed',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '2px',\r\n padding: '2px 4px',\r\n background: '#fff',\r\n border: '1px solid #ccc',\r\n borderRadius: '4px',\r\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\r\n zIndex: '10000',\r\n height: `${TOOLBAR_HEIGHT}px`,\r\n userSelect: 'none',\r\n });\r\n\r\n for (const btn of FORMAT_BUTTONS) {\r\n toolbar.appendChild(this.createFormatButton(btn));\r\n }\r\n\r\n toolbar.appendChild(this.createFontSizeSelect());\r\n\r\n return toolbar;\r\n }\r\n\r\n private createFormatButton(config: FormatButton): HTMLButtonElement {\r\n const btn = document.createElement('button');\r\n btn.dataset['format'] = config.format;\r\n btn.textContent = config.label;\r\n Object.assign(btn.style, {\r\n border: '1px solid transparent',\r\n borderRadius: '3px',\r\n background: 'none',\r\n cursor: 'pointer',\r\n padding: '2px 6px',\r\n fontSize: '13px',\r\n fontWeight: config.format === 'bold' ? 'bold' : 'normal',\r\n fontStyle: config.format === 'italic' ? 'italic' : 'normal',\r\n textDecoration:\r\n config.format === 'underline'\r\n ? 'underline'\r\n : config.format === 'strikethrough'\r\n ? 'line-through'\r\n : 'none',\r\n minWidth: '44px',\r\n height: '44px',\r\n lineHeight: '44px',\r\n });\r\n\r\n btn.addEventListener('pointerdown', (e) => {\r\n e.preventDefault();\r\n document.execCommand(config.command);\r\n this.updateActiveStates();\r\n });\r\n\r\n return btn;\r\n }\r\n\r\n private createFontSizeSelect(): HTMLSelectElement {\r\n const select = document.createElement('select');\r\n Object.assign(select.style, {\r\n border: '1px solid #ccc',\r\n borderRadius: '3px',\r\n background: '#fff',\r\n cursor: 'pointer',\r\n padding: '2px',\r\n fontSize: '12px',\r\n height: '44px',\r\n marginLeft: '4px',\r\n });\r\n\r\n for (const preset of this.fontSizePresets) {\r\n const option = document.createElement('option');\r\n option.value = String(preset.size);\r\n option.textContent = preset.label;\r\n select.appendChild(option);\r\n }\r\n\r\n select.value = String(DEFAULT_NOTE_FONT_SIZE);\r\n\r\n select.addEventListener('pointerdown', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n select.addEventListener('change', () => {\r\n this.applyFontSize(Number(select.value));\r\n this.updateActiveStates();\r\n this.anchor?.focus();\r\n });\r\n\r\n return select;\r\n }\r\n\r\n private applyFontSize(size: number): void {\r\n const sel = window.getSelection();\r\n const collapsed = !sel || sel.rangeCount === 0 || sel.getRangeAt(0).collapsed;\r\n if (collapsed && this.anchor) {\r\n const range = document.createRange();\r\n range.selectNodeContents(this.anchor);\r\n sel?.removeAllRanges();\r\n sel?.addRange(range);\r\n setFontSize(size);\r\n const after = window.getSelection();\r\n if (after) {\r\n const caret = document.createRange();\r\n caret.selectNodeContents(this.anchor);\r\n caret.collapse(false);\r\n after.removeAllRanges();\r\n after.addRange(caret);\r\n }\r\n return;\r\n }\r\n setFontSize(size);\r\n }\r\n\r\n private positionToolbar(anchor: HTMLElement): void {\r\n if (!this.el) return;\r\n\r\n const rect = anchor.getBoundingClientRect();\r\n const toolbarWidth = this.el.offsetWidth || 200;\r\n\r\n let top = rect.top - TOOLBAR_HEIGHT - TOOLBAR_GAP;\r\n if (top < 0) {\r\n top = rect.bottom + TOOLBAR_GAP;\r\n }\r\n\r\n let left = rect.left + (rect.width - toolbarWidth) / 2;\r\n left = Math.max(4, left);\r\n\r\n Object.assign(this.el.style, {\r\n top: `${top}px`,\r\n left: `${left}px`,\r\n });\r\n }\r\n\r\n private updateActiveStates(): void {\r\n if (!this.el) return;\r\n\r\n const active = getActiveFormats();\r\n for (const config of FORMAT_BUTTONS) {\r\n const btn = this.el.querySelector(`[data-format=\"${config.format}\"]`) as HTMLElement | null;\r\n if (!btn) continue;\r\n\r\n const isActive = active[config.format as keyof typeof active] ?? false;\r\n btn.style.background = isActive ? '#e0e0e0' : 'none';\r\n btn.style.borderColor = isActive ? '#bbb' : 'transparent';\r\n }\r\n }\r\n}\r\n","import type { ElementStore } from './element-store';\r\nimport { NoteToolbar } from './note-toolbar';\r\nimport type { FontSizePreset } from './note-toolbar';\r\nimport { sanitizeNoteHtml } from './note-sanitizer';\r\nimport { toggleBold, toggleItalic, toggleUnderline } from './note-formatting';\r\n\r\nconst FORMAT_SHORTCUTS: Record<string, () => void> = {\r\n b: toggleBold,\r\n i: toggleItalic,\r\n u: toggleUnderline,\r\n};\r\n\r\nexport interface NoteEditorOptions {\r\n fontSizePresets?: FontSizePreset[];\r\n toolbar?: boolean;\r\n placeholder?: string;\r\n}\r\n\r\nfunction ensureEditorStyles(): void {\r\n if (document.querySelector('style[data-fieldnotes-editor]')) return;\r\n const style = document.createElement('style');\r\n style.setAttribute('data-fieldnotes-editor', '');\r\n style.textContent = `[data-fn-placeholder][data-fn-empty='true']::before {\r\n content: attr(data-fn-placeholder);\r\n color: #9e9e9e;\r\n position: absolute;\r\n pointer-events: none;\r\n}`;\r\n document.head.appendChild(style);\r\n}\r\n\r\nfunction isNodeEmpty(node: HTMLElement): boolean {\r\n const text = node.textContent ?? '';\r\n return text.replace(/\\u00a0/g, ' ').trim().length === 0;\r\n}\r\n\r\nexport class NoteEditor {\r\n private editingId: string | null = null;\r\n private editingNode: HTMLDivElement | null = null;\r\n private blurHandler: ((e: FocusEvent) => void) | null = null;\r\n private keyHandler: ((e: KeyboardEvent) => void) | null = null;\r\n private pointerHandler: ((e: PointerEvent) => void) | null = null;\r\n private inputHandler: (() => void) | null = null;\r\n private pendingEditId: string | null = null;\r\n private onStopCallback: ((elementId: string) => void) | null = null;\r\n private beginHistory: (() => void) | null = null;\r\n private commitHistory: (() => void) | null = null;\r\n private toolbar: NoteToolbar | null;\r\n private readonly placeholder: string;\r\n\r\n constructor(options?: NoteEditorOptions) {\r\n this.toolbar = options?.toolbar === false ? null : new NoteToolbar(options?.fontSizePresets);\r\n this.placeholder = options?.placeholder ?? 'Type…';\r\n }\r\n\r\n get isEditing(): boolean {\r\n return this.editingId !== null;\r\n }\r\n\r\n get editingElementId(): string | null {\r\n return this.editingId;\r\n }\r\n\r\n setOnStop(callback: (elementId: string) => void): void {\r\n this.onStopCallback = callback;\r\n }\r\n\r\n setHistoryHooks(begin: () => void, commit: () => void): void {\r\n this.beginHistory = begin;\r\n this.commitHistory = commit;\r\n }\r\n\r\n startEditing(node: HTMLDivElement, elementId: string, store: ElementStore): void {\r\n if (this.editingId === elementId) return;\r\n\r\n if (this.editingId) {\r\n this.stopEditing(store);\r\n }\r\n\r\n this.pendingEditId = elementId;\r\n\r\n requestAnimationFrame(() => {\r\n if (this.pendingEditId !== elementId) return;\r\n this.pendingEditId = null;\r\n this.activateEditing(node, elementId, store);\r\n });\r\n }\r\n\r\n stopEditing(store: ElementStore): void {\r\n this.pendingEditId = null;\r\n\r\n if (!this.editingId || !this.editingNode) return;\r\n\r\n if (this.blurHandler) {\r\n this.editingNode.removeEventListener('blur', this.blurHandler);\r\n }\r\n if (this.keyHandler) {\r\n this.editingNode.removeEventListener('keydown', this.keyHandler);\r\n }\r\n if (this.pointerHandler) {\r\n this.editingNode.removeEventListener('pointerdown', this.pointerHandler);\r\n }\r\n if (this.inputHandler) {\r\n this.editingNode.removeEventListener('input', this.inputHandler);\r\n }\r\n this.editingNode.removeAttribute('data-fn-placeholder');\r\n this.editingNode.removeAttribute('data-fn-empty');\r\n\r\n const text = sanitizeNoteHtml(this.editingNode.innerHTML);\r\n const current = store.getById(this.editingId);\r\n const textChanged =\r\n !!current && (current.type === 'note' || current.type === 'text') && current.text !== text;\r\n\r\n this.editingNode.contentEditable = 'false';\r\n Object.assign(this.editingNode.style, {\r\n userSelect: 'none',\r\n cursor: 'default',\r\n });\r\n\r\n this.toolbar?.hide();\r\n\r\n // One history transaction spans the text write and the onStop height-fit/cleanup,\r\n // so a single note/text edit collapses to one undo step (both touch the same element).\r\n this.beginHistory?.();\r\n if (textChanged) {\r\n store.update(this.editingId, { text });\r\n }\r\n if (this.editingId && this.onStopCallback) {\r\n this.onStopCallback(this.editingId);\r\n }\r\n this.commitHistory?.();\r\n\r\n this.editingId = null;\r\n this.editingNode = null;\r\n this.blurHandler = null;\r\n this.keyHandler = null;\r\n this.pointerHandler = null;\r\n this.inputHandler = null;\r\n }\r\n\r\n destroy(store: ElementStore): void {\r\n this.pendingEditId = null;\r\n if (this.isEditing) {\r\n this.stopEditing(store);\r\n }\r\n }\r\n\r\n updateToolbarPosition(): void {\r\n if (this.editingNode) {\r\n this.toolbar?.updatePosition(this.editingNode);\r\n }\r\n }\r\n\r\n private activateEditing(node: HTMLDivElement, elementId: string, store: ElementStore): void {\r\n this.editingId = elementId;\r\n this.editingNode = node;\r\n\r\n node.contentEditable = 'true';\r\n Object.assign(node.style, {\r\n userSelect: 'text',\r\n cursor: 'text',\r\n outline: 'none',\r\n });\r\n node.focus();\r\n\r\n const selection = window.getSelection?.();\r\n if (selection) {\r\n const range = document.createRange();\r\n range.selectNodeContents(node);\r\n range.collapse(false);\r\n selection.removeAllRanges();\r\n selection.addRange(range);\r\n }\r\n\r\n ensureEditorStyles();\r\n node.setAttribute('data-fn-placeholder', this.placeholder);\r\n node.setAttribute('data-fn-empty', String(isNodeEmpty(node)));\r\n this.inputHandler = () => {\r\n node.setAttribute('data-fn-empty', String(isNodeEmpty(node)));\r\n };\r\n node.addEventListener('input', this.inputHandler);\r\n\r\n this.toolbar?.show(node);\r\n\r\n this.blurHandler = (e: FocusEvent) => {\r\n const related = e.relatedTarget as Node | null;\r\n if (related && this.toolbar?.getElement()?.contains(related)) return;\r\n this.stopEditing(store);\r\n };\r\n this.keyHandler = (e: KeyboardEvent) => {\r\n if ((e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) {\r\n const action = FORMAT_SHORTCUTS[e.key.toLowerCase()];\r\n if (action) {\r\n e.preventDefault();\r\n action();\r\n return;\r\n }\r\n }\r\n if (e.key === 'Escape') {\r\n node.blur();\r\n }\r\n e.stopPropagation();\r\n };\r\n this.pointerHandler = (e: PointerEvent) => {\r\n e.stopPropagation();\r\n };\r\n\r\n node.addEventListener('blur', this.blurHandler);\r\n node.addEventListener('keydown', this.keyHandler);\r\n node.addEventListener('pointerdown', this.pointerHandler);\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\n\r\nexport interface ContextMenuItem {\r\n label: string;\r\n action: string;\r\n disabled?: boolean;\r\n}\r\n\r\nexport interface ContextMenuOptions {\r\n onCommand: (action: string) => void;\r\n onClose: () => void;\r\n}\r\n\r\nexport class ContextMenu {\r\n private el: HTMLDivElement | null = null;\r\n private outsideListener: ((e: PointerEvent) => void) | null = null;\r\n private keyListener: ((e: KeyboardEvent) => void) | null = null;\r\n\r\n constructor(private readonly options: ContextMenuOptions) {}\r\n\r\n isOpen(): boolean {\r\n return this.el !== null;\r\n }\r\n\r\n open(items: ContextMenuItem[], screenPos: Point): void {\r\n this.close();\r\n const el = document.createElement('div');\r\n el.className = 'fieldnotes-context-menu';\r\n Object.assign(el.style, {\r\n position: 'fixed',\r\n left: `${screenPos.x}px`,\r\n top: `${screenPos.y}px`,\r\n zIndex: '10000',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n });\r\n for (const item of items) {\r\n const btn = document.createElement('button');\r\n btn.type = 'button';\r\n btn.className =\r\n 'fieldnotes-context-menu-item' +\r\n (item.disabled ? ' fieldnotes-context-menu-item--disabled' : '');\r\n btn.textContent = item.label;\r\n if (item.disabled) {\r\n btn.disabled = true;\r\n } else {\r\n btn.addEventListener('click', () => {\r\n this.options.onCommand(item.action);\r\n this.close();\r\n });\r\n }\r\n el.appendChild(btn);\r\n }\r\n document.body.appendChild(el);\r\n this.el = el;\r\n this.clampToViewport(el, screenPos);\r\n\r\n this.keyListener = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') this.close();\r\n };\r\n document.addEventListener('keydown', this.keyListener);\r\n\r\n this.outsideListener = (e: PointerEvent) => {\r\n if (this.el && !this.el.contains(e.target as Node)) this.close();\r\n };\r\n // Defer attaching so the opening gesture's own pointerdown doesn't immediately close it.\r\n setTimeout(() => {\r\n if (this.outsideListener) document.addEventListener('pointerdown', this.outsideListener);\r\n }, 0);\r\n }\r\n\r\n close(): void {\r\n if (this.keyListener) {\r\n document.removeEventListener('keydown', this.keyListener);\r\n this.keyListener = null;\r\n }\r\n if (this.outsideListener) {\r\n document.removeEventListener('pointerdown', this.outsideListener);\r\n this.outsideListener = null;\r\n }\r\n if (this.el) {\r\n this.el.remove();\r\n this.el = null;\r\n this.options.onClose();\r\n }\r\n }\r\n\r\n dispose(): void {\r\n this.close();\r\n }\r\n\r\n private clampToViewport(el: HTMLElement, screenPos: Point): void {\r\n const rect = el.getBoundingClientRect();\r\n if (rect.width > 0 && screenPos.x + rect.width > window.innerWidth) {\r\n el.style.left = `${Math.max(0, screenPos.x - rect.width)}px`;\r\n }\r\n if (rect.height > 0 && screenPos.y + rect.height > window.innerHeight) {\r\n el.style.top = `${Math.max(0, screenPos.y - rect.height)}px`;\r\n }\r\n }\r\n}\r\n","export function 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 overscrollBehavior: 'none',\r\n userSelect: 'none',\r\n webkitUserSelect: 'none',\r\n });\r\n return el;\r\n}\r\n\r\nexport function 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\nexport function 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","import type { ArrowElement } from './types';\r\nimport type { ElementStore } from './element-store';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport { getArrowMidpoint } from './arrow-geometry';\r\n\r\nexport interface ArrowLabelEditStart {\r\n arrow: ArrowElement;\r\n layer: HTMLElement;\r\n store: ElementStore;\r\n recorder: HistoryRecorder;\r\n onDone: () => void;\r\n}\r\n\r\nexport class ArrowLabelEditor {\r\n private input: HTMLInputElement | null = null;\r\n private done = false;\r\n\r\n get isEditing(): boolean {\r\n return this.input !== null;\r\n }\r\n\r\n startEditing(start: ArrowLabelEditStart): void {\r\n if (this.input) this.cleanup();\r\n const { arrow, layer, store, recorder, onDone } = start;\r\n const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);\r\n\r\n const input = document.createElement('input');\r\n input.type = 'text';\r\n input.value = arrow.label ?? '';\r\n Object.assign(input.style, {\r\n position: 'absolute',\r\n left: `${mid.x}px`,\r\n top: `${mid.y}px`,\r\n transform: 'translate(-50%, -50%)',\r\n // domLayer is pointer-events:none; the input must opt back in to receive taps/clicks.\r\n pointerEvents: 'auto',\r\n font: '14px system-ui, sans-serif',\r\n padding: '2px 6px',\r\n border: '1px solid #2196F3',\r\n borderRadius: '4px',\r\n background: '#ffffff',\r\n color: '#1a1a1a',\r\n outline: 'none',\r\n minWidth: '40px',\r\n });\r\n\r\n this.done = false;\r\n\r\n const commit = (): void => {\r\n if (this.done) return;\r\n this.done = true;\r\n const next = input.value.trim() || undefined;\r\n if (next !== arrow.label) {\r\n recorder.begin();\r\n store.update(arrow.id, { label: next });\r\n recorder.commit();\r\n }\r\n this.cleanup();\r\n onDone();\r\n };\r\n\r\n const cancel = (): void => {\r\n if (this.done) return;\r\n this.done = true;\r\n this.cleanup();\r\n onDone();\r\n };\r\n\r\n input.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter') {\r\n e.preventDefault();\r\n commit();\r\n } else if (e.key === 'Escape') {\r\n e.preventDefault();\r\n cancel();\r\n }\r\n e.stopPropagation();\r\n });\r\n input.addEventListener('blur', commit);\r\n\r\n layer.appendChild(input);\r\n this.input = input;\r\n input.focus();\r\n input.select();\r\n }\r\n\r\n /** Abort any in-progress edit without committing (e.g. on viewport teardown). */\r\n cancel(): void {\r\n this.done = true;\r\n this.cleanup();\r\n }\r\n\r\n private cleanup(): void {\r\n if (this.input) {\r\n this.input.remove();\r\n this.input = null;\r\n }\r\n }\r\n}\r\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';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { Command } from './types';\r\n\r\nexport class AddElementCommand implements Command {\r\n private readonly element: CanvasElement;\r\n\r\n constructor(element: CanvasElement) {\r\n this.element = { ...element };\r\n }\r\n\r\n execute(store: ElementStore): void {\r\n store.add(this.element);\r\n }\r\n\r\n undo(store: ElementStore): void {\r\n store.remove(this.element.id);\r\n }\r\n}\r\n\r\nexport class RemoveElementCommand implements Command {\r\n private readonly element: CanvasElement;\r\n\r\n constructor(element: CanvasElement) {\r\n this.element = { ...element };\r\n }\r\n\r\n execute(store: ElementStore): void {\r\n store.remove(this.element.id);\r\n }\r\n\r\n undo(store: ElementStore): void {\r\n store.add(this.element);\r\n }\r\n}\r\n\r\nexport class UpdateElementCommand implements Command {\r\n constructor(\r\n private readonly id: string,\r\n private readonly previous: CanvasElement,\r\n private readonly current: CanvasElement,\r\n ) {}\r\n\r\n execute(store: ElementStore): void {\r\n store.update(this.id, diffPatch(this.previous, this.current));\r\n }\r\n\r\n undo(store: ElementStore): void {\r\n store.update(this.id, diffPatch(this.current, this.previous));\r\n }\r\n}\r\n\r\n// Patch turning `from` into `to`, explicitly setting keys that exist on `from`\r\n// but not `to` to `undefined` so a merge-based `update` clears them.\r\nfunction diffPatch(from: CanvasElement, to: CanvasElement): Partial<CanvasElement> {\r\n const patch: Record<string, unknown> = { ...to };\r\n for (const key of Object.keys(from)) {\r\n if (!(key in to)) patch[key] = undefined;\r\n }\r\n return patch as Partial<CanvasElement>;\r\n}\r\n\r\nexport class BatchCommand implements Command {\r\n readonly commands: readonly Command[];\r\n\r\n constructor(commands: Command[]) {\r\n this.commands = [...commands];\r\n }\r\n\r\n execute(store: ElementStore): void {\r\n for (const cmd of this.commands) {\r\n cmd.execute(store);\r\n }\r\n }\r\n\r\n undo(store: ElementStore): void {\r\n for (let i = this.commands.length - 1; i >= 0; i--) {\r\n this.commands[i]?.undo(store);\r\n }\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { Command } from './types';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport type { Layer } from '../layers/types';\r\n\r\nexport class CreateLayerCommand implements Command {\r\n constructor(\r\n private readonly manager: LayerManager,\r\n private readonly layer: Layer,\r\n ) {}\r\n\r\n execute(_store: ElementStore): void {\r\n this.manager.addLayerDirect(this.layer);\r\n }\r\n\r\n undo(_store: ElementStore): void {\r\n this.manager.removeLayerDirect(this.layer.id);\r\n }\r\n}\r\n\r\nexport class RemoveLayerCommand implements Command {\r\n constructor(\r\n private readonly manager: LayerManager,\r\n private readonly layer: Layer,\r\n ) {}\r\n\r\n execute(_store: ElementStore): void {\r\n this.manager.removeLayerDirect(this.layer.id);\r\n }\r\n\r\n undo(_store: ElementStore): void {\r\n this.manager.addLayerDirect(this.layer);\r\n }\r\n}\r\n\r\nexport class UpdateLayerCommand implements Command {\r\n constructor(\r\n private readonly manager: LayerManager,\r\n private readonly layerId: string,\r\n private readonly previous: Layer,\r\n private readonly current: Layer,\r\n ) {}\r\n\r\n execute(_store: ElementStore): void {\r\n this.manager.updateLayerDirect(this.layerId, { ...this.current });\r\n }\r\n\r\n undo(_store: ElementStore): void {\r\n this.manager.updateLayerDirect(this.layerId, { ...this.previous });\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport type { Command } from './types';\r\nimport type { HistoryStack } from './history-stack';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport type { Layer } from '../layers/types';\r\nimport {\r\n AddElementCommand,\r\n RemoveElementCommand,\r\n UpdateElementCommand,\r\n BatchCommand,\r\n} from './commands';\r\nimport { CreateLayerCommand, RemoveLayerCommand, UpdateLayerCommand } from './layer-commands';\r\n\r\nexport class HistoryRecorder {\r\n private recording = true;\r\n private transaction: Command[] | null = null;\r\n private generation = 0;\r\n private updateSnapshots = new Map<string, CanvasElement>();\r\n private unsubscribers: (() => void)[];\r\n\r\n constructor(\r\n private readonly store: ElementStore,\r\n private readonly stack: HistoryStack,\r\n private readonly layerManager?: LayerManager,\r\n ) {\r\n this.unsubscribers = [\r\n store.on('add', (el) => this.onAdd(el)),\r\n store.on('remove', (el) => this.onRemove(el)),\r\n store.on('update', ({ previous, current }) => this.onUpdate(previous, current)),\r\n ];\r\n\r\n if (layerManager) {\r\n this.unsubscribers.push(\r\n layerManager.on('create', (layer) => this.onLayerCreate(layer)),\r\n layerManager.on('remove', (layer) => this.onLayerRemove(layer)),\r\n layerManager.on('update', ({ previous, current }) => this.onLayerUpdate(previous, current)),\r\n );\r\n }\r\n }\r\n\r\n pause(): void {\r\n this.recording = false;\r\n }\r\n\r\n resume(): void {\r\n this.recording = true;\r\n }\r\n\r\n begin(): void {\r\n if (this.transaction !== null) {\r\n this.commit();\r\n }\r\n this.transaction = [];\r\n this.updateSnapshots.clear();\r\n this.generation += 1;\r\n }\r\n\r\n get currentTransactionId(): number | null {\r\n return this.transaction !== null ? this.generation : null;\r\n }\r\n\r\n commit(): void {\r\n if (!this.transaction) return;\r\n\r\n const finalCommands = this.flushUpdateSnapshots();\r\n const all = [...this.transaction, ...finalCommands];\r\n this.transaction = null;\r\n this.updateSnapshots.clear();\r\n\r\n if (all.length === 0) return;\r\n const first = all[0];\r\n this.stack.push(all.length === 1 && first ? first : new BatchCommand(all));\r\n }\r\n\r\n rollback(): void {\r\n this.transaction = null;\r\n this.updateSnapshots.clear();\r\n }\r\n\r\n destroy(): void {\r\n this.unsubscribers.forEach((fn) => fn());\r\n }\r\n\r\n private record(command: Command): void {\r\n if (this.transaction) {\r\n this.transaction.push(command);\r\n } else {\r\n this.stack.push(command);\r\n }\r\n }\r\n\r\n private onAdd(element: CanvasElement): void {\r\n if (!this.recording) return;\r\n this.record(new AddElementCommand(element));\r\n }\r\n\r\n private onRemove(element: CanvasElement): void {\r\n if (!this.recording) return;\r\n\r\n if (this.transaction && this.updateSnapshots.has(element.id)) {\r\n this.updateSnapshots.delete(element.id);\r\n }\r\n\r\n this.record(new RemoveElementCommand(element));\r\n }\r\n\r\n private onUpdate(previous: CanvasElement, current: CanvasElement): void {\r\n if (!this.recording) return;\r\n\r\n if (this.transaction) {\r\n if (!this.updateSnapshots.has(current.id)) {\r\n this.updateSnapshots.set(current.id, { ...previous });\r\n }\r\n } else {\r\n this.stack.push(new UpdateElementCommand(current.id, previous, current));\r\n }\r\n }\r\n\r\n private onLayerCreate(layer: Layer): void {\r\n if (!this.recording) return;\r\n if (!this.layerManager) return;\r\n this.record(new CreateLayerCommand(this.layerManager, layer));\r\n }\r\n\r\n private onLayerRemove(layer: Layer): void {\r\n if (!this.recording) return;\r\n if (!this.layerManager) return;\r\n this.record(new RemoveLayerCommand(this.layerManager, layer));\r\n }\r\n\r\n private onLayerUpdate(previous: Layer, current: Layer): void {\r\n if (!this.recording) return;\r\n if (!this.layerManager) return;\r\n this.record(new UpdateLayerCommand(this.layerManager, current.id, previous, current));\r\n }\r\n\r\n private flushUpdateSnapshots(): Command[] {\r\n const commands: Command[] = [];\r\n for (const [id, previous] of this.updateSnapshots) {\r\n const current = this.store.getById(id);\r\n if (current) {\r\n commands.push(new UpdateElementCommand(id, previous, current));\r\n }\r\n }\r\n return commands;\r\n }\r\n}\r\n","import type { NoteElement } from '../elements/types';\r\nimport { DEFAULT_NOTE_FONT_SIZE } from '../elements/element-factory';\r\nimport { parseStyledRuns } from '../elements/note-sanitizer';\r\nimport type { StyledRun } from '../elements/note-sanitizer';\r\n\r\nexport function renderNoteOnCanvas(ctx: CanvasRenderingContext2D, note: NoteElement): void {\r\n const { x, y } = note.position;\r\n const { w, h } = note.size;\r\n const r = 4;\r\n const pad = 8;\r\n const baseFontSize = note.fontSize ?? DEFAULT_NOTE_FONT_SIZE;\r\n\r\n ctx.save();\r\n ctx.fillStyle = note.backgroundColor;\r\n ctx.beginPath();\r\n ctx.moveTo(x + r, y);\r\n ctx.lineTo(x + w - r, y);\r\n ctx.arcTo(x + w, y, x + w, y + r, r);\r\n ctx.lineTo(x + w, y + h - r);\r\n ctx.arcTo(x + w, y + h, x + w - r, y + h, r);\r\n ctx.lineTo(x + r, y + h);\r\n ctx.arcTo(x, y + h, x, y + h - r, r);\r\n ctx.lineTo(x, y + r);\r\n ctx.arcTo(x, y, x + r, y, r);\r\n ctx.closePath();\r\n ctx.fill();\r\n\r\n if (note.text) {\r\n ctx.fillStyle = note.textColor;\r\n const runs = parseStyledRuns(note.text, baseFontSize);\r\n renderStyledRuns(ctx, runs, x + pad, y + pad, w - pad * 2);\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nfunction buildFontString(run: StyledRun): string {\r\n const style = run.italic ? 'italic' : 'normal';\r\n const weight = run.bold ? 'bold' : 'normal';\r\n return `${style} ${weight} ${run.fontSize}px system-ui, sans-serif`;\r\n}\r\n\r\nfunction renderStyledRuns(\r\n ctx: CanvasRenderingContext2D,\r\n runs: StyledRun[],\r\n startX: number,\r\n startY: number,\r\n maxWidth: number,\r\n): void {\r\n ctx.textBaseline = 'top';\r\n let cursorX = startX;\r\n let cursorY = startY;\r\n let lineHeight = 0;\r\n\r\n for (const run of runs) {\r\n ctx.font = buildFontString(run);\r\n const runLineHeight = run.fontSize * 1.3;\r\n lineHeight = Math.max(lineHeight, runLineHeight);\r\n\r\n const words = run.text.split(/(\\n| )/);\r\n for (const word of words) {\r\n if (word === '\\n') {\r\n cursorX = startX;\r\n cursorY += lineHeight;\r\n lineHeight = runLineHeight;\r\n continue;\r\n }\r\n if (word === ' ') {\r\n const spaceWidth = ctx.measureText(' ').width;\r\n if (cursorX + spaceWidth > startX + maxWidth && cursorX > startX) {\r\n cursorX = startX;\r\n cursorY += lineHeight;\r\n lineHeight = runLineHeight;\r\n } else {\r\n cursorX += spaceWidth;\r\n }\r\n continue;\r\n }\r\n if (!word) continue;\r\n\r\n const metrics = ctx.measureText(word);\r\n if (cursorX + metrics.width > startX + maxWidth && cursorX > startX) {\r\n cursorX = startX;\r\n cursorY += lineHeight;\r\n lineHeight = runLineHeight;\r\n }\r\n\r\n ctx.fillText(word, cursorX, cursorY);\r\n\r\n if (run.underline) {\r\n const underY = cursorY + run.fontSize + 1;\r\n ctx.fillRect(cursorX, underY, metrics.width, 1);\r\n }\r\n\r\n if (run.strikethrough) {\r\n const strikeY = cursorY + run.fontSize * 0.55;\r\n ctx.fillRect(cursorX, strikeY, metrics.width, 1);\r\n }\r\n\r\n cursorX += metrics.width;\r\n }\r\n }\r\n}\r\n","import type { CanvasElement, TextElement, GridElement } from '../elements/types';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport { ElementRenderer } from '../elements/element-renderer';\r\nimport { getArrowBounds } from '../elements/arrow-geometry';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { renderSquareGrid, renderHexGrid } from '../elements/grid-renderer';\r\nimport { withRotation } from '../elements/rotate-canvas';\r\nimport { rotatedAABB } from '../core/geometry';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport { renderNoteOnCanvas } from './note-canvas-renderer';\r\n\r\nexport interface ExportImageOptions {\r\n scale?: number;\r\n padding?: number;\r\n background?: string;\r\n filter?: (element: CanvasElement) => boolean;\r\n}\r\n\r\ninterface Rect {\r\n x: number;\r\n y: number;\r\n w: number;\r\n h: number;\r\n}\r\n\r\nconst center = (b: Rect): { x: number; y: number } => ({ x: b.x + b.w / 2, y: b.y + b.h / 2 });\r\n\r\nfunction getStrokeBounds(el: CanvasElement): Rect | null {\r\n if (el.type !== 'stroke') return null;\r\n if (el.points.length === 0) return null;\r\n\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n\r\n for (const p of el.points) {\r\n const px = el.position.x + p.x;\r\n const py = el.position.y + p.y;\r\n minX = Math.min(minX, px);\r\n minY = Math.min(minY, py);\r\n maxX = Math.max(maxX, px);\r\n maxY = Math.max(maxY, py);\r\n }\r\n\r\n const pad = el.width / 2;\r\n return {\r\n x: minX - pad,\r\n y: minY - pad,\r\n w: maxX - minX + el.width,\r\n h: maxY - minY + el.width,\r\n };\r\n}\r\n\r\nfunction getElementRect(el: CanvasElement): Rect | null {\r\n switch (el.type) {\r\n case 'stroke': {\r\n const r = getStrokeBounds(el);\r\n return r ? rotatedAABB(r, el.rotation ?? 0) : r;\r\n }\r\n case 'arrow': {\r\n const b = getArrowBounds(el.from, el.to, el.bend);\r\n const pad = el.width / 2 + 14;\r\n return { x: b.x - pad, y: b.y - pad, w: b.w + pad * 2, h: b.h + pad * 2 };\r\n }\r\n case 'grid':\r\n return null;\r\n case 'template': {\r\n const bounds = getElementBounds(el);\r\n if (!bounds) return null;\r\n return bounds;\r\n }\r\n case 'note':\r\n case 'image':\r\n case 'html':\r\n case 'text':\r\n case 'shape':\r\n if ('size' in el) {\r\n return rotatedAABB(\r\n { x: el.position.x, y: el.position.y, w: el.size.w, h: el.size.h },\r\n el.rotation ?? 0,\r\n );\r\n }\r\n return null;\r\n default:\r\n return null;\r\n }\r\n}\r\n\r\nfunction computeBounds(\r\n elements: CanvasElement[],\r\n padding: number,\r\n): { x: number; y: number; w: number; h: number } | null {\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n let found = false;\r\n\r\n for (const el of elements) {\r\n const rect = getElementRect(el);\r\n if (!rect) continue;\r\n found = true;\r\n minX = Math.min(minX, rect.x);\r\n minY = Math.min(minY, rect.y);\r\n maxX = Math.max(maxX, rect.x + rect.w);\r\n maxY = Math.max(maxY, rect.y + rect.h);\r\n }\r\n\r\n if (!found) return null;\r\n\r\n return {\r\n x: minX - padding,\r\n y: minY - padding,\r\n w: maxX - minX + padding * 2,\r\n h: maxY - minY + padding * 2,\r\n };\r\n}\r\n\r\nfunction renderTextOnCanvas(ctx: CanvasRenderingContext2D, text: TextElement): void {\r\n if (!text.text) return;\r\n\r\n ctx.save();\r\n ctx.fillStyle = text.color;\r\n ctx.font = `${text.fontSize}px system-ui, sans-serif`;\r\n ctx.textBaseline = 'top';\r\n ctx.textAlign = text.textAlign;\r\n\r\n const pad = 2;\r\n let textX = text.position.x + pad;\r\n if (text.textAlign === 'center') {\r\n textX = text.position.x + text.size.w / 2;\r\n } else if (text.textAlign === 'right') {\r\n textX = text.position.x + text.size.w - pad;\r\n }\r\n\r\n const lineHeight = text.fontSize * 1.4;\r\n const lines = text.text.split('\\n');\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i];\r\n if (line !== undefined) {\r\n ctx.fillText(line, textX, text.position.y + pad + i * lineHeight);\r\n }\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nfunction renderGridForBounds(\r\n ctx: CanvasRenderingContext2D,\r\n grid: GridElement,\r\n bounds: { x: number; y: number; w: number; h: number },\r\n): void {\r\n const visibleBounds = {\r\n minX: bounds.x,\r\n minY: bounds.y,\r\n maxX: bounds.x + bounds.w,\r\n maxY: bounds.y + bounds.h,\r\n };\r\n\r\n if (grid.gridType === 'hex') {\r\n renderHexGrid(\r\n ctx,\r\n visibleBounds,\r\n grid.cellSize,\r\n grid.hexOrientation,\r\n grid.strokeColor,\r\n grid.strokeWidth,\r\n grid.opacity,\r\n );\r\n } else {\r\n renderSquareGrid(\r\n ctx,\r\n visibleBounds,\r\n grid.cellSize,\r\n grid.strokeColor,\r\n grid.strokeWidth,\r\n grid.opacity,\r\n );\r\n }\r\n}\r\n\r\nfunction loadImages(elements: CanvasElement[]): Promise<Map<string, HTMLImageElement>> {\r\n const imageElements = elements.filter(\r\n (el): el is CanvasElement & { src: string } => el.type === 'image' && 'src' in el,\r\n );\r\n\r\n const cache = new Map<string, HTMLImageElement>();\r\n if (imageElements.length === 0) return Promise.resolve(cache);\r\n\r\n return new Promise((resolve) => {\r\n let remaining = imageElements.length;\r\n const done = () => {\r\n remaining--;\r\n if (remaining <= 0) resolve(cache);\r\n };\r\n\r\n for (const el of imageElements) {\r\n const img = new Image();\r\n img.crossOrigin = 'anonymous';\r\n img.onload = () => {\r\n cache.set(el.id, img);\r\n done();\r\n };\r\n img.onerror = done;\r\n const sep = el.src.includes('?') ? '&' : '?';\r\n img.src = `${el.src}${sep}_cors=1`;\r\n }\r\n });\r\n}\r\n\r\nexport async function exportImage(\r\n store: ElementStore,\r\n options: ExportImageOptions = {},\r\n layerManager?: LayerManager,\r\n): Promise<Blob | null> {\r\n const scale = options.scale ?? 2;\r\n const padding = options.padding ?? 0;\r\n const background = options.background ?? '#ffffff';\r\n const filter = options.filter;\r\n\r\n const allElements = store.getAll();\r\n let visibleElements = layerManager\r\n ? allElements.filter((el) => layerManager.isLayerVisible(el.layerId))\r\n : allElements;\r\n\r\n if (filter) {\r\n visibleElements = visibleElements.filter(filter);\r\n }\r\n\r\n const bounds = computeBounds(visibleElements, padding);\r\n if (!bounds) return null;\r\n\r\n const imageCache = await loadImages(visibleElements);\r\n\r\n const canvas = document.createElement('canvas');\r\n canvas.width = Math.ceil(bounds.w * scale);\r\n canvas.height = Math.ceil(bounds.h * scale);\r\n\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return null;\r\n\r\n ctx.scale(scale, scale);\r\n ctx.translate(-bounds.x, -bounds.y);\r\n\r\n ctx.fillStyle = background;\r\n ctx.fillRect(bounds.x, bounds.y, bounds.w, bounds.h);\r\n\r\n const renderer = new ElementRenderer();\r\n renderer.setStore(store);\r\n\r\n const grids: GridElement[] = [];\r\n\r\n for (const el of visibleElements) {\r\n if (el.type === 'grid') {\r\n grids.push(el);\r\n continue;\r\n }\r\n\r\n if (el.type === 'note') {\r\n const b = getElementBounds(el);\r\n withRotation(ctx, el, b ? center(b) : el.position, () => renderNoteOnCanvas(ctx, el));\r\n continue;\r\n }\r\n\r\n if (el.type === 'text') {\r\n const b = getElementBounds(el);\r\n withRotation(ctx, el, b ? center(b) : el.position, () => renderTextOnCanvas(ctx, el));\r\n continue;\r\n }\r\n\r\n if (el.type === 'html') {\r\n continue;\r\n }\r\n\r\n if (el.type === 'image') {\r\n const img = imageCache.get(el.id);\r\n if (img) {\r\n const b = getElementBounds(el);\r\n withRotation(ctx, el, b ? center(b) : el.position, () =>\r\n ctx.drawImage(img, el.position.x, el.position.y, el.size.w, el.size.h),\r\n );\r\n }\r\n continue;\r\n }\r\n\r\n renderer.renderCanvasElement(ctx, el);\r\n }\r\n\r\n for (const grid of grids) {\r\n renderGridForBounds(ctx, grid, bounds);\r\n }\r\n\r\n return new Promise((resolve) => {\r\n canvas.toBlob((blob) => resolve(blob), 'image/png');\r\n });\r\n}\r\n\r\nexport { computeBounds, getElementRect };\r\n","import { EventBus } from '../core/event-bus';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { Layer } from './types';\r\nimport { createId } from '../elements/create-id';\r\n\r\ninterface LayerManagerEvents {\r\n change: null;\r\n create: Layer;\r\n remove: Layer;\r\n update: { previous: Layer; current: Layer };\r\n}\r\n\r\nexport class LayerManager {\r\n private layers = new Map<string, Layer>();\r\n private _activeLayerId: string;\r\n private bus = new EventBus<LayerManagerEvents>();\r\n\r\n constructor(private readonly store: ElementStore) {\r\n const defaultLayer: Layer = {\r\n id: createId('layer'),\r\n name: 'Layer 1',\r\n visible: true,\r\n locked: false,\r\n order: 0,\r\n opacity: 1.0,\r\n };\r\n this.layers.set(defaultLayer.id, defaultLayer);\r\n this._activeLayerId = defaultLayer.id;\r\n this.syncLayerOrder();\r\n }\r\n\r\n get activeLayer(): Layer {\r\n const layer = this.layers.get(this._activeLayerId);\r\n if (!layer) throw new Error('Active layer not found');\r\n return { ...layer };\r\n }\r\n\r\n get activeLayerId(): string {\r\n return this._activeLayerId;\r\n }\r\n\r\n getLayers(): Layer[] {\r\n return [...this.layers.values()].sort((a, b) => a.order - b.order).map((l) => ({ ...l }));\r\n }\r\n\r\n getLayer(id: string): Layer | undefined {\r\n const layer = this.layers.get(id);\r\n return layer ? { ...layer } : undefined;\r\n }\r\n\r\n isLayerVisible(id: string): boolean {\r\n return this.layers.get(id)?.visible ?? true;\r\n }\r\n\r\n isLayerLocked(id: string): boolean {\r\n return this.layers.get(id)?.locked ?? false;\r\n }\r\n\r\n createLayer(name?: string): Layer {\r\n const maxOrder = Math.max(...[...this.layers.values()].map((l) => l.order), -1);\r\n const autoName = name ?? `Layer ${this.layers.size + 1}`;\r\n const layer: Layer = {\r\n id: createId('layer'),\r\n name: autoName,\r\n visible: true,\r\n locked: false,\r\n order: maxOrder + 1,\r\n opacity: 1.0,\r\n };\r\n this.addLayerDirect(layer);\r\n return { ...layer };\r\n }\r\n\r\n removeLayer(id: string): void {\r\n if (this.layers.size <= 1) {\r\n throw new Error('Cannot remove the last layer');\r\n }\r\n if (this._activeLayerId === id) {\r\n const remaining = [...this.layers.values()]\r\n .filter((l) => l.id !== id)\r\n .sort((a, b) => b.order - a.order);\r\n const fallback = remaining[0];\r\n if (fallback) this._activeLayerId = fallback.id;\r\n }\r\n const elements = this.store.getAll().filter((el) => el.layerId === id);\r\n for (const el of elements) {\r\n this.store.update(el.id, { layerId: this._activeLayerId });\r\n }\r\n this.removeLayerDirect(id);\r\n }\r\n\r\n renameLayer(id: string, name: string): void {\r\n this.updateLayerDirect(id, { name });\r\n }\r\n\r\n reorderLayer(id: string, newOrder: number): void {\r\n if (!this.layers.has(id)) return;\r\n this.updateLayerDirect(id, { order: newOrder });\r\n }\r\n\r\n setLayerVisible(id: string, visible: boolean): boolean {\r\n if (!visible && id === this._activeLayerId) {\r\n const fallback = this.findFallbackLayer(id);\r\n if (!fallback) return false;\r\n this._activeLayerId = fallback.id;\r\n }\r\n this.updateLayerDirect(id, { visible });\r\n return true;\r\n }\r\n\r\n setLayerLocked(id: string, locked: boolean): boolean {\r\n if (locked && id === this._activeLayerId) {\r\n const fallback = this.findFallbackLayer(id);\r\n if (!fallback) return false;\r\n this._activeLayerId = fallback.id;\r\n }\r\n this.updateLayerDirect(id, { locked });\r\n return true;\r\n }\r\n\r\n setLayerOpacity(id: string, opacity: number): void {\r\n if (!this.layers.has(id)) return;\r\n this.updateLayerDirect(id, { opacity: Math.max(0, Math.min(1, opacity)) });\r\n }\r\n\r\n setActiveLayer(id: string): void {\r\n if (!this.layers.has(id)) return;\r\n this._activeLayerId = id;\r\n this.bus.emit('change', null);\r\n }\r\n\r\n moveElementToLayer(elementId: string, layerId: string): void {\r\n if (!this.layers.has(layerId)) return;\r\n this.store.update(elementId, { layerId });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n snapshot(): Layer[] {\r\n return this.getLayers();\r\n }\r\n\r\n loadSnapshot(layers: Layer[]): void {\r\n this.layers.clear();\r\n for (const layer of layers) {\r\n this.layers.set(layer.id, { ...layer });\r\n }\r\n const first = this.getLayers()[0];\r\n if (first) this._activeLayerId = first.id;\r\n this.syncLayerOrder();\r\n this.bus.emit('change', null);\r\n }\r\n\r\n on<K extends keyof LayerManagerEvents>(\r\n event: K,\r\n callback: (data: LayerManagerEvents[K]) => void,\r\n ): () => void {\r\n return this.bus.on(event, callback);\r\n }\r\n\r\n addLayerDirect(layer: Layer): void {\r\n this.layers.set(layer.id, { ...layer });\r\n this.syncLayerOrder();\r\n this.bus.emit('create', { ...layer });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n removeLayerDirect(id: string): void {\r\n const layer = this.layers.get(id);\r\n this.layers.delete(id);\r\n this.syncLayerOrder();\r\n if (layer) this.bus.emit('remove', { ...layer });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n updateLayerDirect(id: string, props: Omit<Partial<Layer>, 'id'>): void {\r\n const layer = this.layers.get(id);\r\n if (!layer) return;\r\n const previous = { ...layer };\r\n Object.assign(layer, props);\r\n if ('order' in props) this.syncLayerOrder();\r\n this.bus.emit('update', { previous, current: { ...layer } });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n private syncLayerOrder(): void {\r\n const order = new Map<string, number>();\r\n for (const layer of this.layers.values()) {\r\n order.set(layer.id, layer.order);\r\n }\r\n this.store.setLayerOrder(order);\r\n }\r\n\r\n private findFallbackLayer(excludeId: string): Layer | undefined {\r\n return [...this.layers.values()]\r\n .filter((l) => l.id !== excludeId && l.visible && !l.locked)\r\n .sort((a, b) => b.order - a.order)[0];\r\n }\r\n}\r\n","export interface InteractModeDeps {\r\n getNode: (id: string) => HTMLDivElement | undefined;\r\n}\r\n\r\nexport class InteractMode {\r\n private interactingElementId: string | null = null;\r\n private readonly getNode: (id: string) => HTMLDivElement | undefined;\r\n\r\n constructor(deps: InteractModeDeps) {\r\n this.getNode = deps.getNode;\r\n }\r\n\r\n startInteracting(id: string): void {\r\n this.stopInteracting();\r\n const node = this.getNode(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.onNodePointerDown);\r\n\r\n window.addEventListener('keydown', this.onKeyDown);\r\n window.addEventListener('pointerdown', this.onPointerDown);\r\n }\r\n\r\n stopInteracting(): void {\r\n if (!this.interactingElementId) return;\r\n\r\n const node = this.getNode(this.interactingElementId);\r\n if (node) {\r\n node.style.pointerEvents = 'none';\r\n node.removeEventListener('pointerdown', this.onNodePointerDown);\r\n }\r\n\r\n this.interactingElementId = null;\r\n window.removeEventListener('keydown', this.onKeyDown);\r\n window.removeEventListener('pointerdown', this.onPointerDown);\r\n }\r\n\r\n isInteracting(): boolean {\r\n return this.interactingElementId !== null;\r\n }\r\n\r\n destroy(): void {\r\n this.stopInteracting();\r\n }\r\n\r\n private onNodePointerDown = (e: PointerEvent): void => {\r\n e.stopPropagation();\r\n };\r\n\r\n private onKeyDown = (e: KeyboardEvent): void => {\r\n if (e.key === 'Escape') {\r\n this.stopInteracting();\r\n }\r\n };\r\n\r\n private onPointerDown = (e: PointerEvent): void => {\r\n if (!this.interactingElementId) return;\r\n const target = e.target;\r\n if (!(target instanceof Element)) {\r\n this.stopInteracting();\r\n return;\r\n }\r\n\r\n const node = this.getNode(this.interactingElementId);\r\n if (node && !node.contains(target)) {\r\n this.stopInteracting();\r\n }\r\n };\r\n}\r\n","export interface DoubleTapDetectorOptions {\r\n timeout?: number;\r\n maxDistance?: number;\r\n}\r\n\r\nconst DEFAULT_TIMEOUT = 300;\r\nconst DEFAULT_MAX_DISTANCE = 20;\r\n\r\nexport class DoubleTapDetector {\r\n private readonly timeout: number;\r\n private readonly maxDistance: number;\r\n private lastTapTime = 0;\r\n private lastTapX = 0;\r\n private lastTapY = 0;\r\n private hasPendingTap = false;\r\n\r\n constructor(options?: DoubleTapDetectorOptions) {\r\n this.timeout = options?.timeout ?? DEFAULT_TIMEOUT;\r\n this.maxDistance = options?.maxDistance ?? DEFAULT_MAX_DISTANCE;\r\n }\r\n\r\n feed(e: PointerEvent): boolean {\r\n const now = Date.now();\r\n const x = e.clientX;\r\n const y = e.clientY;\r\n\r\n if (this.hasPendingTap) {\r\n const elapsed = now - this.lastTapTime;\r\n const dx = x - this.lastTapX;\r\n const dy = y - this.lastTapY;\r\n const dist = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (elapsed <= this.timeout && dist <= this.maxDistance) {\r\n this.reset();\r\n return true;\r\n }\r\n }\r\n\r\n this.lastTapTime = now;\r\n this.lastTapX = x;\r\n this.lastTapY = y;\r\n this.hasPendingTap = true;\r\n return false;\r\n }\r\n\r\n reset(): void {\r\n this.hasPendingTap = false;\r\n this.lastTapTime = 0;\r\n this.lastTapX = 0;\r\n this.lastTapY = 0;\r\n }\r\n}\r\n","import type { CanvasElement } from '../elements/types';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport { DEFAULT_NOTE_FONT_SIZE } from '../elements/element-factory';\r\nimport { DoubleTapDetector } from './double-tap-detector';\r\nexport interface DomNodeManagerDeps {\r\n domLayer: HTMLDivElement;\r\n onEditRequest: (id: string) => void;\r\n isEditingElement: (id: string) => boolean;\r\n getVersion?: (id: string) => number;\r\n}\r\n\r\nexport class DomNodeManager {\r\n private domNodes = new Map<string, HTMLDivElement>();\r\n private htmlContent = new Map<string, HTMLElement>();\r\n private readonly domLayer: HTMLDivElement;\r\n private readonly onEditRequest: (id: string) => void;\r\n private readonly isEditingElement: (id: string) => boolean;\r\n private readonly getVersion: ((id: string) => number) | null;\r\n private lastSyncedVersion = new Map<string, number>();\r\n private lastSyncedZIndex = new Map<string, number>();\r\n\r\n constructor(deps: DomNodeManagerDeps) {\r\n this.domLayer = deps.domLayer;\r\n this.onEditRequest = deps.onEditRequest;\r\n this.isEditingElement = deps.isEditingElement;\r\n this.getVersion = deps.getVersion ?? null;\r\n }\r\n\r\n getNode(id: string): HTMLDivElement | undefined {\r\n return this.domNodes.get(id);\r\n }\r\n\r\n storeHtmlContent(elementId: string, dom: HTMLElement): void {\r\n this.htmlContent.set(elementId, dom);\r\n }\r\n\r\n hasContent(elementId: string): boolean {\r\n return this.htmlContent.has(elementId);\r\n }\r\n\r\n resetHtmlContent(elementId: string): void {\r\n this.htmlContent.delete(elementId);\r\n this.lastSyncedVersion.delete(elementId);\r\n this.lastSyncedZIndex.delete(elementId);\r\n const node = this.domNodes.get(elementId);\r\n if (!node) return;\r\n while (node.firstChild) {\r\n node.removeChild(node.firstChild);\r\n }\r\n delete node.dataset['initialized'];\r\n }\r\n\r\n syncDomNode(element: CanvasElement, zIndex = 0): 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 } else if (this.getVersion) {\r\n const currentVersion = this.getVersion(element.id);\r\n const lastVersion = this.lastSyncedVersion.get(element.id);\r\n const lastZ = this.lastSyncedZIndex.get(element.id);\r\n if (lastVersion === currentVersion && lastZ === zIndex) {\r\n return;\r\n }\r\n }\r\n\r\n if (this.getVersion) {\r\n this.lastSyncedVersion.set(element.id, this.getVersion(element.id));\r\n this.lastSyncedZIndex.set(element.id, zIndex);\r\n }\r\n\r\n const size = 'size' in element ? element.size : null;\r\n Object.assign(node.style, {\r\n display: 'block',\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 zIndex: String(zIndex),\r\n transform: element.rotation ? `rotate(${element.rotation}rad)` : '',\r\n transformOrigin: '50% 50%',\r\n });\r\n\r\n this.renderDomContent(node, element);\r\n }\r\n\r\n hideDomNode(id: string): void {\r\n const node = this.domNodes.get(id);\r\n if (node) node.style.display = 'none';\r\n }\r\n\r\n removeDomNode(id: string): void {\r\n this.htmlContent.delete(id);\r\n this.lastSyncedVersion.delete(id);\r\n this.lastSyncedZIndex.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 }\r\n\r\n clearDomNodes(): void {\r\n this.domNodes.forEach((node) => node.remove());\r\n this.domNodes.clear();\r\n this.htmlContent.clear();\r\n this.lastSyncedVersion.clear();\r\n this.lastSyncedZIndex.clear();\r\n }\r\n\r\n reattachHtmlContent(store: ElementStore): void {\r\n for (const el of store.getElementsByType('html')) {\r\n if (el.domId) {\r\n const dom = document.getElementById(el.domId);\r\n if (dom) {\r\n this.htmlContent.set(el.id, dom);\r\n }\r\n }\r\n }\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 color: element.textColor,\r\n padding: '8px',\r\n borderRadius: '4px',\r\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\r\n fontSize: `${element.fontSize ?? DEFAULT_NOTE_FONT_SIZE}px`,\r\n overflow: 'hidden',\r\n cursor: 'default',\r\n userSelect: 'none',\r\n wordWrap: 'break-word',\r\n });\r\n node.innerHTML = element.text || '';\r\n\r\n // One-time per node: this pointerup/double-tap listener is attached once (guarded by\r\n // `initialized`) for note/text nodes and is GC'd with the node — no teardown.\r\n // `resetHtmlContent()` (the only path clearing `initialized`) is html-only, and the html\r\n // init branch attaches no listener, so re-init is safe. INVARIANT: never call\r\n // resetHtmlContent on a note/text node, and if you add a listener to the html init branch,\r\n // add matching teardown in resetHtmlContent — else a second listener would stack.\r\n const detector = new DoubleTapDetector();\r\n node.addEventListener('pointerup', (e) => {\r\n if (detector.feed(e)) {\r\n e.stopPropagation();\r\n const id = node.dataset['elementId'];\r\n if (id) this.onEditRequest(id);\r\n }\r\n });\r\n }\r\n\r\n if (!this.isEditingElement(element.id)) {\r\n const text = element.text || '';\r\n if (node.innerHTML !== text) {\r\n node.innerHTML = text;\r\n }\r\n node.style.backgroundColor = element.backgroundColor;\r\n node.style.color = element.textColor;\r\n node.style.fontSize = `${element.fontSize ?? DEFAULT_NOTE_FONT_SIZE}px`;\r\n }\r\n }\r\n\r\n if (element.type === 'html') {\r\n if (!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: element.interactive ? 'auto' : 'none',\r\n });\r\n node.appendChild(content);\r\n }\r\n } else {\r\n node.style.pointerEvents = element.interactive ? 'auto' : 'none';\r\n }\r\n }\r\n\r\n if (element.type === 'text') {\r\n if (!node.dataset['initialized']) {\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n padding: '2px',\r\n fontSize: `${element.fontSize}px`,\r\n color: element.color,\r\n textAlign: element.textAlign,\r\n background: 'none',\r\n border: 'none',\r\n boxShadow: 'none',\r\n overflow: 'visible',\r\n cursor: 'default',\r\n userSelect: 'none',\r\n wordWrap: 'break-word',\r\n whiteSpace: 'pre-wrap',\r\n lineHeight: '1.4',\r\n });\r\n node.textContent = element.text || '';\r\n\r\n // One-time per node; see the note branch above for the one-listener-per-node invariant.\r\n const detector = new DoubleTapDetector();\r\n node.addEventListener('pointerup', (e) => {\r\n if (detector.feed(e)) {\r\n e.stopPropagation();\r\n const id = node.dataset['elementId'];\r\n if (id) this.onEditRequest(id);\r\n }\r\n });\r\n }\r\n\r\n if (!this.isEditingElement(element.id)) {\r\n if (node.textContent !== element.text) {\r\n node.textContent = element.text || '';\r\n }\r\n Object.assign(node.style, {\r\n fontSize: `${element.fontSize}px`,\r\n color: element.color,\r\n textAlign: element.textAlign,\r\n });\r\n }\r\n }\r\n }\r\n}\r\n","const SAMPLE_SIZE = 60;\r\n\r\nexport interface RenderStatsSnapshot {\r\n fps: number;\r\n avgFrameMs: number;\r\n p95FrameMs: number;\r\n lastFrameMs: number;\r\n lastGridMs: number;\r\n layersMs: number;\r\n backgroundMs: number;\r\n compositeMs: number;\r\n overlayMs: number;\r\n frameCount: number;\r\n}\r\n\r\ninterface FrameBreakdown {\r\n gridMs?: number;\r\n layersMs?: number;\r\n backgroundMs?: number;\r\n compositeMs?: number;\r\n overlayMs?: number;\r\n}\r\n\r\nexport class RenderStats {\r\n private frameTimes: number[] = [];\r\n private frameCount = 0;\r\n private _lastGridMs = 0;\r\n private _lastLayersMs = 0;\r\n private _lastBackgroundMs = 0;\r\n private _lastCompositeMs = 0;\r\n private _lastOverlayMs = 0;\r\n\r\n recordFrame(durationMs: number, breakdown?: FrameBreakdown): void {\r\n this.frameCount++;\r\n this.frameTimes.push(durationMs);\r\n if (this.frameTimes.length > SAMPLE_SIZE) {\r\n this.frameTimes.shift();\r\n }\r\n if (breakdown !== undefined) {\r\n if (breakdown.gridMs !== undefined) this._lastGridMs = breakdown.gridMs;\r\n if (breakdown.layersMs !== undefined) this._lastLayersMs = breakdown.layersMs;\r\n if (breakdown.backgroundMs !== undefined) this._lastBackgroundMs = breakdown.backgroundMs;\r\n if (breakdown.compositeMs !== undefined) this._lastCompositeMs = breakdown.compositeMs;\r\n if (breakdown.overlayMs !== undefined) this._lastOverlayMs = breakdown.overlayMs;\r\n }\r\n }\r\n\r\n getSnapshot(): RenderStatsSnapshot {\r\n const times = this.frameTimes;\r\n if (times.length === 0) {\r\n return {\r\n fps: 0,\r\n avgFrameMs: 0,\r\n p95FrameMs: 0,\r\n lastFrameMs: 0,\r\n lastGridMs: 0,\r\n layersMs: 0,\r\n backgroundMs: 0,\r\n compositeMs: 0,\r\n overlayMs: 0,\r\n frameCount: 0,\r\n };\r\n }\r\n\r\n const avg = times.reduce((a, b) => a + b, 0) / times.length;\r\n const sorted = [...times].sort((a, b) => a - b);\r\n const p95Index = Math.min(Math.floor(sorted.length * 0.95), sorted.length - 1);\r\n const lastFrame = times[times.length - 1] ?? 0;\r\n\r\n return {\r\n fps: avg > 0 ? Math.round(1000 / avg) : 0,\r\n avgFrameMs: Math.round(avg * 100) / 100,\r\n p95FrameMs: Math.round((sorted[p95Index] ?? 0) * 100) / 100,\r\n lastFrameMs: Math.round(lastFrame * 100) / 100,\r\n lastGridMs: Math.round(this._lastGridMs * 100) / 100,\r\n layersMs: Math.round(this._lastLayersMs * 100) / 100,\r\n backgroundMs: Math.round(this._lastBackgroundMs * 100) / 100,\r\n compositeMs: Math.round(this._lastCompositeMs * 100) / 100,\r\n overlayMs: Math.round(this._lastOverlayMs * 100) / 100,\r\n frameCount: this.frameCount,\r\n };\r\n }\r\n\r\n reset(): void {\r\n this.frameTimes = [];\r\n this.frameCount = 0;\r\n }\r\n}\r\n","import type { Camera } from './camera';\r\nimport type { Background } from './background';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { ElementRenderer } from '../elements/element-renderer';\r\nimport type { ToolManager } from '../tools/tool-manager';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport type { DomNodeManager } from './dom-node-manager';\r\nimport type { LayerCache } from './layer-cache';\r\nimport type { MarginViewport } from './margin-viewport';\r\nimport type { Bounds } from '../core/types';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { getElementBounds, boundsIntersect } from '../elements/element-bounds';\r\nimport { RenderStats } from './render-stats';\r\nimport type { RenderStatsSnapshot } from './render-stats';\r\n\r\nexport interface RenderLoopDeps {\r\n canvasEl: HTMLCanvasElement;\r\n camera: Camera;\r\n background: Background;\r\n store: ElementStore;\r\n renderer: ElementRenderer;\r\n toolManager: ToolManager;\r\n layerManager: LayerManager;\r\n domNodeManager: DomNodeManager;\r\n layerCache: LayerCache;\r\n marginViewport: MarginViewport;\r\n}\r\n\r\nexport class RenderLoop {\r\n private needsRender = false;\r\n private animFrameId = 0;\r\n private readonly canvasEl: HTMLCanvasElement;\r\n private readonly camera: Camera;\r\n private readonly background: Background;\r\n private readonly store: ElementStore;\r\n private readonly renderer: ElementRenderer;\r\n private readonly toolManager: ToolManager;\r\n private readonly layerManager: LayerManager;\r\n private readonly domNodeManager: DomNodeManager;\r\n private readonly layerCache: LayerCache;\r\n private readonly marginViewport: MarginViewport;\r\n private activeDrawingLayerId: string | null = null;\r\n private gridCacheDirty = true; // set on recenter/viewport-change; consumed by the grid block\r\n private readonly stats = new RenderStats();\r\n private layerGroups = new Map<string, CanvasElement[]>();\r\n private gridCacheCanvas: HTMLCanvasElement | null = null;\r\n private gridCacheCtx: CanvasRenderingContext2D | null = null;\r\n private lastGridRef: unknown = null;\r\n\r\n constructor(deps: RenderLoopDeps) {\r\n this.canvasEl = deps.canvasEl;\r\n this.camera = deps.camera;\r\n this.background = deps.background;\r\n this.store = deps.store;\r\n this.renderer = deps.renderer;\r\n this.toolManager = deps.toolManager;\r\n this.layerManager = deps.layerManager;\r\n this.domNodeManager = deps.domNodeManager;\r\n this.layerCache = deps.layerCache;\r\n this.marginViewport = deps.marginViewport;\r\n }\r\n\r\n requestRender(): void {\r\n this.needsRender = true;\r\n }\r\n\r\n flush(): void {\r\n if (this.needsRender) {\r\n this.render();\r\n this.needsRender = false;\r\n }\r\n }\r\n\r\n start(): 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 stop(): void {\r\n cancelAnimationFrame(this.animFrameId);\r\n }\r\n\r\n setCanvasSize(width: number, height: number): void {\r\n this.canvasEl.width = width;\r\n this.canvasEl.height = height;\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n this.marginViewport.setViewport(width / dpr, height / dpr, dpr);\r\n this.layerCache.resize();\r\n }\r\n\r\n setActiveDrawingLayer(layerId: string | null): void {\r\n this.activeDrawingLayerId = layerId;\r\n }\r\n\r\n markLayerDirty(layerId: string): void {\r\n this.layerCache.markDirty(layerId);\r\n }\r\n\r\n markAllLayersDirty(): void {\r\n this.layerCache.markAllDirty();\r\n }\r\n\r\n getStats(): RenderStatsSnapshot {\r\n return this.stats.getSnapshot();\r\n }\r\n\r\n private compositeLayerCache(ctx: CanvasRenderingContext2D, layerId: string): void {\r\n const cached = this.layerCache.getCanvas(layerId);\r\n const offset = this.marginViewport.compositeOffset(\r\n this.camera.position.x,\r\n this.camera.position.y,\r\n );\r\n ctx.save();\r\n ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n ctx.drawImage(cached as CanvasImageSource, offset.x, offset.y);\r\n ctx.restore();\r\n }\r\n\r\n private ensureGridCache(): void {\r\n const w = this.marginViewport.physicalWidth();\r\n const h = this.marginViewport.physicalHeight();\r\n if (\r\n this.gridCacheCanvas !== null &&\r\n this.gridCacheCanvas.width === w &&\r\n this.gridCacheCanvas.height === h\r\n ) {\r\n return;\r\n }\r\n\r\n if (typeof OffscreenCanvas !== 'undefined') {\r\n this.gridCacheCanvas = new OffscreenCanvas(w, h) as unknown as HTMLCanvasElement;\r\n } else if (typeof document !== 'undefined') {\r\n const el = document.createElement('canvas');\r\n el.width = w;\r\n el.height = h;\r\n this.gridCacheCanvas = el;\r\n } else {\r\n this.gridCacheCanvas = null;\r\n this.gridCacheCtx = null;\r\n return;\r\n }\r\n\r\n this.gridCacheCtx = this.gridCacheCanvas.getContext('2d') as CanvasRenderingContext2D | null;\r\n }\r\n\r\n private render(): void {\r\n const t0 = performance.now();\r\n const ctx = this.canvasEl.getContext('2d');\r\n if (!ctx) return;\r\n\r\n let layersMs = 0;\r\n let compositeMs = 0;\r\n let gridMs = 0;\r\n\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n const cssWidth = this.canvasEl.clientWidth;\r\n const cssHeight = this.canvasEl.clientHeight;\r\n\r\n // idempotent; catches resizes that bypass setCanvasSize\r\n this.marginViewport.setViewport(cssWidth, cssHeight, dpr);\r\n\r\n const currentZoom = this.camera.zoom;\r\n const currentCamX = this.camera.position.x;\r\n const currentCamY = this.camera.position.y;\r\n if (this.marginViewport.needsRecenter(currentCamX, currentCamY, currentZoom)) {\r\n this.marginViewport.recenter(currentCamX, currentCamY, currentZoom);\r\n this.layerCache.markAllDirty();\r\n this.gridCacheDirty = true;\r\n }\r\n\r\n ctx.save();\r\n ctx.scale(dpr, dpr);\r\n\r\n this.renderer.setCanvasSize(cssWidth, cssHeight);\r\n const hasGridElement = this.store.getElementsByType('grid').length > 0;\r\n const bgT0 = performance.now();\r\n if (hasGridElement) {\r\n ctx.save();\r\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n ctx.clearRect(0, 0, cssWidth, cssHeight);\r\n ctx.restore();\r\n } else {\r\n this.background.render(ctx, this.camera);\r\n }\r\n const backgroundMs = performance.now() - bgT0;\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 const cullBounds = this.marginViewport.cachedWorldBounds();\r\n const cullPad = Math.max(cullBounds.w, cullBounds.h) * 0.05;\r\n const cullingRect: Bounds = {\r\n x: cullBounds.x - cullPad,\r\n y: cullBounds.y - cullPad,\r\n w: cullBounds.w + cullPad * 2,\r\n h: cullBounds.h + cullPad * 2,\r\n };\r\n\r\n const allElements = this.store.getAll();\r\n this.layerGroups.clear();\r\n const gridElements: CanvasElement[] = [];\r\n let domZIndex = 0;\r\n\r\n for (const element of allElements) {\r\n if (!this.layerManager.isLayerVisible(element.layerId)) {\r\n if (this.renderer.isDomElement(element)) {\r\n this.domNodeManager.hideDomNode(element.id);\r\n }\r\n continue;\r\n }\r\n\r\n if (this.renderer.isDomElement(element)) {\r\n const elBounds = getElementBounds(element);\r\n if (elBounds && !boundsIntersect(elBounds, cullingRect)) {\r\n this.domNodeManager.hideDomNode(element.id);\r\n } else {\r\n this.domNodeManager.syncDomNode(element, domZIndex++);\r\n }\r\n continue;\r\n }\r\n\r\n // Grids are viewport-filling; handled via anchored cache below\r\n if (element.type === 'grid') {\r\n gridElements.push(element);\r\n continue;\r\n }\r\n\r\n let group = this.layerGroups.get(element.layerId);\r\n if (!group) {\r\n group = [];\r\n this.layerGroups.set(element.layerId, group);\r\n }\r\n group.push(element);\r\n }\r\n\r\n for (const [layerId, elements] of this.layerGroups) {\r\n const isActiveDrawingLayer = layerId === this.activeDrawingLayerId;\r\n\r\n if (!this.layerCache.isDirty(layerId)) {\r\n const compT0 = performance.now();\r\n this.compositeLayerCache(ctx, layerId);\r\n compositeMs += performance.now() - compT0;\r\n continue;\r\n }\r\n\r\n if (isActiveDrawingLayer) {\r\n const compT0 = performance.now();\r\n this.compositeLayerCache(ctx, layerId);\r\n compositeMs += performance.now() - compT0;\r\n continue;\r\n }\r\n\r\n const offCtx = this.layerCache.getContext(layerId);\r\n if (offCtx) {\r\n const layerT0 = performance.now();\r\n const offCanvas = this.layerCache.getCanvas(layerId);\r\n offCtx.clearRect(0, 0, offCanvas.width, offCanvas.height);\r\n offCtx.save();\r\n this.marginViewport.applyRenderTransform(offCtx);\r\n for (const element of elements) {\r\n const elBounds = getElementBounds(element);\r\n if (elBounds && !boundsIntersect(elBounds, cullingRect)) continue;\r\n this.renderer.renderCanvasElement(offCtx as CanvasRenderingContext2D, element);\r\n }\r\n offCtx.restore();\r\n this.layerCache.markClean(layerId);\r\n layersMs += performance.now() - layerT0;\r\n\r\n const compT0 = performance.now();\r\n this.compositeLayerCache(ctx, layerId);\r\n compositeMs += performance.now() - compT0;\r\n }\r\n }\r\n\r\n // Render grids on top of layer elements\r\n if (gridElements.length > 0) {\r\n const gridT0 = performance.now();\r\n const gridRef = gridElements[0];\r\n const gridDirty = this.gridCacheDirty || gridRef !== this.lastGridRef;\r\n\r\n if (gridDirty) {\r\n this.ensureGridCache();\r\n if (this.gridCacheCtx && this.gridCacheCanvas) {\r\n const cb = this.marginViewport.cachedWorldBounds();\r\n this.renderer.setGridBoundsOverride({\r\n minX: cb.x,\r\n minY: cb.y,\r\n maxX: cb.x + cb.w,\r\n maxY: cb.y + cb.h,\r\n });\r\n const gc = this.gridCacheCtx;\r\n gc.clearRect(0, 0, this.gridCacheCanvas.width, this.gridCacheCanvas.height);\r\n gc.save();\r\n this.marginViewport.applyRenderTransform(gc);\r\n try {\r\n for (const grid of gridElements) {\r\n this.renderer.renderCanvasElement(gc as CanvasRenderingContext2D, grid);\r\n }\r\n } finally {\r\n gc.restore();\r\n this.renderer.setGridBoundsOverride(null);\r\n }\r\n }\r\n this.gridCacheDirty = false;\r\n this.lastGridRef = gridRef;\r\n }\r\n\r\n if (this.gridCacheCanvas) {\r\n const offset = this.marginViewport.compositeOffset(\r\n this.camera.position.x,\r\n this.camera.position.y,\r\n );\r\n ctx.save();\r\n ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n ctx.drawImage(this.gridCacheCanvas as CanvasImageSource, offset.x, offset.y);\r\n ctx.restore();\r\n } else {\r\n for (const grid of gridElements) {\r\n this.renderer.renderCanvasElement(ctx, grid);\r\n }\r\n }\r\n gridMs = performance.now() - gridT0;\r\n }\r\n\r\n const overlayT0 = performance.now();\r\n const activeTool = this.toolManager.activeTool;\r\n if (activeTool?.renderOverlay) {\r\n activeTool.renderOverlay(ctx);\r\n }\r\n const overlayMs = performance.now() - overlayT0;\r\n\r\n ctx.restore();\r\n ctx.restore();\r\n\r\n this.stats.recordFrame(performance.now() - t0, {\r\n gridMs,\r\n layersMs,\r\n backgroundMs,\r\n compositeMs,\r\n overlayMs,\r\n });\r\n }\r\n}\r\n","import type { MarginViewport } from './margin-viewport';\r\n\r\nfunction createOffscreenCanvas(width: number, height: number): HTMLCanvasElement | OffscreenCanvas {\r\n if (typeof OffscreenCanvas !== 'undefined') {\r\n return new OffscreenCanvas(width, height);\r\n }\r\n const canvas = document.createElement('canvas');\r\n canvas.width = width;\r\n canvas.height = height;\r\n return canvas;\r\n}\r\n\r\nexport class LayerCache {\r\n private canvases = new Map<string, HTMLCanvasElement | OffscreenCanvas>();\r\n private dirtyFlags = new Map<string, boolean>();\r\n\r\n constructor(private readonly viewport: MarginViewport) {}\r\n\r\n isDirty(layerId: string): boolean {\r\n return this.dirtyFlags.get(layerId) !== false;\r\n }\r\n\r\n markDirty(layerId: string): void {\r\n this.dirtyFlags.set(layerId, true);\r\n }\r\n\r\n markClean(layerId: string): void {\r\n this.dirtyFlags.set(layerId, false);\r\n }\r\n\r\n markAllDirty(): void {\r\n for (const [id] of this.dirtyFlags) {\r\n this.dirtyFlags.set(id, true);\r\n }\r\n }\r\n\r\n getCanvas(layerId: string): HTMLCanvasElement | OffscreenCanvas {\r\n let canvas = this.canvases.get(layerId);\r\n if (!canvas) {\r\n canvas = createOffscreenCanvas(this.viewport.physicalWidth(), this.viewport.physicalHeight());\r\n this.canvases.set(layerId, canvas);\r\n this.dirtyFlags.set(layerId, true);\r\n }\r\n return canvas;\r\n }\r\n\r\n getContext(layerId: string): CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null {\r\n const canvas = this.getCanvas(layerId);\r\n return canvas.getContext('2d') as\r\n | CanvasRenderingContext2D\r\n | OffscreenCanvasRenderingContext2D\r\n | null;\r\n }\r\n\r\n resize(): void {\r\n const w = this.viewport.physicalWidth();\r\n const h = this.viewport.physicalHeight();\r\n for (const [id, canvas] of this.canvases) {\r\n canvas.width = w;\r\n canvas.height = h;\r\n this.dirtyFlags.set(id, true);\r\n }\r\n }\r\n\r\n clear(): void {\r\n this.canvases.clear();\r\n this.dirtyFlags.clear();\r\n }\r\n}\r\n","import type { Bounds } from '../core/types';\r\n\r\n/**\r\n * Owns the cache anchor (the camera state the screen-space caches were last rendered at)\r\n * and the margin geometry. Pure — holds no canvas. Caches render a region inflated by\r\n * `marginPx` on every side, so a pan within the margin is an offset-blit, not a re-raster.\r\n *\r\n * Call setViewport(cssW, cssH, dpr) before physicalWidth/Height, applyRenderTransform, or compositeOffset — they read the stored dpr.\r\n */\r\nexport class MarginViewport {\r\n private cssW = 0;\r\n private cssH = 0;\r\n private dpr = 1;\r\n private anchorCamX = 0;\r\n private anchorCamY = 0;\r\n private anchorZoom = Number.NaN; // sentinel → first needsRecenter is true\r\n private viewportDirty = true;\r\n\r\n constructor(private marginPx: number) {}\r\n\r\n setMargin(marginPx: number): void {\r\n if (marginPx !== this.marginPx) {\r\n this.marginPx = marginPx;\r\n this.viewportDirty = true;\r\n }\r\n }\r\n\r\n setViewport(cssW: number, cssH: number, dpr: number): void {\r\n if (cssW !== this.cssW || cssH !== this.cssH || dpr !== this.dpr) {\r\n this.cssW = cssW;\r\n this.cssH = cssH;\r\n this.dpr = dpr;\r\n this.viewportDirty = true;\r\n }\r\n }\r\n\r\n physicalWidth(): number {\r\n return Math.round((this.cssW + 2 * this.marginPx) * this.dpr);\r\n }\r\n\r\n physicalHeight(): number {\r\n return Math.round((this.cssH + 2 * this.marginPx) * this.dpr);\r\n }\r\n\r\n needsRecenter(camX: number, camY: number, zoom: number): boolean {\r\n return (\r\n this.viewportDirty ||\r\n zoom !== this.anchorZoom ||\r\n Math.abs(camX - this.anchorCamX) > this.marginPx ||\r\n Math.abs(camY - this.anchorCamY) > this.marginPx\r\n );\r\n }\r\n\r\n recenter(camX: number, camY: number, zoom: number): void {\r\n this.anchorCamX = camX;\r\n this.anchorCamY = camY;\r\n this.anchorZoom = zoom;\r\n this.viewportDirty = false;\r\n }\r\n\r\n /** Applies dpr scale + anchor-relative world transform. setViewport must have been called first. */\r\n applyRenderTransform(ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D): void {\r\n ctx.scale(this.dpr, this.dpr);\r\n ctx.translate(this.marginPx + this.anchorCamX, this.marginPx + this.anchorCamY);\r\n ctx.scale(this.anchorZoom, this.anchorZoom);\r\n }\r\n\r\n // Device-px destination for drawImage(cache, x, y).\r\n // A world point P sits in the cache at CSS x `margin + anchorCamX + P*zoom`; it must land on\r\n // screen at `camX + P*zoom`; so the blit offset is `camX - anchorCamX - margin` (CSS) * dpr.\r\n compositeOffset(camX: number, camY: number): { x: number; y: number } {\r\n return {\r\n x: (camX - this.anchorCamX - this.marginPx) * this.dpr,\r\n y: (camY - this.anchorCamY - this.marginPx) * this.dpr,\r\n };\r\n }\r\n\r\n // World-space bounds of the whole cached region at the anchor (cull rect for re-renders).\r\n cachedWorldBounds(): Bounds {\r\n const z = this.anchorZoom;\r\n return {\r\n x: (-this.marginPx - this.anchorCamX) / z,\r\n y: (-this.marginPx - this.anchorCamY) / z,\r\n w: (this.cssW + 2 * this.marginPx) / z,\r\n h: (this.cssH + 2 * this.marginPx) / z,\r\n };\r\n }\r\n}\r\n","import type { CanvasElement } from './types';\r\n\r\n/** Patch that translates an element by (dx, dy). Arrows move position + from + to;\r\n * every other type moves position only (strokes carry points relative to position). */\r\nexport function translateElementPatch(\r\n el: CanvasElement,\r\n dx: number,\r\n dy: number,\r\n): Partial<CanvasElement> {\r\n const position = { x: el.position.x + dx, y: el.position.y + dy };\r\n if (el.type === 'arrow') {\r\n return {\r\n position,\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 }\r\n return { position };\r\n}\r\n","import type { CanvasElement } from './types';\r\n\r\nexport interface ElementStyle {\r\n color?: string;\r\n fillColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n fontSize?: number;\r\n}\r\n\r\nexport function styleToPatch(element: CanvasElement, style: ElementStyle): Partial<CanvasElement> {\r\n const { color, fillColor, strokeWidth, opacity, fontSize } = style;\r\n switch (element.type) {\r\n case 'stroke':\r\n return {\r\n ...(color !== undefined ? { color } : {}),\r\n ...(strokeWidth !== undefined ? { width: strokeWidth } : {}),\r\n ...(opacity !== undefined ? { opacity } : {}),\r\n };\r\n case 'arrow':\r\n return {\r\n ...(color !== undefined ? { color } : {}),\r\n ...(strokeWidth !== undefined ? { width: strokeWidth } : {}),\r\n };\r\n case 'shape':\r\n return {\r\n ...(color !== undefined ? { strokeColor: color } : {}),\r\n ...(fillColor !== undefined ? { fillColor } : {}),\r\n ...(strokeWidth !== undefined ? { strokeWidth } : {}),\r\n };\r\n case 'text':\r\n return {\r\n ...(color !== undefined ? { color } : {}),\r\n ...(fontSize !== undefined ? { fontSize } : {}),\r\n };\r\n case 'note':\r\n return {\r\n ...(color !== undefined ? { textColor: color } : {}),\r\n ...(fillColor !== undefined ? { backgroundColor: fillColor } : {}),\r\n ...(fontSize !== undefined ? { fontSize } : {}),\r\n };\r\n case 'grid':\r\n return {\r\n ...(color !== undefined ? { strokeColor: color } : {}),\r\n ...(strokeWidth !== undefined ? { strokeWidth } : {}),\r\n ...(opacity !== undefined ? { opacity } : {}),\r\n };\r\n case 'template':\r\n return {\r\n ...(color !== undefined ? { strokeColor: color } : {}),\r\n ...(fillColor !== undefined ? { fillColor } : {}),\r\n ...(strokeWidth !== undefined ? { strokeWidth } : {}),\r\n ...(opacity !== undefined ? { opacity } : {}),\r\n };\r\n default:\r\n return {};\r\n }\r\n}\r\n\r\nexport function getElementStyle(element: CanvasElement): ElementStyle {\r\n switch (element.type) {\r\n case 'stroke':\r\n return { color: element.color, strokeWidth: element.width, opacity: element.opacity };\r\n case 'arrow':\r\n return { color: element.color, strokeWidth: element.width };\r\n case 'shape':\r\n return {\r\n color: element.strokeColor,\r\n fillColor: element.fillColor,\r\n strokeWidth: element.strokeWidth,\r\n };\r\n case 'text':\r\n return { color: element.color, fontSize: element.fontSize };\r\n case 'note':\r\n return {\r\n color: element.textColor,\r\n fillColor: element.backgroundColor,\r\n ...(element.fontSize !== undefined ? { fontSize: element.fontSize } : {}),\r\n };\r\n case 'grid':\r\n return {\r\n color: element.strokeColor,\r\n strokeWidth: element.strokeWidth,\r\n opacity: element.opacity,\r\n };\r\n case 'template':\r\n return {\r\n color: element.strokeColor,\r\n fillColor: element.fillColor,\r\n strokeWidth: element.strokeWidth,\r\n opacity: element.opacity,\r\n };\r\n default:\r\n return {};\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport { updateArrowsBoundToElements } from '../elements/arrow-binding';\r\nimport { translateElementPatch } from '../elements/translate';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { createId } from '../elements/create-id';\r\nimport { styleToPatch, getElementStyle } from '../elements/element-style';\r\nimport type { ElementStyle } from '../elements/element-style';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport type { Bounds } from '../core/types';\r\n\r\nexport type AlignEdge = 'left' | 'center-x' | 'right' | 'top' | 'middle' | 'bottom';\r\nexport type DistributeAxis = 'horizontal' | 'vertical';\r\n\r\nfunction unionBounds(list: Bounds[]): Bounds {\r\n let minX = Infinity,\r\n minY = Infinity,\r\n maxX = -Infinity,\r\n maxY = -Infinity;\r\n for (const b of list) {\r\n minX = Math.min(minX, b.x);\r\n minY = Math.min(minY, b.y);\r\n maxX = Math.max(maxX, b.x + b.w);\r\n maxY = Math.max(maxY, b.y + b.h);\r\n }\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n\r\nfunction sharedValue<T>(values: (T | undefined)[]): T | undefined {\r\n const present = values.filter((v): v is T => v !== undefined);\r\n if (present.length === 0) return undefined;\r\n const first = present[0];\r\n return present.every((v) => v === first) ? first : undefined;\r\n}\r\n\r\nexport interface SelectionOpsDeps {\r\n store: ElementStore;\r\n recorder: HistoryRecorder;\r\n getSelectedIds: () => string[];\r\n requestRender: () => void;\r\n}\r\n\r\nexport class SelectionOps {\r\n constructor(private readonly deps: SelectionOpsDeps) {}\r\n\r\n getStyle(): ElementStyle | null {\r\n const ids = this.deps.getSelectedIds();\r\n if (ids.length === 0) return null;\r\n const styles: ElementStyle[] = [];\r\n for (const id of ids) {\r\n const el = this.deps.store.getById(id);\r\n if (el) styles.push(getElementStyle(el));\r\n }\r\n if (styles.length === 0) return null;\r\n const result: ElementStyle = {};\r\n const color = sharedValue(styles.map((s) => s.color));\r\n if (color !== undefined) result.color = color;\r\n const fillColor = sharedValue(styles.map((s) => s.fillColor));\r\n if (fillColor !== undefined) result.fillColor = fillColor;\r\n const strokeWidth = sharedValue(styles.map((s) => s.strokeWidth));\r\n if (strokeWidth !== undefined) result.strokeWidth = strokeWidth;\r\n const opacity = sharedValue(styles.map((s) => s.opacity));\r\n if (opacity !== undefined) result.opacity = opacity;\r\n const fontSize = sharedValue(styles.map((s) => s.fontSize));\r\n if (fontSize !== undefined) result.fontSize = fontSize;\r\n return result;\r\n }\r\n\r\n applyStyle(style: ElementStyle): void {\r\n const ids = this.deps.getSelectedIds();\r\n if (ids.length === 0) return;\r\n this.deps.recorder.begin();\r\n for (const id of ids) {\r\n const el = this.deps.store.getById(id);\r\n if (!el) continue;\r\n const patch = styleToPatch(el, style);\r\n if (Object.keys(patch).length > 0) {\r\n this.deps.store.update(id, patch);\r\n }\r\n }\r\n this.deps.recorder.commit();\r\n }\r\n\r\n group(): void {\r\n const ids = this.deps.getSelectedIds();\r\n if (ids.length < 2) return;\r\n const groupId = createId('group');\r\n this.deps.recorder.begin();\r\n for (const id of ids) {\r\n if (this.deps.store.getById(id)) this.deps.store.update(id, { groupId });\r\n }\r\n this.deps.recorder.commit();\r\n }\r\n\r\n ungroup(): void {\r\n const ids = this.deps.getSelectedIds();\r\n if (ids.length === 0) return;\r\n this.deps.recorder.begin();\r\n for (const id of ids) {\r\n const el = this.deps.store.getById(id);\r\n if (el && el.groupId !== undefined) this.deps.store.update(id, { groupId: undefined });\r\n }\r\n this.deps.recorder.commit();\r\n }\r\n\r\n toggleLock(): void {\r\n const ids = this.deps.getSelectedIds();\r\n if (ids.length === 0) return;\r\n const anyUnlocked = ids.some((id) => {\r\n const el = this.deps.store.getById(id);\r\n return el ? !el.locked : false;\r\n });\r\n this.deps.recorder.begin();\r\n for (const id of ids) {\r\n const el = this.deps.store.getById(id);\r\n if (el && el.locked !== anyUnlocked) this.deps.store.update(id, { locked: anyUnlocked });\r\n }\r\n this.deps.recorder.commit();\r\n }\r\n\r\n align(edge: AlignEdge): void {\r\n const bounded = this.boundedSelection();\r\n if (bounded.length < 2) return;\r\n const B = unionBounds(bounded.map((e) => e.bounds));\r\n this.deps.recorder.begin();\r\n const moved: string[] = [];\r\n for (const { id, el, bounds: b } of bounded) {\r\n if (!this.isMovable(el)) continue;\r\n let dx = 0;\r\n let dy = 0;\r\n switch (edge) {\r\n case 'left':\r\n dx = B.x - b.x;\r\n break;\r\n case 'right':\r\n dx = B.x + B.w - (b.x + b.w);\r\n break;\r\n case 'center-x':\r\n dx = B.x + B.w / 2 - (b.x + b.w / 2);\r\n break;\r\n case 'top':\r\n dy = B.y - b.y;\r\n break;\r\n case 'bottom':\r\n dy = B.y + B.h - (b.y + b.h);\r\n break;\r\n case 'middle':\r\n dy = B.y + B.h / 2 - (b.y + b.h / 2);\r\n break;\r\n }\r\n if (dx === 0 && dy === 0) continue;\r\n this.deps.store.update(id, translateElementPatch(el, dx, dy));\r\n moved.push(id);\r\n }\r\n updateArrowsBoundToElements(moved, this.deps.store);\r\n this.deps.recorder.commit();\r\n this.deps.requestRender();\r\n }\r\n\r\n distribute(axis: DistributeAxis): void {\r\n const bounded = this.boundedSelection();\r\n if (bounded.length < 3) return;\r\n const center = (b: Bounds) => (axis === 'horizontal' ? b.x + b.w / 2 : b.y + b.h / 2);\r\n const sorted = [...bounded].sort((p, q) => center(p.bounds) - center(q.bounds));\r\n const first = sorted[0];\r\n const last = sorted[sorted.length - 1];\r\n if (!first || !last) return;\r\n const c0 = center(first.bounds);\r\n const cN = center(last.bounds);\r\n const n = sorted.length;\r\n this.deps.recorder.begin();\r\n const moved: string[] = [];\r\n for (let i = 1; i < n - 1; i++) {\r\n const item = sorted[i];\r\n if (!item || !this.isMovable(item.el)) continue;\r\n const target = c0 + (i * (cN - c0)) / (n - 1);\r\n const delta = target - center(item.bounds);\r\n if (delta === 0) continue;\r\n const [dx, dy] = axis === 'horizontal' ? [delta, 0] : [0, delta];\r\n this.deps.store.update(item.id, translateElementPatch(item.el, dx, dy));\r\n moved.push(item.id);\r\n }\r\n updateArrowsBoundToElements(moved, this.deps.store);\r\n this.deps.recorder.commit();\r\n this.deps.requestRender();\r\n }\r\n\r\n private boundedSelection(): { id: string; el: CanvasElement; bounds: Bounds }[] {\r\n const out: { id: string; el: CanvasElement; bounds: Bounds }[] = [];\r\n for (const id of this.deps.getSelectedIds()) {\r\n const el = this.deps.store.getById(id);\r\n if (!el) continue;\r\n const bounds = getElementBounds(el);\r\n if (bounds) out.push({ id, el, bounds });\r\n }\r\n return out;\r\n }\r\n\r\n private isMovable(el: CanvasElement): boolean {\r\n if (el.locked) return false;\r\n if (el.type === 'arrow' && (el.fromBinding ?? el.toBinding)) return false;\r\n return true;\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport type { ToolContext } from '../tools/types';\r\nimport type { GridElement } from '../elements/types';\r\nimport { createGrid } from '../elements/element-factory';\r\n\r\nexport interface GridInfo {\r\n gridType: 'square' | 'hex';\r\n hexOrientation: 'pointy' | 'flat';\r\n cellSize: number;\r\n cellRadius: number;\r\n}\r\n\r\nexport interface GridControllerDeps {\r\n store: ElementStore;\r\n recorder: HistoryRecorder;\r\n requestRender: () => void;\r\n getActiveLayerId: () => string;\r\n toolContext: ToolContext;\r\n defaultGridSize: number;\r\n}\r\n\r\nexport class GridController {\r\n private readonly listeners = new Set<(info: GridInfo | null) => void>();\r\n\r\n constructor(private readonly deps: GridControllerDeps) {}\r\n\r\n add(input: {\r\n gridType?: 'square' | 'hex';\r\n hexOrientation?: 'pointy' | 'flat';\r\n cellSize?: number;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n }): string {\r\n const existing = this.deps.store.getElementsByType('grid')[0];\r\n this.deps.recorder.begin();\r\n if (existing) {\r\n this.deps.store.remove(existing.id);\r\n }\r\n const grid = createGrid({ ...input, layerId: this.deps.getActiveLayerId() });\r\n this.deps.store.add(grid);\r\n this.deps.recorder.commit();\r\n this.deps.requestRender();\r\n return grid.id;\r\n }\r\n\r\n update(\r\n updates: Partial<\r\n Pick<\r\n GridElement,\r\n 'gridType' | 'hexOrientation' | 'cellSize' | 'strokeColor' | 'strokeWidth' | 'opacity'\r\n >\r\n >,\r\n ): void {\r\n const grid = this.deps.store.getElementsByType('grid')[0];\r\n if (!grid) return;\r\n this.deps.recorder.begin();\r\n this.deps.store.update(grid.id, updates);\r\n this.deps.recorder.commit();\r\n this.deps.requestRender();\r\n }\r\n\r\n remove(): void {\r\n const grid = this.deps.store.getElementsByType('grid')[0];\r\n if (!grid) return;\r\n this.deps.recorder.begin();\r\n this.deps.store.remove(grid.id);\r\n this.deps.recorder.commit();\r\n this.deps.requestRender();\r\n }\r\n\r\n getInfo(): GridInfo | null {\r\n const grid = this.deps.store.getElementsByType('grid')[0];\r\n if (!grid) return null;\r\n return {\r\n gridType: grid.gridType,\r\n hexOrientation: grid.hexOrientation,\r\n cellSize: grid.cellSize,\r\n cellRadius: grid.gridType === 'hex' ? grid.cellSize : grid.cellSize / 2,\r\n };\r\n }\r\n\r\n onChange(listener: (info: GridInfo | null) => void): () => void {\r\n this.listeners.add(listener);\r\n return () => {\r\n this.listeners.delete(listener);\r\n };\r\n }\r\n\r\n syncContext(): void {\r\n const grid = this.deps.store.getElementsByType('grid')[0];\r\n if (grid) {\r\n this.deps.toolContext.gridSize = grid.cellSize;\r\n this.deps.toolContext.gridType = grid.gridType;\r\n this.deps.toolContext.hexOrientation = grid.hexOrientation;\r\n } else {\r\n this.deps.toolContext.gridSize = this.deps.defaultGridSize;\r\n this.deps.toolContext.gridType = undefined;\r\n this.deps.toolContext.hexOrientation = undefined;\r\n }\r\n this.notify();\r\n }\r\n\r\n private notify(): void {\r\n const info = this.getInfo();\r\n for (const listener of this.listeners) {\r\n listener(info);\r\n }\r\n }\r\n}\r\n","import type { Camera } from './camera';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { ElementRenderer } from '../elements/element-renderer';\r\nimport type { NoteEditor } from '../elements/note-editor';\r\nimport type { ArrowLabelEditor } from '../elements/arrow-label-editor';\r\nimport type { InteractMode } from './interact-mode';\r\nimport type { DomNodeManager } from './dom-node-manager';\r\nimport type { RenderLoop } from './render-loop';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport type { CanvasElement, ArrowElement } from '../elements/types';\r\nimport { DoubleTapDetector } from './double-tap-detector';\r\nimport { isNearBezier } from '../elements/arrow-geometry';\r\nimport { isNoteContentEmpty } from '../elements/note-sanitizer';\r\n\r\nconst ARROW_HIT_THRESHOLD = 10;\r\n\r\nexport interface ViewportInteractionsDeps {\r\n store: ElementStore;\r\n camera: Camera;\r\n wrapper: HTMLDivElement;\r\n domLayer: HTMLDivElement;\r\n renderLoop: RenderLoop;\r\n domNodeManager: DomNodeManager;\r\n noteEditor: NoteEditor;\r\n arrowLabelEditor: ArrowLabelEditor;\r\n interactMode: InteractMode;\r\n renderer: ElementRenderer;\r\n recorder: HistoryRecorder;\r\n requestRender: () => void;\r\n addImage: (src: string, position: { x: number; y: number }) => string;\r\n dropHandler?: (event: DragEvent, worldPosition: { x: number; y: number }) => void;\r\n}\r\n\r\nexport class ViewportInteractions {\r\n private readonly doubleTapDetector = new DoubleTapDetector();\r\n private tapDownX = 0;\r\n private tapDownY = 0;\r\n\r\n constructor(private readonly deps: ViewportInteractionsDeps) {}\r\n\r\n startEditingElement(id: string): void {\r\n const element = this.deps.store.getById(id);\r\n if (!element || (element.type !== 'note' && element.type !== 'text')) return;\r\n\r\n this.deps.renderLoop.flush();\r\n\r\n const node = this.deps.domNodeManager.getNode(id);\r\n if (node) {\r\n this.deps.noteEditor.startEditing(node, id, this.deps.store);\r\n }\r\n }\r\n\r\n fitNoteHeight(elementId: string): void {\r\n const element = this.deps.store.getById(elementId);\r\n if (!element || element.type !== 'note') return;\r\n if (isNoteContentEmpty(element.text)) return;\r\n const node = this.deps.domNodeManager.getNode(elementId);\r\n if (!node) return;\r\n const measured = node.scrollHeight;\r\n if (measured > element.size.h) {\r\n this.deps.store.update(elementId, { size: { w: element.size.w, h: measured } });\r\n }\r\n }\r\n\r\n onTextEditStop(elementId: string): void {\r\n const element = this.deps.store.getById(elementId);\r\n if (!element) return;\r\n\r\n if (element.type === 'note') {\r\n if (isNoteContentEmpty(element.text)) {\r\n this.deps.store.remove(elementId);\r\n return;\r\n }\r\n this.fitNoteHeight(elementId);\r\n return;\r\n }\r\n\r\n if (element.type !== 'text') return;\r\n\r\n if (!element.text || element.text.trim() === '') {\r\n this.deps.store.remove(elementId);\r\n return;\r\n }\r\n\r\n const node = this.deps.domNodeManager.getNode(elementId);\r\n if (node && 'size' in element) {\r\n const measured = node.scrollHeight;\r\n if (measured !== element.size.h) {\r\n this.deps.store.update(elementId, { size: { w: element.size.w, h: measured } });\r\n }\r\n }\r\n }\r\n\r\n onTapDown = (e: PointerEvent): void => {\r\n this.tapDownX = e.clientX;\r\n this.tapDownY = e.clientY;\r\n };\r\n\r\n onDoubleTap = (e: PointerEvent): void => {\r\n const dx = e.clientX - this.tapDownX;\r\n const dy = e.clientY - this.tapDownY;\r\n const moved = Math.sqrt(dx * dx + dy * dy);\r\n if (moved > 10) return;\r\n\r\n if (!this.doubleTapDetector.feed(e)) return;\r\n if (typeof document.elementFromPoint !== 'function') return;\r\n\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.deps.store.getById(elementId);\r\n if (element?.type === 'note' || element?.type === 'text') {\r\n this.startEditingElement(elementId);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n const rect = this.deps.wrapper.getBoundingClientRect();\r\n const screen = { x: e.clientX - rect.left, y: e.clientY - rect.top };\r\n const world = this.deps.camera.screenToWorld(screen);\r\n\r\n // HTML embeds keep double-tap priority: you double-tapped inside the embed even if an\r\n // arrow's curve passes nearby. Arrow-label editing only when no embed is hit.\r\n const hit = this.hitTestWorld(world);\r\n if (hit?.type === 'html') {\r\n this.deps.interactMode.startInteracting(hit.id);\r\n return;\r\n }\r\n\r\n const arrow = this.findArrowAt(world);\r\n if (arrow) {\r\n this.startArrowLabelEdit(arrow);\r\n }\r\n };\r\n\r\n findArrowAt(world: { x: number; y: number }): ArrowElement | undefined {\r\n const candidates = this.deps.store.queryPoint(world).reverse();\r\n for (const el of candidates) {\r\n if (\r\n el.type === 'arrow' &&\r\n isNearBezier(world, el.from, el.to, el.bend, ARROW_HIT_THRESHOLD)\r\n ) {\r\n return el;\r\n }\r\n }\r\n return undefined;\r\n }\r\n\r\n startArrowLabelEdit(arrow: ArrowElement): void {\r\n this.deps.arrowLabelEditor.startEditing({\r\n arrow,\r\n layer: this.deps.domLayer,\r\n store: this.deps.store,\r\n recorder: this.deps.recorder,\r\n onDone: () => {\r\n this.deps.renderer.setLabelEditingId(null);\r\n this.deps.requestRender();\r\n },\r\n });\r\n // Set AFTER startEditing: starting a new edit cleans up any prior session, whose onDone\r\n // synchronously clears the editing id — so claim suppression for this arrow last.\r\n this.deps.renderer.setLabelEditingId(arrow.id);\r\n }\r\n\r\n private hitTestWorld(world: { x: number; y: number }): CanvasElement | null {\r\n const candidates = this.deps.store.queryPoint(world).reverse();\r\n for (const el of candidates) {\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 onDragOver = (e: DragEvent): void => {\r\n e.preventDefault();\r\n };\r\n\r\n onDrop = (e: DragEvent): void => {\r\n e.preventDefault();\r\n const rect = this.deps.wrapper.getBoundingClientRect();\r\n const screenPos = { x: e.clientX - rect.left, y: e.clientY - rect.top };\r\n const worldPos = this.deps.camera.screenToWorld(screenPos);\r\n\r\n if (this.deps.dropHandler) {\r\n this.deps.dropHandler(e, worldPos);\r\n return;\r\n }\r\n\r\n const files = e.dataTransfer?.files;\r\n if (!files) return;\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 this.deps.addImage(src, worldPos);\r\n };\r\n reader.readAsDataURL(file);\r\n }\r\n };\r\n}\r\n","import { Camera } from './camera';\r\nimport type { CameraOptions } from './camera';\r\nimport { InputHandler } from './input-handler';\r\nimport type { ShortcutOptions, ShortcutsApi } from './shortcut-map';\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 { FontSizePreset } from '../elements/note-toolbar';\r\nimport type { CanvasElement, ArrowElement, GridElement, ShapeKind } from '../elements/types';\r\nimport type { Point } from '../core/types';\r\nimport { ContextMenu } from './context-menu';\r\nimport type { ContextMenuItem } from './context-menu';\r\nimport { createWrapper, createCanvas, createDomLayer } from './viewport-dom';\r\nimport { findBoundArrows, getEdgeIntersection } from '../elements/arrow-binding';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { getElementsBoundingBox } from '../elements/bounds';\r\nimport { getArrowTangentAngle } from '../elements/arrow-geometry';\r\nimport { ArrowLabelEditor } from '../elements/arrow-label-editor';\r\nimport { ToolManager } from '../tools/tool-manager';\r\nimport type { ToolContext } from '../tools/types';\r\nimport type { SelectTool } from '../tools/select-tool';\r\nimport { HistoryStack } from '../history/history-stack';\r\nimport { HistoryRecorder } from '../history/history-recorder';\r\nimport { createImage, createHtmlElement, createShape } from '../elements/element-factory';\r\nimport { exportState as exportCanvasState, parseState } from '../core/state-serializer';\r\nimport { exportImage } from './export-image';\r\nimport type { ExportImageOptions } from './export-image';\r\nimport type { CanvasState } from '../core/state-serializer';\r\nimport { LayerManager } from '../layers/layer-manager';\r\nimport { InteractMode } from './interact-mode';\r\nimport { DomNodeManager } from './dom-node-manager';\r\nimport { RenderLoop } from './render-loop';\r\nimport type { RenderStatsSnapshot } from './render-stats';\r\nimport { LayerCache } from './layer-cache';\r\nimport { MarginViewport } from './margin-viewport';\r\nimport type { ElementStyle } from '../elements/element-style';\r\nimport { SelectionOps } from './selection-ops';\r\nimport type { AlignEdge, DistributeAxis } from './selection-ops';\r\nimport { GridController } from './grid-controller';\r\nimport type { GridInfo } from './grid-controller';\r\nimport { ViewportInteractions } from './viewport-interactions';\r\n\r\nexport type { AlignEdge, DistributeAxis } from './selection-ops';\r\nexport type { GridInfo } from './grid-controller';\r\n\r\nconst EMPTY_IDS: string[] = [];\r\n\r\nfunction noop(): void {\r\n // Stable unsubscribe handle returned when no select tool is registered.\r\n}\r\n\r\nexport interface ViewportOptions {\r\n camera?: CameraOptions;\r\n background?: BackgroundOptions;\r\n fontSizePresets?: FontSizePreset[];\r\n toolbar?: boolean;\r\n placeholder?: string;\r\n shortcuts?: ShortcutOptions;\r\n onHtmlElementMount?: (\r\n elementId: string,\r\n domId: string | undefined,\r\n container: HTMLDivElement,\r\n ) => void;\r\n onDrop?: (event: DragEvent, worldPosition: { x: number; y: number }) => void;\r\n onImageError?: (info: { src: string; elementIds: string[]; cause?: unknown }) => void;\r\n /** CSS-pixel margin cached beyond the viewport. Default `256`. Set `0` to disable. */\r\n panBufferMargin?: number;\r\n /** Enable the built-in context menu. Default `true`. */\r\n contextMenu?: boolean;\r\n}\r\n\r\nexport class Viewport {\r\n readonly camera: Camera;\r\n readonly store: ElementStore;\r\n readonly layerManager: LayerManager;\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 unsubToolChange: () => 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 arrowLabelEditor: ArrowLabelEditor;\r\n private readonly historyRecorder: HistoryRecorder;\r\n private readonly selectionOps: SelectionOps;\r\n readonly toolContext: ToolContext;\r\n private readonly marginViewport: MarginViewport;\r\n private resizeObserver: ResizeObserver | null = null;\r\n private _snapToGrid = false;\r\n private _smartGuides = false;\r\n private readonly _gridSize: number;\r\n private readonly renderLoop: RenderLoop;\r\n private readonly domNodeManager: DomNodeManager;\r\n private readonly interactMode: InteractMode;\r\n private readonly onHtmlElementMount?: (\r\n elementId: string,\r\n domId: string | undefined,\r\n container: HTMLDivElement,\r\n ) => void;\r\n private readonly dropHandler?: (\r\n event: DragEvent,\r\n worldPosition: { x: number; y: number },\r\n ) => void;\r\n private readonly gridController: GridController;\r\n private readonly interactions: ViewportInteractions;\r\n private contextMenu: ContextMenu | 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._gridSize = options.background?.spacing ?? 24;\r\n this.store = new ElementStore();\r\n this.layerManager = new LayerManager(this.store);\r\n this.toolManager = new ToolManager();\r\n this.renderer = new ElementRenderer();\r\n this.renderer.setStore(this.store);\r\n this.renderer.setCamera(this.camera);\r\n this.renderer.setOnImageLoad(() => {\r\n this.renderLoop.markAllLayersDirty();\r\n this.requestRender();\r\n });\r\n this.renderer.setOnImageError((src, cause) => {\r\n const elementIds: string[] = [];\r\n for (const el of this.store.getAll()) {\r\n if (el.type === 'image' && el.src === src) elementIds.push(el.id);\r\n }\r\n if (options.onImageError) {\r\n options.onImageError({ src, elementIds, cause });\r\n } else {\r\n console.warn(`[fieldnotes] image failed to load: ${src}`);\r\n }\r\n });\r\n this.noteEditor = new NoteEditor({\r\n fontSizePresets: options.fontSizePresets,\r\n toolbar: options.toolbar,\r\n placeholder: options.placeholder,\r\n });\r\n this.noteEditor.setOnStop((id) => this.interactions.onTextEditStop(id));\r\n this.arrowLabelEditor = new ArrowLabelEditor();\r\n this.noteEditor.setHistoryHooks(\r\n () => this.historyRecorder.begin(),\r\n () => this.historyRecorder.commit(),\r\n );\r\n this.onHtmlElementMount = options.onHtmlElementMount;\r\n this.dropHandler = options.onDrop;\r\n this.history = new HistoryStack();\r\n this.historyRecorder = new HistoryRecorder(this.store, this.history, this.layerManager);\r\n this.selectionOps = new SelectionOps({\r\n store: this.store,\r\n recorder: this.historyRecorder,\r\n getSelectedIds: () => this.getSelectedIds(),\r\n requestRender: () => this.requestRender(),\r\n });\r\n\r\n this.wrapper = createWrapper();\r\n this.canvasEl = createCanvas();\r\n this.domLayer = 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.interactions.startEditingElement(id),\r\n fitNoteHeight: (id: string) => this.interactions.fitNoteHeight(id),\r\n setCursor: (cursor: string) => {\r\n this.wrapper.style.cursor = cursor;\r\n },\r\n snapToGrid: false,\r\n gridSize: this._gridSize,\r\n activeLayerId: this.layerManager.activeLayerId,\r\n isLayerVisible: (id: string) => this.layerManager.isLayerVisible(id),\r\n isLayerLocked: (id: string) => this.layerManager.isLayerLocked(id),\r\n smartGuides: false,\r\n getVisibleRect: () =>\r\n this.camera.getVisibleRect(this.canvasEl.clientWidth, this.canvasEl.clientHeight),\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 fitToContent: () => this.fitToContent(),\r\n group: () => this.groupSelection(),\r\n ungroup: () => this.ungroupSelection(),\r\n toggleLock: () => this.toggleLockSelection(),\r\n openContextMenu: (screenPos, world) => {\r\n this.getSelectTool()?.selectAtPoint(world, this.toolContext);\r\n this.openContextMenu(screenPos);\r\n },\r\n shortcuts: options.shortcuts,\r\n });\r\n\r\n if (options.contextMenu !== false) {\r\n this.contextMenu = new ContextMenu({\r\n onCommand: (action) => this.runAction(action),\r\n onClose: noop,\r\n });\r\n }\r\n this.unsubToolChange = this.toolManager.onChange(() => this.contextMenu?.close());\r\n\r\n this.domNodeManager = new DomNodeManager({\r\n domLayer: this.domLayer,\r\n onEditRequest: (id) => this.interactions.startEditingElement(id),\r\n isEditingElement: (id) =>\r\n this.noteEditor.isEditing && this.noteEditor.editingElementId === id,\r\n getVersion: (id) => this.store.getVersion(id),\r\n });\r\n\r\n this.interactMode = new InteractMode({\r\n getNode: (id) => this.domNodeManager.getNode(id),\r\n });\r\n\r\n this.marginViewport = new MarginViewport(options.panBufferMargin ?? 256);\r\n this.marginViewport.setViewport(\r\n this.canvasEl.clientWidth || 800,\r\n this.canvasEl.clientHeight || 600,\r\n typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1,\r\n );\r\n const layerCache = new LayerCache(this.marginViewport);\r\n\r\n this.renderLoop = new RenderLoop({\r\n canvasEl: this.canvasEl,\r\n camera: this.camera,\r\n background: this.background,\r\n store: this.store,\r\n renderer: this.renderer,\r\n toolManager: this.toolManager,\r\n layerManager: this.layerManager,\r\n domNodeManager: this.domNodeManager,\r\n layerCache,\r\n marginViewport: this.marginViewport,\r\n });\r\n\r\n this.unsubCamera = this.camera.onChange(() => {\r\n this.applyCameraTransform();\r\n this.noteEditor.updateToolbarPosition();\r\n this.contextMenu?.close();\r\n this.requestRender();\r\n });\r\n\r\n this.gridController = new GridController({\r\n store: this.store,\r\n recorder: this.historyRecorder,\r\n requestRender: () => this.requestRender(),\r\n getActiveLayerId: () => this.layerManager.activeLayerId,\r\n toolContext: this.toolContext,\r\n defaultGridSize: this._gridSize,\r\n });\r\n\r\n this.unsubStore = [\r\n this.store.on('add', (el) => {\r\n if (el.type === 'grid') this.gridController.syncContext();\r\n this.renderLoop.markLayerDirty(el.layerId);\r\n this.requestRender();\r\n }),\r\n this.store.on('remove', (el) => {\r\n if (el.type === 'grid') this.gridController.syncContext();\r\n this.unbindArrowsFrom(el);\r\n this.domNodeManager.removeDomNode(el.id);\r\n this.renderLoop.markLayerDirty(el.layerId);\r\n this.requestRender();\r\n }),\r\n this.store.on('update', ({ previous, current }) => {\r\n if (current.type === 'grid') this.gridController.syncContext();\r\n this.renderLoop.markLayerDirty(current.layerId);\r\n if (previous.layerId !== current.layerId) {\r\n this.renderLoop.markLayerDirty(previous.layerId);\r\n }\r\n this.requestRender();\r\n }),\r\n this.store.on('clear', () => {\r\n this.domNodeManager.clearDomNodes();\r\n this.renderLoop.markAllLayersDirty();\r\n this.gridController.syncContext();\r\n this.requestRender();\r\n }),\r\n ];\r\n\r\n this.layerManager.on('change', () => {\r\n this.toolContext.activeLayerId = this.layerManager.activeLayerId;\r\n this.requestRender();\r\n });\r\n\r\n this.interactions = new ViewportInteractions({\r\n store: this.store,\r\n camera: this.camera,\r\n wrapper: this.wrapper,\r\n domLayer: this.domLayer,\r\n renderLoop: this.renderLoop,\r\n domNodeManager: this.domNodeManager,\r\n noteEditor: this.noteEditor,\r\n arrowLabelEditor: this.arrowLabelEditor,\r\n interactMode: this.interactMode,\r\n renderer: this.renderer,\r\n recorder: this.historyRecorder,\r\n requestRender: () => this.requestRender(),\r\n addImage: (src, position) => this.addImage(src, position),\r\n dropHandler: this.dropHandler,\r\n });\r\n\r\n this.wrapper.addEventListener('pointerdown', this.interactions.onTapDown);\r\n this.wrapper.addEventListener('pointerup', this.interactions.onDoubleTap);\r\n this.wrapper.addEventListener('dragover', this.interactions.onDragOver);\r\n this.wrapper.addEventListener('drop', this.interactions.onDrop);\r\n this.observeResize();\r\n this.syncCanvasSize();\r\n this.renderLoop.start();\r\n this.gridController.syncContext();\r\n }\r\n\r\n get ctx(): CanvasRenderingContext2D | null {\r\n return this.canvasEl.getContext('2d');\r\n }\r\n\r\n get snapToGrid(): boolean {\r\n return this._snapToGrid;\r\n }\r\n\r\n setSnapToGrid(enabled: boolean): void {\r\n this._snapToGrid = enabled;\r\n this.toolContext.snapToGrid = enabled;\r\n }\r\n\r\n get smartGuides(): boolean {\r\n return this._smartGuides;\r\n }\r\n\r\n setSmartGuides(enabled: boolean): void {\r\n this._smartGuides = enabled;\r\n this.toolContext.smartGuides = enabled;\r\n }\r\n\r\n fitToContent(padding = 40): void {\r\n if (this.wrapper.clientWidth === 0 || this.wrapper.clientHeight === 0) return;\r\n const visibleElements = this.store\r\n .getAll()\r\n .filter((el) => this.layerManager.isLayerVisible(el.layerId));\r\n const bbox = getElementsBoundingBox(visibleElements);\r\n if (!bbox) return;\r\n this.camera.fitToContent(bbox, this.wrapper.clientWidth, this.wrapper.clientHeight, padding);\r\n }\r\n\r\n requestRender(): void {\r\n this.renderLoop.requestRender();\r\n }\r\n\r\n exportState(): CanvasState {\r\n return exportCanvasState(\r\n this.store.snapshot(),\r\n this.camera,\r\n this.layerManager.snapshot(),\r\n this.layerManager.activeLayerId,\r\n );\r\n }\r\n\r\n exportJSON(): string {\r\n return JSON.stringify(this.exportState());\r\n }\r\n\r\n async exportImage(options?: ExportImageOptions): Promise<Blob | null> {\r\n return exportImage(this.store, options, this.layerManager);\r\n }\r\n\r\n loadState(state: CanvasState): void {\r\n this.inputHandler.flushPendingHistory();\r\n this.historyRecorder.pause();\r\n this.noteEditor.destroy(this.store);\r\n this.domNodeManager.clearDomNodes();\r\n this.store.loadSnapshot(state.elements);\r\n if (state.layers && state.layers.length > 0) {\r\n this.layerManager.loadSnapshot(state.layers);\r\n }\r\n if (state.activeLayerId) {\r\n this.layerManager.setActiveLayer(state.activeLayerId);\r\n }\r\n this.domNodeManager.reattachHtmlContent(this.store);\r\n if (this.onHtmlElementMount) {\r\n for (const el of this.store.getElementsByType('html')) {\r\n if (!this.domNodeManager.hasContent(el.id)) {\r\n this.domNodeManager.syncDomNode(el);\r\n const node = this.domNodeManager.getNode(el.id);\r\n if (node) {\r\n this.onHtmlElementMount(el.id, el.domId, node);\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n overflow: 'hidden',\r\n pointerEvents: el.interactive ? 'auto' : 'none',\r\n });\r\n }\r\n }\r\n }\r\n }\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 setTool(name: string): void {\r\n if (!this.toolManager.getTool(name)) {\r\n console.warn(`[fieldnotes] setTool: no tool registered as \"${name}\"`);\r\n return;\r\n }\r\n this.toolManager.setTool(name, this.toolContext);\r\n }\r\n\r\n get shortcuts(): ShortcutsApi {\r\n return this.inputHandler.shortcuts;\r\n }\r\n\r\n undo(): boolean {\r\n this.inputHandler.flushPendingHistory();\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.inputHandler.flushPendingHistory();\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, layerId: this.layerManager.activeLayerId });\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 domId = dom.id || undefined;\r\n const el = createHtmlElement({\r\n position,\r\n size,\r\n domId,\r\n layerId: this.layerManager.activeLayerId,\r\n });\r\n this.domNodeManager.storeHtmlContent(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 addShape(\r\n opts: {\r\n shape?: ShapeKind;\r\n size?: { w: number; h: number };\r\n position?: { x: number; y: number };\r\n strokeColor?: string;\r\n fillColor?: string;\r\n strokeWidth?: number;\r\n } = {},\r\n ): string {\r\n const size = opts.size ?? { w: 100, h: 100 };\r\n const position = opts.position ?? this.centeredPosition(size);\r\n const shape = createShape({\r\n position,\r\n size,\r\n shape: opts.shape,\r\n strokeColor: opts.strokeColor,\r\n strokeWidth: opts.strokeWidth,\r\n fillColor: opts.fillColor,\r\n layerId: this.layerManager.activeLayerId,\r\n });\r\n this.historyRecorder.begin();\r\n this.store.add(shape);\r\n this.historyRecorder.commit();\r\n this.getSelectTool()?.setSelection([shape.id]);\r\n this.requestRender();\r\n return shape.id;\r\n }\r\n\r\n private centeredPosition(size: { w: number; h: number }): { x: number; y: number } {\r\n const c = this.camera.screenToWorld({\r\n x: this.wrapper.clientWidth / 2,\r\n y: this.wrapper.clientHeight / 2,\r\n });\r\n return { x: c.x - size.w / 2, y: c.y - size.h / 2 };\r\n }\r\n\r\n removeLayer(id: string): void {\r\n this.historyRecorder.begin();\r\n this.layerManager.removeLayer(id);\r\n this.historyRecorder.commit();\r\n }\r\n\r\n updateHtmlElement(id: string, newContent: HTMLElement): void {\r\n const el = this.store.getById(id);\r\n if (!el) throw new Error(`Element not found: ${id}`);\r\n if (el.type !== 'html') throw new Error(`Element ${id} is not an HTML element`);\r\n this.domNodeManager.resetHtmlContent(id);\r\n this.domNodeManager.storeHtmlContent(id, newContent);\r\n this.requestRender();\r\n }\r\n\r\n addGrid(input: {\r\n gridType?: 'square' | 'hex';\r\n hexOrientation?: 'pointy' | 'flat';\r\n cellSize?: number;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n }): string {\r\n return this.gridController.add(input);\r\n }\r\n\r\n updateGrid(\r\n updates: Partial<\r\n Pick<\r\n GridElement,\r\n 'gridType' | 'hexOrientation' | 'cellSize' | 'strokeColor' | 'strokeWidth' | 'opacity'\r\n >\r\n >,\r\n ): void {\r\n this.gridController.update(updates);\r\n }\r\n\r\n removeGrid(): void {\r\n this.gridController.remove();\r\n }\r\n\r\n getGridInfo(): GridInfo | null {\r\n return this.gridController.getInfo();\r\n }\r\n\r\n onGridChange(listener: (info: GridInfo | null) => void): () => void {\r\n return this.gridController.onChange(listener);\r\n }\r\n\r\n private getSelectTool(): SelectTool | undefined {\r\n return this.toolManager.getTool<SelectTool>('select');\r\n }\r\n\r\n getSelectedIds(): string[] {\r\n return this.getSelectTool()?.selectedIds ?? EMPTY_IDS;\r\n }\r\n\r\n runAction(action: string): void {\r\n this.inputHandler.runAction(action);\r\n }\r\n\r\n canPaste(): boolean {\r\n return this.inputHandler.hasClipboard();\r\n }\r\n\r\n openContextMenu(screenPos: Point): void {\r\n if (!this.contextMenu) return;\r\n const ids = this.getSelectedIds();\r\n const items: ContextMenuItem[] = [];\r\n if (ids.length > 0) {\r\n items.push({ label: 'Cut', action: 'cut' });\r\n items.push({ label: 'Copy', action: 'copy' });\r\n if (this.canPaste()) items.push({ label: 'Paste', action: 'paste' });\r\n items.push({ label: 'Duplicate', action: 'duplicate' });\r\n items.push({ label: 'Delete', action: 'delete' });\r\n items.push({ label: 'Bring to Front', action: 'z-front' });\r\n items.push({ label: 'Bring Forward', action: 'z-forward' });\r\n items.push({ label: 'Send Backward', action: 'z-backward' });\r\n items.push({ label: 'Send to Back', action: 'z-back' });\r\n const allLocked = ids.every((id) => this.store.getById(id)?.locked);\r\n items.push({ label: allLocked ? 'Unlock' : 'Lock', action: 'toggle-lock' });\r\n } else if (this.canPaste()) {\r\n items.push({ label: 'Paste', action: 'paste' });\r\n }\r\n if (items.length === 0) return;\r\n this.contextMenu.open(items, screenPos);\r\n }\r\n\r\n onSelectionChange(listener: () => void): () => void {\r\n const tool = this.getSelectTool();\r\n return tool ? tool.onSelectionChange(listener) : noop;\r\n }\r\n\r\n getSelectionStyle(): ElementStyle | null {\r\n return this.selectionOps.getStyle();\r\n }\r\n\r\n applyStyleToSelection(style: ElementStyle): void {\r\n this.selectionOps.applyStyle(style);\r\n }\r\n\r\n groupSelection(): void {\r\n this.selectionOps.group();\r\n }\r\n\r\n ungroupSelection(): void {\r\n this.selectionOps.ungroup();\r\n }\r\n\r\n toggleLockSelection(): void {\r\n this.selectionOps.toggleLock();\r\n }\r\n\r\n alignSelection(edge: AlignEdge): void {\r\n this.selectionOps.align(edge);\r\n }\r\n\r\n distributeSelection(axis: DistributeAxis): void {\r\n this.selectionOps.distribute(axis);\r\n }\r\n\r\n getRenderStats(): RenderStatsSnapshot {\r\n return this.renderLoop.getStats();\r\n }\r\n\r\n logPerformance(intervalMs = 2000): () => void {\r\n const id = setInterval(() => {\r\n const s = this.getRenderStats();\r\n console.log(\r\n `[FieldNotes] fps=${s.fps} frame=${s.avgFrameMs}ms p95=${s.p95FrameMs}ms grid=${s.lastGridMs}ms layers=${s.layersMs}ms comp=${s.compositeMs}ms bg=${s.backgroundMs}ms overlay=${s.overlayMs}ms`,\r\n );\r\n }, intervalMs);\r\n return () => clearInterval(id);\r\n }\r\n\r\n destroy(): void {\r\n this.renderLoop.stop();\r\n this.interactMode.destroy();\r\n this.noteEditor.destroy(this.store);\r\n this.arrowLabelEditor.cancel();\r\n this.historyRecorder.destroy();\r\n this.contextMenu?.dispose();\r\n this.wrapper.removeEventListener('pointerdown', this.interactions.onTapDown);\r\n this.wrapper.removeEventListener('pointerup', this.interactions.onDoubleTap);\r\n this.wrapper.removeEventListener('dragover', this.interactions.onDragOver);\r\n this.wrapper.removeEventListener('drop', this.interactions.onDrop);\r\n this.inputHandler.destroy();\r\n this.unsubCamera();\r\n this.unsubToolChange();\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 stopInteracting(): void {\r\n this.interactMode.stopInteracting();\r\n }\r\n\r\n private unbindArrowsFrom(removedElement: CanvasElement): void {\r\n const boundArrows = findBoundArrows(removedElement.id, this.store);\r\n const bounds = getElementBounds(removedElement);\r\n\r\n for (const arrow of boundArrows) {\r\n const updates: Partial<ArrowElement> = {};\r\n\r\n if (arrow.fromBinding?.elementId === removedElement.id) {\r\n updates.fromBinding = undefined;\r\n if (bounds) {\r\n const angle = getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 0);\r\n const rayTarget = {\r\n x: arrow.from.x + Math.cos(angle) * 1000,\r\n y: arrow.from.y + Math.sin(angle) * 1000,\r\n };\r\n const edge = getEdgeIntersection(bounds, rayTarget);\r\n updates.from = edge;\r\n updates.position = edge;\r\n }\r\n }\r\n\r\n if (arrow.toBinding?.elementId === removedElement.id) {\r\n updates.toBinding = undefined;\r\n if (bounds) {\r\n const angle = getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 1);\r\n const rayTarget = {\r\n x: arrow.to.x - Math.cos(angle) * 1000,\r\n y: arrow.to.y - Math.sin(angle) * 1000,\r\n };\r\n updates.to = getEdgeIntersection(bounds, rayTarget);\r\n }\r\n }\r\n\r\n if (Object.keys(updates).length > 0) {\r\n this.store.update(arrow.id, updates);\r\n }\r\n }\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.renderLoop.setCanvasSize(rect.width * dpr, 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\nimport { computeStrokeSegments } from '../elements/stroke-cache';\r\n\r\nexport interface PencilToolOptions {\r\n name?: string;\r\n color?: string;\r\n width?: number;\r\n smoothing?: number;\r\n minPointDistance?: number;\r\n progressiveSimplifyThreshold?: number;\r\n opacity?: number;\r\n blendMode?: 'multiply';\r\n}\r\n\r\nconst MIN_POINTS_FOR_STROKE = 2;\r\nconst DEFAULT_SMOOTHING = 1.5;\r\nconst DEFAULT_PRESSURE = 0.5;\r\nconst DEFAULT_MIN_POINT_DISTANCE = 3;\r\nconst DEFAULT_PROGRESSIVE_THRESHOLD = 200;\r\nconst PROGRESSIVE_HOT_ZONE = 30;\r\n\r\nexport class PencilTool implements Tool {\r\n readonly name: string;\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 private minPointDistance: number;\r\n private progressiveThreshold: number;\r\n private nextSimplifyAt: number;\r\n private opacity: number;\r\n private blendMode: 'multiply' | undefined;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: PencilToolOptions = {}) {\r\n this.name = options.name ?? 'pencil';\r\n this.color = options.color ?? '#000000';\r\n this.width = options.width ?? 2;\r\n this.smoothing = options.smoothing ?? DEFAULT_SMOOTHING;\r\n this.minPointDistance = options.minPointDistance ?? DEFAULT_MIN_POINT_DISTANCE;\r\n this.progressiveThreshold =\r\n options.progressiveSimplifyThreshold ?? DEFAULT_PROGRESSIVE_THRESHOLD;\r\n this.nextSimplifyAt = this.progressiveThreshold;\r\n this.opacity = options.opacity ?? 1;\r\n this.blendMode = options.blendMode;\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 getOptions(): PencilToolOptions {\r\n return {\r\n color: this.color,\r\n width: this.width,\r\n smoothing: this.smoothing,\r\n minPointDistance: this.minPointDistance,\r\n progressiveSimplifyThreshold: this.progressiveThreshold,\r\n opacity: this.opacity,\r\n blendMode: this.blendMode,\r\n };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\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 if (options.minPointDistance !== undefined) this.minPointDistance = options.minPointDistance;\r\n if (options.progressiveSimplifyThreshold !== undefined)\r\n this.progressiveThreshold = options.progressiveSimplifyThreshold;\r\n if (options.opacity !== undefined) this.opacity = options.opacity;\r\n if (options.blendMode !== undefined) this.blendMode = options.blendMode;\r\n this.notifyOptionsChange();\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 this.nextSimplifyAt = this.progressiveThreshold;\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\r\n const last = this.points[this.points.length - 1];\r\n if (last) {\r\n const dx = world.x - last.x;\r\n const dy = world.y - last.y;\r\n if (dx * dx + dy * dy < this.minPointDistance * this.minPointDistance) return;\r\n }\r\n\r\n this.points.push({ x: world.x, y: world.y, pressure });\r\n\r\n // Progressively simplify the cold zone to bound memory on very long strokes.\r\n // nextSimplifyAt doubles after each pass to avoid compounding data loss.\r\n if (this.points.length > this.nextSimplifyAt) {\r\n const hotZone = this.points.slice(-PROGRESSIVE_HOT_ZONE);\r\n const coldZone = this.points.slice(0, -PROGRESSIVE_HOT_ZONE);\r\n const simplified = simplifyPoints(coldZone, this.smoothing * 2);\r\n this.points = [...simplified, ...hotZone];\r\n this.nextSimplifyAt = this.points.length + this.progressiveThreshold;\r\n }\r\n\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 layerId: ctx.activeLayerId ?? '',\r\n opacity: this.opacity,\r\n blendMode: this.blendMode,\r\n });\r\n ctx.store.add(stroke);\r\n computeStrokeSegments(stroke);\r\n this.points = [];\r\n ctx.requestRender();\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\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 // Preview a highlighter at its real opacity + blend so it doesn't snap on commit;\r\n // a normal pencil keeps the lighter 0.8 in-progress affordance.\r\n ctx.globalAlpha = this.blendMode ? this.opacity : 0.8;\r\n if (this.blendMode) ctx.globalCompositeOperation = this.blendMode;\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';\r\nimport type { StrokeElement } from './types';\r\nimport { getElementBounds } from './element-bounds';\r\nimport { getStrokeRenderData } from './stroke-cache';\r\nimport { distSqToSegment } from '../core/geometry';\r\n\r\nexport function hitTestStroke(stroke: StrokeElement, point: Point, radius: number): boolean {\r\n const bounds = getElementBounds(stroke);\r\n if (!bounds) return false;\r\n if (\r\n point.x < bounds.x - radius ||\r\n point.x > bounds.x + bounds.w + radius ||\r\n point.y < bounds.y - radius ||\r\n point.y > bounds.y + bounds.h + radius\r\n ) {\r\n return false;\r\n }\r\n\r\n const radiusSq = radius * radius;\r\n const local: Point = { x: point.x - stroke.position.x, y: point.y - stroke.position.y };\r\n const { segments } = getStrokeRenderData(stroke);\r\n\r\n if (segments.length === 0) {\r\n const p = stroke.points[0];\r\n if (!p) return false;\r\n const dx = p.x - local.x;\r\n const dy = p.y - local.y;\r\n return dx * dx + dy * dy <= radiusSq;\r\n }\r\n\r\n for (const seg of segments) {\r\n if (distSqToSegment(local, seg.start, seg.end) <= radiusSq) return true;\r\n }\r\n return false;\r\n}\r\n","import type { Point, StrokePoint } from '../core/types';\r\n\r\nfunction lerp(a: StrokePoint, b: StrokePoint, t: number): StrokePoint {\r\n return {\r\n x: a.x + (b.x - a.x) * t,\r\n y: a.y + (b.y - a.y) * t,\r\n pressure: a.pressure + (b.pressure - a.pressure) * t,\r\n };\r\n}\r\n\r\n/**\r\n * Split a stroke's points by an eraser circle (all in the stroke's local space).\r\n * Returns surviving runs (each ≥2 points), `[]` if fully erased, or `null` if nothing\r\n * was within the radius (no change).\r\n */\r\nexport function erasePoints(\r\n points: StrokePoint[],\r\n eraser: Point,\r\n radius: number,\r\n): StrokePoint[][] | null {\r\n const r2 = radius * radius;\r\n\r\n if (points.length < 2) {\r\n const p = points[0];\r\n if (p && (p.x - eraser.x) ** 2 + (p.y - eraser.y) ** 2 <= r2) return [];\r\n return null;\r\n }\r\n\r\n const runs: StrokePoint[][] = [];\r\n let current: StrokePoint[] = [];\r\n let erased = false;\r\n\r\n const flush = (): void => {\r\n if (current.length >= 2) runs.push(current);\r\n current = [];\r\n };\r\n\r\n for (let i = 0; i < points.length - 1; i++) {\r\n const a = points[i];\r\n const b = points[i + 1];\r\n if (!a || !b) continue;\r\n\r\n const dx = b.x - a.x;\r\n const dy = b.y - a.y;\r\n const fx = a.x - eraser.x;\r\n const fy = a.y - eraser.y;\r\n const A = dx * dx + dy * dy;\r\n const B = 2 * (fx * dx + fy * dy);\r\n const C = fx * fx + fy * fy - r2;\r\n\r\n let tLo = 1;\r\n let tHi = 0;\r\n if (A === 0) {\r\n if (C <= 0) {\r\n tLo = 0;\r\n tHi = 1;\r\n }\r\n } else {\r\n const disc = B * B - 4 * A * C;\r\n if (disc >= 0) {\r\n const sq = Math.sqrt(disc);\r\n const lo = Math.max(0, (-B - sq) / (2 * A));\r\n const hi = Math.min(1, (-B + sq) / (2 * A));\r\n // Strict `<`: a tangent graze (lo === hi, zero-width overlap) is not an erase —\r\n // it would otherwise split a stroke in two at a single duplicated point.\r\n if (lo < hi) {\r\n tLo = lo;\r\n tHi = hi;\r\n }\r\n }\r\n }\r\n\r\n if (tLo > tHi) {\r\n if (current.length === 0) current.push(a);\r\n current.push(b);\r\n continue;\r\n }\r\n\r\n erased = true;\r\n if (tLo > 0) {\r\n if (current.length === 0) current.push(a);\r\n current.push(lerp(a, b, tLo));\r\n flush();\r\n } else {\r\n flush();\r\n }\r\n if (tHi < 1) {\r\n current = [lerp(a, b, tHi), b];\r\n }\r\n }\r\n\r\n flush();\r\n return erased ? runs : null;\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport type { StrokeElement } from '../elements/types';\r\nimport { hitTestStroke } from '../elements/stroke-hit';\r\nimport { createStroke } from '../elements/element-factory';\r\nimport { erasePoints } from '../elements/stroke-erase';\r\n\r\nexport interface EraserToolOptions {\r\n /** Eraser radius in SCREEN pixels (matches the cursor circle; converted to world units per zoom). */\r\n radius?: number;\r\n mode?: 'partial' | 'stroke';\r\n}\r\n\r\nconst DEFAULT_RADIUS = 20;\r\n\r\nfunction makeEraserCursor(radius: number): string {\r\n const size = radius * 2;\r\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>`;\r\n return `url(\"data:image/svg+xml,${svg}\") ${radius} ${radius}, crosshair`;\r\n}\r\n\r\nexport class EraserTool implements Tool {\r\n readonly name = 'eraser';\r\n private erasing = false;\r\n private radius: number;\r\n private cursor: string;\r\n private mode: 'partial' | 'stroke';\r\n\r\n constructor(options: EraserToolOptions = {}) {\r\n this.radius = options.radius ?? DEFAULT_RADIUS;\r\n this.cursor = makeEraserCursor(this.radius);\r\n this.mode = options.mode ?? 'partial';\r\n }\r\n\r\n getOptions(): EraserToolOptions {\r\n return { radius: this.radius, mode: this.mode };\r\n }\r\n\r\n setOptions(options: EraserToolOptions): void {\r\n if (options.mode !== undefined) this.mode = options.mode;\r\n if (options.radius !== undefined) {\r\n this.radius = options.radius;\r\n this.cursor = makeEraserCursor(this.radius); // applied on next activate\r\n }\r\n }\r\n\r\n onActivate(ctx: ToolContext): void {\r\n ctx.setCursor?.(this.cursor);\r\n }\r\n\r\n onDeactivate(ctx: ToolContext): void {\r\n ctx.setCursor?.('default');\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.erasing = true;\r\n this.eraseAt(state, ctx);\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.erasing) return;\r\n this.eraseAt(state, ctx);\r\n }\r\n\r\n onPointerUp(_state: PointerState, _ctx: ToolContext): void {\r\n this.erasing = false;\r\n }\r\n\r\n private eraseAt(state: PointerState, ctx: ToolContext): void {\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const worldRadius = this.radius / ctx.camera.zoom;\r\n const queryBounds: Bounds = {\r\n x: world.x - worldRadius,\r\n y: world.y - worldRadius,\r\n w: worldRadius * 2,\r\n h: worldRadius * 2,\r\n };\r\n const candidates = ctx.store.queryRect(queryBounds);\r\n let erased = false;\r\n\r\n for (const el of candidates) {\r\n if (el.type !== 'stroke') continue;\r\n if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) continue;\r\n if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) continue;\r\n if (!this.strokeIntersects(el, world, worldRadius)) continue;\r\n if (this.mode === 'stroke') {\r\n ctx.store.remove(el.id);\r\n erased = true;\r\n continue;\r\n }\r\n const localEraser = { x: world.x - el.position.x, y: world.y - el.position.y };\r\n const runs = erasePoints(el.points, localEraser, worldRadius);\r\n if (runs === null) continue;\r\n ctx.store.remove(el.id);\r\n for (const run of runs) {\r\n ctx.store.add(\r\n createStroke({\r\n points: run,\r\n color: el.color,\r\n width: el.width,\r\n opacity: el.opacity,\r\n layerId: el.layerId,\r\n zIndex: el.zIndex,\r\n position: el.position,\r\n }),\r\n );\r\n }\r\n erased = true;\r\n }\r\n\r\n if (erased) ctx.requestRender();\r\n }\r\n\r\n private strokeIntersects(stroke: StrokeElement, point: Point, worldRadius: number): boolean {\r\n return hitTestStroke(stroke, point, worldRadius);\r\n }\r\n}\r\n","import type { CanvasElement } from './types';\r\n\r\n/** Expand a selection to include every co-member of any group it touches. Returns `ids`\r\n * unchanged (same reference) when no selected element is grouped. */\r\nexport function expandToGroups(ids: string[], elements: CanvasElement[]): string[] {\r\n const byId = new Map(elements.map((e) => [e.id, e]));\r\n const groupIds = new Set<string>();\r\n for (const id of ids) {\r\n const g = byId.get(id)?.groupId;\r\n if (g) groupIds.add(g);\r\n }\r\n if (groupIds.size === 0) return ids;\r\n const idSet = new Set(ids);\r\n const result = [...ids];\r\n for (const el of elements) {\r\n if (el.groupId && groupIds.has(el.groupId) && !idSet.has(el.id)) {\r\n result.push(el.id);\r\n idSet.add(el.id);\r\n }\r\n }\r\n return result;\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { ArrowElement, CanvasElement } from '../elements/types';\r\nimport type { ToolContext } from './types';\r\nimport { getArrowMidpoint, getBendFromPoint } from '../elements/arrow-geometry';\r\nimport { findBindTarget, getElementCenter } from '../elements/arrow-binding';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\n\r\nconst BIND_THRESHOLD = 20;\r\n\r\nexport type ArrowHandle = 'start' | 'mid' | 'end';\r\n\r\nconst HANDLE_RADIUS = 5;\r\nconst HANDLE_HIT_PADDING = 4;\r\n\r\nconst ARROW_HANDLE_CURSORS: Record<ArrowHandle, string> = {\r\n start: 'crosshair',\r\n end: 'crosshair',\r\n mid: 'grab',\r\n};\r\n\r\nexport function getArrowHandleCursor(handle: ArrowHandle, active: boolean): string {\r\n if (handle === 'mid' && active) return 'grabbing';\r\n return ARROW_HANDLE_CURSORS[handle];\r\n}\r\n\r\nexport function getArrowHandlePositions(arrow: ArrowElement): [ArrowHandle, Point][] {\r\n const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);\r\n return [\r\n ['start', arrow.from],\r\n ['mid', mid],\r\n ['end', arrow.to],\r\n ];\r\n}\r\n\r\nexport function hitTestArrowHandles(\r\n world: Point,\r\n selectedIds: string[],\r\n ctx: ToolContext,\r\n): { elementId: string; handle: ArrowHandle } | null {\r\n if (selectedIds.length === 0) return null;\r\n\r\n const zoom = ctx.camera.zoom;\r\n const hitRadius = (HANDLE_RADIUS + HANDLE_HIT_PADDING) / zoom;\r\n\r\n for (const id of selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || el.type !== 'arrow') continue;\r\n\r\n const handles = getArrowHandlePositions(el);\r\n for (const [handle, pos] of handles) {\r\n const dx = world.x - pos.x;\r\n const dy = world.y - pos.y;\r\n if (dx * dx + dy * dy <= hitRadius * hitRadius) {\r\n return { elementId: id, handle };\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport function applyArrowHandleDrag(\r\n handle: ArrowHandle,\r\n elementId: string,\r\n world: Point,\r\n ctx: ToolContext,\r\n): void {\r\n const el = ctx.store.getById(elementId);\r\n if (!el || el.type !== 'arrow') return;\r\n\r\n const threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n\r\n const layerFilter = (candidate: CanvasElement) => candidate.layerId === el.layerId;\r\n\r\n switch (handle) {\r\n case 'start': {\r\n const excludeId = el.toBinding?.elementId;\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);\r\n if (target) {\r\n const center = getElementCenter(target);\r\n ctx.store.update(elementId, {\r\n from: center,\r\n position: center,\r\n fromBinding: { elementId: target.id },\r\n });\r\n } else {\r\n ctx.store.update(elementId, {\r\n from: { x: world.x, y: world.y },\r\n position: { x: world.x, y: world.y },\r\n fromBinding: undefined,\r\n });\r\n }\r\n break;\r\n }\r\n case 'end': {\r\n const excludeId = el.fromBinding?.elementId;\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);\r\n if (target) {\r\n const center = getElementCenter(target);\r\n ctx.store.update(elementId, {\r\n to: center,\r\n toBinding: { elementId: target.id },\r\n });\r\n } else {\r\n ctx.store.update(elementId, {\r\n to: { x: world.x, y: world.y },\r\n toBinding: undefined,\r\n });\r\n }\r\n break;\r\n }\r\n case 'mid': {\r\n const bend = getBendFromPoint(el.from, el.to, world);\r\n ctx.store.update(elementId, { bend });\r\n break;\r\n }\r\n }\r\n\r\n ctx.requestRender();\r\n}\r\n\r\nexport function getArrowHandleDragTarget(\r\n handle: ArrowHandle,\r\n elementId: string,\r\n world: Point,\r\n ctx: ToolContext,\r\n): { x: number; y: number; w: number; h: number } | null {\r\n if (handle === 'mid') return null;\r\n\r\n const el = ctx.store.getById(elementId);\r\n if (!el || el.type !== 'arrow') return null;\r\n\r\n const threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n const excludeId = handle === 'start' ? el.toBinding?.elementId : el.fromBinding?.elementId;\r\n const layerFilter = (candidate: CanvasElement) => candidate.layerId === el.layerId;\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);\r\n if (!target) return null;\r\n\r\n return getElementBounds(target);\r\n}\r\n\r\nexport function renderArrowHandles(\r\n canvasCtx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n zoom: number,\r\n): void {\r\n const radius = HANDLE_RADIUS / zoom;\r\n const handles = getArrowHandlePositions(arrow);\r\n\r\n canvasCtx.setLineDash([]);\r\n canvasCtx.lineWidth = 1.5 / zoom;\r\n\r\n for (const [handle, pos] of handles) {\r\n canvasCtx.fillStyle = handle === 'mid' ? '#2196F3' : '#ffffff';\r\n canvasCtx.strokeStyle = '#2196F3';\r\n\r\n canvasCtx.beginPath();\r\n canvasCtx.arc(pos.x, pos.y, radius, 0, Math.PI * 2);\r\n canvasCtx.fill();\r\n canvasCtx.stroke();\r\n }\r\n}\r\n","import type { Bounds } from '../core/types';\r\n\r\nexport interface SnapGuide {\r\n axis: 'x' | 'y';\r\n position: number;\r\n}\r\nexport interface SnapResult {\r\n dx: number;\r\n dy: number;\r\n guides: SnapGuide[];\r\n}\r\n\r\ninterface AxisAnchors {\r\n lo: number;\r\n mid: number;\r\n hi: number;\r\n}\r\n\r\nfunction xAnchors(b: Bounds): AxisAnchors {\r\n return { lo: b.x, mid: b.x + b.w / 2, hi: b.x + b.w };\r\n}\r\n\r\nfunction yAnchors(b: Bounds): AxisAnchors {\r\n return { lo: b.y, mid: b.y + b.h / 2, hi: b.y + b.h };\r\n}\r\n\r\nfunction bestAxisSnap(\r\n moving: AxisAnchors,\r\n targets: Bounds[],\r\n anchorsFn: (b: Bounds) => AxisAnchors,\r\n threshold: number,\r\n): { delta: number; position: number } | null {\r\n let best: { delta: number; position: number } | null = null;\r\n\r\n for (const t of targets) {\r\n const ta = anchorsFn(t);\r\n const pairs: [number, number][] = [\r\n // colinear alignment: same-type edges/centers line up\r\n [ta.lo - moving.lo, ta.lo],\r\n [ta.mid - moving.mid, ta.mid],\r\n [ta.hi - moving.hi, ta.hi],\r\n // abutment: the moving box sits flush against the target's opposite edge\r\n [ta.lo - moving.hi, ta.lo],\r\n [ta.hi - moving.lo, ta.hi],\r\n ];\r\n\r\n for (const [delta, position] of pairs) {\r\n const abs = Math.abs(delta);\r\n if (abs <= threshold && (best === null || abs < Math.abs(best.delta))) {\r\n best = { delta, position };\r\n }\r\n }\r\n }\r\n\r\n return best;\r\n}\r\n\r\nexport function computeSnapGuides(\r\n moving: Bounds,\r\n targets: Bounds[],\r\n threshold: number,\r\n): SnapResult {\r\n const xSnap = bestAxisSnap(xAnchors(moving), targets, xAnchors, threshold);\r\n const ySnap = bestAxisSnap(yAnchors(moving), targets, yAnchors, threshold);\r\n\r\n const guides: SnapGuide[] = [];\r\n if (xSnap) guides.push({ axis: 'x', position: xSnap.position });\r\n if (ySnap) guides.push({ axis: 'y', position: ySnap.position });\r\n\r\n return { dx: xSnap?.delta ?? 0, dy: ySnap?.delta ?? 0, guides };\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport type { CanvasElement, ArrowElement } from '../elements/types';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { SnapGuide } from '../elements/snap-guides';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { rotatePoint } from '../core/geometry';\r\nimport { lineEndpoints } from '../elements/shape-geometry';\r\nimport { renderArrowHandles } from './arrow-handles';\r\n\r\nexport type HandlePosition = 'nw' | 'ne' | 'sw' | 'se';\r\n\r\nexport const HANDLE_SIZE = 8;\r\nexport const HANDLE_HIT_PADDING = 4;\r\nexport const SELECTION_PAD = 4;\r\nexport const ROTATE_HANDLE_OFFSET = 24;\r\nexport const ROTATABLE_TYPES = new Set(['note', 'text', 'image', 'html', 'shape', 'stroke']);\r\n\r\nexport const 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\nexport interface OverlayLayout {\r\n center: Point;\r\n corners: [HandlePosition, Point][];\r\n rotateHandle: Point;\r\n angle: number;\r\n}\r\n\r\nexport function getOverlayLayout(el: CanvasElement, zoom: number): OverlayLayout | null {\r\n const bounds = getElementBounds(el);\r\n if (!bounds) return null;\r\n const angle = el.rotation ?? 0;\r\n const pad = SELECTION_PAD / zoom;\r\n const center = { x: bounds.x + bounds.w / 2, y: bounds.y + bounds.h / 2 };\r\n const raw: [HandlePosition, Point][] = [\r\n ['nw', { x: bounds.x - pad, y: bounds.y - pad }],\r\n ['ne', { x: bounds.x + bounds.w + pad, y: bounds.y - pad }],\r\n ['sw', { x: bounds.x - pad, y: bounds.y + bounds.h + pad }],\r\n ['se', { x: bounds.x + bounds.w + pad, y: bounds.y + bounds.h + pad }],\r\n ];\r\n const corners = raw.map(\r\n ([h, p]) => [h, rotatePoint(p, center, angle)] as [HandlePosition, Point],\r\n );\r\n const topMid = { x: center.x, y: bounds.y - pad - ROTATE_HANDLE_OFFSET / zoom };\r\n const rotateHandle = rotatePoint(topMid, center, angle);\r\n return { center, corners, rotateHandle, angle };\r\n}\r\n\r\nexport function getHandlePositions(bounds: Bounds): [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\nexport function topMidpoint(layout: { corners: [HandlePosition, Point][] }): Point {\r\n const nw = layout.corners.find(([h]) => h === 'nw')?.[1] ?? { x: 0, y: 0 };\r\n const ne = layout.corners.find(([h]) => h === 'ne')?.[1] ?? { x: 0, y: 0 };\r\n return { x: (nw.x + ne.x) / 2, y: (nw.y + ne.y) / 2 };\r\n}\r\n\r\nexport function drawLockBadge(ctx: CanvasRenderingContext2D, at: Point, zoom: number): void {\r\n const r = 9 / zoom;\r\n ctx.save();\r\n ctx.setLineDash([]);\r\n ctx.beginPath();\r\n ctx.arc(at.x, at.y, r, 0, Math.PI * 2);\r\n ctx.fillStyle = '#ffffff';\r\n ctx.fill();\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.lineWidth = 1.5 / zoom;\r\n ctx.stroke();\r\n const bw = 8 / zoom;\r\n const bh = 6 / zoom;\r\n ctx.fillStyle = '#2196F3';\r\n ctx.fillRect(at.x - bw / 2, at.y - bh / 2 + 1 / zoom, bw, bh);\r\n ctx.beginPath();\r\n ctx.arc(at.x, at.y - bh / 2 + 1 / zoom, 2.5 / zoom, Math.PI, 0);\r\n ctx.lineWidth = 1.4 / zoom;\r\n ctx.stroke();\r\n ctx.restore();\r\n}\r\n\r\nexport function renderMarquee(ctx: CanvasRenderingContext2D, rect: Bounds): void {\r\n ctx.save();\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.fillStyle = 'rgba(33, 150, 243, 0.08)';\r\n ctx.lineWidth = 1;\r\n ctx.setLineDash([4, 4]);\r\n ctx.strokeRect(rect.x, rect.y, rect.w, rect.h);\r\n ctx.fillRect(rect.x, rect.y, rect.w, rect.h);\r\n ctx.restore();\r\n}\r\n\r\nexport function renderBindingHighlights(\r\n ctx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n zoom: number,\r\n store: ElementStore,\r\n): void {\r\n if (!arrow.fromBinding && !arrow.toBinding) return;\r\n\r\n const pad = SELECTION_PAD / zoom;\r\n\r\n ctx.save();\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.lineWidth = 2 / zoom;\r\n ctx.setLineDash([]);\r\n\r\n const drawn = new Set<string>();\r\n for (const binding of [arrow.fromBinding, arrow.toBinding]) {\r\n if (!binding || drawn.has(binding.elementId)) continue;\r\n drawn.add(binding.elementId);\r\n\r\n const target = store.getById(binding.elementId);\r\n if (!target) continue;\r\n\r\n const bounds = getElementBounds(target);\r\n if (!bounds) continue;\r\n\r\n ctx.strokeRect(bounds.x - pad, bounds.y - pad, bounds.w + pad * 2, bounds.h + pad * 2);\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nexport function renderSelectionBoxes(\r\n ctx: CanvasRenderingContext2D,\r\n p: { selectedIds: string[]; store: ElementStore; zoom: number },\r\n): void {\r\n if (p.selectedIds.length === 0) return;\r\n\r\n const zoom = p.zoom;\r\n const handleWorldSize = HANDLE_SIZE / zoom;\r\n\r\n ctx.save();\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.lineWidth = 1.5 / zoom;\r\n ctx.setLineDash([4 / zoom, 4 / zoom]);\r\n\r\n for (const id of p.selectedIds) {\r\n const el = p.store.getById(id);\r\n if (!el) continue;\r\n\r\n if (el.type === 'arrow') {\r\n renderArrowHandles(ctx, el, zoom);\r\n renderBindingHighlights(ctx, el, zoom, p.store);\r\n continue;\r\n }\r\n\r\n if (el.type === 'shape' && el.shape === 'line') {\r\n ctx.setLineDash([]);\r\n ctx.fillStyle = '#ffffff';\r\n const r = handleWorldSize / 2;\r\n for (const pt of lineEndpoints(el)) {\r\n ctx.beginPath();\r\n ctx.arc(pt.x, pt.y, r, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.stroke();\r\n }\r\n ctx.setLineDash([4 / zoom, 4 / zoom]);\r\n continue;\r\n }\r\n\r\n const bounds = getElementBounds(el);\r\n if (!bounds) continue;\r\n\r\n const layout = getOverlayLayout(el, zoom);\r\n if (!layout) continue;\r\n\r\n const pad = SELECTION_PAD / zoom;\r\n if (layout.angle === 0) {\r\n ctx.strokeRect(bounds.x - pad, bounds.y - pad, bounds.w + pad * 2, bounds.h + pad * 2);\r\n } else {\r\n const ordered = (['nw', 'ne', 'se', 'sw'] as HandlePosition[])\r\n .map((h) => layout.corners.find(([c]) => c === h)?.[1])\r\n .filter((pp): pp is Point => !!pp);\r\n const [p0, ...others] = ordered;\r\n if (p0) {\r\n ctx.beginPath();\r\n ctx.moveTo(p0.x, p0.y);\r\n for (const pp of others) ctx.lineTo(pp.x, pp.y);\r\n ctx.closePath();\r\n ctx.stroke();\r\n }\r\n }\r\n\r\n if (!el.locked) {\r\n if ('size' in el) {\r\n ctx.setLineDash([]);\r\n ctx.fillStyle = '#ffffff';\r\n const corners = layout.angle === 0 ? getHandlePositions(bounds) : layout.corners;\r\n for (const [, pos] of corners) {\r\n ctx.fillRect(\r\n pos.x - handleWorldSize / 2,\r\n pos.y - handleWorldSize / 2,\r\n handleWorldSize,\r\n handleWorldSize,\r\n );\r\n ctx.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 ctx.setLineDash([4 / zoom, 4 / zoom]);\r\n } else if (el.type === 'template') {\r\n ctx.setLineDash([]);\r\n ctx.fillStyle = '#ffffff';\r\n const hx = bounds.x + bounds.w;\r\n const hy = bounds.y + bounds.h;\r\n ctx.fillRect(\r\n hx - handleWorldSize / 2,\r\n hy - handleWorldSize / 2,\r\n handleWorldSize,\r\n handleWorldSize,\r\n );\r\n ctx.strokeRect(\r\n hx - handleWorldSize / 2,\r\n hy - handleWorldSize / 2,\r\n handleWorldSize,\r\n handleWorldSize,\r\n );\r\n ctx.setLineDash([4 / zoom, 4 / zoom]);\r\n }\r\n\r\n if (p.selectedIds.length === 1 && ROTATABLE_TYPES.has(el.type)) {\r\n const stemStart = topMidpoint(layout);\r\n const stemEnd = layout.rotateHandle;\r\n ctx.beginPath();\r\n ctx.moveTo(stemStart.x, stemStart.y);\r\n ctx.lineTo(stemEnd.x, stemEnd.y);\r\n ctx.stroke();\r\n\r\n ctx.setLineDash([]);\r\n ctx.fillStyle = '#ffffff';\r\n ctx.beginPath();\r\n ctx.arc(stemEnd.x, stemEnd.y, handleWorldSize / 2, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.stroke();\r\n ctx.setLineDash([4 / zoom, 4 / zoom]);\r\n }\r\n }\r\n\r\n if (el.locked) {\r\n const ne = layout.corners.find(([h]) => h === 'ne')?.[1];\r\n if (ne) drawLockBadge(ctx, ne, zoom);\r\n }\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nexport function renderGuideLines(\r\n ctx: CanvasRenderingContext2D,\r\n p: { guides: SnapGuide[]; rect: Bounds | null; currentWorld: Point; zoom: number },\r\n): void {\r\n const zoom = p.zoom;\r\n const rect = p.rect; // cached at drag start (same source as the candidate query)\r\n ctx.save();\r\n ctx.strokeStyle = '#FF4081';\r\n ctx.lineWidth = 1 / zoom;\r\n ctx.setLineDash([]);\r\n for (const g of p.guides) {\r\n ctx.beginPath();\r\n if (g.axis === 'x') {\r\n const y0 = rect ? rect.y : p.currentWorld.y - 1e5;\r\n const y1 = rect ? rect.y + rect.h : p.currentWorld.y + 1e5;\r\n ctx.moveTo(g.position, y0);\r\n ctx.lineTo(g.position, y1);\r\n } else {\r\n const x0 = rect ? rect.x : p.currentWorld.x - 1e5;\r\n const x1 = rect ? rect.x + rect.w : p.currentWorld.x + 1e5;\r\n ctx.moveTo(x0, g.position);\r\n ctx.lineTo(x1, g.position);\r\n }\r\n ctx.stroke();\r\n }\r\n ctx.restore();\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport type { ToolContext } from './types';\r\nimport { distSqToSegment, rotatePoint, rotatedAABB } from '../core/geometry';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { isNearBezier } from '../elements/arrow-geometry';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { hitTestStroke } from '../elements/stroke-hit';\r\nimport { lineEndpoints } from '../elements/shape-geometry';\r\nimport type { HandlePosition } from './select-overlay';\r\nimport {\r\n HANDLE_SIZE,\r\n HANDLE_HIT_PADDING,\r\n ROTATABLE_TYPES,\r\n getOverlayLayout,\r\n} from './select-overlay';\r\n\r\nexport function hitTest(world: Point, ctx: ToolContext): CanvasElement | null {\r\n // Inflate query by hit radius so strokes/arrows near the point are included\r\n const r = 10;\r\n const candidates = ctx.store\r\n .queryRect({ x: world.x - r, y: world.y - r, w: r * 2, h: r * 2 })\r\n .reverse();\r\n for (const el of candidates) {\r\n if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) continue;\r\n if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) continue;\r\n if (el.type === 'grid') continue;\r\n if (isInsideBounds(world, el)) return el;\r\n }\r\n return null;\r\n}\r\n\r\nexport function isInsideBounds(point: Point, el: CanvasElement): boolean {\r\n if (el.type === 'grid') return false;\r\n const angle = el.rotation ?? 0;\r\n if (angle !== 0) {\r\n const b = getElementBounds(el);\r\n if (b) {\r\n point = rotatePoint(point, { x: b.x + b.w / 2, y: b.y + b.h / 2 }, -angle);\r\n }\r\n }\r\n if (el.type === 'shape' && el.shape === 'line') {\r\n const [a, b] = lineEndpoints(el);\r\n const threshold = Math.max(el.strokeWidth / 2, 6);\r\n return distSqToSegment(point, a, b) <= threshold * threshold;\r\n }\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 return hitTestStroke(el, point, 10);\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 if (el.type === 'template') {\r\n const bounds = getElementBounds(el);\r\n if (!bounds) return false;\r\n return (\r\n point.x >= bounds.x &&\r\n point.x <= bounds.x + bounds.w &&\r\n point.y >= bounds.y &&\r\n point.y <= bounds.y + bounds.h\r\n );\r\n }\r\n\r\n return false;\r\n}\r\n\r\nexport function hitTestResizeHandle(\r\n world: Point,\r\n ctx: ToolContext,\r\n selectedIds: string[],\r\n): { elementId: string; handle: HandlePosition } | null {\r\n if (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 selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || !('size' in el)) continue;\r\n if (el.locked) continue;\r\n if (el.type === 'shape' && el.shape === 'line') continue;\r\n\r\n const layout = getOverlayLayout(el, zoom);\r\n if (!layout) continue;\r\n for (const [handle, pos] of layout.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\nexport function hitTestRotateHandle(\r\n world: Point,\r\n ctx: ToolContext,\r\n selectedIds: string[],\r\n): { elementId: string } | null {\r\n if (selectedIds.length !== 1) return null;\r\n const id = selectedIds[0];\r\n if (!id) return null;\r\n const el = ctx.store.getById(id);\r\n if (!el || el.locked || !ROTATABLE_TYPES.has(el.type)) return null;\r\n const layout = getOverlayLayout(el, ctx.camera.zoom);\r\n if (!layout) return null;\r\n const r = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / ctx.camera.zoom;\r\n const dx = world.x - layout.rotateHandle.x;\r\n const dy = world.y - layout.rotateHandle.y;\r\n return dx * dx + dy * dy <= r * r ? { elementId: id } : null;\r\n}\r\n\r\nexport function hitTestLineHandles(\r\n world: Point,\r\n ctx: ToolContext,\r\n selectedIds: string[],\r\n): { elementId: string; fixed: Point } | null {\r\n if (selectedIds.length === 0) return null;\r\n const zoom = ctx.camera.zoom;\r\n const r = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / zoom;\r\n const r2 = r * r;\r\n for (const id of selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || el.type !== 'shape' || el.shape !== 'line') continue;\r\n const [a, b] = lineEndpoints(el);\r\n if ((world.x - a.x) ** 2 + (world.y - a.y) ** 2 <= r2) return { elementId: id, fixed: b };\r\n if ((world.x - b.x) ** 2 + (world.y - b.y) ** 2 <= r2) return { elementId: id, fixed: a };\r\n }\r\n return null;\r\n}\r\n\r\nexport function hitTestTemplateResizeHandle(\r\n world: Point,\r\n ctx: ToolContext,\r\n selectedIds: string[],\r\n): string | null {\r\n if (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 selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || el.type !== 'template') continue;\r\n\r\n const bounds = getElementBounds(el);\r\n if (!bounds) continue;\r\n\r\n const hx = bounds.x + bounds.w;\r\n const hy = bounds.y + bounds.h;\r\n if (Math.abs(world.x - hx) <= handleHalf && Math.abs(world.y - hy) <= handleHalf) {\r\n return id;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport function findElementsInRect(marquee: Bounds, ctx: ToolContext): string[] {\r\n const candidates = ctx.store.queryRect(marquee);\r\n const ids: string[] = [];\r\n for (const el of candidates) {\r\n if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) continue;\r\n if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) continue;\r\n if (el.type === 'grid') continue;\r\n const bounds = getElementBounds(el);\r\n if (bounds && rectsOverlap(marquee, rotatedAABB(bounds, el.rotation ?? 0))) {\r\n ids.push(el.id);\r\n }\r\n }\r\n return ids;\r\n}\r\n\r\nexport function rectsOverlap(a: Bounds, b: Bounds): 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","import type { Point } from '../core/types';\r\nimport type { CanvasElement, TemplateElement } from '../elements/types';\r\nimport { rotatePoint } from '../core/geometry';\r\nimport type { HandlePosition } from './select-overlay';\r\n\r\nexport const MIN_ELEMENT_SIZE = 20;\r\n\r\nexport function anchorOffset(handle: HandlePosition, w: number, h: number): Point {\r\n switch (handle) {\r\n case 'se':\r\n return { x: -w / 2, y: -h / 2 };\r\n case 'sw':\r\n return { x: w / 2, y: -h / 2 };\r\n case 'ne':\r\n return { x: -w / 2, y: h / 2 };\r\n case 'nw':\r\n return { x: w / 2, y: h / 2 };\r\n default:\r\n return { x: 0, y: 0 };\r\n }\r\n}\r\n\r\nexport function computeResize(\r\n el: CanvasElement & { size: { w: number; h: number } },\r\n handle: HandlePosition,\r\n world: Point,\r\n lastWorld: Point,\r\n aspectRatio: number,\r\n shiftKey: boolean,\r\n): { position: { x: number; y: number }; size: { w: number; h: number } } {\r\n const dx = world.x - lastWorld.x;\r\n const dy = world.y - lastWorld.y;\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 (shiftKey && aspectRatio > 0) {\r\n const absDw = Math.abs(w - el.size.w);\r\n const absDh = Math.abs(h - el.size.h);\r\n if (absDw >= absDh) {\r\n h = w / aspectRatio;\r\n } else {\r\n w = h * aspectRatio;\r\n }\r\n if (handle === 'nw' || handle === 'sw') {\r\n x = el.position.x + el.size.w - w;\r\n }\r\n if (handle === 'nw' || handle === 'ne') {\r\n y = el.position.y + el.size.h - h;\r\n }\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 return { position: { x, y }, size: { w, h } };\r\n}\r\n\r\nexport function computeRotatedResize(\r\n el: CanvasElement & { size: { w: number; h: number } },\r\n handle: HandlePosition,\r\n angle: number,\r\n world: Point,\r\n lastWorld: Point,\r\n aspectRatio: number,\r\n shiftKey: boolean,\r\n): { position: { x: number; y: number }; size: { w: number; h: number } } {\r\n const wdx = world.x - lastWorld.x;\r\n const wdy = world.y - lastWorld.y;\r\n\r\n // world delta → element local frame (inverse rotation of the vector)\r\n const cosN = Math.cos(-angle);\r\n const sinN = Math.sin(-angle);\r\n const ldx = wdx * cosN - wdy * sinN;\r\n const ldy = wdx * sinN + wdy * cosN;\r\n\r\n let w = el.size.w;\r\n let h = el.size.h;\r\n switch (handle) {\r\n case 'se':\r\n w += ldx;\r\n h += ldy;\r\n break;\r\n case 'sw':\r\n w -= ldx;\r\n h += ldy;\r\n break;\r\n case 'ne':\r\n w += ldx;\r\n h -= ldy;\r\n break;\r\n case 'nw':\r\n w -= ldx;\r\n h -= ldy;\r\n break;\r\n }\r\n\r\n if (shiftKey && aspectRatio > 0) {\r\n const absDw = Math.abs(w - el.size.w);\r\n const absDh = Math.abs(h - el.size.h);\r\n if (absDw >= absDh) h = w / aspectRatio;\r\n else w = h * aspectRatio;\r\n }\r\n w = Math.max(w, MIN_ELEMENT_SIZE);\r\n h = Math.max(h, MIN_ELEMENT_SIZE);\r\n\r\n // anchor (opposite corner) fixed in world space, computed from OLD geometry\r\n const oldCenter = { x: el.position.x + el.size.w / 2, y: el.position.y + el.size.h / 2 };\r\n const oldAnchorLocal = anchorOffset(handle, el.size.w, el.size.h);\r\n const anchorWorld = rotatePoint(\r\n { x: oldCenter.x + oldAnchorLocal.x, y: oldCenter.y + oldAnchorLocal.y },\r\n oldCenter,\r\n angle,\r\n );\r\n\r\n // new center so the anchor stays put: anchorWorld = newCenter + R(angle)·newAnchorLocal\r\n const newAnchorLocal = anchorOffset(handle, w, h);\r\n const cos = Math.cos(angle);\r\n const sin = Math.sin(angle);\r\n const rotatedAnchor = {\r\n x: newAnchorLocal.x * cos - newAnchorLocal.y * sin,\r\n y: newAnchorLocal.x * sin + newAnchorLocal.y * cos,\r\n };\r\n const newCenter = { x: anchorWorld.x - rotatedAnchor.x, y: anchorWorld.y - rotatedAnchor.y };\r\n const position = { x: newCenter.x - w / 2, y: newCenter.y - h / 2 };\r\n\r\n return { position, size: { w, h } };\r\n}\r\n\r\nexport interface TemplateResizeOptions {\r\n snapToGrid?: boolean;\r\n gridSize?: number;\r\n gridType?: 'square' | 'hex';\r\n}\r\n\r\nexport function computeTemplateResize(\r\n el: TemplateElement,\r\n world: Point,\r\n opts: TemplateResizeOptions,\r\n): Record<string, unknown> | null {\r\n const dx = world.x - el.position.x;\r\n const dy = world.y - el.position.y;\r\n let newRadius = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (opts.snapToGrid && opts.gridSize && opts.gridSize > 0) {\r\n const snapUnit = opts.gridType === 'hex' ? Math.sqrt(3) * opts.gridSize : opts.gridSize;\r\n newRadius = Math.max(snapUnit, Math.round(newRadius / snapUnit) * snapUnit);\r\n }\r\n newRadius = Math.max(MIN_ELEMENT_SIZE, newRadius);\r\n\r\n const updates: Record<string, unknown> = { radius: newRadius };\r\n if (el.feetPerCell != null && opts.gridSize && opts.gridSize > 0) {\r\n const snapUnit = opts.gridType === 'hex' ? Math.sqrt(3) * opts.gridSize : opts.gridSize;\r\n updates.radiusFeet = (newRadius / snapUnit) * el.feetPerCell;\r\n }\r\n\r\n return updates;\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { smartSnap } from '../core/snap';\r\nimport { normalizeAngle } from '../core/geometry';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { updateArrowsBoundToElements } from '../elements/arrow-binding';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { expandToGroups } from '../elements/group';\r\nimport { getElementsBoundingBox } from '../elements/bounds';\r\nimport { lineFromEndpoints } from '../elements/shape-geometry';\r\nimport { translateElementPatch } from '../elements/translate';\r\nimport {\r\n type ArrowHandle,\r\n hitTestArrowHandles,\r\n applyArrowHandleDrag,\r\n getArrowHandleCursor,\r\n getArrowHandleDragTarget,\r\n} from './arrow-handles';\r\nimport { computeSnapGuides } from '../elements/snap-guides';\r\nimport type { SnapGuide } from '../elements/snap-guides';\r\nimport {\r\n hitTest,\r\n hitTestResizeHandle,\r\n hitTestRotateHandle,\r\n hitTestLineHandles,\r\n hitTestTemplateResizeHandle,\r\n findElementsInRect,\r\n} from './select-hit';\r\nimport type { HandlePosition, OverlayLayout } from './select-overlay';\r\nimport {\r\n HANDLE_CURSORS,\r\n getOverlayLayout,\r\n renderMarquee,\r\n renderSelectionBoxes,\r\n renderGuideLines,\r\n} from './select-overlay';\r\nimport { computeResize, computeRotatedResize, computeTemplateResize } from './select-resize';\r\n\r\nconst SNAP_PX = 6;\r\nconst ROTATE_SNAP = Math.PI / 12; // 15°\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: 'resizing-template'; elementId: string }\r\n | { type: 'arrow-handle'; elementId: string; handle: ArrowHandle }\r\n | { type: 'line-handle'; elementId: string; fixed: Point }\r\n | {\r\n type: 'rotating';\r\n elementId: string;\r\n center: Point;\r\n startPointerAngle: number;\r\n startRotation: number;\r\n };\r\n\r\nexport class SelectTool implements Tool {\r\n readonly name = 'select';\r\n private _selectedIds: string[] = [];\r\n private selectionListeners = new Set<() => void>();\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 private pendingSingleSelectId: string | null = null;\r\n private hasDragged = false;\r\n private activeGuides: SnapGuide[] = [];\r\n private dragSnapTargets: Bounds[] | null = null;\r\n private dragVisibleRect: Bounds | null = null;\r\n private resizeAspectRatio = 0;\r\n private hoveredId: string | null = null;\r\n\r\n get selectedIds(): string[] {\r\n return this._selectedIds;\r\n }\r\n\r\n onSelectionChange(listener: () => void): () => void {\r\n this.selectionListeners.add(listener);\r\n return () => {\r\n this.selectionListeners.delete(listener);\r\n };\r\n }\r\n\r\n private setSelectedIds(ids: string[]): void {\r\n const prev = this._selectedIds;\r\n if (prev.length === ids.length && prev.every((id, i) => id === ids[i])) return;\r\n this._selectedIds = ids;\r\n for (const listener of this.selectionListeners) listener();\r\n }\r\n\r\n setSelection(ids: string[]): void {\r\n this.setSelectedIds(ids);\r\n this.ctx?.requestRender();\r\n }\r\n\r\n selectAtPoint(world: Point, ctx: ToolContext): void {\r\n const hit = hitTest(world, ctx);\r\n if (!hit) {\r\n this.setSelectedIds([]);\r\n return;\r\n }\r\n if (this._selectedIds.includes(hit.id)) return;\r\n this.setSelectedIds(expandToGroups([hit.id], ctx.store.getAll()));\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.setSelectedIds([]);\r\n this.mode = { type: 'idle' };\r\n this.hoveredId = null;\r\n this.activeGuides = [];\r\n this.dragSnapTargets = null;\r\n this.dragVisibleRect = null;\r\n ctx.setCursor?.('default');\r\n }\r\n\r\n private snap(point: Point, ctx: ToolContext): Point {\r\n return smartSnap(point, ctx);\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.ctx = ctx;\r\n this.setHovered(null, ctx);\r\n this.dragSnapTargets = null;\r\n this.dragVisibleRect = null;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.lastWorld = this.snap(world, ctx);\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 lineHit = hitTestLineHandles(world, ctx, this._selectedIds);\r\n if (lineHit) {\r\n this.mode = { type: 'line-handle', elementId: lineHit.elementId, fixed: lineHit.fixed };\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n const templateResizeHit = hitTestTemplateResizeHandle(world, ctx, this._selectedIds);\r\n if (templateResizeHit) {\r\n this.mode = { type: 'resizing-template', elementId: templateResizeHit };\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n const rotateHit = hitTestRotateHandle(world, ctx, this._selectedIds);\r\n if (rotateHit) {\r\n const el = ctx.store.getById(rotateHit.elementId);\r\n const layout = el ? this.getOverlayLayout(el, ctx.camera.zoom) : null;\r\n if (el && layout) {\r\n this.mode = {\r\n type: 'rotating',\r\n elementId: rotateHit.elementId,\r\n center: layout.center,\r\n startPointerAngle: Math.atan2(world.y - layout.center.y, world.x - layout.center.x),\r\n startRotation: el.rotation ?? 0,\r\n };\r\n ctx.requestRender();\r\n return;\r\n }\r\n }\r\n\r\n const resizeHit = hitTestResizeHandle(world, ctx, this._selectedIds);\r\n if (resizeHit) {\r\n const el = ctx.store.getById(resizeHit.elementId);\r\n if (el && 'size' in el) {\r\n this.resizeAspectRatio = el.size.h > 0 ? el.size.w / el.size.h : 0;\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 this.pendingSingleSelectId = null;\r\n this.hasDragged = false;\r\n const hit = hitTest(world, ctx);\r\n if (hit) {\r\n const all = ctx.store.getAll();\r\n const alreadySelected = this._selectedIds.includes(hit.id);\r\n if (state.shiftKey) {\r\n if (alreadySelected) {\r\n const grp = new Set(expandToGroups([hit.id], all));\r\n this.setSelectedIds(this._selectedIds.filter((id) => !grp.has(id)));\r\n this.mode = { type: 'idle' };\r\n } else {\r\n this.setSelectedIds(expandToGroups([...this._selectedIds, hit.id], all));\r\n this.mode = hit.locked ? { type: 'idle' } : { type: 'dragging' };\r\n }\r\n } else {\r\n if (!alreadySelected) {\r\n this.setSelectedIds(expandToGroups([hit.id], all));\r\n } else if (this._selectedIds.length > 1) {\r\n this.pendingSingleSelectId = hit.id;\r\n }\r\n this.mode = hit.locked ? { type: 'idle' } : { type: 'dragging' };\r\n }\r\n } else {\r\n this.setSelectedIds([]);\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 === 'line-handle') {\r\n ctx.setCursor?.('grabbing');\r\n const el = ctx.store.getById(this.mode.elementId);\r\n if (el && el.type === 'shape') {\r\n ctx.store.update(el.id, lineFromEndpoints(this.mode.fixed, world));\r\n }\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'resizing-template') {\r\n ctx.setCursor?.('nwse-resize');\r\n this.handleTemplateResize(world, ctx);\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'rotating') {\r\n const { elementId, center, startPointerAngle, startRotation } = this.mode;\r\n const a = Math.atan2(world.y - center.y, world.x - center.x);\r\n let next = startRotation + (a - startPointerAngle);\r\n if (state.shiftKey) next = Math.round(next / ROTATE_SNAP) * ROTATE_SNAP;\r\n ctx.store.update(elementId, { rotation: normalizeAngle(next) });\r\n ctx.requestRender();\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, state.shiftKey);\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'dragging' && this._selectedIds.length > 0) {\r\n this.hasDragged = true;\r\n ctx.setCursor?.('move');\r\n const snapped = this.snap(world, ctx);\r\n const dx = snapped.x - this.lastWorld.x;\r\n const dy = snapped.y - this.lastWorld.y;\r\n this.lastWorld = snapped;\r\n\r\n let adjDx = dx;\r\n let adjDy = dy;\r\n this.activeGuides = [];\r\n if (ctx.smartGuides) {\r\n // Candidates (non-selected visible elements) and the viewport rect don't change\r\n // during a single-pointer drag, so compute them once per drag and reuse each frame.\r\n if (this.dragSnapTargets === null) {\r\n const selSet = new Set(this._selectedIds);\r\n this.dragVisibleRect = ctx.getVisibleRect?.() ?? null;\r\n const candidates = (\r\n this.dragVisibleRect ? ctx.store.queryRect(this.dragVisibleRect) : ctx.store.getAll()\r\n ).filter((el) => !selSet.has(el.id) && el.type !== 'grid');\r\n const targets: Bounds[] = [];\r\n for (const el of candidates) {\r\n const b = getElementBounds(el);\r\n if (b) targets.push(b);\r\n }\r\n this.dragSnapTargets = targets;\r\n }\r\n const selectedEls = this._selectedIds\r\n .map((id) => ctx.store.getById(id))\r\n .filter((el): el is CanvasElement => !!el && !el.locked);\r\n const base = getElementsBoundingBox(selectedEls);\r\n if (base) {\r\n const moving: Bounds = { x: base.x + dx, y: base.y + dy, w: base.w, h: base.h };\r\n const res = computeSnapGuides(moving, this.dragSnapTargets, SNAP_PX / ctx.camera.zoom);\r\n adjDx = dx + res.dx;\r\n adjDy = dy + res.dy;\r\n this.activeGuides = res.guides;\r\n }\r\n }\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 if (el.fromBinding || el.toBinding) {\r\n continue;\r\n }\r\n\r\n ctx.store.update(id, {\r\n position: { x: el.position.x + adjDx, y: el.position.y + adjDy },\r\n from: { x: el.from.x + adjDx, y: el.from.y + adjDy },\r\n to: { x: el.to.x + adjDx, y: el.to.y + adjDy },\r\n });\r\n } else if (!ctx.smartGuides && ctx.gridType && 'size' in el) {\r\n const centerX = el.position.x + el.size.w / 2 + adjDx;\r\n const centerY = el.position.y + el.size.h / 2 + adjDy;\r\n const snappedCenter = this.snap({ x: centerX, y: centerY }, ctx);\r\n ctx.store.update(id, {\r\n position: {\r\n x: snappedCenter.x - el.size.w / 2,\r\n y: snappedCenter.y - el.size.h / 2,\r\n },\r\n });\r\n } else {\r\n ctx.store.update(id, {\r\n position: { x: el.position.x + adjDx, y: el.position.y + adjDy },\r\n });\r\n }\r\n }\r\n\r\n this.updateArrowsBoundTo(this._selectedIds, ctx);\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.setSelectedIds(expandToGroups(findElementsInRect(rect, ctx), ctx.store.getAll()));\r\n }\r\n ctx.requestRender();\r\n }\r\n\r\n if (!this.hasDragged && this.pendingSingleSelectId !== null) {\r\n this.setSelectedIds(expandToGroups([this.pendingSingleSelectId], ctx.store.getAll()));\r\n }\r\n this.pendingSingleSelectId = null;\r\n this.hasDragged = false;\r\n\r\n const resizedNoteId = this.mode.type === 'resizing' ? this.mode.elementId : null;\r\n\r\n this.mode = { type: 'idle' };\r\n this.activeGuides = [];\r\n this.dragSnapTargets = null;\r\n this.dragVisibleRect = null;\r\n ctx.requestRender();\r\n ctx.setCursor?.('default');\r\n\r\n if (resizedNoteId !== null) {\r\n const el = ctx.store.getById(resizedNoteId);\r\n // Runs during tool pointer-up, inside the InputHandler resize transaction, so the\r\n // height fit coalesces into the same undo step as the resize.\r\n if (el?.type === 'note') ctx.fitNoteHeight?.(resizedNoteId);\r\n }\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 const hoverId = this.updateHoverCursor(world, ctx);\r\n this.setHovered(hoverId, ctx);\r\n }\r\n\r\n renderOverlay(canvasCtx: CanvasRenderingContext2D): void {\r\n if (this.mode.type === 'marquee') {\r\n const rect = this.getMarqueeRect();\r\n if (rect) renderMarquee(canvasCtx, rect);\r\n }\r\n if (this.ctx)\r\n renderSelectionBoxes(canvasCtx, {\r\n selectedIds: this._selectedIds,\r\n store: this.ctx.store,\r\n zoom: this.ctx.camera.zoom,\r\n });\r\n\r\n if (this.mode.type === 'arrow-handle' && this.ctx) {\r\n const target = getArrowHandleDragTarget(\r\n this.mode.handle,\r\n this.mode.elementId,\r\n this.currentWorld,\r\n this.ctx,\r\n );\r\n if (target) {\r\n canvasCtx.save();\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.lineWidth = 2 / this.ctx.camera.zoom;\r\n canvasCtx.setLineDash([]);\r\n canvasCtx.strokeRect(target.x, target.y, target.w, target.h);\r\n canvasCtx.restore();\r\n }\r\n }\r\n\r\n if (this.hoveredId && this.ctx && this.mode.type === 'idle') {\r\n if (!this._selectedIds.includes(this.hoveredId)) {\r\n const el = this.ctx.store.getById(this.hoveredId);\r\n if (el) {\r\n const b = getElementBounds(el);\r\n if (b) {\r\n canvasCtx.save();\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.globalAlpha = 0.35;\r\n canvasCtx.lineWidth = 1.5 / this.ctx.camera.zoom;\r\n canvasCtx.setLineDash([]);\r\n canvasCtx.strokeRect(b.x, b.y, b.w, b.h);\r\n canvasCtx.restore();\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (this.mode.type === 'dragging' && this.ctx && this.activeGuides.length)\r\n renderGuideLines(canvasCtx, {\r\n guides: this.activeGuides,\r\n rect: this.dragVisibleRect,\r\n currentWorld: this.currentWorld,\r\n zoom: this.ctx.camera.zoom,\r\n });\r\n }\r\n\r\n private updateArrowsBoundTo(ids: Iterable<string>, ctx: ToolContext): void {\r\n updateArrowsBoundToElements(ids, ctx.store);\r\n }\r\n\r\n nudgeSelection(dx: number, dy: number, ctx: ToolContext): boolean {\r\n let moved = false;\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 if (el.type === 'arrow' && (el.fromBinding || el.toBinding)) continue;\r\n ctx.store.update(id, translateElementPatch(el, dx, dy));\r\n moved = true;\r\n }\r\n\r\n if (moved) {\r\n this.updateArrowsBoundTo(this._selectedIds, ctx);\r\n ctx.requestRender();\r\n }\r\n return moved;\r\n }\r\n\r\n private updateHoverCursor(world: Point, ctx: ToolContext): string | null {\r\n const arrowHit = hitTestArrowHandles(world, this._selectedIds, ctx);\r\n if (arrowHit) {\r\n ctx.setCursor?.(getArrowHandleCursor(arrowHit.handle, false));\r\n return null;\r\n }\r\n\r\n if (hitTestLineHandles(world, ctx, this._selectedIds)) {\r\n ctx.setCursor?.('grab');\r\n return null;\r\n }\r\n\r\n const templateResizeHit = hitTestTemplateResizeHandle(world, ctx, this._selectedIds);\r\n if (templateResizeHit) {\r\n ctx.setCursor?.('nwse-resize');\r\n return null;\r\n }\r\n\r\n if (hitTestRotateHandle(world, ctx, this._selectedIds)) {\r\n ctx.setCursor?.('grab');\r\n return null;\r\n }\r\n\r\n const resizeHit = hitTestResizeHandle(world, ctx, this._selectedIds);\r\n if (resizeHit) {\r\n ctx.setCursor?.(HANDLE_CURSORS[resizeHit.handle]);\r\n return null;\r\n }\r\n\r\n const hit = hitTest(world, ctx);\r\n ctx.setCursor?.(hit ? 'move' : 'default');\r\n return hit ? hit.id : null;\r\n }\r\n\r\n private setHovered(id: string | null, ctx: ToolContext): void {\r\n if (this.hoveredId === id) return;\r\n this.hoveredId = id;\r\n ctx.requestRender();\r\n }\r\n\r\n private handleResize(world: Point, ctx: ToolContext, shiftKey = false): 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 angle = el.rotation ?? 0;\r\n const patch =\r\n angle !== 0\r\n ? computeRotatedResize(\r\n el,\r\n this.mode.handle,\r\n angle,\r\n world,\r\n this.lastWorld,\r\n this.resizeAspectRatio,\r\n shiftKey,\r\n )\r\n : computeResize(\r\n el,\r\n this.mode.handle,\r\n world,\r\n this.lastWorld,\r\n this.resizeAspectRatio,\r\n shiftKey,\r\n );\r\n\r\n this.lastWorld = world;\r\n ctx.store.update(this.mode.elementId, patch);\r\n this.updateArrowsBoundTo([this.mode.elementId], ctx);\r\n ctx.requestRender();\r\n }\r\n\r\n private getOverlayLayout(el: CanvasElement, zoom: number): OverlayLayout | null {\r\n return getOverlayLayout(el, zoom);\r\n }\r\n\r\n private handleTemplateResize(world: Point, ctx: ToolContext): void {\r\n if (this.mode.type !== 'resizing-template') return;\r\n\r\n const el = ctx.store.getById(this.mode.elementId);\r\n if (!el || el.type !== 'template' || el.locked) return;\r\n\r\n const patch = computeTemplateResize(el, world, {\r\n snapToGrid: ctx.snapToGrid,\r\n gridSize: ctx.gridSize,\r\n gridType: ctx.gridType,\r\n });\r\n if (patch) {\r\n ctx.store.update(this.mode.elementId, patch);\r\n ctx.requestRender();\r\n }\r\n }\r\n\r\n private getMarqueeRect(): Bounds | 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","import type { Point } from '../core/types';\r\nimport type { Binding, CanvasElement } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createArrow } from '../elements/element-factory';\r\nimport { findBindTarget, getElementCenter } from '../elements/arrow-binding';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nconst BIND_THRESHOLD = 20;\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 private fromBinding: Binding | undefined;\r\n private fromTarget: CanvasElement | null = null;\r\n private toTarget: CanvasElement | null = null;\r\n private optionListeners = new Set<() => void>();\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 getOptions(): ArrowToolOptions {\r\n return { color: this.color, width: this.width };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\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 this.notifyOptionsChange();\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n\r\n private layerFilter(ctx: ToolContext): ((el: CanvasElement) => boolean) | undefined {\r\n const activeLayerId = ctx.activeLayerId;\r\n if (!activeLayerId && !ctx.isLayerVisible && !ctx.isLayerLocked) return undefined;\r\n return (el: CanvasElement) => {\r\n if (activeLayerId && el.layerId !== activeLayerId) return false;\r\n if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) return false;\r\n if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) return false;\r\n return true;\r\n };\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 threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n const filter = this.layerFilter(ctx);\r\n\r\n const target = findBindTarget(world, ctx.store, threshold, undefined, filter);\r\n if (target) {\r\n this.start = getElementCenter(target);\r\n this.fromBinding = { elementId: target.id };\r\n this.fromTarget = target;\r\n } else {\r\n this.start = smartSnap(world, ctx);\r\n this.fromBinding = undefined;\r\n this.fromTarget = null;\r\n }\r\n this.end = { ...this.start };\r\n this.toTarget = null;\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 threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n const excludeId = this.fromBinding?.elementId;\r\n const filter = this.layerFilter(ctx);\r\n\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, filter);\r\n if (target) {\r\n this.end = getElementCenter(target);\r\n this.toTarget = target;\r\n } else {\r\n this.end = smartSnap(world, ctx);\r\n this.toTarget = null;\r\n }\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 position: this.start,\r\n color: this.color,\r\n width: this.width,\r\n fromBinding: this.fromBinding,\r\n toBinding: this.toTarget ? { elementId: this.toTarget.id } : undefined,\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(arrow);\r\n this.fromTarget = null;\r\n this.toTarget = null;\r\n ctx.requestRender();\r\n ctx.switchTool?.('select');\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\r\n if (this.fromTarget) {\r\n const bounds = getElementBounds(this.fromTarget);\r\n if (bounds) {\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.lineWidth = 2;\r\n ctx.setLineDash([]);\r\n ctx.strokeRect(bounds.x, bounds.y, bounds.w, bounds.h);\r\n }\r\n }\r\n\r\n if (this.toTarget) {\r\n const bounds = getElementBounds(this.toTarget);\r\n if (bounds) {\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.lineWidth = 2;\r\n ctx.setLineDash([]);\r\n ctx.strokeRect(bounds.x, bounds.y, bounds.w, bounds.h);\r\n }\r\n }\r\n\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, DEFAULT_NOTE_FONT_SIZE } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nexport interface NoteToolOptions {\r\n backgroundColor?: string;\r\n textColor?: string;\r\n size?: Size;\r\n fontSize?: number;\r\n}\r\n\r\nexport class NoteTool implements Tool {\r\n readonly name = 'note';\r\n private backgroundColor: string;\r\n private textColor: string;\r\n private size: Size;\r\n private fontSize: number;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: NoteToolOptions = {}) {\r\n this.backgroundColor = options.backgroundColor ?? '#ffeb3b';\r\n this.textColor = options.textColor ?? '#000000';\r\n this.size = options.size ?? { w: 200, h: 100 };\r\n this.fontSize = options.fontSize ?? DEFAULT_NOTE_FONT_SIZE;\r\n }\r\n\r\n getOptions(): NoteToolOptions {\r\n return {\r\n backgroundColor: this.backgroundColor,\r\n textColor: this.textColor,\r\n size: { ...this.size },\r\n fontSize: this.fontSize,\r\n };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n setOptions(options: NoteToolOptions): void {\r\n if (options.backgroundColor !== undefined) this.backgroundColor = options.backgroundColor;\r\n if (options.textColor !== undefined) this.textColor = options.textColor;\r\n if (options.size !== undefined) this.size = options.size;\r\n if (options.fontSize !== undefined) this.fontSize = options.fontSize;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\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 let world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n world = smartSnap(world, ctx);\r\n const note = createNote({\r\n position: world,\r\n size: { ...this.size },\r\n backgroundColor: this.backgroundColor,\r\n textColor: this.textColor,\r\n fontSize: this.fontSize,\r\n layerId: ctx.activeLayerId ?? '',\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 { Tool, ToolContext, PointerState } from './types';\r\nimport { createText } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nexport interface TextToolOptions {\r\n fontSize?: number;\r\n color?: string;\r\n textAlign?: 'left' | 'center' | 'right';\r\n}\r\n\r\nexport class TextTool implements Tool {\r\n readonly name = 'text';\r\n private fontSize: number;\r\n private color: string;\r\n private textAlign: 'left' | 'center' | 'right';\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: TextToolOptions = {}) {\r\n this.fontSize = options.fontSize ?? 16;\r\n this.color = options.color ?? '#1a1a1a';\r\n this.textAlign = options.textAlign ?? 'left';\r\n }\r\n\r\n getOptions(): TextToolOptions {\r\n return { fontSize: this.fontSize, color: this.color, textAlign: this.textAlign };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n setOptions(options: TextToolOptions): void {\r\n if (options.fontSize !== undefined) this.fontSize = options.fontSize;\r\n if (options.color !== undefined) this.color = options.color;\r\n if (options.textAlign !== undefined) this.textAlign = options.textAlign;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n\r\n onActivate(ctx: ToolContext): void {\r\n ctx.setCursor?.('text');\r\n }\r\n\r\n onDeactivate(ctx: ToolContext): void {\r\n ctx.setCursor?.('default');\r\n }\r\n\r\n onPointerDown(_state: PointerState, _ctx: ToolContext): void {\r\n // Text is placed on pointer up\r\n }\r\n\r\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\r\n // No drag behavior for text placement\r\n }\r\n\r\n onPointerUp(state: PointerState, ctx: ToolContext): void {\r\n let world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n world = smartSnap(world, ctx);\r\n const textEl = createText({\r\n position: world,\r\n fontSize: this.fontSize,\r\n color: this.color,\r\n textAlign: this.textAlign,\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(textEl);\r\n ctx.requestRender();\r\n\r\n ctx.switchTool?.('select');\r\n ctx.editElement?.(textEl.id);\r\n }\r\n}\r\n","import type { Size } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createImage } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nexport interface ImageToolOptions {\r\n size?: Size;\r\n}\r\n\r\nexport class ImageTool implements Tool {\r\n readonly name = 'image';\r\n private size: Size;\r\n private src: string | null = null;\r\n\r\n constructor(options: ImageToolOptions = {}) {\r\n this.size = options.size ?? { w: 300, h: 200 };\r\n }\r\n\r\n setSrc(src: string): void {\r\n this.src = src;\r\n }\r\n\r\n onPointerDown(_state: PointerState, _ctx: ToolContext): void {\r\n // No action on pointer down — image is placed on pointer up\r\n }\r\n\r\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\r\n // No action on pointer move\r\n }\r\n\r\n onPointerUp(state: PointerState, ctx: ToolContext): void {\r\n if (!this.src) return;\r\n\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const snapped = smartSnap(world, ctx);\r\n const image = createImage({\r\n position: {\r\n x: snapped.x - this.size.w / 2,\r\n y: snapped.y - this.size.h / 2,\r\n },\r\n size: { ...this.size },\r\n src: this.src,\r\n });\r\n ctx.store.add(image);\r\n ctx.requestRender();\r\n\r\n this.src = null;\r\n ctx.switchTool?.('select');\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { ShapeKind } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createShape } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nfunction snapTo45(start: Point, end: Point): Point {\r\n const dx = end.x - start.x;\r\n const dy = end.y - start.y;\r\n const len = Math.hypot(dx, dy);\r\n if (len === 0) return { ...end };\r\n const step = Math.PI / 4;\r\n const angle = Math.round(Math.atan2(dy, dx) / step) * step;\r\n return { x: start.x + Math.cos(angle) * len, y: start.y + Math.sin(angle) * len };\r\n}\r\n\r\nexport interface ShapeToolOptions {\r\n shape?: ShapeKind;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n fillColor?: string;\r\n}\r\n\r\nexport class ShapeTool implements Tool {\r\n readonly name = 'shape';\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 shiftHeld = false;\r\n private shape: ShapeKind;\r\n private strokeColor: string;\r\n private strokeWidth: number;\r\n private fillColor: string;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: ShapeToolOptions = {}) {\r\n this.shape = options.shape ?? 'rectangle';\r\n this.strokeColor = options.strokeColor ?? '#000000';\r\n this.strokeWidth = options.strokeWidth ?? 2;\r\n this.fillColor = options.fillColor ?? 'none';\r\n }\r\n\r\n getOptions(): ShapeToolOptions {\r\n return {\r\n shape: this.shape,\r\n strokeColor: this.strokeColor,\r\n strokeWidth: this.strokeWidth,\r\n fillColor: this.fillColor,\r\n };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n setOptions(options: ShapeToolOptions): void {\r\n if (options.shape !== undefined) this.shape = options.shape;\r\n if (options.strokeColor !== undefined) this.strokeColor = options.strokeColor;\r\n if (options.strokeWidth !== undefined) this.strokeWidth = options.strokeWidth;\r\n if (options.fillColor !== undefined) this.fillColor = options.fillColor;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n onActivate(_ctx: ToolContext): void {\r\n if (typeof window !== 'undefined') {\r\n window.addEventListener('keydown', this.onKeyDown);\r\n window.addEventListener('keyup', this.onKeyUp);\r\n }\r\n }\r\n\r\n onDeactivate(_ctx: ToolContext): void {\r\n this.shiftHeld = false;\r\n if (typeof window !== 'undefined') {\r\n window.removeEventListener('keydown', this.onKeyDown);\r\n window.removeEventListener('keyup', this.onKeyUp);\r\n }\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.drawing = true;\r\n this.start = this.snap(ctx.camera.screenToWorld({ x: state.x, y: state.y }), ctx);\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 = this.snap(ctx.camera.screenToWorld({ x: state.x, y: state.y }), ctx);\r\n if (this.shape === 'line' && this.shiftHeld) {\r\n this.end = snapTo45(this.start, this.end);\r\n }\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 const { position, size } = this.computeRect();\r\n const isLine = this.shape === 'line';\r\n if (isLine ? size.w === 0 && size.h === 0 : size.w === 0 || size.h === 0) return;\r\n\r\n const shape = createShape({\r\n position,\r\n size,\r\n shape: this.shape,\r\n strokeColor: this.strokeColor,\r\n strokeWidth: this.strokeWidth,\r\n fillColor: this.fillColor,\r\n ...(isLine ? { flip: this.end.x > this.start.x !== this.end.y > this.start.y } : {}),\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(shape);\r\n ctx.requestRender();\r\n ctx.switchTool?.('select');\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (!this.drawing) return;\r\n\r\n const { position, size } = this.computeRect();\r\n if (size.w === 0 && size.h === 0) return;\r\n\r\n ctx.save();\r\n ctx.globalAlpha = 0.5;\r\n ctx.strokeStyle = this.strokeColor;\r\n ctx.lineWidth = this.strokeWidth;\r\n\r\n if (this.fillColor !== 'none') {\r\n ctx.fillStyle = this.fillColor;\r\n }\r\n\r\n switch (this.shape) {\r\n case 'rectangle':\r\n if (this.fillColor !== 'none') {\r\n ctx.fillRect(position.x, position.y, size.w, size.h);\r\n }\r\n ctx.strokeRect(position.x, position.y, size.w, size.h);\r\n break;\r\n case 'ellipse': {\r\n const cx = position.x + size.w / 2;\r\n const cy = position.y + size.h / 2;\r\n ctx.beginPath();\r\n ctx.ellipse(cx, cy, size.w / 2, size.h / 2, 0, 0, Math.PI * 2);\r\n if (this.fillColor !== 'none') ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n case 'line':\r\n ctx.lineCap = 'round';\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 break;\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private computeRect(): { position: Point; size: { w: number; h: number } } {\r\n let x = Math.min(this.start.x, this.end.x);\r\n let y = Math.min(this.start.y, this.end.y);\r\n let w = Math.abs(this.end.x - this.start.x);\r\n let h = Math.abs(this.end.y - this.start.y);\r\n\r\n if (this.shiftHeld && this.shape !== 'line') {\r\n const side = Math.max(w, h);\r\n w = side;\r\n h = side;\r\n x = this.end.x >= this.start.x ? this.start.x : this.start.x - side;\r\n y = this.end.y >= this.start.y ? this.start.y : this.start.y - side;\r\n }\r\n\r\n return { position: { x, y }, size: { w, h } };\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n\r\n private snap(point: Point, ctx: ToolContext): Point {\r\n return smartSnap(point, ctx);\r\n }\r\n\r\n private onKeyDown = (e: KeyboardEvent): void => {\r\n if (e.key === 'Shift') this.shiftHeld = true;\r\n };\r\n\r\n private onKeyUp = (e: KeyboardEvent): void => {\r\n if (e.key === 'Shift') this.shiftHeld = false;\r\n };\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { HexOrientation } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { snapPoint, snapToHexCenter } from '../core/snap';\r\nimport { getHexDistance } from '../elements/hex-fill';\r\n\r\nexport interface MeasureToolOptions {\r\n feetPerCell?: number;\r\n}\r\n\r\nexport interface Measurement {\r\n start: Point;\r\n end: Point;\r\n worldDistance: number;\r\n cells: number;\r\n feet: number;\r\n}\r\n\r\nexport class MeasureTool implements Tool {\r\n readonly name = 'measure';\r\n private start: Point | null = null;\r\n private end: Point | null = null;\r\n private gridSize = 1;\r\n private gridType: 'square' | 'hex' | undefined;\r\n private hexOrientation: HexOrientation | undefined;\r\n private feetPerCell: number;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: MeasureToolOptions = {}) {\r\n this.feetPerCell = options.feetPerCell ?? 5;\r\n }\r\n\r\n getOptions(): MeasureToolOptions {\r\n return { feetPerCell: this.feetPerCell };\r\n }\r\n\r\n setOptions(options: MeasureToolOptions): void {\r\n if (options.feetPerCell !== undefined) this.feetPerCell = options.feetPerCell;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.gridSize = ctx.gridSize ?? 1;\r\n this.gridType = ctx.gridType;\r\n this.hexOrientation = ctx.hexOrientation;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.start = this.snapToGrid(world, ctx);\r\n this.end = { ...this.start };\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.start) return;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.end = this.snapToGrid(world, ctx);\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\r\n if (!this.start) return;\r\n this.start = null;\r\n this.end = null;\r\n ctx.requestRender();\r\n }\r\n\r\n onDeactivate(_ctx: ToolContext): void {\r\n this.start = null;\r\n this.end = null;\r\n }\r\n\r\n getMeasurement(): Measurement | null {\r\n if (!this.start || !this.end) return null;\r\n const dx = this.end.x - this.start.x;\r\n const dy = this.end.y - this.start.y;\r\n const worldDistance = Math.sqrt(dx * dx + dy * dy);\r\n\r\n let cells: number;\r\n if (this.gridType === 'hex' && this.hexOrientation) {\r\n cells = getHexDistance(this.start, this.end, this.gridSize, this.hexOrientation);\r\n } else {\r\n const snapUnit = this.gridSize;\r\n cells = worldDistance / snapUnit;\r\n }\r\n\r\n const feet = cells * this.feetPerCell;\r\n return {\r\n start: { ...this.start },\r\n end: { ...this.end },\r\n worldDistance,\r\n cells,\r\n feet,\r\n };\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n const m = this.getMeasurement();\r\n if (!m) return;\r\n\r\n ctx.save();\r\n\r\n ctx.strokeStyle = '#FF5722';\r\n ctx.setLineDash([8, 4]);\r\n ctx.lineWidth = 2;\r\n ctx.beginPath();\r\n ctx.moveTo(m.start.x, m.start.y);\r\n ctx.lineTo(m.end.x, m.end.y);\r\n ctx.stroke();\r\n\r\n ctx.setLineDash([]);\r\n ctx.fillStyle = '#FF5722';\r\n const dotRadius = 4;\r\n ctx.beginPath();\r\n ctx.arc(m.start.x, m.start.y, dotRadius, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.beginPath();\r\n ctx.arc(m.end.x, m.end.y, dotRadius, 0, Math.PI * 2);\r\n ctx.fill();\r\n\r\n const label = `${Math.round(m.feet)} ft`;\r\n const midX = (m.start.x + m.end.x) / 2;\r\n const midY = (m.start.y + m.end.y) / 2;\r\n ctx.font = '14px sans-serif';\r\n const metrics = ctx.measureText(label);\r\n const padX = 6;\r\n const padY = 4;\r\n const textH = 14;\r\n\r\n ctx.fillStyle = 'rgba(0, 0, 0, 0.75)';\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n midX - metrics.width / 2 - padX,\r\n midY - textH / 2 - padY,\r\n metrics.width + padX * 2,\r\n textH + padY * 2,\r\n 4,\r\n );\r\n ctx.fill();\r\n\r\n ctx.fillStyle = '#FFFFFF';\r\n ctx.textAlign = 'center';\r\n ctx.textBaseline = 'middle';\r\n ctx.fillText(label, midX, midY);\r\n\r\n ctx.restore();\r\n }\r\n\r\n private snapToGrid(point: Point, ctx: ToolContext): Point {\r\n if (!ctx.gridSize) return point;\r\n if (ctx.gridType === 'hex' && ctx.hexOrientation) {\r\n return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);\r\n }\r\n if (ctx.gridType === 'square') {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n if (ctx.snapToGrid) {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n return point;\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { TemplateShape, HexOrientation } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createTemplate } from '../elements/element-factory';\r\nimport { snapPoint, snapToHexCenter } from '../core/snap';\r\nimport {\r\n getHexCellsInRadius,\r\n getHexCellsInCone,\r\n getHexCellsInLine,\r\n getHexCellsInSquare,\r\n drawHexPath,\r\n} from '../elements/hex-fill';\r\n\r\nexport interface TemplateToolOptions {\r\n templateShape?: TemplateShape;\r\n fillColor?: string;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n feetPerCell?: number;\r\n}\r\n\r\nexport class TemplateTool implements Tool {\r\n readonly name = 'template';\r\n private drawing = false;\r\n private origin: Point = { x: 0, y: 0 };\r\n private current: Point = { x: 0, y: 0 };\r\n private gridSize = 1;\r\n private gridType: 'square' | 'hex' | undefined;\r\n private hexOrientation: HexOrientation | undefined;\r\n private snapEnabled = false;\r\n private templateShape: TemplateShape;\r\n private fillColor: string;\r\n private strokeColor: string;\r\n private strokeWidth: number;\r\n private opacity: number;\r\n private feetPerCell: number;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: TemplateToolOptions = {}) {\r\n this.templateShape = options.templateShape ?? 'circle';\r\n this.fillColor = options.fillColor ?? 'rgba(255, 87, 34, 0.2)';\r\n this.strokeColor = options.strokeColor ?? '#FF5722';\r\n this.strokeWidth = options.strokeWidth ?? 2;\r\n this.opacity = options.opacity ?? 0.6;\r\n this.feetPerCell = options.feetPerCell ?? 5;\r\n }\r\n\r\n getOptions(): TemplateToolOptions {\r\n return {\r\n templateShape: this.templateShape,\r\n fillColor: this.fillColor,\r\n strokeColor: this.strokeColor,\r\n strokeWidth: this.strokeWidth,\r\n opacity: this.opacity,\r\n feetPerCell: this.feetPerCell,\r\n };\r\n }\r\n\r\n setOptions(options: TemplateToolOptions): void {\r\n if (options.templateShape !== undefined) this.templateShape = options.templateShape;\r\n if (options.fillColor !== undefined) this.fillColor = options.fillColor;\r\n if (options.strokeColor !== undefined) this.strokeColor = options.strokeColor;\r\n if (options.strokeWidth !== undefined) this.strokeWidth = options.strokeWidth;\r\n if (options.opacity !== undefined) this.opacity = options.opacity;\r\n if (options.feetPerCell !== undefined) this.feetPerCell = options.feetPerCell;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.drawing = true;\r\n this.gridSize = ctx.gridSize ?? 1;\r\n this.gridType = ctx.gridType;\r\n this.hexOrientation = ctx.hexOrientation;\r\n this.snapEnabled = !!ctx.gridType || (ctx.snapToGrid ?? false);\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.origin = this.snapToGrid(world, ctx);\r\n this.current = { ...this.origin };\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.current = 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 const radius = this.computeRadius();\r\n if (radius <= 0) return;\r\n\r\n const angle = this.computeAngle();\r\n const gridSize = ctx.gridSize;\r\n const snapUnit =\r\n gridSize && gridSize > 0 ? (ctx.gridType === 'hex' ? Math.sqrt(3) * gridSize : gridSize) : 0;\r\n const cells = snapUnit > 0 ? radius / snapUnit : 0;\r\n const radiusFeet = cells * this.feetPerCell;\r\n\r\n const element = createTemplate({\r\n position: { ...this.origin },\r\n templateShape: this.templateShape,\r\n radius,\r\n angle,\r\n fillColor: this.fillColor,\r\n strokeColor: this.strokeColor,\r\n strokeWidth: this.strokeWidth,\r\n opacity: this.opacity,\r\n feetPerCell: this.feetPerCell,\r\n radiusFeet: radiusFeet > 0 ? radiusFeet : undefined,\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(element);\r\n ctx.requestRender();\r\n ctx.switchTool?.('select');\r\n }\r\n\r\n onDeactivate(_ctx: ToolContext): void {\r\n this.drawing = false;\r\n this.origin = { x: 0, y: 0 };\r\n this.current = { x: 0, y: 0 };\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (!this.drawing) return;\r\n\r\n const radius = this.computeRadius();\r\n if (radius <= 0) return;\r\n\r\n if (this.gridType === 'hex' && this.hexOrientation) {\r\n this.renderHexOverlay(ctx, radius);\r\n return;\r\n }\r\n\r\n this.renderGeometricOverlay(ctx, radius);\r\n }\r\n\r\n private renderGeometricOverlay(ctx: CanvasRenderingContext2D, radius: number): void {\r\n const cx = this.origin.x;\r\n const cy = this.origin.y;\r\n const angle = this.computeAngle();\r\n\r\n ctx.save();\r\n ctx.globalAlpha = 0.4;\r\n ctx.fillStyle = this.fillColor;\r\n ctx.strokeStyle = this.strokeColor;\r\n ctx.lineWidth = this.strokeWidth;\r\n\r\n switch (this.templateShape) {\r\n case 'circle':\r\n ctx.beginPath();\r\n ctx.arc(cx, cy, radius, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n\r\n case 'square':\r\n ctx.fillRect(cx - radius / 2, cy - radius / 2, radius, radius);\r\n ctx.strokeRect(cx - radius / 2, cy - radius / 2, radius, radius);\r\n break;\r\n\r\n case 'cone': {\r\n const halfAngle = Math.atan(0.5);\r\n ctx.beginPath();\r\n ctx.moveTo(cx, cy);\r\n ctx.arc(cx, cy, radius, angle - halfAngle, angle + halfAngle);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n\r\n case 'line': {\r\n const halfW = radius / 12;\r\n const cos = Math.cos(angle);\r\n const sin = Math.sin(angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(cx + perpX, cy + perpY);\r\n ctx.lineTo(cx + radius * cos + perpX, cy + radius * sin + perpY);\r\n ctx.lineTo(cx + radius * cos - perpX, cy + radius * sin - perpY);\r\n ctx.lineTo(cx - perpX, cy - perpY);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private renderHexOverlay(ctx: CanvasRenderingContext2D, radius: number): void {\r\n const orientation = this.hexOrientation;\r\n if (!orientation) return;\r\n const cellSize = this.gridSize;\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const radiusCells = radius / snapUnit;\r\n const angle = this.computeAngle();\r\n const center = this.origin;\r\n\r\n let hexCells: Point[];\r\n switch (this.templateShape) {\r\n case 'circle':\r\n hexCells = getHexCellsInRadius(center, radiusCells, cellSize, orientation);\r\n break;\r\n case 'cone':\r\n hexCells = getHexCellsInCone(center, angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'line':\r\n hexCells = getHexCellsInLine(center, angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'square':\r\n hexCells = getHexCellsInSquare(center, radiusCells, cellSize, orientation);\r\n break;\r\n }\r\n\r\n ctx.save();\r\n ctx.globalAlpha = 0.4;\r\n\r\n ctx.beginPath();\r\n for (const cell of hexCells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.fillStyle = this.fillColor;\r\n ctx.fill();\r\n\r\n ctx.beginPath();\r\n for (const cell of hexCells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.strokeStyle = this.strokeColor;\r\n ctx.lineWidth = this.strokeWidth;\r\n ctx.stroke();\r\n\r\n if (\r\n this.templateShape === 'cone' ||\r\n this.templateShape === 'line' ||\r\n this.templateShape === 'circle' ||\r\n this.templateShape === 'square'\r\n ) {\r\n ctx.globalAlpha = 0.5;\r\n ctx.beginPath();\r\n drawHexPath(ctx, center.x, center.y, cellSize, orientation);\r\n ctx.fillStyle = this.strokeColor;\r\n ctx.fill();\r\n ctx.strokeStyle = this.strokeColor;\r\n ctx.lineWidth = this.strokeWidth;\r\n ctx.stroke();\r\n }\r\n\r\n if (this.templateShape === 'circle') {\r\n const feet = radiusCells * this.feetPerCell;\r\n if (feet > 0) {\r\n ctx.globalAlpha = 1;\r\n const label = `${Math.round(feet)} ft`;\r\n const fontSize = Math.max(10, Math.min(14, radius * 0.15));\r\n ctx.font = `bold ${fontSize}px system-ui, sans-serif`;\r\n ctx.textAlign = 'center';\r\n ctx.textBaseline = 'bottom';\r\n const textX = center.x;\r\n const textY = center.y - 4;\r\n\r\n const metrics = ctx.measureText(label);\r\n const padX = 4;\r\n const padY = 2;\r\n const textW = metrics.width + padX * 2;\r\n const textH = fontSize + padY * 2;\r\n\r\n ctx.fillStyle = 'rgba(255, 255, 255, 0.85)';\r\n ctx.beginPath();\r\n ctx.roundRect(textX - textW / 2, textY - textH, textW, textH, 3);\r\n ctx.fill();\r\n\r\n ctx.fillStyle = this.strokeColor;\r\n ctx.fillText(label, textX, textY - padY);\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private computeRadius(): number {\r\n const dx = this.current.x - this.origin.x;\r\n const dy = this.current.y - this.origin.y;\r\n const raw = Math.sqrt(dx * dx + dy * dy);\r\n if (this.snapEnabled && this.gridSize > 0) {\r\n const snapUnit = this.gridType === 'hex' ? Math.sqrt(3) * this.gridSize : this.gridSize;\r\n return Math.max(snapUnit, Math.round(raw / snapUnit) * snapUnit);\r\n }\r\n return raw;\r\n }\r\n\r\n private computeAngle(): number {\r\n const dx = this.current.x - this.origin.x;\r\n const dy = this.current.y - this.origin.y;\r\n return Math.atan2(dy, dx);\r\n }\r\n\r\n private snapToGrid(point: Point, ctx: ToolContext): Point {\r\n if (!ctx.gridSize) return point;\r\n if (ctx.gridType === 'hex' && ctx.hexOrientation) {\r\n return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);\r\n }\r\n if (ctx.gridType === 'square') {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n if (ctx.snapToGrid) {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n return point;\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n}\r\n"],"mappings":"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","names":["center","minX","minY","minX","minY","center","center","cache","center","center","center","cache","center","center","HANDLE_HIT_PADDING","center","HANDLE_HIT_PADDING","center","BIND_THRESHOLD","center"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/core/snap.ts","../src/elements/note-sanitizer.ts","../src/core/state-serializer.ts","../src/core/auto-save.ts","../src/canvas/camera.ts","../src/canvas/input-filter.ts","../src/elements/create-id.ts","../src/core/geometry.ts","../src/elements/arrow-geometry.ts","../src/elements/element-bounds.ts","../src/elements/bounds.ts","../src/canvas/keyboard-actions.ts","../src/canvas/shortcut-map.ts","../src/canvas/keyboard-handler.ts","../src/canvas/input-handler.ts","../src/canvas/background.ts","../src/core/event-bus.ts","../src/core/quadtree.ts","../src/elements/stroke-smoothing.ts","../src/elements/stroke-cache.ts","../src/elements/element-store.ts","../src/elements/rotate-canvas.ts","../src/elements/renderers/stroke-renderer.ts","../src/elements/shape-geometry.ts","../src/elements/renderers/shape-renderer.ts","../src/elements/arrow-render-cache.ts","../src/elements/arrow-binding.ts","../src/elements/renderers/arrow-renderer.ts","../src/elements/renderers/image-renderer.ts","../src/elements/hex-fill.ts","../src/elements/renderers/template-renderer.ts","../src/elements/grid-renderer.ts","../src/elements/element-renderer.ts","../src/elements/element-factory.ts","../src/elements/note-formatting.ts","../src/elements/note-toolbar.ts","../src/elements/note-editor.ts","../src/canvas/context-menu.ts","../src/canvas/viewport-dom.ts","../src/elements/arrow-label-editor.ts","../src/tools/tool-manager.ts","../src/history/history-stack.ts","../src/history/commands.ts","../src/history/layer-commands.ts","../src/history/history-recorder.ts","../src/canvas/note-canvas-renderer.ts","../src/canvas/export-image.ts","../src/layers/layer-manager.ts","../src/canvas/interact-mode.ts","../src/canvas/double-tap-detector.ts","../src/canvas/dom-node-manager.ts","../src/canvas/render-stats.ts","../src/canvas/render-loop.ts","../src/canvas/layer-cache.ts","../src/canvas/margin-viewport.ts","../src/elements/translate.ts","../src/elements/element-style.ts","../src/canvas/selection-ops.ts","../src/canvas/grid-controller.ts","../src/canvas/viewport-interactions.ts","../src/canvas/viewport.ts","../src/tools/hand-tool.ts","../src/tools/pencil-tool.ts","../src/elements/stroke-hit.ts","../src/elements/stroke-erase.ts","../src/tools/eraser-tool.ts","../src/elements/group.ts","../src/tools/arrow-handles.ts","../src/elements/snap-guides.ts","../src/tools/select-overlay.ts","../src/tools/select-hit.ts","../src/tools/select-resize.ts","../src/tools/select-tool.ts","../src/tools/arrow-tool.ts","../src/tools/note-tool.ts","../src/tools/text-tool.ts","../src/tools/image-tool.ts","../src/tools/shape-tool.ts","../src/tools/measure-tool.ts","../src/tools/template-tool.ts"],"sourcesContent":["export const VERSION = '0.38.7';\n\nexport type { Point, StrokePoint, Size, Bounds } from './core/types';\nexport { snapPoint, smartSnap, snapToHexCenter } from './core/snap';\nexport type { CanvasState } from './core/state-serializer';\nexport { AutoSave } from './core/auto-save';\nexport type { AutoSaveOptions } from './core/auto-save';\n\nexport { Camera } from './canvas/camera';\nexport type { CameraOptions, CameraChangeInfo } from './canvas/camera';\nexport type { BackgroundOptions, BackgroundPattern } from './canvas/background';\nexport type { ShortcutOptions, ShortcutBindings, ShortcutsApi } from './canvas/shortcut-map';\nexport { Viewport } from './canvas/viewport';\nexport type { ViewportOptions, GridInfo, AlignEdge, DistributeAxis } from './canvas/viewport';\nexport { exportImage } from './canvas/export-image';\nexport type { ExportImageOptions } from './canvas/export-image';\nexport type { RenderStatsSnapshot } from './canvas/render-stats';\n\nexport { ElementStore } from './elements/element-store';\nexport type { ElementUpdateEvent } from './elements/element-store';\nexport type { FontSizePreset } from './elements/note-toolbar';\nexport {\n toggleBold,\n toggleItalic,\n toggleUnderline,\n toggleStrikethrough,\n setFontSize,\n getActiveFormats,\n} from './elements/note-formatting';\nexport type { ActiveFormats } from './elements/note-formatting';\nexport {\n createStroke,\n createNote,\n createArrow,\n createImage,\n createHtmlElement,\n createText,\n createShape,\n createGrid,\n createTemplate,\n DEFAULT_NOTE_FONT_SIZE,\n} from './elements/element-factory';\nexport {\n getArrowControlPoint,\n getArrowMidpoint,\n getBendFromPoint,\n getArrowTangentAngle,\n isNearBezier,\n getArrowBounds,\n} from './elements/arrow-geometry';\nexport { getElementBounds, boundsIntersect } from './elements/element-bounds';\nexport { styleToPatch, getElementStyle } from './elements/element-style';\nexport type { ElementStyle } from './elements/element-style';\nexport { getElementsBoundingBox } from './elements/bounds';\nexport {\n getHexDistance,\n getHexCellsInRadius,\n getHexCellsInCone,\n getHexCellsInLine,\n getHexCellsInSquare,\n drawHexPath,\n} from './elements/hex-fill';\nexport type {\n Binding,\n CanvasElement,\n ElementType,\n StrokeElement,\n NoteElement,\n ArrowElement,\n ImageElement,\n HtmlElement,\n TextElement,\n ShapeElement,\n ShapeKind,\n GridElement,\n HexOrientation,\n TemplateElement,\n TemplateShape,\n} from './elements/types';\n\nexport type { Command } from './history/types';\nexport { HistoryStack } from './history/history-stack';\nexport type { HistoryStackOptions } from './history/history-stack';\n\nexport { ToolManager } from './tools/tool-manager';\nexport { HandTool } from './tools/hand-tool';\nexport { PencilTool } from './tools/pencil-tool';\nexport type { PencilToolOptions } from './tools/pencil-tool';\nexport { EraserTool } from './tools/eraser-tool';\nexport type { EraserToolOptions } from './tools/eraser-tool';\nexport { SelectTool } from './tools/select-tool';\nexport { ArrowTool } from './tools/arrow-tool';\nexport type { ArrowToolOptions } from './tools/arrow-tool';\nexport { NoteTool } from './tools/note-tool';\nexport type { NoteToolOptions } from './tools/note-tool';\nexport { TextTool } from './tools/text-tool';\nexport type { TextToolOptions } from './tools/text-tool';\nexport { ImageTool } from './tools/image-tool';\nexport type { ImageToolOptions } from './tools/image-tool';\nexport { ShapeTool } from './tools/shape-tool';\nexport type { ShapeToolOptions } from './tools/shape-tool';\nexport { MeasureTool } from './tools/measure-tool';\nexport type { MeasureToolOptions, Measurement } from './tools/measure-tool';\nexport { TemplateTool } from './tools/template-tool';\nexport type { TemplateToolOptions } from './tools/template-tool';\nexport type { Tool, ToolContext, PointerState, ToolName } from './tools/types';\n\nexport { LayerManager } from './layers/layer-manager';\nexport type { Layer } from './layers/types';\n","import type { Point } from './types';\r\nimport type { HexOrientation } from '../elements/types';\r\nimport type { ToolContext } from '../tools/types';\r\n\r\nexport function snapPoint(point: Point, gridSize: number): Point {\r\n return {\r\n x: Math.round(point.x / gridSize) * gridSize || 0,\r\n y: Math.round(point.y / gridSize) * gridSize || 0,\r\n };\r\n}\r\n\r\nexport function snapToHexCenter(\r\n point: Point,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point {\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * cellSize;\r\n const rowH = 1.5 * cellSize;\r\n const row = Math.round(point.y / rowH);\r\n const offsetX = row % 2 !== 0 ? hexW / 2 : 0;\r\n const col = Math.round((point.x - offsetX) / hexW);\r\n return { x: col * hexW + offsetX || 0, y: row * rowH || 0 };\r\n } else {\r\n const hexH = Math.sqrt(3) * cellSize;\r\n const colW = 1.5 * cellSize;\r\n const col = Math.round(point.x / colW);\r\n const offsetY = col % 2 !== 0 ? hexH / 2 : 0;\r\n const row = Math.round((point.y - offsetY) / hexH);\r\n return { x: col * colW || 0, y: row * hexH + offsetY || 0 };\r\n }\r\n}\r\n\r\nexport function smartSnap(point: Point, ctx: ToolContext): Point {\r\n if (!ctx.snapToGrid || !ctx.gridSize) return point;\r\n if (ctx.gridType === 'hex' && ctx.hexOrientation) {\r\n return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);\r\n }\r\n return snapPoint(point, ctx.gridSize);\r\n}\r\n","interface RunStyle {\r\n bold: boolean;\r\n italic: boolean;\r\n underline: boolean;\r\n strikethrough: boolean;\r\n fontSize: number;\r\n}\r\n\r\nexport interface StyledRun extends RunStyle {\r\n text: string;\r\n}\r\n\r\nconst BOLD_TAGS = new Set(['b', 'strong']);\r\nconst ITALIC_TAGS = new Set(['i', 'em']);\r\nconst UNDERLINE_TAGS = new Set(['u']);\r\nconst STRIKE_TAGS = new Set(['s', 'strike', 'del']);\r\nconst BLOCK_TAGS = new Set(['div']);\r\n\r\nexport function parseStyledRuns(html: string, baseFontSize: number): StyledRun[] {\r\n if (!html) return [];\r\n\r\n const doc = new DOMParser().parseFromString(html, 'text/html');\r\n const runs: StyledRun[] = [];\r\n const baseStyle: RunStyle = {\r\n bold: false,\r\n italic: false,\r\n underline: false,\r\n strikethrough: false,\r\n fontSize: baseFontSize,\r\n };\r\n\r\n walkNodes(doc.body, baseStyle, runs);\r\n return runs;\r\n}\r\n\r\nfunction walkNodes(node: Node, style: RunStyle, runs: StyledRun[]): void {\r\n for (const child of Array.from(node.childNodes)) {\r\n if (child.nodeType === Node.TEXT_NODE) {\r\n const text = child.textContent ?? '';\r\n if (text) {\r\n runs.push({ text, ...style });\r\n }\r\n continue;\r\n }\r\n\r\n if (child.nodeType !== Node.ELEMENT_NODE) continue;\r\n\r\n const el = child as Element;\r\n const tag = el.tagName.toLowerCase();\r\n\r\n if (tag === 'br') {\r\n runs.push({ text: '\\n', ...style });\r\n continue;\r\n }\r\n\r\n if (BLOCK_TAGS.has(tag) && runs.length > 0) {\r\n const lastRun = runs[runs.length - 1];\r\n if (lastRun && !lastRun.text.endsWith('\\n')) {\r\n runs.push({ text: '\\n', ...style });\r\n }\r\n }\r\n\r\n const childStyle = { ...style };\r\n if (BOLD_TAGS.has(tag)) childStyle.bold = true;\r\n if (ITALIC_TAGS.has(tag)) childStyle.italic = true;\r\n if (UNDERLINE_TAGS.has(tag)) childStyle.underline = true;\r\n if (STRIKE_TAGS.has(tag)) childStyle.strikethrough = true;\r\n\r\n if (tag === 'span') {\r\n const fontSize = (el as HTMLElement).style.fontSize;\r\n if (fontSize) {\r\n childStyle.fontSize = parseInt(fontSize, 10) || style.fontSize;\r\n }\r\n }\r\n\r\n walkNodes(el, childStyle, runs);\r\n }\r\n}\r\n\r\nconst ALLOWED_TAGS = new Set([\r\n 'b',\r\n 'strong',\r\n 'i',\r\n 'em',\r\n 'u',\r\n 's',\r\n 'strike',\r\n 'del',\r\n 'span',\r\n 'br',\r\n 'div',\r\n]);\r\n\r\nexport function sanitizeNoteHtml(html: string): string {\r\n if (!html) return '';\r\n\r\n const doc = new DOMParser().parseFromString(html, 'text/html');\r\n sanitizeNode(doc.body);\r\n return doc.body.innerHTML;\r\n}\r\n\r\nfunction sanitizeNode(node: Node): void {\r\n const children = Array.from(node.childNodes);\r\n\r\n for (const child of children) {\r\n if (child.nodeType === Node.TEXT_NODE) continue;\r\n\r\n if (child.nodeType !== Node.ELEMENT_NODE) {\r\n child.remove();\r\n continue;\r\n }\r\n\r\n const el = child as Element;\r\n const tag = el.tagName.toLowerCase();\r\n\r\n if (!ALLOWED_TAGS.has(tag)) {\r\n const fragment = document.createDocumentFragment();\r\n while (el.firstChild) {\r\n fragment.appendChild(el.firstChild);\r\n }\r\n node.replaceChild(fragment, el);\r\n sanitizeNode(node);\r\n return;\r\n }\r\n\r\n sanitizeAttributes(el, tag);\r\n sanitizeNode(el);\r\n }\r\n}\r\n\r\nexport function isNoteContentEmpty(html: string): boolean {\r\n if (!html) return true;\r\n const doc = new DOMParser().parseFromString(html, 'text/html');\r\n const text = doc.body.textContent ?? '';\r\n return text.replace(/\\u00a0/g, ' ').trim().length === 0;\r\n}\r\n\r\nfunction sanitizeAttributes(el: Element, tag: string): void {\r\n const attrs = Array.from(el.attributes);\r\n for (const attr of attrs) {\r\n if (tag === 'span' && attr.name === 'style') {\r\n const fontSize = (el as HTMLElement).style.fontSize;\r\n if (fontSize) {\r\n el.setAttribute('style', `font-size: ${fontSize};`);\r\n } else {\r\n el.removeAttribute('style');\r\n }\r\n continue;\r\n }\r\n el.removeAttribute(attr.name);\r\n }\r\n}\r\n","import type { CanvasElement } from '../elements/types';\r\nimport type { Point } from './types';\r\nimport type { Layer } from '../layers/types';\r\nimport { sanitizeNoteHtml } from '../elements/note-sanitizer';\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 layers?: Layer[];\r\n activeLayerId?: string;\r\n}\r\n\r\nconst CURRENT_VERSION = 2;\r\n\r\nexport function exportState(\r\n elements: CanvasElement[],\r\n camera: { position: Point; zoom: number },\r\n layers: Layer[] = [],\r\n activeLayerId?: string,\r\n): CanvasState {\r\n const state: CanvasState = {\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) => {\r\n const clone = structuredClone(el);\r\n if (clone.type === 'arrow') {\r\n delete clone.cachedControlPoint;\r\n }\r\n return clone;\r\n }),\r\n layers: layers.map((l) => ({ ...l })),\r\n };\r\n if (activeLayerId) state.activeLayerId = activeLayerId;\r\n return state;\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 cleanBindings(obj['elements'] as Record<string, unknown>[]);\r\n\r\n const layers = obj['layers'];\r\n if (!Array.isArray(layers) || layers.length === 0) {\r\n obj['layers'] = [\r\n {\r\n id: 'default-layer',\r\n name: 'Layer 1',\r\n visible: true,\r\n locked: false,\r\n order: 0,\r\n opacity: 1.0,\r\n },\r\n ];\r\n }\r\n}\r\n\r\nconst VALID_TYPES = new Set([\r\n 'stroke',\r\n 'note',\r\n 'arrow',\r\n 'image',\r\n 'html',\r\n 'text',\r\n 'shape',\r\n 'grid',\r\n 'template',\r\n]);\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 cleanBindings(elements: Record<string, unknown>[]): void {\r\n const ids = new Set(elements.map((el) => el['id'] as string));\r\n\r\n for (const el of elements) {\r\n if (el['type'] !== 'arrow') continue;\r\n\r\n const fromBinding = el['fromBinding'] as Record<string, unknown> | undefined;\r\n if (fromBinding && !ids.has(fromBinding['elementId'] as string)) {\r\n el['fromBinding'] = undefined;\r\n }\r\n\r\n const toBinding = el['toBinding'] as Record<string, unknown> | undefined;\r\n if (toBinding && !ids.has(toBinding['elementId'] as string)) {\r\n el['toBinding'] = undefined;\r\n }\r\n }\r\n}\r\n\r\nfunction migrateElement(obj: Record<string, unknown>): void {\r\n if (typeof obj['layerId'] !== 'string') {\r\n obj['layerId'] = 'default-layer';\r\n }\r\n\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 if (obj['type'] === 'shape' && typeof obj['shape'] !== 'string') {\r\n obj['shape'] = 'rectangle';\r\n }\r\n\r\n if (obj['type'] === 'note' && typeof obj['textColor'] !== 'string') {\r\n obj['textColor'] = '#000000';\r\n }\r\n\r\n if (obj['type'] === 'note' && typeof obj['text'] === 'string') {\r\n obj['text'] = sanitizeNoteHtml(obj['text']);\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { Camera } from '../canvas/camera';\r\nimport type { LayerManager } from '../layers/layer-manager';\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 layerManager?: LayerManager;\r\n onError?: (error: Error) => void;\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 readonly layerManager?: LayerManager;\r\n private timerId: ReturnType<typeof setTimeout> | null = null;\r\n private unsubscribers: (() => void)[] = [];\r\n private readonly onError?: (error: Error) => 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 this.layerManager = options.layerManager;\r\n this.onError = options.onError;\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 if (this.layerManager) {\r\n this.unsubscribers.push(this.layerManager.on('change', 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 layers = this.layerManager?.snapshot() ?? [];\r\n const state = exportState(this.store.snapshot(), this.camera, layers);\r\n try {\r\n localStorage.setItem(this.key, JSON.stringify(state));\r\n } catch (e) {\r\n console.warn('Auto-save failed: storage quota exceeded. State too large for localStorage.');\r\n this.onError?.(e instanceof Error ? e : new Error(String(e)));\r\n }\r\n }\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\n\r\nexport interface CameraOptions {\r\n minZoom?: number;\r\n maxZoom?: number;\r\n}\r\n\r\nexport interface CameraChangeInfo {\r\n panned: boolean;\r\n zoomed: boolean;\r\n}\r\n\r\nconst DEFAULT_MIN_ZOOM = 0.1;\r\nconst DEFAULT_MAX_ZOOM = 10;\r\n\r\nexport class Camera {\r\n private x = 0;\r\n private y = 0;\r\n private z = 1;\r\n private readonly minZoom: number;\r\n private readonly maxZoom: number;\r\n private changeListeners = new Set<(info: CameraChangeInfo) => void>();\r\n\r\n constructor(options: CameraOptions = {}) {\r\n this.minZoom = options.minZoom ?? DEFAULT_MIN_ZOOM;\r\n this.maxZoom = options.maxZoom ?? DEFAULT_MAX_ZOOM;\r\n }\r\n\r\n get position(): Point {\r\n return { x: this.x, y: this.y };\r\n }\r\n\r\n get zoom(): number {\r\n return this.z;\r\n }\r\n\r\n pan(dx: number, dy: number): void {\r\n this.x += dx;\r\n this.y += dy;\r\n this.notifyPan();\r\n }\r\n\r\n moveTo(x: number, y: number): void {\r\n this.x = x;\r\n this.y = y;\r\n this.notifyPan();\r\n }\r\n\r\n setZoom(level: number): void {\r\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, level));\r\n this.notifyZoom();\r\n }\r\n\r\n zoomAt(level: number, screenPoint: Point): void {\r\n const before = this.screenToWorld(screenPoint);\r\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, level));\r\n const after = this.screenToWorld(screenPoint);\r\n this.x += (after.x - before.x) * this.z;\r\n this.y += (after.y - before.y) * this.z;\r\n this.notifyPanAndZoom();\r\n }\r\n\r\n screenToWorld(screen: Point): Point {\r\n return {\r\n x: (screen.x - this.x) / this.z,\r\n y: (screen.y - this.y) / this.z,\r\n };\r\n }\r\n\r\n worldToScreen(world: Point): Point {\r\n return {\r\n x: world.x * this.z + this.x,\r\n y: world.y * this.z + this.y,\r\n };\r\n }\r\n\r\n getVisibleRect(canvasWidth: number, canvasHeight: number): Bounds {\r\n const topLeft = this.screenToWorld({ x: 0, y: 0 });\r\n const bottomRight = this.screenToWorld({ x: canvasWidth, y: canvasHeight });\r\n return {\r\n x: topLeft.x,\r\n y: topLeft.y,\r\n w: bottomRight.x - topLeft.x,\r\n h: bottomRight.y - topLeft.y,\r\n };\r\n }\r\n\r\n fitToContent(boundingBox: Bounds, canvasWidth: number, canvasHeight: number, padding = 40): void {\r\n if (boundingBox.w === 0 && boundingBox.h === 0) return;\r\n\r\n const scaleX = canvasWidth / (boundingBox.w + 2 * padding);\r\n const scaleY = canvasHeight / (boundingBox.h + 2 * padding);\r\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, Math.min(scaleX, scaleY)));\r\n this.x = (canvasWidth - boundingBox.w * this.z) / 2 - boundingBox.x * this.z;\r\n this.y = (canvasHeight - boundingBox.h * this.z) / 2 - boundingBox.y * this.z;\r\n this.notifyPanAndZoom();\r\n }\r\n\r\n toCSSTransform(): string {\r\n return `translate3d(${this.x}px, ${this.y}px, 0) scale(${this.z})`;\r\n }\r\n\r\n onChange(listener: (info: CameraChangeInfo) => void): () => void {\r\n this.changeListeners.add(listener);\r\n return () => this.changeListeners.delete(listener);\r\n }\r\n\r\n private notifyPan(): void {\r\n this.changeListeners.forEach((fn) => fn({ panned: true, zoomed: false }));\r\n }\r\n\r\n private notifyZoom(): void {\r\n this.changeListeners.forEach((fn) => fn({ panned: false, zoomed: true }));\r\n }\r\n\r\n private notifyPanAndZoom(): void {\r\n this.changeListeners.forEach((fn) => fn({ panned: true, zoomed: true }));\r\n }\r\n}\r\n","export type FilterAction = 'dispatch' | 'suppress' | 'defer';\r\n\r\nexport interface FilteredEvent {\r\n event: PointerEvent;\r\n action: FilterAction;\r\n}\r\n\r\nexport interface FilteredUpEvent extends FilteredEvent {\r\n pendingTap?: { x: number; y: number };\r\n}\r\n\r\nexport class InputFilter {\r\n private activePenId: number | null = null;\r\n private pendingTap: { pointerId: number; x: number; y: number } | null = null;\r\n\r\n static readonly MIN_MOVE_DISTANCE = 3;\r\n\r\n filterDown(e: PointerEvent): FilteredEvent {\r\n if (e.pointerType === 'pen') {\r\n this.activePenId = e.pointerId;\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n if (e.pointerType === 'touch' && this.activePenId !== null) {\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n if (e.pointerType === 'touch') {\r\n this.pendingTap = { pointerId: e.pointerId, x: e.clientX, y: e.clientY };\r\n return { event: e, action: 'defer' };\r\n }\r\n\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n filterMove(e: PointerEvent): FilteredEvent {\r\n if (e.pointerType === 'touch' && this.activePenId !== null) {\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {\r\n const dx = e.clientX - this.pendingTap.x;\r\n const dy = e.clientY - this.pendingTap.y;\r\n if (dx * dx + dy * dy > InputFilter.MIN_MOVE_DISTANCE * InputFilter.MIN_MOVE_DISTANCE) {\r\n this.pendingTap = null;\r\n return { event: e, action: 'dispatch' };\r\n }\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n filterUp(e: PointerEvent): FilteredUpEvent {\r\n if (e.pointerId === this.activePenId) {\r\n this.activePenId = null;\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n if (e.pointerType === 'touch' && this.activePenId !== null) {\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {\r\n const tap = { x: this.pendingTap.x, y: this.pendingTap.y };\r\n this.pendingTap = null;\r\n return { event: e, action: 'dispatch', pendingTap: tap };\r\n }\r\n\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n reset(): void {\r\n this.activePenId = null;\r\n this.pendingTap = null;\r\n }\r\n}\r\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, Bounds } from './types';\r\n\r\nexport function distSqToSegment(p: Point, a: Point, b: Point): number {\r\n const abx = b.x - a.x;\r\n const aby = b.y - a.y;\r\n const apx = p.x - a.x;\r\n const apy = p.y - a.y;\r\n const lenSq = abx * abx + aby * aby;\r\n if (lenSq === 0) {\r\n return apx * apx + apy * apy;\r\n }\r\n const t = Math.max(0, Math.min(1, (apx * abx + apy * aby) / lenSq));\r\n const dx = p.x - (a.x + t * abx);\r\n const dy = p.y - (a.y + t * aby);\r\n return dx * dx + dy * dy;\r\n}\r\n\r\nexport function rotatePoint(p: Point, center: Point, angle: number): Point {\r\n if (angle === 0) return p;\r\n const cos = Math.cos(angle);\r\n const sin = Math.sin(angle);\r\n const dx = p.x - center.x;\r\n const dy = p.y - center.y;\r\n return { x: center.x + dx * cos - dy * sin, y: center.y + dx * sin + dy * cos };\r\n}\r\n\r\nexport function rotatedAABB(bounds: Bounds, angle: number): Bounds {\r\n if (angle === 0) return bounds;\r\n const c = { x: bounds.x + bounds.w / 2, y: bounds.y + bounds.h / 2 };\r\n const corners = [\r\n { x: bounds.x, y: bounds.y },\r\n { x: bounds.x + bounds.w, y: bounds.y },\r\n { x: bounds.x + bounds.w, y: bounds.y + bounds.h },\r\n { x: bounds.x, y: bounds.y + bounds.h },\r\n ].map((p) => rotatePoint(p, c, angle));\r\n const xs = corners.map((p) => p.x);\r\n const ys = corners.map((p) => p.y);\r\n const minX = Math.min(...xs);\r\n const minY = Math.min(...ys);\r\n return { x: minX, y: minY, w: Math.max(...xs) - minX, h: Math.max(...ys) - minY };\r\n}\r\n\r\nexport function normalizeAngle(angle: number): number {\r\n const twoPi = Math.PI * 2;\r\n let a = angle % twoPi;\r\n if (a <= -Math.PI) a += twoPi;\r\n else if (a > Math.PI) a -= twoPi;\r\n return a;\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport { distSqToSegment } from '../core/geometry';\r\n\r\nexport function getArrowControlPoint(from: Point, to: Point, bend: number): Point {\r\n const midX = (from.x + to.x) / 2;\r\n const midY = (from.y + to.y) / 2;\r\n\r\n if (bend === 0) return { x: midX, y: midY };\r\n\r\n const dx = to.x - from.x;\r\n const dy = to.y - from.y;\r\n const len = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (len === 0) return { x: midX, y: midY };\r\n\r\n const perpX = -dy / len;\r\n const perpY = dx / len;\r\n\r\n return {\r\n x: midX + perpX * bend,\r\n y: midY + perpY * bend,\r\n };\r\n}\r\n\r\nexport function getArrowMidpoint(from: Point, to: Point, bend: number): Point {\r\n const cp = getArrowControlPoint(from, to, bend);\r\n return {\r\n x: 0.25 * from.x + 0.5 * cp.x + 0.25 * to.x,\r\n y: 0.25 * from.y + 0.5 * cp.y + 0.25 * to.y,\r\n };\r\n}\r\n\r\nexport function getBendFromPoint(from: Point, to: Point, dragPoint: Point): number {\r\n const midX = (from.x + to.x) / 2;\r\n const midY = (from.y + to.y) / 2;\r\n\r\n const dx = to.x - from.x;\r\n const dy = to.y - from.y;\r\n const len = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (len === 0) return 0;\r\n\r\n const perpX = -dy / len;\r\n const perpY = dx / len;\r\n\r\n return (dragPoint.x - midX) * perpX + (dragPoint.y - midY) * perpY;\r\n}\r\n\r\nexport function getArrowTangentAngle(from: Point, to: Point, bend: number, t: number): number {\r\n const cp = getArrowControlPoint(from, to, bend);\r\n\r\n const tangentX = 2 * (1 - t) * (cp.x - from.x) + 2 * t * (to.x - cp.x);\r\n const tangentY = 2 * (1 - t) * (cp.y - from.y) + 2 * t * (to.y - cp.y);\r\n\r\n return Math.atan2(tangentY, tangentX);\r\n}\r\n\r\nexport function isNearBezier(\r\n point: Point,\r\n from: Point,\r\n to: Point,\r\n bend: number,\r\n threshold: number,\r\n): boolean {\r\n if (bend === 0) return isNearLine(point, from, to, threshold);\r\n\r\n const cp = getArrowControlPoint(from, to, bend);\r\n const segments = 20;\r\n\r\n for (let i = 0; i < segments; i++) {\r\n const t0 = i / segments;\r\n const t1 = (i + 1) / segments;\r\n const a = bezierPoint(from, cp, to, t0);\r\n const b = bezierPoint(from, cp, to, t1);\r\n if (isNearLine(point, a, b, threshold)) return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\nexport function getArrowBounds(from: Point, to: Point, bend: number): Bounds {\r\n if (bend === 0) {\r\n const minX = Math.min(from.x, to.x);\r\n const minY = Math.min(from.y, to.y);\r\n return {\r\n x: minX,\r\n y: minY,\r\n w: Math.abs(to.x - from.x),\r\n h: Math.abs(to.y - from.y),\r\n };\r\n }\r\n\r\n const cp = getArrowControlPoint(from, to, bend);\r\n const steps = 20;\r\n let minX = Math.min(from.x, to.x);\r\n let minY = Math.min(from.y, to.y);\r\n let maxX = Math.max(from.x, to.x);\r\n let maxY = Math.max(from.y, to.y);\r\n\r\n for (let i = 1; i < steps; i++) {\r\n const t = i / steps;\r\n const p = bezierPoint(from, cp, to, t);\r\n if (p.x < minX) minX = p.x;\r\n if (p.y < minY) minY = p.y;\r\n if (p.x > maxX) maxX = p.x;\r\n if (p.y > maxY) maxY = p.y;\r\n }\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n\r\nfunction bezierPoint(from: Point, cp: Point, to: Point, t: number): Point {\r\n const mt = 1 - t;\r\n return {\r\n x: mt * mt * from.x + 2 * mt * t * cp.x + t * t * to.x,\r\n y: mt * mt * from.y + 2 * mt * t * cp.y + t * t * to.y,\r\n };\r\n}\r\n\r\nfunction isNearLine(point: Point, a: Point, b: Point, threshold: number): boolean {\r\n return distSqToSegment(point, a, b) <= threshold * threshold;\r\n}\r\n","import type { Bounds } from '../core/types';\r\nimport type { CanvasElement, TemplateElement } from './types';\r\nimport { getArrowControlPoint } from './arrow-geometry';\r\n\r\n// Cache stroke bounds via WeakMap.\r\n// May miss after ElementStore.update() creates new object via spread,\r\n// acceptable since stroke points never change after commit.\r\nconst strokeBoundsCache = new WeakMap<CanvasElement, Bounds>();\r\n\r\nexport function getElementBounds(element: CanvasElement): Bounds | null {\r\n if (element.type === 'grid') return null;\r\n\r\n if ('size' in element) {\r\n return {\r\n x: element.position.x,\r\n y: element.position.y,\r\n w: element.size.w,\r\n h: element.size.h,\r\n };\r\n }\r\n\r\n if (element.type === 'stroke') {\r\n if (element.points.length === 0) return null;\r\n\r\n const cached = strokeBoundsCache.get(element);\r\n if (cached) return cached;\r\n\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n\r\n for (const p of element.points) {\r\n const px = p.x + element.position.x;\r\n const py = p.y + element.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\r\n const bounds: Bounds = { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n strokeBoundsCache.set(element, bounds);\r\n return bounds;\r\n }\r\n\r\n if (element.type === 'arrow') {\r\n return getArrowBoundsAnalytical(element.from, element.to, element.bend);\r\n }\r\n\r\n if (element.type === 'template') {\r\n return getTemplateBounds(element);\r\n }\r\n\r\n return null;\r\n}\r\n\r\nfunction getArrowBoundsAnalytical(\r\n from: { x: number; y: number },\r\n to: { x: number; y: number },\r\n bend: number,\r\n): Bounds {\r\n if (bend === 0) {\r\n const minX = Math.min(from.x, to.x);\r\n const minY = Math.min(from.y, to.y);\r\n return {\r\n x: minX,\r\n y: minY,\r\n w: Math.abs(to.x - from.x),\r\n h: Math.abs(to.y - from.y),\r\n };\r\n }\r\n\r\n const cp = getArrowControlPoint(from, to, bend);\r\n\r\n let minX = Math.min(from.x, to.x);\r\n let maxX = Math.max(from.x, to.x);\r\n let minY = Math.min(from.y, to.y);\r\n let maxY = Math.max(from.y, to.y);\r\n\r\n // Analytical extrema for quadratic bezier: t = (P0 - P1) / (P0 - 2*P1 + P2)\r\n const tx = from.x - 2 * cp.x + to.x;\r\n if (tx !== 0) {\r\n const t = (from.x - cp.x) / tx;\r\n if (t > 0 && t < 1) {\r\n const mt = 1 - t;\r\n const x = mt * mt * from.x + 2 * mt * t * cp.x + t * t * to.x;\r\n if (x < minX) minX = x;\r\n if (x > maxX) maxX = x;\r\n }\r\n }\r\n\r\n const ty = from.y - 2 * cp.y + to.y;\r\n if (ty !== 0) {\r\n const t = (from.y - cp.y) / ty;\r\n if (t > 0 && t < 1) {\r\n const mt = 1 - t;\r\n const y = mt * mt * from.y + 2 * mt * t * cp.y + t * t * to.y;\r\n if (y < minY) minY = y;\r\n if (y > maxY) maxY = y;\r\n }\r\n }\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n\r\nfunction getTemplateBounds(el: TemplateElement): Bounds {\r\n const { x: cx, y: cy } = el.position;\r\n const r = el.radius;\r\n\r\n switch (el.templateShape) {\r\n case 'circle':\r\n return { x: cx - r, y: cy - r, w: 2 * r, h: 2 * r };\r\n\r\n case 'square':\r\n return { x: cx - r / 2, y: cy - r / 2, w: r, h: r };\r\n\r\n case 'cone': {\r\n const halfAngle = Math.atan(0.5);\r\n const tipX = cx;\r\n const tipY = cy;\r\n const leftX = cx + r * Math.cos(el.angle - halfAngle);\r\n const leftY = cy + r * Math.sin(el.angle - halfAngle);\r\n const rightX = cx + r * Math.cos(el.angle + halfAngle);\r\n const rightY = cy + r * Math.sin(el.angle + halfAngle);\r\n const farX = cx + r * Math.cos(el.angle);\r\n const farY = cy + r * Math.sin(el.angle);\r\n\r\n const xs = [tipX, leftX, rightX, farX];\r\n const ys = [tipY, leftY, rightY, farY];\r\n\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n\r\n for (let i = 0; i < xs.length; i++) {\r\n const px = xs[i];\r\n const py = ys[i];\r\n if (px !== undefined && px < minX) minX = px;\r\n if (px !== undefined && px > maxX) maxX = px;\r\n if (py !== undefined && py < minY) minY = py;\r\n if (py !== undefined && py > maxY) maxY = py;\r\n }\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n }\r\n\r\n case 'line': {\r\n const halfW = r / 12;\r\n const cos = Math.cos(el.angle);\r\n const sin = Math.sin(el.angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n\r\n const x0 = cx + perpX;\r\n const y0 = cy + perpY;\r\n const x1 = cx + r * cos + perpX;\r\n const y1 = cy + r * sin + perpY;\r\n const x2 = cx + r * cos - perpX;\r\n const y2 = cy + r * sin - perpY;\r\n const x3 = cx - perpX;\r\n const y3 = cy - perpY;\r\n\r\n const minX = Math.min(x0, x1, x2, x3);\r\n const minY = Math.min(y0, y1, y2, y3);\r\n const maxX = Math.max(x0, x1, x2, x3);\r\n const maxY = Math.max(y0, y1, y2, y3);\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n }\r\n }\r\n}\r\n\r\nexport function transferStrokeBounds(prev: CanvasElement, next: CanvasElement): void {\r\n if (prev.type !== 'stroke' || next.type !== 'stroke') return;\r\n if (prev.points !== next.points) return;\r\n if (prev.position.x !== next.position.x || prev.position.y !== next.position.y) return;\r\n const bounds = strokeBoundsCache.get(prev);\r\n if (bounds) strokeBoundsCache.set(next, bounds);\r\n}\r\n\r\nexport function boundsIntersect(a: Bounds, b: Bounds): 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","import type { Bounds } from '../core/types';\r\nimport type { CanvasElement } from './types';\r\nimport { getElementBounds } from './element-bounds';\r\n\r\nexport function getElementsBoundingBox(elements: CanvasElement[]): Bounds | null {\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n let found = false;\r\n\r\n for (const el of elements) {\r\n const b = getElementBounds(el);\r\n if (!b) continue;\r\n found = true;\r\n if (b.x < minX) minX = b.x;\r\n if (b.y < minY) minY = b.y;\r\n if (b.x + b.w > maxX) maxX = b.x + b.w;\r\n if (b.y + b.h > maxY) maxY = b.y + b.h;\r\n }\r\n\r\n if (!found) return null;\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n","import type { ToolManager } from '../tools/tool-manager';\nimport type { ToolContext } from '../tools/types';\nimport type { SelectTool } from '../tools/select-tool';\nimport type { HistoryRecorder } from '../history/history-recorder';\nimport type { HistoryStack } from '../history/history-stack';\nimport type { CanvasElement } from '../elements/types';\nimport type { Point } from '../core/types';\nimport { createId } from '../elements/create-id';\nimport { getElementsBoundingBox } from '../elements/bounds';\n\nexport interface KeyboardActionsDeps {\n getToolManager: () => ToolManager | null;\n getToolContext: () => ToolContext | null;\n getHistoryRecorder: () => HistoryRecorder | null;\n getHistoryStack: () => HistoryStack | null;\n isToolActive: () => boolean;\n fitToContent?: () => void;\n group?: () => void;\n ungroup?: () => void;\n toggleLock?: () => void;\n getLastPointerWorld?: () => Point | null;\n}\n\nexport class KeyboardActions {\n private clipboard: CanvasElement[] = [];\n private pasteCount = 0;\n private nudgeTimer: ReturnType<typeof setTimeout> | null = null;\n private nudgeTxId: number | null = null;\n\n constructor(private readonly deps: KeyboardActionsDeps) {}\n\n dispose(): void {\n this.flushPendingNudge();\n }\n\n private selectTool(): { tool: SelectTool; ctx: ToolContext } | null {\n const tm = this.deps.getToolManager();\n const ctx = this.deps.getToolContext();\n if (!tm || !ctx) return null;\n const tool = tm.activeTool;\n if (tool?.name !== 'select') return null;\n return { tool: tool as SelectTool, ctx };\n }\n\n nudge(dx: number, dy: number, byCell: boolean): boolean {\n if (this.deps.isToolActive()) return false;\n const sel = this.selectTool();\n if (!sel) return false;\n if (sel.tool.selectedIds.length === 0) return false;\n\n const step = byCell ? (sel.ctx.gridSize ?? 10) : 1;\n if (this.nudgeTimer === null) {\n const recorder = this.deps.getHistoryRecorder();\n recorder?.begin();\n this.nudgeTxId = recorder?.currentTransactionId ?? null;\n } else {\n clearTimeout(this.nudgeTimer);\n const recorder = this.deps.getHistoryRecorder();\n if (recorder?.currentTransactionId !== this.nudgeTxId) {\n recorder?.begin();\n this.nudgeTxId = recorder?.currentTransactionId ?? null;\n }\n }\n const moved = sel.tool.nudgeSelection(dx * step, dy * step, sel.ctx);\n this.nudgeTimer = setTimeout(() => this.flushPendingNudge(), 400);\n return moved;\n }\n\n flushPendingNudge(): void {\n if (this.nudgeTimer === null) return;\n clearTimeout(this.nudgeTimer);\n this.nudgeTimer = null;\n const recorder = this.deps.getHistoryRecorder();\n if (recorder?.currentTransactionId === this.nudgeTxId) {\n recorder?.commit();\n }\n this.nudgeTxId = null;\n }\n\n deleteSelected(): void {\n if (this.deps.isToolActive()) return;\n this.flushPendingNudge();\n const sel = this.selectTool();\n if (!sel) return;\n const ids = sel.tool.selectedIds;\n if (ids.length === 0) return;\n const recorder = this.deps.getHistoryRecorder();\n recorder?.begin();\n for (const id of ids) {\n sel.ctx.store.remove(id);\n }\n recorder?.commit();\n sel.ctx.requestRender();\n }\n\n undo(): void {\n if (this.deps.isToolActive()) return;\n this.flushPendingNudge();\n const ctx = this.deps.getToolContext();\n const stack = this.deps.getHistoryStack();\n if (!stack || !ctx) return;\n const recorder = this.deps.getHistoryRecorder();\n recorder?.pause();\n stack.undo(ctx.store);\n recorder?.resume();\n ctx.requestRender();\n }\n\n redo(): void {\n if (this.deps.isToolActive()) return;\n this.flushPendingNudge();\n const ctx = this.deps.getToolContext();\n const stack = this.deps.getHistoryStack();\n if (!stack || !ctx) return;\n const recorder = this.deps.getHistoryRecorder();\n recorder?.pause();\n stack.redo(ctx.store);\n recorder?.resume();\n ctx.requestRender();\n }\n\n copy(): void {\n if (this.deps.isToolActive()) return;\n const sel = this.selectTool();\n if (!sel) return;\n const ids = sel.tool.selectedIds;\n if (ids.length === 0) return;\n this.clipboard = [];\n for (const id of ids) {\n const el = sel.ctx.store.getById(id);\n if (el) this.clipboard.push(structuredClone(el));\n }\n this.pasteCount = 0;\n }\n\n cut(): void {\n if (this.deps.isToolActive()) return;\n this.copy();\n this.deleteSelected();\n }\n\n hasClipboard(): boolean {\n return this.clipboard.length > 0;\n }\n\n paste(): void {\n if (this.deps.isToolActive()) return;\n this.flushPendingNudge();\n if (this.clipboard.length === 0) return;\n const sel = this.selectTool();\n if (!sel) return;\n\n const cursor = this.deps.getLastPointerWorld?.() ?? null;\n if (cursor) {\n const bbox = getElementsBoundingBox(this.clipboard);\n if (bbox) {\n const centerX = bbox.x + bbox.w / 2;\n const centerY = bbox.y + bbox.h / 2;\n this.insertClones(this.clipboard, { x: cursor.x - centerX, y: cursor.y - centerY }, sel);\n return;\n }\n }\n\n this.pasteCount++;\n this.insertClones(this.clipboard, { x: this.pasteCount * 20, y: this.pasteCount * 20 }, sel);\n }\n\n duplicate(): void {\n if (this.deps.isToolActive()) return;\n this.flushPendingNudge();\n const sel = this.selectTool();\n if (!sel) return;\n const source: CanvasElement[] = [];\n for (const id of sel.tool.selectedIds) {\n const el = sel.ctx.store.getById(id);\n if (el) source.push(el);\n }\n if (source.length === 0) return;\n this.insertClones(source, { x: 20, y: 20 }, sel);\n }\n\n deselect(): void {\n if (this.deps.isToolActive()) return;\n const sel = this.selectTool();\n if (!sel) return;\n if (sel.tool.selectedIds.length === 0) return;\n sel.tool.setSelection([]);\n sel.ctx.requestRender();\n }\n\n selectAll(): void {\n if (this.deps.isToolActive()) return;\n const tm = this.deps.getToolManager();\n const ctx = this.deps.getToolContext();\n if (!tm || !ctx) return;\n if (tm.activeTool?.name !== 'select') {\n ctx.switchTool?.('select');\n }\n const sel = this.selectTool();\n if (!sel) return;\n const ids = sel.ctx.store\n .getAll()\n .filter(\n (el) =>\n !el.locked &&\n (sel.ctx.isLayerVisible?.(el.layerId) ?? true) &&\n !(sel.ctx.isLayerLocked?.(el.layerId) ?? false),\n )\n .map((el) => el.id);\n sel.tool.setSelection(ids);\n sel.ctx.requestRender();\n }\n\n zoomToFit(): void {\n if (this.deps.isToolActive()) return;\n this.deps.fitToContent?.();\n }\n\n group(): void {\n if (this.deps.isToolActive()) return;\n this.deps.group?.();\n }\n\n ungroup(): void {\n if (this.deps.isToolActive()) return;\n this.deps.ungroup?.();\n }\n\n toggleLock(): void {\n if (this.deps.isToolActive()) return;\n this.deps.toggleLock?.();\n }\n\n zOrder(operation: 'forward' | 'backward' | 'front' | 'back'): void {\n if (this.deps.isToolActive()) return;\n this.flushPendingNudge();\n const sel = this.selectTool();\n if (!sel) return;\n const ids = sel.tool.selectedIds;\n if (ids.length === 0) return;\n const recorder = this.deps.getHistoryRecorder();\n recorder?.begin();\n for (const id of ids) {\n switch (operation) {\n case 'forward':\n sel.ctx.store.bringForward(id);\n break;\n case 'backward':\n sel.ctx.store.sendBackward(id);\n break;\n case 'front':\n sel.ctx.store.bringToFront(id);\n break;\n case 'back':\n sel.ctx.store.sendToBack(id);\n break;\n }\n }\n recorder?.commit();\n sel.ctx.requestRender();\n }\n\n private insertClones(\n source: CanvasElement[],\n offset: Point,\n sel: { tool: SelectTool; ctx: ToolContext },\n ): void {\n const idMap = new Map<string, string>();\n for (const el of source) {\n idMap.set(el.id, createId(el.type));\n }\n\n const groupIdMap = new Map<string, string>();\n for (const el of source) {\n if (el.groupId && !groupIdMap.has(el.groupId)) groupIdMap.set(el.groupId, createId('group'));\n }\n\n const newIds: string[] = [];\n const recorder = this.deps.getHistoryRecorder();\n recorder?.begin();\n\n for (const el of source) {\n const clone = structuredClone(el);\n const newId = idMap.get(el.id);\n if (!newId) continue;\n clone.id = newId;\n if (clone.groupId) clone.groupId = groupIdMap.get(clone.groupId) ?? clone.groupId;\n clone.position = { x: clone.position.x + offset.x, y: clone.position.y + offset.y };\n\n if (clone.type === 'arrow') {\n const arrow = clone;\n arrow.from = { x: arrow.from.x + offset.x, y: arrow.from.y + offset.y };\n arrow.to = { x: arrow.to.x + offset.x, y: arrow.to.y + offset.y };\n delete arrow.cachedControlPoint;\n\n if (arrow.fromBinding) {\n const newTarget = idMap.get(arrow.fromBinding.elementId);\n if (newTarget) {\n arrow.fromBinding = { elementId: newTarget };\n } else {\n delete arrow.fromBinding;\n }\n }\n if (arrow.toBinding) {\n const newTarget = idMap.get(arrow.toBinding.elementId);\n if (newTarget) {\n arrow.toBinding = { elementId: newTarget };\n } else {\n delete arrow.toBinding;\n }\n }\n }\n\n if (sel.ctx.activeLayerId) {\n clone.layerId = sel.ctx.activeLayerId;\n }\n\n sel.ctx.store.add(clone);\n newIds.push(clone.id);\n }\n\n recorder?.commit();\n sel.tool.setSelection(newIds);\n sel.ctx.requestRender();\n }\n}\n","export type ShortcutBindings = Record<string, string | string[] | null>;\r\n\r\nexport interface ShortcutOptions {\r\n scope?: 'focus' | 'window';\r\n bindings?: ShortcutBindings;\r\n}\r\n\r\nexport interface ShortcutsApi {\r\n rebind(action: string, bindings: string | string[] | null): void;\r\n disable(action: string): void;\r\n reset(action?: string): void;\r\n getBindings(): Record<string, string[]>;\r\n}\r\n\r\ninterface ParsedBinding {\r\n mod: boolean;\r\n ctrl: boolean;\r\n meta: boolean;\r\n shift: boolean;\r\n alt: boolean;\r\n key: string;\r\n digit: boolean;\r\n}\r\n\r\nconst DEFAULT_BINDINGS: readonly (readonly [string, readonly string[]])[] = [\r\n ['delete', ['delete', 'backspace']],\r\n ['deselect', ['escape']],\r\n ['undo', ['mod+z']],\r\n ['redo', ['mod+y', 'mod+shift+z']],\r\n ['select-all', ['mod+a']],\r\n ['copy', ['mod+c']],\r\n ['paste', ['mod+v']],\r\n ['duplicate', ['mod+d']],\r\n ['z-forward', [']']],\r\n ['z-backward', ['[']],\r\n ['z-front', ['mod+]']],\r\n ['z-back', ['mod+[']],\r\n ['zoom-fit', ['shift+1']],\r\n ['zoom-in', ['mod+=']],\r\n ['zoom-out', ['mod+-']],\r\n ['zoom-reset', ['mod+0']],\r\n ['group', ['mod+g']],\r\n ['ungroup', ['mod+shift+g']],\r\n ['cut', ['mod+x']],\r\n ['toggle-lock', ['mod+shift+l']],\r\n ['nudge-left', ['arrowleft']],\r\n ['nudge-right', ['arrowright']],\r\n ['nudge-up', ['arrowup']],\r\n ['nudge-down', ['arrowdown']],\r\n ['tool:select', ['v']],\r\n ['tool:hand', ['h']],\r\n ['tool:pencil', ['p']],\r\n ['tool:eraser', ['e']],\r\n ['tool:arrow', ['a']],\r\n ['tool:note', ['n']],\r\n ['tool:text', ['t']],\r\n ['tool:shape', ['s']],\r\n ['tool:measure', ['m']],\r\n ['tool:template', ['g']],\r\n];\r\n\r\nconst ALLOW_SHIFT = new Set(['nudge-left', 'nudge-right', 'nudge-up', 'nudge-down']);\r\nconst MODIFIERS = new Set(['mod', 'ctrl', 'meta', 'shift', 'alt']);\r\n\r\nfunction parseBinding(binding: string): ParsedBinding {\r\n const parts = binding.toLowerCase().split('+');\r\n const key = parts.pop();\r\n if (key === undefined || key.length === 0 || MODIFIERS.has(key)) {\r\n throw new Error(`Invalid shortcut binding \"${binding}\": missing key`);\r\n }\r\n const normalizedKey = key === 'space' ? ' ' : key;\r\n const parsed: ParsedBinding = {\r\n mod: false,\r\n ctrl: false,\r\n meta: false,\r\n shift: false,\r\n alt: false,\r\n key: normalizedKey,\r\n digit: /^[0-9]$/.test(normalizedKey),\r\n };\r\n for (const part of parts) {\r\n switch (part) {\r\n case 'mod':\r\n parsed.mod = true;\r\n break;\r\n case 'ctrl':\r\n parsed.ctrl = true;\r\n break;\r\n case 'meta':\r\n parsed.meta = true;\r\n break;\r\n case 'shift':\r\n parsed.shift = true;\r\n break;\r\n case 'alt':\r\n parsed.alt = true;\r\n break;\r\n default:\r\n throw new Error(`Invalid shortcut binding \"${binding}\": unknown modifier \"${part}\"`);\r\n }\r\n }\r\n if (parsed.mod && (parsed.ctrl || parsed.meta)) {\r\n throw new Error(\r\n `Invalid shortcut binding \"${binding}\": \"mod\" already means Ctrl or Cmd; don't combine it with ctrl/meta`,\r\n );\r\n }\r\n return parsed;\r\n}\r\n\r\nfunction bindingMatches(p: ParsedBinding, e: KeyboardEvent, allowShift: boolean): boolean {\r\n if (p.mod) {\r\n if (!e.ctrlKey && !e.metaKey) return false;\r\n } else if (e.ctrlKey !== p.ctrl || e.metaKey !== p.meta) {\r\n return false;\r\n }\r\n if (!allowShift && e.shiftKey !== p.shift) return false;\r\n if (e.altKey !== p.alt) return false;\r\n return p.digit ? e.code === `Digit${p.key}` : e.key.toLowerCase() === p.key;\r\n}\r\n\r\nfunction sameBinding(a: ParsedBinding, b: ParsedBinding): boolean {\r\n return (\r\n a.key === b.key &&\r\n a.mod === b.mod &&\r\n a.ctrl === b.ctrl &&\r\n a.meta === b.meta &&\r\n a.shift === b.shift &&\r\n a.alt === b.alt\r\n );\r\n}\r\n\r\nfunction toArray(bindings: string | string[] | null): string[] {\r\n if (bindings === null) return [];\r\n return Array.isArray(bindings) ? [...bindings] : [bindings];\r\n}\r\n\r\nexport class ShortcutMap implements ShortcutsApi {\r\n private raw = new Map<string, string[]>();\r\n private parsed = new Map<string, ParsedBinding[]>();\r\n\r\n constructor(overrides?: ShortcutBindings) {\r\n this.applyDefaults();\r\n if (overrides) {\r\n for (const [action, bindings] of Object.entries(overrides)) {\r\n this.rebind(action, bindings);\r\n }\r\n }\r\n }\r\n\r\n /** First matching action in registration order wins when bindings conflict. */\r\n match(e: KeyboardEvent): string | null {\r\n for (const [action, parsedList] of this.parsed) {\r\n const allowShift = ALLOW_SHIFT.has(action);\r\n for (const p of parsedList) {\r\n if (bindingMatches(p, e, allowShift)) return action;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n rebind(action: string, bindings: string | string[] | null): void {\r\n const list = toArray(bindings);\r\n const parsedList = list.map(parseBinding);\r\n for (const p of parsedList) {\r\n for (const [otherAction, otherList] of this.parsed) {\r\n if (otherAction === action) continue;\r\n if (otherList.some((q) => sameBinding(p, q))) {\r\n console.warn(\r\n `[fieldnotes] shortcut binding for \"${action}\" conflicts with \"${otherAction}\"; first registered wins`,\r\n );\r\n }\r\n }\r\n }\r\n this.raw.set(action, list);\r\n this.parsed.set(action, parsedList);\r\n }\r\n\r\n disable(action: string): void {\r\n this.rebind(action, null);\r\n }\r\n\r\n reset(action?: string): void {\r\n if (action === undefined) {\r\n this.raw.clear();\r\n this.parsed.clear();\r\n this.applyDefaults();\r\n return;\r\n }\r\n const def = DEFAULT_BINDINGS.find(([name]) => name === action);\r\n if (def) {\r\n this.rebind(action, [...def[1]]);\r\n } else if (this.raw.has(action)) {\r\n this.raw.delete(action);\r\n this.parsed.delete(action);\r\n }\r\n }\r\n\r\n getBindings(): Record<string, string[]> {\r\n const out: Record<string, string[]> = {};\r\n for (const [action, list] of this.raw) {\r\n out[action] = [...list];\r\n }\r\n return out;\r\n }\r\n\r\n private applyDefaults(): void {\r\n for (const [action, bindings] of DEFAULT_BINDINGS) {\r\n this.rebind(action, [...bindings]);\r\n }\r\n }\r\n}\r\n","import type { Camera } from './camera';\r\nimport type { ToolContext } from '../tools/types';\r\nimport type { ShortcutOptions, ShortcutsApi } from './shortcut-map';\r\nimport { ShortcutMap } from './shortcut-map';\r\nimport type { KeyboardActions } from './keyboard-actions';\r\n\r\nconst ZOOM_STEP = 1.2;\r\n\r\nconst NUDGE_DELTAS: Record<string, readonly [number, number]> = {\r\n 'nudge-left': [-1, 0],\r\n 'nudge-right': [1, 0],\r\n 'nudge-up': [0, -1],\r\n 'nudge-down': [0, 1],\r\n};\r\n\r\nexport interface KeyboardHandlerDeps {\r\n element: HTMLElement;\r\n camera: Camera;\r\n actions: KeyboardActions;\r\n scope: 'focus' | 'window';\r\n shortcuts?: ShortcutOptions;\r\n abortSignal: AbortSignal;\r\n getToolContext: () => ToolContext | null;\r\n getIsToolActive: () => boolean;\r\n getLastPointerEvent: () => PointerEvent | null;\r\n setSpaceHeld: (v: boolean) => void;\r\n getActivePointerCount: () => number;\r\n dispatchToolHover: (e: PointerEvent) => void;\r\n}\r\n\r\nexport class KeyboardHandler {\r\n private readonly shortcutMap: ShortcutMap;\r\n\r\n constructor(private readonly deps: KeyboardHandlerDeps) {\r\n this.shortcutMap = new ShortcutMap(deps.shortcuts?.bindings);\r\n window.addEventListener('keydown', this.onKeyDown, { signal: deps.abortSignal });\r\n window.addEventListener('keyup', this.onKeyUp, { signal: deps.abortSignal });\r\n }\r\n\r\n get shortcuts(): ShortcutsApi {\r\n return this.shortcutMap;\r\n }\r\n\r\n private viewportCenter(): { x: number; y: number } {\r\n const rect = this.deps.element.getBoundingClientRect();\r\n return { x: rect.width / 2, y: rect.height / 2 };\r\n }\r\n\r\n private zoomByFactor(factor: number): void {\r\n this.deps.camera.zoomAt(this.deps.camera.zoom * factor, this.viewportCenter());\r\n }\r\n\r\n private zoomToLevel(level: number): void {\r\n this.deps.camera.zoomAt(level, this.viewportCenter());\r\n }\r\n\r\n onKeyDown = (e: KeyboardEvent): void => {\r\n const target = e.target as HTMLElement | null;\r\n if (target?.isContentEditable) return;\r\n const tag = target?.tagName;\r\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return;\r\n if (!this.isInScope()) return;\r\n\r\n if (e.key === ' ') {\r\n this.deps.setSpaceHeld(true);\r\n }\r\n const action = this.shortcutMap.match(e);\r\n if (action !== null) {\r\n this.runAction(action, e);\r\n }\r\n };\r\n\r\n onKeyUp = (e: KeyboardEvent): void => {\r\n if (e.key === ' ') {\r\n this.deps.setSpaceHeld(false);\r\n if (this.deps.getActivePointerCount() === 0) {\r\n const lastPointerEvent = this.deps.getLastPointerEvent();\r\n if (lastPointerEvent) {\r\n this.deps.dispatchToolHover(lastPointerEvent);\r\n } else {\r\n this.deps.getToolContext()?.setCursor?.('default');\r\n }\r\n }\r\n }\r\n };\r\n\r\n runAction(action: string, e?: KeyboardEvent): void {\r\n switch (action) {\r\n case 'delete':\r\n e?.preventDefault();\r\n this.deps.actions.deleteSelected();\r\n return;\r\n case 'deselect':\r\n this.deps.actions.deselect();\r\n return;\r\n case 'undo':\r\n e?.preventDefault();\r\n this.deps.actions.undo();\r\n return;\r\n case 'redo':\r\n e?.preventDefault();\r\n this.deps.actions.redo();\r\n return;\r\n case 'select-all':\r\n e?.preventDefault();\r\n this.deps.actions.selectAll();\r\n return;\r\n case 'copy':\r\n e?.preventDefault();\r\n this.deps.actions.copy();\r\n return;\r\n case 'paste':\r\n e?.preventDefault();\r\n this.deps.actions.paste();\r\n return;\r\n case 'duplicate':\r\n e?.preventDefault();\r\n this.deps.actions.duplicate();\r\n return;\r\n case 'z-forward':\r\n e?.preventDefault();\r\n this.deps.actions.zOrder('forward');\r\n return;\r\n case 'z-backward':\r\n e?.preventDefault();\r\n this.deps.actions.zOrder('backward');\r\n return;\r\n case 'z-front':\r\n e?.preventDefault();\r\n this.deps.actions.zOrder('front');\r\n return;\r\n case 'z-back':\r\n e?.preventDefault();\r\n this.deps.actions.zOrder('back');\r\n return;\r\n case 'zoom-fit':\r\n e?.preventDefault();\r\n this.deps.actions.zoomToFit();\r\n return;\r\n case 'group':\r\n e?.preventDefault();\r\n this.deps.actions.group();\r\n return;\r\n case 'ungroup':\r\n e?.preventDefault();\r\n this.deps.actions.ungroup();\r\n return;\r\n case 'cut':\r\n e?.preventDefault();\r\n this.deps.actions.cut();\r\n return;\r\n case 'toggle-lock':\r\n e?.preventDefault();\r\n this.deps.actions.toggleLock();\r\n return;\r\n case 'zoom-in':\r\n e?.preventDefault();\r\n this.zoomByFactor(ZOOM_STEP);\r\n return;\r\n case 'zoom-out':\r\n e?.preventDefault();\r\n this.zoomByFactor(1 / ZOOM_STEP);\r\n return;\r\n case 'zoom-reset':\r\n e?.preventDefault();\r\n this.zoomToLevel(1);\r\n return;\r\n case 'nudge-left':\r\n case 'nudge-right':\r\n case 'nudge-up':\r\n case 'nudge-down': {\r\n const delta = NUDGE_DELTAS[action];\r\n if (delta && this.deps.actions.nudge(delta[0], delta[1], e?.shiftKey ?? false)) {\r\n e?.preventDefault();\r\n }\r\n return;\r\n }\r\n default:\r\n if (action.startsWith('tool:')) {\r\n if (this.deps.getIsToolActive()) return;\r\n e?.preventDefault();\r\n this.deps.getToolContext()?.switchTool?.(action.slice('tool:'.length));\r\n return;\r\n }\r\n console.warn(`[fieldnotes] unknown shortcut action \"${action}\"`);\r\n }\r\n }\r\n\r\n private isInScope(): boolean {\r\n if (this.deps.scope === 'window') return true;\r\n const active = document.activeElement;\r\n return active === this.deps.element || this.deps.element.contains(active);\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { Camera } from './camera';\r\nimport type { ToolManager } from '../tools/tool-manager';\r\nimport type { ToolContext, PointerState } from '../tools/types';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport type { HistoryStack } from '../history/history-stack';\r\nimport type { ShortcutOptions, ShortcutsApi } from './shortcut-map';\r\nimport { InputFilter } from './input-filter';\r\nimport { KeyboardActions } from './keyboard-actions';\r\nimport { KeyboardHandler } from './keyboard-handler';\r\n\r\nconst ZOOM_SENSITIVITY = 0.001;\r\nconst MIDDLE_BUTTON = 1;\r\nconst LONG_PRESS_MS = 500;\r\n\r\nexport interface InputHandlerOptions {\r\n toolManager?: ToolManager;\r\n toolContext?: ToolContext;\r\n historyRecorder?: HistoryRecorder;\r\n historyStack?: HistoryStack;\r\n fitToContent?: () => void;\r\n group?: () => void;\r\n ungroup?: () => void;\r\n toggleLock?: () => void;\r\n openContextMenu?: (screenPos: Point, world: Point) => void;\r\n shortcuts?: ShortcutOptions;\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 lastPointerEvent: PointerEvent | null = null;\r\n private readonly inputFilter = new InputFilter();\r\n private deferredDown: PointerEvent | null = null;\r\n private longPressTimer: ReturnType<typeof setTimeout> | null = null;\r\n private longPressStart: { x: number; y: number } | null = null;\r\n private readonly abortController = new AbortController();\r\n private readonly actions: KeyboardActions;\r\n private readonly keyboard: KeyboardHandler;\r\n private readonly scope: 'focus' | 'window';\r\n private readonly openContextMenu?: (screenPos: Point, world: Point) => void;\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.actions = new KeyboardActions({\r\n getToolManager: () => this.toolManager,\r\n getToolContext: () => this.toolContext,\r\n getHistoryRecorder: () => this.historyRecorder,\r\n getHistoryStack: () => this.historyStack,\r\n isToolActive: () => this.isToolActive,\r\n fitToContent: options.fitToContent,\r\n group: options.group,\r\n ungroup: options.ungroup,\r\n toggleLock: options.toggleLock,\r\n getLastPointerWorld: () => this.lastPointerWorld(),\r\n });\r\n this.openContextMenu = options.openContextMenu;\r\n this.scope = options.shortcuts?.scope ?? 'focus';\r\n this.keyboard = new KeyboardHandler({\r\n element: this.element,\r\n camera: this.camera,\r\n actions: this.actions,\r\n scope: this.scope,\r\n shortcuts: options.shortcuts,\r\n abortSignal: this.abortController.signal,\r\n getToolContext: () => this.toolContext,\r\n getIsToolActive: () => this.isToolActive,\r\n getLastPointerEvent: () => this.lastPointerEvent,\r\n setSpaceHeld: (v) => {\r\n this.spaceHeld = v;\r\n },\r\n getActivePointerCount: () => this.activePointers.size,\r\n dispatchToolHover: (e) => this.dispatchToolHover(e),\r\n });\r\n this.element.style.touchAction = 'none';\r\n if (this.scope === 'focus') {\r\n this.element.tabIndex = 0;\r\n // Suppressed like other canvas SDKs; consumers needing a focus ring style their container.\r\n this.element.style.outline = 'none';\r\n }\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 flushPendingHistory(): void {\r\n this.actions.flushPendingNudge();\r\n }\r\n\r\n get shortcuts(): ShortcutsApi {\r\n return this.keyboard.shortcuts;\r\n }\r\n\r\n destroy(): void {\r\n this.actions.dispose();\r\n this.abortController.abort();\r\n this.inputFilter.reset();\r\n this.cancelLongPress();\r\n this.deferredDown = null;\r\n this.lastPointerEvent = null;\r\n if (this.scope === 'focus') {\r\n this.element.removeAttribute('tabindex');\r\n this.element.style.outline = '';\r\n }\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.onPointerLeave, opts);\r\n this.element.addEventListener('pointercancel', this.onPointerUp, opts);\r\n this.element.addEventListener('contextmenu', this.onContextMenu, 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.focusSelf();\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.cancelLongPress();\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.cancelLongPress();\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 (\r\n this.activePointers.size === 1 &&\r\n (e.button === 0 || e.pointerType === 'touch' || e.pointerType === 'pen')\r\n ) {\r\n const result = this.inputFilter.filterDown(e);\r\n if (result.action === 'suppress') return;\r\n if (result.action === 'defer') {\r\n this.deferredDown = e;\r\n this.startLongPress(e);\r\n return;\r\n }\r\n this.dispatchToolDown(e);\r\n }\r\n };\r\n\r\n private onPointerMove = (e: PointerEvent): void => {\r\n this.lastPointerEvent = e;\r\n\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 (e.pointerType === 'pen' && !this.activePointers.has(e.pointerId)) {\r\n this.dispatchToolHover(e);\r\n } else if (this.isToolActive) {\r\n this.dispatchToolMove(e);\r\n } else if (this.deferredDown) {\r\n const result = this.inputFilter.filterMove(e);\r\n if (result.action === 'dispatch') {\r\n this.cancelLongPress();\r\n this.dispatchToolDown(this.deferredDown);\r\n this.deferredDown = null;\r\n this.dispatchToolMove(e);\r\n }\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.cancelLongPress();\r\n try {\r\n this.element.releasePointerCapture(e.pointerId);\r\n } catch {\r\n // Already released (e.g., pointercancel fired first)\r\n }\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 const upResult = this.inputFilter.filterUp(e);\r\n\r\n if (this.isToolActive) {\r\n this.dispatchToolUp(e);\r\n this.isToolActive = false;\r\n } else if (this.deferredDown && upResult.pendingTap) {\r\n this.dispatchToolDown(this.deferredDown);\r\n this.dispatchToolUp(e);\r\n this.deferredDown = null;\r\n } else {\r\n this.deferredDown = null;\r\n }\r\n };\r\n\r\n runAction(action: string, e?: KeyboardEvent): void {\r\n this.keyboard.runAction(action, e);\r\n }\r\n\r\n hasClipboard(): boolean {\r\n return this.actions.hasClipboard();\r\n }\r\n\r\n private startPinch(): void {\r\n this.cancelLongPress();\r\n this.inputFilter.reset();\r\n this.deferredDown = null;\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 lastPointerWorld(): { x: number; y: number } | null {\r\n const e = this.lastPointerEvent;\r\n if (!e) return null;\r\n const rect = this.element.getBoundingClientRect();\r\n return this.camera.screenToWorld({ x: e.clientX - rect.left, y: e.clientY - rect.top });\r\n }\r\n\r\n private onContextMenu = (e: MouseEvent): void => {\r\n e.preventDefault();\r\n if (this.toolManager?.activeTool?.name !== 'select') return;\r\n const rect = this.element.getBoundingClientRect();\r\n const world = this.camera.screenToWorld({ x: e.clientX - rect.left, y: e.clientY - rect.top });\r\n this.openContextMenu?.({ x: e.clientX, y: e.clientY }, world);\r\n };\r\n\r\n private onPointerLeave = (e: PointerEvent): void => {\r\n this.lastPointerEvent = null;\r\n this.onPointerUp(e);\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 pointerType: e.pointerType === 'touch' || e.pointerType === 'pen' ? e.pointerType : 'mouse',\r\n shiftKey: e.shiftKey,\r\n };\r\n }\r\n\r\n private dispatchToolDown(e: PointerEvent): void {\r\n if (!this.toolManager || !this.toolContext) return;\r\n this.actions.flushPendingNudge();\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 isInScope(): boolean {\r\n if (this.scope === 'window') return true;\r\n const active = document.activeElement;\r\n return active === this.element || this.element.contains(active);\r\n }\r\n\r\n private focusSelf(): void {\r\n if (this.scope !== 'focus' || this.isInScope()) return;\r\n this.element.focus({ preventScroll: true });\r\n }\r\n\r\n private cancelToolIfActive(e: PointerEvent): void {\r\n this.cancelLongPress();\r\n if (this.isToolActive) {\r\n this.dispatchToolUp(e);\r\n this.isToolActive = false;\r\n }\r\n this.deferredDown = null;\r\n }\r\n\r\n private startLongPress(e: PointerEvent): void {\r\n if (e.pointerType !== 'touch') return;\r\n if (this.toolManager?.activeTool?.name !== 'select') return;\r\n this.longPressStart = { x: e.clientX, y: e.clientY };\r\n this.longPressTimer = setTimeout(() => this.fireLongPress(), LONG_PRESS_MS);\r\n }\r\n\r\n private cancelLongPress(): void {\r\n if (this.longPressTimer !== null) {\r\n clearTimeout(this.longPressTimer);\r\n this.longPressTimer = null;\r\n }\r\n this.longPressStart = null;\r\n }\r\n\r\n private fireLongPress(): void {\r\n this.longPressTimer = null;\r\n if (!this.deferredDown || this.activePointers.size !== 1 || this.isPanning) return;\r\n const start = this.longPressStart;\r\n if (!start) return;\r\n const rect = this.element.getBoundingClientRect();\r\n const world = this.camera.screenToWorld({ x: start.x - rect.left, y: start.y - rect.top });\r\n this.deferredDown = null;\r\n this.openContextMenu?.({ x: start.x, y: start.y }, world);\r\n }\r\n}\r\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 private cachedCanvas: OffscreenCanvas | HTMLCanvasElement | null = null;\r\n private cachedCtx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null = null;\r\n private lastZoom = -1;\r\n private lastOffsetX = -Infinity;\r\n private lastOffsetY = -Infinity;\r\n private lastWidth = 0;\r\n private lastHeight = 0;\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\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 === 'none') {\r\n ctx.restore();\r\n return;\r\n }\r\n\r\n const spacing = this.adaptSpacing(this.spacing, camera.zoom);\r\n const keyZoom = camera.zoom;\r\n const keyX = Math.floor(camera.position.x % spacing);\r\n const keyY = Math.floor(camera.position.y % spacing);\r\n\r\n if (\r\n this.cachedCanvas !== null &&\r\n keyZoom === this.lastZoom &&\r\n keyX === this.lastOffsetX &&\r\n keyY === this.lastOffsetY &&\r\n cssWidth === this.lastWidth &&\r\n cssHeight === this.lastHeight\r\n ) {\r\n ctx.drawImage(this.cachedCanvas as CanvasImageSource, 0, 0);\r\n ctx.restore();\r\n return;\r\n }\r\n\r\n this.ensureCachedCanvas(cssWidth, cssHeight, dpr);\r\n\r\n if (this.cachedCtx === null) {\r\n // Fallback: render directly when offscreen canvas is unavailable (e.g. jsdom)\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 ctx.restore();\r\n return;\r\n }\r\n\r\n const offCtx = this.cachedCtx as CanvasRenderingContext2D;\r\n offCtx.clearRect(0, 0, cssWidth, cssHeight);\r\n if (this.pattern === 'dots') {\r\n this.renderDots(offCtx, camera, cssWidth, cssHeight);\r\n } else if (this.pattern === 'grid') {\r\n this.renderGrid(offCtx, camera, cssWidth, cssHeight);\r\n }\r\n\r\n this.lastZoom = keyZoom;\r\n this.lastOffsetX = keyX;\r\n this.lastOffsetY = keyY;\r\n this.lastWidth = cssWidth;\r\n this.lastHeight = cssHeight;\r\n\r\n ctx.drawImage(this.cachedCanvas as CanvasImageSource, 0, 0);\r\n ctx.restore();\r\n }\r\n\r\n private ensureCachedCanvas(cssWidth: number, cssHeight: number, dpr: number): void {\r\n if (\r\n this.cachedCanvas !== null &&\r\n this.lastWidth === cssWidth &&\r\n this.lastHeight === cssHeight\r\n ) {\r\n return;\r\n }\r\n\r\n const physWidth = Math.round(cssWidth * dpr);\r\n const physHeight = Math.round(cssHeight * dpr);\r\n\r\n if (typeof OffscreenCanvas !== 'undefined') {\r\n this.cachedCanvas = new OffscreenCanvas(physWidth, physHeight);\r\n } else if (typeof document !== 'undefined') {\r\n const el = document.createElement('canvas');\r\n el.width = physWidth;\r\n el.height = physHeight;\r\n this.cachedCanvas = el;\r\n } else {\r\n // No offscreen canvas support available; fall back to direct rendering\r\n this.cachedCanvas = null;\r\n this.cachedCtx = null;\r\n return;\r\n }\r\n\r\n const offCtx = this.cachedCanvas.getContext('2d');\r\n if (offCtx !== null) {\r\n (offCtx as CanvasRenderingContext2D).scale(dpr, dpr);\r\n }\r\n this.cachedCtx = offCtx as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;\r\n\r\n // Force re-render on next frame since canvas was recreated\r\n this.lastZoom = -1;\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","type Listener<T> = (data: T) => void;\r\n\r\nexport class EventBus<TEvents extends { [K in keyof TEvents]: TEvents[K] }> {\r\n private listeners = new Map<keyof TEvents, Set<Listener<never>>>();\r\n\r\n on<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): () => void {\r\n const existing = this.listeners.get(event);\r\n if (existing) {\r\n existing.add(listener as Listener<never>);\r\n } else {\r\n const set = new Set<Listener<never>>([listener as Listener<never>]);\r\n this.listeners.set(event, set);\r\n }\r\n return () => this.off(event, listener);\r\n }\r\n\r\n off<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): void {\r\n this.listeners.get(event)?.delete(listener as Listener<never>);\r\n }\r\n\r\n emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void {\r\n this.listeners.get(event)?.forEach((listener) => {\r\n try {\r\n listener(data as never);\r\n } catch (err) {\r\n console.error(`[fieldnotes] listener error for \"${String(event)}\"`, err);\r\n }\r\n });\r\n }\r\n\r\n clear(): void {\r\n this.listeners.clear();\r\n }\r\n}\r\n","import type { Bounds, Point } from './types';\r\n\r\ninterface Entry {\r\n id: string;\r\n bounds: Bounds;\r\n}\r\n\r\nconst MAX_ITEMS = 8;\r\nconst MAX_DEPTH = 8;\r\n\r\nfunction intersects(a: Bounds, b: Bounds): 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\nclass QuadNode {\r\n items: Entry[] = [];\r\n children: QuadNode[] | null = null;\r\n\r\n constructor(\r\n readonly bounds: Bounds,\r\n readonly depth: number,\r\n ) {}\r\n\r\n insert(entry: Entry): void {\r\n if (this.children) {\r\n const idx = this.getChildIndex(entry.bounds);\r\n if (idx !== -1) {\r\n const child = this.children[idx];\r\n if (child) child.insert(entry);\r\n return;\r\n }\r\n this.items.push(entry);\r\n return;\r\n }\r\n\r\n this.items.push(entry);\r\n\r\n if (this.items.length > MAX_ITEMS && this.depth < MAX_DEPTH) {\r\n this.split();\r\n }\r\n }\r\n\r\n remove(id: string): boolean {\r\n const idx = this.items.findIndex((e) => e.id === id);\r\n if (idx !== -1) {\r\n this.items.splice(idx, 1);\r\n return true;\r\n }\r\n\r\n if (this.children) {\r\n for (const child of this.children) {\r\n if (child.remove(id)) {\r\n this.collapseIfEmpty();\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n query(rect: Bounds, result: string[]): void {\r\n if (!intersects(this.bounds, rect)) return;\r\n\r\n for (const item of this.items) {\r\n if (intersects(item.bounds, rect)) {\r\n result.push(item.id);\r\n }\r\n }\r\n\r\n if (this.children) {\r\n for (const child of this.children) {\r\n child.query(rect, result);\r\n }\r\n }\r\n }\r\n\r\n private getChildIndex(itemBounds: Bounds): number {\r\n const midX = this.bounds.x + this.bounds.w / 2;\r\n const midY = this.bounds.y + this.bounds.h / 2;\r\n\r\n const left = itemBounds.x >= this.bounds.x && itemBounds.x + itemBounds.w <= midX;\r\n const right =\r\n itemBounds.x >= midX && itemBounds.x + itemBounds.w <= this.bounds.x + this.bounds.w;\r\n const top = itemBounds.y >= this.bounds.y && itemBounds.y + itemBounds.h <= midY;\r\n const bottom =\r\n itemBounds.y >= midY && itemBounds.y + itemBounds.h <= this.bounds.y + this.bounds.h;\r\n\r\n if (left && top) return 0;\r\n if (right && top) return 1;\r\n if (left && bottom) return 2;\r\n if (right && bottom) return 3;\r\n\r\n return -1;\r\n }\r\n\r\n private split(): void {\r\n const { x, y, w, h } = this.bounds;\r\n const halfW = w / 2;\r\n const halfH = h / 2;\r\n const d = this.depth + 1;\r\n\r\n this.children = [\r\n new QuadNode({ x, y, w: halfW, h: halfH }, d),\r\n new QuadNode({ x: x + halfW, y, w: halfW, h: halfH }, d),\r\n new QuadNode({ x, y: y + halfH, w: halfW, h: halfH }, d),\r\n new QuadNode({ x: x + halfW, y: y + halfH, w: halfW, h: halfH }, d),\r\n ];\r\n\r\n const remaining: Entry[] = [];\r\n for (const item of this.items) {\r\n const idx = this.getChildIndex(item.bounds);\r\n if (idx !== -1) {\r\n const target = this.children[idx];\r\n if (target) target.insert(item);\r\n } else {\r\n remaining.push(item);\r\n }\r\n }\r\n this.items = remaining;\r\n }\r\n\r\n private collapseIfEmpty(): void {\r\n if (!this.children) return;\r\n let totalItems = this.items.length;\r\n for (const child of this.children) {\r\n if (child.children) return;\r\n totalItems += child.items.length;\r\n }\r\n if (totalItems <= MAX_ITEMS) {\r\n for (const child of this.children) {\r\n this.items.push(...child.items);\r\n }\r\n this.children = null;\r\n }\r\n }\r\n}\r\n\r\nexport class Quadtree {\r\n private root: QuadNode;\r\n private _size = 0;\r\n private readonly worldBounds: Bounds;\r\n\r\n constructor(worldBounds: Bounds) {\r\n this.worldBounds = worldBounds;\r\n this.root = new QuadNode(worldBounds, 0);\r\n }\r\n\r\n get size(): number {\r\n return this._size;\r\n }\r\n\r\n insert(id: string, bounds: Bounds): void {\r\n this.root.insert({ id, bounds });\r\n this._size++;\r\n }\r\n\r\n remove(id: string): void {\r\n if (this.root.remove(id)) {\r\n this._size--;\r\n }\r\n }\r\n\r\n update(id: string, newBounds: Bounds): void {\r\n this.remove(id);\r\n this.insert(id, newBounds);\r\n }\r\n\r\n query(rect: Bounds): string[] {\r\n const result: string[] = [];\r\n this.root.query(rect, result);\r\n return result;\r\n }\r\n\r\n queryPoint(point: Point): string[] {\r\n return this.query({ x: point.x, y: point.y, w: 0, h: 0 });\r\n }\r\n\r\n clear(): void {\r\n this.root = new QuadNode(this.worldBounds, 0);\r\n this._size = 0;\r\n }\r\n}\r\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.4;\r\nconst MAX_PRESSURE_SCALE = 1.8;\r\n\r\nexport function pressureToWidth(pressure: number, baseWidth: number): number {\r\n return baseWidth * (MIN_PRESSURE_SCALE + (MAX_PRESSURE_SCALE - 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 } from './types';\r\nimport type { CurveSegment } from './stroke-smoothing';\r\nimport { smoothToSegments, pressureToWidth } from './stroke-smoothing';\r\n\r\nexport interface StrokeWidthBucket {\r\n width: number;\r\n path: Path2D;\r\n}\r\n\r\nexport interface StrokeRenderData {\r\n segments: CurveSegment[]; // always populated; used by hit-testing and the no-Path2D fallback\r\n widths: number[];\r\n buckets: StrokeWidthBucket[] | null; // null when Path2D is unavailable (jsdom / old browsers)\r\n}\r\n\r\n// Strokes are immutable after commit. If points ever become mutable,\r\n// this cache must be invalidated on store.update().\r\nconst cache = new WeakMap<StrokeElement, StrokeRenderData>();\r\n\r\nconst WIDTH_QUANTUM = 0.25;\r\n\r\nfunction buildWidthBuckets(segments: CurveSegment[], widths: number[]): StrokeWidthBucket[] | null {\r\n if (typeof Path2D === 'undefined') return null;\r\n const byWidth = new Map<number, Path2D>();\r\n for (let i = 0; i < segments.length; i++) {\r\n const seg = segments[i];\r\n const w = widths[i];\r\n if (!seg || w === undefined) continue;\r\n const q = Math.max(WIDTH_QUANTUM, Math.round(w / WIDTH_QUANTUM) * WIDTH_QUANTUM);\r\n let path = byWidth.get(q);\r\n if (!path) {\r\n path = new Path2D();\r\n byWidth.set(q, path);\r\n }\r\n // Each segment is an independent open sub-path; moveTo resets the pen between them.\r\n path.moveTo(seg.start.x, seg.start.y);\r\n path.bezierCurveTo(seg.cp1.x, seg.cp1.y, seg.cp2.x, seg.cp2.y, seg.end.x, seg.end.y);\r\n }\r\n return [...byWidth.entries()].map(([width, path]) => ({ width, path }));\r\n}\r\n\r\nexport function computeStrokeSegments(stroke: StrokeElement): StrokeRenderData {\r\n const segments = smoothToSegments(stroke.points);\r\n const widths: number[] = [];\r\n\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 widths.push(w);\r\n }\r\n\r\n const data: StrokeRenderData = { segments, widths, buckets: buildWidthBuckets(segments, widths) };\r\n cache.set(stroke, data);\r\n return data;\r\n}\r\n\r\nexport function getStrokeRenderData(stroke: StrokeElement): StrokeRenderData {\r\n const cached = cache.get(stroke);\r\n if (cached) return cached;\r\n return computeStrokeSegments(stroke);\r\n}\r\n\r\nexport function transferStrokeRenderData(prev: CanvasElement, next: CanvasElement): void {\r\n if (prev.type !== 'stroke' || next.type !== 'stroke') return;\r\n if (prev.points !== next.points) return;\r\n const data = cache.get(prev);\r\n if (data) cache.set(next, data);\r\n}\r\n","import { EventBus } from '../core/event-bus';\r\nimport type { Bounds, Point } from '../core/types';\r\nimport { Quadtree } from '../core/quadtree';\r\nimport { rotatedAABB } from '../core/geometry';\r\nimport { getElementBounds, transferStrokeBounds } from './element-bounds';\r\nimport { getArrowControlPoint } from './arrow-geometry';\r\nimport { sanitizeNoteHtml } from './note-sanitizer';\r\nimport { computeStrokeSegments, transferStrokeRenderData } from './stroke-cache';\r\nimport type { CanvasElement, ElementType } from './types';\r\n\r\nexport interface ElementUpdateEvent {\r\n previous: CanvasElement;\r\n current: CanvasElement;\r\n}\r\n\r\ninterface ElementStoreEvents {\r\n add: CanvasElement;\r\n remove: CanvasElement;\r\n update: ElementUpdateEvent;\r\n clear: null;\r\n}\r\n\r\nexport class ElementStore {\r\n private elements = new Map<string, CanvasElement>();\r\n private bus = new EventBus<ElementStoreEvents>();\r\n private layerOrderMap = new Map<string, number>();\r\n private spatialIndex = new Quadtree({ x: -100000, y: -100000, w: 200000, h: 200000 });\r\n private sortedCache: CanvasElement[] | null = null;\r\n private _versions = new Map<string, number>();\r\n\r\n get count(): number {\r\n return this.elements.size;\r\n }\r\n\r\n getVersion(id: string): number {\r\n return this._versions.get(id) ?? -1;\r\n }\r\n\r\n setLayerOrder(order: Map<string, number>): void {\r\n this.layerOrderMap = new Map(order);\r\n this.sortedCache = null;\r\n }\r\n\r\n getAll(): CanvasElement[] {\r\n if (this.sortedCache) return this.sortedCache;\r\n this.sortedCache = [...this.elements.values()].sort((a, b) => {\r\n const layerA = this.layerOrderMap.get(a.layerId) ?? 0;\r\n const layerB = this.layerOrderMap.get(b.layerId) ?? 0;\r\n if (layerA !== layerB) return layerA - layerB;\r\n return a.zIndex - b.zIndex;\r\n });\r\n return this.sortedCache;\r\n }\r\n\r\n getById(id: string): CanvasElement | undefined {\r\n return this.elements.get(id);\r\n }\r\n\r\n getElementsByType<T extends ElementType>(type: T): Extract<CanvasElement, { type: T }>[] {\r\n return this.getAll().filter(\r\n (el): el is Extract<CanvasElement, { type: T }> => el.type === type,\r\n );\r\n }\r\n\r\n // Spatial index stores the rotation-expanded AABB so rotated elements remain\r\n // broad-phase hit-test/marquee candidates; precise tests run against local bounds.\r\n private indexBounds(element: CanvasElement): Bounds | null {\r\n const bounds = getElementBounds(element);\r\n if (!bounds) return null;\r\n const angle = element.rotation ?? 0;\r\n return angle === 0 ? bounds : rotatedAABB(bounds, angle);\r\n }\r\n\r\n add(element: CanvasElement): void {\r\n this.sortedCache = null;\r\n this._versions.set(element.id, 0);\r\n this.elements.set(element.id, element);\r\n const bounds = this.indexBounds(element);\r\n if (bounds) this.spatialIndex.insert(element.id, bounds);\r\n this.bus.emit('add', element);\r\n }\r\n\r\n update(id: string, partial: Partial<CanvasElement>): void {\r\n const existing = this.elements.get(id);\r\n if (!existing) return;\r\n this.sortedCache = null;\r\n this._versions.set(id, (this._versions.get(id) ?? 0) + 1);\r\n\r\n // Shallow spread preserves the points array identity when `partial` omits points;\r\n // transferStrokeRenderData/transferStrokeBounds rely on that reference equality.\r\n const updated = {\r\n ...existing,\r\n ...partial,\r\n id: existing.id,\r\n type: existing.type,\r\n } as CanvasElement;\r\n\r\n if (updated.type === 'stroke' && existing.type === 'stroke') {\r\n transferStrokeRenderData(existing, updated);\r\n transferStrokeBounds(existing, updated);\r\n }\r\n\r\n if (updated.type === 'arrow') {\r\n const arrow = updated;\r\n arrow.cachedControlPoint = getArrowControlPoint(arrow.from, arrow.to, arrow.bend);\r\n }\r\n\r\n if (updated.type === 'note' && 'text' in partial) {\r\n updated.text = sanitizeNoteHtml(updated.text);\r\n }\r\n\r\n this.elements.set(id, updated);\r\n\r\n const newBounds = this.indexBounds(updated);\r\n if (newBounds) {\r\n this.spatialIndex.update(id, newBounds);\r\n }\r\n\r\n this.bus.emit('update', { previous: existing, current: updated });\r\n }\r\n\r\n remove(id: string): void {\r\n const element = this.elements.get(id);\r\n if (!element) return;\r\n this.sortedCache = null;\r\n this._versions.delete(id);\r\n\r\n this.elements.delete(id);\r\n this.spatialIndex.remove(id);\r\n this.bus.emit('remove', element);\r\n }\r\n\r\n clear(): void {\r\n this.sortedCache = null;\r\n this._versions.clear();\r\n this.elements.clear();\r\n this.spatialIndex.clear();\r\n this.bus.emit('clear', null);\r\n }\r\n\r\n snapshot(): CanvasElement[] {\r\n return this.getAll().map((el) => ({ ...el }));\r\n }\r\n\r\n loadSnapshot(elements: CanvasElement[]): void {\r\n this.sortedCache = null;\r\n this._versions.clear();\r\n this.elements.clear();\r\n this.spatialIndex.clear();\r\n for (const el of elements) {\r\n this.elements.set(el.id, el);\r\n this._versions.set(el.id, 0);\r\n const bounds = this.indexBounds(el);\r\n if (bounds) this.spatialIndex.insert(el.id, bounds);\r\n if (el.type === 'stroke') {\r\n computeStrokeSegments(el);\r\n }\r\n if (el.type === 'arrow' && el.bend !== 0 && !el.cachedControlPoint) {\r\n el.cachedControlPoint = getArrowControlPoint(el.from, el.to, el.bend);\r\n }\r\n }\r\n this.bus.emit('clear', null);\r\n for (const el of elements) {\r\n this.bus.emit('add', el);\r\n }\r\n }\r\n\r\n bringToFront(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const siblings = [...this.elements.values()].filter(\r\n (e) => e.layerId === el.layerId && e.id !== id,\r\n );\r\n if (siblings.length === 0) return;\r\n const maxZ = Math.max(...siblings.map((e) => e.zIndex));\r\n if (el.zIndex >= maxZ) return;\r\n this.update(id, { zIndex: maxZ + 1 });\r\n }\r\n\r\n sendToBack(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const siblings = [...this.elements.values()].filter(\r\n (e) => e.layerId === el.layerId && e.id !== id,\r\n );\r\n if (siblings.length === 0) return;\r\n const minZ = Math.min(...siblings.map((e) => e.zIndex));\r\n if (el.zIndex <= minZ) return;\r\n this.update(id, { zIndex: minZ - 1 });\r\n }\r\n\r\n bringForward(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const sorted = [...this.elements.values()]\r\n .filter((e) => e.layerId === el.layerId)\r\n .sort((a, b) => a.zIndex - b.zIndex);\r\n const idx = sorted.findIndex((e) => e.id === id);\r\n if (idx < 0 || idx >= sorted.length - 1) return;\r\n const next = sorted[idx + 1];\r\n if (!next) return;\r\n const myZ = el.zIndex;\r\n const nextZ = next.zIndex;\r\n this.update(id, { zIndex: nextZ });\r\n this.update(next.id, { zIndex: myZ });\r\n }\r\n\r\n sendBackward(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const sorted = [...this.elements.values()]\r\n .filter((e) => e.layerId === el.layerId)\r\n .sort((a, b) => a.zIndex - b.zIndex);\r\n const idx = sorted.findIndex((e) => e.id === id);\r\n if (idx <= 0) return;\r\n const prev = sorted[idx - 1];\r\n if (!prev) return;\r\n const myZ = el.zIndex;\r\n const prevZ = prev.zIndex;\r\n this.update(id, { zIndex: prevZ });\r\n this.update(prev.id, { zIndex: myZ });\r\n }\r\n\r\n queryRect(rect: Bounds): CanvasElement[] {\r\n const ids = this.spatialIndex.query(rect);\r\n const elements: CanvasElement[] = [];\r\n for (const id of ids) {\r\n const el = this.elements.get(id);\r\n if (el) elements.push(el);\r\n }\r\n return elements.sort((a, b) => {\r\n const layerA = this.layerOrderMap.get(a.layerId) ?? 0;\r\n const layerB = this.layerOrderMap.get(b.layerId) ?? 0;\r\n if (layerA !== layerB) return layerA - layerB;\r\n return a.zIndex - b.zIndex;\r\n });\r\n }\r\n\r\n queryPoint(point: Point): CanvasElement[] {\r\n return this.queryRect({ x: point.x, y: point.y, w: 0, h: 0 });\r\n }\r\n\r\n on<K extends keyof ElementStoreEvents>(\r\n event: K,\r\n listener: (data: ElementStoreEvents[K]) => void,\r\n ): () => void {\r\n return this.bus.on(event, listener);\r\n }\r\n\r\n onChange(listener: () => void): () => void {\r\n const unsubs = [\r\n this.bus.on('add', listener),\r\n this.bus.on('remove', listener),\r\n this.bus.on('update', listener),\r\n this.bus.on('clear', listener),\r\n ];\r\n return () => unsubs.forEach((fn) => fn());\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\n\r\nexport function withRotation(\r\n ctx: CanvasRenderingContext2D,\r\n el: { rotation?: number },\r\n center: Point,\r\n draw: () => void,\r\n): void {\r\n const angle = el.rotation ?? 0;\r\n if (angle === 0) {\r\n draw();\r\n return;\r\n }\r\n ctx.save();\r\n ctx.translate(center.x, center.y);\r\n ctx.rotate(angle);\r\n ctx.translate(-center.x, -center.y);\r\n draw();\r\n ctx.restore();\r\n}\r\n","import type { StrokeElement } from '../types';\r\nimport { getStrokeRenderData } from '../stroke-cache';\r\n\r\nexport function renderStroke(ctx: CanvasRenderingContext2D, stroke: StrokeElement): void {\r\n if (stroke.points.length < 2) return;\r\n\r\n ctx.save();\r\n if (stroke.blendMode) ctx.globalCompositeOperation = stroke.blendMode;\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 data = getStrokeRenderData(stroke);\r\n if (data.buckets) {\r\n for (const bucket of data.buckets) {\r\n ctx.lineWidth = bucket.width;\r\n ctx.stroke(bucket.path);\r\n }\r\n } else {\r\n for (let i = 0; i < data.segments.length; i++) {\r\n const seg = data.segments[i];\r\n const w = data.widths[i];\r\n if (!seg || w === undefined) continue;\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\r\n ctx.restore();\r\n}\r\n","import type { Point, Size } from '../core/types';\r\nimport type { ShapeElement } from './types';\r\n\r\n/** Inverse of lineEndpoints: two endpoints → a line shape's bbox + flip. */\r\nexport function lineFromEndpoints(a: Point, b: Point): { position: Point; size: Size; flip: boolean } {\r\n return {\r\n position: { x: Math.min(a.x, b.x), y: Math.min(a.y, b.y) },\r\n size: { w: Math.abs(b.x - a.x), h: Math.abs(b.y - a.y) },\r\n flip: (b.x > a.x) !== (b.y > a.y),\r\n };\r\n}\r\n\r\n/** The two segment endpoints of a 'line' shape, from its bbox + flip. */\r\nexport function lineEndpoints(shape: ShapeElement): [Point, Point] {\r\n const { x, y } = shape.position;\r\n const { w, h } = shape.size;\r\n return shape.flip\r\n ? [\r\n { x, y: y + h },\r\n { x: x + w, y },\r\n ]\r\n : [\r\n { x, y },\r\n { x: x + w, y: y + h },\r\n ];\r\n}\r\n","import type { ShapeElement } from '../types';\r\nimport { lineEndpoints } from '../shape-geometry';\r\n\r\nexport function renderShape(ctx: CanvasRenderingContext2D, shape: ShapeElement): void {\r\n ctx.save();\r\n\r\n if (shape.fillColor !== 'none' && shape.shape !== 'line') {\r\n ctx.fillStyle = shape.fillColor;\r\n fillShapePath(ctx, shape);\r\n }\r\n\r\n if (shape.strokeWidth > 0) {\r\n ctx.strokeStyle = shape.strokeColor;\r\n ctx.lineWidth = shape.strokeWidth;\r\n strokeShapePath(ctx, shape);\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nfunction fillShapePath(ctx: CanvasRenderingContext2D, shape: ShapeElement): void {\r\n switch (shape.shape) {\r\n case 'rectangle':\r\n ctx.fillRect(shape.position.x, shape.position.y, shape.size.w, shape.size.h);\r\n break;\r\n case 'ellipse': {\r\n const cx = shape.position.x + shape.size.w / 2;\r\n const cy = shape.position.y + shape.size.h / 2;\r\n ctx.beginPath();\r\n ctx.ellipse(cx, cy, shape.size.w / 2, shape.size.h / 2, 0, 0, Math.PI * 2);\r\n ctx.fill();\r\n break;\r\n }\r\n }\r\n}\r\n\r\nfunction strokeShapePath(ctx: CanvasRenderingContext2D, shape: ShapeElement): void {\r\n switch (shape.shape) {\r\n case 'rectangle':\r\n ctx.strokeRect(shape.position.x, shape.position.y, shape.size.w, shape.size.h);\r\n break;\r\n case 'ellipse': {\r\n const cx = shape.position.x + shape.size.w / 2;\r\n const cy = shape.position.y + shape.size.h / 2;\r\n ctx.beginPath();\r\n ctx.ellipse(cx, cy, shape.size.w / 2, shape.size.h / 2, 0, 0, Math.PI * 2);\r\n ctx.stroke();\r\n break;\r\n }\r\n case 'line': {\r\n const [a, b] = lineEndpoints(shape);\r\n ctx.lineCap = 'round';\r\n ctx.beginPath();\r\n ctx.moveTo(a.x, a.y);\r\n ctx.lineTo(b.x, b.y);\r\n ctx.stroke();\r\n break;\r\n }\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { ArrowElement } from './types';\r\nimport { getArrowControlPoint, getArrowTangentAngle } from './arrow-geometry';\r\n\r\nexport interface ArrowRenderGeometry {\r\n controlPoint: Point | null;\r\n tangentStart: number;\r\n tangentEnd: number;\r\n}\r\n\r\n// Intrinsic geometry only (from/to/bend). Binding-resolved endpoints are deliberately\r\n// NOT cached: bound targets can move without the arrow object being replaced.\r\nconst cache = new WeakMap<ArrowElement, ArrowRenderGeometry>();\r\n\r\nexport function getArrowRenderGeometry(arrow: ArrowElement): ArrowRenderGeometry {\r\n const hit = cache.get(arrow);\r\n if (hit) return hit;\r\n const geometry: ArrowRenderGeometry = {\r\n controlPoint:\r\n arrow.bend !== 0\r\n ? (arrow.cachedControlPoint ?? getArrowControlPoint(arrow.from, arrow.to, arrow.bend))\r\n : null,\r\n tangentStart: getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 0),\r\n tangentEnd: getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 1),\r\n };\r\n cache.set(arrow, geometry);\r\n return geometry;\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport type { ArrowElement, CanvasElement } from './types';\r\nimport type { ElementStore } from './element-store';\r\nimport { getArrowTangentAngle } from './arrow-geometry';\r\nimport { getElementBounds } from './element-bounds';\r\n\r\nconst BINDABLE_TYPES = new Set(['note', 'text', 'image', 'html', 'shape']);\r\n\r\nexport function isBindable(element: CanvasElement): boolean {\r\n return BINDABLE_TYPES.has(element.type);\r\n}\r\n\r\nexport function getElementCenter(element: CanvasElement): Point {\r\n if (!('size' in element)) {\r\n throw new Error(`getElementCenter: element type \"${element.type}\" has no size`);\r\n }\r\n return {\r\n x: element.position.x + element.size.w / 2,\r\n y: element.position.y + element.size.h / 2,\r\n };\r\n}\r\n\r\nexport function getEdgeIntersection(bounds: Bounds, outsidePoint: Point): Point {\r\n const cx = bounds.x + bounds.w / 2;\r\n const cy = bounds.y + bounds.h / 2;\r\n const dx = outsidePoint.x - cx;\r\n const dy = outsidePoint.y - cy;\r\n\r\n if (dx === 0 && dy === 0) return { x: cx, y: cy };\r\n\r\n const halfW = bounds.w / 2;\r\n const halfH = bounds.h / 2;\r\n\r\n const scaleX = dx !== 0 ? halfW / Math.abs(dx) : Infinity;\r\n const scaleY = dy !== 0 ? halfH / Math.abs(dy) : Infinity;\r\n const scale = Math.min(scaleX, scaleY);\r\n\r\n return {\r\n x: cx + dx * scale,\r\n y: cy + dy * scale,\r\n };\r\n}\r\n\r\nexport function findBindTarget(\r\n point: Point,\r\n store: ElementStore,\r\n threshold: number,\r\n excludeId?: string,\r\n filter?: (el: CanvasElement) => boolean,\r\n): CanvasElement | null {\r\n let closest: CanvasElement | null = null;\r\n let closestDist = Infinity;\r\n\r\n for (const el of store.getAll()) {\r\n if (!isBindable(el)) continue;\r\n if (excludeId && el.id === excludeId) continue;\r\n if (filter && !filter(el)) continue;\r\n\r\n const bounds = getElementBounds(el);\r\n if (!bounds) continue;\r\n\r\n const dist = distToBounds(point, bounds);\r\n if (dist <= threshold && dist < closestDist) {\r\n closest = el;\r\n closestDist = dist;\r\n }\r\n }\r\n\r\n return closest;\r\n}\r\n\r\nfunction distToBounds(point: Point, bounds: Bounds): number {\r\n const clampedX = Math.max(bounds.x, Math.min(point.x, bounds.x + bounds.w));\r\n const clampedY = Math.max(bounds.y, Math.min(point.y, bounds.y + bounds.h));\r\n return Math.hypot(point.x - clampedX, point.y - clampedY);\r\n}\r\n\r\nexport function findBoundArrows(elementId: string, store: ElementStore): ArrowElement[] {\r\n return store\r\n .getElementsByType('arrow')\r\n .filter((a) => a.fromBinding?.elementId === elementId || a.toBinding?.elementId === elementId);\r\n}\r\n\r\n/** Re-anchor every arrow bound to any of the moved non-arrow elements (each updated once). */\r\nexport function updateArrowsBoundToElements(movedIds: Iterable<string>, store: ElementStore): void {\r\n const movedNonArrowIds = new Set<string>();\r\n for (const id of movedIds) {\r\n const el = store.getById(id);\r\n if (el && el.type !== 'arrow') movedNonArrowIds.add(id);\r\n }\r\n if (movedNonArrowIds.size === 0) return;\r\n const updated = new Set<string>();\r\n for (const id of movedNonArrowIds) {\r\n for (const ba of findBoundArrows(id, store)) {\r\n if (updated.has(ba.id)) continue;\r\n updated.add(ba.id);\r\n const updates = updateBoundArrow(ba, store);\r\n if (updates) store.update(ba.id, updates);\r\n }\r\n }\r\n}\r\n\r\nexport function updateBoundArrow(\r\n arrow: ArrowElement,\r\n store: ElementStore,\r\n): Partial<ArrowElement> | null {\r\n if (!arrow.fromBinding && !arrow.toBinding) return null;\r\n\r\n const updates: Partial<ArrowElement> = {};\r\n\r\n if (arrow.fromBinding) {\r\n const el = store.getById(arrow.fromBinding.elementId);\r\n if (el) {\r\n const center = getElementCenter(el);\r\n updates.from = center;\r\n updates.position = center;\r\n }\r\n }\r\n\r\n if (arrow.toBinding) {\r\n const el = store.getById(arrow.toBinding.elementId);\r\n if (el) {\r\n updates.to = getElementCenter(el);\r\n }\r\n }\r\n\r\n return Object.keys(updates).length > 0 ? updates : null;\r\n}\r\n\r\nexport function clearStaleBindings(\r\n arrow: ArrowElement,\r\n store: ElementStore,\r\n): Partial<ArrowElement> | null {\r\n const updates: Partial<ArrowElement> = {};\r\n let hasUpdates = false;\r\n\r\n if (arrow.fromBinding && !store.getById(arrow.fromBinding.elementId)) {\r\n updates.fromBinding = undefined;\r\n hasUpdates = true;\r\n }\r\n\r\n if (arrow.toBinding && !store.getById(arrow.toBinding.elementId)) {\r\n updates.toBinding = undefined;\r\n hasUpdates = true;\r\n }\r\n\r\n return hasUpdates ? updates : null;\r\n}\r\n\r\nexport function unbindArrow(arrow: ArrowElement, store: ElementStore): Partial<ArrowElement> {\r\n const updates: Partial<ArrowElement> = {};\r\n\r\n if (arrow.fromBinding) {\r\n const el = store.getById(arrow.fromBinding.elementId);\r\n const bounds = el ? getElementBounds(el) : null;\r\n if (bounds) {\r\n const angle = getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 0);\r\n const rayTarget = {\r\n x: arrow.from.x + Math.cos(angle) * 1000,\r\n y: arrow.from.y + Math.sin(angle) * 1000,\r\n };\r\n const edge = getEdgeIntersection(bounds, rayTarget);\r\n updates.from = edge;\r\n updates.position = edge;\r\n }\r\n updates.fromBinding = undefined;\r\n }\r\n\r\n if (arrow.toBinding) {\r\n const el = store.getById(arrow.toBinding.elementId);\r\n const bounds = el ? getElementBounds(el) : null;\r\n if (bounds) {\r\n const angle = getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 1);\r\n // Reverse tangent direction — tangent at t=1 points away from curve body\r\n const rayTarget = {\r\n x: arrow.to.x - Math.cos(angle) * 1000,\r\n y: arrow.to.y - Math.sin(angle) * 1000,\r\n };\r\n updates.to = getEdgeIntersection(bounds, rayTarget);\r\n }\r\n updates.toBinding = undefined;\r\n }\r\n\r\n return updates;\r\n}\r\n","import type { ArrowElement } from '../types';\r\nimport type { ElementStore } from '../element-store';\r\nimport { getArrowRenderGeometry } from '../arrow-render-cache';\r\nimport { getArrowMidpoint } from '../arrow-geometry';\r\nimport { getEdgeIntersection } from '../arrow-binding';\r\nimport { getElementBounds } from '../element-bounds';\r\n\r\nconst ARROWHEAD_LENGTH = 12;\r\nconst ARROWHEAD_ANGLE = Math.PI / 6;\r\nconst ARROW_LABEL_FONT_SIZE = 14;\r\n\r\nexport function renderArrow(\r\n ctx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n store: ElementStore | null,\r\n labelEditingId: string | null,\r\n): void {\r\n const geometry = getArrowRenderGeometry(arrow);\r\n const { visualFrom, visualTo } = getVisualEndpoints(arrow, geometry, store);\r\n\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 if (arrow.fromBinding || arrow.toBinding) {\r\n ctx.setLineDash([8, 4]);\r\n }\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(visualFrom.x, visualFrom.y);\r\n\r\n if (arrow.bend !== 0) {\r\n const cp = geometry.controlPoint;\r\n if (cp) {\r\n ctx.quadraticCurveTo(cp.x, cp.y, visualTo.x, visualTo.y);\r\n }\r\n } else {\r\n ctx.lineTo(visualTo.x, visualTo.y);\r\n }\r\n ctx.stroke();\r\n\r\n renderArrowhead(ctx, arrow, visualTo, geometry.tangentEnd);\r\n ctx.restore();\r\n renderArrowLabel(ctx, arrow, labelEditingId);\r\n}\r\n\r\nfunction renderArrowLabel(\r\n ctx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n labelEditingId: string | null,\r\n): void {\r\n if (!arrow.label || arrow.label.length === 0) return;\r\n if (arrow.id === labelEditingId) return;\r\n const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);\r\n ctx.save();\r\n ctx.font = `${ARROW_LABEL_FONT_SIZE}px system-ui, sans-serif`;\r\n const metrics = ctx.measureText(arrow.label);\r\n const padX = 6;\r\n const padY = 4;\r\n const w = metrics.width + padX * 2;\r\n const h = ARROW_LABEL_FONT_SIZE + padY * 2;\r\n ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';\r\n ctx.beginPath();\r\n ctx.roundRect(mid.x - w / 2, mid.y - h / 2, w, h, 4);\r\n ctx.fill();\r\n ctx.fillStyle = '#1a1a1a';\r\n ctx.textAlign = 'center';\r\n ctx.textBaseline = 'middle';\r\n ctx.fillText(arrow.label, mid.x, mid.y);\r\n ctx.restore();\r\n}\r\n\r\nfunction renderArrowhead(\r\n ctx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n tip: { x: number; y: number },\r\n angle: number,\r\n): void {\r\n ctx.beginPath();\r\n ctx.moveTo(tip.x, tip.y);\r\n ctx.lineTo(\r\n tip.x - ARROWHEAD_LENGTH * Math.cos(angle - ARROWHEAD_ANGLE),\r\n tip.y - ARROWHEAD_LENGTH * Math.sin(angle - ARROWHEAD_ANGLE),\r\n );\r\n ctx.lineTo(\r\n tip.x - ARROWHEAD_LENGTH * Math.cos(angle + ARROWHEAD_ANGLE),\r\n tip.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\nfunction getVisualEndpoints(\r\n arrow: ArrowElement,\r\n geometry: ReturnType<typeof getArrowRenderGeometry>,\r\n store: ElementStore | null,\r\n): {\r\n visualFrom: { x: number; y: number };\r\n visualTo: { x: number; y: number };\r\n} {\r\n let visualFrom = arrow.from;\r\n let visualTo = arrow.to;\r\n\r\n if (!store) return { visualFrom, visualTo };\r\n\r\n if (arrow.fromBinding) {\r\n const el = store.getById(arrow.fromBinding.elementId);\r\n if (el) {\r\n const bounds = getElementBounds(el);\r\n if (bounds) {\r\n const tangentAngle = geometry.tangentStart;\r\n const rayTarget = {\r\n x: arrow.from.x + Math.cos(tangentAngle) * 1000,\r\n y: arrow.from.y + Math.sin(tangentAngle) * 1000,\r\n };\r\n visualFrom = getEdgeIntersection(bounds, rayTarget);\r\n }\r\n }\r\n }\r\n\r\n if (arrow.toBinding) {\r\n const el = store.getById(arrow.toBinding.elementId);\r\n if (el) {\r\n const bounds = getElementBounds(el);\r\n if (bounds) {\r\n const tangentAngle = geometry.tangentEnd;\r\n // Reverse tangent — at t=1 tangent points away from curve body,\r\n // but we need the ray from center back toward the curve\r\n const rayTarget = {\r\n x: arrow.to.x - Math.cos(tangentAngle) * 1000,\r\n y: arrow.to.y - Math.sin(tangentAngle) * 1000,\r\n };\r\n visualTo = getEdgeIntersection(bounds, rayTarget);\r\n }\r\n }\r\n }\r\n\r\n return { visualFrom, visualTo };\r\n}\r\n","import type { ImageElement } from '../types';\r\n\r\nexport function renderImage(\r\n ctx: CanvasRenderingContext2D,\r\n image: ImageElement,\r\n imageCache: Map<string, ImageBitmap | HTMLImageElement | 'failed'>,\r\n onImageLoad: (() => void) | null,\r\n onImageError: ((src: string, cause?: unknown) => void) | null,\r\n): void {\r\n if (imageCache.get(image.src) === 'failed') {\r\n renderImagePlaceholder(ctx, image);\r\n return;\r\n }\r\n const img = getImage(image.src, imageCache, onImageLoad, onImageError);\r\n if (!img) return;\r\n ctx.drawImage(\r\n img as CanvasImageSource,\r\n image.position.x,\r\n image.position.y,\r\n image.size.w,\r\n image.size.h,\r\n );\r\n}\r\n\r\nfunction renderImagePlaceholder(ctx: CanvasRenderingContext2D, image: ImageElement): void {\r\n const { x, y } = image.position;\r\n const { w, h } = image.size;\r\n ctx.save();\r\n ctx.fillStyle = '#eeeeee';\r\n ctx.fillRect(x, y, w, h);\r\n ctx.strokeStyle = '#bdbdbd';\r\n ctx.lineWidth = 1;\r\n ctx.strokeRect(x, y, w, h);\r\n\r\n const glyph = Math.min(24, w / 2, h / 2);\r\n const cx = x + w / 2;\r\n const cy = y + h / 2;\r\n ctx.strokeStyle = '#9e9e9e';\r\n ctx.lineWidth = 2;\r\n ctx.beginPath();\r\n ctx.arc(cx, cy, glyph / 2, 0, Math.PI * 2);\r\n ctx.moveTo(cx - glyph / 2, cy + glyph / 2);\r\n ctx.lineTo(cx + glyph / 2, cy - glyph / 2);\r\n ctx.stroke();\r\n ctx.restore();\r\n}\r\n\r\nfunction getImage(\r\n src: string,\r\n imageCache: Map<string, ImageBitmap | HTMLImageElement | 'failed'>,\r\n onImageLoad: (() => void) | null,\r\n onImageError: ((src: string, cause?: unknown) => void) | null,\r\n): ImageBitmap | HTMLImageElement | null {\r\n const cached = imageCache.get(src);\r\n if (cached) {\r\n if (cached === 'failed') return null;\r\n if (cached instanceof HTMLImageElement) return cached.complete ? cached : null;\r\n return cached;\r\n }\r\n\r\n const img = new Image();\r\n img.src = src;\r\n imageCache.set(src, img);\r\n img.onload = () => {\r\n onImageLoad?.();\r\n // Decode from already-loaded image in memory, not a re-fetch\r\n if (typeof createImageBitmap !== 'undefined') {\r\n createImageBitmap(img)\r\n .then((bitmap) => {\r\n imageCache.set(src, bitmap);\r\n onImageLoad?.();\r\n })\r\n .catch(() => {\r\n /* keep HTMLImageElement fallback — handles CORS rejection */\r\n });\r\n }\r\n };\r\n img.onerror = (event) => {\r\n // failed srcs stay failed for the session; pointing the element at a new src loads fresh\r\n imageCache.set(src, 'failed');\r\n onImageError?.(src, event);\r\n onImageLoad?.();\r\n };\r\n return null;\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { HexOrientation } from './types';\r\n\r\ninterface HexCoord {\r\n col: number;\r\n row: number;\r\n}\r\n\r\nfunction offsetToCube(\r\n col: number,\r\n row: number,\r\n orientation: HexOrientation,\r\n): { q: number; r: number } {\r\n if (orientation === 'pointy') {\r\n return { q: col - (row - (row & 1)) / 2, r: row };\r\n }\r\n return { q: col, r: row - (col - (col & 1)) / 2 };\r\n}\r\n\r\nfunction cubeToOffset(q: number, r: number, orientation: HexOrientation): HexCoord {\r\n if (orientation === 'pointy') {\r\n return { col: q + (r - (r & 1)) / 2, row: r };\r\n }\r\n return { col: q, row: r + (q - (q & 1)) / 2 };\r\n}\r\n\r\nfunction offsetToPixel(\r\n col: number,\r\n row: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point {\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * cellSize;\r\n const rowH = 1.5 * cellSize;\r\n const offsetX = row % 2 !== 0 ? hexW / 2 : 0;\r\n return { x: col * hexW + offsetX, y: row * rowH };\r\n }\r\n const hexH = Math.sqrt(3) * cellSize;\r\n const colW = 1.5 * cellSize;\r\n const offsetY = col % 2 !== 0 ? hexH / 2 : 0;\r\n return { x: col * colW, y: row * hexH + offsetY };\r\n}\r\n\r\nfunction pixelToOffset(\r\n x: number,\r\n y: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): HexCoord {\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * cellSize;\r\n const rowH = 1.5 * cellSize;\r\n const row = Math.round(y / rowH);\r\n const offsetX = row % 2 !== 0 ? hexW / 2 : 0;\r\n return { col: Math.round((x - offsetX) / hexW), row };\r\n }\r\n const hexH = Math.sqrt(3) * cellSize;\r\n const colW = 1.5 * cellSize;\r\n const col = Math.round(x / colW);\r\n const offsetY = col % 2 !== 0 ? hexH / 2 : 0;\r\n return { col, row: Math.round((y - offsetY) / hexH) };\r\n}\r\n\r\nfunction enumerateHexRing(\r\n centerQ: number,\r\n centerR: number,\r\n n: number,\r\n orientation: HexOrientation,\r\n cellSize: number,\r\n): Point[] {\r\n const cells: Point[] = [];\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n const absQ = centerQ + dq;\r\n const absR = centerR + dr;\r\n const off = cubeToOffset(absQ, absR, orientation);\r\n cells.push(offsetToPixel(off.col, off.row, cellSize, orientation));\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function getHexDistance(\r\n a: Point,\r\n b: Point,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): number {\r\n const offA = pixelToOffset(a.x, a.y, cellSize, orientation);\r\n const offB = pixelToOffset(b.x, b.y, cellSize, orientation);\r\n const cubeA = offsetToCube(offA.col, offA.row, orientation);\r\n const cubeB = offsetToCube(offB.col, offB.row, orientation);\r\n const dq = cubeA.q - cubeB.q;\r\n const dr = cubeA.r - cubeB.r;\r\n const ds = -dq - dr;\r\n return Math.max(Math.abs(dq), Math.abs(dr), Math.abs(ds));\r\n}\r\n\r\nexport function getHexCellsInRadius(\r\n center: Point,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n if (n <= 0) {\r\n return [offsetToPixel(off.col, off.row, cellSize, orientation)];\r\n }\r\n return enumerateHexRing(cube.q, cube.r, n, orientation, cellSize);\r\n}\r\n\r\nexport function getHexCellsInCone(\r\n center: Point,\r\n angle: number,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n const centerPixel = offsetToPixel(off.col, off.row, cellSize, orientation);\r\n\r\n if (n <= 0) return [centerPixel];\r\n\r\n const vertexOffset = orientation === 'pointy' ? Math.PI / 6 : 0;\r\n const step = Math.PI / 3;\r\n const snappedAngle = Math.round((angle - vertexOffset) / step) * step + vertexOffset;\r\n\r\n const halfAngle = Math.PI / 6 + 1e-6;\r\n const cells: Point[] = [centerPixel];\r\n\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n if (dq === 0 && dr === 0) continue;\r\n const absQ = cube.q + dq;\r\n const absR = cube.r + dr;\r\n const pixel = offsetToPixel(\r\n cubeToOffset(absQ, absR, orientation).col,\r\n cubeToOffset(absQ, absR, orientation).row,\r\n cellSize,\r\n orientation,\r\n );\r\n\r\n const dx = pixel.x - centerPixel.x;\r\n const dy = pixel.y - centerPixel.y;\r\n let diff = Math.atan2(dy, dx) - snappedAngle;\r\n if (diff > Math.PI) diff -= 2 * Math.PI;\r\n if (diff < -Math.PI) diff += 2 * Math.PI;\r\n\r\n if (Math.abs(diff) <= halfAngle) {\r\n cells.push(pixel);\r\n }\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function getHexCellsInLine(\r\n center: Point,\r\n angle: number,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n const centerPixel = offsetToPixel(off.col, off.row, cellSize, orientation);\r\n\r\n if (n <= 0) return [centerPixel];\r\n\r\n const vertexOffset = orientation === 'pointy' ? Math.PI / 6 : 0;\r\n const step = Math.PI / 3;\r\n const snappedAngle = Math.round((angle - vertexOffset) / step) * step + vertexOffset;\r\n\r\n const cos = Math.cos(snappedAngle);\r\n const sin = Math.sin(snappedAngle);\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const lineLength = n * snapUnit;\r\n const halfWidth = snapUnit * 0.5 + 1e-6;\r\n const cells: Point[] = [];\r\n\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n const absQ = cube.q + dq;\r\n const absR = cube.r + dr;\r\n const pixel = offsetToPixel(\r\n cubeToOffset(absQ, absR, orientation).col,\r\n cubeToOffset(absQ, absR, orientation).row,\r\n cellSize,\r\n orientation,\r\n );\r\n\r\n const dx = pixel.x - centerPixel.x;\r\n const dy = pixel.y - centerPixel.y;\r\n const along = dx * cos + dy * sin;\r\n const perp = Math.abs(-dx * sin + dy * cos);\r\n\r\n if (along >= -snapUnit * 0.1 && along <= lineLength + snapUnit * 0.1 && perp <= halfWidth) {\r\n cells.push(pixel);\r\n }\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function getHexCellsInSquare(\r\n center: Point,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n const centerPixel = offsetToPixel(off.col, off.row, cellSize, orientation);\r\n\r\n if (n <= 0) return [centerPixel];\r\n\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const halfSide = (n * snapUnit) / 2;\r\n const cells: Point[] = [];\r\n\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n const absQ = cube.q + dq;\r\n const absR = cube.r + dr;\r\n const pixel = offsetToPixel(\r\n cubeToOffset(absQ, absR, orientation).col,\r\n cubeToOffset(absQ, absR, orientation).row,\r\n cellSize,\r\n orientation,\r\n );\r\n\r\n if (\r\n Math.abs(pixel.x - centerPixel.x) <= halfSide &&\r\n Math.abs(pixel.y - centerPixel.y) <= halfSide\r\n ) {\r\n cells.push(pixel);\r\n }\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function drawHexPath(\r\n ctx: CanvasRenderingContext2D,\r\n cx: number,\r\n cy: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): void {\r\n const angleOffset = orientation === 'pointy' ? Math.PI / 6 : 0;\r\n ctx.moveTo(cx + cellSize * Math.cos(angleOffset), cy + cellSize * Math.sin(angleOffset));\r\n for (let i = 1; i < 6; i++) {\r\n const a = angleOffset + (Math.PI / 3) * i;\r\n ctx.lineTo(cx + cellSize * Math.cos(a), cy + cellSize * Math.sin(a));\r\n }\r\n ctx.closePath();\r\n}\r\n","import type { TemplateElement, HexOrientation } from '../types';\r\nimport type { ElementStore } from '../element-store';\r\nimport {\r\n getHexCellsInRadius,\r\n getHexCellsInCone,\r\n getHexCellsInLine,\r\n getHexCellsInSquare,\r\n drawHexPath,\r\n} from '../hex-fill';\r\n\r\nexport function renderTemplate(\r\n ctx: CanvasRenderingContext2D,\r\n template: TemplateElement,\r\n store: ElementStore | null,\r\n): void {\r\n const grid = store?.getElementsByType('grid')[0];\r\n if (grid && grid.gridType === 'hex') {\r\n renderHexTemplate(ctx, template, grid.cellSize, grid.hexOrientation);\r\n return;\r\n }\r\n\r\n renderGeometricTemplate(ctx, template);\r\n}\r\n\r\nfunction renderGeometricTemplate(ctx: CanvasRenderingContext2D, template: TemplateElement): void {\r\n const { x: cx, y: cy } = template.position;\r\n const r = template.radius;\r\n\r\n ctx.save();\r\n ctx.globalAlpha = template.opacity;\r\n ctx.fillStyle = template.fillColor;\r\n ctx.strokeStyle = template.strokeColor;\r\n ctx.lineWidth = template.strokeWidth;\r\n\r\n switch (template.templateShape) {\r\n case 'circle':\r\n ctx.beginPath();\r\n ctx.arc(cx, cy, r, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.stroke();\r\n if (template.radiusFeet != null && template.radiusFeet > 0) {\r\n renderRadiusMarker(ctx, cx, cy, r, template.radiusFeet);\r\n }\r\n break;\r\n\r\n case 'square':\r\n ctx.fillRect(cx - r / 2, cy - r / 2, r, r);\r\n ctx.strokeRect(cx - r / 2, cy - r / 2, r, r);\r\n break;\r\n\r\n case 'cone': {\r\n const halfAngle = Math.atan(0.5);\r\n ctx.beginPath();\r\n ctx.moveTo(cx, cy);\r\n ctx.arc(cx, cy, r, template.angle - halfAngle, template.angle + halfAngle);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n\r\n case 'line': {\r\n const halfW = r / 12;\r\n const cos = Math.cos(template.angle);\r\n const sin = Math.sin(template.angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(cx + perpX, cy + perpY);\r\n ctx.lineTo(cx + r * cos + perpX, cy + r * sin + perpY);\r\n ctx.lineTo(cx + r * cos - perpX, cy + r * sin - perpY);\r\n ctx.lineTo(cx - perpX, cy - perpY);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nfunction renderHexTemplate(\r\n ctx: CanvasRenderingContext2D,\r\n template: TemplateElement,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): void {\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const radiusCells = template.radius / snapUnit;\r\n const center = template.position;\r\n\r\n let cells: { x: number; y: number }[];\r\n switch (template.templateShape) {\r\n case 'circle':\r\n cells = getHexCellsInRadius(center, radiusCells, cellSize, orientation);\r\n break;\r\n case 'cone':\r\n cells = getHexCellsInCone(center, template.angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'line':\r\n cells = getHexCellsInLine(center, template.angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'square':\r\n cells = getHexCellsInSquare(center, radiusCells, cellSize, orientation);\r\n break;\r\n }\r\n\r\n ctx.save();\r\n ctx.globalAlpha = template.opacity;\r\n\r\n ctx.beginPath();\r\n for (const cell of cells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.fillStyle = template.fillColor;\r\n ctx.fill();\r\n\r\n ctx.beginPath();\r\n for (const cell of cells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.strokeStyle = template.strokeColor;\r\n ctx.lineWidth = template.strokeWidth;\r\n ctx.stroke();\r\n\r\n {\r\n ctx.globalAlpha = Math.min(template.opacity + 0.1, 1);\r\n ctx.beginPath();\r\n drawHexPath(ctx, center.x, center.y, cellSize, orientation);\r\n ctx.fillStyle = template.strokeColor;\r\n ctx.fill();\r\n ctx.strokeStyle = template.strokeColor;\r\n ctx.lineWidth = template.strokeWidth;\r\n ctx.stroke();\r\n }\r\n\r\n if (\r\n template.templateShape === 'circle' &&\r\n template.radiusFeet != null &&\r\n template.radiusFeet > 0\r\n ) {\r\n const r = template.radius;\r\n renderRadiusMarker(ctx, center.x, center.y, r, template.radiusFeet);\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nfunction renderRadiusMarker(\r\n ctx: CanvasRenderingContext2D,\r\n cx: number,\r\n cy: number,\r\n r: number,\r\n feet: number,\r\n): void {\r\n const markerColor = ctx.strokeStyle as string;\r\n\r\n ctx.save();\r\n ctx.globalAlpha = 1;\r\n\r\n ctx.beginPath();\r\n ctx.setLineDash([4, 4]);\r\n ctx.strokeStyle = markerColor;\r\n ctx.lineWidth = 1.5;\r\n ctx.moveTo(cx, cy);\r\n ctx.lineTo(cx + r, cy);\r\n ctx.stroke();\r\n ctx.setLineDash([]);\r\n\r\n const label = `${Math.round(feet)} ft`;\r\n const fontSize = Math.max(10, Math.min(14, r * 0.15));\r\n ctx.font = `bold ${fontSize}px system-ui, sans-serif`;\r\n ctx.textAlign = 'center';\r\n ctx.textBaseline = 'bottom';\r\n const textX = cx + r / 2;\r\n const textY = cy - 4;\r\n\r\n const metrics = ctx.measureText(label);\r\n const padX = 4;\r\n const padY = 2;\r\n const textW = metrics.width + padX * 2;\r\n const textH = fontSize + padY * 2;\r\n\r\n ctx.fillStyle = 'rgba(255, 255, 255, 0.85)';\r\n ctx.beginPath();\r\n ctx.roundRect(textX - textW / 2, textY - textH, textW, textH, 3);\r\n ctx.fill();\r\n\r\n ctx.fillStyle = markerColor;\r\n ctx.fillText(label, textX, textY - padY);\r\n\r\n ctx.restore();\r\n}\r\n","import type { HexOrientation } from './types';\r\n\r\nexport interface VisibleBounds {\r\n minX: number;\r\n minY: number;\r\n maxX: number;\r\n maxY: number;\r\n}\r\n\r\nexport interface SquareGridLines {\r\n verticals: number[];\r\n horizontals: number[];\r\n}\r\n\r\nexport function getSquareGridLines(bounds: VisibleBounds, cellSize: number): SquareGridLines {\r\n if (cellSize <= 0) return { verticals: [], horizontals: [] };\r\n\r\n const verticals: number[] = [];\r\n const startX = Math.floor(bounds.minX / cellSize) * cellSize;\r\n const endX = Math.ceil(bounds.maxX / cellSize) * cellSize;\r\n for (let x = startX; x <= endX; x += cellSize) {\r\n verticals.push(x);\r\n }\r\n\r\n const horizontals: number[] = [];\r\n const startY = Math.floor(bounds.minY / cellSize) * cellSize;\r\n const endY = Math.ceil(bounds.maxY / cellSize) * cellSize;\r\n for (let y = startY; y <= endY; y += cellSize) {\r\n horizontals.push(y);\r\n }\r\n\r\n return { verticals, horizontals };\r\n}\r\n\r\nexport interface HexVertex {\r\n x: number;\r\n y: number;\r\n}\r\n\r\nexport function getHexVertices(\r\n cx: number,\r\n cy: number,\r\n circumradius: number,\r\n orientation: HexOrientation,\r\n): HexVertex[] {\r\n const vertices: HexVertex[] = [];\r\n const angleOffset = orientation === 'pointy' ? -Math.PI / 2 : 0;\r\n for (let i = 0; i < 6; i++) {\r\n const angle = (Math.PI / 3) * i + angleOffset;\r\n vertices.push({\r\n x: cx + circumradius * Math.cos(angle),\r\n y: cy + circumradius * Math.sin(angle),\r\n });\r\n }\r\n return vertices;\r\n}\r\n\r\nexport function getHexCenters(\r\n bounds: VisibleBounds,\r\n circumradius: number,\r\n orientation: HexOrientation,\r\n): HexVertex[] {\r\n if (circumradius <= 0) return [];\r\n\r\n const centers: HexVertex[] = [];\r\n\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * circumradius;\r\n const hexH = 2 * circumradius;\r\n const rowH = hexH * 0.75;\r\n\r\n const startRow = Math.floor((bounds.minY - circumradius) / rowH);\r\n const endRow = Math.ceil((bounds.maxY + circumradius) / rowH);\r\n const startCol = Math.floor((bounds.minX - hexW) / hexW);\r\n const endCol = Math.ceil((bounds.maxX + hexW) / hexW);\r\n\r\n for (let row = startRow; row <= endRow; row++) {\r\n const offsetX = row % 2 !== 0 ? hexW / 2 : 0;\r\n for (let col = startCol; col <= endCol; col++) {\r\n centers.push({\r\n x: col * hexW + offsetX,\r\n y: row * rowH,\r\n });\r\n }\r\n }\r\n } else {\r\n const hexW = 2 * circumradius;\r\n const hexH = Math.sqrt(3) * circumradius;\r\n const colW = hexW * 0.75;\r\n\r\n const startCol = Math.floor((bounds.minX - circumradius) / colW);\r\n const endCol = Math.ceil((bounds.maxX + circumradius) / colW);\r\n const startRow = Math.floor((bounds.minY - hexH) / hexH);\r\n const endRow = Math.ceil((bounds.maxY + hexH) / hexH);\r\n\r\n for (let col = startCol; col <= endCol; col++) {\r\n const offsetY = col % 2 !== 0 ? hexH / 2 : 0;\r\n for (let row = startRow; row <= endRow; row++) {\r\n centers.push({\r\n x: col * colW,\r\n y: row * hexH + offsetY,\r\n });\r\n }\r\n }\r\n }\r\n\r\n return centers;\r\n}\r\n\r\nexport function renderSquareGrid(\r\n ctx: CanvasRenderingContext2D,\r\n bounds: VisibleBounds,\r\n cellSize: number,\r\n strokeColor: string,\r\n strokeWidth: number,\r\n opacity: number,\r\n): void {\r\n if (cellSize <= 0) return;\r\n\r\n const { verticals, horizontals } = getSquareGridLines(bounds, cellSize);\r\n\r\n ctx.save();\r\n ctx.strokeStyle = strokeColor;\r\n ctx.lineWidth = strokeWidth;\r\n ctx.globalAlpha = opacity;\r\n ctx.beginPath();\r\n\r\n for (const x of verticals) {\r\n ctx.moveTo(x, bounds.minY);\r\n ctx.lineTo(x, bounds.maxY);\r\n }\r\n for (const y of horizontals) {\r\n ctx.moveTo(bounds.minX, y);\r\n ctx.lineTo(bounds.maxX, y);\r\n }\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n}\r\n\r\nexport function renderHexGrid(\r\n ctx: CanvasRenderingContext2D,\r\n bounds: VisibleBounds,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n strokeColor: string,\r\n strokeWidth: number,\r\n opacity: number,\r\n): void {\r\n if (cellSize <= 0) return;\r\n\r\n // Precompute 6 vertex offsets once (12 trig calls total, not 12 per hex)\r\n const angleOffset = orientation === 'pointy' ? -Math.PI / 2 : 0;\r\n const ox0 = cellSize * Math.cos(angleOffset);\r\n const oy0 = cellSize * Math.sin(angleOffset);\r\n const ox1 = cellSize * Math.cos(Math.PI / 3 + angleOffset);\r\n const oy1 = cellSize * Math.sin(Math.PI / 3 + angleOffset);\r\n const ox2 = cellSize * Math.cos((2 * Math.PI) / 3 + angleOffset);\r\n const oy2 = cellSize * Math.sin((2 * Math.PI) / 3 + angleOffset);\r\n const ox3 = cellSize * Math.cos(Math.PI + angleOffset);\r\n const oy3 = cellSize * Math.sin(Math.PI + angleOffset);\r\n const ox4 = cellSize * Math.cos((4 * Math.PI) / 3 + angleOffset);\r\n const oy4 = cellSize * Math.sin((4 * Math.PI) / 3 + angleOffset);\r\n const ox5 = cellSize * Math.cos((5 * Math.PI) / 3 + angleOffset);\r\n const oy5 = cellSize * Math.sin((5 * Math.PI) / 3 + angleOffset);\r\n\r\n ctx.save();\r\n ctx.strokeStyle = strokeColor;\r\n ctx.lineWidth = strokeWidth;\r\n ctx.globalAlpha = opacity;\r\n ctx.beginPath();\r\n\r\n // Inline center iteration — zero allocations per hex\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * cellSize;\r\n const rowH = 1.5 * cellSize;\r\n\r\n const startRow = Math.floor((bounds.minY - cellSize) / rowH);\r\n const endRow = Math.ceil((bounds.maxY + cellSize) / rowH);\r\n const startCol = Math.floor((bounds.minX - hexW) / hexW);\r\n const endCol = Math.ceil((bounds.maxX + hexW) / hexW);\r\n\r\n for (let row = startRow; row <= endRow; row++) {\r\n const offX = row % 2 !== 0 ? hexW / 2 : 0;\r\n for (let col = startCol; col <= endCol; col++) {\r\n const cx = col * hexW + offX;\r\n const cy = row * rowH;\r\n ctx.moveTo(cx + ox0, cy + oy0);\r\n ctx.lineTo(cx + ox1, cy + oy1);\r\n ctx.lineTo(cx + ox2, cy + oy2);\r\n ctx.lineTo(cx + ox3, cy + oy3);\r\n ctx.lineTo(cx + ox4, cy + oy4);\r\n ctx.lineTo(cx + ox5, cy + oy5);\r\n ctx.closePath();\r\n }\r\n }\r\n } else {\r\n const hexH = Math.sqrt(3) * cellSize;\r\n const colW = 1.5 * cellSize;\r\n\r\n const startCol = Math.floor((bounds.minX - cellSize) / colW);\r\n const endCol = Math.ceil((bounds.maxX + cellSize) / colW);\r\n const startRow = Math.floor((bounds.minY - hexH) / hexH);\r\n const endRow = Math.ceil((bounds.maxY + hexH) / hexH);\r\n\r\n for (let col = startCol; col <= endCol; col++) {\r\n const offY = col % 2 !== 0 ? hexH / 2 : 0;\r\n for (let row = startRow; row <= endRow; row++) {\r\n const cx = col * colW;\r\n const cy = row * hexH + offY;\r\n ctx.moveTo(cx + ox0, cy + oy0);\r\n ctx.lineTo(cx + ox1, cy + oy1);\r\n ctx.lineTo(cx + ox2, cy + oy2);\r\n ctx.lineTo(cx + ox3, cy + oy3);\r\n ctx.lineTo(cx + ox4, cy + oy4);\r\n ctx.lineTo(cx + ox5, cy + oy5);\r\n ctx.closePath();\r\n }\r\n }\r\n }\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n}\r\n\r\nexport interface HexGridTile {\r\n canvas: HTMLCanvasElement | OffscreenCanvas;\r\n tileW: number;\r\n tileH: number;\r\n}\r\n\r\nexport function createHexGridTile(\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n strokeColor: string,\r\n strokeWidth: number,\r\n opacity: number,\r\n scale: number,\r\n): HexGridTile | null {\r\n let tileW: number;\r\n let tileH: number;\r\n if (orientation === 'pointy') {\r\n tileW = Math.sqrt(3) * cellSize;\r\n tileH = 3 * cellSize;\r\n } else {\r\n tileW = 3 * cellSize;\r\n tileH = Math.sqrt(3) * cellSize;\r\n }\r\n\r\n const pxW = Math.ceil(tileW * scale);\r\n const pxH = Math.ceil(tileH * scale);\r\n if (pxW <= 0 || pxH <= 0) return null;\r\n\r\n let canvas: HTMLCanvasElement | OffscreenCanvas;\r\n if (typeof OffscreenCanvas !== 'undefined') {\r\n canvas = new OffscreenCanvas(pxW, pxH);\r\n } else if (typeof document !== 'undefined') {\r\n const el = document.createElement('canvas');\r\n el.width = pxW;\r\n el.height = pxH;\r\n canvas = el;\r\n } else {\r\n return null;\r\n }\r\n\r\n const tc = canvas.getContext('2d') as CanvasRenderingContext2D | null;\r\n if (!tc) return null;\r\n\r\n tc.scale(scale, scale);\r\n tc.beginPath();\r\n tc.rect(0, 0, tileW, tileH);\r\n tc.clip();\r\n\r\n const angleOffset = orientation === 'pointy' ? -Math.PI / 2 : 0;\r\n const ox0 = cellSize * Math.cos(angleOffset);\r\n const oy0 = cellSize * Math.sin(angleOffset);\r\n const ox1 = cellSize * Math.cos(Math.PI / 3 + angleOffset);\r\n const oy1 = cellSize * Math.sin(Math.PI / 3 + angleOffset);\r\n const ox2 = cellSize * Math.cos((2 * Math.PI) / 3 + angleOffset);\r\n const oy2 = cellSize * Math.sin((2 * Math.PI) / 3 + angleOffset);\r\n const ox3 = cellSize * Math.cos(Math.PI + angleOffset);\r\n const oy3 = cellSize * Math.sin(Math.PI + angleOffset);\r\n const ox4 = cellSize * Math.cos((4 * Math.PI) / 3 + angleOffset);\r\n const oy4 = cellSize * Math.sin((4 * Math.PI) / 3 + angleOffset);\r\n const ox5 = cellSize * Math.cos((5 * Math.PI) / 3 + angleOffset);\r\n const oy5 = cellSize * Math.sin((5 * Math.PI) / 3 + angleOffset);\r\n\r\n tc.strokeStyle = strokeColor;\r\n tc.lineWidth = strokeWidth;\r\n tc.globalAlpha = opacity;\r\n tc.beginPath();\r\n\r\n if (orientation === 'pointy') {\r\n const hexW = tileW;\r\n const rowH = 1.5 * cellSize;\r\n for (let row = -1; row <= 3; row++) {\r\n const offX = row % 2 !== 0 ? hexW / 2 : 0;\r\n for (let col = -1; col <= 1; col++) {\r\n const cx = col * hexW + offX;\r\n const cy = row * rowH;\r\n tc.moveTo(cx + ox0, cy + oy0);\r\n tc.lineTo(cx + ox1, cy + oy1);\r\n tc.lineTo(cx + ox2, cy + oy2);\r\n tc.lineTo(cx + ox3, cy + oy3);\r\n tc.lineTo(cx + ox4, cy + oy4);\r\n tc.lineTo(cx + ox5, cy + oy5);\r\n tc.closePath();\r\n }\r\n }\r\n } else {\r\n const hexH = tileH;\r\n const colW = 1.5 * cellSize;\r\n for (let col = -1; col <= 3; col++) {\r\n const offY = col % 2 !== 0 ? hexH / 2 : 0;\r\n for (let row = -1; row <= 1; row++) {\r\n const cx = col * colW;\r\n const cy = row * hexH + offY;\r\n tc.moveTo(cx + ox0, cy + oy0);\r\n tc.lineTo(cx + ox1, cy + oy1);\r\n tc.lineTo(cx + ox2, cy + oy2);\r\n tc.lineTo(cx + ox3, cy + oy3);\r\n tc.lineTo(cx + ox4, cy + oy4);\r\n tc.lineTo(cx + ox5, cy + oy5);\r\n tc.closePath();\r\n }\r\n }\r\n }\r\n\r\n tc.stroke();\r\n return { canvas, tileW, tileH };\r\n}\r\n\r\nexport function renderHexGridTiled(\r\n ctx: CanvasRenderingContext2D,\r\n bounds: VisibleBounds,\r\n cellSize: number,\r\n tile: HexGridTile,\r\n): void {\r\n const { tileW, tileH } = tile;\r\n\r\n const startCol = Math.floor(bounds.minX / tileW) - 1;\r\n const endCol = Math.ceil(bounds.maxX / tileW) + 1;\r\n const startRow = Math.floor(bounds.minY / tileH) - 1;\r\n const endRow = Math.ceil(bounds.maxY / tileH) + 1;\r\n\r\n for (let row = startRow; row <= endRow; row++) {\r\n for (let col = startCol; col <= endCol; col++) {\r\n ctx.drawImage(tile.canvas as CanvasImageSource, col * tileW, row * tileH, tileW, tileH);\r\n }\r\n }\r\n}\r\n","import type { CanvasElement, GridElement } from './types';\r\nimport { getElementBounds } from './element-bounds';\r\nimport { withRotation } from './rotate-canvas';\r\nimport { renderStroke } from './renderers/stroke-renderer';\r\nimport { renderShape } from './renderers/shape-renderer';\r\nimport { renderArrow } from './renderers/arrow-renderer';\r\nimport { renderImage } from './renderers/image-renderer';\r\nimport { renderTemplate } from './renderers/template-renderer';\r\nimport type { ElementStore } from './element-store';\r\nimport {\r\n renderSquareGrid,\r\n renderHexGrid,\r\n createHexGridTile,\r\n renderHexGridTiled,\r\n} from './grid-renderer';\r\nimport type { HexGridTile } from './grid-renderer';\r\nimport type { HexOrientation } from './types';\r\nimport type { Camera } from '../canvas/camera';\r\n\r\nconst DOM_ELEMENT_TYPES = new Set(['note', 'html', 'text']);\r\n\r\nexport class ElementRenderer {\r\n private store: ElementStore | null = null;\r\n private imageCache = new Map<string, ImageBitmap | HTMLImageElement | 'failed'>();\r\n private onImageLoad: (() => void) | null = null;\r\n private onImageError: ((src: string, cause?: unknown) => void) | null = null;\r\n private camera: Camera | null = null;\r\n private canvasSize: { w: number; h: number } | null = null;\r\n private hexTileCache: HexGridTile | null = null;\r\n private hexTileCacheKey = '';\r\n private gridBoundsOverride: { minX: number; minY: number; maxX: number; maxY: number } | null =\r\n null;\r\n private labelEditingId: string | null = null;\r\n\r\n setStore(store: ElementStore): void {\r\n this.store = store;\r\n }\r\n\r\n setOnImageLoad(callback: () => void): void {\r\n this.onImageLoad = callback;\r\n }\r\n\r\n setOnImageError(callback: (src: string, cause?: unknown) => void): void {\r\n this.onImageError = callback;\r\n }\r\n\r\n setCamera(camera: Camera): void {\r\n this.camera = camera;\r\n }\r\n\r\n setCanvasSize(w: number, h: number): void {\r\n this.canvasSize = { w, h };\r\n }\r\n\r\n setGridBoundsOverride(\r\n bounds: { minX: number; minY: number; maxX: number; maxY: number } | null,\r\n ): void {\r\n this.gridBoundsOverride = bounds;\r\n }\r\n\r\n setLabelEditingId(id: string | null): void {\r\n this.labelEditingId = id;\r\n }\r\n\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 const b = getElementBounds(element);\r\n const c = b ? { x: b.x + b.w / 2, y: b.y + b.h / 2 } : element.position;\r\n withRotation(ctx, element, c, () => renderStroke(ctx, element));\r\n break;\r\n }\r\n case 'arrow':\r\n renderArrow(ctx, element, this.store, this.labelEditingId);\r\n break;\r\n case 'shape': {\r\n const b = getElementBounds(element);\r\n const c = b ? { x: b.x + b.w / 2, y: b.y + b.h / 2 } : element.position;\r\n withRotation(ctx, element, c, () => renderShape(ctx, element));\r\n break;\r\n }\r\n case 'image': {\r\n const b = getElementBounds(element);\r\n const c = b ? { x: b.x + b.w / 2, y: b.y + b.h / 2 } : element.position;\r\n withRotation(ctx, element, c, () =>\r\n renderImage(ctx, element, this.imageCache, this.onImageLoad, this.onImageError),\r\n );\r\n break;\r\n }\r\n case 'grid':\r\n this.renderGrid(ctx, element);\r\n break;\r\n case 'template':\r\n renderTemplate(ctx, element, this.store);\r\n break;\r\n }\r\n }\r\n\r\n private renderGrid(ctx: CanvasRenderingContext2D, grid: GridElement): void {\r\n const canvasSize = this.canvasSize;\r\n if (!canvasSize) return;\r\n\r\n const cam = this.camera;\r\n if (!cam) return;\r\n\r\n const bounds =\r\n this.gridBoundsOverride ??\r\n (() => {\r\n const topLeft = cam.screenToWorld({ x: 0, y: 0 });\r\n const bottomRight = cam.screenToWorld({ x: canvasSize.w, y: canvasSize.h });\r\n return {\r\n minX: topLeft.x,\r\n minY: topLeft.y,\r\n maxX: bottomRight.x,\r\n maxY: bottomRight.y,\r\n };\r\n })();\r\n\r\n if (grid.gridType === 'hex') {\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n const scale = cam.zoom * dpr;\r\n const tile = this.getHexTile(\r\n grid.cellSize,\r\n grid.hexOrientation,\r\n grid.strokeColor,\r\n grid.strokeWidth,\r\n grid.opacity,\r\n scale,\r\n );\r\n if (tile) {\r\n renderHexGridTiled(ctx, bounds, grid.cellSize, tile);\r\n } else {\r\n renderHexGrid(\r\n ctx,\r\n bounds,\r\n grid.cellSize,\r\n grid.hexOrientation,\r\n grid.strokeColor,\r\n grid.strokeWidth,\r\n grid.opacity,\r\n );\r\n }\r\n } else {\r\n renderSquareGrid(\r\n ctx,\r\n bounds,\r\n grid.cellSize,\r\n grid.strokeColor,\r\n grid.strokeWidth,\r\n grid.opacity,\r\n );\r\n }\r\n }\r\n\r\n private getHexTile(\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n strokeColor: string,\r\n strokeWidth: number,\r\n opacity: number,\r\n scale: number,\r\n ): HexGridTile | null {\r\n const key = `${cellSize}:${orientation}:${strokeColor}:${strokeWidth}:${opacity}:${scale}`;\r\n if (this.hexTileCacheKey === key && this.hexTileCache) {\r\n return this.hexTileCache;\r\n }\r\n const tile = createHexGridTile(cellSize, orientation, strokeColor, strokeWidth, opacity, scale);\r\n if (tile) {\r\n this.hexTileCache = tile;\r\n this.hexTileCacheKey = key;\r\n }\r\n return tile;\r\n }\r\n}\r\n","import type { Point, Size, StrokePoint } from '../core/types';\r\nimport type {\r\n Binding,\r\n StrokeElement,\r\n NoteElement,\r\n ArrowElement,\r\n ImageElement,\r\n HtmlElement,\r\n TextElement,\r\n ShapeElement,\r\n ShapeKind,\r\n GridElement,\r\n HexOrientation,\r\n TemplateElement,\r\n TemplateShape,\r\n} from './types';\r\nimport { createId } from './create-id';\r\nimport { getArrowControlPoint } from './arrow-geometry';\r\nimport { sanitizeNoteHtml } from './note-sanitizer';\r\n\r\nexport const DEFAULT_NOTE_FONT_SIZE = 18;\r\n\r\ninterface BaseDefaults {\r\n position?: Point;\r\n zIndex?: number;\r\n locked?: boolean;\r\n layerId?: string;\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 blendMode?: 'multiply';\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 textColor?: string;\r\n fontSize?: number;\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 fromBinding?: Binding;\r\n toBinding?: Binding;\r\n label?: string;\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 domId?: string;\r\n interactive?: boolean;\r\n}\r\n\r\ninterface TextInput extends BaseDefaults {\r\n position: Point;\r\n size?: Size;\r\n text?: string;\r\n fontSize?: number;\r\n color?: string;\r\n textAlign?: 'left' | 'center' | 'right';\r\n}\r\n\r\nexport function createStroke(input: StrokeInput): StrokeElement {\r\n const result: StrokeElement = {\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 layerId: input.layerId ?? '',\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 if (input.blendMode) result.blendMode = input.blendMode;\r\n return result;\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 layerId: input.layerId ?? '',\r\n size: input.size ?? { w: 200, h: 100 },\r\n text: sanitizeNoteHtml(input.text ?? ''),\r\n backgroundColor: input.backgroundColor ?? '#ffeb3b',\r\n textColor: input.textColor ?? '#000000',\r\n fontSize: input.fontSize ?? DEFAULT_NOTE_FONT_SIZE,\r\n };\r\n}\r\n\r\nexport function createArrow(input: ArrowInput): ArrowElement {\r\n const bend = input.bend ?? 0;\r\n const result: ArrowElement = {\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 layerId: input.layerId ?? '',\r\n from: input.from,\r\n to: input.to,\r\n bend,\r\n color: input.color ?? '#000000',\r\n width: input.width ?? 2,\r\n cachedControlPoint: getArrowControlPoint(input.from, input.to, bend),\r\n };\r\n if (input.fromBinding) result.fromBinding = input.fromBinding;\r\n if (input.toBinding) result.toBinding = input.toBinding;\r\n if (input.label !== undefined) result.label = input.label;\r\n return result;\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 layerId: input.layerId ?? '',\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 const el: HtmlElement = {\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 layerId: input.layerId ?? '',\r\n size: input.size,\r\n };\r\n if (input.domId) el.domId = input.domId;\r\n if (input.interactive) el.interactive = input.interactive;\r\n return el;\r\n}\r\n\r\ninterface ShapeInput extends BaseDefaults {\r\n position: Point;\r\n size: Size;\r\n shape?: ShapeKind;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n fillColor?: string;\r\n flip?: boolean;\r\n}\r\n\r\nexport function createShape(input: ShapeInput): ShapeElement {\r\n const result: ShapeElement = {\r\n id: createId('shape'),\r\n type: 'shape',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n shape: input.shape ?? 'rectangle',\r\n size: input.size,\r\n strokeColor: input.strokeColor ?? '#000000',\r\n strokeWidth: input.strokeWidth ?? 2,\r\n fillColor: input.fillColor ?? 'none',\r\n };\r\n if (input.flip) result.flip = input.flip;\r\n return result;\r\n}\r\n\r\ninterface GridInput extends BaseDefaults {\r\n gridType?: 'square' | 'hex';\r\n hexOrientation?: HexOrientation;\r\n cellSize?: number;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n}\r\n\r\nexport function createGrid(input: GridInput): GridElement {\r\n return {\r\n id: createId('grid'),\r\n type: 'grid',\r\n position: input.position ?? { x: 0, y: 0 },\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n gridType: input.gridType ?? 'square',\r\n hexOrientation: input.hexOrientation ?? 'pointy',\r\n cellSize: input.cellSize ?? 40,\r\n strokeColor: input.strokeColor ?? '#000000',\r\n strokeWidth: input.strokeWidth ?? 1,\r\n opacity: input.opacity ?? 1,\r\n };\r\n}\r\n\r\nexport function createText(input: TextInput): TextElement {\r\n return {\r\n id: createId('text'),\r\n type: 'text',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n size: input.size ?? { w: 200, h: 28 },\r\n text: input.text ?? '',\r\n fontSize: input.fontSize ?? 16,\r\n color: input.color ?? '#1a1a1a',\r\n textAlign: input.textAlign ?? 'left',\r\n };\r\n}\r\n\r\ninterface TemplateInput extends BaseDefaults {\r\n position: Point;\r\n templateShape: TemplateShape;\r\n radius: number;\r\n angle?: number;\r\n fillColor?: string;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n feetPerCell?: number;\r\n radiusFeet?: number;\r\n}\r\n\r\nexport function createTemplate(input: TemplateInput): TemplateElement {\r\n return {\r\n id: createId('template'),\r\n type: 'template',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n templateShape: input.templateShape,\r\n radius: input.radius,\r\n angle: input.angle ?? 0,\r\n fillColor: input.fillColor ?? 'rgba(255, 87, 34, 0.2)',\r\n strokeColor: input.strokeColor ?? '#FF5722',\r\n strokeWidth: input.strokeWidth ?? 2,\r\n opacity: input.opacity ?? 0.6,\r\n feetPerCell: input.feetPerCell,\r\n radiusFeet: input.radiusFeet,\r\n };\r\n}\r\n","export interface ActiveFormats {\r\n bold: boolean;\r\n italic: boolean;\r\n underline: boolean;\r\n strikethrough: boolean;\r\n}\r\n\r\nexport function toggleBold(): void {\r\n document.execCommand('bold');\r\n}\r\n\r\nexport function toggleItalic(): void {\r\n document.execCommand('italic');\r\n}\r\n\r\nexport function toggleUnderline(): void {\r\n document.execCommand('underline');\r\n}\r\n\r\nexport function toggleStrikethrough(): void {\r\n document.execCommand('strikeThrough');\r\n}\r\n\r\nexport function setFontSize(size: number): void {\r\n const sel = window.getSelection();\r\n if (!sel || sel.rangeCount === 0) return;\r\n\r\n const range = sel.getRangeAt(0);\r\n if (range.collapsed) return;\r\n\r\n const span = document.createElement('span');\r\n span.style.fontSize = `${size}px`;\r\n try {\r\n range.surroundContents(span);\r\n } catch {\r\n span.appendChild(range.extractContents());\r\n range.insertNode(span);\r\n }\r\n}\r\n\r\nexport function getActiveFormats(): ActiveFormats {\r\n const query = (cmd: string): boolean => {\r\n try {\r\n return document.queryCommandState(cmd);\r\n } catch {\r\n return false;\r\n }\r\n };\r\n\r\n return {\r\n bold: query('bold'),\r\n italic: query('italic'),\r\n underline: query('underline'),\r\n strikethrough: query('strikeThrough'),\r\n };\r\n}\r\n","import { DEFAULT_NOTE_FONT_SIZE } from './element-factory';\r\nimport { setFontSize, getActiveFormats } from './note-formatting';\r\n\r\nconst TOOLBAR_HEIGHT = 52;\r\nconst TOOLBAR_GAP = 4;\r\n\r\ninterface FormatButton {\r\n label: string;\r\n format: string;\r\n command: string;\r\n}\r\n\r\nconst FORMAT_BUTTONS: FormatButton[] = [\r\n { label: 'B', format: 'bold', command: 'bold' },\r\n { label: 'I', format: 'italic', command: 'italic' },\r\n { label: 'U', format: 'underline', command: 'underline' },\r\n { label: 'S', format: 'strikethrough', command: 'strikeThrough' },\r\n];\r\n\r\nexport interface FontSizePreset {\r\n label: string;\r\n size: number;\r\n}\r\n\r\nexport const DEFAULT_FONT_SIZE_PRESETS: FontSizePreset[] = [\r\n { label: 'Small', size: 14 },\r\n { label: 'Normal', size: 18 },\r\n { label: 'Large', size: 24 },\r\n { label: 'Heading', size: 32 },\r\n];\r\n\r\nexport class NoteToolbar {\r\n private el: HTMLDivElement | null = null;\r\n private anchor: HTMLElement | null = null;\r\n private selectionListener: (() => void) | null = null;\r\n private readonly fontSizePresets: FontSizePreset[];\r\n\r\n constructor(fontSizePresets?: FontSizePreset[]) {\r\n this.fontSizePresets = fontSizePresets ?? DEFAULT_FONT_SIZE_PRESETS;\r\n }\r\n\r\n show(anchor: HTMLElement): void {\r\n this.hide();\r\n this.anchor = anchor;\r\n this.el = this.createToolbarElement();\r\n document.body.appendChild(this.el);\r\n this.positionToolbar(anchor);\r\n this.selectionListener = () => this.updateActiveStates();\r\n document.addEventListener('selectionchange', this.selectionListener);\r\n }\r\n\r\n hide(): void {\r\n if (this.selectionListener) {\r\n document.removeEventListener('selectionchange', this.selectionListener);\r\n this.selectionListener = null;\r\n }\r\n if (this.el) {\r\n this.el.remove();\r\n this.el = null;\r\n }\r\n this.anchor = null;\r\n }\r\n\r\n getElement(): HTMLDivElement | null {\r\n return this.el;\r\n }\r\n\r\n updatePosition(anchor: HTMLElement): void {\r\n if (this.el) {\r\n this.positionToolbar(anchor);\r\n }\r\n }\r\n\r\n private createToolbarElement(): HTMLDivElement {\r\n const toolbar = document.createElement('div');\r\n toolbar.dataset['noteToolbar'] = '';\r\n Object.assign(toolbar.style, {\r\n position: 'fixed',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '2px',\r\n padding: '2px 4px',\r\n background: '#fff',\r\n border: '1px solid #ccc',\r\n borderRadius: '4px',\r\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\r\n zIndex: '10000',\r\n height: `${TOOLBAR_HEIGHT}px`,\r\n userSelect: 'none',\r\n });\r\n\r\n for (const btn of FORMAT_BUTTONS) {\r\n toolbar.appendChild(this.createFormatButton(btn));\r\n }\r\n\r\n toolbar.appendChild(this.createFontSizeSelect());\r\n\r\n return toolbar;\r\n }\r\n\r\n private createFormatButton(config: FormatButton): HTMLButtonElement {\r\n const btn = document.createElement('button');\r\n btn.dataset['format'] = config.format;\r\n btn.textContent = config.label;\r\n Object.assign(btn.style, {\r\n border: '1px solid transparent',\r\n borderRadius: '3px',\r\n background: 'none',\r\n cursor: 'pointer',\r\n padding: '2px 6px',\r\n fontSize: '13px',\r\n fontWeight: config.format === 'bold' ? 'bold' : 'normal',\r\n fontStyle: config.format === 'italic' ? 'italic' : 'normal',\r\n textDecoration:\r\n config.format === 'underline'\r\n ? 'underline'\r\n : config.format === 'strikethrough'\r\n ? 'line-through'\r\n : 'none',\r\n minWidth: '44px',\r\n height: '44px',\r\n lineHeight: '44px',\r\n });\r\n\r\n btn.addEventListener('pointerdown', (e) => {\r\n e.preventDefault();\r\n document.execCommand(config.command);\r\n this.updateActiveStates();\r\n });\r\n\r\n return btn;\r\n }\r\n\r\n private createFontSizeSelect(): HTMLSelectElement {\r\n const select = document.createElement('select');\r\n Object.assign(select.style, {\r\n border: '1px solid #ccc',\r\n borderRadius: '3px',\r\n background: '#fff',\r\n cursor: 'pointer',\r\n padding: '2px',\r\n fontSize: '12px',\r\n height: '44px',\r\n marginLeft: '4px',\r\n });\r\n\r\n for (const preset of this.fontSizePresets) {\r\n const option = document.createElement('option');\r\n option.value = String(preset.size);\r\n option.textContent = preset.label;\r\n select.appendChild(option);\r\n }\r\n\r\n select.value = String(DEFAULT_NOTE_FONT_SIZE);\r\n\r\n select.addEventListener('pointerdown', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n select.addEventListener('change', () => {\r\n this.applyFontSize(Number(select.value));\r\n this.updateActiveStates();\r\n this.anchor?.focus();\r\n });\r\n\r\n return select;\r\n }\r\n\r\n private applyFontSize(size: number): void {\r\n const sel = window.getSelection();\r\n const collapsed = !sel || sel.rangeCount === 0 || sel.getRangeAt(0).collapsed;\r\n if (collapsed && this.anchor) {\r\n const range = document.createRange();\r\n range.selectNodeContents(this.anchor);\r\n sel?.removeAllRanges();\r\n sel?.addRange(range);\r\n setFontSize(size);\r\n const after = window.getSelection();\r\n if (after) {\r\n const caret = document.createRange();\r\n caret.selectNodeContents(this.anchor);\r\n caret.collapse(false);\r\n after.removeAllRanges();\r\n after.addRange(caret);\r\n }\r\n return;\r\n }\r\n setFontSize(size);\r\n }\r\n\r\n private positionToolbar(anchor: HTMLElement): void {\r\n if (!this.el) return;\r\n\r\n const rect = anchor.getBoundingClientRect();\r\n const toolbarWidth = this.el.offsetWidth || 200;\r\n\r\n let top = rect.top - TOOLBAR_HEIGHT - TOOLBAR_GAP;\r\n if (top < 0) {\r\n top = rect.bottom + TOOLBAR_GAP;\r\n }\r\n\r\n let left = rect.left + (rect.width - toolbarWidth) / 2;\r\n left = Math.max(4, left);\r\n\r\n Object.assign(this.el.style, {\r\n top: `${top}px`,\r\n left: `${left}px`,\r\n });\r\n }\r\n\r\n private updateActiveStates(): void {\r\n if (!this.el) return;\r\n\r\n const active = getActiveFormats();\r\n for (const config of FORMAT_BUTTONS) {\r\n const btn = this.el.querySelector(`[data-format=\"${config.format}\"]`) as HTMLElement | null;\r\n if (!btn) continue;\r\n\r\n const isActive = active[config.format as keyof typeof active] ?? false;\r\n btn.style.background = isActive ? '#e0e0e0' : 'none';\r\n btn.style.borderColor = isActive ? '#bbb' : 'transparent';\r\n }\r\n }\r\n}\r\n","import type { ElementStore } from './element-store';\r\nimport { NoteToolbar } from './note-toolbar';\r\nimport type { FontSizePreset } from './note-toolbar';\r\nimport { sanitizeNoteHtml } from './note-sanitizer';\r\nimport { toggleBold, toggleItalic, toggleUnderline } from './note-formatting';\r\n\r\nconst FORMAT_SHORTCUTS: Record<string, () => void> = {\r\n b: toggleBold,\r\n i: toggleItalic,\r\n u: toggleUnderline,\r\n};\r\n\r\nexport interface NoteEditorOptions {\r\n fontSizePresets?: FontSizePreset[];\r\n toolbar?: boolean;\r\n placeholder?: string;\r\n}\r\n\r\nfunction ensureEditorStyles(): void {\r\n if (document.querySelector('style[data-fieldnotes-editor]')) return;\r\n const style = document.createElement('style');\r\n style.setAttribute('data-fieldnotes-editor', '');\r\n style.textContent = `[data-fn-placeholder][data-fn-empty='true']::before {\r\n content: attr(data-fn-placeholder);\r\n color: #9e9e9e;\r\n position: absolute;\r\n pointer-events: none;\r\n}`;\r\n document.head.appendChild(style);\r\n}\r\n\r\nfunction isNodeEmpty(node: HTMLElement): boolean {\r\n const text = node.textContent ?? '';\r\n return text.replace(/\\u00a0/g, ' ').trim().length === 0;\r\n}\r\n\r\nexport class NoteEditor {\r\n private editingId: string | null = null;\r\n private editingNode: HTMLDivElement | null = null;\r\n private blurHandler: ((e: FocusEvent) => void) | null = null;\r\n private keyHandler: ((e: KeyboardEvent) => void) | null = null;\r\n private pointerHandler: ((e: PointerEvent) => void) | null = null;\r\n private inputHandler: (() => void) | null = null;\r\n private pendingEditId: string | null = null;\r\n private onStopCallback: ((elementId: string) => void) | null = null;\r\n private beginHistory: (() => void) | null = null;\r\n private commitHistory: (() => void) | null = null;\r\n private toolbar: NoteToolbar | null;\r\n private readonly placeholder: string;\r\n\r\n constructor(options?: NoteEditorOptions) {\r\n this.toolbar = options?.toolbar === false ? null : new NoteToolbar(options?.fontSizePresets);\r\n this.placeholder = options?.placeholder ?? 'Type…';\r\n }\r\n\r\n get isEditing(): boolean {\r\n return this.editingId !== null;\r\n }\r\n\r\n get editingElementId(): string | null {\r\n return this.editingId;\r\n }\r\n\r\n setOnStop(callback: (elementId: string) => void): void {\r\n this.onStopCallback = callback;\r\n }\r\n\r\n setHistoryHooks(begin: () => void, commit: () => void): void {\r\n this.beginHistory = begin;\r\n this.commitHistory = commit;\r\n }\r\n\r\n startEditing(node: HTMLDivElement, elementId: string, store: ElementStore): void {\r\n if (this.editingId === elementId) return;\r\n\r\n if (this.editingId) {\r\n this.stopEditing(store);\r\n }\r\n\r\n this.pendingEditId = elementId;\r\n\r\n requestAnimationFrame(() => {\r\n if (this.pendingEditId !== elementId) return;\r\n this.pendingEditId = null;\r\n this.activateEditing(node, elementId, store);\r\n });\r\n }\r\n\r\n stopEditing(store: ElementStore): void {\r\n this.pendingEditId = null;\r\n\r\n if (!this.editingId || !this.editingNode) return;\r\n\r\n if (this.blurHandler) {\r\n this.editingNode.removeEventListener('blur', this.blurHandler);\r\n }\r\n if (this.keyHandler) {\r\n this.editingNode.removeEventListener('keydown', this.keyHandler);\r\n }\r\n if (this.pointerHandler) {\r\n this.editingNode.removeEventListener('pointerdown', this.pointerHandler);\r\n }\r\n if (this.inputHandler) {\r\n this.editingNode.removeEventListener('input', this.inputHandler);\r\n }\r\n this.editingNode.removeAttribute('data-fn-placeholder');\r\n this.editingNode.removeAttribute('data-fn-empty');\r\n\r\n const text = sanitizeNoteHtml(this.editingNode.innerHTML);\r\n const current = store.getById(this.editingId);\r\n const textChanged =\r\n !!current && (current.type === 'note' || current.type === 'text') && current.text !== text;\r\n\r\n this.editingNode.contentEditable = 'false';\r\n Object.assign(this.editingNode.style, {\r\n userSelect: 'none',\r\n cursor: 'default',\r\n });\r\n\r\n this.toolbar?.hide();\r\n\r\n // One history transaction spans the text write and the onStop height-fit/cleanup,\r\n // so a single note/text edit collapses to one undo step (both touch the same element).\r\n this.beginHistory?.();\r\n if (textChanged) {\r\n store.update(this.editingId, { text });\r\n }\r\n if (this.editingId && this.onStopCallback) {\r\n this.onStopCallback(this.editingId);\r\n }\r\n this.commitHistory?.();\r\n\r\n this.editingId = null;\r\n this.editingNode = null;\r\n this.blurHandler = null;\r\n this.keyHandler = null;\r\n this.pointerHandler = null;\r\n this.inputHandler = null;\r\n }\r\n\r\n destroy(store: ElementStore): void {\r\n this.pendingEditId = null;\r\n if (this.isEditing) {\r\n this.stopEditing(store);\r\n }\r\n }\r\n\r\n updateToolbarPosition(): void {\r\n if (this.editingNode) {\r\n this.toolbar?.updatePosition(this.editingNode);\r\n }\r\n }\r\n\r\n private activateEditing(node: HTMLDivElement, elementId: string, store: ElementStore): void {\r\n this.editingId = elementId;\r\n this.editingNode = node;\r\n\r\n node.contentEditable = 'true';\r\n Object.assign(node.style, {\r\n userSelect: 'text',\r\n cursor: 'text',\r\n outline: 'none',\r\n });\r\n node.focus();\r\n\r\n const selection = window.getSelection?.();\r\n if (selection) {\r\n const range = document.createRange();\r\n range.selectNodeContents(node);\r\n range.collapse(false);\r\n selection.removeAllRanges();\r\n selection.addRange(range);\r\n }\r\n\r\n ensureEditorStyles();\r\n node.setAttribute('data-fn-placeholder', this.placeholder);\r\n node.setAttribute('data-fn-empty', String(isNodeEmpty(node)));\r\n this.inputHandler = () => {\r\n node.setAttribute('data-fn-empty', String(isNodeEmpty(node)));\r\n };\r\n node.addEventListener('input', this.inputHandler);\r\n\r\n this.toolbar?.show(node);\r\n\r\n this.blurHandler = (e: FocusEvent) => {\r\n const related = e.relatedTarget as Node | null;\r\n if (related && this.toolbar?.getElement()?.contains(related)) return;\r\n this.stopEditing(store);\r\n };\r\n this.keyHandler = (e: KeyboardEvent) => {\r\n if ((e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) {\r\n const action = FORMAT_SHORTCUTS[e.key.toLowerCase()];\r\n if (action) {\r\n e.preventDefault();\r\n action();\r\n return;\r\n }\r\n }\r\n if (e.key === 'Escape') {\r\n node.blur();\r\n }\r\n e.stopPropagation();\r\n };\r\n this.pointerHandler = (e: PointerEvent) => {\r\n e.stopPropagation();\r\n };\r\n\r\n node.addEventListener('blur', this.blurHandler);\r\n node.addEventListener('keydown', this.keyHandler);\r\n node.addEventListener('pointerdown', this.pointerHandler);\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\n\r\nexport interface ContextMenuItem {\r\n label: string;\r\n action: string;\r\n disabled?: boolean;\r\n}\r\n\r\nexport interface ContextMenuOptions {\r\n onCommand: (action: string) => void;\r\n onClose: () => void;\r\n}\r\n\r\nexport class ContextMenu {\r\n private el: HTMLDivElement | null = null;\r\n private outsideListener: ((e: PointerEvent) => void) | null = null;\r\n private keyListener: ((e: KeyboardEvent) => void) | null = null;\r\n\r\n constructor(private readonly options: ContextMenuOptions) {}\r\n\r\n isOpen(): boolean {\r\n return this.el !== null;\r\n }\r\n\r\n open(items: ContextMenuItem[], screenPos: Point): void {\r\n this.close();\r\n const el = document.createElement('div');\r\n el.className = 'fieldnotes-context-menu';\r\n Object.assign(el.style, {\r\n position: 'fixed',\r\n left: `${screenPos.x}px`,\r\n top: `${screenPos.y}px`,\r\n zIndex: '10000',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n });\r\n for (const item of items) {\r\n const btn = document.createElement('button');\r\n btn.type = 'button';\r\n btn.className =\r\n 'fieldnotes-context-menu-item' +\r\n (item.disabled ? ' fieldnotes-context-menu-item--disabled' : '');\r\n btn.textContent = item.label;\r\n if (item.disabled) {\r\n btn.disabled = true;\r\n } else {\r\n btn.addEventListener('click', () => {\r\n this.options.onCommand(item.action);\r\n this.close();\r\n });\r\n }\r\n el.appendChild(btn);\r\n }\r\n document.body.appendChild(el);\r\n this.el = el;\r\n this.clampToViewport(el, screenPos);\r\n\r\n this.keyListener = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') this.close();\r\n };\r\n document.addEventListener('keydown', this.keyListener);\r\n\r\n this.outsideListener = (e: PointerEvent) => {\r\n if (this.el && !this.el.contains(e.target as Node)) this.close();\r\n };\r\n // Defer attaching so the opening gesture's own pointerdown doesn't immediately close it.\r\n setTimeout(() => {\r\n if (this.outsideListener) document.addEventListener('pointerdown', this.outsideListener);\r\n }, 0);\r\n }\r\n\r\n close(): void {\r\n if (this.keyListener) {\r\n document.removeEventListener('keydown', this.keyListener);\r\n this.keyListener = null;\r\n }\r\n if (this.outsideListener) {\r\n document.removeEventListener('pointerdown', this.outsideListener);\r\n this.outsideListener = null;\r\n }\r\n if (this.el) {\r\n this.el.remove();\r\n this.el = null;\r\n this.options.onClose();\r\n }\r\n }\r\n\r\n dispose(): void {\r\n this.close();\r\n }\r\n\r\n private clampToViewport(el: HTMLElement, screenPos: Point): void {\r\n const rect = el.getBoundingClientRect();\r\n if (rect.width > 0 && screenPos.x + rect.width > window.innerWidth) {\r\n el.style.left = `${Math.max(0, screenPos.x - rect.width)}px`;\r\n }\r\n if (rect.height > 0 && screenPos.y + rect.height > window.innerHeight) {\r\n el.style.top = `${Math.max(0, screenPos.y - rect.height)}px`;\r\n }\r\n }\r\n}\r\n","export function 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 overscrollBehavior: 'none',\r\n userSelect: 'none',\r\n webkitUserSelect: 'none',\r\n });\r\n return el;\r\n}\r\n\r\nexport function 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\nexport function 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","import type { ArrowElement } from './types';\r\nimport type { ElementStore } from './element-store';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport { getArrowMidpoint } from './arrow-geometry';\r\n\r\nexport interface ArrowLabelEditStart {\r\n arrow: ArrowElement;\r\n layer: HTMLElement;\r\n store: ElementStore;\r\n recorder: HistoryRecorder;\r\n onDone: () => void;\r\n}\r\n\r\nexport class ArrowLabelEditor {\r\n private input: HTMLInputElement | null = null;\r\n private done = false;\r\n\r\n get isEditing(): boolean {\r\n return this.input !== null;\r\n }\r\n\r\n startEditing(start: ArrowLabelEditStart): void {\r\n if (this.input) this.cleanup();\r\n const { arrow, layer, store, recorder, onDone } = start;\r\n const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);\r\n\r\n const input = document.createElement('input');\r\n input.type = 'text';\r\n input.value = arrow.label ?? '';\r\n Object.assign(input.style, {\r\n position: 'absolute',\r\n left: `${mid.x}px`,\r\n top: `${mid.y}px`,\r\n transform: 'translate(-50%, -50%)',\r\n // domLayer is pointer-events:none; the input must opt back in to receive taps/clicks.\r\n pointerEvents: 'auto',\r\n font: '14px system-ui, sans-serif',\r\n padding: '2px 6px',\r\n border: '1px solid #2196F3',\r\n borderRadius: '4px',\r\n background: '#ffffff',\r\n color: '#1a1a1a',\r\n outline: 'none',\r\n minWidth: '40px',\r\n });\r\n\r\n this.done = false;\r\n\r\n const commit = (): void => {\r\n if (this.done) return;\r\n this.done = true;\r\n const next = input.value.trim() || undefined;\r\n if (next !== arrow.label) {\r\n recorder.begin();\r\n store.update(arrow.id, { label: next });\r\n recorder.commit();\r\n }\r\n this.cleanup();\r\n onDone();\r\n };\r\n\r\n const cancel = (): void => {\r\n if (this.done) return;\r\n this.done = true;\r\n this.cleanup();\r\n onDone();\r\n };\r\n\r\n input.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter') {\r\n e.preventDefault();\r\n commit();\r\n } else if (e.key === 'Escape') {\r\n e.preventDefault();\r\n cancel();\r\n }\r\n e.stopPropagation();\r\n });\r\n input.addEventListener('blur', commit);\r\n\r\n layer.appendChild(input);\r\n this.input = input;\r\n input.focus();\r\n input.select();\r\n }\r\n\r\n /** Abort any in-progress edit without committing (e.g. on viewport teardown). */\r\n cancel(): void {\r\n this.done = true;\r\n this.cleanup();\r\n }\r\n\r\n private cleanup(): void {\r\n if (this.input) {\r\n this.input.remove();\r\n this.input = null;\r\n }\r\n }\r\n}\r\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';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { Command } from './types';\r\n\r\nexport class AddElementCommand implements Command {\r\n private readonly element: CanvasElement;\r\n\r\n constructor(element: CanvasElement) {\r\n this.element = { ...element };\r\n }\r\n\r\n execute(store: ElementStore): void {\r\n store.add(this.element);\r\n }\r\n\r\n undo(store: ElementStore): void {\r\n store.remove(this.element.id);\r\n }\r\n}\r\n\r\nexport class RemoveElementCommand implements Command {\r\n private readonly element: CanvasElement;\r\n\r\n constructor(element: CanvasElement) {\r\n this.element = { ...element };\r\n }\r\n\r\n execute(store: ElementStore): void {\r\n store.remove(this.element.id);\r\n }\r\n\r\n undo(store: ElementStore): void {\r\n store.add(this.element);\r\n }\r\n}\r\n\r\nexport class UpdateElementCommand implements Command {\r\n constructor(\r\n private readonly id: string,\r\n private readonly previous: CanvasElement,\r\n private readonly current: CanvasElement,\r\n ) {}\r\n\r\n execute(store: ElementStore): void {\r\n store.update(this.id, diffPatch(this.previous, this.current));\r\n }\r\n\r\n undo(store: ElementStore): void {\r\n store.update(this.id, diffPatch(this.current, this.previous));\r\n }\r\n}\r\n\r\n// Patch turning `from` into `to`, explicitly setting keys that exist on `from`\r\n// but not `to` to `undefined` so a merge-based `update` clears them.\r\nfunction diffPatch(from: CanvasElement, to: CanvasElement): Partial<CanvasElement> {\r\n const patch: Record<string, unknown> = { ...to };\r\n for (const key of Object.keys(from)) {\r\n if (!(key in to)) patch[key] = undefined;\r\n }\r\n return patch as Partial<CanvasElement>;\r\n}\r\n\r\nexport class BatchCommand implements Command {\r\n readonly commands: readonly Command[];\r\n\r\n constructor(commands: Command[]) {\r\n this.commands = [...commands];\r\n }\r\n\r\n execute(store: ElementStore): void {\r\n for (const cmd of this.commands) {\r\n cmd.execute(store);\r\n }\r\n }\r\n\r\n undo(store: ElementStore): void {\r\n for (let i = this.commands.length - 1; i >= 0; i--) {\r\n this.commands[i]?.undo(store);\r\n }\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { Command } from './types';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport type { Layer } from '../layers/types';\r\n\r\nexport class CreateLayerCommand implements Command {\r\n constructor(\r\n private readonly manager: LayerManager,\r\n private readonly layer: Layer,\r\n ) {}\r\n\r\n execute(_store: ElementStore): void {\r\n this.manager.addLayerDirect(this.layer);\r\n }\r\n\r\n undo(_store: ElementStore): void {\r\n this.manager.removeLayerDirect(this.layer.id);\r\n }\r\n}\r\n\r\nexport class RemoveLayerCommand implements Command {\r\n constructor(\r\n private readonly manager: LayerManager,\r\n private readonly layer: Layer,\r\n ) {}\r\n\r\n execute(_store: ElementStore): void {\r\n this.manager.removeLayerDirect(this.layer.id);\r\n }\r\n\r\n undo(_store: ElementStore): void {\r\n this.manager.addLayerDirect(this.layer);\r\n }\r\n}\r\n\r\nexport class UpdateLayerCommand implements Command {\r\n constructor(\r\n private readonly manager: LayerManager,\r\n private readonly layerId: string,\r\n private readonly previous: Layer,\r\n private readonly current: Layer,\r\n ) {}\r\n\r\n execute(_store: ElementStore): void {\r\n this.manager.updateLayerDirect(this.layerId, { ...this.current });\r\n }\r\n\r\n undo(_store: ElementStore): void {\r\n this.manager.updateLayerDirect(this.layerId, { ...this.previous });\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport type { Command } from './types';\r\nimport type { HistoryStack } from './history-stack';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport type { Layer } from '../layers/types';\r\nimport {\r\n AddElementCommand,\r\n RemoveElementCommand,\r\n UpdateElementCommand,\r\n BatchCommand,\r\n} from './commands';\r\nimport { CreateLayerCommand, RemoveLayerCommand, UpdateLayerCommand } from './layer-commands';\r\n\r\nexport class HistoryRecorder {\r\n private recording = true;\r\n private transaction: Command[] | null = null;\r\n private generation = 0;\r\n private updateSnapshots = new Map<string, CanvasElement>();\r\n private unsubscribers: (() => void)[];\r\n\r\n constructor(\r\n private readonly store: ElementStore,\r\n private readonly stack: HistoryStack,\r\n private readonly layerManager?: LayerManager,\r\n ) {\r\n this.unsubscribers = [\r\n store.on('add', (el) => this.onAdd(el)),\r\n store.on('remove', (el) => this.onRemove(el)),\r\n store.on('update', ({ previous, current }) => this.onUpdate(previous, current)),\r\n ];\r\n\r\n if (layerManager) {\r\n this.unsubscribers.push(\r\n layerManager.on('create', (layer) => this.onLayerCreate(layer)),\r\n layerManager.on('remove', (layer) => this.onLayerRemove(layer)),\r\n layerManager.on('update', ({ previous, current }) => this.onLayerUpdate(previous, current)),\r\n );\r\n }\r\n }\r\n\r\n pause(): void {\r\n this.recording = false;\r\n }\r\n\r\n resume(): void {\r\n this.recording = true;\r\n }\r\n\r\n begin(): void {\r\n if (this.transaction !== null) {\r\n this.commit();\r\n }\r\n this.transaction = [];\r\n this.updateSnapshots.clear();\r\n this.generation += 1;\r\n }\r\n\r\n get currentTransactionId(): number | null {\r\n return this.transaction !== null ? this.generation : null;\r\n }\r\n\r\n commit(): void {\r\n if (!this.transaction) return;\r\n\r\n const finalCommands = this.flushUpdateSnapshots();\r\n const all = [...this.transaction, ...finalCommands];\r\n this.transaction = null;\r\n this.updateSnapshots.clear();\r\n\r\n if (all.length === 0) return;\r\n const first = all[0];\r\n this.stack.push(all.length === 1 && first ? first : new BatchCommand(all));\r\n }\r\n\r\n rollback(): void {\r\n this.transaction = null;\r\n this.updateSnapshots.clear();\r\n }\r\n\r\n destroy(): void {\r\n this.unsubscribers.forEach((fn) => fn());\r\n }\r\n\r\n private record(command: Command): void {\r\n if (this.transaction) {\r\n this.transaction.push(command);\r\n } else {\r\n this.stack.push(command);\r\n }\r\n }\r\n\r\n private onAdd(element: CanvasElement): void {\r\n if (!this.recording) return;\r\n this.record(new AddElementCommand(element));\r\n }\r\n\r\n private onRemove(element: CanvasElement): void {\r\n if (!this.recording) return;\r\n\r\n if (this.transaction && this.updateSnapshots.has(element.id)) {\r\n this.updateSnapshots.delete(element.id);\r\n }\r\n\r\n this.record(new RemoveElementCommand(element));\r\n }\r\n\r\n private onUpdate(previous: CanvasElement, current: CanvasElement): void {\r\n if (!this.recording) return;\r\n\r\n if (this.transaction) {\r\n if (!this.updateSnapshots.has(current.id)) {\r\n this.updateSnapshots.set(current.id, { ...previous });\r\n }\r\n } else {\r\n this.stack.push(new UpdateElementCommand(current.id, previous, current));\r\n }\r\n }\r\n\r\n private onLayerCreate(layer: Layer): void {\r\n if (!this.recording) return;\r\n if (!this.layerManager) return;\r\n this.record(new CreateLayerCommand(this.layerManager, layer));\r\n }\r\n\r\n private onLayerRemove(layer: Layer): void {\r\n if (!this.recording) return;\r\n if (!this.layerManager) return;\r\n this.record(new RemoveLayerCommand(this.layerManager, layer));\r\n }\r\n\r\n private onLayerUpdate(previous: Layer, current: Layer): void {\r\n if (!this.recording) return;\r\n if (!this.layerManager) return;\r\n this.record(new UpdateLayerCommand(this.layerManager, current.id, previous, current));\r\n }\r\n\r\n private flushUpdateSnapshots(): Command[] {\r\n const commands: Command[] = [];\r\n for (const [id, previous] of this.updateSnapshots) {\r\n const current = this.store.getById(id);\r\n if (current) {\r\n commands.push(new UpdateElementCommand(id, previous, current));\r\n }\r\n }\r\n return commands;\r\n }\r\n}\r\n","import type { NoteElement } from '../elements/types';\r\nimport { DEFAULT_NOTE_FONT_SIZE } from '../elements/element-factory';\r\nimport { parseStyledRuns } from '../elements/note-sanitizer';\r\nimport type { StyledRun } from '../elements/note-sanitizer';\r\n\r\nexport function renderNoteOnCanvas(ctx: CanvasRenderingContext2D, note: NoteElement): void {\r\n const { x, y } = note.position;\r\n const { w, h } = note.size;\r\n const r = 4;\r\n const pad = 8;\r\n const baseFontSize = note.fontSize ?? DEFAULT_NOTE_FONT_SIZE;\r\n\r\n ctx.save();\r\n ctx.fillStyle = note.backgroundColor;\r\n ctx.beginPath();\r\n ctx.moveTo(x + r, y);\r\n ctx.lineTo(x + w - r, y);\r\n ctx.arcTo(x + w, y, x + w, y + r, r);\r\n ctx.lineTo(x + w, y + h - r);\r\n ctx.arcTo(x + w, y + h, x + w - r, y + h, r);\r\n ctx.lineTo(x + r, y + h);\r\n ctx.arcTo(x, y + h, x, y + h - r, r);\r\n ctx.lineTo(x, y + r);\r\n ctx.arcTo(x, y, x + r, y, r);\r\n ctx.closePath();\r\n ctx.fill();\r\n\r\n if (note.text) {\r\n ctx.fillStyle = note.textColor;\r\n const runs = parseStyledRuns(note.text, baseFontSize);\r\n renderStyledRuns(ctx, runs, x + pad, y + pad, w - pad * 2);\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nfunction buildFontString(run: StyledRun): string {\r\n const style = run.italic ? 'italic' : 'normal';\r\n const weight = run.bold ? 'bold' : 'normal';\r\n return `${style} ${weight} ${run.fontSize}px system-ui, sans-serif`;\r\n}\r\n\r\nfunction renderStyledRuns(\r\n ctx: CanvasRenderingContext2D,\r\n runs: StyledRun[],\r\n startX: number,\r\n startY: number,\r\n maxWidth: number,\r\n): void {\r\n ctx.textBaseline = 'top';\r\n let cursorX = startX;\r\n let cursorY = startY;\r\n let lineHeight = 0;\r\n\r\n for (const run of runs) {\r\n ctx.font = buildFontString(run);\r\n const runLineHeight = run.fontSize * 1.3;\r\n lineHeight = Math.max(lineHeight, runLineHeight);\r\n\r\n const words = run.text.split(/(\\n| )/);\r\n for (const word of words) {\r\n if (word === '\\n') {\r\n cursorX = startX;\r\n cursorY += lineHeight;\r\n lineHeight = runLineHeight;\r\n continue;\r\n }\r\n if (word === ' ') {\r\n const spaceWidth = ctx.measureText(' ').width;\r\n if (cursorX + spaceWidth > startX + maxWidth && cursorX > startX) {\r\n cursorX = startX;\r\n cursorY += lineHeight;\r\n lineHeight = runLineHeight;\r\n } else {\r\n cursorX += spaceWidth;\r\n }\r\n continue;\r\n }\r\n if (!word) continue;\r\n\r\n const metrics = ctx.measureText(word);\r\n if (cursorX + metrics.width > startX + maxWidth && cursorX > startX) {\r\n cursorX = startX;\r\n cursorY += lineHeight;\r\n lineHeight = runLineHeight;\r\n }\r\n\r\n ctx.fillText(word, cursorX, cursorY);\r\n\r\n if (run.underline) {\r\n const underY = cursorY + run.fontSize + 1;\r\n ctx.fillRect(cursorX, underY, metrics.width, 1);\r\n }\r\n\r\n if (run.strikethrough) {\r\n const strikeY = cursorY + run.fontSize * 0.55;\r\n ctx.fillRect(cursorX, strikeY, metrics.width, 1);\r\n }\r\n\r\n cursorX += metrics.width;\r\n }\r\n }\r\n}\r\n","import type { CanvasElement, TextElement, GridElement } from '../elements/types';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport { ElementRenderer } from '../elements/element-renderer';\r\nimport { getArrowBounds } from '../elements/arrow-geometry';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { renderSquareGrid, renderHexGrid } from '../elements/grid-renderer';\r\nimport { withRotation } from '../elements/rotate-canvas';\r\nimport { rotatedAABB } from '../core/geometry';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport { renderNoteOnCanvas } from './note-canvas-renderer';\r\n\r\nexport interface ExportImageOptions {\r\n scale?: number;\r\n padding?: number;\r\n background?: string;\r\n filter?: (element: CanvasElement) => boolean;\r\n}\r\n\r\ninterface Rect {\r\n x: number;\r\n y: number;\r\n w: number;\r\n h: number;\r\n}\r\n\r\nconst center = (b: Rect): { x: number; y: number } => ({ x: b.x + b.w / 2, y: b.y + b.h / 2 });\r\n\r\nfunction getStrokeBounds(el: CanvasElement): Rect | null {\r\n if (el.type !== 'stroke') return null;\r\n if (el.points.length === 0) return null;\r\n\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n\r\n for (const p of el.points) {\r\n const px = el.position.x + p.x;\r\n const py = el.position.y + p.y;\r\n minX = Math.min(minX, px);\r\n minY = Math.min(minY, py);\r\n maxX = Math.max(maxX, px);\r\n maxY = Math.max(maxY, py);\r\n }\r\n\r\n const pad = el.width / 2;\r\n return {\r\n x: minX - pad,\r\n y: minY - pad,\r\n w: maxX - minX + el.width,\r\n h: maxY - minY + el.width,\r\n };\r\n}\r\n\r\nfunction getElementRect(el: CanvasElement): Rect | null {\r\n switch (el.type) {\r\n case 'stroke': {\r\n const r = getStrokeBounds(el);\r\n return r ? rotatedAABB(r, el.rotation ?? 0) : r;\r\n }\r\n case 'arrow': {\r\n const b = getArrowBounds(el.from, el.to, el.bend);\r\n const pad = el.width / 2 + 14;\r\n return { x: b.x - pad, y: b.y - pad, w: b.w + pad * 2, h: b.h + pad * 2 };\r\n }\r\n case 'grid':\r\n return null;\r\n case 'template': {\r\n const bounds = getElementBounds(el);\r\n if (!bounds) return null;\r\n return bounds;\r\n }\r\n case 'note':\r\n case 'image':\r\n case 'html':\r\n case 'text':\r\n case 'shape':\r\n if ('size' in el) {\r\n return rotatedAABB(\r\n { x: el.position.x, y: el.position.y, w: el.size.w, h: el.size.h },\r\n el.rotation ?? 0,\r\n );\r\n }\r\n return null;\r\n default:\r\n return null;\r\n }\r\n}\r\n\r\nfunction computeBounds(\r\n elements: CanvasElement[],\r\n padding: number,\r\n): { x: number; y: number; w: number; h: number } | null {\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n let found = false;\r\n\r\n for (const el of elements) {\r\n const rect = getElementRect(el);\r\n if (!rect) continue;\r\n found = true;\r\n minX = Math.min(minX, rect.x);\r\n minY = Math.min(minY, rect.y);\r\n maxX = Math.max(maxX, rect.x + rect.w);\r\n maxY = Math.max(maxY, rect.y + rect.h);\r\n }\r\n\r\n if (!found) return null;\r\n\r\n return {\r\n x: minX - padding,\r\n y: minY - padding,\r\n w: maxX - minX + padding * 2,\r\n h: maxY - minY + padding * 2,\r\n };\r\n}\r\n\r\nfunction renderTextOnCanvas(ctx: CanvasRenderingContext2D, text: TextElement): void {\r\n if (!text.text) return;\r\n\r\n ctx.save();\r\n ctx.fillStyle = text.color;\r\n ctx.font = `${text.fontSize}px system-ui, sans-serif`;\r\n ctx.textBaseline = 'top';\r\n ctx.textAlign = text.textAlign;\r\n\r\n const pad = 2;\r\n let textX = text.position.x + pad;\r\n if (text.textAlign === 'center') {\r\n textX = text.position.x + text.size.w / 2;\r\n } else if (text.textAlign === 'right') {\r\n textX = text.position.x + text.size.w - pad;\r\n }\r\n\r\n const lineHeight = text.fontSize * 1.4;\r\n const lines = text.text.split('\\n');\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i];\r\n if (line !== undefined) {\r\n ctx.fillText(line, textX, text.position.y + pad + i * lineHeight);\r\n }\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nfunction renderGridForBounds(\r\n ctx: CanvasRenderingContext2D,\r\n grid: GridElement,\r\n bounds: { x: number; y: number; w: number; h: number },\r\n): void {\r\n const visibleBounds = {\r\n minX: bounds.x,\r\n minY: bounds.y,\r\n maxX: bounds.x + bounds.w,\r\n maxY: bounds.y + bounds.h,\r\n };\r\n\r\n if (grid.gridType === 'hex') {\r\n renderHexGrid(\r\n ctx,\r\n visibleBounds,\r\n grid.cellSize,\r\n grid.hexOrientation,\r\n grid.strokeColor,\r\n grid.strokeWidth,\r\n grid.opacity,\r\n );\r\n } else {\r\n renderSquareGrid(\r\n ctx,\r\n visibleBounds,\r\n grid.cellSize,\r\n grid.strokeColor,\r\n grid.strokeWidth,\r\n grid.opacity,\r\n );\r\n }\r\n}\r\n\r\nfunction loadImages(elements: CanvasElement[]): Promise<Map<string, HTMLImageElement>> {\r\n const imageElements = elements.filter(\r\n (el): el is CanvasElement & { src: string } => el.type === 'image' && 'src' in el,\r\n );\r\n\r\n const cache = new Map<string, HTMLImageElement>();\r\n if (imageElements.length === 0) return Promise.resolve(cache);\r\n\r\n return new Promise((resolve) => {\r\n let remaining = imageElements.length;\r\n const done = () => {\r\n remaining--;\r\n if (remaining <= 0) resolve(cache);\r\n };\r\n\r\n for (const el of imageElements) {\r\n const img = new Image();\r\n img.crossOrigin = 'anonymous';\r\n img.onload = () => {\r\n cache.set(el.id, img);\r\n done();\r\n };\r\n img.onerror = done;\r\n const sep = el.src.includes('?') ? '&' : '?';\r\n img.src = `${el.src}${sep}_cors=1`;\r\n }\r\n });\r\n}\r\n\r\nexport async function exportImage(\r\n store: ElementStore,\r\n options: ExportImageOptions = {},\r\n layerManager?: LayerManager,\r\n): Promise<Blob | null> {\r\n const scale = options.scale ?? 2;\r\n const padding = options.padding ?? 0;\r\n const background = options.background ?? '#ffffff';\r\n const filter = options.filter;\r\n\r\n const allElements = store.getAll();\r\n let visibleElements = layerManager\r\n ? allElements.filter((el) => layerManager.isLayerVisible(el.layerId))\r\n : allElements;\r\n\r\n if (filter) {\r\n visibleElements = visibleElements.filter(filter);\r\n }\r\n\r\n const bounds = computeBounds(visibleElements, padding);\r\n if (!bounds) return null;\r\n\r\n const imageCache = await loadImages(visibleElements);\r\n\r\n const canvas = document.createElement('canvas');\r\n canvas.width = Math.ceil(bounds.w * scale);\r\n canvas.height = Math.ceil(bounds.h * scale);\r\n\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return null;\r\n\r\n ctx.scale(scale, scale);\r\n ctx.translate(-bounds.x, -bounds.y);\r\n\r\n ctx.fillStyle = background;\r\n ctx.fillRect(bounds.x, bounds.y, bounds.w, bounds.h);\r\n\r\n const renderer = new ElementRenderer();\r\n renderer.setStore(store);\r\n\r\n const grids: GridElement[] = [];\r\n\r\n for (const el of visibleElements) {\r\n if (el.type === 'grid') {\r\n grids.push(el);\r\n continue;\r\n }\r\n\r\n if (el.type === 'note') {\r\n const b = getElementBounds(el);\r\n withRotation(ctx, el, b ? center(b) : el.position, () => renderNoteOnCanvas(ctx, el));\r\n continue;\r\n }\r\n\r\n if (el.type === 'text') {\r\n const b = getElementBounds(el);\r\n withRotation(ctx, el, b ? center(b) : el.position, () => renderTextOnCanvas(ctx, el));\r\n continue;\r\n }\r\n\r\n if (el.type === 'html') {\r\n continue;\r\n }\r\n\r\n if (el.type === 'image') {\r\n const img = imageCache.get(el.id);\r\n if (img) {\r\n const b = getElementBounds(el);\r\n withRotation(ctx, el, b ? center(b) : el.position, () =>\r\n ctx.drawImage(img, el.position.x, el.position.y, el.size.w, el.size.h),\r\n );\r\n }\r\n continue;\r\n }\r\n\r\n renderer.renderCanvasElement(ctx, el);\r\n }\r\n\r\n for (const grid of grids) {\r\n renderGridForBounds(ctx, grid, bounds);\r\n }\r\n\r\n return new Promise((resolve) => {\r\n canvas.toBlob((blob) => resolve(blob), 'image/png');\r\n });\r\n}\r\n\r\nexport { computeBounds, getElementRect };\r\n","import { EventBus } from '../core/event-bus';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { Layer } from './types';\r\nimport { createId } from '../elements/create-id';\r\n\r\ninterface LayerManagerEvents {\r\n change: null;\r\n create: Layer;\r\n remove: Layer;\r\n update: { previous: Layer; current: Layer };\r\n}\r\n\r\nexport class LayerManager {\r\n private layers = new Map<string, Layer>();\r\n private _activeLayerId: string;\r\n private bus = new EventBus<LayerManagerEvents>();\r\n\r\n constructor(private readonly store: ElementStore) {\r\n const defaultLayer: Layer = {\r\n id: createId('layer'),\r\n name: 'Layer 1',\r\n visible: true,\r\n locked: false,\r\n order: 0,\r\n opacity: 1.0,\r\n };\r\n this.layers.set(defaultLayer.id, defaultLayer);\r\n this._activeLayerId = defaultLayer.id;\r\n this.syncLayerOrder();\r\n }\r\n\r\n get activeLayer(): Layer {\r\n const layer = this.layers.get(this._activeLayerId);\r\n if (!layer) throw new Error('Active layer not found');\r\n return { ...layer };\r\n }\r\n\r\n get activeLayerId(): string {\r\n return this._activeLayerId;\r\n }\r\n\r\n getLayers(): Layer[] {\r\n return [...this.layers.values()].sort((a, b) => a.order - b.order).map((l) => ({ ...l }));\r\n }\r\n\r\n getLayer(id: string): Layer | undefined {\r\n const layer = this.layers.get(id);\r\n return layer ? { ...layer } : undefined;\r\n }\r\n\r\n isLayerVisible(id: string): boolean {\r\n return this.layers.get(id)?.visible ?? true;\r\n }\r\n\r\n isLayerLocked(id: string): boolean {\r\n return this.layers.get(id)?.locked ?? false;\r\n }\r\n\r\n createLayer(name?: string): Layer {\r\n const maxOrder = Math.max(...[...this.layers.values()].map((l) => l.order), -1);\r\n const autoName = name ?? `Layer ${this.layers.size + 1}`;\r\n const layer: Layer = {\r\n id: createId('layer'),\r\n name: autoName,\r\n visible: true,\r\n locked: false,\r\n order: maxOrder + 1,\r\n opacity: 1.0,\r\n };\r\n this.addLayerDirect(layer);\r\n return { ...layer };\r\n }\r\n\r\n removeLayer(id: string): void {\r\n if (this.layers.size <= 1) {\r\n throw new Error('Cannot remove the last layer');\r\n }\r\n if (this._activeLayerId === id) {\r\n const remaining = [...this.layers.values()]\r\n .filter((l) => l.id !== id)\r\n .sort((a, b) => b.order - a.order);\r\n const fallback = remaining[0];\r\n if (fallback) this._activeLayerId = fallback.id;\r\n }\r\n const elements = this.store.getAll().filter((el) => el.layerId === id);\r\n for (const el of elements) {\r\n this.store.update(el.id, { layerId: this._activeLayerId });\r\n }\r\n this.removeLayerDirect(id);\r\n }\r\n\r\n renameLayer(id: string, name: string): void {\r\n this.updateLayerDirect(id, { name });\r\n }\r\n\r\n reorderLayer(id: string, newOrder: number): void {\r\n if (!this.layers.has(id)) return;\r\n this.updateLayerDirect(id, { order: newOrder });\r\n }\r\n\r\n setLayerVisible(id: string, visible: boolean): boolean {\r\n if (!visible && id === this._activeLayerId) {\r\n const fallback = this.findFallbackLayer(id);\r\n if (!fallback) return false;\r\n this._activeLayerId = fallback.id;\r\n }\r\n this.updateLayerDirect(id, { visible });\r\n return true;\r\n }\r\n\r\n setLayerLocked(id: string, locked: boolean): boolean {\r\n if (locked && id === this._activeLayerId) {\r\n const fallback = this.findFallbackLayer(id);\r\n if (!fallback) return false;\r\n this._activeLayerId = fallback.id;\r\n }\r\n this.updateLayerDirect(id, { locked });\r\n return true;\r\n }\r\n\r\n setLayerOpacity(id: string, opacity: number): void {\r\n if (!this.layers.has(id)) return;\r\n this.updateLayerDirect(id, { opacity: Math.max(0, Math.min(1, opacity)) });\r\n }\r\n\r\n setActiveLayer(id: string): void {\r\n if (!this.layers.has(id)) return;\r\n this._activeLayerId = id;\r\n this.bus.emit('change', null);\r\n }\r\n\r\n moveElementToLayer(elementId: string, layerId: string): void {\r\n if (!this.layers.has(layerId)) return;\r\n this.store.update(elementId, { layerId });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n snapshot(): Layer[] {\r\n return this.getLayers();\r\n }\r\n\r\n loadSnapshot(layers: Layer[]): void {\r\n this.layers.clear();\r\n for (const layer of layers) {\r\n this.layers.set(layer.id, { ...layer });\r\n }\r\n const first = this.getLayers()[0];\r\n if (first) this._activeLayerId = first.id;\r\n this.syncLayerOrder();\r\n this.bus.emit('change', null);\r\n }\r\n\r\n on<K extends keyof LayerManagerEvents>(\r\n event: K,\r\n callback: (data: LayerManagerEvents[K]) => void,\r\n ): () => void {\r\n return this.bus.on(event, callback);\r\n }\r\n\r\n addLayerDirect(layer: Layer): void {\r\n this.layers.set(layer.id, { ...layer });\r\n this.syncLayerOrder();\r\n this.bus.emit('create', { ...layer });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n removeLayerDirect(id: string): void {\r\n const layer = this.layers.get(id);\r\n this.layers.delete(id);\r\n this.syncLayerOrder();\r\n if (layer) this.bus.emit('remove', { ...layer });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n updateLayerDirect(id: string, props: Omit<Partial<Layer>, 'id'>): void {\r\n const layer = this.layers.get(id);\r\n if (!layer) return;\r\n const previous = { ...layer };\r\n Object.assign(layer, props);\r\n if ('order' in props) this.syncLayerOrder();\r\n this.bus.emit('update', { previous, current: { ...layer } });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n private syncLayerOrder(): void {\r\n const order = new Map<string, number>();\r\n for (const layer of this.layers.values()) {\r\n order.set(layer.id, layer.order);\r\n }\r\n this.store.setLayerOrder(order);\r\n }\r\n\r\n private findFallbackLayer(excludeId: string): Layer | undefined {\r\n return [...this.layers.values()]\r\n .filter((l) => l.id !== excludeId && l.visible && !l.locked)\r\n .sort((a, b) => b.order - a.order)[0];\r\n }\r\n}\r\n","export interface InteractModeDeps {\r\n getNode: (id: string) => HTMLDivElement | undefined;\r\n}\r\n\r\nexport class InteractMode {\r\n private interactingElementId: string | null = null;\r\n private readonly getNode: (id: string) => HTMLDivElement | undefined;\r\n\r\n constructor(deps: InteractModeDeps) {\r\n this.getNode = deps.getNode;\r\n }\r\n\r\n startInteracting(id: string): void {\r\n this.stopInteracting();\r\n const node = this.getNode(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.onNodePointerDown);\r\n\r\n window.addEventListener('keydown', this.onKeyDown);\r\n window.addEventListener('pointerdown', this.onPointerDown);\r\n }\r\n\r\n stopInteracting(): void {\r\n if (!this.interactingElementId) return;\r\n\r\n const node = this.getNode(this.interactingElementId);\r\n if (node) {\r\n node.style.pointerEvents = 'none';\r\n node.removeEventListener('pointerdown', this.onNodePointerDown);\r\n }\r\n\r\n this.interactingElementId = null;\r\n window.removeEventListener('keydown', this.onKeyDown);\r\n window.removeEventListener('pointerdown', this.onPointerDown);\r\n }\r\n\r\n isInteracting(): boolean {\r\n return this.interactingElementId !== null;\r\n }\r\n\r\n destroy(): void {\r\n this.stopInteracting();\r\n }\r\n\r\n private onNodePointerDown = (e: PointerEvent): void => {\r\n e.stopPropagation();\r\n };\r\n\r\n private onKeyDown = (e: KeyboardEvent): void => {\r\n if (e.key === 'Escape') {\r\n this.stopInteracting();\r\n }\r\n };\r\n\r\n private onPointerDown = (e: PointerEvent): void => {\r\n if (!this.interactingElementId) return;\r\n const target = e.target;\r\n if (!(target instanceof Element)) {\r\n this.stopInteracting();\r\n return;\r\n }\r\n\r\n const node = this.getNode(this.interactingElementId);\r\n if (node && !node.contains(target)) {\r\n this.stopInteracting();\r\n }\r\n };\r\n}\r\n","export interface DoubleTapDetectorOptions {\r\n timeout?: number;\r\n maxDistance?: number;\r\n}\r\n\r\nconst DEFAULT_TIMEOUT = 300;\r\nconst DEFAULT_MAX_DISTANCE = 20;\r\n\r\nexport class DoubleTapDetector {\r\n private readonly timeout: number;\r\n private readonly maxDistance: number;\r\n private lastTapTime = 0;\r\n private lastTapX = 0;\r\n private lastTapY = 0;\r\n private hasPendingTap = false;\r\n\r\n constructor(options?: DoubleTapDetectorOptions) {\r\n this.timeout = options?.timeout ?? DEFAULT_TIMEOUT;\r\n this.maxDistance = options?.maxDistance ?? DEFAULT_MAX_DISTANCE;\r\n }\r\n\r\n feed(e: PointerEvent): boolean {\r\n const now = Date.now();\r\n const x = e.clientX;\r\n const y = e.clientY;\r\n\r\n if (this.hasPendingTap) {\r\n const elapsed = now - this.lastTapTime;\r\n const dx = x - this.lastTapX;\r\n const dy = y - this.lastTapY;\r\n const dist = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (elapsed <= this.timeout && dist <= this.maxDistance) {\r\n this.reset();\r\n return true;\r\n }\r\n }\r\n\r\n this.lastTapTime = now;\r\n this.lastTapX = x;\r\n this.lastTapY = y;\r\n this.hasPendingTap = true;\r\n return false;\r\n }\r\n\r\n reset(): void {\r\n this.hasPendingTap = false;\r\n this.lastTapTime = 0;\r\n this.lastTapX = 0;\r\n this.lastTapY = 0;\r\n }\r\n}\r\n","import type { CanvasElement } from '../elements/types';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport { DEFAULT_NOTE_FONT_SIZE } from '../elements/element-factory';\r\nimport { DoubleTapDetector } from './double-tap-detector';\r\nexport interface DomNodeManagerDeps {\r\n domLayer: HTMLDivElement;\r\n onEditRequest: (id: string) => void;\r\n isEditingElement: (id: string) => boolean;\r\n getVersion?: (id: string) => number;\r\n}\r\n\r\nexport class DomNodeManager {\r\n private domNodes = new Map<string, HTMLDivElement>();\r\n private htmlContent = new Map<string, HTMLElement>();\r\n private readonly domLayer: HTMLDivElement;\r\n private readonly onEditRequest: (id: string) => void;\r\n private readonly isEditingElement: (id: string) => boolean;\r\n private readonly getVersion: ((id: string) => number) | null;\r\n private lastSyncedVersion = new Map<string, number>();\r\n private lastSyncedZIndex = new Map<string, number>();\r\n\r\n constructor(deps: DomNodeManagerDeps) {\r\n this.domLayer = deps.domLayer;\r\n this.onEditRequest = deps.onEditRequest;\r\n this.isEditingElement = deps.isEditingElement;\r\n this.getVersion = deps.getVersion ?? null;\r\n }\r\n\r\n getNode(id: string): HTMLDivElement | undefined {\r\n return this.domNodes.get(id);\r\n }\r\n\r\n storeHtmlContent(elementId: string, dom: HTMLElement): void {\r\n this.htmlContent.set(elementId, dom);\r\n }\r\n\r\n hasContent(elementId: string): boolean {\r\n return this.htmlContent.has(elementId);\r\n }\r\n\r\n resetHtmlContent(elementId: string): void {\r\n this.htmlContent.delete(elementId);\r\n this.lastSyncedVersion.delete(elementId);\r\n this.lastSyncedZIndex.delete(elementId);\r\n const node = this.domNodes.get(elementId);\r\n if (!node) return;\r\n while (node.firstChild) {\r\n node.removeChild(node.firstChild);\r\n }\r\n delete node.dataset['initialized'];\r\n }\r\n\r\n syncDomNode(element: CanvasElement, zIndex = 0): 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 } else if (this.getVersion) {\r\n const currentVersion = this.getVersion(element.id);\r\n const lastVersion = this.lastSyncedVersion.get(element.id);\r\n const lastZ = this.lastSyncedZIndex.get(element.id);\r\n if (lastVersion === currentVersion && lastZ === zIndex) {\r\n return;\r\n }\r\n }\r\n\r\n if (this.getVersion) {\r\n this.lastSyncedVersion.set(element.id, this.getVersion(element.id));\r\n this.lastSyncedZIndex.set(element.id, zIndex);\r\n }\r\n\r\n const size = 'size' in element ? element.size : null;\r\n Object.assign(node.style, {\r\n display: 'block',\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 zIndex: String(zIndex),\r\n transform: element.rotation ? `rotate(${element.rotation}rad)` : '',\r\n transformOrigin: '50% 50%',\r\n });\r\n\r\n this.renderDomContent(node, element);\r\n }\r\n\r\n hideDomNode(id: string): void {\r\n const node = this.domNodes.get(id);\r\n if (node) node.style.display = 'none';\r\n }\r\n\r\n removeDomNode(id: string): void {\r\n this.htmlContent.delete(id);\r\n this.lastSyncedVersion.delete(id);\r\n this.lastSyncedZIndex.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 }\r\n\r\n clearDomNodes(): void {\r\n this.domNodes.forEach((node) => node.remove());\r\n this.domNodes.clear();\r\n this.htmlContent.clear();\r\n this.lastSyncedVersion.clear();\r\n this.lastSyncedZIndex.clear();\r\n }\r\n\r\n reattachHtmlContent(store: ElementStore): void {\r\n for (const el of store.getElementsByType('html')) {\r\n if (el.domId) {\r\n const dom = document.getElementById(el.domId);\r\n if (dom) {\r\n this.htmlContent.set(el.id, dom);\r\n }\r\n }\r\n }\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 color: element.textColor,\r\n padding: '8px',\r\n borderRadius: '4px',\r\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\r\n fontSize: `${element.fontSize ?? DEFAULT_NOTE_FONT_SIZE}px`,\r\n overflow: 'hidden',\r\n cursor: 'default',\r\n userSelect: 'none',\r\n wordWrap: 'break-word',\r\n });\r\n node.innerHTML = element.text || '';\r\n\r\n // One-time per node: this pointerup/double-tap listener is attached once (guarded by\r\n // `initialized`) for note/text nodes and is GC'd with the node — no teardown.\r\n // `resetHtmlContent()` (the only path clearing `initialized`) is html-only, and the html\r\n // init branch attaches no listener, so re-init is safe. INVARIANT: never call\r\n // resetHtmlContent on a note/text node, and if you add a listener to the html init branch,\r\n // add matching teardown in resetHtmlContent — else a second listener would stack.\r\n const detector = new DoubleTapDetector();\r\n node.addEventListener('pointerup', (e) => {\r\n if (detector.feed(e)) {\r\n e.stopPropagation();\r\n const id = node.dataset['elementId'];\r\n if (id) this.onEditRequest(id);\r\n }\r\n });\r\n }\r\n\r\n if (!this.isEditingElement(element.id)) {\r\n const text = element.text || '';\r\n if (node.innerHTML !== text) {\r\n node.innerHTML = text;\r\n }\r\n node.style.backgroundColor = element.backgroundColor;\r\n node.style.color = element.textColor;\r\n node.style.fontSize = `${element.fontSize ?? DEFAULT_NOTE_FONT_SIZE}px`;\r\n }\r\n }\r\n\r\n if (element.type === 'html') {\r\n if (!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: element.interactive ? 'auto' : 'none',\r\n });\r\n node.appendChild(content);\r\n }\r\n } else {\r\n node.style.pointerEvents = element.interactive ? 'auto' : 'none';\r\n }\r\n }\r\n\r\n if (element.type === 'text') {\r\n if (!node.dataset['initialized']) {\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n padding: '2px',\r\n fontSize: `${element.fontSize}px`,\r\n color: element.color,\r\n textAlign: element.textAlign,\r\n background: 'none',\r\n border: 'none',\r\n boxShadow: 'none',\r\n overflow: 'visible',\r\n cursor: 'default',\r\n userSelect: 'none',\r\n wordWrap: 'break-word',\r\n whiteSpace: 'pre-wrap',\r\n lineHeight: '1.4',\r\n });\r\n node.textContent = element.text || '';\r\n\r\n // One-time per node; see the note branch above for the one-listener-per-node invariant.\r\n const detector = new DoubleTapDetector();\r\n node.addEventListener('pointerup', (e) => {\r\n if (detector.feed(e)) {\r\n e.stopPropagation();\r\n const id = node.dataset['elementId'];\r\n if (id) this.onEditRequest(id);\r\n }\r\n });\r\n }\r\n\r\n if (!this.isEditingElement(element.id)) {\r\n if (node.textContent !== element.text) {\r\n node.textContent = element.text || '';\r\n }\r\n Object.assign(node.style, {\r\n fontSize: `${element.fontSize}px`,\r\n color: element.color,\r\n textAlign: element.textAlign,\r\n });\r\n }\r\n }\r\n }\r\n}\r\n","const SAMPLE_SIZE = 60;\r\n\r\nexport interface RenderStatsSnapshot {\r\n fps: number;\r\n avgFrameMs: number;\r\n p95FrameMs: number;\r\n lastFrameMs: number;\r\n lastGridMs: number;\r\n layersMs: number;\r\n backgroundMs: number;\r\n compositeMs: number;\r\n overlayMs: number;\r\n frameCount: number;\r\n}\r\n\r\ninterface FrameBreakdown {\r\n gridMs?: number;\r\n layersMs?: number;\r\n backgroundMs?: number;\r\n compositeMs?: number;\r\n overlayMs?: number;\r\n}\r\n\r\nexport class RenderStats {\r\n private frameTimes: number[] = [];\r\n private frameCount = 0;\r\n private _lastGridMs = 0;\r\n private _lastLayersMs = 0;\r\n private _lastBackgroundMs = 0;\r\n private _lastCompositeMs = 0;\r\n private _lastOverlayMs = 0;\r\n\r\n recordFrame(durationMs: number, breakdown?: FrameBreakdown): void {\r\n this.frameCount++;\r\n this.frameTimes.push(durationMs);\r\n if (this.frameTimes.length > SAMPLE_SIZE) {\r\n this.frameTimes.shift();\r\n }\r\n if (breakdown !== undefined) {\r\n if (breakdown.gridMs !== undefined) this._lastGridMs = breakdown.gridMs;\r\n if (breakdown.layersMs !== undefined) this._lastLayersMs = breakdown.layersMs;\r\n if (breakdown.backgroundMs !== undefined) this._lastBackgroundMs = breakdown.backgroundMs;\r\n if (breakdown.compositeMs !== undefined) this._lastCompositeMs = breakdown.compositeMs;\r\n if (breakdown.overlayMs !== undefined) this._lastOverlayMs = breakdown.overlayMs;\r\n }\r\n }\r\n\r\n getSnapshot(): RenderStatsSnapshot {\r\n const times = this.frameTimes;\r\n if (times.length === 0) {\r\n return {\r\n fps: 0,\r\n avgFrameMs: 0,\r\n p95FrameMs: 0,\r\n lastFrameMs: 0,\r\n lastGridMs: 0,\r\n layersMs: 0,\r\n backgroundMs: 0,\r\n compositeMs: 0,\r\n overlayMs: 0,\r\n frameCount: 0,\r\n };\r\n }\r\n\r\n const avg = times.reduce((a, b) => a + b, 0) / times.length;\r\n const sorted = [...times].sort((a, b) => a - b);\r\n const p95Index = Math.min(Math.floor(sorted.length * 0.95), sorted.length - 1);\r\n const lastFrame = times[times.length - 1] ?? 0;\r\n\r\n return {\r\n fps: avg > 0 ? Math.round(1000 / avg) : 0,\r\n avgFrameMs: Math.round(avg * 100) / 100,\r\n p95FrameMs: Math.round((sorted[p95Index] ?? 0) * 100) / 100,\r\n lastFrameMs: Math.round(lastFrame * 100) / 100,\r\n lastGridMs: Math.round(this._lastGridMs * 100) / 100,\r\n layersMs: Math.round(this._lastLayersMs * 100) / 100,\r\n backgroundMs: Math.round(this._lastBackgroundMs * 100) / 100,\r\n compositeMs: Math.round(this._lastCompositeMs * 100) / 100,\r\n overlayMs: Math.round(this._lastOverlayMs * 100) / 100,\r\n frameCount: this.frameCount,\r\n };\r\n }\r\n\r\n reset(): void {\r\n this.frameTimes = [];\r\n this.frameCount = 0;\r\n }\r\n}\r\n","import type { Camera } from './camera';\r\nimport type { Background } from './background';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { ElementRenderer } from '../elements/element-renderer';\r\nimport type { ToolManager } from '../tools/tool-manager';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport type { DomNodeManager } from './dom-node-manager';\r\nimport type { LayerCache } from './layer-cache';\r\nimport type { MarginViewport } from './margin-viewport';\r\nimport type { Bounds } from '../core/types';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { getElementBounds, boundsIntersect } from '../elements/element-bounds';\r\nimport { RenderStats } from './render-stats';\r\nimport type { RenderStatsSnapshot } from './render-stats';\r\n\r\nexport interface RenderLoopDeps {\r\n canvasEl: HTMLCanvasElement;\r\n camera: Camera;\r\n background: Background;\r\n store: ElementStore;\r\n renderer: ElementRenderer;\r\n toolManager: ToolManager;\r\n layerManager: LayerManager;\r\n domNodeManager: DomNodeManager;\r\n layerCache: LayerCache;\r\n marginViewport: MarginViewport;\r\n}\r\n\r\nexport class RenderLoop {\r\n private needsRender = false;\r\n private animFrameId = 0;\r\n private readonly canvasEl: HTMLCanvasElement;\r\n private readonly camera: Camera;\r\n private readonly background: Background;\r\n private readonly store: ElementStore;\r\n private readonly renderer: ElementRenderer;\r\n private readonly toolManager: ToolManager;\r\n private readonly layerManager: LayerManager;\r\n private readonly domNodeManager: DomNodeManager;\r\n private readonly layerCache: LayerCache;\r\n private readonly marginViewport: MarginViewport;\r\n private activeDrawingLayerId: string | null = null;\r\n private gridCacheDirty = true; // set on recenter/viewport-change; consumed by the grid block\r\n private readonly stats = new RenderStats();\r\n private layerGroups = new Map<string, CanvasElement[]>();\r\n private gridCacheCanvas: HTMLCanvasElement | null = null;\r\n private gridCacheCtx: CanvasRenderingContext2D | null = null;\r\n private lastGridRef: unknown = null;\r\n\r\n constructor(deps: RenderLoopDeps) {\r\n this.canvasEl = deps.canvasEl;\r\n this.camera = deps.camera;\r\n this.background = deps.background;\r\n this.store = deps.store;\r\n this.renderer = deps.renderer;\r\n this.toolManager = deps.toolManager;\r\n this.layerManager = deps.layerManager;\r\n this.domNodeManager = deps.domNodeManager;\r\n this.layerCache = deps.layerCache;\r\n this.marginViewport = deps.marginViewport;\r\n }\r\n\r\n requestRender(): void {\r\n this.needsRender = true;\r\n }\r\n\r\n flush(): void {\r\n if (this.needsRender) {\r\n this.render();\r\n this.needsRender = false;\r\n }\r\n }\r\n\r\n start(): 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 stop(): void {\r\n cancelAnimationFrame(this.animFrameId);\r\n }\r\n\r\n setCanvasSize(width: number, height: number): void {\r\n this.canvasEl.width = width;\r\n this.canvasEl.height = height;\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n this.marginViewport.setViewport(width / dpr, height / dpr, dpr);\r\n this.layerCache.resize();\r\n }\r\n\r\n setActiveDrawingLayer(layerId: string | null): void {\r\n this.activeDrawingLayerId = layerId;\r\n }\r\n\r\n markLayerDirty(layerId: string): void {\r\n this.layerCache.markDirty(layerId);\r\n }\r\n\r\n markAllLayersDirty(): void {\r\n this.layerCache.markAllDirty();\r\n }\r\n\r\n getStats(): RenderStatsSnapshot {\r\n return this.stats.getSnapshot();\r\n }\r\n\r\n private compositeLayerCache(ctx: CanvasRenderingContext2D, layerId: string): void {\r\n const cached = this.layerCache.getCanvas(layerId);\r\n const offset = this.marginViewport.compositeOffset(\r\n this.camera.position.x,\r\n this.camera.position.y,\r\n );\r\n ctx.save();\r\n ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n ctx.drawImage(cached as CanvasImageSource, offset.x, offset.y);\r\n ctx.restore();\r\n }\r\n\r\n private ensureGridCache(): void {\r\n const w = this.marginViewport.physicalWidth();\r\n const h = this.marginViewport.physicalHeight();\r\n if (\r\n this.gridCacheCanvas !== null &&\r\n this.gridCacheCanvas.width === w &&\r\n this.gridCacheCanvas.height === h\r\n ) {\r\n return;\r\n }\r\n\r\n if (typeof OffscreenCanvas !== 'undefined') {\r\n this.gridCacheCanvas = new OffscreenCanvas(w, h) as unknown as HTMLCanvasElement;\r\n } else if (typeof document !== 'undefined') {\r\n const el = document.createElement('canvas');\r\n el.width = w;\r\n el.height = h;\r\n this.gridCacheCanvas = el;\r\n } else {\r\n this.gridCacheCanvas = null;\r\n this.gridCacheCtx = null;\r\n return;\r\n }\r\n\r\n this.gridCacheCtx = this.gridCacheCanvas.getContext('2d') as CanvasRenderingContext2D | null;\r\n }\r\n\r\n private render(): void {\r\n const t0 = performance.now();\r\n const ctx = this.canvasEl.getContext('2d');\r\n if (!ctx) return;\r\n\r\n let layersMs = 0;\r\n let compositeMs = 0;\r\n let gridMs = 0;\r\n\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n const cssWidth = this.canvasEl.clientWidth;\r\n const cssHeight = this.canvasEl.clientHeight;\r\n\r\n // idempotent; catches resizes that bypass setCanvasSize\r\n this.marginViewport.setViewport(cssWidth, cssHeight, dpr);\r\n\r\n const currentZoom = this.camera.zoom;\r\n const currentCamX = this.camera.position.x;\r\n const currentCamY = this.camera.position.y;\r\n if (this.marginViewport.needsRecenter(currentCamX, currentCamY, currentZoom)) {\r\n this.marginViewport.recenter(currentCamX, currentCamY, currentZoom);\r\n this.layerCache.markAllDirty();\r\n this.gridCacheDirty = true;\r\n }\r\n\r\n ctx.save();\r\n ctx.scale(dpr, dpr);\r\n\r\n this.renderer.setCanvasSize(cssWidth, cssHeight);\r\n const hasGridElement = this.store.getElementsByType('grid').length > 0;\r\n const bgT0 = performance.now();\r\n if (hasGridElement) {\r\n ctx.save();\r\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n ctx.clearRect(0, 0, cssWidth, cssHeight);\r\n ctx.restore();\r\n } else {\r\n this.background.render(ctx, this.camera);\r\n }\r\n const backgroundMs = performance.now() - bgT0;\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 const cullBounds = this.marginViewport.cachedWorldBounds();\r\n const cullPad = Math.max(cullBounds.w, cullBounds.h) * 0.05;\r\n const cullingRect: Bounds = {\r\n x: cullBounds.x - cullPad,\r\n y: cullBounds.y - cullPad,\r\n w: cullBounds.w + cullPad * 2,\r\n h: cullBounds.h + cullPad * 2,\r\n };\r\n\r\n const allElements = this.store.getAll();\r\n this.layerGroups.clear();\r\n const gridElements: CanvasElement[] = [];\r\n let domZIndex = 0;\r\n\r\n for (const element of allElements) {\r\n if (!this.layerManager.isLayerVisible(element.layerId)) {\r\n if (this.renderer.isDomElement(element)) {\r\n this.domNodeManager.hideDomNode(element.id);\r\n }\r\n continue;\r\n }\r\n\r\n if (this.renderer.isDomElement(element)) {\r\n const elBounds = getElementBounds(element);\r\n if (elBounds && !boundsIntersect(elBounds, cullingRect)) {\r\n this.domNodeManager.hideDomNode(element.id);\r\n } else {\r\n this.domNodeManager.syncDomNode(element, domZIndex++);\r\n }\r\n continue;\r\n }\r\n\r\n // Grids are viewport-filling; handled via anchored cache below\r\n if (element.type === 'grid') {\r\n gridElements.push(element);\r\n continue;\r\n }\r\n\r\n let group = this.layerGroups.get(element.layerId);\r\n if (!group) {\r\n group = [];\r\n this.layerGroups.set(element.layerId, group);\r\n }\r\n group.push(element);\r\n }\r\n\r\n for (const [layerId, elements] of this.layerGroups) {\r\n const isActiveDrawingLayer = layerId === this.activeDrawingLayerId;\r\n\r\n if (!this.layerCache.isDirty(layerId)) {\r\n const compT0 = performance.now();\r\n this.compositeLayerCache(ctx, layerId);\r\n compositeMs += performance.now() - compT0;\r\n continue;\r\n }\r\n\r\n if (isActiveDrawingLayer) {\r\n const compT0 = performance.now();\r\n this.compositeLayerCache(ctx, layerId);\r\n compositeMs += performance.now() - compT0;\r\n continue;\r\n }\r\n\r\n const offCtx = this.layerCache.getContext(layerId);\r\n if (offCtx) {\r\n const layerT0 = performance.now();\r\n const offCanvas = this.layerCache.getCanvas(layerId);\r\n offCtx.clearRect(0, 0, offCanvas.width, offCanvas.height);\r\n offCtx.save();\r\n this.marginViewport.applyRenderTransform(offCtx);\r\n for (const element of elements) {\r\n const elBounds = getElementBounds(element);\r\n if (elBounds && !boundsIntersect(elBounds, cullingRect)) continue;\r\n this.renderer.renderCanvasElement(offCtx as CanvasRenderingContext2D, element);\r\n }\r\n offCtx.restore();\r\n this.layerCache.markClean(layerId);\r\n layersMs += performance.now() - layerT0;\r\n\r\n const compT0 = performance.now();\r\n this.compositeLayerCache(ctx, layerId);\r\n compositeMs += performance.now() - compT0;\r\n }\r\n }\r\n\r\n // Render grids on top of layer elements\r\n if (gridElements.length > 0) {\r\n const gridT0 = performance.now();\r\n const gridRef = gridElements[0];\r\n const gridDirty = this.gridCacheDirty || gridRef !== this.lastGridRef;\r\n\r\n if (gridDirty) {\r\n this.ensureGridCache();\r\n if (this.gridCacheCtx && this.gridCacheCanvas) {\r\n const cb = this.marginViewport.cachedWorldBounds();\r\n this.renderer.setGridBoundsOverride({\r\n minX: cb.x,\r\n minY: cb.y,\r\n maxX: cb.x + cb.w,\r\n maxY: cb.y + cb.h,\r\n });\r\n const gc = this.gridCacheCtx;\r\n gc.clearRect(0, 0, this.gridCacheCanvas.width, this.gridCacheCanvas.height);\r\n gc.save();\r\n this.marginViewport.applyRenderTransform(gc);\r\n try {\r\n for (const grid of gridElements) {\r\n this.renderer.renderCanvasElement(gc as CanvasRenderingContext2D, grid);\r\n }\r\n } finally {\r\n gc.restore();\r\n this.renderer.setGridBoundsOverride(null);\r\n }\r\n }\r\n this.gridCacheDirty = false;\r\n this.lastGridRef = gridRef;\r\n }\r\n\r\n if (this.gridCacheCanvas) {\r\n const offset = this.marginViewport.compositeOffset(\r\n this.camera.position.x,\r\n this.camera.position.y,\r\n );\r\n ctx.save();\r\n ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n ctx.drawImage(this.gridCacheCanvas as CanvasImageSource, offset.x, offset.y);\r\n ctx.restore();\r\n } else {\r\n for (const grid of gridElements) {\r\n this.renderer.renderCanvasElement(ctx, grid);\r\n }\r\n }\r\n gridMs = performance.now() - gridT0;\r\n }\r\n\r\n const overlayT0 = performance.now();\r\n const activeTool = this.toolManager.activeTool;\r\n if (activeTool?.renderOverlay) {\r\n activeTool.renderOverlay(ctx);\r\n }\r\n const overlayMs = performance.now() - overlayT0;\r\n\r\n ctx.restore();\r\n ctx.restore();\r\n\r\n this.stats.recordFrame(performance.now() - t0, {\r\n gridMs,\r\n layersMs,\r\n backgroundMs,\r\n compositeMs,\r\n overlayMs,\r\n });\r\n }\r\n}\r\n","import type { MarginViewport } from './margin-viewport';\r\n\r\nfunction createOffscreenCanvas(width: number, height: number): HTMLCanvasElement | OffscreenCanvas {\r\n if (typeof OffscreenCanvas !== 'undefined') {\r\n return new OffscreenCanvas(width, height);\r\n }\r\n const canvas = document.createElement('canvas');\r\n canvas.width = width;\r\n canvas.height = height;\r\n return canvas;\r\n}\r\n\r\nexport class LayerCache {\r\n private canvases = new Map<string, HTMLCanvasElement | OffscreenCanvas>();\r\n private dirtyFlags = new Map<string, boolean>();\r\n\r\n constructor(private readonly viewport: MarginViewport) {}\r\n\r\n isDirty(layerId: string): boolean {\r\n return this.dirtyFlags.get(layerId) !== false;\r\n }\r\n\r\n markDirty(layerId: string): void {\r\n this.dirtyFlags.set(layerId, true);\r\n }\r\n\r\n markClean(layerId: string): void {\r\n this.dirtyFlags.set(layerId, false);\r\n }\r\n\r\n markAllDirty(): void {\r\n for (const [id] of this.dirtyFlags) {\r\n this.dirtyFlags.set(id, true);\r\n }\r\n }\r\n\r\n getCanvas(layerId: string): HTMLCanvasElement | OffscreenCanvas {\r\n let canvas = this.canvases.get(layerId);\r\n if (!canvas) {\r\n canvas = createOffscreenCanvas(this.viewport.physicalWidth(), this.viewport.physicalHeight());\r\n this.canvases.set(layerId, canvas);\r\n this.dirtyFlags.set(layerId, true);\r\n }\r\n return canvas;\r\n }\r\n\r\n getContext(layerId: string): CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null {\r\n const canvas = this.getCanvas(layerId);\r\n return canvas.getContext('2d') as\r\n | CanvasRenderingContext2D\r\n | OffscreenCanvasRenderingContext2D\r\n | null;\r\n }\r\n\r\n resize(): void {\r\n const w = this.viewport.physicalWidth();\r\n const h = this.viewport.physicalHeight();\r\n for (const [id, canvas] of this.canvases) {\r\n canvas.width = w;\r\n canvas.height = h;\r\n this.dirtyFlags.set(id, true);\r\n }\r\n }\r\n\r\n clear(): void {\r\n this.canvases.clear();\r\n this.dirtyFlags.clear();\r\n }\r\n}\r\n","import type { Bounds } from '../core/types';\r\n\r\n/**\r\n * Owns the cache anchor (the camera state the screen-space caches were last rendered at)\r\n * and the margin geometry. Pure — holds no canvas. Caches render a region inflated by\r\n * `marginPx` on every side, so a pan within the margin is an offset-blit, not a re-raster.\r\n *\r\n * Call setViewport(cssW, cssH, dpr) before physicalWidth/Height, applyRenderTransform, or compositeOffset — they read the stored dpr.\r\n */\r\nexport class MarginViewport {\r\n private cssW = 0;\r\n private cssH = 0;\r\n private dpr = 1;\r\n private anchorCamX = 0;\r\n private anchorCamY = 0;\r\n private anchorZoom = Number.NaN; // sentinel → first needsRecenter is true\r\n private viewportDirty = true;\r\n\r\n constructor(private marginPx: number) {}\r\n\r\n setMargin(marginPx: number): void {\r\n if (marginPx !== this.marginPx) {\r\n this.marginPx = marginPx;\r\n this.viewportDirty = true;\r\n }\r\n }\r\n\r\n setViewport(cssW: number, cssH: number, dpr: number): void {\r\n if (cssW !== this.cssW || cssH !== this.cssH || dpr !== this.dpr) {\r\n this.cssW = cssW;\r\n this.cssH = cssH;\r\n this.dpr = dpr;\r\n this.viewportDirty = true;\r\n }\r\n }\r\n\r\n physicalWidth(): number {\r\n return Math.round((this.cssW + 2 * this.marginPx) * this.dpr);\r\n }\r\n\r\n physicalHeight(): number {\r\n return Math.round((this.cssH + 2 * this.marginPx) * this.dpr);\r\n }\r\n\r\n needsRecenter(camX: number, camY: number, zoom: number): boolean {\r\n return (\r\n this.viewportDirty ||\r\n zoom !== this.anchorZoom ||\r\n Math.abs(camX - this.anchorCamX) > this.marginPx ||\r\n Math.abs(camY - this.anchorCamY) > this.marginPx\r\n );\r\n }\r\n\r\n recenter(camX: number, camY: number, zoom: number): void {\r\n this.anchorCamX = camX;\r\n this.anchorCamY = camY;\r\n this.anchorZoom = zoom;\r\n this.viewportDirty = false;\r\n }\r\n\r\n /** Applies dpr scale + anchor-relative world transform. setViewport must have been called first. */\r\n applyRenderTransform(ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D): void {\r\n ctx.scale(this.dpr, this.dpr);\r\n ctx.translate(this.marginPx + this.anchorCamX, this.marginPx + this.anchorCamY);\r\n ctx.scale(this.anchorZoom, this.anchorZoom);\r\n }\r\n\r\n // Device-px destination for drawImage(cache, x, y).\r\n // A world point P sits in the cache at CSS x `margin + anchorCamX + P*zoom`; it must land on\r\n // screen at `camX + P*zoom`; so the blit offset is `camX - anchorCamX - margin` (CSS) * dpr.\r\n compositeOffset(camX: number, camY: number): { x: number; y: number } {\r\n return {\r\n x: (camX - this.anchorCamX - this.marginPx) * this.dpr,\r\n y: (camY - this.anchorCamY - this.marginPx) * this.dpr,\r\n };\r\n }\r\n\r\n // World-space bounds of the whole cached region at the anchor (cull rect for re-renders).\r\n cachedWorldBounds(): Bounds {\r\n const z = this.anchorZoom;\r\n return {\r\n x: (-this.marginPx - this.anchorCamX) / z,\r\n y: (-this.marginPx - this.anchorCamY) / z,\r\n w: (this.cssW + 2 * this.marginPx) / z,\r\n h: (this.cssH + 2 * this.marginPx) / z,\r\n };\r\n }\r\n}\r\n","import type { CanvasElement } from './types';\r\n\r\n/** Patch that translates an element by (dx, dy). Arrows move position + from + to;\r\n * every other type moves position only (strokes carry points relative to position). */\r\nexport function translateElementPatch(\r\n el: CanvasElement,\r\n dx: number,\r\n dy: number,\r\n): Partial<CanvasElement> {\r\n const position = { x: el.position.x + dx, y: el.position.y + dy };\r\n if (el.type === 'arrow') {\r\n return {\r\n position,\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 }\r\n return { position };\r\n}\r\n","import type { CanvasElement } from './types';\r\n\r\nexport interface ElementStyle {\r\n color?: string;\r\n fillColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n fontSize?: number;\r\n}\r\n\r\nexport function styleToPatch(element: CanvasElement, style: ElementStyle): Partial<CanvasElement> {\r\n const { color, fillColor, strokeWidth, opacity, fontSize } = style;\r\n switch (element.type) {\r\n case 'stroke':\r\n return {\r\n ...(color !== undefined ? { color } : {}),\r\n ...(strokeWidth !== undefined ? { width: strokeWidth } : {}),\r\n ...(opacity !== undefined ? { opacity } : {}),\r\n };\r\n case 'arrow':\r\n return {\r\n ...(color !== undefined ? { color } : {}),\r\n ...(strokeWidth !== undefined ? { width: strokeWidth } : {}),\r\n };\r\n case 'shape':\r\n return {\r\n ...(color !== undefined ? { strokeColor: color } : {}),\r\n ...(fillColor !== undefined ? { fillColor } : {}),\r\n ...(strokeWidth !== undefined ? { strokeWidth } : {}),\r\n };\r\n case 'text':\r\n return {\r\n ...(color !== undefined ? { color } : {}),\r\n ...(fontSize !== undefined ? { fontSize } : {}),\r\n };\r\n case 'note':\r\n return {\r\n ...(color !== undefined ? { textColor: color } : {}),\r\n ...(fillColor !== undefined ? { backgroundColor: fillColor } : {}),\r\n ...(fontSize !== undefined ? { fontSize } : {}),\r\n };\r\n case 'grid':\r\n return {\r\n ...(color !== undefined ? { strokeColor: color } : {}),\r\n ...(strokeWidth !== undefined ? { strokeWidth } : {}),\r\n ...(opacity !== undefined ? { opacity } : {}),\r\n };\r\n case 'template':\r\n return {\r\n ...(color !== undefined ? { strokeColor: color } : {}),\r\n ...(fillColor !== undefined ? { fillColor } : {}),\r\n ...(strokeWidth !== undefined ? { strokeWidth } : {}),\r\n ...(opacity !== undefined ? { opacity } : {}),\r\n };\r\n default:\r\n return {};\r\n }\r\n}\r\n\r\nexport function getElementStyle(element: CanvasElement): ElementStyle {\r\n switch (element.type) {\r\n case 'stroke':\r\n return { color: element.color, strokeWidth: element.width, opacity: element.opacity };\r\n case 'arrow':\r\n return { color: element.color, strokeWidth: element.width };\r\n case 'shape':\r\n return {\r\n color: element.strokeColor,\r\n fillColor: element.fillColor,\r\n strokeWidth: element.strokeWidth,\r\n };\r\n case 'text':\r\n return { color: element.color, fontSize: element.fontSize };\r\n case 'note':\r\n return {\r\n color: element.textColor,\r\n fillColor: element.backgroundColor,\r\n ...(element.fontSize !== undefined ? { fontSize: element.fontSize } : {}),\r\n };\r\n case 'grid':\r\n return {\r\n color: element.strokeColor,\r\n strokeWidth: element.strokeWidth,\r\n opacity: element.opacity,\r\n };\r\n case 'template':\r\n return {\r\n color: element.strokeColor,\r\n fillColor: element.fillColor,\r\n strokeWidth: element.strokeWidth,\r\n opacity: element.opacity,\r\n };\r\n default:\r\n return {};\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport { updateArrowsBoundToElements } from '../elements/arrow-binding';\r\nimport { translateElementPatch } from '../elements/translate';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { createId } from '../elements/create-id';\r\nimport { styleToPatch, getElementStyle } from '../elements/element-style';\r\nimport type { ElementStyle } from '../elements/element-style';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport type { Bounds } from '../core/types';\r\n\r\nexport type AlignEdge = 'left' | 'center-x' | 'right' | 'top' | 'middle' | 'bottom';\r\nexport type DistributeAxis = 'horizontal' | 'vertical';\r\n\r\nfunction unionBounds(list: Bounds[]): Bounds {\r\n let minX = Infinity,\r\n minY = Infinity,\r\n maxX = -Infinity,\r\n maxY = -Infinity;\r\n for (const b of list) {\r\n minX = Math.min(minX, b.x);\r\n minY = Math.min(minY, b.y);\r\n maxX = Math.max(maxX, b.x + b.w);\r\n maxY = Math.max(maxY, b.y + b.h);\r\n }\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n\r\nfunction sharedValue<T>(values: (T | undefined)[]): T | undefined {\r\n const present = values.filter((v): v is T => v !== undefined);\r\n if (present.length === 0) return undefined;\r\n const first = present[0];\r\n return present.every((v) => v === first) ? first : undefined;\r\n}\r\n\r\nexport interface SelectionOpsDeps {\r\n store: ElementStore;\r\n recorder: HistoryRecorder;\r\n getSelectedIds: () => string[];\r\n requestRender: () => void;\r\n}\r\n\r\nexport class SelectionOps {\r\n constructor(private readonly deps: SelectionOpsDeps) {}\r\n\r\n getStyle(): ElementStyle | null {\r\n const ids = this.deps.getSelectedIds();\r\n if (ids.length === 0) return null;\r\n const styles: ElementStyle[] = [];\r\n for (const id of ids) {\r\n const el = this.deps.store.getById(id);\r\n if (el) styles.push(getElementStyle(el));\r\n }\r\n if (styles.length === 0) return null;\r\n const result: ElementStyle = {};\r\n const color = sharedValue(styles.map((s) => s.color));\r\n if (color !== undefined) result.color = color;\r\n const fillColor = sharedValue(styles.map((s) => s.fillColor));\r\n if (fillColor !== undefined) result.fillColor = fillColor;\r\n const strokeWidth = sharedValue(styles.map((s) => s.strokeWidth));\r\n if (strokeWidth !== undefined) result.strokeWidth = strokeWidth;\r\n const opacity = sharedValue(styles.map((s) => s.opacity));\r\n if (opacity !== undefined) result.opacity = opacity;\r\n const fontSize = sharedValue(styles.map((s) => s.fontSize));\r\n if (fontSize !== undefined) result.fontSize = fontSize;\r\n return result;\r\n }\r\n\r\n applyStyle(style: ElementStyle): void {\r\n const ids = this.deps.getSelectedIds();\r\n if (ids.length === 0) return;\r\n this.deps.recorder.begin();\r\n for (const id of ids) {\r\n const el = this.deps.store.getById(id);\r\n if (!el) continue;\r\n const patch = styleToPatch(el, style);\r\n if (Object.keys(patch).length > 0) {\r\n this.deps.store.update(id, patch);\r\n }\r\n }\r\n this.deps.recorder.commit();\r\n }\r\n\r\n group(): void {\r\n const ids = this.deps.getSelectedIds();\r\n if (ids.length < 2) return;\r\n const groupId = createId('group');\r\n this.deps.recorder.begin();\r\n for (const id of ids) {\r\n if (this.deps.store.getById(id)) this.deps.store.update(id, { groupId });\r\n }\r\n this.deps.recorder.commit();\r\n }\r\n\r\n ungroup(): void {\r\n const ids = this.deps.getSelectedIds();\r\n if (ids.length === 0) return;\r\n this.deps.recorder.begin();\r\n for (const id of ids) {\r\n const el = this.deps.store.getById(id);\r\n if (el && el.groupId !== undefined) this.deps.store.update(id, { groupId: undefined });\r\n }\r\n this.deps.recorder.commit();\r\n }\r\n\r\n toggleLock(): void {\r\n const ids = this.deps.getSelectedIds();\r\n if (ids.length === 0) return;\r\n const anyUnlocked = ids.some((id) => {\r\n const el = this.deps.store.getById(id);\r\n return el ? !el.locked : false;\r\n });\r\n this.deps.recorder.begin();\r\n for (const id of ids) {\r\n const el = this.deps.store.getById(id);\r\n if (el && el.locked !== anyUnlocked) this.deps.store.update(id, { locked: anyUnlocked });\r\n }\r\n this.deps.recorder.commit();\r\n }\r\n\r\n align(edge: AlignEdge): void {\r\n const bounded = this.boundedSelection();\r\n if (bounded.length < 2) return;\r\n const B = unionBounds(bounded.map((e) => e.bounds));\r\n this.deps.recorder.begin();\r\n const moved: string[] = [];\r\n for (const { id, el, bounds: b } of bounded) {\r\n if (!this.isMovable(el)) continue;\r\n let dx = 0;\r\n let dy = 0;\r\n switch (edge) {\r\n case 'left':\r\n dx = B.x - b.x;\r\n break;\r\n case 'right':\r\n dx = B.x + B.w - (b.x + b.w);\r\n break;\r\n case 'center-x':\r\n dx = B.x + B.w / 2 - (b.x + b.w / 2);\r\n break;\r\n case 'top':\r\n dy = B.y - b.y;\r\n break;\r\n case 'bottom':\r\n dy = B.y + B.h - (b.y + b.h);\r\n break;\r\n case 'middle':\r\n dy = B.y + B.h / 2 - (b.y + b.h / 2);\r\n break;\r\n }\r\n if (dx === 0 && dy === 0) continue;\r\n this.deps.store.update(id, translateElementPatch(el, dx, dy));\r\n moved.push(id);\r\n }\r\n updateArrowsBoundToElements(moved, this.deps.store);\r\n this.deps.recorder.commit();\r\n this.deps.requestRender();\r\n }\r\n\r\n distribute(axis: DistributeAxis): void {\r\n const bounded = this.boundedSelection();\r\n if (bounded.length < 3) return;\r\n const center = (b: Bounds) => (axis === 'horizontal' ? b.x + b.w / 2 : b.y + b.h / 2);\r\n const sorted = [...bounded].sort((p, q) => center(p.bounds) - center(q.bounds));\r\n const first = sorted[0];\r\n const last = sorted[sorted.length - 1];\r\n if (!first || !last) return;\r\n const c0 = center(first.bounds);\r\n const cN = center(last.bounds);\r\n const n = sorted.length;\r\n this.deps.recorder.begin();\r\n const moved: string[] = [];\r\n for (let i = 1; i < n - 1; i++) {\r\n const item = sorted[i];\r\n if (!item || !this.isMovable(item.el)) continue;\r\n const target = c0 + (i * (cN - c0)) / (n - 1);\r\n const delta = target - center(item.bounds);\r\n if (delta === 0) continue;\r\n const [dx, dy] = axis === 'horizontal' ? [delta, 0] : [0, delta];\r\n this.deps.store.update(item.id, translateElementPatch(item.el, dx, dy));\r\n moved.push(item.id);\r\n }\r\n updateArrowsBoundToElements(moved, this.deps.store);\r\n this.deps.recorder.commit();\r\n this.deps.requestRender();\r\n }\r\n\r\n private boundedSelection(): { id: string; el: CanvasElement; bounds: Bounds }[] {\r\n const out: { id: string; el: CanvasElement; bounds: Bounds }[] = [];\r\n for (const id of this.deps.getSelectedIds()) {\r\n const el = this.deps.store.getById(id);\r\n if (!el) continue;\r\n const bounds = getElementBounds(el);\r\n if (bounds) out.push({ id, el, bounds });\r\n }\r\n return out;\r\n }\r\n\r\n private isMovable(el: CanvasElement): boolean {\r\n if (el.locked) return false;\r\n if (el.type === 'arrow' && (el.fromBinding ?? el.toBinding)) return false;\r\n return true;\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport type { ToolContext } from '../tools/types';\r\nimport type { GridElement } from '../elements/types';\r\nimport { createGrid } from '../elements/element-factory';\r\n\r\nexport interface GridInfo {\r\n gridType: 'square' | 'hex';\r\n hexOrientation: 'pointy' | 'flat';\r\n cellSize: number;\r\n cellRadius: number;\r\n}\r\n\r\nexport interface GridControllerDeps {\r\n store: ElementStore;\r\n recorder: HistoryRecorder;\r\n requestRender: () => void;\r\n getActiveLayerId: () => string;\r\n toolContext: ToolContext;\r\n defaultGridSize: number;\r\n}\r\n\r\nexport class GridController {\r\n private readonly listeners = new Set<(info: GridInfo | null) => void>();\r\n\r\n constructor(private readonly deps: GridControllerDeps) {}\r\n\r\n add(input: {\r\n gridType?: 'square' | 'hex';\r\n hexOrientation?: 'pointy' | 'flat';\r\n cellSize?: number;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n }): string {\r\n const existing = this.deps.store.getElementsByType('grid')[0];\r\n this.deps.recorder.begin();\r\n if (existing) {\r\n this.deps.store.remove(existing.id);\r\n }\r\n const grid = createGrid({ ...input, layerId: this.deps.getActiveLayerId() });\r\n this.deps.store.add(grid);\r\n this.deps.recorder.commit();\r\n this.deps.requestRender();\r\n return grid.id;\r\n }\r\n\r\n update(\r\n updates: Partial<\r\n Pick<\r\n GridElement,\r\n 'gridType' | 'hexOrientation' | 'cellSize' | 'strokeColor' | 'strokeWidth' | 'opacity'\r\n >\r\n >,\r\n ): void {\r\n const grid = this.deps.store.getElementsByType('grid')[0];\r\n if (!grid) return;\r\n this.deps.recorder.begin();\r\n this.deps.store.update(grid.id, updates);\r\n this.deps.recorder.commit();\r\n this.deps.requestRender();\r\n }\r\n\r\n remove(): void {\r\n const grid = this.deps.store.getElementsByType('grid')[0];\r\n if (!grid) return;\r\n this.deps.recorder.begin();\r\n this.deps.store.remove(grid.id);\r\n this.deps.recorder.commit();\r\n this.deps.requestRender();\r\n }\r\n\r\n getInfo(): GridInfo | null {\r\n const grid = this.deps.store.getElementsByType('grid')[0];\r\n if (!grid) return null;\r\n return {\r\n gridType: grid.gridType,\r\n hexOrientation: grid.hexOrientation,\r\n cellSize: grid.cellSize,\r\n cellRadius: grid.gridType === 'hex' ? grid.cellSize : grid.cellSize / 2,\r\n };\r\n }\r\n\r\n onChange(listener: (info: GridInfo | null) => void): () => void {\r\n this.listeners.add(listener);\r\n return () => {\r\n this.listeners.delete(listener);\r\n };\r\n }\r\n\r\n syncContext(): void {\r\n const grid = this.deps.store.getElementsByType('grid')[0];\r\n if (grid) {\r\n this.deps.toolContext.gridSize = grid.cellSize;\r\n this.deps.toolContext.gridType = grid.gridType;\r\n this.deps.toolContext.hexOrientation = grid.hexOrientation;\r\n } else {\r\n this.deps.toolContext.gridSize = this.deps.defaultGridSize;\r\n this.deps.toolContext.gridType = undefined;\r\n this.deps.toolContext.hexOrientation = undefined;\r\n }\r\n this.notify();\r\n }\r\n\r\n private notify(): void {\r\n const info = this.getInfo();\r\n for (const listener of this.listeners) {\r\n listener(info);\r\n }\r\n }\r\n}\r\n","import type { Camera } from './camera';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { ElementRenderer } from '../elements/element-renderer';\r\nimport type { NoteEditor } from '../elements/note-editor';\r\nimport type { ArrowLabelEditor } from '../elements/arrow-label-editor';\r\nimport type { InteractMode } from './interact-mode';\r\nimport type { DomNodeManager } from './dom-node-manager';\r\nimport type { RenderLoop } from './render-loop';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport type { CanvasElement, ArrowElement } from '../elements/types';\r\nimport { DoubleTapDetector } from './double-tap-detector';\r\nimport { isNearBezier } from '../elements/arrow-geometry';\r\nimport { isNoteContentEmpty } from '../elements/note-sanitizer';\r\n\r\nconst ARROW_HIT_THRESHOLD = 10;\r\n\r\nexport interface ViewportInteractionsDeps {\r\n store: ElementStore;\r\n camera: Camera;\r\n wrapper: HTMLDivElement;\r\n domLayer: HTMLDivElement;\r\n renderLoop: RenderLoop;\r\n domNodeManager: DomNodeManager;\r\n noteEditor: NoteEditor;\r\n arrowLabelEditor: ArrowLabelEditor;\r\n interactMode: InteractMode;\r\n renderer: ElementRenderer;\r\n recorder: HistoryRecorder;\r\n requestRender: () => void;\r\n addImage: (src: string, position: { x: number; y: number }) => string;\r\n dropHandler?: (event: DragEvent, worldPosition: { x: number; y: number }) => void;\r\n}\r\n\r\nexport class ViewportInteractions {\r\n private readonly doubleTapDetector = new DoubleTapDetector();\r\n private tapDownX = 0;\r\n private tapDownY = 0;\r\n\r\n constructor(private readonly deps: ViewportInteractionsDeps) {}\r\n\r\n startEditingElement(id: string): void {\r\n const element = this.deps.store.getById(id);\r\n if (!element || (element.type !== 'note' && element.type !== 'text')) return;\r\n\r\n this.deps.renderLoop.flush();\r\n\r\n const node = this.deps.domNodeManager.getNode(id);\r\n if (node) {\r\n this.deps.noteEditor.startEditing(node, id, this.deps.store);\r\n }\r\n }\r\n\r\n fitNoteHeight(elementId: string): void {\r\n const element = this.deps.store.getById(elementId);\r\n if (!element || element.type !== 'note') return;\r\n if (isNoteContentEmpty(element.text)) return;\r\n const node = this.deps.domNodeManager.getNode(elementId);\r\n if (!node) return;\r\n const measured = node.scrollHeight;\r\n if (measured > element.size.h) {\r\n this.deps.store.update(elementId, { size: { w: element.size.w, h: measured } });\r\n }\r\n }\r\n\r\n onTextEditStop(elementId: string): void {\r\n const element = this.deps.store.getById(elementId);\r\n if (!element) return;\r\n\r\n if (element.type === 'note') {\r\n if (isNoteContentEmpty(element.text)) {\r\n this.deps.store.remove(elementId);\r\n return;\r\n }\r\n this.fitNoteHeight(elementId);\r\n return;\r\n }\r\n\r\n if (element.type !== 'text') return;\r\n\r\n if (!element.text || element.text.trim() === '') {\r\n this.deps.store.remove(elementId);\r\n return;\r\n }\r\n\r\n const node = this.deps.domNodeManager.getNode(elementId);\r\n if (node && 'size' in element) {\r\n const measured = node.scrollHeight;\r\n if (measured !== element.size.h) {\r\n this.deps.store.update(elementId, { size: { w: element.size.w, h: measured } });\r\n }\r\n }\r\n }\r\n\r\n onTapDown = (e: PointerEvent): void => {\r\n this.tapDownX = e.clientX;\r\n this.tapDownY = e.clientY;\r\n };\r\n\r\n onDoubleTap = (e: PointerEvent): void => {\r\n const dx = e.clientX - this.tapDownX;\r\n const dy = e.clientY - this.tapDownY;\r\n const moved = Math.sqrt(dx * dx + dy * dy);\r\n if (moved > 10) return;\r\n\r\n if (!this.doubleTapDetector.feed(e)) return;\r\n if (typeof document.elementFromPoint !== 'function') return;\r\n\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.deps.store.getById(elementId);\r\n if (element?.type === 'note' || element?.type === 'text') {\r\n this.startEditingElement(elementId);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n const rect = this.deps.wrapper.getBoundingClientRect();\r\n const screen = { x: e.clientX - rect.left, y: e.clientY - rect.top };\r\n const world = this.deps.camera.screenToWorld(screen);\r\n\r\n // HTML embeds keep double-tap priority: you double-tapped inside the embed even if an\r\n // arrow's curve passes nearby. Arrow-label editing only when no embed is hit.\r\n const hit = this.hitTestWorld(world);\r\n if (hit?.type === 'html') {\r\n this.deps.interactMode.startInteracting(hit.id);\r\n return;\r\n }\r\n\r\n const arrow = this.findArrowAt(world);\r\n if (arrow) {\r\n this.startArrowLabelEdit(arrow);\r\n }\r\n };\r\n\r\n findArrowAt(world: { x: number; y: number }): ArrowElement | undefined {\r\n const candidates = this.deps.store.queryPoint(world).reverse();\r\n for (const el of candidates) {\r\n if (\r\n el.type === 'arrow' &&\r\n isNearBezier(world, el.from, el.to, el.bend, ARROW_HIT_THRESHOLD)\r\n ) {\r\n return el;\r\n }\r\n }\r\n return undefined;\r\n }\r\n\r\n startArrowLabelEdit(arrow: ArrowElement): void {\r\n this.deps.arrowLabelEditor.startEditing({\r\n arrow,\r\n layer: this.deps.domLayer,\r\n store: this.deps.store,\r\n recorder: this.deps.recorder,\r\n onDone: () => {\r\n this.deps.renderer.setLabelEditingId(null);\r\n this.deps.requestRender();\r\n },\r\n });\r\n // Set AFTER startEditing: starting a new edit cleans up any prior session, whose onDone\r\n // synchronously clears the editing id — so claim suppression for this arrow last.\r\n this.deps.renderer.setLabelEditingId(arrow.id);\r\n }\r\n\r\n private hitTestWorld(world: { x: number; y: number }): CanvasElement | null {\r\n const candidates = this.deps.store.queryPoint(world).reverse();\r\n for (const el of candidates) {\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 onDragOver = (e: DragEvent): void => {\r\n e.preventDefault();\r\n };\r\n\r\n onDrop = (e: DragEvent): void => {\r\n e.preventDefault();\r\n const rect = this.deps.wrapper.getBoundingClientRect();\r\n const screenPos = { x: e.clientX - rect.left, y: e.clientY - rect.top };\r\n const worldPos = this.deps.camera.screenToWorld(screenPos);\r\n\r\n if (this.deps.dropHandler) {\r\n this.deps.dropHandler(e, worldPos);\r\n return;\r\n }\r\n\r\n const files = e.dataTransfer?.files;\r\n if (!files) return;\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 this.deps.addImage(src, worldPos);\r\n };\r\n reader.readAsDataURL(file);\r\n }\r\n };\r\n}\r\n","import { Camera } from './camera';\r\nimport type { CameraOptions } from './camera';\r\nimport { InputHandler } from './input-handler';\r\nimport type { ShortcutOptions, ShortcutsApi } from './shortcut-map';\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 { FontSizePreset } from '../elements/note-toolbar';\r\nimport type { CanvasElement, ArrowElement, GridElement, ShapeKind } from '../elements/types';\r\nimport type { Point } from '../core/types';\r\nimport { ContextMenu } from './context-menu';\r\nimport type { ContextMenuItem } from './context-menu';\r\nimport { createWrapper, createCanvas, createDomLayer } from './viewport-dom';\r\nimport { findBoundArrows, getEdgeIntersection } from '../elements/arrow-binding';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { getElementsBoundingBox } from '../elements/bounds';\r\nimport { getArrowTangentAngle } from '../elements/arrow-geometry';\r\nimport { ArrowLabelEditor } from '../elements/arrow-label-editor';\r\nimport { ToolManager } from '../tools/tool-manager';\r\nimport type { ToolContext } from '../tools/types';\r\nimport type { SelectTool } from '../tools/select-tool';\r\nimport { HistoryStack } from '../history/history-stack';\r\nimport { HistoryRecorder } from '../history/history-recorder';\r\nimport { createImage, createHtmlElement, createShape } from '../elements/element-factory';\r\nimport { exportState as exportCanvasState, parseState } from '../core/state-serializer';\r\nimport { exportImage } from './export-image';\r\nimport type { ExportImageOptions } from './export-image';\r\nimport type { CanvasState } from '../core/state-serializer';\r\nimport { LayerManager } from '../layers/layer-manager';\r\nimport { InteractMode } from './interact-mode';\r\nimport { DomNodeManager } from './dom-node-manager';\r\nimport { RenderLoop } from './render-loop';\r\nimport type { RenderStatsSnapshot } from './render-stats';\r\nimport { LayerCache } from './layer-cache';\r\nimport { MarginViewport } from './margin-viewport';\r\nimport type { ElementStyle } from '../elements/element-style';\r\nimport { SelectionOps } from './selection-ops';\r\nimport type { AlignEdge, DistributeAxis } from './selection-ops';\r\nimport { GridController } from './grid-controller';\r\nimport type { GridInfo } from './grid-controller';\r\nimport { ViewportInteractions } from './viewport-interactions';\r\n\r\nexport type { AlignEdge, DistributeAxis } from './selection-ops';\r\nexport type { GridInfo } from './grid-controller';\r\n\r\nconst EMPTY_IDS: string[] = [];\r\n\r\nfunction noop(): void {\r\n // Stable unsubscribe handle returned when no select tool is registered.\r\n}\r\n\r\nexport interface ViewportOptions {\r\n camera?: CameraOptions;\r\n background?: BackgroundOptions;\r\n fontSizePresets?: FontSizePreset[];\r\n toolbar?: boolean;\r\n placeholder?: string;\r\n shortcuts?: ShortcutOptions;\r\n onHtmlElementMount?: (\r\n elementId: string,\r\n domId: string | undefined,\r\n container: HTMLDivElement,\r\n ) => void;\r\n onDrop?: (event: DragEvent, worldPosition: { x: number; y: number }) => void;\r\n onImageError?: (info: { src: string; elementIds: string[]; cause?: unknown }) => void;\r\n /** CSS-pixel margin cached beyond the viewport. Default `256`. Set `0` to disable. */\r\n panBufferMargin?: number;\r\n /** Enable the built-in context menu. Default `true`. */\r\n contextMenu?: boolean;\r\n}\r\n\r\nexport class Viewport {\r\n readonly camera: Camera;\r\n readonly store: ElementStore;\r\n readonly layerManager: LayerManager;\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 unsubToolChange: () => 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 arrowLabelEditor: ArrowLabelEditor;\r\n private readonly historyRecorder: HistoryRecorder;\r\n private readonly selectionOps: SelectionOps;\r\n readonly toolContext: ToolContext;\r\n private readonly marginViewport: MarginViewport;\r\n private resizeObserver: ResizeObserver | null = null;\r\n private _snapToGrid = false;\r\n private _smartGuides = false;\r\n private readonly _gridSize: number;\r\n private readonly renderLoop: RenderLoop;\r\n private readonly domNodeManager: DomNodeManager;\r\n private readonly interactMode: InteractMode;\r\n private readonly onHtmlElementMount?: (\r\n elementId: string,\r\n domId: string | undefined,\r\n container: HTMLDivElement,\r\n ) => void;\r\n private readonly dropHandler?: (\r\n event: DragEvent,\r\n worldPosition: { x: number; y: number },\r\n ) => void;\r\n private readonly gridController: GridController;\r\n private readonly interactions: ViewportInteractions;\r\n private contextMenu: ContextMenu | 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._gridSize = options.background?.spacing ?? 24;\r\n this.store = new ElementStore();\r\n this.layerManager = new LayerManager(this.store);\r\n this.toolManager = new ToolManager();\r\n this.renderer = new ElementRenderer();\r\n this.renderer.setStore(this.store);\r\n this.renderer.setCamera(this.camera);\r\n this.renderer.setOnImageLoad(() => {\r\n this.renderLoop.markAllLayersDirty();\r\n this.requestRender();\r\n });\r\n this.renderer.setOnImageError((src, cause) => {\r\n const elementIds: string[] = [];\r\n for (const el of this.store.getAll()) {\r\n if (el.type === 'image' && el.src === src) elementIds.push(el.id);\r\n }\r\n if (options.onImageError) {\r\n options.onImageError({ src, elementIds, cause });\r\n } else {\r\n console.warn(`[fieldnotes] image failed to load: ${src}`);\r\n }\r\n });\r\n this.noteEditor = new NoteEditor({\r\n fontSizePresets: options.fontSizePresets,\r\n toolbar: options.toolbar,\r\n placeholder: options.placeholder,\r\n });\r\n this.noteEditor.setOnStop((id) => this.interactions.onTextEditStop(id));\r\n this.arrowLabelEditor = new ArrowLabelEditor();\r\n this.noteEditor.setHistoryHooks(\r\n () => this.historyRecorder.begin(),\r\n () => this.historyRecorder.commit(),\r\n );\r\n this.onHtmlElementMount = options.onHtmlElementMount;\r\n this.dropHandler = options.onDrop;\r\n this.history = new HistoryStack();\r\n this.historyRecorder = new HistoryRecorder(this.store, this.history, this.layerManager);\r\n this.selectionOps = new SelectionOps({\r\n store: this.store,\r\n recorder: this.historyRecorder,\r\n getSelectedIds: () => this.getSelectedIds(),\r\n requestRender: () => this.requestRender(),\r\n });\r\n\r\n this.wrapper = createWrapper();\r\n this.canvasEl = createCanvas();\r\n this.domLayer = 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.interactions.startEditingElement(id),\r\n fitNoteHeight: (id: string) => this.interactions.fitNoteHeight(id),\r\n setCursor: (cursor: string) => {\r\n this.wrapper.style.cursor = cursor;\r\n },\r\n snapToGrid: false,\r\n gridSize: this._gridSize,\r\n activeLayerId: this.layerManager.activeLayerId,\r\n isLayerVisible: (id: string) => this.layerManager.isLayerVisible(id),\r\n isLayerLocked: (id: string) => this.layerManager.isLayerLocked(id),\r\n smartGuides: false,\r\n getVisibleRect: () =>\r\n this.camera.getVisibleRect(this.canvasEl.clientWidth, this.canvasEl.clientHeight),\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 fitToContent: () => this.fitToContent(),\r\n group: () => this.groupSelection(),\r\n ungroup: () => this.ungroupSelection(),\r\n toggleLock: () => this.toggleLockSelection(),\r\n openContextMenu: (screenPos, world) => {\r\n this.getSelectTool()?.selectAtPoint(world, this.toolContext);\r\n this.openContextMenu(screenPos);\r\n },\r\n shortcuts: options.shortcuts,\r\n });\r\n\r\n if (options.contextMenu !== false) {\r\n this.contextMenu = new ContextMenu({\r\n onCommand: (action) => this.runAction(action),\r\n onClose: noop,\r\n });\r\n }\r\n this.unsubToolChange = this.toolManager.onChange(() => this.contextMenu?.close());\r\n\r\n this.domNodeManager = new DomNodeManager({\r\n domLayer: this.domLayer,\r\n onEditRequest: (id) => this.interactions.startEditingElement(id),\r\n isEditingElement: (id) =>\r\n this.noteEditor.isEditing && this.noteEditor.editingElementId === id,\r\n getVersion: (id) => this.store.getVersion(id),\r\n });\r\n\r\n this.interactMode = new InteractMode({\r\n getNode: (id) => this.domNodeManager.getNode(id),\r\n });\r\n\r\n this.marginViewport = new MarginViewport(options.panBufferMargin ?? 256);\r\n this.marginViewport.setViewport(\r\n this.canvasEl.clientWidth || 800,\r\n this.canvasEl.clientHeight || 600,\r\n typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1,\r\n );\r\n const layerCache = new LayerCache(this.marginViewport);\r\n\r\n this.renderLoop = new RenderLoop({\r\n canvasEl: this.canvasEl,\r\n camera: this.camera,\r\n background: this.background,\r\n store: this.store,\r\n renderer: this.renderer,\r\n toolManager: this.toolManager,\r\n layerManager: this.layerManager,\r\n domNodeManager: this.domNodeManager,\r\n layerCache,\r\n marginViewport: this.marginViewport,\r\n });\r\n\r\n this.unsubCamera = this.camera.onChange(() => {\r\n this.applyCameraTransform();\r\n this.noteEditor.updateToolbarPosition();\r\n this.contextMenu?.close();\r\n this.requestRender();\r\n });\r\n\r\n this.gridController = new GridController({\r\n store: this.store,\r\n recorder: this.historyRecorder,\r\n requestRender: () => this.requestRender(),\r\n getActiveLayerId: () => this.layerManager.activeLayerId,\r\n toolContext: this.toolContext,\r\n defaultGridSize: this._gridSize,\r\n });\r\n\r\n this.unsubStore = [\r\n this.store.on('add', (el) => {\r\n if (el.type === 'grid') this.gridController.syncContext();\r\n this.renderLoop.markLayerDirty(el.layerId);\r\n this.requestRender();\r\n }),\r\n this.store.on('remove', (el) => {\r\n if (el.type === 'grid') this.gridController.syncContext();\r\n this.unbindArrowsFrom(el);\r\n this.domNodeManager.removeDomNode(el.id);\r\n this.renderLoop.markLayerDirty(el.layerId);\r\n this.requestRender();\r\n }),\r\n this.store.on('update', ({ previous, current }) => {\r\n if (current.type === 'grid') this.gridController.syncContext();\r\n this.renderLoop.markLayerDirty(current.layerId);\r\n if (previous.layerId !== current.layerId) {\r\n this.renderLoop.markLayerDirty(previous.layerId);\r\n }\r\n this.requestRender();\r\n }),\r\n this.store.on('clear', () => {\r\n this.domNodeManager.clearDomNodes();\r\n this.renderLoop.markAllLayersDirty();\r\n this.gridController.syncContext();\r\n this.requestRender();\r\n }),\r\n ];\r\n\r\n this.layerManager.on('change', () => {\r\n this.toolContext.activeLayerId = this.layerManager.activeLayerId;\r\n this.requestRender();\r\n });\r\n\r\n this.interactions = new ViewportInteractions({\r\n store: this.store,\r\n camera: this.camera,\r\n wrapper: this.wrapper,\r\n domLayer: this.domLayer,\r\n renderLoop: this.renderLoop,\r\n domNodeManager: this.domNodeManager,\r\n noteEditor: this.noteEditor,\r\n arrowLabelEditor: this.arrowLabelEditor,\r\n interactMode: this.interactMode,\r\n renderer: this.renderer,\r\n recorder: this.historyRecorder,\r\n requestRender: () => this.requestRender(),\r\n addImage: (src, position) => this.addImage(src, position),\r\n dropHandler: this.dropHandler,\r\n });\r\n\r\n this.wrapper.addEventListener('pointerdown', this.interactions.onTapDown);\r\n this.wrapper.addEventListener('pointerup', this.interactions.onDoubleTap);\r\n this.wrapper.addEventListener('dragover', this.interactions.onDragOver);\r\n this.wrapper.addEventListener('drop', this.interactions.onDrop);\r\n this.observeResize();\r\n this.syncCanvasSize();\r\n this.renderLoop.start();\r\n this.gridController.syncContext();\r\n }\r\n\r\n get ctx(): CanvasRenderingContext2D | null {\r\n return this.canvasEl.getContext('2d');\r\n }\r\n\r\n get snapToGrid(): boolean {\r\n return this._snapToGrid;\r\n }\r\n\r\n setSnapToGrid(enabled: boolean): void {\r\n this._snapToGrid = enabled;\r\n this.toolContext.snapToGrid = enabled;\r\n }\r\n\r\n get smartGuides(): boolean {\r\n return this._smartGuides;\r\n }\r\n\r\n setSmartGuides(enabled: boolean): void {\r\n this._smartGuides = enabled;\r\n this.toolContext.smartGuides = enabled;\r\n }\r\n\r\n fitToContent(padding = 40): void {\r\n if (this.wrapper.clientWidth === 0 || this.wrapper.clientHeight === 0) return;\r\n const visibleElements = this.store\r\n .getAll()\r\n .filter((el) => this.layerManager.isLayerVisible(el.layerId));\r\n const bbox = getElementsBoundingBox(visibleElements);\r\n if (!bbox) return;\r\n this.camera.fitToContent(bbox, this.wrapper.clientWidth, this.wrapper.clientHeight, padding);\r\n }\r\n\r\n requestRender(): void {\r\n this.renderLoop.requestRender();\r\n }\r\n\r\n exportState(): CanvasState {\r\n return exportCanvasState(\r\n this.store.snapshot(),\r\n this.camera,\r\n this.layerManager.snapshot(),\r\n this.layerManager.activeLayerId,\r\n );\r\n }\r\n\r\n exportJSON(): string {\r\n return JSON.stringify(this.exportState());\r\n }\r\n\r\n async exportImage(options?: ExportImageOptions): Promise<Blob | null> {\r\n return exportImage(this.store, options, this.layerManager);\r\n }\r\n\r\n loadState(state: CanvasState): void {\r\n this.inputHandler.flushPendingHistory();\r\n this.historyRecorder.pause();\r\n this.noteEditor.destroy(this.store);\r\n this.domNodeManager.clearDomNodes();\r\n this.store.loadSnapshot(state.elements);\r\n if (state.layers && state.layers.length > 0) {\r\n this.layerManager.loadSnapshot(state.layers);\r\n }\r\n if (state.activeLayerId) {\r\n this.layerManager.setActiveLayer(state.activeLayerId);\r\n }\r\n this.domNodeManager.reattachHtmlContent(this.store);\r\n if (this.onHtmlElementMount) {\r\n for (const el of this.store.getElementsByType('html')) {\r\n if (!this.domNodeManager.hasContent(el.id)) {\r\n this.domNodeManager.syncDomNode(el);\r\n const node = this.domNodeManager.getNode(el.id);\r\n if (node) {\r\n this.onHtmlElementMount(el.id, el.domId, node);\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n overflow: 'hidden',\r\n pointerEvents: el.interactive ? 'auto' : 'none',\r\n });\r\n }\r\n }\r\n }\r\n }\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 setTool(name: string): void {\r\n if (!this.toolManager.getTool(name)) {\r\n console.warn(`[fieldnotes] setTool: no tool registered as \"${name}\"`);\r\n return;\r\n }\r\n this.toolManager.setTool(name, this.toolContext);\r\n }\r\n\r\n get shortcuts(): ShortcutsApi {\r\n return this.inputHandler.shortcuts;\r\n }\r\n\r\n undo(): boolean {\r\n this.inputHandler.flushPendingHistory();\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.inputHandler.flushPendingHistory();\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, layerId: this.layerManager.activeLayerId });\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 domId = dom.id || undefined;\r\n const el = createHtmlElement({\r\n position,\r\n size,\r\n domId,\r\n layerId: this.layerManager.activeLayerId,\r\n });\r\n this.domNodeManager.storeHtmlContent(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 addShape(\r\n opts: {\r\n shape?: ShapeKind;\r\n size?: { w: number; h: number };\r\n position?: { x: number; y: number };\r\n strokeColor?: string;\r\n fillColor?: string;\r\n strokeWidth?: number;\r\n } = {},\r\n ): string {\r\n const size = opts.size ?? { w: 100, h: 100 };\r\n const position = opts.position ?? this.centeredPosition(size);\r\n const shape = createShape({\r\n position,\r\n size,\r\n shape: opts.shape,\r\n strokeColor: opts.strokeColor,\r\n strokeWidth: opts.strokeWidth,\r\n fillColor: opts.fillColor,\r\n layerId: this.layerManager.activeLayerId,\r\n });\r\n this.historyRecorder.begin();\r\n this.store.add(shape);\r\n this.historyRecorder.commit();\r\n this.getSelectTool()?.setSelection([shape.id]);\r\n this.requestRender();\r\n return shape.id;\r\n }\r\n\r\n private centeredPosition(size: { w: number; h: number }): { x: number; y: number } {\r\n const c = this.camera.screenToWorld({\r\n x: this.wrapper.clientWidth / 2,\r\n y: this.wrapper.clientHeight / 2,\r\n });\r\n return { x: c.x - size.w / 2, y: c.y - size.h / 2 };\r\n }\r\n\r\n removeLayer(id: string): void {\r\n this.historyRecorder.begin();\r\n this.layerManager.removeLayer(id);\r\n this.historyRecorder.commit();\r\n }\r\n\r\n updateHtmlElement(id: string, newContent: HTMLElement): void {\r\n const el = this.store.getById(id);\r\n if (!el) throw new Error(`Element not found: ${id}`);\r\n if (el.type !== 'html') throw new Error(`Element ${id} is not an HTML element`);\r\n this.domNodeManager.resetHtmlContent(id);\r\n this.domNodeManager.storeHtmlContent(id, newContent);\r\n this.requestRender();\r\n }\r\n\r\n addGrid(input: {\r\n gridType?: 'square' | 'hex';\r\n hexOrientation?: 'pointy' | 'flat';\r\n cellSize?: number;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n }): string {\r\n return this.gridController.add(input);\r\n }\r\n\r\n updateGrid(\r\n updates: Partial<\r\n Pick<\r\n GridElement,\r\n 'gridType' | 'hexOrientation' | 'cellSize' | 'strokeColor' | 'strokeWidth' | 'opacity'\r\n >\r\n >,\r\n ): void {\r\n this.gridController.update(updates);\r\n }\r\n\r\n removeGrid(): void {\r\n this.gridController.remove();\r\n }\r\n\r\n getGridInfo(): GridInfo | null {\r\n return this.gridController.getInfo();\r\n }\r\n\r\n onGridChange(listener: (info: GridInfo | null) => void): () => void {\r\n return this.gridController.onChange(listener);\r\n }\r\n\r\n private getSelectTool(): SelectTool | undefined {\r\n return this.toolManager.getTool<SelectTool>('select');\r\n }\r\n\r\n getSelectedIds(): string[] {\r\n return this.getSelectTool()?.selectedIds ?? EMPTY_IDS;\r\n }\r\n\r\n runAction(action: string): void {\r\n this.inputHandler.runAction(action);\r\n }\r\n\r\n canPaste(): boolean {\r\n return this.inputHandler.hasClipboard();\r\n }\r\n\r\n openContextMenu(screenPos: Point): void {\r\n if (!this.contextMenu) return;\r\n const ids = this.getSelectedIds();\r\n const items: ContextMenuItem[] = [];\r\n if (ids.length > 0) {\r\n items.push({ label: 'Cut', action: 'cut' });\r\n items.push({ label: 'Copy', action: 'copy' });\r\n if (this.canPaste()) items.push({ label: 'Paste', action: 'paste' });\r\n items.push({ label: 'Duplicate', action: 'duplicate' });\r\n items.push({ label: 'Delete', action: 'delete' });\r\n items.push({ label: 'Bring to Front', action: 'z-front' });\r\n items.push({ label: 'Bring Forward', action: 'z-forward' });\r\n items.push({ label: 'Send Backward', action: 'z-backward' });\r\n items.push({ label: 'Send to Back', action: 'z-back' });\r\n const allLocked = ids.every((id) => this.store.getById(id)?.locked);\r\n items.push({ label: allLocked ? 'Unlock' : 'Lock', action: 'toggle-lock' });\r\n } else if (this.canPaste()) {\r\n items.push({ label: 'Paste', action: 'paste' });\r\n }\r\n if (items.length === 0) return;\r\n this.contextMenu.open(items, screenPos);\r\n }\r\n\r\n onSelectionChange(listener: () => void): () => void {\r\n const tool = this.getSelectTool();\r\n return tool ? tool.onSelectionChange(listener) : noop;\r\n }\r\n\r\n getSelectionStyle(): ElementStyle | null {\r\n return this.selectionOps.getStyle();\r\n }\r\n\r\n applyStyleToSelection(style: ElementStyle): void {\r\n this.selectionOps.applyStyle(style);\r\n }\r\n\r\n groupSelection(): void {\r\n this.selectionOps.group();\r\n }\r\n\r\n ungroupSelection(): void {\r\n this.selectionOps.ungroup();\r\n }\r\n\r\n toggleLockSelection(): void {\r\n this.selectionOps.toggleLock();\r\n }\r\n\r\n alignSelection(edge: AlignEdge): void {\r\n this.selectionOps.align(edge);\r\n }\r\n\r\n distributeSelection(axis: DistributeAxis): void {\r\n this.selectionOps.distribute(axis);\r\n }\r\n\r\n getRenderStats(): RenderStatsSnapshot {\r\n return this.renderLoop.getStats();\r\n }\r\n\r\n logPerformance(intervalMs = 2000): () => void {\r\n const id = setInterval(() => {\r\n const s = this.getRenderStats();\r\n console.log(\r\n `[FieldNotes] fps=${s.fps} frame=${s.avgFrameMs}ms p95=${s.p95FrameMs}ms grid=${s.lastGridMs}ms layers=${s.layersMs}ms comp=${s.compositeMs}ms bg=${s.backgroundMs}ms overlay=${s.overlayMs}ms`,\r\n );\r\n }, intervalMs);\r\n return () => clearInterval(id);\r\n }\r\n\r\n destroy(): void {\r\n this.renderLoop.stop();\r\n this.interactMode.destroy();\r\n this.noteEditor.destroy(this.store);\r\n this.arrowLabelEditor.cancel();\r\n this.historyRecorder.destroy();\r\n this.contextMenu?.dispose();\r\n this.wrapper.removeEventListener('pointerdown', this.interactions.onTapDown);\r\n this.wrapper.removeEventListener('pointerup', this.interactions.onDoubleTap);\r\n this.wrapper.removeEventListener('dragover', this.interactions.onDragOver);\r\n this.wrapper.removeEventListener('drop', this.interactions.onDrop);\r\n this.inputHandler.destroy();\r\n this.unsubCamera();\r\n this.unsubToolChange();\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 stopInteracting(): void {\r\n this.interactMode.stopInteracting();\r\n }\r\n\r\n private unbindArrowsFrom(removedElement: CanvasElement): void {\r\n const boundArrows = findBoundArrows(removedElement.id, this.store);\r\n const bounds = getElementBounds(removedElement);\r\n\r\n for (const arrow of boundArrows) {\r\n const updates: Partial<ArrowElement> = {};\r\n\r\n if (arrow.fromBinding?.elementId === removedElement.id) {\r\n updates.fromBinding = undefined;\r\n if (bounds) {\r\n const angle = getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 0);\r\n const rayTarget = {\r\n x: arrow.from.x + Math.cos(angle) * 1000,\r\n y: arrow.from.y + Math.sin(angle) * 1000,\r\n };\r\n const edge = getEdgeIntersection(bounds, rayTarget);\r\n updates.from = edge;\r\n updates.position = edge;\r\n }\r\n }\r\n\r\n if (arrow.toBinding?.elementId === removedElement.id) {\r\n updates.toBinding = undefined;\r\n if (bounds) {\r\n const angle = getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 1);\r\n const rayTarget = {\r\n x: arrow.to.x - Math.cos(angle) * 1000,\r\n y: arrow.to.y - Math.sin(angle) * 1000,\r\n };\r\n updates.to = getEdgeIntersection(bounds, rayTarget);\r\n }\r\n }\r\n\r\n if (Object.keys(updates).length > 0) {\r\n this.store.update(arrow.id, updates);\r\n }\r\n }\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.renderLoop.setCanvasSize(rect.width * dpr, 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\nimport { computeStrokeSegments } from '../elements/stroke-cache';\r\n\r\nexport interface PencilToolOptions {\r\n name?: string;\r\n color?: string;\r\n width?: number;\r\n smoothing?: number;\r\n minPointDistance?: number;\r\n progressiveSimplifyThreshold?: number;\r\n opacity?: number;\r\n blendMode?: 'multiply';\r\n}\r\n\r\nconst MIN_POINTS_FOR_STROKE = 2;\r\nconst DEFAULT_SMOOTHING = 1.5;\r\nconst DEFAULT_PRESSURE = 0.5;\r\nconst DEFAULT_MIN_POINT_DISTANCE = 3;\r\nconst DEFAULT_PROGRESSIVE_THRESHOLD = 200;\r\nconst PROGRESSIVE_HOT_ZONE = 30;\r\n\r\nexport class PencilTool implements Tool {\r\n readonly name: string;\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 private minPointDistance: number;\r\n private progressiveThreshold: number;\r\n private nextSimplifyAt: number;\r\n private opacity: number;\r\n private blendMode: 'multiply' | undefined;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: PencilToolOptions = {}) {\r\n this.name = options.name ?? 'pencil';\r\n this.color = options.color ?? '#000000';\r\n this.width = options.width ?? 2;\r\n this.smoothing = options.smoothing ?? DEFAULT_SMOOTHING;\r\n this.minPointDistance = options.minPointDistance ?? DEFAULT_MIN_POINT_DISTANCE;\r\n this.progressiveThreshold =\r\n options.progressiveSimplifyThreshold ?? DEFAULT_PROGRESSIVE_THRESHOLD;\r\n this.nextSimplifyAt = this.progressiveThreshold;\r\n this.opacity = options.opacity ?? 1;\r\n this.blendMode = options.blendMode;\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 getOptions(): PencilToolOptions {\r\n return {\r\n color: this.color,\r\n width: this.width,\r\n smoothing: this.smoothing,\r\n minPointDistance: this.minPointDistance,\r\n progressiveSimplifyThreshold: this.progressiveThreshold,\r\n opacity: this.opacity,\r\n blendMode: this.blendMode,\r\n };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\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 if (options.minPointDistance !== undefined) this.minPointDistance = options.minPointDistance;\r\n if (options.progressiveSimplifyThreshold !== undefined)\r\n this.progressiveThreshold = options.progressiveSimplifyThreshold;\r\n if (options.opacity !== undefined) this.opacity = options.opacity;\r\n if (options.blendMode !== undefined) this.blendMode = options.blendMode;\r\n this.notifyOptionsChange();\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 this.nextSimplifyAt = this.progressiveThreshold;\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\r\n const last = this.points[this.points.length - 1];\r\n if (last) {\r\n const dx = world.x - last.x;\r\n const dy = world.y - last.y;\r\n if (dx * dx + dy * dy < this.minPointDistance * this.minPointDistance) return;\r\n }\r\n\r\n this.points.push({ x: world.x, y: world.y, pressure });\r\n\r\n // Progressively simplify the cold zone to bound memory on very long strokes.\r\n // nextSimplifyAt doubles after each pass to avoid compounding data loss.\r\n if (this.points.length > this.nextSimplifyAt) {\r\n const hotZone = this.points.slice(-PROGRESSIVE_HOT_ZONE);\r\n const coldZone = this.points.slice(0, -PROGRESSIVE_HOT_ZONE);\r\n const simplified = simplifyPoints(coldZone, this.smoothing * 2);\r\n this.points = [...simplified, ...hotZone];\r\n this.nextSimplifyAt = this.points.length + this.progressiveThreshold;\r\n }\r\n\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 layerId: ctx.activeLayerId ?? '',\r\n opacity: this.opacity,\r\n blendMode: this.blendMode,\r\n });\r\n ctx.store.add(stroke);\r\n computeStrokeSegments(stroke);\r\n this.points = [];\r\n ctx.requestRender();\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\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 // Preview a highlighter at its real opacity + blend so it doesn't snap on commit;\r\n // a normal pencil keeps the lighter 0.8 in-progress affordance.\r\n ctx.globalAlpha = this.blendMode ? this.opacity : 0.8;\r\n if (this.blendMode) ctx.globalCompositeOperation = this.blendMode;\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';\r\nimport type { StrokeElement } from './types';\r\nimport { getElementBounds } from './element-bounds';\r\nimport { getStrokeRenderData } from './stroke-cache';\r\nimport { distSqToSegment } from '../core/geometry';\r\n\r\nexport function hitTestStroke(stroke: StrokeElement, point: Point, radius: number): boolean {\r\n const bounds = getElementBounds(stroke);\r\n if (!bounds) return false;\r\n if (\r\n point.x < bounds.x - radius ||\r\n point.x > bounds.x + bounds.w + radius ||\r\n point.y < bounds.y - radius ||\r\n point.y > bounds.y + bounds.h + radius\r\n ) {\r\n return false;\r\n }\r\n\r\n const radiusSq = radius * radius;\r\n const local: Point = { x: point.x - stroke.position.x, y: point.y - stroke.position.y };\r\n const { segments } = getStrokeRenderData(stroke);\r\n\r\n if (segments.length === 0) {\r\n const p = stroke.points[0];\r\n if (!p) return false;\r\n const dx = p.x - local.x;\r\n const dy = p.y - local.y;\r\n return dx * dx + dy * dy <= radiusSq;\r\n }\r\n\r\n for (const seg of segments) {\r\n if (distSqToSegment(local, seg.start, seg.end) <= radiusSq) return true;\r\n }\r\n return false;\r\n}\r\n","import type { Point, StrokePoint } from '../core/types';\r\n\r\nfunction lerp(a: StrokePoint, b: StrokePoint, t: number): StrokePoint {\r\n return {\r\n x: a.x + (b.x - a.x) * t,\r\n y: a.y + (b.y - a.y) * t,\r\n pressure: a.pressure + (b.pressure - a.pressure) * t,\r\n };\r\n}\r\n\r\n/**\r\n * Split a stroke's points by an eraser circle (all in the stroke's local space).\r\n * Returns surviving runs (each ≥2 points), `[]` if fully erased, or `null` if nothing\r\n * was within the radius (no change).\r\n */\r\nexport function erasePoints(\r\n points: StrokePoint[],\r\n eraser: Point,\r\n radius: number,\r\n): StrokePoint[][] | null {\r\n const r2 = radius * radius;\r\n\r\n if (points.length < 2) {\r\n const p = points[0];\r\n if (p && (p.x - eraser.x) ** 2 + (p.y - eraser.y) ** 2 <= r2) return [];\r\n return null;\r\n }\r\n\r\n const runs: StrokePoint[][] = [];\r\n let current: StrokePoint[] = [];\r\n let erased = false;\r\n\r\n const flush = (): void => {\r\n if (current.length >= 2) runs.push(current);\r\n current = [];\r\n };\r\n\r\n for (let i = 0; i < points.length - 1; i++) {\r\n const a = points[i];\r\n const b = points[i + 1];\r\n if (!a || !b) continue;\r\n\r\n const dx = b.x - a.x;\r\n const dy = b.y - a.y;\r\n const fx = a.x - eraser.x;\r\n const fy = a.y - eraser.y;\r\n const A = dx * dx + dy * dy;\r\n const B = 2 * (fx * dx + fy * dy);\r\n const C = fx * fx + fy * fy - r2;\r\n\r\n let tLo = 1;\r\n let tHi = 0;\r\n if (A === 0) {\r\n if (C <= 0) {\r\n tLo = 0;\r\n tHi = 1;\r\n }\r\n } else {\r\n const disc = B * B - 4 * A * C;\r\n if (disc >= 0) {\r\n const sq = Math.sqrt(disc);\r\n const lo = Math.max(0, (-B - sq) / (2 * A));\r\n const hi = Math.min(1, (-B + sq) / (2 * A));\r\n // Strict `<`: a tangent graze (lo === hi, zero-width overlap) is not an erase —\r\n // it would otherwise split a stroke in two at a single duplicated point.\r\n if (lo < hi) {\r\n tLo = lo;\r\n tHi = hi;\r\n }\r\n }\r\n }\r\n\r\n if (tLo > tHi) {\r\n if (current.length === 0) current.push(a);\r\n current.push(b);\r\n continue;\r\n }\r\n\r\n erased = true;\r\n if (tLo > 0) {\r\n if (current.length === 0) current.push(a);\r\n current.push(lerp(a, b, tLo));\r\n flush();\r\n } else {\r\n flush();\r\n }\r\n if (tHi < 1) {\r\n current = [lerp(a, b, tHi), b];\r\n }\r\n }\r\n\r\n flush();\r\n return erased ? runs : null;\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport type { StrokeElement } from '../elements/types';\r\nimport { hitTestStroke } from '../elements/stroke-hit';\r\nimport { createStroke } from '../elements/element-factory';\r\nimport { erasePoints } from '../elements/stroke-erase';\r\n\r\nexport interface EraserToolOptions {\r\n /** Eraser radius in SCREEN pixels (matches the cursor circle; converted to world units per zoom). */\r\n radius?: number;\r\n mode?: 'partial' | 'stroke';\r\n}\r\n\r\nconst DEFAULT_RADIUS = 20;\r\n\r\nfunction makeEraserCursor(radius: number): string {\r\n const size = radius * 2;\r\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>`;\r\n return `url(\"data:image/svg+xml,${svg}\") ${radius} ${radius}, crosshair`;\r\n}\r\n\r\nexport class EraserTool implements Tool {\r\n readonly name = 'eraser';\r\n private erasing = false;\r\n private radius: number;\r\n private cursor: string;\r\n private mode: 'partial' | 'stroke';\r\n\r\n constructor(options: EraserToolOptions = {}) {\r\n this.radius = options.radius ?? DEFAULT_RADIUS;\r\n this.cursor = makeEraserCursor(this.radius);\r\n this.mode = options.mode ?? 'partial';\r\n }\r\n\r\n getOptions(): EraserToolOptions {\r\n return { radius: this.radius, mode: this.mode };\r\n }\r\n\r\n setOptions(options: EraserToolOptions): void {\r\n if (options.mode !== undefined) this.mode = options.mode;\r\n if (options.radius !== undefined) {\r\n this.radius = options.radius;\r\n this.cursor = makeEraserCursor(this.radius); // applied on next activate\r\n }\r\n }\r\n\r\n onActivate(ctx: ToolContext): void {\r\n ctx.setCursor?.(this.cursor);\r\n }\r\n\r\n onDeactivate(ctx: ToolContext): void {\r\n ctx.setCursor?.('default');\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.erasing = true;\r\n this.eraseAt(state, ctx);\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.erasing) return;\r\n this.eraseAt(state, ctx);\r\n }\r\n\r\n onPointerUp(_state: PointerState, _ctx: ToolContext): void {\r\n this.erasing = false;\r\n }\r\n\r\n private eraseAt(state: PointerState, ctx: ToolContext): void {\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const worldRadius = this.radius / ctx.camera.zoom;\r\n const queryBounds: Bounds = {\r\n x: world.x - worldRadius,\r\n y: world.y - worldRadius,\r\n w: worldRadius * 2,\r\n h: worldRadius * 2,\r\n };\r\n const candidates = ctx.store.queryRect(queryBounds);\r\n let erased = false;\r\n\r\n for (const el of candidates) {\r\n if (el.type !== 'stroke') continue;\r\n if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) continue;\r\n if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) continue;\r\n if (!this.strokeIntersects(el, world, worldRadius)) continue;\r\n if (this.mode === 'stroke') {\r\n ctx.store.remove(el.id);\r\n erased = true;\r\n continue;\r\n }\r\n const localEraser = { x: world.x - el.position.x, y: world.y - el.position.y };\r\n const runs = erasePoints(el.points, localEraser, worldRadius);\r\n if (runs === null) continue;\r\n ctx.store.remove(el.id);\r\n for (const run of runs) {\r\n ctx.store.add(\r\n createStroke({\r\n points: run,\r\n color: el.color,\r\n width: el.width,\r\n opacity: el.opacity,\r\n layerId: el.layerId,\r\n zIndex: el.zIndex,\r\n position: el.position,\r\n }),\r\n );\r\n }\r\n erased = true;\r\n }\r\n\r\n if (erased) ctx.requestRender();\r\n }\r\n\r\n private strokeIntersects(stroke: StrokeElement, point: Point, worldRadius: number): boolean {\r\n return hitTestStroke(stroke, point, worldRadius);\r\n }\r\n}\r\n","import type { CanvasElement } from './types';\r\n\r\n/** Expand a selection to include every co-member of any group it touches. Returns `ids`\r\n * unchanged (same reference) when no selected element is grouped. */\r\nexport function expandToGroups(ids: string[], elements: CanvasElement[]): string[] {\r\n const byId = new Map(elements.map((e) => [e.id, e]));\r\n const groupIds = new Set<string>();\r\n for (const id of ids) {\r\n const g = byId.get(id)?.groupId;\r\n if (g) groupIds.add(g);\r\n }\r\n if (groupIds.size === 0) return ids;\r\n const idSet = new Set(ids);\r\n const result = [...ids];\r\n for (const el of elements) {\r\n if (el.groupId && groupIds.has(el.groupId) && !idSet.has(el.id)) {\r\n result.push(el.id);\r\n idSet.add(el.id);\r\n }\r\n }\r\n return result;\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { ArrowElement, CanvasElement } from '../elements/types';\r\nimport type { ToolContext } from './types';\r\nimport { getArrowMidpoint, getBendFromPoint } from '../elements/arrow-geometry';\r\nimport { findBindTarget, getElementCenter } from '../elements/arrow-binding';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\n\r\nconst BIND_THRESHOLD = 20;\r\n\r\nexport type ArrowHandle = 'start' | 'mid' | 'end';\r\n\r\nconst HANDLE_RADIUS = 5;\r\nconst HANDLE_HIT_PADDING = 4;\r\n\r\nconst ARROW_HANDLE_CURSORS: Record<ArrowHandle, string> = {\r\n start: 'crosshair',\r\n end: 'crosshair',\r\n mid: 'grab',\r\n};\r\n\r\nexport function getArrowHandleCursor(handle: ArrowHandle, active: boolean): string {\r\n if (handle === 'mid' && active) return 'grabbing';\r\n return ARROW_HANDLE_CURSORS[handle];\r\n}\r\n\r\nexport function getArrowHandlePositions(arrow: ArrowElement): [ArrowHandle, Point][] {\r\n const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);\r\n return [\r\n ['start', arrow.from],\r\n ['mid', mid],\r\n ['end', arrow.to],\r\n ];\r\n}\r\n\r\nexport function hitTestArrowHandles(\r\n world: Point,\r\n selectedIds: string[],\r\n ctx: ToolContext,\r\n): { elementId: string; handle: ArrowHandle } | null {\r\n if (selectedIds.length === 0) return null;\r\n\r\n const zoom = ctx.camera.zoom;\r\n const hitRadius = (HANDLE_RADIUS + HANDLE_HIT_PADDING) / zoom;\r\n\r\n for (const id of selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || el.type !== 'arrow') continue;\r\n\r\n const handles = getArrowHandlePositions(el);\r\n for (const [handle, pos] of handles) {\r\n const dx = world.x - pos.x;\r\n const dy = world.y - pos.y;\r\n if (dx * dx + dy * dy <= hitRadius * hitRadius) {\r\n return { elementId: id, handle };\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport function applyArrowHandleDrag(\r\n handle: ArrowHandle,\r\n elementId: string,\r\n world: Point,\r\n ctx: ToolContext,\r\n): void {\r\n const el = ctx.store.getById(elementId);\r\n if (!el || el.type !== 'arrow') return;\r\n\r\n const threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n\r\n const layerFilter = (candidate: CanvasElement) => candidate.layerId === el.layerId;\r\n\r\n switch (handle) {\r\n case 'start': {\r\n const excludeId = el.toBinding?.elementId;\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);\r\n if (target) {\r\n const center = getElementCenter(target);\r\n ctx.store.update(elementId, {\r\n from: center,\r\n position: center,\r\n fromBinding: { elementId: target.id },\r\n });\r\n } else {\r\n ctx.store.update(elementId, {\r\n from: { x: world.x, y: world.y },\r\n position: { x: world.x, y: world.y },\r\n fromBinding: undefined,\r\n });\r\n }\r\n break;\r\n }\r\n case 'end': {\r\n const excludeId = el.fromBinding?.elementId;\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);\r\n if (target) {\r\n const center = getElementCenter(target);\r\n ctx.store.update(elementId, {\r\n to: center,\r\n toBinding: { elementId: target.id },\r\n });\r\n } else {\r\n ctx.store.update(elementId, {\r\n to: { x: world.x, y: world.y },\r\n toBinding: undefined,\r\n });\r\n }\r\n break;\r\n }\r\n case 'mid': {\r\n const bend = getBendFromPoint(el.from, el.to, world);\r\n ctx.store.update(elementId, { bend });\r\n break;\r\n }\r\n }\r\n\r\n ctx.requestRender();\r\n}\r\n\r\nexport function getArrowHandleDragTarget(\r\n handle: ArrowHandle,\r\n elementId: string,\r\n world: Point,\r\n ctx: ToolContext,\r\n): { x: number; y: number; w: number; h: number } | null {\r\n if (handle === 'mid') return null;\r\n\r\n const el = ctx.store.getById(elementId);\r\n if (!el || el.type !== 'arrow') return null;\r\n\r\n const threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n const excludeId = handle === 'start' ? el.toBinding?.elementId : el.fromBinding?.elementId;\r\n const layerFilter = (candidate: CanvasElement) => candidate.layerId === el.layerId;\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);\r\n if (!target) return null;\r\n\r\n return getElementBounds(target);\r\n}\r\n\r\nexport function renderArrowHandles(\r\n canvasCtx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n zoom: number,\r\n): void {\r\n const radius = HANDLE_RADIUS / zoom;\r\n const handles = getArrowHandlePositions(arrow);\r\n\r\n canvasCtx.setLineDash([]);\r\n canvasCtx.lineWidth = 1.5 / zoom;\r\n\r\n for (const [handle, pos] of handles) {\r\n canvasCtx.fillStyle = handle === 'mid' ? '#2196F3' : '#ffffff';\r\n canvasCtx.strokeStyle = '#2196F3';\r\n\r\n canvasCtx.beginPath();\r\n canvasCtx.arc(pos.x, pos.y, radius, 0, Math.PI * 2);\r\n canvasCtx.fill();\r\n canvasCtx.stroke();\r\n }\r\n}\r\n","import type { Bounds } from '../core/types';\r\n\r\nexport interface SnapGuide {\r\n axis: 'x' | 'y';\r\n position: number;\r\n}\r\nexport interface SnapResult {\r\n dx: number;\r\n dy: number;\r\n guides: SnapGuide[];\r\n}\r\n\r\ninterface AxisAnchors {\r\n lo: number;\r\n mid: number;\r\n hi: number;\r\n}\r\n\r\nfunction xAnchors(b: Bounds): AxisAnchors {\r\n return { lo: b.x, mid: b.x + b.w / 2, hi: b.x + b.w };\r\n}\r\n\r\nfunction yAnchors(b: Bounds): AxisAnchors {\r\n return { lo: b.y, mid: b.y + b.h / 2, hi: b.y + b.h };\r\n}\r\n\r\nfunction bestAxisSnap(\r\n moving: AxisAnchors,\r\n targets: Bounds[],\r\n anchorsFn: (b: Bounds) => AxisAnchors,\r\n threshold: number,\r\n): { delta: number; position: number } | null {\r\n let best: { delta: number; position: number } | null = null;\r\n\r\n for (const t of targets) {\r\n const ta = anchorsFn(t);\r\n const pairs: [number, number][] = [\r\n // colinear alignment: same-type edges/centers line up\r\n [ta.lo - moving.lo, ta.lo],\r\n [ta.mid - moving.mid, ta.mid],\r\n [ta.hi - moving.hi, ta.hi],\r\n // abutment: the moving box sits flush against the target's opposite edge\r\n [ta.lo - moving.hi, ta.lo],\r\n [ta.hi - moving.lo, ta.hi],\r\n ];\r\n\r\n for (const [delta, position] of pairs) {\r\n const abs = Math.abs(delta);\r\n if (abs <= threshold && (best === null || abs < Math.abs(best.delta))) {\r\n best = { delta, position };\r\n }\r\n }\r\n }\r\n\r\n return best;\r\n}\r\n\r\nexport function computeSnapGuides(\r\n moving: Bounds,\r\n targets: Bounds[],\r\n threshold: number,\r\n): SnapResult {\r\n const xSnap = bestAxisSnap(xAnchors(moving), targets, xAnchors, threshold);\r\n const ySnap = bestAxisSnap(yAnchors(moving), targets, yAnchors, threshold);\r\n\r\n const guides: SnapGuide[] = [];\r\n if (xSnap) guides.push({ axis: 'x', position: xSnap.position });\r\n if (ySnap) guides.push({ axis: 'y', position: ySnap.position });\r\n\r\n return { dx: xSnap?.delta ?? 0, dy: ySnap?.delta ?? 0, guides };\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport type { CanvasElement, ArrowElement } from '../elements/types';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { SnapGuide } from '../elements/snap-guides';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { rotatePoint } from '../core/geometry';\r\nimport { lineEndpoints } from '../elements/shape-geometry';\r\nimport { renderArrowHandles } from './arrow-handles';\r\n\r\nexport type HandlePosition = 'nw' | 'ne' | 'sw' | 'se';\r\n\r\nexport const HANDLE_SIZE = 8;\r\nexport const HANDLE_HIT_PADDING = 4;\r\nexport const SELECTION_PAD = 4;\r\nexport const ROTATE_HANDLE_OFFSET = 24;\r\nexport const ROTATABLE_TYPES = new Set(['note', 'text', 'image', 'html', 'shape', 'stroke']);\r\n\r\nexport const 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\nexport interface OverlayLayout {\r\n center: Point;\r\n corners: [HandlePosition, Point][];\r\n rotateHandle: Point;\r\n angle: number;\r\n}\r\n\r\nexport function getOverlayLayout(el: CanvasElement, zoom: number): OverlayLayout | null {\r\n const bounds = getElementBounds(el);\r\n if (!bounds) return null;\r\n const angle = el.rotation ?? 0;\r\n const pad = SELECTION_PAD / zoom;\r\n const center = { x: bounds.x + bounds.w / 2, y: bounds.y + bounds.h / 2 };\r\n const raw: [HandlePosition, Point][] = [\r\n ['nw', { x: bounds.x - pad, y: bounds.y - pad }],\r\n ['ne', { x: bounds.x + bounds.w + pad, y: bounds.y - pad }],\r\n ['sw', { x: bounds.x - pad, y: bounds.y + bounds.h + pad }],\r\n ['se', { x: bounds.x + bounds.w + pad, y: bounds.y + bounds.h + pad }],\r\n ];\r\n const corners = raw.map(\r\n ([h, p]) => [h, rotatePoint(p, center, angle)] as [HandlePosition, Point],\r\n );\r\n const topMid = { x: center.x, y: bounds.y - pad - ROTATE_HANDLE_OFFSET / zoom };\r\n const rotateHandle = rotatePoint(topMid, center, angle);\r\n return { center, corners, rotateHandle, angle };\r\n}\r\n\r\nexport function getHandlePositions(bounds: Bounds): [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\nexport function topMidpoint(layout: { corners: [HandlePosition, Point][] }): Point {\r\n const nw = layout.corners.find(([h]) => h === 'nw')?.[1] ?? { x: 0, y: 0 };\r\n const ne = layout.corners.find(([h]) => h === 'ne')?.[1] ?? { x: 0, y: 0 };\r\n return { x: (nw.x + ne.x) / 2, y: (nw.y + ne.y) / 2 };\r\n}\r\n\r\nexport function drawLockBadge(ctx: CanvasRenderingContext2D, at: Point, zoom: number): void {\r\n const r = 9 / zoom;\r\n ctx.save();\r\n ctx.setLineDash([]);\r\n ctx.beginPath();\r\n ctx.arc(at.x, at.y, r, 0, Math.PI * 2);\r\n ctx.fillStyle = '#ffffff';\r\n ctx.fill();\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.lineWidth = 1.5 / zoom;\r\n ctx.stroke();\r\n const bw = 8 / zoom;\r\n const bh = 6 / zoom;\r\n ctx.fillStyle = '#2196F3';\r\n ctx.fillRect(at.x - bw / 2, at.y - bh / 2 + 1 / zoom, bw, bh);\r\n ctx.beginPath();\r\n ctx.arc(at.x, at.y - bh / 2 + 1 / zoom, 2.5 / zoom, Math.PI, 0);\r\n ctx.lineWidth = 1.4 / zoom;\r\n ctx.stroke();\r\n ctx.restore();\r\n}\r\n\r\nexport function renderMarquee(ctx: CanvasRenderingContext2D, rect: Bounds): void {\r\n ctx.save();\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.fillStyle = 'rgba(33, 150, 243, 0.08)';\r\n ctx.lineWidth = 1;\r\n ctx.setLineDash([4, 4]);\r\n ctx.strokeRect(rect.x, rect.y, rect.w, rect.h);\r\n ctx.fillRect(rect.x, rect.y, rect.w, rect.h);\r\n ctx.restore();\r\n}\r\n\r\nexport function renderBindingHighlights(\r\n ctx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n zoom: number,\r\n store: ElementStore,\r\n): void {\r\n if (!arrow.fromBinding && !arrow.toBinding) return;\r\n\r\n const pad = SELECTION_PAD / zoom;\r\n\r\n ctx.save();\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.lineWidth = 2 / zoom;\r\n ctx.setLineDash([]);\r\n\r\n const drawn = new Set<string>();\r\n for (const binding of [arrow.fromBinding, arrow.toBinding]) {\r\n if (!binding || drawn.has(binding.elementId)) continue;\r\n drawn.add(binding.elementId);\r\n\r\n const target = store.getById(binding.elementId);\r\n if (!target) continue;\r\n\r\n const bounds = getElementBounds(target);\r\n if (!bounds) continue;\r\n\r\n ctx.strokeRect(bounds.x - pad, bounds.y - pad, bounds.w + pad * 2, bounds.h + pad * 2);\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nexport function renderSelectionBoxes(\r\n ctx: CanvasRenderingContext2D,\r\n p: { selectedIds: string[]; store: ElementStore; zoom: number },\r\n): void {\r\n if (p.selectedIds.length === 0) return;\r\n\r\n const zoom = p.zoom;\r\n const handleWorldSize = HANDLE_SIZE / zoom;\r\n\r\n ctx.save();\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.lineWidth = 1.5 / zoom;\r\n ctx.setLineDash([4 / zoom, 4 / zoom]);\r\n\r\n for (const id of p.selectedIds) {\r\n const el = p.store.getById(id);\r\n if (!el) continue;\r\n\r\n if (el.type === 'arrow') {\r\n renderArrowHandles(ctx, el, zoom);\r\n renderBindingHighlights(ctx, el, zoom, p.store);\r\n continue;\r\n }\r\n\r\n if (el.type === 'shape' && el.shape === 'line') {\r\n ctx.setLineDash([]);\r\n ctx.fillStyle = '#ffffff';\r\n const r = handleWorldSize / 2;\r\n for (const pt of lineEndpoints(el)) {\r\n ctx.beginPath();\r\n ctx.arc(pt.x, pt.y, r, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.stroke();\r\n }\r\n ctx.setLineDash([4 / zoom, 4 / zoom]);\r\n continue;\r\n }\r\n\r\n const bounds = getElementBounds(el);\r\n if (!bounds) continue;\r\n\r\n const layout = getOverlayLayout(el, zoom);\r\n if (!layout) continue;\r\n\r\n const pad = SELECTION_PAD / zoom;\r\n if (layout.angle === 0) {\r\n ctx.strokeRect(bounds.x - pad, bounds.y - pad, bounds.w + pad * 2, bounds.h + pad * 2);\r\n } else {\r\n const ordered = (['nw', 'ne', 'se', 'sw'] as HandlePosition[])\r\n .map((h) => layout.corners.find(([c]) => c === h)?.[1])\r\n .filter((pp): pp is Point => !!pp);\r\n const [p0, ...others] = ordered;\r\n if (p0) {\r\n ctx.beginPath();\r\n ctx.moveTo(p0.x, p0.y);\r\n for (const pp of others) ctx.lineTo(pp.x, pp.y);\r\n ctx.closePath();\r\n ctx.stroke();\r\n }\r\n }\r\n\r\n if (!el.locked) {\r\n if ('size' in el) {\r\n ctx.setLineDash([]);\r\n ctx.fillStyle = '#ffffff';\r\n const corners = layout.angle === 0 ? getHandlePositions(bounds) : layout.corners;\r\n for (const [, pos] of corners) {\r\n ctx.fillRect(\r\n pos.x - handleWorldSize / 2,\r\n pos.y - handleWorldSize / 2,\r\n handleWorldSize,\r\n handleWorldSize,\r\n );\r\n ctx.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 ctx.setLineDash([4 / zoom, 4 / zoom]);\r\n } else if (el.type === 'template') {\r\n ctx.setLineDash([]);\r\n ctx.fillStyle = '#ffffff';\r\n const hx = bounds.x + bounds.w;\r\n const hy = bounds.y + bounds.h;\r\n ctx.fillRect(\r\n hx - handleWorldSize / 2,\r\n hy - handleWorldSize / 2,\r\n handleWorldSize,\r\n handleWorldSize,\r\n );\r\n ctx.strokeRect(\r\n hx - handleWorldSize / 2,\r\n hy - handleWorldSize / 2,\r\n handleWorldSize,\r\n handleWorldSize,\r\n );\r\n ctx.setLineDash([4 / zoom, 4 / zoom]);\r\n }\r\n\r\n if (p.selectedIds.length === 1 && ROTATABLE_TYPES.has(el.type)) {\r\n const stemStart = topMidpoint(layout);\r\n const stemEnd = layout.rotateHandle;\r\n ctx.beginPath();\r\n ctx.moveTo(stemStart.x, stemStart.y);\r\n ctx.lineTo(stemEnd.x, stemEnd.y);\r\n ctx.stroke();\r\n\r\n ctx.setLineDash([]);\r\n ctx.fillStyle = '#ffffff';\r\n ctx.beginPath();\r\n ctx.arc(stemEnd.x, stemEnd.y, handleWorldSize / 2, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.stroke();\r\n ctx.setLineDash([4 / zoom, 4 / zoom]);\r\n }\r\n }\r\n\r\n if (el.locked) {\r\n const ne = layout.corners.find(([h]) => h === 'ne')?.[1];\r\n if (ne) drawLockBadge(ctx, ne, zoom);\r\n }\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nexport function renderGuideLines(\r\n ctx: CanvasRenderingContext2D,\r\n p: { guides: SnapGuide[]; rect: Bounds | null; currentWorld: Point; zoom: number },\r\n): void {\r\n const zoom = p.zoom;\r\n const rect = p.rect; // cached at drag start (same source as the candidate query)\r\n ctx.save();\r\n ctx.strokeStyle = '#FF4081';\r\n ctx.lineWidth = 1 / zoom;\r\n ctx.setLineDash([]);\r\n for (const g of p.guides) {\r\n ctx.beginPath();\r\n if (g.axis === 'x') {\r\n const y0 = rect ? rect.y : p.currentWorld.y - 1e5;\r\n const y1 = rect ? rect.y + rect.h : p.currentWorld.y + 1e5;\r\n ctx.moveTo(g.position, y0);\r\n ctx.lineTo(g.position, y1);\r\n } else {\r\n const x0 = rect ? rect.x : p.currentWorld.x - 1e5;\r\n const x1 = rect ? rect.x + rect.w : p.currentWorld.x + 1e5;\r\n ctx.moveTo(x0, g.position);\r\n ctx.lineTo(x1, g.position);\r\n }\r\n ctx.stroke();\r\n }\r\n ctx.restore();\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport type { ToolContext } from './types';\r\nimport { distSqToSegment, rotatePoint, rotatedAABB } from '../core/geometry';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { isNearBezier } from '../elements/arrow-geometry';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { hitTestStroke } from '../elements/stroke-hit';\r\nimport { lineEndpoints } from '../elements/shape-geometry';\r\nimport type { HandlePosition } from './select-overlay';\r\nimport {\r\n HANDLE_SIZE,\r\n HANDLE_HIT_PADDING,\r\n ROTATABLE_TYPES,\r\n getOverlayLayout,\r\n} from './select-overlay';\r\n\r\nexport function hitTest(world: Point, ctx: ToolContext): CanvasElement | null {\r\n // Inflate query by hit radius so strokes/arrows near the point are included\r\n const r = 10;\r\n const candidates = ctx.store\r\n .queryRect({ x: world.x - r, y: world.y - r, w: r * 2, h: r * 2 })\r\n .reverse();\r\n for (const el of candidates) {\r\n if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) continue;\r\n if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) continue;\r\n if (el.type === 'grid') continue;\r\n if (isInsideBounds(world, el)) return el;\r\n }\r\n return null;\r\n}\r\n\r\nexport function isInsideBounds(point: Point, el: CanvasElement): boolean {\r\n if (el.type === 'grid') return false;\r\n const angle = el.rotation ?? 0;\r\n if (angle !== 0) {\r\n const b = getElementBounds(el);\r\n if (b) {\r\n point = rotatePoint(point, { x: b.x + b.w / 2, y: b.y + b.h / 2 }, -angle);\r\n }\r\n }\r\n if (el.type === 'shape' && el.shape === 'line') {\r\n const [a, b] = lineEndpoints(el);\r\n const threshold = Math.max(el.strokeWidth / 2, 6);\r\n return distSqToSegment(point, a, b) <= threshold * threshold;\r\n }\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 return hitTestStroke(el, point, 10);\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 if (el.type === 'template') {\r\n const bounds = getElementBounds(el);\r\n if (!bounds) return false;\r\n return (\r\n point.x >= bounds.x &&\r\n point.x <= bounds.x + bounds.w &&\r\n point.y >= bounds.y &&\r\n point.y <= bounds.y + bounds.h\r\n );\r\n }\r\n\r\n return false;\r\n}\r\n\r\nexport function hitTestResizeHandle(\r\n world: Point,\r\n ctx: ToolContext,\r\n selectedIds: string[],\r\n): { elementId: string; handle: HandlePosition } | null {\r\n if (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 selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || !('size' in el)) continue;\r\n if (el.locked) continue;\r\n if (el.type === 'shape' && el.shape === 'line') continue;\r\n\r\n const layout = getOverlayLayout(el, zoom);\r\n if (!layout) continue;\r\n for (const [handle, pos] of layout.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\nexport function hitTestRotateHandle(\r\n world: Point,\r\n ctx: ToolContext,\r\n selectedIds: string[],\r\n): { elementId: string } | null {\r\n if (selectedIds.length !== 1) return null;\r\n const id = selectedIds[0];\r\n if (!id) return null;\r\n const el = ctx.store.getById(id);\r\n if (!el || el.locked || !ROTATABLE_TYPES.has(el.type)) return null;\r\n const layout = getOverlayLayout(el, ctx.camera.zoom);\r\n if (!layout) return null;\r\n const r = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / ctx.camera.zoom;\r\n const dx = world.x - layout.rotateHandle.x;\r\n const dy = world.y - layout.rotateHandle.y;\r\n return dx * dx + dy * dy <= r * r ? { elementId: id } : null;\r\n}\r\n\r\nexport function hitTestLineHandles(\r\n world: Point,\r\n ctx: ToolContext,\r\n selectedIds: string[],\r\n): { elementId: string; fixed: Point } | null {\r\n if (selectedIds.length === 0) return null;\r\n const zoom = ctx.camera.zoom;\r\n const r = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / zoom;\r\n const r2 = r * r;\r\n for (const id of selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || el.type !== 'shape' || el.shape !== 'line') continue;\r\n const [a, b] = lineEndpoints(el);\r\n if ((world.x - a.x) ** 2 + (world.y - a.y) ** 2 <= r2) return { elementId: id, fixed: b };\r\n if ((world.x - b.x) ** 2 + (world.y - b.y) ** 2 <= r2) return { elementId: id, fixed: a };\r\n }\r\n return null;\r\n}\r\n\r\nexport function hitTestTemplateResizeHandle(\r\n world: Point,\r\n ctx: ToolContext,\r\n selectedIds: string[],\r\n): string | null {\r\n if (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 selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || el.type !== 'template') continue;\r\n\r\n const bounds = getElementBounds(el);\r\n if (!bounds) continue;\r\n\r\n const hx = bounds.x + bounds.w;\r\n const hy = bounds.y + bounds.h;\r\n if (Math.abs(world.x - hx) <= handleHalf && Math.abs(world.y - hy) <= handleHalf) {\r\n return id;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport function findElementsInRect(marquee: Bounds, ctx: ToolContext): string[] {\r\n const candidates = ctx.store.queryRect(marquee);\r\n const ids: string[] = [];\r\n for (const el of candidates) {\r\n if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) continue;\r\n if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) continue;\r\n if (el.type === 'grid') continue;\r\n const bounds = getElementBounds(el);\r\n if (bounds && rectsOverlap(marquee, rotatedAABB(bounds, el.rotation ?? 0))) {\r\n ids.push(el.id);\r\n }\r\n }\r\n return ids;\r\n}\r\n\r\nexport function rectsOverlap(a: Bounds, b: Bounds): 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","import type { Point } from '../core/types';\r\nimport type { CanvasElement, TemplateElement } from '../elements/types';\r\nimport { rotatePoint } from '../core/geometry';\r\nimport type { HandlePosition } from './select-overlay';\r\n\r\nexport const MIN_ELEMENT_SIZE = 20;\r\n\r\nexport function anchorOffset(handle: HandlePosition, w: number, h: number): Point {\r\n switch (handle) {\r\n case 'se':\r\n return { x: -w / 2, y: -h / 2 };\r\n case 'sw':\r\n return { x: w / 2, y: -h / 2 };\r\n case 'ne':\r\n return { x: -w / 2, y: h / 2 };\r\n case 'nw':\r\n return { x: w / 2, y: h / 2 };\r\n default:\r\n return { x: 0, y: 0 };\r\n }\r\n}\r\n\r\nexport function computeResize(\r\n el: CanvasElement & { size: { w: number; h: number } },\r\n handle: HandlePosition,\r\n world: Point,\r\n lastWorld: Point,\r\n aspectRatio: number,\r\n shiftKey: boolean,\r\n): { position: { x: number; y: number }; size: { w: number; h: number } } {\r\n const dx = world.x - lastWorld.x;\r\n const dy = world.y - lastWorld.y;\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 (shiftKey && aspectRatio > 0) {\r\n const absDw = Math.abs(w - el.size.w);\r\n const absDh = Math.abs(h - el.size.h);\r\n if (absDw >= absDh) {\r\n h = w / aspectRatio;\r\n } else {\r\n w = h * aspectRatio;\r\n }\r\n if (handle === 'nw' || handle === 'sw') {\r\n x = el.position.x + el.size.w - w;\r\n }\r\n if (handle === 'nw' || handle === 'ne') {\r\n y = el.position.y + el.size.h - h;\r\n }\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 return { position: { x, y }, size: { w, h } };\r\n}\r\n\r\nexport function computeRotatedResize(\r\n el: CanvasElement & { size: { w: number; h: number } },\r\n handle: HandlePosition,\r\n angle: number,\r\n world: Point,\r\n lastWorld: Point,\r\n aspectRatio: number,\r\n shiftKey: boolean,\r\n): { position: { x: number; y: number }; size: { w: number; h: number } } {\r\n const wdx = world.x - lastWorld.x;\r\n const wdy = world.y - lastWorld.y;\r\n\r\n // world delta → element local frame (inverse rotation of the vector)\r\n const cosN = Math.cos(-angle);\r\n const sinN = Math.sin(-angle);\r\n const ldx = wdx * cosN - wdy * sinN;\r\n const ldy = wdx * sinN + wdy * cosN;\r\n\r\n let w = el.size.w;\r\n let h = el.size.h;\r\n switch (handle) {\r\n case 'se':\r\n w += ldx;\r\n h += ldy;\r\n break;\r\n case 'sw':\r\n w -= ldx;\r\n h += ldy;\r\n break;\r\n case 'ne':\r\n w += ldx;\r\n h -= ldy;\r\n break;\r\n case 'nw':\r\n w -= ldx;\r\n h -= ldy;\r\n break;\r\n }\r\n\r\n if (shiftKey && aspectRatio > 0) {\r\n const absDw = Math.abs(w - el.size.w);\r\n const absDh = Math.abs(h - el.size.h);\r\n if (absDw >= absDh) h = w / aspectRatio;\r\n else w = h * aspectRatio;\r\n }\r\n w = Math.max(w, MIN_ELEMENT_SIZE);\r\n h = Math.max(h, MIN_ELEMENT_SIZE);\r\n\r\n // anchor (opposite corner) fixed in world space, computed from OLD geometry\r\n const oldCenter = { x: el.position.x + el.size.w / 2, y: el.position.y + el.size.h / 2 };\r\n const oldAnchorLocal = anchorOffset(handle, el.size.w, el.size.h);\r\n const anchorWorld = rotatePoint(\r\n { x: oldCenter.x + oldAnchorLocal.x, y: oldCenter.y + oldAnchorLocal.y },\r\n oldCenter,\r\n angle,\r\n );\r\n\r\n // new center so the anchor stays put: anchorWorld = newCenter + R(angle)·newAnchorLocal\r\n const newAnchorLocal = anchorOffset(handle, w, h);\r\n const cos = Math.cos(angle);\r\n const sin = Math.sin(angle);\r\n const rotatedAnchor = {\r\n x: newAnchorLocal.x * cos - newAnchorLocal.y * sin,\r\n y: newAnchorLocal.x * sin + newAnchorLocal.y * cos,\r\n };\r\n const newCenter = { x: anchorWorld.x - rotatedAnchor.x, y: anchorWorld.y - rotatedAnchor.y };\r\n const position = { x: newCenter.x - w / 2, y: newCenter.y - h / 2 };\r\n\r\n return { position, size: { w, h } };\r\n}\r\n\r\nexport interface TemplateResizeOptions {\r\n snapToGrid?: boolean;\r\n gridSize?: number;\r\n gridType?: 'square' | 'hex';\r\n}\r\n\r\nexport function computeTemplateResize(\r\n el: TemplateElement,\r\n world: Point,\r\n opts: TemplateResizeOptions,\r\n): Record<string, unknown> | null {\r\n const dx = world.x - el.position.x;\r\n const dy = world.y - el.position.y;\r\n let newRadius = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (opts.snapToGrid && opts.gridSize && opts.gridSize > 0) {\r\n const snapUnit = opts.gridType === 'hex' ? Math.sqrt(3) * opts.gridSize : opts.gridSize;\r\n newRadius = Math.max(snapUnit, Math.round(newRadius / snapUnit) * snapUnit);\r\n }\r\n newRadius = Math.max(MIN_ELEMENT_SIZE, newRadius);\r\n\r\n const updates: Record<string, unknown> = { radius: newRadius };\r\n if (el.feetPerCell != null && opts.gridSize && opts.gridSize > 0) {\r\n const snapUnit = opts.gridType === 'hex' ? Math.sqrt(3) * opts.gridSize : opts.gridSize;\r\n updates.radiusFeet = (newRadius / snapUnit) * el.feetPerCell;\r\n }\r\n\r\n return updates;\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { smartSnap } from '../core/snap';\r\nimport { normalizeAngle } from '../core/geometry';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { updateArrowsBoundToElements } from '../elements/arrow-binding';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { expandToGroups } from '../elements/group';\r\nimport { getElementsBoundingBox } from '../elements/bounds';\r\nimport { lineFromEndpoints } from '../elements/shape-geometry';\r\nimport { translateElementPatch } from '../elements/translate';\r\nimport {\r\n type ArrowHandle,\r\n hitTestArrowHandles,\r\n applyArrowHandleDrag,\r\n getArrowHandleCursor,\r\n getArrowHandleDragTarget,\r\n} from './arrow-handles';\r\nimport { computeSnapGuides } from '../elements/snap-guides';\r\nimport type { SnapGuide } from '../elements/snap-guides';\r\nimport {\r\n hitTest,\r\n hitTestResizeHandle,\r\n hitTestRotateHandle,\r\n hitTestLineHandles,\r\n hitTestTemplateResizeHandle,\r\n findElementsInRect,\r\n} from './select-hit';\r\nimport type { HandlePosition, OverlayLayout } from './select-overlay';\r\nimport {\r\n HANDLE_CURSORS,\r\n getOverlayLayout,\r\n renderMarquee,\r\n renderSelectionBoxes,\r\n renderGuideLines,\r\n} from './select-overlay';\r\nimport { computeResize, computeRotatedResize, computeTemplateResize } from './select-resize';\r\n\r\nconst SNAP_PX = 6;\r\nconst ROTATE_SNAP = Math.PI / 12; // 15°\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: 'resizing-template'; elementId: string }\r\n | { type: 'arrow-handle'; elementId: string; handle: ArrowHandle }\r\n | { type: 'line-handle'; elementId: string; fixed: Point }\r\n | {\r\n type: 'rotating';\r\n elementId: string;\r\n center: Point;\r\n startPointerAngle: number;\r\n startRotation: number;\r\n };\r\n\r\nexport class SelectTool implements Tool {\r\n readonly name = 'select';\r\n private _selectedIds: string[] = [];\r\n private selectionListeners = new Set<() => void>();\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 private pendingSingleSelectId: string | null = null;\r\n private hasDragged = false;\r\n private activeGuides: SnapGuide[] = [];\r\n private dragSnapTargets: Bounds[] | null = null;\r\n private dragVisibleRect: Bounds | null = null;\r\n private resizeAspectRatio = 0;\r\n private hoveredId: string | null = null;\r\n\r\n get selectedIds(): string[] {\r\n return this._selectedIds;\r\n }\r\n\r\n onSelectionChange(listener: () => void): () => void {\r\n this.selectionListeners.add(listener);\r\n return () => {\r\n this.selectionListeners.delete(listener);\r\n };\r\n }\r\n\r\n private setSelectedIds(ids: string[]): void {\r\n const prev = this._selectedIds;\r\n if (prev.length === ids.length && prev.every((id, i) => id === ids[i])) return;\r\n this._selectedIds = ids;\r\n for (const listener of this.selectionListeners) listener();\r\n }\r\n\r\n setSelection(ids: string[]): void {\r\n this.setSelectedIds(ids);\r\n this.ctx?.requestRender();\r\n }\r\n\r\n selectAtPoint(world: Point, ctx: ToolContext): void {\r\n const hit = hitTest(world, ctx);\r\n if (!hit) {\r\n this.setSelectedIds([]);\r\n return;\r\n }\r\n if (this._selectedIds.includes(hit.id)) return;\r\n this.setSelectedIds(expandToGroups([hit.id], ctx.store.getAll()));\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.setSelectedIds([]);\r\n this.mode = { type: 'idle' };\r\n this.hoveredId = null;\r\n this.activeGuides = [];\r\n this.dragSnapTargets = null;\r\n this.dragVisibleRect = null;\r\n ctx.setCursor?.('default');\r\n }\r\n\r\n private snap(point: Point, ctx: ToolContext): Point {\r\n return smartSnap(point, ctx);\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.ctx = ctx;\r\n this.setHovered(null, ctx);\r\n this.dragSnapTargets = null;\r\n this.dragVisibleRect = null;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.lastWorld = this.snap(world, ctx);\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 lineHit = hitTestLineHandles(world, ctx, this._selectedIds);\r\n if (lineHit) {\r\n this.mode = { type: 'line-handle', elementId: lineHit.elementId, fixed: lineHit.fixed };\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n const templateResizeHit = hitTestTemplateResizeHandle(world, ctx, this._selectedIds);\r\n if (templateResizeHit) {\r\n this.mode = { type: 'resizing-template', elementId: templateResizeHit };\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n const rotateHit = hitTestRotateHandle(world, ctx, this._selectedIds);\r\n if (rotateHit) {\r\n const el = ctx.store.getById(rotateHit.elementId);\r\n const layout = el ? this.getOverlayLayout(el, ctx.camera.zoom) : null;\r\n if (el && layout) {\r\n this.mode = {\r\n type: 'rotating',\r\n elementId: rotateHit.elementId,\r\n center: layout.center,\r\n startPointerAngle: Math.atan2(world.y - layout.center.y, world.x - layout.center.x),\r\n startRotation: el.rotation ?? 0,\r\n };\r\n ctx.requestRender();\r\n return;\r\n }\r\n }\r\n\r\n const resizeHit = hitTestResizeHandle(world, ctx, this._selectedIds);\r\n if (resizeHit) {\r\n const el = ctx.store.getById(resizeHit.elementId);\r\n if (el && 'size' in el) {\r\n this.resizeAspectRatio = el.size.h > 0 ? el.size.w / el.size.h : 0;\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 this.pendingSingleSelectId = null;\r\n this.hasDragged = false;\r\n const hit = hitTest(world, ctx);\r\n if (hit) {\r\n const all = ctx.store.getAll();\r\n const alreadySelected = this._selectedIds.includes(hit.id);\r\n if (state.shiftKey) {\r\n if (alreadySelected) {\r\n const grp = new Set(expandToGroups([hit.id], all));\r\n this.setSelectedIds(this._selectedIds.filter((id) => !grp.has(id)));\r\n this.mode = { type: 'idle' };\r\n } else {\r\n this.setSelectedIds(expandToGroups([...this._selectedIds, hit.id], all));\r\n this.mode = hit.locked ? { type: 'idle' } : { type: 'dragging' };\r\n }\r\n } else {\r\n if (!alreadySelected) {\r\n this.setSelectedIds(expandToGroups([hit.id], all));\r\n } else if (this._selectedIds.length > 1) {\r\n this.pendingSingleSelectId = hit.id;\r\n }\r\n this.mode = hit.locked ? { type: 'idle' } : { type: 'dragging' };\r\n }\r\n } else {\r\n this.setSelectedIds([]);\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 === 'line-handle') {\r\n ctx.setCursor?.('grabbing');\r\n const el = ctx.store.getById(this.mode.elementId);\r\n if (el && el.type === 'shape') {\r\n ctx.store.update(el.id, lineFromEndpoints(this.mode.fixed, world));\r\n }\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'resizing-template') {\r\n ctx.setCursor?.('nwse-resize');\r\n this.handleTemplateResize(world, ctx);\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'rotating') {\r\n const { elementId, center, startPointerAngle, startRotation } = this.mode;\r\n const a = Math.atan2(world.y - center.y, world.x - center.x);\r\n let next = startRotation + (a - startPointerAngle);\r\n if (state.shiftKey) next = Math.round(next / ROTATE_SNAP) * ROTATE_SNAP;\r\n ctx.store.update(elementId, { rotation: normalizeAngle(next) });\r\n ctx.requestRender();\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, state.shiftKey);\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'dragging' && this._selectedIds.length > 0) {\r\n this.hasDragged = true;\r\n ctx.setCursor?.('move');\r\n const snapped = this.snap(world, ctx);\r\n const dx = snapped.x - this.lastWorld.x;\r\n const dy = snapped.y - this.lastWorld.y;\r\n this.lastWorld = snapped;\r\n\r\n let adjDx = dx;\r\n let adjDy = dy;\r\n this.activeGuides = [];\r\n if (ctx.smartGuides) {\r\n // Candidates (non-selected visible elements) and the viewport rect don't change\r\n // during a single-pointer drag, so compute them once per drag and reuse each frame.\r\n if (this.dragSnapTargets === null) {\r\n const selSet = new Set(this._selectedIds);\r\n this.dragVisibleRect = ctx.getVisibleRect?.() ?? null;\r\n const candidates = (\r\n this.dragVisibleRect ? ctx.store.queryRect(this.dragVisibleRect) : ctx.store.getAll()\r\n ).filter((el) => !selSet.has(el.id) && el.type !== 'grid');\r\n const targets: Bounds[] = [];\r\n for (const el of candidates) {\r\n const b = getElementBounds(el);\r\n if (b) targets.push(b);\r\n }\r\n this.dragSnapTargets = targets;\r\n }\r\n const selectedEls = this._selectedIds\r\n .map((id) => ctx.store.getById(id))\r\n .filter((el): el is CanvasElement => !!el && !el.locked);\r\n const base = getElementsBoundingBox(selectedEls);\r\n if (base) {\r\n const moving: Bounds = { x: base.x + dx, y: base.y + dy, w: base.w, h: base.h };\r\n const res = computeSnapGuides(moving, this.dragSnapTargets, SNAP_PX / ctx.camera.zoom);\r\n adjDx = dx + res.dx;\r\n adjDy = dy + res.dy;\r\n this.activeGuides = res.guides;\r\n }\r\n }\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 if (el.fromBinding || el.toBinding) {\r\n continue;\r\n }\r\n\r\n ctx.store.update(id, {\r\n position: { x: el.position.x + adjDx, y: el.position.y + adjDy },\r\n from: { x: el.from.x + adjDx, y: el.from.y + adjDy },\r\n to: { x: el.to.x + adjDx, y: el.to.y + adjDy },\r\n });\r\n } else if (!ctx.smartGuides && ctx.gridType && 'size' in el) {\r\n const centerX = el.position.x + el.size.w / 2 + adjDx;\r\n const centerY = el.position.y + el.size.h / 2 + adjDy;\r\n const snappedCenter = this.snap({ x: centerX, y: centerY }, ctx);\r\n ctx.store.update(id, {\r\n position: {\r\n x: snappedCenter.x - el.size.w / 2,\r\n y: snappedCenter.y - el.size.h / 2,\r\n },\r\n });\r\n } else {\r\n ctx.store.update(id, {\r\n position: { x: el.position.x + adjDx, y: el.position.y + adjDy },\r\n });\r\n }\r\n }\r\n\r\n this.updateArrowsBoundTo(this._selectedIds, ctx);\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.setSelectedIds(expandToGroups(findElementsInRect(rect, ctx), ctx.store.getAll()));\r\n }\r\n ctx.requestRender();\r\n }\r\n\r\n if (!this.hasDragged && this.pendingSingleSelectId !== null) {\r\n this.setSelectedIds(expandToGroups([this.pendingSingleSelectId], ctx.store.getAll()));\r\n }\r\n this.pendingSingleSelectId = null;\r\n this.hasDragged = false;\r\n\r\n const resizedNoteId = this.mode.type === 'resizing' ? this.mode.elementId : null;\r\n\r\n this.mode = { type: 'idle' };\r\n this.activeGuides = [];\r\n this.dragSnapTargets = null;\r\n this.dragVisibleRect = null;\r\n ctx.requestRender();\r\n ctx.setCursor?.('default');\r\n\r\n if (resizedNoteId !== null) {\r\n const el = ctx.store.getById(resizedNoteId);\r\n // Runs during tool pointer-up, inside the InputHandler resize transaction, so the\r\n // height fit coalesces into the same undo step as the resize.\r\n if (el?.type === 'note') ctx.fitNoteHeight?.(resizedNoteId);\r\n }\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 const hoverId = this.updateHoverCursor(world, ctx);\r\n this.setHovered(hoverId, ctx);\r\n }\r\n\r\n renderOverlay(canvasCtx: CanvasRenderingContext2D): void {\r\n if (this.mode.type === 'marquee') {\r\n const rect = this.getMarqueeRect();\r\n if (rect) renderMarquee(canvasCtx, rect);\r\n }\r\n if (this.ctx)\r\n renderSelectionBoxes(canvasCtx, {\r\n selectedIds: this._selectedIds,\r\n store: this.ctx.store,\r\n zoom: this.ctx.camera.zoom,\r\n });\r\n\r\n if (this.mode.type === 'arrow-handle' && this.ctx) {\r\n const target = getArrowHandleDragTarget(\r\n this.mode.handle,\r\n this.mode.elementId,\r\n this.currentWorld,\r\n this.ctx,\r\n );\r\n if (target) {\r\n canvasCtx.save();\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.lineWidth = 2 / this.ctx.camera.zoom;\r\n canvasCtx.setLineDash([]);\r\n canvasCtx.strokeRect(target.x, target.y, target.w, target.h);\r\n canvasCtx.restore();\r\n }\r\n }\r\n\r\n if (this.hoveredId && this.ctx && this.mode.type === 'idle') {\r\n if (!this._selectedIds.includes(this.hoveredId)) {\r\n const el = this.ctx.store.getById(this.hoveredId);\r\n if (el) {\r\n const b = getElementBounds(el);\r\n if (b) {\r\n canvasCtx.save();\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.globalAlpha = 0.35;\r\n canvasCtx.lineWidth = 1.5 / this.ctx.camera.zoom;\r\n canvasCtx.setLineDash([]);\r\n canvasCtx.strokeRect(b.x, b.y, b.w, b.h);\r\n canvasCtx.restore();\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (this.mode.type === 'dragging' && this.ctx && this.activeGuides.length)\r\n renderGuideLines(canvasCtx, {\r\n guides: this.activeGuides,\r\n rect: this.dragVisibleRect,\r\n currentWorld: this.currentWorld,\r\n zoom: this.ctx.camera.zoom,\r\n });\r\n }\r\n\r\n private updateArrowsBoundTo(ids: Iterable<string>, ctx: ToolContext): void {\r\n updateArrowsBoundToElements(ids, ctx.store);\r\n }\r\n\r\n nudgeSelection(dx: number, dy: number, ctx: ToolContext): boolean {\r\n let moved = false;\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 if (el.type === 'arrow' && (el.fromBinding || el.toBinding)) continue;\r\n ctx.store.update(id, translateElementPatch(el, dx, dy));\r\n moved = true;\r\n }\r\n\r\n if (moved) {\r\n this.updateArrowsBoundTo(this._selectedIds, ctx);\r\n ctx.requestRender();\r\n }\r\n return moved;\r\n }\r\n\r\n private updateHoverCursor(world: Point, ctx: ToolContext): string | null {\r\n const arrowHit = hitTestArrowHandles(world, this._selectedIds, ctx);\r\n if (arrowHit) {\r\n ctx.setCursor?.(getArrowHandleCursor(arrowHit.handle, false));\r\n return null;\r\n }\r\n\r\n if (hitTestLineHandles(world, ctx, this._selectedIds)) {\r\n ctx.setCursor?.('grab');\r\n return null;\r\n }\r\n\r\n const templateResizeHit = hitTestTemplateResizeHandle(world, ctx, this._selectedIds);\r\n if (templateResizeHit) {\r\n ctx.setCursor?.('nwse-resize');\r\n return null;\r\n }\r\n\r\n if (hitTestRotateHandle(world, ctx, this._selectedIds)) {\r\n ctx.setCursor?.('grab');\r\n return null;\r\n }\r\n\r\n const resizeHit = hitTestResizeHandle(world, ctx, this._selectedIds);\r\n if (resizeHit) {\r\n ctx.setCursor?.(HANDLE_CURSORS[resizeHit.handle]);\r\n return null;\r\n }\r\n\r\n const hit = hitTest(world, ctx);\r\n ctx.setCursor?.(hit ? 'move' : 'default');\r\n return hit ? hit.id : null;\r\n }\r\n\r\n private setHovered(id: string | null, ctx: ToolContext): void {\r\n if (this.hoveredId === id) return;\r\n this.hoveredId = id;\r\n ctx.requestRender();\r\n }\r\n\r\n private handleResize(world: Point, ctx: ToolContext, shiftKey = false): 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 angle = el.rotation ?? 0;\r\n const patch =\r\n angle !== 0\r\n ? computeRotatedResize(\r\n el,\r\n this.mode.handle,\r\n angle,\r\n world,\r\n this.lastWorld,\r\n this.resizeAspectRatio,\r\n shiftKey,\r\n )\r\n : computeResize(\r\n el,\r\n this.mode.handle,\r\n world,\r\n this.lastWorld,\r\n this.resizeAspectRatio,\r\n shiftKey,\r\n );\r\n\r\n this.lastWorld = world;\r\n ctx.store.update(this.mode.elementId, patch);\r\n this.updateArrowsBoundTo([this.mode.elementId], ctx);\r\n ctx.requestRender();\r\n }\r\n\r\n private getOverlayLayout(el: CanvasElement, zoom: number): OverlayLayout | null {\r\n return getOverlayLayout(el, zoom);\r\n }\r\n\r\n private handleTemplateResize(world: Point, ctx: ToolContext): void {\r\n if (this.mode.type !== 'resizing-template') return;\r\n\r\n const el = ctx.store.getById(this.mode.elementId);\r\n if (!el || el.type !== 'template' || el.locked) return;\r\n\r\n const patch = computeTemplateResize(el, world, {\r\n snapToGrid: ctx.snapToGrid,\r\n gridSize: ctx.gridSize,\r\n gridType: ctx.gridType,\r\n });\r\n if (patch) {\r\n ctx.store.update(this.mode.elementId, patch);\r\n ctx.requestRender();\r\n }\r\n }\r\n\r\n private getMarqueeRect(): Bounds | 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","import type { Point } from '../core/types';\r\nimport type { Binding, CanvasElement } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createArrow } from '../elements/element-factory';\r\nimport { findBindTarget, getElementCenter } from '../elements/arrow-binding';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nconst BIND_THRESHOLD = 20;\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 private fromBinding: Binding | undefined;\r\n private fromTarget: CanvasElement | null = null;\r\n private toTarget: CanvasElement | null = null;\r\n private optionListeners = new Set<() => void>();\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 getOptions(): ArrowToolOptions {\r\n return { color: this.color, width: this.width };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\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 this.notifyOptionsChange();\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n\r\n private layerFilter(ctx: ToolContext): ((el: CanvasElement) => boolean) | undefined {\r\n const activeLayerId = ctx.activeLayerId;\r\n if (!activeLayerId && !ctx.isLayerVisible && !ctx.isLayerLocked) return undefined;\r\n return (el: CanvasElement) => {\r\n if (activeLayerId && el.layerId !== activeLayerId) return false;\r\n if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) return false;\r\n if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) return false;\r\n return true;\r\n };\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 threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n const filter = this.layerFilter(ctx);\r\n\r\n const target = findBindTarget(world, ctx.store, threshold, undefined, filter);\r\n if (target) {\r\n this.start = getElementCenter(target);\r\n this.fromBinding = { elementId: target.id };\r\n this.fromTarget = target;\r\n } else {\r\n this.start = smartSnap(world, ctx);\r\n this.fromBinding = undefined;\r\n this.fromTarget = null;\r\n }\r\n this.end = { ...this.start };\r\n this.toTarget = null;\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 threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n const excludeId = this.fromBinding?.elementId;\r\n const filter = this.layerFilter(ctx);\r\n\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, filter);\r\n if (target) {\r\n this.end = getElementCenter(target);\r\n this.toTarget = target;\r\n } else {\r\n this.end = smartSnap(world, ctx);\r\n this.toTarget = null;\r\n }\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 position: this.start,\r\n color: this.color,\r\n width: this.width,\r\n fromBinding: this.fromBinding,\r\n toBinding: this.toTarget ? { elementId: this.toTarget.id } : undefined,\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(arrow);\r\n this.fromTarget = null;\r\n this.toTarget = null;\r\n ctx.requestRender();\r\n ctx.switchTool?.('select');\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\r\n if (this.fromTarget) {\r\n const bounds = getElementBounds(this.fromTarget);\r\n if (bounds) {\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.lineWidth = 2;\r\n ctx.setLineDash([]);\r\n ctx.strokeRect(bounds.x, bounds.y, bounds.w, bounds.h);\r\n }\r\n }\r\n\r\n if (this.toTarget) {\r\n const bounds = getElementBounds(this.toTarget);\r\n if (bounds) {\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.lineWidth = 2;\r\n ctx.setLineDash([]);\r\n ctx.strokeRect(bounds.x, bounds.y, bounds.w, bounds.h);\r\n }\r\n }\r\n\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, DEFAULT_NOTE_FONT_SIZE } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nexport interface NoteToolOptions {\r\n backgroundColor?: string;\r\n textColor?: string;\r\n size?: Size;\r\n fontSize?: number;\r\n}\r\n\r\nexport class NoteTool implements Tool {\r\n readonly name = 'note';\r\n private backgroundColor: string;\r\n private textColor: string;\r\n private size: Size;\r\n private fontSize: number;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: NoteToolOptions = {}) {\r\n this.backgroundColor = options.backgroundColor ?? '#ffeb3b';\r\n this.textColor = options.textColor ?? '#000000';\r\n this.size = options.size ?? { w: 200, h: 100 };\r\n this.fontSize = options.fontSize ?? DEFAULT_NOTE_FONT_SIZE;\r\n }\r\n\r\n getOptions(): NoteToolOptions {\r\n return {\r\n backgroundColor: this.backgroundColor,\r\n textColor: this.textColor,\r\n size: { ...this.size },\r\n fontSize: this.fontSize,\r\n };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n setOptions(options: NoteToolOptions): void {\r\n if (options.backgroundColor !== undefined) this.backgroundColor = options.backgroundColor;\r\n if (options.textColor !== undefined) this.textColor = options.textColor;\r\n if (options.size !== undefined) this.size = options.size;\r\n if (options.fontSize !== undefined) this.fontSize = options.fontSize;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\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 let world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n world = smartSnap(world, ctx);\r\n const note = createNote({\r\n position: world,\r\n size: { ...this.size },\r\n backgroundColor: this.backgroundColor,\r\n textColor: this.textColor,\r\n fontSize: this.fontSize,\r\n layerId: ctx.activeLayerId ?? '',\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 { Tool, ToolContext, PointerState } from './types';\r\nimport { createText } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nexport interface TextToolOptions {\r\n fontSize?: number;\r\n color?: string;\r\n textAlign?: 'left' | 'center' | 'right';\r\n}\r\n\r\nexport class TextTool implements Tool {\r\n readonly name = 'text';\r\n private fontSize: number;\r\n private color: string;\r\n private textAlign: 'left' | 'center' | 'right';\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: TextToolOptions = {}) {\r\n this.fontSize = options.fontSize ?? 16;\r\n this.color = options.color ?? '#1a1a1a';\r\n this.textAlign = options.textAlign ?? 'left';\r\n }\r\n\r\n getOptions(): TextToolOptions {\r\n return { fontSize: this.fontSize, color: this.color, textAlign: this.textAlign };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n setOptions(options: TextToolOptions): void {\r\n if (options.fontSize !== undefined) this.fontSize = options.fontSize;\r\n if (options.color !== undefined) this.color = options.color;\r\n if (options.textAlign !== undefined) this.textAlign = options.textAlign;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n\r\n onActivate(ctx: ToolContext): void {\r\n ctx.setCursor?.('text');\r\n }\r\n\r\n onDeactivate(ctx: ToolContext): void {\r\n ctx.setCursor?.('default');\r\n }\r\n\r\n onPointerDown(_state: PointerState, _ctx: ToolContext): void {\r\n // Text is placed on pointer up\r\n }\r\n\r\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\r\n // No drag behavior for text placement\r\n }\r\n\r\n onPointerUp(state: PointerState, ctx: ToolContext): void {\r\n let world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n world = smartSnap(world, ctx);\r\n const textEl = createText({\r\n position: world,\r\n fontSize: this.fontSize,\r\n color: this.color,\r\n textAlign: this.textAlign,\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(textEl);\r\n ctx.requestRender();\r\n\r\n ctx.switchTool?.('select');\r\n ctx.editElement?.(textEl.id);\r\n }\r\n}\r\n","import type { Size } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createImage } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nexport interface ImageToolOptions {\r\n size?: Size;\r\n}\r\n\r\nexport class ImageTool implements Tool {\r\n readonly name = 'image';\r\n private size: Size;\r\n private src: string | null = null;\r\n\r\n constructor(options: ImageToolOptions = {}) {\r\n this.size = options.size ?? { w: 300, h: 200 };\r\n }\r\n\r\n setSrc(src: string): void {\r\n this.src = src;\r\n }\r\n\r\n onPointerDown(_state: PointerState, _ctx: ToolContext): void {\r\n // No action on pointer down — image is placed on pointer up\r\n }\r\n\r\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\r\n // No action on pointer move\r\n }\r\n\r\n onPointerUp(state: PointerState, ctx: ToolContext): void {\r\n if (!this.src) return;\r\n\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const snapped = smartSnap(world, ctx);\r\n const image = createImage({\r\n position: {\r\n x: snapped.x - this.size.w / 2,\r\n y: snapped.y - this.size.h / 2,\r\n },\r\n size: { ...this.size },\r\n src: this.src,\r\n });\r\n ctx.store.add(image);\r\n ctx.requestRender();\r\n\r\n this.src = null;\r\n ctx.switchTool?.('select');\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { ShapeKind } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createShape } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nfunction snapTo45(start: Point, end: Point): Point {\r\n const dx = end.x - start.x;\r\n const dy = end.y - start.y;\r\n const len = Math.hypot(dx, dy);\r\n if (len === 0) return { ...end };\r\n const step = Math.PI / 4;\r\n const angle = Math.round(Math.atan2(dy, dx) / step) * step;\r\n return { x: start.x + Math.cos(angle) * len, y: start.y + Math.sin(angle) * len };\r\n}\r\n\r\nexport interface ShapeToolOptions {\r\n shape?: ShapeKind;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n fillColor?: string;\r\n}\r\n\r\nexport class ShapeTool implements Tool {\r\n readonly name = 'shape';\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 shiftHeld = false;\r\n private shape: ShapeKind;\r\n private strokeColor: string;\r\n private strokeWidth: number;\r\n private fillColor: string;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: ShapeToolOptions = {}) {\r\n this.shape = options.shape ?? 'rectangle';\r\n this.strokeColor = options.strokeColor ?? '#000000';\r\n this.strokeWidth = options.strokeWidth ?? 2;\r\n this.fillColor = options.fillColor ?? 'none';\r\n }\r\n\r\n getOptions(): ShapeToolOptions {\r\n return {\r\n shape: this.shape,\r\n strokeColor: this.strokeColor,\r\n strokeWidth: this.strokeWidth,\r\n fillColor: this.fillColor,\r\n };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n setOptions(options: ShapeToolOptions): void {\r\n if (options.shape !== undefined) this.shape = options.shape;\r\n if (options.strokeColor !== undefined) this.strokeColor = options.strokeColor;\r\n if (options.strokeWidth !== undefined) this.strokeWidth = options.strokeWidth;\r\n if (options.fillColor !== undefined) this.fillColor = options.fillColor;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n onActivate(_ctx: ToolContext): void {\r\n if (typeof window !== 'undefined') {\r\n window.addEventListener('keydown', this.onKeyDown);\r\n window.addEventListener('keyup', this.onKeyUp);\r\n }\r\n }\r\n\r\n onDeactivate(_ctx: ToolContext): void {\r\n this.shiftHeld = false;\r\n if (typeof window !== 'undefined') {\r\n window.removeEventListener('keydown', this.onKeyDown);\r\n window.removeEventListener('keyup', this.onKeyUp);\r\n }\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.drawing = true;\r\n this.start = this.snap(ctx.camera.screenToWorld({ x: state.x, y: state.y }), ctx);\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 = this.snap(ctx.camera.screenToWorld({ x: state.x, y: state.y }), ctx);\r\n if (this.shape === 'line' && this.shiftHeld) {\r\n this.end = snapTo45(this.start, this.end);\r\n }\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 const { position, size } = this.computeRect();\r\n const isLine = this.shape === 'line';\r\n if (isLine ? size.w === 0 && size.h === 0 : size.w === 0 || size.h === 0) return;\r\n\r\n const shape = createShape({\r\n position,\r\n size,\r\n shape: this.shape,\r\n strokeColor: this.strokeColor,\r\n strokeWidth: this.strokeWidth,\r\n fillColor: this.fillColor,\r\n ...(isLine ? { flip: this.end.x > this.start.x !== this.end.y > this.start.y } : {}),\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(shape);\r\n ctx.requestRender();\r\n ctx.switchTool?.('select');\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (!this.drawing) return;\r\n\r\n const { position, size } = this.computeRect();\r\n if (size.w === 0 && size.h === 0) return;\r\n\r\n ctx.save();\r\n ctx.globalAlpha = 0.5;\r\n ctx.strokeStyle = this.strokeColor;\r\n ctx.lineWidth = this.strokeWidth;\r\n\r\n if (this.fillColor !== 'none') {\r\n ctx.fillStyle = this.fillColor;\r\n }\r\n\r\n switch (this.shape) {\r\n case 'rectangle':\r\n if (this.fillColor !== 'none') {\r\n ctx.fillRect(position.x, position.y, size.w, size.h);\r\n }\r\n ctx.strokeRect(position.x, position.y, size.w, size.h);\r\n break;\r\n case 'ellipse': {\r\n const cx = position.x + size.w / 2;\r\n const cy = position.y + size.h / 2;\r\n ctx.beginPath();\r\n ctx.ellipse(cx, cy, size.w / 2, size.h / 2, 0, 0, Math.PI * 2);\r\n if (this.fillColor !== 'none') ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n case 'line':\r\n ctx.lineCap = 'round';\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 break;\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private computeRect(): { position: Point; size: { w: number; h: number } } {\r\n let x = Math.min(this.start.x, this.end.x);\r\n let y = Math.min(this.start.y, this.end.y);\r\n let w = Math.abs(this.end.x - this.start.x);\r\n let h = Math.abs(this.end.y - this.start.y);\r\n\r\n if (this.shiftHeld && this.shape !== 'line') {\r\n const side = Math.max(w, h);\r\n w = side;\r\n h = side;\r\n x = this.end.x >= this.start.x ? this.start.x : this.start.x - side;\r\n y = this.end.y >= this.start.y ? this.start.y : this.start.y - side;\r\n }\r\n\r\n return { position: { x, y }, size: { w, h } };\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n\r\n private snap(point: Point, ctx: ToolContext): Point {\r\n return smartSnap(point, ctx);\r\n }\r\n\r\n private onKeyDown = (e: KeyboardEvent): void => {\r\n if (e.key === 'Shift') this.shiftHeld = true;\r\n };\r\n\r\n private onKeyUp = (e: KeyboardEvent): void => {\r\n if (e.key === 'Shift') this.shiftHeld = false;\r\n };\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { HexOrientation } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { snapPoint, snapToHexCenter } from '../core/snap';\r\nimport { getHexDistance } from '../elements/hex-fill';\r\n\r\nexport interface MeasureToolOptions {\r\n feetPerCell?: number;\r\n}\r\n\r\nexport interface Measurement {\r\n start: Point;\r\n end: Point;\r\n worldDistance: number;\r\n cells: number;\r\n feet: number;\r\n}\r\n\r\nexport class MeasureTool implements Tool {\r\n readonly name = 'measure';\r\n private start: Point | null = null;\r\n private end: Point | null = null;\r\n private gridSize = 1;\r\n private gridType: 'square' | 'hex' | undefined;\r\n private hexOrientation: HexOrientation | undefined;\r\n private feetPerCell: number;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: MeasureToolOptions = {}) {\r\n this.feetPerCell = options.feetPerCell ?? 5;\r\n }\r\n\r\n getOptions(): MeasureToolOptions {\r\n return { feetPerCell: this.feetPerCell };\r\n }\r\n\r\n setOptions(options: MeasureToolOptions): void {\r\n if (options.feetPerCell !== undefined) this.feetPerCell = options.feetPerCell;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.gridSize = ctx.gridSize ?? 1;\r\n this.gridType = ctx.gridType;\r\n this.hexOrientation = ctx.hexOrientation;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.start = this.snapToGrid(world, ctx);\r\n this.end = { ...this.start };\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.start) return;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.end = this.snapToGrid(world, ctx);\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\r\n if (!this.start) return;\r\n this.start = null;\r\n this.end = null;\r\n ctx.requestRender();\r\n }\r\n\r\n onDeactivate(_ctx: ToolContext): void {\r\n this.start = null;\r\n this.end = null;\r\n }\r\n\r\n getMeasurement(): Measurement | null {\r\n if (!this.start || !this.end) return null;\r\n const dx = this.end.x - this.start.x;\r\n const dy = this.end.y - this.start.y;\r\n const worldDistance = Math.sqrt(dx * dx + dy * dy);\r\n\r\n let cells: number;\r\n if (this.gridType === 'hex' && this.hexOrientation) {\r\n cells = getHexDistance(this.start, this.end, this.gridSize, this.hexOrientation);\r\n } else {\r\n const snapUnit = this.gridSize;\r\n cells = worldDistance / snapUnit;\r\n }\r\n\r\n const feet = cells * this.feetPerCell;\r\n return {\r\n start: { ...this.start },\r\n end: { ...this.end },\r\n worldDistance,\r\n cells,\r\n feet,\r\n };\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n const m = this.getMeasurement();\r\n if (!m) return;\r\n\r\n ctx.save();\r\n\r\n ctx.strokeStyle = '#FF5722';\r\n ctx.setLineDash([8, 4]);\r\n ctx.lineWidth = 2;\r\n ctx.beginPath();\r\n ctx.moveTo(m.start.x, m.start.y);\r\n ctx.lineTo(m.end.x, m.end.y);\r\n ctx.stroke();\r\n\r\n ctx.setLineDash([]);\r\n ctx.fillStyle = '#FF5722';\r\n const dotRadius = 4;\r\n ctx.beginPath();\r\n ctx.arc(m.start.x, m.start.y, dotRadius, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.beginPath();\r\n ctx.arc(m.end.x, m.end.y, dotRadius, 0, Math.PI * 2);\r\n ctx.fill();\r\n\r\n const label = `${Math.round(m.feet)} ft`;\r\n const midX = (m.start.x + m.end.x) / 2;\r\n const midY = (m.start.y + m.end.y) / 2;\r\n ctx.font = '14px sans-serif';\r\n const metrics = ctx.measureText(label);\r\n const padX = 6;\r\n const padY = 4;\r\n const textH = 14;\r\n\r\n ctx.fillStyle = 'rgba(0, 0, 0, 0.75)';\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n midX - metrics.width / 2 - padX,\r\n midY - textH / 2 - padY,\r\n metrics.width + padX * 2,\r\n textH + padY * 2,\r\n 4,\r\n );\r\n ctx.fill();\r\n\r\n ctx.fillStyle = '#FFFFFF';\r\n ctx.textAlign = 'center';\r\n ctx.textBaseline = 'middle';\r\n ctx.fillText(label, midX, midY);\r\n\r\n ctx.restore();\r\n }\r\n\r\n private snapToGrid(point: Point, ctx: ToolContext): Point {\r\n if (!ctx.gridSize) return point;\r\n if (ctx.gridType === 'hex' && ctx.hexOrientation) {\r\n return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);\r\n }\r\n if (ctx.gridType === 'square') {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n if (ctx.snapToGrid) {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n return point;\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { TemplateShape, HexOrientation } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createTemplate } from '../elements/element-factory';\r\nimport { snapPoint, snapToHexCenter } from '../core/snap';\r\nimport {\r\n getHexCellsInRadius,\r\n getHexCellsInCone,\r\n getHexCellsInLine,\r\n getHexCellsInSquare,\r\n drawHexPath,\r\n} from '../elements/hex-fill';\r\n\r\nexport interface TemplateToolOptions {\r\n templateShape?: TemplateShape;\r\n fillColor?: string;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n feetPerCell?: number;\r\n}\r\n\r\nexport class TemplateTool implements Tool {\r\n readonly name = 'template';\r\n private drawing = false;\r\n private origin: Point = { x: 0, y: 0 };\r\n private current: Point = { x: 0, y: 0 };\r\n private gridSize = 1;\r\n private gridType: 'square' | 'hex' | undefined;\r\n private hexOrientation: HexOrientation | undefined;\r\n private snapEnabled = false;\r\n private templateShape: TemplateShape;\r\n private fillColor: string;\r\n private strokeColor: string;\r\n private strokeWidth: number;\r\n private opacity: number;\r\n private feetPerCell: number;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: TemplateToolOptions = {}) {\r\n this.templateShape = options.templateShape ?? 'circle';\r\n this.fillColor = options.fillColor ?? 'rgba(255, 87, 34, 0.2)';\r\n this.strokeColor = options.strokeColor ?? '#FF5722';\r\n this.strokeWidth = options.strokeWidth ?? 2;\r\n this.opacity = options.opacity ?? 0.6;\r\n this.feetPerCell = options.feetPerCell ?? 5;\r\n }\r\n\r\n getOptions(): TemplateToolOptions {\r\n return {\r\n templateShape: this.templateShape,\r\n fillColor: this.fillColor,\r\n strokeColor: this.strokeColor,\r\n strokeWidth: this.strokeWidth,\r\n opacity: this.opacity,\r\n feetPerCell: this.feetPerCell,\r\n };\r\n }\r\n\r\n setOptions(options: TemplateToolOptions): void {\r\n if (options.templateShape !== undefined) this.templateShape = options.templateShape;\r\n if (options.fillColor !== undefined) this.fillColor = options.fillColor;\r\n if (options.strokeColor !== undefined) this.strokeColor = options.strokeColor;\r\n if (options.strokeWidth !== undefined) this.strokeWidth = options.strokeWidth;\r\n if (options.opacity !== undefined) this.opacity = options.opacity;\r\n if (options.feetPerCell !== undefined) this.feetPerCell = options.feetPerCell;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.drawing = true;\r\n this.gridSize = ctx.gridSize ?? 1;\r\n this.gridType = ctx.gridType;\r\n this.hexOrientation = ctx.hexOrientation;\r\n this.snapEnabled = !!ctx.gridType || (ctx.snapToGrid ?? false);\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.origin = this.snapToGrid(world, ctx);\r\n this.current = { ...this.origin };\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.current = 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 const radius = this.computeRadius();\r\n if (radius <= 0) return;\r\n\r\n const angle = this.computeAngle();\r\n const gridSize = ctx.gridSize;\r\n const snapUnit =\r\n gridSize && gridSize > 0 ? (ctx.gridType === 'hex' ? Math.sqrt(3) * gridSize : gridSize) : 0;\r\n const cells = snapUnit > 0 ? radius / snapUnit : 0;\r\n const radiusFeet = cells * this.feetPerCell;\r\n\r\n const element = createTemplate({\r\n position: { ...this.origin },\r\n templateShape: this.templateShape,\r\n radius,\r\n angle,\r\n fillColor: this.fillColor,\r\n strokeColor: this.strokeColor,\r\n strokeWidth: this.strokeWidth,\r\n opacity: this.opacity,\r\n feetPerCell: this.feetPerCell,\r\n radiusFeet: radiusFeet > 0 ? radiusFeet : undefined,\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(element);\r\n ctx.requestRender();\r\n ctx.switchTool?.('select');\r\n }\r\n\r\n onDeactivate(_ctx: ToolContext): void {\r\n this.drawing = false;\r\n this.origin = { x: 0, y: 0 };\r\n this.current = { x: 0, y: 0 };\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (!this.drawing) return;\r\n\r\n const radius = this.computeRadius();\r\n if (radius <= 0) return;\r\n\r\n if (this.gridType === 'hex' && this.hexOrientation) {\r\n this.renderHexOverlay(ctx, radius);\r\n return;\r\n }\r\n\r\n this.renderGeometricOverlay(ctx, radius);\r\n }\r\n\r\n private renderGeometricOverlay(ctx: CanvasRenderingContext2D, radius: number): void {\r\n const cx = this.origin.x;\r\n const cy = this.origin.y;\r\n const angle = this.computeAngle();\r\n\r\n ctx.save();\r\n ctx.globalAlpha = 0.4;\r\n ctx.fillStyle = this.fillColor;\r\n ctx.strokeStyle = this.strokeColor;\r\n ctx.lineWidth = this.strokeWidth;\r\n\r\n switch (this.templateShape) {\r\n case 'circle':\r\n ctx.beginPath();\r\n ctx.arc(cx, cy, radius, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n\r\n case 'square':\r\n ctx.fillRect(cx - radius / 2, cy - radius / 2, radius, radius);\r\n ctx.strokeRect(cx - radius / 2, cy - radius / 2, radius, radius);\r\n break;\r\n\r\n case 'cone': {\r\n const halfAngle = Math.atan(0.5);\r\n ctx.beginPath();\r\n ctx.moveTo(cx, cy);\r\n ctx.arc(cx, cy, radius, angle - halfAngle, angle + halfAngle);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n\r\n case 'line': {\r\n const halfW = radius / 12;\r\n const cos = Math.cos(angle);\r\n const sin = Math.sin(angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(cx + perpX, cy + perpY);\r\n ctx.lineTo(cx + radius * cos + perpX, cy + radius * sin + perpY);\r\n ctx.lineTo(cx + radius * cos - perpX, cy + radius * sin - perpY);\r\n ctx.lineTo(cx - perpX, cy - perpY);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private renderHexOverlay(ctx: CanvasRenderingContext2D, radius: number): void {\r\n const orientation = this.hexOrientation;\r\n if (!orientation) return;\r\n const cellSize = this.gridSize;\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const radiusCells = radius / snapUnit;\r\n const angle = this.computeAngle();\r\n const center = this.origin;\r\n\r\n let hexCells: Point[];\r\n switch (this.templateShape) {\r\n case 'circle':\r\n hexCells = getHexCellsInRadius(center, radiusCells, cellSize, orientation);\r\n break;\r\n case 'cone':\r\n hexCells = getHexCellsInCone(center, angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'line':\r\n hexCells = getHexCellsInLine(center, angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'square':\r\n hexCells = getHexCellsInSquare(center, radiusCells, cellSize, orientation);\r\n break;\r\n }\r\n\r\n ctx.save();\r\n ctx.globalAlpha = 0.4;\r\n\r\n ctx.beginPath();\r\n for (const cell of hexCells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.fillStyle = this.fillColor;\r\n ctx.fill();\r\n\r\n ctx.beginPath();\r\n for (const cell of hexCells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.strokeStyle = this.strokeColor;\r\n ctx.lineWidth = this.strokeWidth;\r\n ctx.stroke();\r\n\r\n if (\r\n this.templateShape === 'cone' ||\r\n this.templateShape === 'line' ||\r\n this.templateShape === 'circle' ||\r\n this.templateShape === 'square'\r\n ) {\r\n ctx.globalAlpha = 0.5;\r\n ctx.beginPath();\r\n drawHexPath(ctx, center.x, center.y, cellSize, orientation);\r\n ctx.fillStyle = this.strokeColor;\r\n ctx.fill();\r\n ctx.strokeStyle = this.strokeColor;\r\n ctx.lineWidth = this.strokeWidth;\r\n ctx.stroke();\r\n }\r\n\r\n if (this.templateShape === 'circle') {\r\n const feet = radiusCells * this.feetPerCell;\r\n if (feet > 0) {\r\n ctx.globalAlpha = 1;\r\n const label = `${Math.round(feet)} ft`;\r\n const fontSize = Math.max(10, Math.min(14, radius * 0.15));\r\n ctx.font = `bold ${fontSize}px system-ui, sans-serif`;\r\n ctx.textAlign = 'center';\r\n ctx.textBaseline = 'bottom';\r\n const textX = center.x;\r\n const textY = center.y - 4;\r\n\r\n const metrics = ctx.measureText(label);\r\n const padX = 4;\r\n const padY = 2;\r\n const textW = metrics.width + padX * 2;\r\n const textH = fontSize + padY * 2;\r\n\r\n ctx.fillStyle = 'rgba(255, 255, 255, 0.85)';\r\n ctx.beginPath();\r\n ctx.roundRect(textX - textW / 2, textY - textH, textW, textH, 3);\r\n ctx.fill();\r\n\r\n ctx.fillStyle = this.strokeColor;\r\n ctx.fillText(label, textX, textY - padY);\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private computeRadius(): number {\r\n const dx = this.current.x - this.origin.x;\r\n const dy = this.current.y - this.origin.y;\r\n const raw = Math.sqrt(dx * dx + dy * dy);\r\n if (this.snapEnabled && this.gridSize > 0) {\r\n const snapUnit = this.gridType === 'hex' ? Math.sqrt(3) * this.gridSize : this.gridSize;\r\n return Math.max(snapUnit, Math.round(raw / snapUnit) * snapUnit);\r\n }\r\n return raw;\r\n }\r\n\r\n private computeAngle(): number {\r\n const dx = this.current.x - this.origin.x;\r\n const dy = this.current.y - this.origin.y;\r\n return Math.atan2(dy, dx);\r\n }\r\n\r\n private snapToGrid(point: Point, ctx: ToolContext): Point {\r\n if (!ctx.gridSize) return point;\r\n if (ctx.gridType === 'hex' && ctx.hexOrientation) {\r\n return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);\r\n }\r\n if (ctx.gridType === 'square') {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n if (ctx.snapToGrid) {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n return point;\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n}\r\n"],"mappings":"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","names":["center","minX","minY","minX","minY","center","center","cache","center","center","center","cache","center","center","HANDLE_HIT_PADDING","center","HANDLE_HIT_PADDING","center","BIND_THRESHOLD","center"]}