@fieldnotes/core 0.56.0 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +274 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +147 -35
- package/dist/index.d.ts +147 -35
- package/dist/index.js +270 -50
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -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/storage/local-storage-adapter.ts","../src/core/auto-save.ts","../src/core/storage/memory-adapter.ts","../src/core/storage/indexeddb-adapter.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/pan-inertia.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-measure.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/minimap-transform.ts","../src/canvas/minimap.ts","../src/canvas/viewport-dom.ts","../src/canvas/hybrid-render-surface.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/text-canvas-renderer.ts","../src/canvas/html-export.ts","../src/canvas/export-image.ts","../src/canvas/export-svg.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-rotate.ts","../src/canvas/selection-ops.ts","../src/canvas/grid-controller.ts","../src/canvas/viewport-interactions.ts","../src/canvas/viewport.ts","../src/canvas/remote-laser-overlay.ts","../src/canvas/ping-pulse.ts","../src/canvas/remote-ping-overlay.ts","../src/canvas/ping-input.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","../src/tools/laser-tool.ts","../src/tools/ping-tool.ts"],"sourcesContent":["export const VERSION = '0.56.0';\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';\nexport { MemoryAdapter } from './core/storage/memory-adapter';\nexport { LocalStorageAdapter } from './core/storage/local-storage-adapter';\nexport { IndexedDBAdapter } from './core/storage/indexeddb-adapter';\nexport type { StorageAdapter } from './core/storage/storage-adapter';\nexport type { IndexedDBAdapterOptions } from './core/storage/indexeddb-adapter';\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 {\n ViewportOptions,\n GridInfo,\n AlignEdge,\n DistributeAxis,\n RotateDirection,\n} from './canvas/viewport';\nexport { exportImage } from './canvas/export-image';\nexport type {\n ExportAssetError,\n ExportAssetErrorReason,\n ExportImageOptions,\n ExportResourceOptions,\n} from './canvas/export-image';\nexport { exportSvg } from './canvas/export-svg';\nexport type { ExportSvgOptions } from './canvas/export-svg';\nexport type {\n HtmlExportError,\n HtmlExportErrorReason,\n HtmlExportOptions,\n HtmlExportRenderer,\n} from './canvas/html-export';\nexport type { RenderStatsSnapshot } from './canvas/render-stats';\nexport type { OverlayRenderer } from './canvas/render-loop';\nexport {\n RemoteLaserOverlay,\n isLaserTrailPresence,\n toLaserTrailPresence,\n LASER_TRAIL_PRESENCE_KIND,\n} from './canvas/remote-laser-overlay';\nexport type {\n LaserTrailPresence,\n RemoteLaserOverlayHost,\n RemoteLaserOverlayOptions,\n} from './canvas/remote-laser-overlay';\nexport {\n RemotePingOverlay,\n isPingPresence,\n toPingPresence,\n PING_PRESENCE_KIND,\n} from './canvas/remote-ping-overlay';\nexport type {\n PingPresence,\n RemotePingOverlayHost,\n RemotePingOverlayOptions,\n} from './canvas/remote-ping-overlay';\nexport { PingInput } from './canvas/ping-input';\nexport type { PingInputHost, PingInputOptions } from './canvas/ping-input';\n\nexport { ElementStore } from './elements/element-store';\nexport type { ElementUpdateEvent } from './elements/element-store';\nexport type { ElementChangeMeta } 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 getHexCellsInRectangle,\n drawHexPath,\n} from './elements/hex-fill';\nexport type {\n Binding,\n CanvasElement,\n ElementType,\n StrokeElement,\n NoteElement,\n ArrowElement,\n ArrowStrokeStyle,\n ImageElement,\n HtmlElement,\n TextElement,\n ShapeElement,\n ShapeKind,\n GridElement,\n HexOrientation,\n TemplateElement,\n TemplateShape,\n TemplateRenderStyle,\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 { LaserTool } from './tools/laser-tool';\nexport type { LaserToolOptions, LaserTrailEmission } from './tools/laser-tool';\nexport { PingTool } from './tools/ping-tool';\nexport type { PingToolOptions, PingEmission } from './tools/ping-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\nconst ELEMENT_TYPES = [\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] as const satisfies readonly CanvasElement['type'][];\r\ntype _ElementTypesAreExhaustive = CanvasElement['type'] extends (typeof ELEMENT_TYPES)[number]\r\n ? true\r\n : never;\r\nconst _elementTypesAreExhaustive: _ElementTypesAreExhaustive = true;\r\nvoid _elementTypesAreExhaustive;\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 (!isRecord(data)) {\r\n throw new Error('Invalid state: expected an object');\r\n }\r\n\r\n const obj = data;\r\n\r\n if (!Number.isInteger(obj['version']) || (obj['version'] as number) < 1) {\r\n throw new Error('Invalid state: missing or invalid version');\r\n }\r\n if ((obj['version'] as number) > CURRENT_VERSION) {\r\n throw new Error(`Invalid state: unsupported version ${String(obj['version'])}`);\r\n }\r\n\r\n if (!isRecord(obj['camera'])) {\r\n throw new Error('Invalid state: missing camera');\r\n }\r\n\r\n const cam = obj['camera'];\r\n if (!isRecord(cam['position'])) {\r\n throw new Error('Invalid state: missing camera.position');\r\n }\r\n\r\n if (!isPoint(cam['position'])) {\r\n throw new Error('Invalid state: camera.position must have finite x and y numbers');\r\n }\r\n\r\n if (!isFiniteNumber(cam['zoom']) || cam['zoom'] <= 0) {\r\n throw new Error('Invalid state: camera.zoom must be a positive finite number');\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 if (obj['layers'] !== undefined && !Array.isArray(obj['layers'])) {\r\n throw new Error('Invalid state: layers must be an array');\r\n }\r\n\r\n const elements = obj['elements'] as unknown[];\r\n const hasLayers = Array.isArray(obj['layers']) && obj['layers'].length > 0;\r\n for (const el of elements) {\r\n if (!isRecord(el)) throw new Error('Invalid element: expected an object');\r\n migrateElement(el, !hasLayers);\r\n }\r\n\r\n if (!hasLayers) {\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 const layers = obj['layers'] as unknown[];\r\n const layerIds = new Set<string>();\r\n for (const layer of layers) {\r\n validateLayer(layer);\r\n if (layerIds.has(layer.id)) throw new Error(`Invalid state: duplicate layer id \"${layer.id}\"`);\r\n layerIds.add(layer.id);\r\n }\r\n\r\n const elementIds = new Set<string>();\r\n for (const el of elements) {\r\n validateElement(el);\r\n if (elementIds.has(el.id)) throw new Error(`Invalid state: duplicate element id \"${el.id}\"`);\r\n elementIds.add(el.id);\r\n if (!layerIds.has(el.layerId)) {\r\n throw new Error(`Invalid element \"${el.id}\": unknown layerId \"${el.layerId}\"`);\r\n }\r\n }\r\n\r\n if (obj['activeLayerId'] !== undefined) {\r\n if (typeof obj['activeLayerId'] !== 'string' || !layerIds.has(obj['activeLayerId'])) {\r\n throw new Error('Invalid state: activeLayerId must reference an existing layer');\r\n }\r\n }\r\n\r\n cleanBindings(elements as Record<string, unknown>[]);\r\n}\r\n\r\nfunction validateElement(el: unknown): asserts el is CanvasElement {\r\n if (!isRecord(el)) {\r\n throw new Error('Invalid element: expected an object');\r\n }\r\n\r\n if (typeof el['id'] !== 'string' || el['id'].length === 0) {\r\n throw new Error('Invalid element: missing id');\r\n }\r\n if (!isEnum(el['type'], ELEMENT_TYPES)) {\r\n throw new Error(`Invalid element: unknown type \"${String(el['type'])}\"`);\r\n }\r\n if (!isFiniteNumber(el['zIndex'])) {\r\n throw new Error(`Invalid element \"${el['id']}\": missing or invalid zIndex`);\r\n }\r\n if (\r\n !isPoint(el['position']) ||\r\n typeof el['locked'] !== 'boolean' ||\r\n typeof el['layerId'] !== 'string' ||\r\n !isOptional(el['groupId'], isString) ||\r\n !isOptional(el['rotation'], isFiniteNumber)\r\n ) {\r\n throw new Error(`Invalid element \"${el['id']}\": invalid base fields or geometry`);\r\n }\r\n\r\n const valid = validateTypeFields(el, el['type']);\r\n if (!valid) throw new Error(`Invalid element \"${el['id']}\": malformed ${el['type']} data`);\r\n}\r\n\r\nfunction validateTypeFields(el: Record<string, unknown>, type: CanvasElement['type']): boolean {\r\n switch (type) {\r\n case 'stroke':\r\n return (\r\n Array.isArray(el['points']) &&\r\n el['points'].every(isStrokePoint) &&\r\n isString(el['color']) &&\r\n isFiniteNumber(el['width']) &&\r\n isFiniteNumber(el['opacity']) &&\r\n isOptionalEnum(el['blendMode'], ['multiply'])\r\n );\r\n case 'note':\r\n return (\r\n isSize(el['size']) &&\r\n isString(el['text']) &&\r\n isString(el['backgroundColor']) &&\r\n isString(el['textColor']) &&\r\n isOptional(el['fontSize'], isFiniteNumber)\r\n );\r\n case 'arrow':\r\n return (\r\n isPoint(el['from']) &&\r\n isPoint(el['to']) &&\r\n isFiniteNumber(el['bend']) &&\r\n isString(el['color']) &&\r\n isFiniteNumber(el['width']) &&\r\n isOptional(el['fromBinding'], isBinding) &&\r\n isOptional(el['toBinding'], isBinding) &&\r\n isOptional(el['cachedControlPoint'], isPoint) &&\r\n isOptional(el['label'], isString) &&\r\n isOptionalEnum(el['strokeStyle'], ['solid', 'dashed', 'dotted'])\r\n );\r\n case 'image':\r\n return isSize(el['size']) && isString(el['src']);\r\n case 'html':\r\n return (\r\n isSize(el['size']) &&\r\n isOptional(el['domId'], isString) &&\r\n isOptional(el['interactive'], isBoolean) &&\r\n isOptional(el['htmlType'], isString) &&\r\n isOptional(el['data'], isRecord)\r\n );\r\n case 'text':\r\n return (\r\n isSize(el['size']) &&\r\n isString(el['text']) &&\r\n isFiniteNumber(el['fontSize']) &&\r\n isString(el['color']) &&\r\n isEnum(el['textAlign'], ['left', 'center', 'right'])\r\n );\r\n case 'shape':\r\n return (\r\n isEnum(el['shape'], ['rectangle', 'ellipse', 'line']) &&\r\n isSize(el['size']) &&\r\n isString(el['strokeColor']) &&\r\n isFiniteNumber(el['strokeWidth']) &&\r\n isString(el['fillColor']) &&\r\n isOptional(el['flip'], isBoolean)\r\n );\r\n case 'grid':\r\n return (\r\n isEnum(el['gridType'], ['square', 'hex']) &&\r\n isEnum(el['hexOrientation'], ['pointy', 'flat']) &&\r\n isFiniteNumber(el['cellSize']) &&\r\n isString(el['strokeColor']) &&\r\n isFiniteNumber(el['strokeWidth']) &&\r\n isFiniteNumber(el['opacity'])\r\n );\r\n case 'template':\r\n return (\r\n isEnum(el['templateShape'], ['circle', 'cone', 'line', 'square', 'rectangle']) &&\r\n isFiniteNumber(el['radius']) &&\r\n isFiniteNumber(el['angle']) &&\r\n isOptional(el['width'], isFiniteNumber) &&\r\n isString(el['fillColor']) &&\r\n isString(el['strokeColor']) &&\r\n isFiniteNumber(el['strokeWidth']) &&\r\n isFiniteNumber(el['opacity']) &&\r\n isOptional(el['feetPerCell'], isFiniteNumber) &&\r\n isOptional(el['radiusFeet'], isFiniteNumber) &&\r\n isOptionalEnum(el['renderStyle'], ['cells', 'geometric'])\r\n );\r\n }\r\n}\r\n\r\nfunction validateLayer(layer: unknown): asserts layer is Layer {\r\n if (\r\n !isRecord(layer) ||\r\n typeof layer['id'] !== 'string' ||\r\n layer['id'].length === 0 ||\r\n typeof layer['name'] !== 'string' ||\r\n typeof layer['visible'] !== 'boolean' ||\r\n typeof layer['locked'] !== 'boolean' ||\r\n !isFiniteNumber(layer['order']) ||\r\n !isFiniteNumber(layer['opacity']) ||\r\n layer['opacity'] < 0 ||\r\n layer['opacity'] > 1\r\n ) {\r\n throw new Error('Invalid state: malformed layer');\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>, useDefaultLayer: boolean): void {\r\n if (obj['layerId'] === undefined || (useDefaultLayer && obj['layerId'] === '')) {\r\n obj['layerId'] = 'default-layer';\r\n }\r\n\r\n if (obj['type'] === 'arrow' && obj['bend'] === undefined) {\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 (pt['pressure'] === undefined) {\r\n pt['pressure'] = 0.5;\r\n }\r\n }\r\n }\r\n\r\n if (obj['type'] === 'shape' && obj['shape'] === undefined) {\r\n obj['shape'] = 'rectangle';\r\n }\r\n\r\n if (obj['type'] === 'note' && obj['textColor'] === undefined) {\r\n obj['textColor'] = '#000000';\r\n }\r\n\r\n if ((obj['type'] === 'note' || obj['type'] === 'text') && typeof obj['text'] === 'string') {\r\n obj['text'] = sanitizeNoteHtml(obj['text']);\r\n }\r\n}\r\n\r\ntype Validator = (value: unknown) => boolean;\r\n\r\nfunction isRecord(value: unknown): value is Record<string, unknown> {\r\n return typeof value === 'object' && value !== null && !Array.isArray(value);\r\n}\r\n\r\nfunction isFiniteNumber(value: unknown): value is number {\r\n return typeof value === 'number' && Number.isFinite(value);\r\n}\r\n\r\nfunction isString(value: unknown): value is string {\r\n return typeof value === 'string';\r\n}\r\n\r\nfunction isBoolean(value: unknown): value is boolean {\r\n return typeof value === 'boolean';\r\n}\r\n\r\nfunction isOptional(value: unknown, validate: Validator): boolean {\r\n return value === undefined || validate(value);\r\n}\r\n\r\nfunction isEnum<const T extends readonly string[]>(value: unknown, values: T): value is T[number] {\r\n return typeof value === 'string' && (values as readonly string[]).includes(value);\r\n}\r\n\r\nfunction isOptionalEnum<const T extends readonly string[]>(value: unknown, values: T): boolean {\r\n return value === undefined || isEnum(value, values);\r\n}\r\n\r\nfunction isPoint(value: unknown): boolean {\r\n return isRecord(value) && isFiniteNumber(value['x']) && isFiniteNumber(value['y']);\r\n}\r\n\r\nfunction isSize(value: unknown): boolean {\r\n return isRecord(value) && isFiniteNumber(value['w']) && isFiniteNumber(value['h']);\r\n}\r\n\r\nfunction isStrokePoint(value: unknown): boolean {\r\n return isRecord(value) && isPoint(value) && isFiniteNumber(value['pressure']);\r\n}\r\n\r\nfunction isBinding(value: unknown): boolean {\r\n return isRecord(value) && typeof value['elementId'] === 'string';\r\n}\r\n","import type { StorageAdapter } from './storage-adapter';\r\n\r\nexport class LocalStorageAdapter implements StorageAdapter {\r\n async load(key: string): Promise<string | null> {\r\n if (typeof localStorage === 'undefined') return null;\r\n return localStorage.getItem(key);\r\n }\r\n async save(key: string, value: string): Promise<void> {\r\n if (typeof localStorage === 'undefined') return;\r\n localStorage.setItem(key, value);\r\n }\r\n async clear(key: string): Promise<void> {\r\n if (typeof localStorage === 'undefined') return;\r\n localStorage.removeItem(key);\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\nimport { LocalStorageAdapter } from './storage/local-storage-adapter';\r\nimport type { StorageAdapter } from './storage/storage-adapter';\r\n\r\nexport interface AutoSaveOptions {\r\n key?: string;\r\n debounceMs?: number;\r\n layerManager?: LayerManager;\r\n adapter?: StorageAdapter;\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 readonly adapter: StorageAdapter;\r\n private timerId: ReturnType<typeof setTimeout> | null = null;\r\n private unsubscribers: (() => void)[] = [];\r\n private readonly onError?: (error: Error) => void;\r\n private saving = false;\r\n private pendingSave = false;\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.adapter = options.adapter ?? new LocalStorageAdapter();\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 async load(): Promise<CanvasState | null> {\r\n const json = await this.adapter.load(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 async clear(): Promise<void> {\r\n await this.adapter.clear(this.key);\r\n }\r\n\r\n private scheduleSave(): void {\r\n this.cancelPending();\r\n this.timerId = setTimeout(() => void 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 async save(): Promise<void> {\r\n if (this.saving) {\r\n this.pendingSave = true;\r\n return;\r\n }\r\n this.saving = true;\r\n try {\r\n const layers = this.layerManager?.snapshot() ?? [];\r\n const state = exportState(this.store.snapshot(), this.camera, layers);\r\n await this.adapter.save(this.key, JSON.stringify(state));\r\n } catch (e) {\r\n this.onError?.(e instanceof Error ? e : new Error(String(e)));\r\n } finally {\r\n this.saving = false;\r\n if (this.pendingSave) {\r\n this.pendingSave = false;\r\n void this.save();\r\n }\r\n }\r\n }\r\n}\r\n","import type { StorageAdapter } from './storage-adapter';\r\n\r\nexport class MemoryAdapter implements StorageAdapter {\r\n private store = new Map<string, string>();\r\n async load(key: string): Promise<string | null> {\r\n return this.store.get(key) ?? null;\r\n }\r\n async save(key: string, value: string): Promise<void> {\r\n this.store.set(key, value);\r\n }\r\n async clear(key: string): Promise<void> {\r\n this.store.delete(key);\r\n }\r\n}\r\n","import type { StorageAdapter } from './storage-adapter';\r\n\r\nexport interface IndexedDBAdapterOptions {\r\n dbName?: string;\r\n storeName?: string;\r\n indexedDB?: IDBFactory;\r\n}\r\n\r\nconst DEFAULT_DB = 'fieldnotes';\r\nconst DEFAULT_STORE = 'state';\r\n\r\nexport class IndexedDBAdapter implements StorageAdapter {\r\n private readonly dbName: string;\r\n private readonly storeName: string;\r\n private readonly idb: IDBFactory | null;\r\n private dbPromise: Promise<IDBDatabase> | null = null;\r\n\r\n constructor(options: IndexedDBAdapterOptions = {}) {\r\n this.dbName = options.dbName ?? DEFAULT_DB;\r\n this.storeName = options.storeName ?? DEFAULT_STORE;\r\n this.idb = options.indexedDB ?? (typeof indexedDB !== 'undefined' ? indexedDB : null);\r\n }\r\n\r\n private open(): Promise<IDBDatabase> {\r\n const idb = this.idb;\r\n if (!idb) return Promise.reject(new Error('IndexedDB unavailable'));\r\n if (!this.dbPromise) {\r\n const storeName = this.storeName;\r\n this.dbPromise = new Promise((resolve, reject) => {\r\n const req = idb.open(this.dbName, 1);\r\n req.onupgradeneeded = () => {\r\n const db = req.result;\r\n if (!db.objectStoreNames.contains(storeName)) db.createObjectStore(storeName);\r\n };\r\n req.onsuccess = () => resolve(req.result);\r\n req.onerror = () => reject(req.error ?? new Error('IndexedDB open failed'));\r\n });\r\n }\r\n return this.dbPromise;\r\n }\r\n\r\n async load(key: string): Promise<string | null> {\r\n if (!this.idb) return null;\r\n const db = await this.open();\r\n return new Promise((resolve, reject) => {\r\n const req = db.transaction(this.storeName, 'readonly').objectStore(this.storeName).get(key);\r\n req.onsuccess = () => {\r\n const v = req.result;\r\n resolve(typeof v === 'string' ? v : null);\r\n };\r\n req.onerror = () => reject(req.error ?? new Error('IndexedDB read failed'));\r\n });\r\n }\r\n\r\n async save(key: string, value: string): Promise<void> {\r\n if (!this.idb) return;\r\n const db = await this.open();\r\n return new Promise((resolve, reject) => {\r\n const tx = db.transaction(this.storeName, 'readwrite');\r\n tx.objectStore(this.storeName).put(value, key);\r\n tx.oncomplete = () => resolve();\r\n tx.onerror = () => reject(tx.error ?? new Error('IndexedDB write failed'));\r\n tx.onabort = () => reject(tx.error ?? new Error('IndexedDB write aborted'));\r\n });\r\n }\r\n\r\n async clear(key: string): Promise<void> {\r\n if (!this.idb) return;\r\n const db = await this.open();\r\n return new Promise((resolve, reject) => {\r\n const tx = db.transaction(this.storeName, 'readwrite');\r\n tx.objectStore(this.storeName).delete(key);\r\n tx.oncomplete = () => resolve();\r\n tx.onerror = () => reject(tx.error ?? new Error('IndexedDB delete failed'));\r\n tx.onabort = () => reject(tx.error ?? new Error('IndexedDB delete aborted'));\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;\r\n\r\nexport function randomClientComponent(): string {\r\n // getRandomValues works in NON-secure contexts (an iPad on http://LAN) — unlike crypto.randomUUID, which\r\n // is secure-context-gated in browsers. Uniqueness, not security.\r\n if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {\r\n const bytes = new Uint8Array(8);\r\n crypto.getRandomValues(bytes);\r\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join(''); // 16 hex = 64 bits\r\n }\r\n return Math.random().toString(36).slice(2, 14); // last resort — no crypto at all\r\n}\r\n\r\n// Per-process (per tab/worker) client component — generated ONCE at module load so two clients never collide\r\n// even at counter 0 in the same millisecond.\r\nconst CLIENT = randomClientComponent();\r\n\r\n// Internal (module-exported for tests; NOT in the package barrel — see index.ts / index.test.ts `removed`).\r\nexport function formatId(prefix: string, time: string, counter: string, client: string): string {\r\n return `${prefix}_${time}_${counter}_${client}`;\r\n}\r\n\r\nexport function createId(prefix: string): string {\r\n return formatId(prefix, Date.now().toString(36), (counter++).toString(36), CLIENT);\r\n}\r\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 // The bend handle sits at the curve midpoint (getArrowMidpoint), which is HALF the control-point\r\n // offset. Double the projection so the handle tracks the pointer 1:1 (bend is the control-point offset).\r\n return 2 * ((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 { rotatedAABB } from '../core/geometry';\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\n/** Axis-aligned world bounds covering the element's complete rotated visual footprint. */\r\nexport function getElementVisualBounds(element: CanvasElement): Bounds | null {\r\n const bounds = getElementBounds(element);\r\n if (!bounds) return null;\r\n const rotation = element.rotation ?? 0;\r\n return rotation === 0 ? bounds : rotatedAABB(bounds, rotation);\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 case 'rectangle': {\r\n const halfW = (el.width ?? 0) / 2;\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 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 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 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\nimport type { RotateDirection } from './selection-rotate';\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 rotate?: (direction: RotateDirection) => 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 private selectableElements(ctx: ToolContext): CanvasElement[] {\r\n return ctx.store\r\n .getAll()\r\n .filter(\r\n (el) =>\r\n !el.locked &&\r\n (ctx.isLayerVisible?.(el.layerId) ?? true) &&\r\n !(ctx.isLayerLocked?.(el.layerId) ?? false),\r\n );\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 const recorder = this.deps.getHistoryRecorder();\r\n if (recorder?.currentTransactionId !== this.nudgeTxId) {\r\n recorder?.begin();\r\n this.nudgeTxId = recorder?.currentTransactionId ?? null;\r\n }\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 (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 = this.selectableElements(sel.ctx).map((el) => el.id);\r\n sel.tool.setSelection(ids);\r\n sel.ctx.requestRender();\r\n }\r\n\r\n cycleSelection(direction: 1 | -1): 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') ctx.switchTool?.('select');\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const eligible = this.selectableElements(sel.ctx).filter((el) => el.type !== 'grid');\r\n if (eligible.length === 0) return;\r\n const idxs = sel.tool.selectedIds\r\n .map((id) => eligible.findIndex((e) => e.id === id))\r\n .filter((i) => i >= 0);\r\n const anchor =\r\n idxs.length === 0\r\n ? direction > 0\r\n ? -1\r\n : 0\r\n : direction > 0\r\n ? Math.max(...idxs)\r\n : Math.min(...idxs);\r\n const next = (anchor + direction + eligible.length) % eligible.length;\r\n const target = eligible[next];\r\n if (!target) return;\r\n sel.tool.setSelection([target.id]);\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 rotate(direction: RotateDirection): 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 if (sel.tool.selectedIds.length === 0) return;\r\n this.deps.rotate?.(direction);\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 ['cycle-selection', ['tab']],\r\n ['cycle-selection-reverse', ['shift+tab']],\r\n ['copy', ['mod+c']],\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 ['rotate-cw', ['r']],\r\n ['rotate-ccw', ['shift+r']],\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 addImage: (src: string, world: { x: number; y: number }) => string;\r\n getLastPointerWorld: () => { x: number; y: number } | null;\r\n getCenteredWorld: () => { x: number; y: number };\r\n onPaste?: (e: ClipboardEvent, world: { x: number; y: number }) => 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 window.addEventListener('paste', this.onPaste, { 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 private shouldHandle(target: EventTarget | null): boolean {\r\n const el = target as HTMLElement | null;\r\n if (el?.isContentEditable) return false;\r\n const tag = el?.tagName;\r\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return false;\r\n return this.isInScope();\r\n }\r\n\r\n onKeyDown = (e: KeyboardEvent): void => {\r\n if (!this.shouldHandle(e.target)) 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 onPaste = (e: ClipboardEvent): void => {\r\n if (!this.shouldHandle(e.target)) return;\r\n const items = e.clipboardData?.items;\r\n let file: File | null = null;\r\n if (items) {\r\n for (const it of items) {\r\n if (it.kind === 'file' && it.type.startsWith('image/')) {\r\n file = it.getAsFile();\r\n break;\r\n }\r\n }\r\n }\r\n if (file) {\r\n e.preventDefault();\r\n const world = this.deps.getLastPointerWorld() ?? this.deps.getCenteredWorld();\r\n if (this.deps.onPaste) {\r\n this.deps.onPaste(e, world);\r\n return;\r\n }\r\n const reader = new FileReader();\r\n reader.onload = () => {\r\n if (typeof reader.result === 'string') this.deps.addImage(reader.result, world);\r\n };\r\n reader.readAsDataURL(file);\r\n return;\r\n }\r\n this.deps.actions.paste();\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 'cycle-selection':\r\n e?.preventDefault();\r\n this.deps.actions.cycleSelection(1);\r\n return;\r\n case 'cycle-selection-reverse':\r\n e?.preventDefault();\r\n this.deps.actions.cycleSelection(-1);\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 'rotate-cw':\r\n e?.preventDefault();\r\n this.deps.actions.rotate('cw');\r\n return;\r\n case 'rotate-ccw':\r\n e?.preventDefault();\r\n this.deps.actions.rotate('ccw');\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","export interface PanInertiaDeps {\r\n pan: (dx: number, dy: number) => void;\r\n now: () => number;\r\n requestFrame: (cb: () => void) => number;\r\n cancelFrame: (id: number) => void;\r\n enabled: () => boolean;\r\n}\r\n\r\n// Only the last VELOCITY_WINDOW_MS of drag samples count toward release velocity,\r\n// so a paused or slow finger at release does not produce a coast.\r\nconst VELOCITY_WINDOW_MS = 60;\r\nconst FRICTION = 0.92;\r\nconst MIN_START_SPEED = 2;\r\nconst MIN_STOP_SPEED = 0.3;\r\n\r\ninterface Sample {\r\n dx: number;\r\n dy: number;\r\n t: number;\r\n}\r\n\r\nexport class PanInertia {\r\n private samples: Sample[] = [];\r\n private vx = 0;\r\n private vy = 0;\r\n private rafId: number | null = null;\r\n\r\n constructor(private readonly deps: PanInertiaDeps) {}\r\n\r\n sample(dx: number, dy: number): void {\r\n const t = this.deps.now();\r\n this.samples.push({ dx, dy, t });\r\n this.prune(t);\r\n }\r\n\r\n release(): void {\r\n if (!this.deps.enabled()) {\r\n this.reset();\r\n return;\r\n }\r\n const t = this.deps.now();\r\n this.prune(t);\r\n const recent = this.samples;\r\n if (recent.length === 0) {\r\n this.reset();\r\n return;\r\n }\r\n let sx = 0;\r\n let sy = 0;\r\n for (const s of recent) {\r\n sx += s.dx;\r\n sy += s.dy;\r\n }\r\n this.vx = sx / recent.length;\r\n this.vy = sy / recent.length;\r\n this.samples = [];\r\n if (Math.hypot(this.vx, this.vy) < MIN_START_SPEED) {\r\n this.vx = 0;\r\n this.vy = 0;\r\n return;\r\n }\r\n this.rafId = this.deps.requestFrame(this.step);\r\n }\r\n\r\n cancel(): void {\r\n this.reset();\r\n }\r\n\r\n private step = (): void => {\r\n if (this.rafId === null) return;\r\n this.deps.pan(this.vx, this.vy);\r\n this.vx *= FRICTION;\r\n this.vy *= FRICTION;\r\n if (Math.hypot(this.vx, this.vy) >= MIN_STOP_SPEED) {\r\n this.rafId = this.deps.requestFrame(this.step);\r\n } else {\r\n this.reset();\r\n }\r\n };\r\n\r\n private prune(now: number): void {\r\n const cutoff = now - VELOCITY_WINDOW_MS;\r\n this.samples = this.samples.filter((s) => s.t >= cutoff);\r\n }\r\n\r\n private reset(): void {\r\n if (this.rafId !== null) {\r\n this.deps.cancelFrame(this.rafId);\r\n this.rafId = null;\r\n }\r\n this.samples = [];\r\n this.vx = 0;\r\n this.vy = 0;\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 type { RotateDirection } from './selection-rotate';\r\nimport { InputFilter } from './input-filter';\r\nimport { KeyboardActions } from './keyboard-actions';\r\nimport { KeyboardHandler } from './keyboard-handler';\r\nimport { PanInertia } from './pan-inertia';\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 rotate?: (direction: RotateDirection) => void;\r\n openContextMenu?: (screenPos: Point, world: Point) => void;\r\n shortcuts?: ShortcutOptions;\r\n addImage?: (src: string, world: { x: number; y: number }) => string;\r\n getCenteredWorld?: () => { x: number; y: number };\r\n onPaste?: (event: ClipboardEvent, worldPosition: { x: number; y: number }) => void;\r\n panInertia?: boolean;\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 private readonly panInertia: PanInertia;\r\n private readonly panInertiaEnabled: boolean;\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 rotate: options.rotate,\r\n getLastPointerWorld: () => this.lastPointerWorld(),\r\n });\r\n this.openContextMenu = options.openContextMenu;\r\n this.panInertiaEnabled = options.panInertia ?? true;\r\n this.panInertia = new PanInertia({\r\n pan: (dx, dy) => this.camera.pan(dx, dy),\r\n now: () => (typeof performance !== 'undefined' ? performance.now() : Date.now()),\r\n requestFrame: (cb) =>\r\n typeof requestAnimationFrame !== 'undefined' ? requestAnimationFrame(cb) : 0,\r\n cancelFrame: (id) => {\r\n if (typeof cancelAnimationFrame !== 'undefined') cancelAnimationFrame(id);\r\n },\r\n enabled: () => this.panInertiaEnabled,\r\n });\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 addImage: options.addImage ?? (() => ''),\r\n getLastPointerWorld: () => this.lastPointerWorld(),\r\n getCenteredWorld: options.getCenteredWorld ?? (() => ({ x: 0, y: 0 })),\r\n onPaste: options.onPaste,\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.panInertia.cancel();\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 this.panInertia.cancel();\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.panInertia.cancel();\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 this.panInertia.sample(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 const removedActivePointer = this.activePointers.delete(e.pointerId);\r\n\r\n if (removedActivePointer && this.activePointers.size >= 2) {\r\n // Pointer membership may have changed the first-two navigation pair. Rebaseline before the\r\n // next move so the replacement pointer cannot produce a discontinuous pan or zoom.\r\n this.startPinch();\r\n } else if (this.activePointers.size < 2) {\r\n this.lastPinchDistance = 0;\r\n const remainingPointer = this.activePointers.values().next().value;\r\n if (remainingPointer && this.isPanning) {\r\n this.lastPointer = { ...remainingPointer };\r\n }\r\n }\r\n\r\n if (this.isPanning && this.activePointers.size === 0) {\r\n this.isPanning = false;\r\n this.panInertia.release();\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.panInertia.cancel();\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 const rect = this.element.getBoundingClientRect();\r\n this.camera.zoomAt(newZoom, {\r\n x: center.x - rect.left,\r\n y: center.y - rect.top,\r\n });\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 this.panInertia.sample(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","export interface EventMeta {\r\n origin?: string;\r\n}\r\n\r\nconst EMPTY_META: EventMeta = Object.freeze({});\r\n\r\ntype Listener<T> = (data: T, meta: EventMeta) => 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], meta: EventMeta = EMPTY_META): void {\r\n this.listeners.get(event)?.forEach((listener) => {\r\n try {\r\n listener(data as never, meta);\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\nfunction contains(outer: Bounds, inner: Bounds): boolean {\r\n return (\r\n inner.x >= outer.x &&\r\n inner.x + inner.w <= outer.x + outer.w &&\r\n inner.y >= outer.y &&\r\n inner.y + inner.h <= outer.y + outer.h\r\n );\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 collect(result: Entry[]): void {\r\n result.push(...this.items);\r\n if (this.children) {\r\n for (const child of this.children) {\r\n child.collect(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.expandToFit(bounds);\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 private expandToFit(bounds: Bounds): void {\r\n const current = this.root.bounds;\r\n if (contains(current, bounds)) return;\r\n\r\n const currentRight = current.x + current.w;\r\n const currentBottom = current.y + current.h;\r\n const requiredWidth =\r\n Math.max(currentRight, bounds.x + bounds.w) - Math.min(current.x, bounds.x);\r\n const requiredHeight =\r\n Math.max(currentBottom, bounds.y + bounds.h) - Math.min(current.y, bounds.y);\r\n const width = Math.max(current.w * 2, requiredWidth);\r\n const height = Math.max(current.h * 2, requiredHeight);\r\n const x = bounds.x < current.x ? currentRight - width : current.x;\r\n const y = bounds.y < current.y ? currentBottom - height : current.y;\r\n\r\n const entries: Entry[] = [];\r\n this.root.collect(entries);\r\n this.root = new QuadNode({ x, y, w: width, h: height }, 0);\r\n for (const entry of entries) {\r\n this.root.insert(entry);\r\n }\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 { getElementVisualBounds, 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\nfunction sanitizeRichText(element: CanvasElement): CanvasElement {\r\n if (element.type !== 'note' && element.type !== 'text') return element;\r\n const text = sanitizeNoteHtml(element.text);\r\n return text === element.text ? element : { ...element, text };\r\n}\r\n\r\nexport interface ElementUpdateEvent {\r\n previous: CanvasElement;\r\n current: CanvasElement;\r\n}\r\n\r\nexport interface ElementChangeMeta {\r\n /**\r\n * Identifies what caused the change. `undefined` or `'local'` = a local change (recorded to undo\r\n * history and observed as local). Any other value (e.g. `'remote'`) marks an externally-applied\r\n * change: it is NOT recorded to undo history, and is tagged so observers can avoid re-broadcasting it.\r\n */\r\n origin?: string;\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 return getElementVisualBounds(element);\r\n }\r\n\r\n add(element: CanvasElement, meta?: ElementChangeMeta): void {\r\n element = sanitizeRichText(element);\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, meta);\r\n }\r\n\r\n update(id: string, partial: Partial<CanvasElement>, meta?: ElementChangeMeta): 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' || updated.type === 'text') && '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 }, meta);\r\n }\r\n\r\n remove(id: string, meta?: ElementChangeMeta): 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, meta);\r\n }\r\n\r\n clear(meta?: ElementChangeMeta): 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, meta);\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[], meta?: ElementChangeMeta): void {\r\n const sanitizedElements = elements.map(sanitizeRichText);\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 sanitizedElements) {\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, meta);\r\n for (const el of sanitizedElements) {\r\n this.bus.emit('add', el, meta);\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], meta: ElementChangeMeta) => 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, ArrowStrokeStyle } 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 getArrowDashPattern(strokeStyle: ArrowStrokeStyle | undefined): number[] {\r\n switch (strokeStyle) {\r\n case 'dashed':\r\n return [8, 4];\r\n case 'dotted':\r\n return [2, 4];\r\n default:\r\n return [];\r\n }\r\n}\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 const dash = getArrowDashPattern(arrow.strokeStyle);\r\n if (dash.length > 0) ctx.setLineDash(dash);\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\nexport function 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 getHexCellsInRectangle(\r\n center: Point,\r\n angle: number,\r\n lengthCells: number,\r\n widthCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const nLen = Math.round(lengthCells);\r\n const wCells = Math.max(1, Math.round(widthCells));\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 (nLen <= 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 = nLen * snapUnit;\r\n const halfWidth = (wCells * snapUnit) / 2 + 1e-6;\r\n const iterM = nLen + Math.ceil(wCells / 2) + 1;\r\n const cells: Point[] = [];\r\n\r\n for (let dq = -iterM; dq <= iterM; dq++) {\r\n const rMin = Math.max(-iterM, -dq - iterM);\r\n const rMax = Math.min(iterM, -dq + iterM);\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 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 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 { Point } from '../../core/types';\r\nimport type { TemplateShape } from '../types';\r\n\r\nexport interface TemplateFeetLabelParams {\r\n position: Point;\r\n radius: number;\r\n angle: number;\r\n templateShape: TemplateShape;\r\n feet: number;\r\n color: string;\r\n}\r\n\r\nexport function renderTemplateFeetLabel(\r\n ctx: CanvasRenderingContext2D,\r\n p: TemplateFeetLabelParams,\r\n): void {\r\n if (p.feet <= 0) return;\r\n\r\n const directional =\r\n p.templateShape === 'cone' || p.templateShape === 'line' || p.templateShape === 'rectangle';\r\n const dir = directional ? p.angle : 0;\r\n const length = p.templateShape === 'square' ? p.radius / 2 : p.radius;\r\n const cos = Math.cos(dir);\r\n const sin = Math.sin(dir);\r\n const start = p.position;\r\n const end = { x: start.x + length * cos, y: start.y + length * sin };\r\n const midX = start.x + (length / 2) * cos;\r\n const midY = start.y + (length / 2) * sin;\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 = p.color;\r\n ctx.lineWidth = 1.5;\r\n ctx.moveTo(start.x, start.y);\r\n ctx.lineTo(end.x, end.y);\r\n ctx.stroke();\r\n ctx.setLineDash([]);\r\n\r\n const label = `${Math.round(p.feet)} ft`;\r\n const fontSize = Math.max(10, Math.min(14, p.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 textY = midY - 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(midX - textW / 2, textY - textH, textW, textH, 3);\r\n ctx.fill();\r\n\r\n ctx.fillStyle = p.color;\r\n ctx.fillText(label, midX, textY - padY);\r\n\r\n ctx.restore();\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 getHexCellsInRectangle,\r\n drawHexPath,\r\n} from '../hex-fill';\r\nimport { renderTemplateFeetLabel } from './template-measure';\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' && template.renderStyle !== 'geometric') {\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 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 case 'rectangle': {\r\n const halfW = (template.width ?? 0) / 2;\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 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 if (template.radiusFeet != null && template.radiusFeet > 0) {\r\n renderTemplateFeetLabel(ctx, {\r\n position: template.position,\r\n radius: template.radius,\r\n angle: template.angle,\r\n templateShape: template.templateShape,\r\n feet: template.radiusFeet,\r\n color: template.strokeColor,\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 case 'rectangle': {\r\n const widthCells = (template.width ?? 0) / snapUnit;\r\n cells = getHexCellsInRectangle(\r\n center,\r\n template.angle,\r\n radiusCells,\r\n widthCells,\r\n cellSize,\r\n orientation,\r\n );\r\n break;\r\n }\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 (template.radiusFeet != null && template.radiusFeet > 0) {\r\n renderTemplateFeetLabel(ctx, {\r\n position: template.position,\r\n radius: template.radius,\r\n angle: template.angle,\r\n templateShape: template.templateShape,\r\n feet: template.radiusFeet,\r\n color: template.strokeColor,\r\n });\r\n }\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 ArrowStrokeStyle,\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 TemplateRenderStyle,\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 strokeStyle?: ArrowStrokeStyle;\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 htmlType?: string;\r\n data?: Record<string, unknown>;\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 if (input.strokeStyle !== undefined) result.strokeStyle = input.strokeStyle;\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 if (input.htmlType) el.htmlType = input.htmlType;\r\n if (input.data) el.data = input.data;\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: sanitizeNoteHtml(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 width?: 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 renderStyle?: TemplateRenderStyle;\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 ...(input.renderStyle !== undefined ? { renderStyle: input.renderStyle } : {}),\r\n ...(input.width !== undefined ? { width: input.width } : {}),\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 onInputCallback: ((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 setOnInput(callback: (elementId: string) => void): void {\r\n this.onInputCallback = 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 // The history transaction spans the whole edit session: opened at activate, committed\r\n // here at stop. Live height fits during editing plus the final text write all touch the\r\n // same element, so the recorder coalesces them into one undo step.\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 this.beginHistory?.();\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 this.onInputCallback?.(elementId);\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","import type { Bounds, Point } from '../core/types';\r\n\r\nexport interface MinimapTransform {\r\n scale: number;\r\n offsetX: number;\r\n offsetY: number;\r\n}\r\n\r\nexport function unionBounds(a: Bounds, b: Bounds): Bounds {\r\n const minX = Math.min(a.x, b.x);\r\n const minY = Math.min(a.y, b.y);\r\n const maxX = Math.max(a.x + a.w, b.x + b.w);\r\n const maxY = Math.max(a.y + a.h, b.y + b.h);\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n\r\n// `mapping` is the union of the content bounds and the visible viewport, so the\r\n// minimap always frames both what exists and where the camera is looking.\r\nexport function computeMinimapTransform(\r\n mapping: Bounds,\r\n miniW: number,\r\n miniH: number,\r\n padding: number,\r\n): MinimapTransform {\r\n const availW = Math.max(1, miniW - 2 * padding);\r\n const availH = Math.max(1, miniH - 2 * padding);\r\n const w = Math.max(mapping.w, 1);\r\n const h = Math.max(mapping.h, 1);\r\n const scale = Math.min(availW / w, availH / h);\r\n const offsetX = (miniW - mapping.w * scale) / 2 - mapping.x * scale;\r\n const offsetY = (miniH - mapping.h * scale) / 2 - mapping.y * scale;\r\n return { scale, offsetX, offsetY };\r\n}\r\n\r\nexport function worldToMini(t: MinimapTransform, p: Point): Point {\r\n return { x: p.x * t.scale + t.offsetX, y: p.y * t.scale + t.offsetY };\r\n}\r\n\r\nexport function miniToWorld(t: MinimapTransform, p: Point): Point {\r\n return { x: (p.x - t.offsetX) / t.scale, y: (p.y - t.offsetY) / t.scale };\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport {\r\n computeMinimapTransform,\r\n miniToWorld,\r\n unionBounds,\r\n worldToMini,\r\n type MinimapTransform,\r\n} from './minimap-transform';\r\n\r\nexport interface MinimapDeps {\r\n container: HTMLElement;\r\n getElements: () => CanvasElement[];\r\n getContentBounds: () => Bounds | null;\r\n getViewportRect: () => Bounds;\r\n navigateTo: (worldCenter: Point) => void;\r\n requestFrame: (cb: () => void) => number;\r\n cancelFrame: (id: number) => void;\r\n}\r\n\r\nconst WIDTH = 200;\r\nconst HEIGHT = 140;\r\nconst MARGIN = 16;\r\nconst PADDING = 8;\r\nconst NEUTRAL = 'rgba(100,116,139,0.6)';\r\nconst VIEWPORT_STROKE = '#3b82f6';\r\n\r\nfunction elementColor(el: CanvasElement): string {\r\n return 'color' in el && typeof el.color === 'string' ? el.color : NEUTRAL;\r\n}\r\n\r\nexport class Minimap {\r\n private readonly canvas: HTMLCanvasElement;\r\n private rafId: number | null = null;\r\n private dragging = false;\r\n\r\n constructor(private readonly deps: MinimapDeps) {\r\n const canvas = document.createElement('canvas');\r\n canvas.width = WIDTH;\r\n canvas.height = HEIGHT;\r\n Object.assign(canvas.style, {\r\n position: 'absolute',\r\n right: `${MARGIN}px`,\r\n bottom: `${MARGIN}px`,\r\n width: `${WIDTH}px`,\r\n height: `${HEIGHT}px`,\r\n background: 'rgba(255,255,255,0.85)',\r\n border: '1px solid rgba(0,0,0,0.15)',\r\n borderRadius: '4px',\r\n touchAction: 'none',\r\n cursor: 'pointer',\r\n zIndex: '10',\r\n });\r\n canvas.addEventListener('pointerdown', this.onPointerDown);\r\n canvas.addEventListener('pointermove', this.onPointerMove);\r\n canvas.addEventListener('pointerup', this.onPointerUp);\r\n this.deps.container.appendChild(canvas);\r\n this.canvas = canvas;\r\n }\r\n\r\n scheduleDraw(): void {\r\n if (this.rafId !== null) return;\r\n this.rafId = this.deps.requestFrame(this.draw);\r\n }\r\n\r\n destroy(): void {\r\n if (this.rafId !== null) {\r\n this.deps.cancelFrame(this.rafId);\r\n this.rafId = null;\r\n }\r\n this.canvas.removeEventListener('pointerdown', this.onPointerDown);\r\n this.canvas.removeEventListener('pointermove', this.onPointerMove);\r\n this.canvas.removeEventListener('pointerup', this.onPointerUp);\r\n this.canvas.remove();\r\n }\r\n\r\n private currentTransform(): MinimapTransform {\r\n const viewport = this.deps.getViewportRect();\r\n const content = this.deps.getContentBounds();\r\n const mapping = content ? unionBounds(content, viewport) : viewport;\r\n return computeMinimapTransform(mapping, WIDTH, HEIGHT, PADDING);\r\n }\r\n\r\n private draw = (): void => {\r\n this.rafId = null;\r\n const ctx = this.canvas.getContext('2d');\r\n if (!ctx) return;\r\n const t = this.currentTransform();\r\n const viewport = this.deps.getViewportRect();\r\n ctx.clearRect(0, 0, WIDTH, HEIGHT);\r\n for (const el of this.deps.getElements()) {\r\n const b = getElementBounds(el);\r\n if (!b) continue;\r\n const tl = worldToMini(t, { x: b.x, y: b.y });\r\n ctx.fillStyle = elementColor(el);\r\n ctx.fillRect(tl.x, tl.y, Math.max(1, b.w * t.scale), Math.max(1, b.h * t.scale));\r\n }\r\n const vtl = worldToMini(t, { x: viewport.x, y: viewport.y });\r\n ctx.strokeStyle = VIEWPORT_STROKE;\r\n ctx.lineWidth = 1.5;\r\n ctx.strokeRect(vtl.x, vtl.y, viewport.w * t.scale, viewport.h * t.scale);\r\n };\r\n\r\n private navigateFromEvent(e: PointerEvent): void {\r\n const rect = this.canvas.getBoundingClientRect();\r\n const point = { x: e.clientX - rect.left, y: e.clientY - rect.top };\r\n const world = miniToWorld(this.currentTransform(), point);\r\n this.deps.navigateTo(world);\r\n }\r\n\r\n private onPointerDown = (e: PointerEvent): void => {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n this.dragging = true;\r\n this.canvas.setPointerCapture?.(e.pointerId);\r\n this.navigateFromEvent(e);\r\n };\r\n\r\n private onPointerMove = (e: PointerEvent): void => {\r\n if (!this.dragging) return;\r\n e.stopPropagation();\r\n this.navigateFromEvent(e);\r\n };\r\n\r\n private onPointerUp = (e: PointerEvent): void => {\r\n this.dragging = false;\r\n try {\r\n this.canvas.releasePointerCapture(e.pointerId);\r\n } catch {\r\n // already released\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\r\nexport function createPaintStack(): HTMLDivElement {\r\n const el = createDomLayer();\r\n el.dataset['fieldnotesPaintStack'] = '';\r\n el.style.transformOrigin = '';\r\n return el;\r\n}\r\n","export class HybridRenderSurface {\r\n private readonly canvases = new Map<number, HTMLCanvasElement>();\r\n\r\n constructor(private readonly root: HTMLDivElement) {}\r\n\r\n beginFrame(activeOrders: ReadonlySet<number>, width: number, height: number): void {\r\n for (const [order, canvas] of this.canvases) {\r\n if (!activeOrders.has(order)) {\r\n canvas.remove();\r\n this.canvases.delete(order);\r\n }\r\n }\r\n\r\n for (const order of activeOrders) {\r\n const canvas = this.getCanvas(order);\r\n if (canvas.width !== width) canvas.width = width;\r\n if (canvas.height !== height) canvas.height = height;\r\n canvas.style.zIndex = String(order);\r\n }\r\n }\r\n\r\n getContext(order: number): CanvasRenderingContext2D | null {\r\n return this.getCanvas(order).getContext('2d');\r\n }\r\n\r\n clear(): void {\r\n for (const canvas of this.canvases.values()) canvas.remove();\r\n this.canvases.clear();\r\n }\r\n\r\n private getCanvas(order: number): HTMLCanvasElement {\r\n let canvas = this.canvases.get(order);\r\n if (canvas) return canvas;\r\n\r\n canvas = document.createElement('canvas');\r\n canvas.dataset['paintOrder'] = String(order);\r\n Object.assign(canvas.style, {\r\n position: 'absolute',\r\n inset: '0',\r\n width: '100%',\r\n height: '100%',\r\n pointerEvents: 'none',\r\n });\r\n this.root.appendChild(canvas);\r\n this.canvases.set(order, canvas);\r\n return canvas;\r\n }\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 { EventMeta } from '../core/event-bus';\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\nfunction isExternalChange(meta: EventMeta): boolean {\r\n return meta.origin !== undefined && meta.origin !== 'local';\r\n}\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, meta) => this.onAdd(el, meta)),\r\n store.on('remove', (el, meta) => this.onRemove(el, meta)),\r\n store.on('update', ({ previous, current }, meta) => this.onUpdate(previous, current, meta)),\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, meta: EventMeta): void {\r\n if (isExternalChange(meta)) return;\r\n if (!this.recording) return;\r\n this.record(new AddElementCommand(element));\r\n }\r\n\r\n private onRemove(element: CanvasElement, meta: EventMeta): void {\r\n if (isExternalChange(meta)) return;\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, meta: EventMeta): void {\r\n if (isExternalChange(meta)) return;\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 { parseStyledRuns };\r\nexport type { StyledRun };\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\ninterface LineFragment {\r\n text: string;\r\n font: string;\r\n x: number;\r\n width: number;\r\n fontSize: number;\r\n underline: boolean;\r\n strikethrough: boolean;\r\n}\r\n\r\ninterface LaidOutLine {\r\n y: number;\r\n width: number;\r\n fragments: LineFragment[];\r\n}\r\n\r\nexport function renderStyledRuns(\r\n ctx: CanvasRenderingContext2D,\r\n runs: StyledRun[],\r\n startX: number,\r\n startY: number,\r\n maxWidth: number,\r\n opts: { align?: 'left' | 'center' | 'right'; lineHeight?: number } = {},\r\n): void {\r\n const align = opts.align ?? 'left';\r\n const lhMul = opts.lineHeight ?? 1.3;\r\n ctx.textBaseline = 'top';\r\n\r\n // PASS 1 — lay runs out into lines (no drawing). Wrap behaviour mirrors the\r\n // original single-pass renderer exactly so wrap points are alignment-agnostic.\r\n const lines: LaidOutLine[] = [];\r\n let cursorX = startX;\r\n let lineY = startY;\r\n let lineHeight = 0;\r\n let fragments: LineFragment[] = [];\r\n\r\n const finalizeLine = (): void => {\r\n const last = fragments[fragments.length - 1];\r\n const width = last ? last.x + last.width : 0;\r\n lines.push({ y: lineY, width, fragments });\r\n };\r\n\r\n const breakLine = (runLineHeight: number): void => {\r\n finalizeLine();\r\n lineY += lineHeight;\r\n lineHeight = runLineHeight;\r\n fragments = [];\r\n cursorX = startX;\r\n };\r\n\r\n for (const run of runs) {\r\n const font = buildFontString(run);\r\n ctx.font = font;\r\n const runLineHeight = run.fontSize * lhMul;\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 breakLine(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 breakLine(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 breakLine(runLineHeight);\r\n }\r\n\r\n fragments.push({\r\n text: word,\r\n font,\r\n x: cursorX - startX,\r\n width: metrics.width,\r\n fontSize: run.fontSize,\r\n underline: run.underline,\r\n strikethrough: run.strikethrough,\r\n });\r\n cursorX += metrics.width;\r\n }\r\n }\r\n finalizeLine();\r\n\r\n // PASS 2 — draw each line at its alignment offset. For align 'left' the\r\n // offset is 0, so the absolute x equals the original streaming cursorX.\r\n for (const line of lines) {\r\n const offset =\r\n align === 'center'\r\n ? (maxWidth - line.width) / 2\r\n : align === 'right'\r\n ? maxWidth - line.width\r\n : 0;\r\n for (const fragment of line.fragments) {\r\n ctx.font = fragment.font;\r\n const fx = startX + offset + fragment.x;\r\n ctx.fillText(fragment.text, fx, line.y);\r\n\r\n if (fragment.underline) {\r\n ctx.fillRect(fx, line.y + fragment.fontSize + 1, fragment.width, 1);\r\n }\r\n\r\n if (fragment.strikethrough) {\r\n ctx.fillRect(fx, line.y + fragment.fontSize * 0.55, fragment.width, 1);\r\n }\r\n }\r\n }\r\n}\r\n","import type { TextElement } from '../elements/types';\r\nimport { parseStyledRuns, renderStyledRuns } from './note-canvas-renderer';\r\n\r\nexport function renderTextOnCanvas(ctx: CanvasRenderingContext2D, text: TextElement): void {\r\n const pad = 2; // matches the DOM text padding\r\n ctx.save();\r\n ctx.fillStyle = text.color;\r\n const runs = parseStyledRuns(text.text ?? '', text.fontSize);\r\n renderStyledRuns(ctx, runs, text.position.x + pad, text.position.y + pad, text.size.w - pad * 2, {\r\n align: text.textAlign,\r\n lineHeight: 1.4,\r\n });\r\n ctx.restore();\r\n}\r\n","import type { HtmlElement } from '../elements/types';\r\n\r\nexport type HtmlExportRenderer = (\r\n element: HtmlElement,\r\n) => CanvasImageSource | null | Promise<CanvasImageSource | null>;\r\n\r\nexport type HtmlExportErrorReason = 'unsupported' | 'timeout' | 'render' | 'encode';\r\n\r\nexport interface HtmlExportError {\r\n elementId: string;\r\n htmlType?: string;\r\n reason: HtmlExportErrorReason;\r\n cause?: unknown;\r\n}\r\n\r\nexport interface HtmlExportOptions {\r\n /** Converts an application-owned HTML embed into a ready canvas image source. */\r\n renderHtml?: HtmlExportRenderer;\r\n /** Maximum wait for each HTML renderer. Defaults to 10 seconds. */\r\n htmlTimeoutMs?: number;\r\n /** Called when an HTML embed cannot be rendered or encoded. The export continues. */\r\n onHtmlError?: (error: HtmlExportError) => void;\r\n}\r\n\r\nconst DEFAULT_HTML_TIMEOUT_MS = 10_000;\r\nconst TIMEOUT = Symbol('html-export-timeout');\r\n\r\nexport function validateHtmlExportOptions(options: HtmlExportOptions): number {\r\n const timeoutMs = options.htmlTimeoutMs ?? DEFAULT_HTML_TIMEOUT_MS;\r\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\r\n throw new RangeError('htmlTimeoutMs must be a finite number greater than 0');\r\n }\r\n return timeoutMs;\r\n}\r\n\r\nexport async function renderHtmlElements(\r\n elements: HtmlElement[],\r\n options: HtmlExportOptions,\r\n): Promise<Map<string, CanvasImageSource>> {\r\n const timeoutMs = validateHtmlExportOptions(options);\r\n const sources = new Map<string, CanvasImageSource>();\r\n\r\n await Promise.all(\r\n elements.map(async (element) => {\r\n if (!options.renderHtml) {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'unsupported',\r\n });\r\n return;\r\n }\r\n\r\n let timer: ReturnType<typeof setTimeout> | undefined;\r\n try {\r\n const timeout = new Promise<typeof TIMEOUT>((resolve) => {\r\n timer = setTimeout(() => resolve(TIMEOUT), timeoutMs);\r\n });\r\n const result = await Promise.race([Promise.resolve(options.renderHtml(element)), timeout]);\r\n if (result === TIMEOUT) {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'timeout',\r\n });\r\n return;\r\n }\r\n if (!result) {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'render',\r\n });\r\n return;\r\n }\r\n sources.set(element.id, result);\r\n } catch (cause) {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'render',\r\n cause,\r\n });\r\n } finally {\r\n if (timer !== undefined) clearTimeout(timer);\r\n }\r\n }),\r\n );\r\n\r\n return sources;\r\n}\r\n","import type { CanvasElement, GridElement, HtmlElement } 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\nimport { renderTextOnCanvas } from './text-canvas-renderer';\r\nimport { renderHtmlElements, validateHtmlExportOptions } from './html-export';\r\nimport type { HtmlExportOptions } from './html-export';\r\n\r\nexport interface ExportImageOptions extends ExportResourceOptions, HtmlExportOptions {\r\n scale?: number;\r\n padding?: number;\r\n background?: string;\r\n filter?: (element: CanvasElement) => boolean;\r\n}\r\n\r\nexport type ExportAssetErrorReason = 'load' | 'timeout' | 'encode';\r\n\r\nexport interface ExportAssetError {\r\n elementId: string;\r\n src: string;\r\n reason: ExportAssetErrorReason;\r\n cause?: unknown;\r\n}\r\n\r\nexport interface ExportResourceOptions {\r\n /** Maximum wait for each image asset. Defaults to 10 seconds. */\r\n imageTimeoutMs?: number;\r\n /** Maximum width or height of any allocated export canvas. Defaults to 16,384. */\r\n maxDimension?: number;\r\n /** Maximum pixel count of any allocated export canvas. Defaults to 67,108,864. */\r\n maxPixels?: number;\r\n /** Called when an image cannot be loaded or embedded. The export continues. */\r\n onAssetError?: (error: ExportAssetError) => void;\r\n}\r\n\r\nconst DEFAULT_IMAGE_TIMEOUT_MS = 10_000;\r\nconst DEFAULT_MAX_DIMENSION = 16_384;\r\nconst DEFAULT_MAX_PIXELS = 67_108_864;\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 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 positiveOption(value: number | undefined, fallback: number, name: string): number {\r\n const resolved = value ?? fallback;\r\n if (!Number.isFinite(resolved) || resolved <= 0) {\r\n throw new RangeError(`${name} must be a finite number greater than 0`);\r\n }\r\n return resolved;\r\n}\r\n\r\nfunction nonNegativeOption(value: number | undefined, fallback: number, name: string): number {\r\n const resolved = value ?? fallback;\r\n if (!Number.isFinite(resolved) || resolved < 0) {\r\n throw new RangeError(`${name} must be a finite number greater than or equal to 0`);\r\n }\r\n return resolved;\r\n}\r\n\r\nfunction assertExportSize(\r\n width: number,\r\n height: number,\r\n options: Pick<ExportResourceOptions, 'maxDimension' | 'maxPixels'>,\r\n): void {\r\n const maxDimension = positiveOption(options.maxDimension, DEFAULT_MAX_DIMENSION, 'maxDimension');\r\n const maxPixels = positiveOption(options.maxPixels, DEFAULT_MAX_PIXELS, 'maxPixels');\r\n if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {\r\n throw new RangeError('Export dimensions must be finite numbers greater than 0');\r\n }\r\n if (width > maxDimension || height > maxDimension) {\r\n throw new RangeError(\r\n `Export dimensions ${width}x${height} exceed the maximum dimension of ${maxDimension}`,\r\n );\r\n }\r\n if (width * height > maxPixels) {\r\n throw new RangeError(\r\n `Export size ${width}x${height} exceeds the maximum of ${maxPixels} pixels`,\r\n );\r\n }\r\n}\r\n\r\nfunction validateExportResourceOptions(options: ExportResourceOptions): void {\r\n positiveOption(options.imageTimeoutMs, DEFAULT_IMAGE_TIMEOUT_MS, 'imageTimeoutMs');\r\n positiveOption(options.maxDimension, DEFAULT_MAX_DIMENSION, 'maxDimension');\r\n positiveOption(options.maxPixels, DEFAULT_MAX_PIXELS, 'maxPixels');\r\n}\r\n\r\nfunction loadImages(\r\n elements: CanvasElement[],\r\n options: Pick<ExportResourceOptions, 'imageTimeoutMs' | 'onAssetError'> = {},\r\n): 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 const timeoutMs = positiveOption(\r\n options.imageTimeoutMs,\r\n DEFAULT_IMAGE_TIMEOUT_MS,\r\n 'imageTimeoutMs',\r\n );\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 let settled = false;\r\n const timer = setTimeout(() => {\r\n if (settled) return;\r\n settled = true;\r\n img.onload = null;\r\n img.onerror = null;\r\n options.onAssetError?.({ elementId: el.id, src: el.src, reason: 'timeout' });\r\n done();\r\n }, timeoutMs);\r\n const settle = (): boolean => {\r\n if (settled) return false;\r\n settled = true;\r\n clearTimeout(timer);\r\n img.onload = null;\r\n img.onerror = null;\r\n return true;\r\n };\r\n img.onload = () => {\r\n if (!settle()) return;\r\n cache.set(el.id, img);\r\n done();\r\n };\r\n img.onerror = (cause) => {\r\n if (!settle()) return;\r\n options.onAssetError?.({ elementId: el.id, src: el.src, reason: 'load', cause });\r\n done();\r\n };\r\n img.src = el.src;\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 = positiveOption(options.scale, 2, 'scale');\r\n const padding = nonNegativeOption(options.padding, 0, 'padding');\r\n validateExportResourceOptions(options);\r\n validateHtmlExportOptions(options);\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 width = Math.ceil(bounds.w * scale);\r\n const height = Math.ceil(bounds.h * scale);\r\n assertExportSize(width, height, options);\r\n const imageCache = await loadImages(visibleElements, options);\r\n const htmlElements = visibleElements.filter((el): el is HtmlElement => el.type === 'html');\r\n const htmlSources = await renderHtmlElements(htmlElements, options);\r\n\r\n const canvas = document.createElement('canvas');\r\n canvas.width = width;\r\n canvas.height = height;\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 const renderElement = (target: CanvasRenderingContext2D, el: CanvasElement): void => {\r\n if (el.type === 'note') {\r\n const b = getElementBounds(el);\r\n withRotation(target, el, b ? center(b) : el.position, () => renderNoteOnCanvas(target, el));\r\n return;\r\n }\r\n\r\n if (el.type === 'text') {\r\n const b = getElementBounds(el);\r\n withRotation(target, el, b ? center(b) : el.position, () => renderTextOnCanvas(target, el));\r\n return;\r\n }\r\n\r\n if (el.type === 'html') {\r\n const source = htmlSources.get(el.id);\r\n if (!source) return;\r\n const b = getElementBounds(el);\r\n try {\r\n withRotation(target, el, b ? center(b) : el.position, () =>\r\n target.drawImage(source, el.position.x, el.position.y, el.size.w, el.size.h),\r\n );\r\n } catch (cause) {\r\n options.onHtmlError?.({\r\n elementId: el.id,\r\n htmlType: el.htmlType,\r\n reason: 'render',\r\n cause,\r\n });\r\n }\r\n return;\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(target, el, b ? center(b) : el.position, () =>\r\n target.drawImage(img, el.position.x, el.position.y, el.size.w, el.size.h),\r\n );\r\n }\r\n return;\r\n }\r\n\r\n renderer.renderCanvasElement(target, el);\r\n };\r\n\r\n const layerGroups = new Map<string, CanvasElement[]>();\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 const group = layerGroups.get(el.layerId) ?? [];\r\n group.push(el);\r\n layerGroups.set(el.layerId, group);\r\n }\r\n\r\n for (const [layerId, elements] of layerGroups) {\r\n const opacity = layerManager?.getLayer?.(layerId)?.opacity ?? 1;\r\n if (opacity === 1) {\r\n for (const el of elements) renderElement(ctx, el);\r\n continue;\r\n }\r\n\r\n const layerCanvas = document.createElement('canvas');\r\n layerCanvas.width = canvas.width;\r\n layerCanvas.height = canvas.height;\r\n const layerCtx = layerCanvas.getContext('2d');\r\n if (!layerCtx) continue;\r\n layerCtx.scale(scale, scale);\r\n layerCtx.translate(-bounds.x, -bounds.y);\r\n for (const el of elements) renderElement(layerCtx, el);\r\n\r\n ctx.save();\r\n ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n ctx.globalAlpha = opacity;\r\n ctx.drawImage(layerCanvas, 0, 0);\r\n ctx.restore();\r\n }\r\n\r\n for (const grid of grids) {\r\n ctx.save();\r\n ctx.globalAlpha = layerManager?.getLayer?.(grid.layerId)?.opacity ?? 1;\r\n renderGridForBounds(ctx, grid, bounds);\r\n ctx.restore();\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 {\r\n assertExportSize,\r\n computeBounds,\r\n getElementRect,\r\n loadImages,\r\n nonNegativeOption,\r\n positiveOption,\r\n validateExportResourceOptions,\r\n};\r\n","import type {\r\n CanvasElement,\r\n StrokeElement,\r\n ShapeElement,\r\n ArrowElement,\r\n ImageElement,\r\n TextElement,\r\n NoteElement,\r\n GridElement,\r\n TemplateElement,\r\n HtmlElement,\r\n} from '../elements/types';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport { getStrokeRenderData } from '../elements/stroke-cache';\r\nimport { lineEndpoints } from '../elements/shape-geometry';\r\nimport { getArrowControlPoint, getArrowMidpoint } from '../elements/arrow-geometry';\r\nimport { getArrowRenderGeometry } from '../elements/arrow-render-cache';\r\nimport { getVisualEndpoints, getArrowDashPattern } from '../elements/renderers/arrow-renderer';\r\nimport { getSquareGridLines, getHexVertices, getHexCenters } from '../elements/grid-renderer';\r\nimport {\r\n getHexCellsInRadius,\r\n getHexCellsInCone,\r\n getHexCellsInLine,\r\n getHexCellsInSquare,\r\n getHexCellsInRectangle,\r\n} from '../elements/hex-fill';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { renderNoteOnCanvas } from './note-canvas-renderer';\r\nimport { renderTextOnCanvas } from './text-canvas-renderer';\r\nimport {\r\n assertExportSize,\r\n loadImages,\r\n computeBounds,\r\n nonNegativeOption,\r\n positiveOption,\r\n validateExportResourceOptions,\r\n} from './export-image';\r\nimport type { ExportResourceOptions } from './export-image';\r\nimport { renderHtmlElements, validateHtmlExportOptions } from './html-export';\r\nimport type { HtmlExportOptions } from './html-export';\r\n\r\nexport interface ExportSvgOptions extends ExportResourceOptions, HtmlExportOptions {\r\n padding?: number;\r\n background?: string;\r\n filter?: (el: CanvasElement) => boolean;\r\n rasterScale?: number;\r\n}\r\n\r\ninterface Bounds {\r\n x: number;\r\n y: number;\r\n w: number;\r\n h: number;\r\n}\r\n\r\nconst ARROWHEAD_LENGTH = 12;\r\nconst ARROWHEAD_ANGLE = Math.PI / 6;\r\nconst ARROW_LABEL_FONT_SIZE = 14;\r\n\r\nfunction esc(s: string): string {\r\n return s\r\n .replace(/&/g, '&')\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/\"/g, '"')\r\n .replace(/'/g, ''');\r\n}\r\n\r\nconst n = (v: number): string => (Number.isFinite(v) ? `${Math.round(v * 1000) / 1000}` : '0');\r\n\r\nfunction elementCenter(el: CanvasElement): { x: number; y: number } | null {\r\n const b = getElementBounds(el);\r\n if (!b) return null;\r\n return { x: b.x + b.w / 2, y: b.y + b.h / 2 };\r\n}\r\n\r\n/** Wrap a fragment in a rotation group matching withRotation (radians → degrees). */\r\nfunction withRotationSvg(el: CanvasElement, fragment: string): string {\r\n const angle = el.rotation ?? 0;\r\n if (!angle || !fragment) return fragment;\r\n const c = elementCenter(el);\r\n if (!c) return fragment;\r\n const deg = (angle * 180) / Math.PI;\r\n return `<g transform=\"rotate(${n(deg)} ${n(c.x)} ${n(c.y)})\">${fragment}</g>`;\r\n}\r\n\r\n// Strokes use variable per-point width on the canvas; SVG <path> takes a single\r\n// stroke-width, so we mirror the canvas width-bucketing: segments are grouped by\r\n// quantized width and each bucket becomes one <path> of bezier sub-paths. This\r\n// reproduces the canvas geometry exactly. We rebuild buckets from segments+widths\r\n// (always populated) rather than the Path2D buckets, which are absent under jsdom.\r\nconst WIDTH_QUANTUM = 0.25;\r\n\r\nfunction emitStroke(stroke: StrokeElement): string {\r\n if (stroke.points.length < 2) return '';\r\n const data = getStrokeRenderData(stroke);\r\n const { x: ox, y: oy } = stroke.position;\r\n\r\n const byWidth = new Map<number, string[]>();\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 const q = Math.max(WIDTH_QUANTUM, Math.round(w / WIDTH_QUANTUM) * WIDTH_QUANTUM);\r\n let parts = byWidth.get(q);\r\n if (!parts) {\r\n parts = [];\r\n byWidth.set(q, parts);\r\n }\r\n parts.push(\r\n `M${n(ox + seg.start.x)} ${n(oy + seg.start.y)} C${n(ox + seg.cp1.x)} ${n(oy + seg.cp1.y)} ${n(ox + seg.cp2.x)} ${n(oy + seg.cp2.y)} ${n(ox + seg.end.x)} ${n(oy + seg.end.y)}`,\r\n );\r\n }\r\n\r\n const blend = stroke.blendMode === 'multiply' ? ' style=\"mix-blend-mode:multiply\"' : '';\r\n let out = '';\r\n for (const [width, parts] of byWidth) {\r\n out += `<path d=\"${parts.join(' ')}\" fill=\"none\" stroke=\"${esc(stroke.color)}\" stroke-width=\"${n(width)}\" stroke-linecap=\"round\" stroke-linejoin=\"round\" opacity=\"${n(stroke.opacity)}\"${blend} />`;\r\n }\r\n return out;\r\n}\r\n\r\nfunction emitShape(shape: ShapeElement): string {\r\n const { x, y } = shape.position;\r\n const { w, h } = shape.size;\r\n const fill = shape.fillColor !== 'none' && shape.shape !== 'line' ? esc(shape.fillColor) : 'none';\r\n const stroke = shape.strokeWidth > 0 ? esc(shape.strokeColor) : 'none';\r\n const sw = shape.strokeWidth > 0 ? ` stroke-width=\"${n(shape.strokeWidth)}\"` : '';\r\n\r\n switch (shape.shape) {\r\n case 'rectangle':\r\n return `<rect x=\"${n(x)}\" y=\"${n(y)}\" width=\"${n(w)}\" height=\"${n(h)}\" fill=\"${fill}\" stroke=\"${stroke}\"${sw} />`;\r\n case 'ellipse':\r\n return `<ellipse cx=\"${n(x + w / 2)}\" cy=\"${n(y + h / 2)}\" rx=\"${n(w / 2)}\" ry=\"${n(h / 2)}\" fill=\"${fill}\" stroke=\"${stroke}\"${sw} />`;\r\n case 'line': {\r\n const [a, b] = lineEndpoints(shape);\r\n return `<line x1=\"${n(a.x)}\" y1=\"${n(a.y)}\" x2=\"${n(b.x)}\" y2=\"${n(b.y)}\" stroke=\"${stroke}\"${sw} stroke-linecap=\"round\" />`;\r\n }\r\n }\r\n}\r\n\r\nfunction emitArrow(arrow: ArrowElement, store: ElementStore): string {\r\n const geometry = getArrowRenderGeometry(arrow);\r\n // Bound arrows store from/to at the bound element's CENTER; the canvas renderer\r\n // snaps them to the element EDGE at draw time. Mirror that for PNG/canvas parity.\r\n const { visualFrom: from, visualTo: to } = getVisualEndpoints(arrow, geometry, store);\r\n\r\n let d: string;\r\n if (arrow.bend !== 0) {\r\n const cp = geometry.controlPoint ?? getArrowControlPoint(from, to, arrow.bend);\r\n d = `M${n(from.x)} ${n(from.y)} Q${n(cp.x)} ${n(cp.y)} ${n(to.x)} ${n(to.y)}`;\r\n } else {\r\n d = `M${n(from.x)} ${n(from.y)} L${n(to.x)} ${n(to.y)}`;\r\n }\r\n\r\n const pattern = getArrowDashPattern(arrow.strokeStyle);\r\n const dash = pattern.length > 0 ? ` stroke-dasharray=\"${pattern.join(' ')}\"` : '';\r\n let out = `<path d=\"${d}\" fill=\"none\" stroke=\"${esc(arrow.color)}\" stroke-width=\"${n(arrow.width)}\" stroke-linecap=\"round\"${dash} />`;\r\n\r\n // Arrowhead — mirror arrow-renderer's polygon math (tip at the visual endpoint).\r\n const angle = geometry.tangentEnd;\r\n const p1x = to.x - ARROWHEAD_LENGTH * Math.cos(angle - ARROWHEAD_ANGLE);\r\n const p1y = to.y - ARROWHEAD_LENGTH * Math.sin(angle - ARROWHEAD_ANGLE);\r\n const p2x = to.x - ARROWHEAD_LENGTH * Math.cos(angle + ARROWHEAD_ANGLE);\r\n const p2y = to.y - ARROWHEAD_LENGTH * Math.sin(angle + ARROWHEAD_ANGLE);\r\n out += `<polygon points=\"${n(to.x)},${n(to.y)} ${n(p1x)},${n(p1y)} ${n(p2x)},${n(p2y)}\" fill=\"${esc(arrow.color)}\" />`;\r\n\r\n if (arrow.label && arrow.label.length > 0) {\r\n // Canvas renderer places the label at the raw-endpoint midpoint, not the visual one.\r\n const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);\r\n const approxW = arrow.label.length * ARROW_LABEL_FONT_SIZE * 0.6;\r\n const padX = 6;\r\n const padY = 4;\r\n const lw = approxW + padX * 2;\r\n const lh = ARROW_LABEL_FONT_SIZE + padY * 2;\r\n out += `<rect x=\"${n(mid.x - lw / 2)}\" y=\"${n(mid.y - lh / 2)}\" width=\"${n(lw)}\" height=\"${n(lh)}\" rx=\"4\" fill=\"rgba(255,255,255,0.9)\" />`;\r\n out += `<text x=\"${n(mid.x)}\" y=\"${n(mid.y)}\" font-family=\"system-ui, sans-serif\" font-size=\"${ARROW_LABEL_FONT_SIZE}\" fill=\"#1a1a1a\" text-anchor=\"middle\" dominant-baseline=\"central\">${esc(arrow.label)}</text>`;\r\n }\r\n\r\n return out;\r\n}\r\n\r\nfunction emitImage(image: ImageElement | HtmlElement, dataUri: string | undefined): string {\r\n const href = dataUri ?? ('src' in image ? image.src : '');\r\n if (!href) return '';\r\n const { x, y } = image.position;\r\n const { w, h } = image.size;\r\n return `<image href=\"${esc(href)}\" x=\"${n(x)}\" y=\"${n(y)}\" width=\"${n(w)}\" height=\"${n(h)}\" />`;\r\n}\r\n\r\nfunction emitText(\r\n text: TextElement,\r\n rasterScale: number,\r\n resourceOptions: ExportResourceOptions,\r\n): string {\r\n if (!text.text) return '';\r\n const { x, y } = text.position;\r\n const { w, h } = text.size;\r\n if (typeof document === 'undefined') return '';\r\n\r\n const width = Math.max(1, Math.ceil(w * rasterScale));\r\n const height = Math.max(1, Math.ceil(h * rasterScale));\r\n assertExportSize(width, height, resourceOptions);\r\n const canvas = document.createElement('canvas');\r\n canvas.width = width;\r\n canvas.height = height;\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return '';\r\n\r\n ctx.scale(rasterScale, rasterScale);\r\n ctx.translate(-x, -y);\r\n renderTextOnCanvas(ctx, text);\r\n\r\n let dataUri: string;\r\n try {\r\n dataUri = canvas.toDataURL();\r\n } catch {\r\n return '';\r\n }\r\n if (!dataUri || !dataUri.startsWith('data:')) return '';\r\n\r\n return `<image href=\"${esc(dataUri)}\" x=\"${n(x)}\" y=\"${n(y)}\" width=\"${n(w)}\" height=\"${n(h)}\" />`;\r\n}\r\n\r\nfunction emitNote(\r\n note: NoteElement,\r\n rasterScale: number,\r\n resourceOptions: ExportResourceOptions,\r\n): string {\r\n const { x, y } = note.position;\r\n const { w, h } = note.size;\r\n if (typeof document === 'undefined') return emitNotePlaceholder(note);\r\n\r\n const width = Math.max(1, Math.ceil(w * rasterScale));\r\n const height = Math.max(1, Math.ceil(h * rasterScale));\r\n assertExportSize(width, height, resourceOptions);\r\n const canvas = document.createElement('canvas');\r\n canvas.width = width;\r\n canvas.height = height;\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return emitNotePlaceholder(note);\r\n\r\n ctx.scale(rasterScale, rasterScale);\r\n ctx.translate(-x, -y);\r\n renderNoteOnCanvas(ctx, note);\r\n\r\n let dataUri: string;\r\n try {\r\n dataUri = canvas.toDataURL();\r\n } catch {\r\n return emitNotePlaceholder(note);\r\n }\r\n if (!dataUri || !dataUri.startsWith('data:')) return emitNotePlaceholder(note);\r\n\r\n return `<image href=\"${esc(dataUri)}\" x=\"${n(x)}\" y=\"${n(y)}\" width=\"${n(w)}\" height=\"${n(h)}\" />`;\r\n}\r\n\r\nfunction emitNotePlaceholder(note: NoteElement): string {\r\n const { x, y } = note.position;\r\n const { w, h } = note.size;\r\n return `<rect x=\"${n(x)}\" y=\"${n(y)}\" width=\"${n(w)}\" height=\"${n(h)}\" rx=\"4\" fill=\"${esc(note.backgroundColor)}\" />`;\r\n}\r\n\r\nfunction emitGrid(grid: GridElement, bounds: Bounds): string {\r\n if (grid.cellSize <= 0) return '';\r\n const vb = {\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 const stroke = esc(grid.strokeColor);\r\n const sw = n(grid.strokeWidth);\r\n const op = n(grid.opacity);\r\n\r\n if (grid.gridType === 'hex') {\r\n const centers = getHexCenters(vb, grid.cellSize, grid.hexOrientation);\r\n let d = '';\r\n for (const c of centers) {\r\n const verts = getHexVertices(c.x, c.y, grid.cellSize, grid.hexOrientation);\r\n const first = verts[0];\r\n if (!first) continue;\r\n d += `M${n(first.x)} ${n(first.y)}`;\r\n for (let i = 1; i < verts.length; i++) {\r\n const v = verts[i];\r\n if (v) d += `L${n(v.x)} ${n(v.y)}`;\r\n }\r\n d += 'Z';\r\n }\r\n return `<path d=\"${d}\" fill=\"none\" stroke=\"${stroke}\" stroke-width=\"${sw}\" opacity=\"${op}\" />`;\r\n }\r\n\r\n const { verticals, horizontals } = getSquareGridLines(vb, grid.cellSize);\r\n let d = '';\r\n for (const gx of verticals) d += `M${n(gx)} ${n(vb.minY)}L${n(gx)} ${n(vb.maxY)}`;\r\n for (const gy of horizontals) d += `M${n(vb.minX)} ${n(gy)}L${n(vb.maxX)} ${n(gy)}`;\r\n return `<path d=\"${d}\" fill=\"none\" stroke=\"${stroke}\" stroke-width=\"${sw}\" opacity=\"${op}\" />`;\r\n}\r\n\r\n// Geometric template only (square-grid context). Hex-grid templates fill snapped\r\n// hex cells; we approximate by emitting the cell hex outlines.\r\nfunction emitTemplate(template: TemplateElement, grid: GridElement | undefined): string {\r\n if (grid && grid.gridType === 'hex') {\r\n return emitHexTemplate(template, grid);\r\n }\r\n return emitGeometricTemplate(template);\r\n}\r\n\r\nfunction emitGeometricTemplate(t: TemplateElement): string {\r\n const { x: cx, y: cy } = t.position;\r\n const r = t.radius;\r\n const fill = esc(t.fillColor);\r\n const stroke = esc(t.strokeColor);\r\n const sw = n(t.strokeWidth);\r\n const op = n(t.opacity);\r\n const attrs = `fill=\"${fill}\" stroke=\"${stroke}\" stroke-width=\"${sw}\" opacity=\"${op}\"`;\r\n\r\n switch (t.templateShape) {\r\n case 'circle':\r\n return `<circle cx=\"${n(cx)}\" cy=\"${n(cy)}\" r=\"${n(r)}\" ${attrs} />`;\r\n case 'square':\r\n return `<rect x=\"${n(cx - r / 2)}\" y=\"${n(cy - r / 2)}\" width=\"${n(r)}\" height=\"${n(r)}\" ${attrs} />`;\r\n case 'cone': {\r\n const halfAngle = Math.atan(0.5);\r\n const a0 = t.angle - halfAngle;\r\n const a1 = t.angle + halfAngle;\r\n const p0x = cx + r * Math.cos(a0);\r\n const p0y = cy + r * Math.sin(a0);\r\n const p1x = cx + r * Math.cos(a1);\r\n const p1y = cy + r * Math.sin(a1);\r\n const large = a1 - a0 > Math.PI ? 1 : 0;\r\n return `<path d=\"M${n(cx)} ${n(cy)} L${n(p0x)} ${n(p0y)} A${n(r)} ${n(r)} 0 ${large} 1 ${n(p1x)} ${n(p1y)} Z\" ${attrs} />`;\r\n }\r\n case 'line': {\r\n const halfW = r / 12;\r\n const cos = Math.cos(t.angle);\r\n const sin = Math.sin(t.angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n const pts = [\r\n [cx + perpX, cy + perpY],\r\n [cx + r * cos + perpX, cy + r * sin + perpY],\r\n [cx + r * cos - perpX, cy + r * sin - perpY],\r\n [cx - perpX, cy - perpY],\r\n ]\r\n .map(([px, py]) => `${n(px ?? 0)},${n(py ?? 0)}`)\r\n .join(' ');\r\n return `<polygon points=\"${pts}\" ${attrs} />`;\r\n }\r\n case 'rectangle': {\r\n const halfW = (t.width ?? 0) / 2;\r\n const cos = Math.cos(t.angle);\r\n const sin = Math.sin(t.angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n const pts = [\r\n [cx + perpX, cy + perpY],\r\n [cx + r * cos + perpX, cy + r * sin + perpY],\r\n [cx + r * cos - perpX, cy + r * sin - perpY],\r\n [cx - perpX, cy - perpY],\r\n ]\r\n .map(([px, py]) => `${n(px ?? 0)},${n(py ?? 0)}`)\r\n .join(' ');\r\n return `<polygon points=\"${pts}\" ${attrs} />`;\r\n }\r\n }\r\n}\r\n\r\nfunction emitHexTemplate(t: TemplateElement, grid: GridElement): string {\r\n const cellSize = grid.cellSize;\r\n const orientation = grid.hexOrientation;\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const radiusCells = t.radius / snapUnit;\r\n const center = t.position;\r\n\r\n let cells: { x: number; y: number }[];\r\n switch (t.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, t.angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'line':\r\n cells = getHexCellsInLine(center, t.angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'square':\r\n cells = getHexCellsInSquare(center, radiusCells, cellSize, orientation);\r\n break;\r\n case 'rectangle': {\r\n const widthCells = (t.width ?? 0) / snapUnit;\r\n cells = getHexCellsInRectangle(\r\n center,\r\n t.angle,\r\n radiusCells,\r\n widthCells,\r\n cellSize,\r\n orientation,\r\n );\r\n break;\r\n }\r\n }\r\n\r\n let d = '';\r\n for (const cell of cells) {\r\n const verts = getHexVertices(cell.x, cell.y, cellSize, orientation);\r\n const first = verts[0];\r\n if (!first) continue;\r\n d += `M${n(first.x)} ${n(first.y)}`;\r\n for (let i = 1; i < verts.length; i++) {\r\n const v = verts[i];\r\n if (v) d += `L${n(v.x)} ${n(v.y)}`;\r\n }\r\n d += 'Z';\r\n }\r\n return `<path d=\"${d}\" fill=\"${esc(t.fillColor)}\" stroke=\"${esc(t.strokeColor)}\" stroke-width=\"${n(t.strokeWidth)}\" opacity=\"${n(t.opacity)}\" />`;\r\n}\r\n\r\nexport async function exportSvg(\r\n store: ElementStore,\r\n options: ExportSvgOptions = {},\r\n layerManager?: LayerManager,\r\n): Promise<string> {\r\n const padding = nonNegativeOption(options.padding, 0, 'padding');\r\n const rasterScale = positiveOption(options.rasterScale, 2, 'rasterScale');\r\n validateExportResourceOptions(options);\r\n validateHtmlExportOptions(options);\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 if (filter) visibleElements = visibleElements.filter(filter);\r\n\r\n const bounds = computeBounds(visibleElements, padding);\r\n if (!bounds) {\r\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"0\" height=\"0\" viewBox=\"0 0 0 0\"></svg>`;\r\n }\r\n assertExportSize(Math.ceil(bounds.w), Math.ceil(bounds.h), options);\r\n\r\n // Only remote/blob image srcs need network loading; data: srcs pass through.\r\n const remoteImages = visibleElements.filter(\r\n (el) => el.type === 'image' && !el.src.startsWith('data:'),\r\n );\r\n const imageCache = await loadImages(remoteImages, options);\r\n const imageDataUris = encodeImages(visibleElements, imageCache, rasterScale, options);\r\n const htmlElements = visibleElements.filter((el): el is HtmlElement => el.type === 'html');\r\n const htmlSources = await renderHtmlElements(htmlElements, options);\r\n const htmlDataUris = encodeHtmlElements(htmlElements, htmlSources, rasterScale, options);\r\n\r\n const grids = visibleElements.filter((el): el is GridElement => el.type === 'grid');\r\n const firstGrid = grids[0];\r\n\r\n let body = '';\r\n if (options.background) {\r\n body += `<rect x=\"${n(bounds.x)}\" y=\"${n(bounds.y)}\" width=\"${n(bounds.w)}\" height=\"${n(bounds.h)}\" fill=\"${esc(options.background)}\" />`;\r\n }\r\n\r\n const layerBodies = new Map<string, string>();\r\n for (const el of visibleElements) {\r\n const emitted = emitElement(\r\n el,\r\n imageDataUris,\r\n htmlDataUris,\r\n rasterScale,\r\n firstGrid,\r\n store,\r\n options,\r\n );\r\n layerBodies.set(el.layerId, (layerBodies.get(el.layerId) ?? '') + emitted);\r\n }\r\n for (const [layerId, emitted] of layerBodies) {\r\n const opacity = layerManager?.getLayer?.(layerId)?.opacity ?? 1;\r\n body += opacity === 1 || emitted === '' ? emitted : `<g opacity=\"${n(opacity)}\">${emitted}</g>`;\r\n }\r\n for (const grid of grids) {\r\n const emitted = emitGrid(grid, bounds);\r\n const opacity = layerManager?.getLayer?.(grid.layerId)?.opacity ?? 1;\r\n body += opacity === 1 ? emitted : `<g opacity=\"${n(opacity)}\">${emitted}</g>`;\r\n }\r\n\r\n return (\r\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${n(bounds.w)}\" height=\"${n(bounds.h)}\" ` +\r\n `viewBox=\"${n(bounds.x)} ${n(bounds.y)} ${n(bounds.w)} ${n(bounds.h)}\">${body}</svg>`\r\n );\r\n}\r\n\r\nfunction emitElement(\r\n el: CanvasElement,\r\n imageDataUris: Map<string, string>,\r\n htmlDataUris: Map<string, string>,\r\n rasterScale: number,\r\n firstGrid: GridElement | undefined,\r\n store: ElementStore,\r\n resourceOptions: ExportResourceOptions,\r\n): string {\r\n switch (el.type) {\r\n case 'stroke':\r\n return withRotationSvg(el, emitStroke(el));\r\n case 'shape':\r\n return withRotationSvg(el, emitShape(el));\r\n case 'arrow':\r\n return emitArrow(el, store);\r\n case 'image':\r\n return withRotationSvg(el, emitImage(el, imageDataUris.get(el.id)));\r\n case 'text':\r\n return withRotationSvg(el, emitText(el, rasterScale, resourceOptions));\r\n case 'note':\r\n return withRotationSvg(el, emitNote(el, rasterScale, resourceOptions));\r\n case 'template':\r\n return emitTemplate(el, firstGrid);\r\n case 'grid':\r\n return '';\r\n case 'html':\r\n return withRotationSvg(el, emitImage(el, htmlDataUris.get(el.id)));\r\n default:\r\n return '';\r\n }\r\n}\r\n\r\nfunction encodeHtmlElements(\r\n elements: HtmlElement[],\r\n sources: Map<string, CanvasImageSource>,\r\n rasterScale: number,\r\n options: ExportSvgOptions,\r\n): Map<string, string> {\r\n const encoded = new Map<string, string>();\r\n for (const element of elements) {\r\n const source = sources.get(element.id);\r\n if (!source) continue;\r\n const width = Math.max(1, Math.ceil(element.size.w * rasterScale));\r\n const height = Math.max(1, Math.ceil(element.size.h * rasterScale));\r\n assertExportSize(width, height, options);\r\n if (typeof document === 'undefined') {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'encode',\r\n });\r\n continue;\r\n }\r\n const canvas = document.createElement('canvas');\r\n canvas.width = width;\r\n canvas.height = height;\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'encode',\r\n });\r\n continue;\r\n }\r\n try {\r\n ctx.drawImage(source, 0, 0, width, height);\r\n const dataUri = canvas.toDataURL();\r\n if (dataUri.startsWith('data:')) {\r\n encoded.set(element.id, dataUri);\r\n } else {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'encode',\r\n });\r\n }\r\n } catch (cause) {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'encode',\r\n cause,\r\n });\r\n }\r\n }\r\n return encoded;\r\n}\r\n\r\n/** data: srcs pass through; remote/blob srcs are rasterized to data-URIs via the loaded image. */\r\nfunction encodeImages(\r\n elements: CanvasElement[],\r\n imageCache: Map<string, HTMLImageElement>,\r\n rasterScale: number,\r\n resourceOptions: ExportResourceOptions,\r\n): Map<string, string> {\r\n const out = new Map<string, string>();\r\n for (const el of elements) {\r\n if (el.type !== 'image') continue;\r\n if (el.src.startsWith('data:')) {\r\n out.set(el.id, el.src);\r\n continue;\r\n }\r\n const img = imageCache.get(el.id);\r\n if (!img || typeof document === 'undefined') continue;\r\n const width = Math.max(1, Math.ceil(el.size.w * rasterScale));\r\n const height = Math.max(1, Math.ceil(el.size.h * rasterScale));\r\n assertExportSize(width, height, resourceOptions);\r\n const canvas = document.createElement('canvas');\r\n canvas.width = width;\r\n canvas.height = height;\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) {\r\n resourceOptions.onAssetError?.({ elementId: el.id, src: el.src, reason: 'encode' });\r\n continue;\r\n }\r\n try {\r\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height);\r\n const uri = canvas.toDataURL();\r\n if (uri.startsWith('data:')) out.set(el.id, uri);\r\n else resourceOptions.onAssetError?.({ elementId: el.id, src: el.src, reason: 'encode' });\r\n } catch (cause) {\r\n resourceOptions.onAssetError?.({ elementId: el.id, src: el.src, reason: 'encode', cause });\r\n }\r\n }\r\n return out;\r\n}\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 strata = new Map<number, 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 private lastSyncedOpacity = new Map<string, number>();\r\n private cameraTransform = '';\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 setCameraTransform(transform: string): void {\r\n if (transform === this.cameraTransform) return;\r\n this.cameraTransform = transform;\r\n for (const stratum of this.strata.values()) stratum.style.transform = transform;\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 this.lastSyncedOpacity.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, opacity = 1): 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.getStratum(zIndex).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 const lastOpacity = this.lastSyncedOpacity.get(element.id);\r\n if (lastVersion === currentVersion && lastZ === zIndex && lastOpacity === opacity) {\r\n return;\r\n }\r\n }\r\n\r\n if (node.parentElement !== this.getStratum(zIndex)) {\r\n const previousStratum = node.parentElement;\r\n this.getStratum(zIndex).appendChild(node);\r\n if (previousStratum?.childElementCount === 0) {\r\n const previousOrder = Number(previousStratum.dataset['paintOrder']);\r\n previousStratum.remove();\r\n this.strata.delete(previousOrder);\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 this.lastSyncedOpacity.set(element.id, opacity);\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 opacity: String(opacity),\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) {\r\n node.style.display = 'none';\r\n this.lastSyncedVersion.delete(id);\r\n }\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 this.lastSyncedOpacity.delete(id);\r\n const node = this.domNodes.get(id);\r\n if (node) {\r\n const stratum = node.parentElement;\r\n node.remove();\r\n this.domNodes.delete(id);\r\n if (stratum?.childElementCount === 0) {\r\n const order = Number(stratum.dataset['paintOrder']);\r\n stratum.remove();\r\n this.strata.delete(order);\r\n }\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 this.lastSyncedOpacity.clear();\r\n for (const stratum of this.strata.values()) stratum.remove();\r\n this.strata.clear();\r\n }\r\n\r\n private getStratum(order: number): HTMLDivElement {\r\n let stratum = this.strata.get(order);\r\n if (stratum) return stratum;\r\n stratum = document.createElement('div');\r\n stratum.dataset['paintOrder'] = String(order);\r\n Object.assign(stratum.style, {\r\n position: 'absolute',\r\n inset: '0',\r\n width: '100%',\r\n height: '100%',\r\n pointerEvents: 'none',\r\n transformOrigin: '0 0',\r\n transform: this.cameraTransform,\r\n zIndex: String(order),\r\n });\r\n this.domLayer.appendChild(stratum);\r\n this.strata.set(order, stratum);\r\n return stratum;\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 lineHeight: '1.4',\r\n });\r\n node.innerHTML = 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 const text = element.text || '';\r\n if (node.innerHTML !== text) {\r\n node.innerHTML = 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 { getElementVisualBounds, boundsIntersect } from '../elements/element-bounds';\r\nimport { RenderStats } from './render-stats';\r\nimport type { RenderStatsSnapshot } from './render-stats';\r\nimport type { HybridRenderSurface } from './hybrid-render-surface';\r\n\r\n/**\r\n * A world-space draw callback rendered above elements on every frame,\r\n * regardless of which tool is active. The context arrives with the camera\r\n * transform applied; implementations must not assume exclusive context state\r\n * (each renderer is wrapped in save/restore). A throwing renderer is isolated\r\n * per frame and must not break the render loop.\r\n */\r\nexport type OverlayRenderer = (ctx: CanvasRenderingContext2D) => void;\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 hybridSurface: HybridRenderSurface;\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 readonly hybridSurface: HybridRenderSurface;\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 readonly overlays = new Set<OverlayRenderer>();\r\n private gridCacheCanvas: HTMLCanvasElement | null = null;\r\n private gridCacheCtx: CanvasRenderingContext2D | null = null;\r\n private lastGridRefs: CanvasElement[] = [];\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 this.hybridSurface = deps.hybridSurface;\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 this.gridCacheDirty = true;\r\n }\r\n\r\n getStats(): RenderStatsSnapshot {\r\n return this.stats.getSnapshot();\r\n }\r\n\r\n /**\r\n * Registers a viewport overlay drawn beneath the active tool's own overlay.\r\n * Returns an idempotent unsubscribe that also erases the overlay's last\r\n * frame.\r\n */\r\n registerOverlay(draw: OverlayRenderer): () => void {\r\n this.overlays.add(draw);\r\n this.requestRender();\r\n return () => {\r\n if (this.overlays.delete(draw)) this.requestRender();\r\n };\r\n }\r\n\r\n private drawRegisteredOverlays(ctx: CanvasRenderingContext2D): void {\r\n for (const draw of this.overlays) {\r\n ctx.save();\r\n try {\r\n draw(ctx);\r\n } catch {\r\n // One faulty overlay must not take down the frame or its siblings.\r\n } finally {\r\n ctx.restore();\r\n }\r\n }\r\n }\r\n\r\n private compositeLayerCache(\r\n ctx: CanvasRenderingContext2D,\r\n layerId: string,\r\n opacity: number,\r\n ): 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.globalAlpha = opacity;\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 const visibleElements = allElements.filter((element) =>\r\n this.layerManager.isLayerVisible(element.layerId),\r\n );\r\n const firstDomIndex = visibleElements.findIndex((element) =>\r\n this.renderer.isDomElement(element),\r\n );\r\n const hybridActive =\r\n firstDomIndex >= 0 &&\r\n visibleElements\r\n .slice(firstDomIndex + 1)\r\n .some((element) => !this.renderer.isDomElement(element));\r\n const hybridCanvasRuns = new Map<number, CanvasElement[]>();\r\n const hybridOrders = new Set<number>();\r\n let activeHybridOrder: number | null = null;\r\n this.layerGroups.clear();\r\n const gridElements: CanvasElement[] = [];\r\n let paintOrder = 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 const order = ++paintOrder;\r\n\r\n if (this.renderer.isDomElement(element)) {\r\n activeHybridOrder = null;\r\n const layerOpacity = this.layerManager.getLayer?.(element.layerId)?.opacity ?? 1;\r\n const elBounds = getElementVisualBounds(element);\r\n if (elBounds && !boundsIntersect(elBounds, cullingRect)) {\r\n this.domNodeManager.hideDomNode(element.id);\r\n } else {\r\n this.domNodeManager.syncDomNode(element, order, layerOpacity);\r\n }\r\n continue;\r\n }\r\n\r\n if (hybridActive && paintOrder > firstDomIndex + 1 && element.type !== 'grid') {\r\n activeHybridOrder ??= order;\r\n let run = hybridCanvasRuns.get(activeHybridOrder);\r\n if (!run) {\r\n run = [];\r\n hybridCanvasRuns.set(activeHybridOrder, run);\r\n hybridOrders.add(activeHybridOrder);\r\n }\r\n run.push(element);\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 const activeTool = this.toolManager.activeTool;\r\n const overlayOrder = visibleElements.length + 1;\r\n const hasOverlay = activeTool?.renderOverlay !== undefined || this.overlays.size > 0;\r\n if (hybridActive && hasOverlay) hybridOrders.add(overlayOrder);\r\n this.hybridSurface.beginFrame(hybridOrders, this.canvasEl.width, this.canvasEl.height);\r\n\r\n for (const [layerId, elements] of this.layerGroups) {\r\n const isActiveDrawingLayer = layerId === this.activeDrawingLayerId;\r\n const layerOpacity = this.layerManager.getLayer?.(layerId)?.opacity ?? 1;\r\n\r\n if (!this.layerCache.isDirty(layerId)) {\r\n const compT0 = performance.now();\r\n this.compositeLayerCache(ctx, layerId, layerOpacity);\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, layerOpacity);\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 = getElementVisualBounds(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, layerOpacity);\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 gridsChanged =\r\n gridElements.length !== this.lastGridRefs.length ||\r\n gridElements.some((grid, index) => grid !== this.lastGridRefs[index]);\r\n const gridDirty = this.gridCacheDirty || gridsChanged;\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 gc.save();\r\n gc.globalAlpha = this.layerManager.getLayer?.(grid.layerId)?.opacity ?? 1;\r\n this.renderer.renderCanvasElement(gc as CanvasRenderingContext2D, grid);\r\n gc.restore();\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.lastGridRefs = [...gridElements];\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 ctx.save();\r\n ctx.globalAlpha = this.layerManager.getLayer?.(grid.layerId)?.opacity ?? 1;\r\n this.renderer.renderCanvasElement(ctx, grid);\r\n ctx.restore();\r\n }\r\n }\r\n gridMs = performance.now() - gridT0;\r\n } else {\r\n this.lastGridRefs = [];\r\n }\r\n\r\n for (const [order, elements] of hybridCanvasRuns) {\r\n const hybridCtx = this.hybridSurface.getContext(order);\r\n if (!hybridCtx) continue;\r\n hybridCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);\r\n hybridCtx.save();\r\n hybridCtx.scale(dpr, dpr);\r\n hybridCtx.translate(this.camera.position.x, this.camera.position.y);\r\n hybridCtx.scale(this.camera.zoom, this.camera.zoom);\r\n for (const element of elements) {\r\n const elBounds = getElementVisualBounds(element);\r\n if (elBounds && !boundsIntersect(elBounds, cullingRect)) continue;\r\n hybridCtx.save();\r\n hybridCtx.globalAlpha = this.layerManager.getLayer?.(element.layerId)?.opacity ?? 1;\r\n this.renderer.renderCanvasElement(hybridCtx, element);\r\n hybridCtx.restore();\r\n }\r\n hybridCtx.restore();\r\n }\r\n\r\n const overlayT0 = performance.now();\r\n if (hybridActive && hasOverlay) {\r\n const overlayCtx = this.hybridSurface.getContext(overlayOrder);\r\n if (overlayCtx) {\r\n overlayCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);\r\n overlayCtx.save();\r\n overlayCtx.scale(dpr, dpr);\r\n overlayCtx.translate(this.camera.position.x, this.camera.position.y);\r\n overlayCtx.scale(this.camera.zoom, this.camera.zoom);\r\n this.drawRegisteredOverlays(overlayCtx);\r\n if (activeTool?.renderOverlay) activeTool.renderOverlay(overlayCtx);\r\n overlayCtx.restore();\r\n }\r\n } else if (hasOverlay) {\r\n this.drawRegisteredOverlays(ctx);\r\n if (activeTool?.renderOverlay) 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 { ArrowStrokeStyle, 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 strokeStyle?: ArrowStrokeStyle;\r\n}\r\n\r\nexport function styleToPatch(element: CanvasElement, style: ElementStyle): Partial<CanvasElement> {\r\n const { color, fillColor, strokeWidth, opacity, fontSize, strokeStyle } = 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 ...(strokeStyle !== undefined ? { strokeStyle } : {}),\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 {\r\n color: element.color,\r\n strokeWidth: element.width,\r\n ...(element.strokeStyle !== undefined ? { strokeStyle: element.strokeStyle } : {}),\r\n };\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 { Bounds, Point } from '../core/types';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { normalizeAngle, rotatePoint, rotatedAABB } from '../core/geometry';\r\n\r\nexport type RotateDirection = 'cw' | 'ccw';\r\n\r\nexport interface BoundedElement {\r\n id: string;\r\n el: CanvasElement;\r\n bounds: Bounds;\r\n}\r\n\r\nexport function 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\nexport function rotationPivot(items: readonly BoundedElement[]): Point {\r\n const first = items[0];\r\n if (items.length === 1 && first) {\r\n return { x: first.bounds.x + first.bounds.w / 2, y: first.bounds.y + first.bounds.h / 2 };\r\n }\r\n const u = unionBounds(items.map((it) => rotatedAABB(it.bounds, it.el.rotation ?? 0)));\r\n return { x: u.x + u.w / 2, y: u.y + u.h / 2 };\r\n}\r\n\r\nexport function rotateElementPatch(\r\n el: CanvasElement,\r\n bounds: Bounds,\r\n pivot: Point,\r\n delta: number,\r\n): Partial<CanvasElement> {\r\n if (el.type === 'arrow') {\r\n const center = { x: bounds.x + bounds.w / 2, y: bounds.y + bounds.h / 2 };\r\n const moved = rotatePoint(center, pivot, delta);\r\n return {\r\n position: { x: el.position.x + moved.x - center.x, y: el.position.y + moved.y - center.y },\r\n from: rotatePoint(el.from, pivot, delta),\r\n to: rotatePoint(el.to, pivot, delta),\r\n };\r\n }\r\n if (el.type === 'template') {\r\n return {\r\n position: rotatePoint(el.position, pivot, delta),\r\n angle: normalizeAngle(el.angle + delta),\r\n };\r\n }\r\n const center = { x: bounds.x + bounds.w / 2, y: bounds.y + bounds.h / 2 };\r\n const moved = rotatePoint(center, pivot, delta);\r\n return {\r\n position: { x: el.position.x + moved.x - center.x, y: el.position.y + moved.y - center.y },\r\n rotation: normalizeAngle((el.rotation ?? 0) + delta),\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\nimport { rotationPivot, rotateElementPatch, unionBounds } from './selection-rotate';\r\nimport type { RotateDirection } from './selection-rotate';\r\n\r\nexport type AlignEdge = 'left' | 'center-x' | 'right' | 'top' | 'middle' | 'bottom';\r\nexport type DistributeAxis = 'horizontal' | 'vertical';\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 const strokeStyle = sharedValue(styles.map((s) => s.strokeStyle));\r\n if (strokeStyle !== undefined) result.strokeStyle = strokeStyle;\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 rotateSelection(direction: RotateDirection): void {\r\n const eligible = this.boundedSelection().filter(({ el }) => this.isMovable(el));\r\n if (eligible.length === 0) return;\r\n const delta = direction === 'cw' ? Math.PI / 2 : -Math.PI / 2;\r\n const pivot = rotationPivot(eligible);\r\n this.deps.recorder.begin();\r\n const moved: string[] = [];\r\n for (const { id, el, bounds } of eligible) {\r\n this.deps.store.update(id, rotateElementPatch(el, bounds, pivot, delta));\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 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';\nimport type { ElementStore } from '../elements/element-store';\nimport type { ElementRenderer } from '../elements/element-renderer';\nimport type { NoteEditor } from '../elements/note-editor';\nimport type { ArrowLabelEditor } from '../elements/arrow-label-editor';\nimport type { InteractMode } from './interact-mode';\nimport type { DomNodeManager } from './dom-node-manager';\nimport type { RenderLoop } from './render-loop';\nimport type { HistoryRecorder } from '../history/history-recorder';\nimport type { CanvasElement, ArrowElement } from '../elements/types';\nimport { DoubleTapDetector } from './double-tap-detector';\nimport { isNearBezier } from '../elements/arrow-geometry';\nimport { isNoteContentEmpty } from '../elements/note-sanitizer';\n\nconst ARROW_HIT_THRESHOLD = 10;\n\nexport interface ViewportInteractionsDeps {\n store: ElementStore;\n camera: Camera;\n wrapper: HTMLDivElement;\n domLayer: HTMLDivElement;\n renderLoop: RenderLoop;\n domNodeManager: DomNodeManager;\n noteEditor: NoteEditor;\n arrowLabelEditor: ArrowLabelEditor;\n interactMode: InteractMode;\n renderer: ElementRenderer;\n recorder: HistoryRecorder;\n requestRender: () => void;\n addImage: (src: string, position: { x: number; y: number }) => string;\n dropHandler?: (event: DragEvent, worldPosition: { x: number; y: number }) => void;\n}\n\nexport class ViewportInteractions {\n private readonly doubleTapDetector = new DoubleTapDetector();\n private tapDownX = 0;\n private tapDownY = 0;\n\n constructor(private readonly deps: ViewportInteractionsDeps) {}\n\n startEditingElement(id: string): void {\n const element = this.deps.store.getById(id);\n if (!element || (element.type !== 'note' && element.type !== 'text')) return;\n\n this.deps.renderLoop.flush();\n\n const node = this.deps.domNodeManager.getNode(id);\n if (node) {\n this.deps.noteEditor.startEditing(node, id, this.deps.store);\n }\n }\n\n liveFitHeight(elementId: string): void {\n const element = this.deps.store.getById(elementId);\n if (!element || (element.type !== 'note' && element.type !== 'text')) return;\n const node = this.deps.domNodeManager.getNode(elementId);\n if (!node) return;\n const measured = node.scrollHeight;\n if (measured > 0 && measured !== element.size.h) {\n this.deps.store.update(elementId, { size: { w: element.size.w, h: measured } });\n }\n }\n\n fitNoteHeight(elementId: string): void {\n const element = this.deps.store.getById(elementId);\n if (!element || element.type !== 'note') return;\n if (isNoteContentEmpty(element.text)) return;\n const node = this.deps.domNodeManager.getNode(elementId);\n if (!node) return;\n const measured = node.scrollHeight;\n if (measured > element.size.h) {\n this.deps.store.update(elementId, { size: { w: element.size.w, h: measured } });\n }\n }\n\n onTextEditStop(elementId: string): void {\n const element = this.deps.store.getById(elementId);\n if (!element) return;\n\n if (element.type === 'note') {\n if (isNoteContentEmpty(element.text)) {\n this.deps.store.remove(elementId);\n return;\n }\n this.liveFitHeight(elementId);\n return;\n }\n\n if (element.type !== 'text') return;\n\n if (!element.text || element.text.trim() === '') {\n this.deps.store.remove(elementId);\n return;\n }\n\n this.liveFitHeight(elementId);\n }\n\n onTapDown = (e: PointerEvent): void => {\n this.tapDownX = e.clientX;\n this.tapDownY = e.clientY;\n };\n\n onDoubleTap = (e: PointerEvent): void => {\n const dx = e.clientX - this.tapDownX;\n const dy = e.clientY - this.tapDownY;\n const moved = Math.sqrt(dx * dx + dy * dy);\n if (moved > 10) return;\n\n if (!this.doubleTapDetector.feed(e)) return;\n if (typeof document.elementFromPoint !== 'function') return;\n\n const el = document.elementFromPoint(e.clientX, e.clientY);\n\n const nodeEl = (el as HTMLElement | null)?.closest<HTMLDivElement>('[data-element-id]');\n if (nodeEl) {\n const elementId = nodeEl.dataset['elementId'];\n if (elementId) {\n const element = this.deps.store.getById(elementId);\n if (element?.type === 'note' || element?.type === 'text') {\n this.startEditingElement(elementId);\n return;\n }\n }\n }\n\n const rect = this.deps.wrapper.getBoundingClientRect();\n const screen = { x: e.clientX - rect.left, y: e.clientY - rect.top };\n const world = this.deps.camera.screenToWorld(screen);\n\n // HTML embeds keep double-tap priority: you double-tapped inside the embed even if an\n // arrow's curve passes nearby. Arrow-label editing only when no embed is hit.\n const hit = this.hitTestWorld(world);\n if (hit?.type === 'html') {\n this.deps.interactMode.startInteracting(hit.id);\n return;\n }\n\n const arrow = this.findArrowAt(world);\n if (arrow) {\n this.startArrowLabelEdit(arrow);\n }\n };\n\n findArrowAt(world: { x: number; y: number }): ArrowElement | undefined {\n const candidates = this.deps.store.queryPoint(world).reverse();\n for (const el of candidates) {\n if (\n el.type === 'arrow' &&\n isNearBezier(world, el.from, el.to, el.bend, ARROW_HIT_THRESHOLD)\n ) {\n return el;\n }\n }\n return undefined;\n }\n\n startArrowLabelEdit(arrow: ArrowElement): void {\n this.deps.arrowLabelEditor.startEditing({\n arrow,\n layer: this.deps.domLayer,\n store: this.deps.store,\n recorder: this.deps.recorder,\n onDone: () => {\n this.deps.renderer.setLabelEditingId(null);\n this.deps.requestRender();\n },\n });\n // Set AFTER startEditing: starting a new edit cleans up any prior session, whose onDone\n // synchronously clears the editing id — so claim suppression for this arrow last.\n this.deps.renderer.setLabelEditingId(arrow.id);\n }\n\n private hitTestWorld(world: { x: number; y: number }): CanvasElement | null {\n const candidates = this.deps.store.queryPoint(world).reverse();\n for (const el of candidates) {\n if (!('size' in el)) continue;\n const { x, y } = el.position;\n const { w, h } = el.size;\n if (world.x >= x && world.x <= x + w && world.y >= y && world.y <= y + h) {\n return el;\n }\n }\n return null;\n }\n\n onDragOver = (e: DragEvent): void => {\n e.preventDefault();\n };\n\n onDrop = (e: DragEvent): void => {\n e.preventDefault();\n const rect = this.deps.wrapper.getBoundingClientRect();\n const screenPos = { x: e.clientX - rect.left, y: e.clientY - rect.top };\n const worldPos = this.deps.camera.screenToWorld(screenPos);\n\n if (this.deps.dropHandler) {\n this.deps.dropHandler(e, worldPos);\n return;\n }\n\n const files = e.dataTransfer?.files;\n if (!files) return;\n\n for (const file of files) {\n if (!file.type.startsWith('image/')) continue;\n\n const reader = new FileReader();\n reader.onload = () => {\n const src = reader.result;\n if (typeof src !== 'string') return;\n this.deps.addImage(src, worldPos);\n };\n reader.readAsDataURL(file);\n }\n };\n}\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 {\r\n CanvasElement,\r\n ArrowElement,\r\n GridElement,\r\n HtmlElement,\r\n ShapeKind,\r\n} 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 { Minimap } from './minimap';\r\nimport { createWrapper, createCanvas, createDomLayer, createPaintStack } from './viewport-dom';\r\nimport { HybridRenderSurface } from './hybrid-render-surface';\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 { exportSvg } from './export-svg';\r\nimport type { ExportSvgOptions } from './export-svg';\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 { OverlayRenderer } 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\nimport type { RotateDirection } from './selection-rotate';\r\n\r\nexport type { AlignEdge, DistributeAxis } from './selection-ops';\r\nexport type { GridInfo } from './grid-controller';\r\nexport type { RotateDirection } from './selection-rotate';\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 onPaste?: (event: ClipboardEvent, 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 /** Coast (inertial glide) after a pan flick. Default `true`. */\r\n panInertia?: boolean;\r\n /** Show an overview minimap (bottom-right) with tap/drag-to-navigate. Default `false`. */\r\n minimap?: 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 paintStack: HTMLDivElement;\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 transactionDepth = 0;\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 private minimap: Minimap | null = null;\r\n private readonly htmlRenderers = new Map<string, (el: HtmlElement) => HTMLElement>();\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.noteEditor.setOnInput((id) => this.interactions.liveFitHeight(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.paintStack = createPaintStack();\r\n this.domLayer = createDomLayer();\r\n this.domLayer.style.zIndex = '2147483647';\r\n\r\n this.wrapper.appendChild(this.canvasEl);\r\n this.wrapper.appendChild(this.paintStack);\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 rotate: (direction) => this.rotateSelection(direction),\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 addImage: (src, world) => this.addImage(src, world),\r\n getCenteredWorld: () => this.centeredPosition({ w: 300, h: 200 }),\r\n onPaste: options.onPaste,\r\n panInertia: options.panInertia,\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 if (options.minimap) {\r\n const visibleEls = () =>\r\n this.store.getAll().filter((el) => this.layerManager.isLayerVisible(el.layerId));\r\n this.minimap = new Minimap({\r\n container: this.wrapper,\r\n getElements: visibleEls,\r\n getContentBounds: () => getElementsBoundingBox(visibleEls()),\r\n getViewportRect: () =>\r\n this.camera.getVisibleRect(this.canvasEl.clientWidth, this.canvasEl.clientHeight),\r\n navigateTo: (w) => {\r\n const z = this.camera.zoom;\r\n this.camera.moveTo(\r\n this.canvasEl.clientWidth / 2 - w.x * z,\r\n this.canvasEl.clientHeight / 2 - w.y * z,\r\n );\r\n },\r\n requestFrame: (cb) =>\r\n typeof requestAnimationFrame !== 'undefined' ? requestAnimationFrame(cb) : 0,\r\n cancelFrame: (id) => {\r\n if (typeof cancelAnimationFrame !== 'undefined') cancelAnimationFrame(id);\r\n },\r\n });\r\n this.minimap.scheduleDraw();\r\n }\r\n\r\n this.domNodeManager = new DomNodeManager({\r\n domLayer: this.paintStack,\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 this.domNodeManager.setCameraTransform(this.camera.toCSSTransform());\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 hybridSurface: new HybridRenderSurface(this.paintStack),\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.minimap?.scheduleDraw();\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.minimap?.scheduleDraw();\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.minimap?.scheduleDraw();\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.minimap?.scheduleDraw();\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.minimap?.scheduleDraw();\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.renderLoop.markAllLayersDirty();\r\n this.minimap?.scheduleDraw();\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 /**\r\n * Registers a world-space overlay drawn above elements on every frame,\r\n * regardless of the active tool — the surface for remote presence visuals\r\n * such as laser trails, cursors, pings, and shared rulers. Overlays draw\r\n * beneath the active tool's own `renderOverlay` and never touch elements,\r\n * history, or persisted state. Returns an idempotent unsubscribe that also\r\n * erases the overlay's last frame.\r\n */\r\n registerOverlay(draw: OverlayRenderer): () => void {\r\n return this.renderLoop.registerOverlay(draw);\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 async exportSVG(options?: ExportSvgOptions): Promise<string> {\r\n return exportSvg(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 for (const el of this.store.getElementsByType('html')) {\r\n if (this.domNodeManager.hasContent(el.id)) continue;\r\n\r\n // Registry first: rebuild the embed from serialized data and mount it via the html branch\r\n // of renderDomContent. This stores content BEFORE the onHtmlElementMount path's hasContent\r\n // check, so a factory-rebuilt element never also gets an empty node from the callback path.\r\n const factory = el.htmlType ? this.htmlRenderers.get(el.htmlType) : undefined;\r\n const rebuilt = factory ? factory(el) : null;\r\n if (rebuilt) {\r\n this.domNodeManager.storeHtmlContent(el.id, rebuilt);\r\n this.domNodeManager.syncDomNode(el);\r\n }\r\n\r\n // Callback still fires for wiring (both fire; registry produces the node, callback wires it).\r\n if (this.onHtmlElementMount) {\r\n if (!rebuilt) 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 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 /**\r\n * Groups synchronous local store and layer mutations into one undo step.\r\n * Nested calls join the outer transaction. If the callback throws, mutations\r\n * already applied remain undoable and the original error is rethrown.\r\n */\r\n transaction<T>(operation: () => T): T {\r\n const isOuterTransaction = this.transactionDepth === 0;\r\n if (isOuterTransaction) {\r\n this.inputHandler.flushPendingHistory();\r\n this.historyRecorder.begin();\r\n }\r\n this.transactionDepth += 1;\r\n try {\r\n return operation();\r\n } finally {\r\n this.transactionDepth -= 1;\r\n if (isOuterTransaction) this.historyRecorder.commit();\r\n }\r\n }\r\n\r\n /** Removes existing elements as one undoable operation and returns the number removed. */\r\n removeElements(ids: Iterable<string>): number {\r\n const existingIds = [...new Set(ids)].filter((id) => this.store.getById(id) !== undefined);\r\n if (existingIds.length === 0) return 0;\r\n this.transaction(() => {\r\n for (const id of existingIds) this.store.remove(id);\r\n });\r\n this.requestRender();\r\n return existingIds.length;\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 opts?: { htmlType?: string; data?: Record<string, unknown> },\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 htmlType: opts?.htmlType,\r\n data: opts?.data,\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 registerHtmlRenderer(htmlType: string, factory: (el: HtmlElement) => HTMLElement): void {\r\n this.htmlRenderers.set(htmlType, factory);\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 items.push({ label: 'Rotate 90° CW', action: 'rotate-cw' });\r\n items.push({ label: 'Rotate 90° CCW', action: 'rotate-ccw' });\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 rotateSelection(direction: RotateDirection): void {\r\n this.selectionOps.rotateSelection(direction);\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.minimap?.destroy();\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 const transform = this.camera.toCSSTransform();\r\n this.domLayer.style.transform = transform;\r\n this.domNodeManager.setCameraTransform(transform);\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 { Point } from '../core/types';\r\nimport type { OverlayRenderer } from './render-loop';\r\nimport type { LaserTrailEmission } from '../tools/laser-tool';\r\n\r\n/**\r\n * The wire shape of a laser-trail presence payload. Presence data is untyped\r\n * on the wire, so hosts discriminate on `kind`; `isLaserTrailPresence`\r\n * validates a received payload before it reaches the overlay. Trails are\r\n * ephemeral by contract: they must travel as presence only — never as\r\n * elements, undo history, persisted canvas state, or durable operations.\r\n */\r\nexport interface LaserTrailPresence {\r\n readonly kind: 'laser';\r\n /** World-space points, oldest first. */\r\n readonly points: readonly Point[];\r\n readonly color?: string;\r\n readonly width?: number;\r\n readonly fadeMs?: number;\r\n}\r\n\r\nexport const LASER_TRAIL_PRESENCE_KIND = 'laser';\r\n\r\nfunction isFinitePoint(value: unknown): value is Point {\r\n if (typeof value !== 'object' || value === null) return false;\r\n const point = value as { x?: unknown; y?: unknown };\r\n return (\r\n typeof point.x === 'number' &&\r\n Number.isFinite(point.x) &&\r\n typeof point.y === 'number' &&\r\n Number.isFinite(point.y)\r\n );\r\n}\r\n\r\nexport function isLaserTrailPresence(data: unknown): data is LaserTrailPresence {\r\n if (typeof data !== 'object' || data === null) return false;\r\n const payload = data as {\r\n kind?: unknown;\r\n points?: unknown;\r\n color?: unknown;\r\n width?: unknown;\r\n fadeMs?: unknown;\r\n };\r\n if (payload.kind !== LASER_TRAIL_PRESENCE_KIND) return false;\r\n if (!Array.isArray(payload.points) || !payload.points.every(isFinitePoint)) return false;\r\n if (payload.color !== undefined && typeof payload.color !== 'string') return false;\r\n if (payload.width !== undefined && !(typeof payload.width === 'number' && payload.width > 0)) {\r\n return false;\r\n }\r\n if (payload.fadeMs !== undefined && !(typeof payload.fadeMs === 'number' && payload.fadeMs > 0)) {\r\n return false;\r\n }\r\n return true;\r\n}\r\n\r\n/** Builds the presence payload for one local `LaserTool` emission. */\r\nexport function toLaserTrailPresence(emission: LaserTrailEmission): LaserTrailPresence {\r\n return {\r\n kind: LASER_TRAIL_PRESENCE_KIND,\r\n points: emission.points.map((point) => ({ x: point.x, y: point.y })),\r\n color: emission.color,\r\n width: emission.width,\r\n fadeMs: emission.fadeMs,\r\n };\r\n}\r\n\r\n/**\r\n * The two viewport capabilities the overlay needs; `Viewport` satisfies it.\r\n */\r\nexport interface RemoteLaserOverlayHost {\r\n registerOverlay(draw: OverlayRenderer): () => void;\r\n requestRender(): void;\r\n}\r\n\r\nexport interface RemoteLaserOverlayOptions {\r\n /** Style fallbacks when a payload omits them. */\r\n color?: string;\r\n width?: number;\r\n fadeMs?: number;\r\n /** Per-sender point cap; oldest points drop first. Default `512`. */\r\n maxPointsPerSender?: number;\r\n}\r\n\r\ninterface RemoteTrailPoint {\r\n x: number;\r\n y: number;\r\n t: number;\r\n}\r\n\r\ninterface RemoteTrail {\r\n points: RemoteTrailPoint[];\r\n color: string;\r\n width: number;\r\n fadeMs: number;\r\n}\r\n\r\nconst DEFAULT_COLOR = '#ff3b30';\r\nconst DEFAULT_WIDTH = 4;\r\nconst DEFAULT_FADE_MS = 1200;\r\nconst DEFAULT_MAX_POINTS = 512;\r\n\r\n/**\r\n * Renders fading laser trails for remote senders through the viewport overlay\r\n * registration, independent of the viewer's active tool. Points are stamped\r\n * with local receive time (remote clocks are never trusted), fade like the\r\n * local `LaserTool`, and a sender's trail disappears immediately on\r\n * `remove()` — wire that to `presence-leave`/disconnect. The controller never\r\n * touches elements, history, or persisted state.\r\n */\r\nexport class RemoteLaserOverlay {\r\n private readonly host: RemoteLaserOverlayHost;\r\n private readonly color: string;\r\n private readonly width: number;\r\n private readonly fadeMs: number;\r\n private readonly maxPointsPerSender: number;\r\n private readonly trails = new Map<string, RemoteTrail>();\r\n private unregister: (() => void) | null;\r\n private rafId: number | null = null;\r\n private disposed = false;\r\n\r\n constructor(host: RemoteLaserOverlayHost, options: RemoteLaserOverlayOptions = {}) {\r\n this.host = host;\r\n this.color = options.color ?? DEFAULT_COLOR;\r\n this.width = options.width ?? DEFAULT_WIDTH;\r\n this.fadeMs = options.fadeMs ?? DEFAULT_FADE_MS;\r\n this.maxPointsPerSender = options.maxPointsPerSender ?? DEFAULT_MAX_POINTS;\r\n this.unregister = host.registerOverlay((ctx) => this.renderTrails(ctx));\r\n }\r\n\r\n private now(): number {\r\n return performance.now();\r\n }\r\n\r\n /**\r\n * Applies a presence payload from `sender` (any opaque per-sender key, e.g.\r\n * the envelope `from`). Non-laser or malformed payloads are ignored and\r\n * reported as `false`, so hosts can feed every presence frame through.\r\n */\r\n apply(sender: string, data: unknown): boolean {\r\n if (this.disposed || !isLaserTrailPresence(data)) return false;\r\n let trail = this.trails.get(sender);\r\n if (!trail) {\r\n trail = { points: [], color: this.color, width: this.width, fadeMs: this.fadeMs };\r\n this.trails.set(sender, trail);\r\n }\r\n trail.color = data.color ?? this.color;\r\n trail.width = data.width ?? this.width;\r\n trail.fadeMs = data.fadeMs ?? this.fadeMs;\r\n const t = this.now();\r\n for (const point of data.points) {\r\n trail.points.push({ x: point.x, y: point.y, t });\r\n }\r\n const excess = trail.points.length - this.maxPointsPerSender;\r\n if (excess > 0) trail.points.splice(0, excess);\r\n this.ensureAnimating();\r\n this.host.requestRender();\r\n return true;\r\n }\r\n\r\n /** Removes a sender's trail immediately (presence-leave/disconnect). */\r\n remove(sender: string): void {\r\n if (this.trails.delete(sender)) this.host.requestRender();\r\n }\r\n\r\n /** Removes every trail immediately. */\r\n clear(): void {\r\n if (this.trails.size === 0) return;\r\n this.trails.clear();\r\n this.host.requestRender();\r\n }\r\n\r\n /** Number of senders with a live (unfaded) trail. */\r\n get activeSenderCount(): number {\r\n return this.trails.size;\r\n }\r\n\r\n /** Unregisters the overlay and stops the fade loop. Idempotent. */\r\n dispose(): void {\r\n if (this.disposed) return;\r\n this.disposed = true;\r\n if (this.rafId !== null) {\r\n cancelAnimationFrame(this.rafId);\r\n this.rafId = null;\r\n }\r\n this.trails.clear();\r\n this.unregister?.();\r\n this.unregister = null;\r\n }\r\n\r\n private ensureAnimating(): void {\r\n if (this.rafId === null) {\r\n this.rafId = requestAnimationFrame(() => this.tick());\r\n }\r\n }\r\n\r\n private tick(): void {\r\n if (this.disposed) return;\r\n const now = this.now();\r\n for (const [sender, trail] of this.trails) {\r\n const cutoff = now - trail.fadeMs;\r\n trail.points = trail.points.filter((point) => point.t >= cutoff);\r\n if (trail.points.length === 0) this.trails.delete(sender);\r\n }\r\n this.host.requestRender();\r\n this.rafId = this.trails.size > 0 ? requestAnimationFrame(() => this.tick()) : null;\r\n }\r\n\r\n private renderTrails(ctx: CanvasRenderingContext2D): void {\r\n if (this.trails.size === 0) return;\r\n const now = this.now();\r\n for (const trail of this.trails.values()) {\r\n if (trail.points.length < 2) continue;\r\n ctx.save();\r\n ctx.strokeStyle = trail.color;\r\n ctx.lineWidth = trail.width;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n for (let i = 0; i < trail.points.length - 1; i++) {\r\n const a = trail.points[i];\r\n const b = trail.points[i + 1];\r\n if (!a || !b) continue;\r\n const age = now - b.t;\r\n ctx.globalAlpha = Math.max(0, 1 - age / trail.fadeMs);\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 }\r\n ctx.restore();\r\n }\r\n }\r\n}\r\n","/**\r\n * Shared expanding-pulse rendering for map pings. Internal helper used by the\r\n * local `PingTool` overlay and the `RemotePingOverlay` so a viewer sees the\r\n * same animation for local and remote pings. Not part of the public API.\r\n */\r\n\r\nexport interface PingPulseStyle {\r\n color: string;\r\n /** Total animation length in milliseconds. */\r\n durationMs: number;\r\n /** Maximum ripple radius in world units. */\r\n radius: number;\r\n}\r\n\r\n/** Ripple start offsets as fractions of the total duration. */\r\nconst RIPPLE_OFFSETS = [0, 0.25] as const;\r\n\r\nfunction easeOutCubic(t: number): number {\r\n const inv = 1 - t;\r\n return 1 - inv * inv * inv;\r\n}\r\n\r\n/**\r\n * Draws one ping at world position (`x`, `y`) given its age. The context is\r\n * already in world space. Draws nothing once `ageMs >= durationMs`.\r\n */\r\nexport function renderPingPulse(\r\n ctx: CanvasRenderingContext2D,\r\n x: number,\r\n y: number,\r\n ageMs: number,\r\n style: PingPulseStyle,\r\n): void {\r\n if (ageMs < 0 || ageMs >= style.durationMs) return;\r\n\r\n ctx.save();\r\n ctx.strokeStyle = style.color;\r\n ctx.fillStyle = style.color;\r\n\r\n for (const offset of RIPPLE_OFFSETS) {\r\n const rippleSpan = style.durationMs * (1 - offset);\r\n const rippleAge = ageMs - style.durationMs * offset;\r\n if (rippleAge < 0) continue;\r\n const progress = Math.min(1, rippleAge / rippleSpan);\r\n const rippleRadius = style.radius * easeOutCubic(progress);\r\n if (rippleRadius <= 0) continue;\r\n ctx.globalAlpha = Math.max(0, 1 - progress);\r\n ctx.lineWidth = Math.max(1.5, style.radius / 12);\r\n ctx.beginPath();\r\n ctx.arc(x, y, rippleRadius, 0, Math.PI * 2);\r\n ctx.stroke();\r\n }\r\n\r\n // Center dot: solid for the first half, then fades with the ripples.\r\n const dotProgress = ageMs / style.durationMs;\r\n ctx.globalAlpha = Math.max(0, 1 - Math.max(0, dotProgress - 0.5) * 2);\r\n ctx.beginPath();\r\n ctx.arc(x, y, Math.max(2, style.radius / 8), 0, Math.PI * 2);\r\n ctx.fill();\r\n\r\n ctx.restore();\r\n}\r\n","import type { OverlayRenderer } from './render-loop';\r\nimport { renderPingPulse } from './ping-pulse';\r\nimport type { PingEmission } from '../tools/ping-tool';\r\n\r\n/**\r\n * The wire shape of a map-ping presence payload. Presence data is untyped on\r\n * the wire, so hosts discriminate on `kind`; `isPingPresence` validates a\r\n * received payload before it reaches the overlay. Pings are ephemeral by\r\n * contract: they must travel as presence only — never as elements, undo\r\n * history, persisted canvas state, or durable operations.\r\n */\r\nexport interface PingPresence {\r\n readonly kind: 'ping';\r\n /** World-space ping position. */\r\n readonly x: number;\r\n readonly y: number;\r\n readonly color?: string;\r\n readonly durationMs?: number;\r\n readonly radius?: number;\r\n}\r\n\r\nexport const PING_PRESENCE_KIND = 'ping';\r\n\r\nexport function isPingPresence(data: unknown): data is PingPresence {\r\n if (typeof data !== 'object' || data === null) return false;\r\n const payload = data as {\r\n kind?: unknown;\r\n x?: unknown;\r\n y?: unknown;\r\n color?: unknown;\r\n durationMs?: unknown;\r\n radius?: unknown;\r\n };\r\n if (payload.kind !== PING_PRESENCE_KIND) return false;\r\n if (typeof payload.x !== 'number' || !Number.isFinite(payload.x)) return false;\r\n if (typeof payload.y !== 'number' || !Number.isFinite(payload.y)) return false;\r\n if (payload.color !== undefined && typeof payload.color !== 'string') return false;\r\n if (\r\n payload.durationMs !== undefined &&\r\n !(\r\n typeof payload.durationMs === 'number' &&\r\n Number.isFinite(payload.durationMs) &&\r\n payload.durationMs > 0\r\n )\r\n ) {\r\n return false;\r\n }\r\n if (\r\n payload.radius !== undefined &&\r\n !(typeof payload.radius === 'number' && Number.isFinite(payload.radius) && payload.radius > 0)\r\n ) {\r\n return false;\r\n }\r\n return true;\r\n}\r\n\r\n/** Builds the presence payload for one local `PingTool` emission. */\r\nexport function toPingPresence(emission: PingEmission): PingPresence {\r\n return {\r\n kind: PING_PRESENCE_KIND,\r\n x: emission.x,\r\n y: emission.y,\r\n color: emission.color,\r\n durationMs: emission.durationMs,\r\n radius: emission.radius,\r\n };\r\n}\r\n\r\n/**\r\n * The two viewport capabilities the overlay needs; `Viewport` satisfies it.\r\n */\r\nexport interface RemotePingOverlayHost {\r\n registerOverlay(draw: OverlayRenderer): () => void;\r\n requestRender(): void;\r\n}\r\n\r\nexport interface RemotePingOverlayOptions {\r\n /** Style fallbacks when a payload omits them. */\r\n color?: string;\r\n durationMs?: number;\r\n radius?: number;\r\n /** Per-sender live-ping cap; oldest pings drop first. Default `8`. */\r\n maxPingsPerSender?: number;\r\n}\r\n\r\ninterface RemotePing {\r\n x: number;\r\n y: number;\r\n t: number;\r\n color: string;\r\n durationMs: number;\r\n radius: number;\r\n}\r\n\r\nconst DEFAULT_COLOR = '#ff3b30';\r\nconst DEFAULT_DURATION_MS = 1800;\r\nconst DEFAULT_RADIUS = 48;\r\nconst DEFAULT_MAX_PINGS = 8;\r\n\r\n/**\r\n * Renders expanding-pulse pings for remote senders through the viewport\r\n * overlay registration, independent of the viewer's active tool. Pings are\r\n * stamped with local receive time (remote clocks are never trusted),\r\n * self-expire when their animation ends, and a sender's pings disappear\r\n * immediately on `remove()` — wire that to `presence-leave`/disconnect. The\r\n * controller never touches elements, history, or persisted state, and it\r\n * never moves the viewer's camera: pings are visual only.\r\n */\r\nexport class RemotePingOverlay {\r\n private readonly host: RemotePingOverlayHost;\r\n private readonly color: string;\r\n private readonly durationMs: number;\r\n private readonly radius: number;\r\n private readonly maxPingsPerSender: number;\r\n private readonly pings = new Map<string, RemotePing[]>();\r\n private unregister: (() => void) | null;\r\n private rafId: number | null = null;\r\n private disposed = false;\r\n\r\n constructor(host: RemotePingOverlayHost, options: RemotePingOverlayOptions = {}) {\r\n this.host = host;\r\n this.color = options.color ?? DEFAULT_COLOR;\r\n this.durationMs = options.durationMs ?? DEFAULT_DURATION_MS;\r\n this.radius = options.radius ?? DEFAULT_RADIUS;\r\n this.maxPingsPerSender = options.maxPingsPerSender ?? DEFAULT_MAX_PINGS;\r\n this.unregister = host.registerOverlay((ctx) => this.renderPings(ctx));\r\n }\r\n\r\n private now(): number {\r\n return performance.now();\r\n }\r\n\r\n /**\r\n * Applies a presence payload from `sender` (any opaque per-sender key, e.g.\r\n * the envelope `from`). Non-ping or malformed payloads are ignored and\r\n * reported as `false`, so hosts can feed every presence frame through.\r\n */\r\n apply(sender: string, data: unknown): boolean {\r\n if (this.disposed || !isPingPresence(data)) return false;\r\n let senderPings = this.pings.get(sender);\r\n if (!senderPings) {\r\n senderPings = [];\r\n this.pings.set(sender, senderPings);\r\n }\r\n senderPings.push({\r\n x: data.x,\r\n y: data.y,\r\n t: this.now(),\r\n color: data.color ?? this.color,\r\n durationMs: data.durationMs ?? this.durationMs,\r\n radius: data.radius ?? this.radius,\r\n });\r\n const excess = senderPings.length - this.maxPingsPerSender;\r\n if (excess > 0) senderPings.splice(0, excess);\r\n this.ensureAnimating();\r\n this.host.requestRender();\r\n return true;\r\n }\r\n\r\n /** Removes a sender's pings immediately (presence-leave/disconnect). */\r\n remove(sender: string): void {\r\n if (this.pings.delete(sender)) this.host.requestRender();\r\n }\r\n\r\n /** Removes every ping immediately. */\r\n clear(): void {\r\n if (this.pings.size === 0) return;\r\n this.pings.clear();\r\n this.host.requestRender();\r\n }\r\n\r\n /** Number of senders with a live (unexpired) ping. */\r\n get activeSenderCount(): number {\r\n return this.pings.size;\r\n }\r\n\r\n /** Unregisters the overlay and stops the animation loop. Idempotent. */\r\n dispose(): void {\r\n if (this.disposed) return;\r\n this.disposed = true;\r\n if (this.rafId !== null) {\r\n cancelAnimationFrame(this.rafId);\r\n this.rafId = null;\r\n }\r\n this.pings.clear();\r\n this.unregister?.();\r\n this.unregister = null;\r\n }\r\n\r\n private ensureAnimating(): void {\r\n if (this.rafId === null) {\r\n this.rafId = requestAnimationFrame(() => this.tick());\r\n }\r\n }\r\n\r\n private tick(): void {\r\n if (this.disposed) return;\r\n const now = this.now();\r\n for (const [sender, senderPings] of this.pings) {\r\n const live = senderPings.filter((ping) => now - ping.t < ping.durationMs);\r\n if (live.length === 0) {\r\n this.pings.delete(sender);\r\n } else {\r\n this.pings.set(sender, live);\r\n }\r\n }\r\n this.host.requestRender();\r\n this.rafId = this.pings.size > 0 ? requestAnimationFrame(() => this.tick()) : null;\r\n }\r\n\r\n private renderPings(ctx: CanvasRenderingContext2D): void {\r\n if (this.pings.size === 0) return;\r\n const now = this.now();\r\n for (const senderPings of this.pings.values()) {\r\n for (const ping of senderPings) {\r\n renderPingPulse(ctx, ping.x, ping.y, now - ping.t, {\r\n color: ping.color,\r\n durationMs: ping.durationMs,\r\n radius: ping.radius,\r\n });\r\n }\r\n }\r\n }\r\n}\r\n","import type { Point } from '../core/types';\nimport type { PingEmission } from '../tools/ping-tool';\n\n/**\n * The one camera capability `PingInput` needs; `Camera` satisfies it. Screen\n * coordinates are element-local (the same space `Camera.screenToWorld`\n * expects).\n */\nexport interface PingInputHost {\n screenToWorld(screen: Point): Point;\n}\n\nexport interface PingInputOptions {\n /**\n * Opt-in for the long-press gesture. Off by default: a hidden hold-to-ping\n * gesture surprises users outside shared-canvas products, so hosts enable\n * it deliberately. The keyboard/programmatic paths (`pingAtPointer`,\n * `pingAt`) are always available. Default `false`.\n */\n longPressEnabled?: boolean;\n /** Hold duration before a still press pings. Default `600`. */\n longPressMs?: number;\n /** Maximum pointer travel while holding; moving further cancels. Default `8`. */\n slopPx?: number;\n /** Emission style forwarded to hosts; matches `PingTool` defaults. */\n color?: string;\n durationMs?: number;\n radius?: number;\n /**\n * Minimum interval between emitted pings, shared across the long-press and\n * keyboard/programmatic paths. Faster pings are dropped entirely. Default\n * `300`.\n */\n minIntervalMs?: number;\n /**\n * Host veto consulted at fire time on every path (e.g. return `false` while\n * a ping tool is active to avoid double pings). A veto does not consume the\n * rate-limit interval.\n */\n shouldPing?: () => boolean;\n}\n\ninterface PressState {\n pointerId: number;\n /** Element-local press position; the ping fires here, not where the pointer drifted. */\n x: number;\n y: number;\n timer: ReturnType<typeof setTimeout>;\n}\n\nconst DEFAULT_LONG_PRESS_MS = 600;\nconst DEFAULT_SLOP_PX = 8;\nconst DEFAULT_COLOR = '#ff3b30';\nconst DEFAULT_DURATION_MS = 1800;\nconst DEFAULT_RADIUS = 48;\nconst DEFAULT_MIN_INTERVAL_MS = 300;\n\n/**\n * Always-available ping input alongside the active tool: long-press-to-ping\n * plus keyboard/programmatic pings, independent of `PingTool`.\n *\n * `PingInput` is a passive observer by contract. Its DOM pointer listeners are\n * registered `passive: true` and it never calls `preventDefault`,\n * `stopPropagation`, or captures pointers, so the active tool, panning, and\n * pinch navigation behave exactly as if it were absent (with a pencil active,\n * a still hold pings AND the pencil still draws its dot). It also never\n * renders: hosts feed emissions into their own `RemotePingOverlay` under a\n * `'self'` sender key. Pings are ephemeral — no elements, no undo history, no\n * persisted state, no camera movement.\n *\n * The long-press gesture is opt-in via `longPressEnabled` (hosts whose users\n * would not expect hold-to-ping simply leave it off and keep the keyboard\n * paths). When enabled, a long-press arms on the first pointer down (mouse\n * primary button, touch, or pen), fires after `longPressMs` at the original\n * press position, and\n * cancels on movement past `slopPx`, a second pointer (two-finger\n * navigation), or pointer up/cancel/leave. Keyboard support is a capability,\n * not a binding: hosts call `pingAtPointer()` (last tracked hover position,\n * world-converted at call time) or `pingAt(world)` from their own shortcut\n * handling.\n */\nexport class PingInput {\n private readonly element: HTMLElement;\n private readonly host: PingInputHost;\n private longPressEnabled: boolean;\n private longPressMs: number;\n private slopPx: number;\n private color: string;\n private durationMs: number;\n private radius: number;\n private minIntervalMs: number;\n private shouldPing: (() => boolean) | undefined;\n\n private press: PressState | null = null;\n private readonly downPointers = new Set<number>();\n private lastPointerScreen: Point | null = null;\n private lastEmitAt = -Infinity;\n private disposed = false;\n private optionListeners = new Set<() => void>();\n private pingListeners = new Set<(emission: PingEmission) => void>();\n\n private readonly handlePointerDown = (e: PointerEvent): void => this.onPointerDown(e);\n private readonly handlePointerMove = (e: PointerEvent): void => this.onPointerMove(e);\n private readonly handlePointerUp = (e: PointerEvent): void => this.onPointerEnd(e);\n private readonly handlePointerCancel = (e: PointerEvent): void => this.onPointerEnd(e);\n private readonly handlePointerLeave = (e: PointerEvent): void => this.onPointerEnd(e);\n\n constructor(element: HTMLElement, host: PingInputHost, options: PingInputOptions = {}) {\n this.element = element;\n this.host = host;\n this.longPressEnabled = options.longPressEnabled ?? false;\n this.longPressMs = options.longPressMs ?? DEFAULT_LONG_PRESS_MS;\n this.slopPx = options.slopPx ?? DEFAULT_SLOP_PX;\n this.color = options.color ?? DEFAULT_COLOR;\n this.durationMs = options.durationMs ?? DEFAULT_DURATION_MS;\n this.radius = options.radius ?? DEFAULT_RADIUS;\n this.minIntervalMs = options.minIntervalMs ?? DEFAULT_MIN_INTERVAL_MS;\n this.shouldPing = options.shouldPing;\n\n const opts: AddEventListenerOptions = { passive: true };\n element.addEventListener('pointerdown', this.handlePointerDown, opts);\n element.addEventListener('pointermove', this.handlePointerMove, opts);\n element.addEventListener('pointerup', this.handlePointerUp, opts);\n element.addEventListener('pointercancel', this.handlePointerCancel, opts);\n element.addEventListener('pointerleave', this.handlePointerLeave, opts);\n }\n\n private now(): number {\n return performance.now();\n }\n\n getOptions(): PingInputOptions {\n return {\n longPressEnabled: this.longPressEnabled,\n longPressMs: this.longPressMs,\n slopPx: this.slopPx,\n color: this.color,\n durationMs: this.durationMs,\n radius: this.radius,\n minIntervalMs: this.minIntervalMs,\n ...(this.shouldPing ? { shouldPing: this.shouldPing } : {}),\n };\n }\n\n setOptions(options: PingInputOptions): void {\n if (options.longPressEnabled !== undefined) {\n this.longPressEnabled = options.longPressEnabled;\n if (!this.longPressEnabled) this.cancelPress();\n }\n if (options.longPressMs !== undefined) this.longPressMs = options.longPressMs;\n if (options.slopPx !== undefined) this.slopPx = options.slopPx;\n if (options.color !== undefined) this.color = options.color;\n if (options.durationMs !== undefined) this.durationMs = options.durationMs;\n if (options.radius !== undefined) this.radius = options.radius;\n if (options.minIntervalMs !== undefined) this.minIntervalMs = options.minIntervalMs;\n if (options.shouldPing !== undefined) this.shouldPing = options.shouldPing;\n for (const listener of this.optionListeners) listener();\n }\n\n onOptionsChange(listener: () => void): () => void {\n this.optionListeners.add(listener);\n return () => this.optionListeners.delete(listener);\n }\n\n /**\n * Subscribes to emitted pings. Listeners must not throw; a throwing\n * listener is isolated so it cannot break input handling or other\n * listeners.\n */\n onPing(listener: (emission: PingEmission) => void): () => void {\n this.pingListeners.add(listener);\n return () => this.pingListeners.delete(listener);\n }\n\n /**\n * Pings at the last tracked pointer position (hover moves and presses),\n * world-converted at call time. Returns `false` when no pointer has been\n * seen yet, the host vetoes, or the rate limit drops the ping.\n */\n pingAtPointer(): boolean {\n if (this.disposed || this.lastPointerScreen === null) return false;\n return this.emit(this.host.screenToWorld(this.lastPointerScreen));\n }\n\n /** Pings a world position directly. Same veto and rate limit as every path. */\n pingAt(world: Point): boolean {\n if (this.disposed) return false;\n return this.emit(world);\n }\n\n /** Removes all DOM listeners and cancels any pending press. Idempotent. */\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n this.cancelPress();\n this.downPointers.clear();\n this.element.removeEventListener('pointerdown', this.handlePointerDown);\n this.element.removeEventListener('pointermove', this.handlePointerMove);\n this.element.removeEventListener('pointerup', this.handlePointerUp);\n this.element.removeEventListener('pointercancel', this.handlePointerCancel);\n this.element.removeEventListener('pointerleave', this.handlePointerLeave);\n this.optionListeners.clear();\n this.pingListeners.clear();\n }\n\n private toLocal(e: PointerEvent): Point {\n const rect = this.element.getBoundingClientRect();\n return { x: e.clientX - rect.left, y: e.clientY - rect.top };\n }\n\n private onPointerDown(e: PointerEvent): void {\n const local = this.toLocal(e);\n this.lastPointerScreen = local;\n\n const hadPointers = this.downPointers.size > 0;\n this.downPointers.add(e.pointerId);\n if (hadPointers) {\n // A second pointer means navigation, not a press — and the new pointer\n // must not arm its own press while others are down.\n this.cancelPress();\n return;\n }\n if (!this.longPressEnabled) return;\n if (e.pointerType === 'mouse' && e.button !== 0) return;\n\n this.press = {\n pointerId: e.pointerId,\n x: local.x,\n y: local.y,\n timer: setTimeout(() => this.firePress(), this.longPressMs),\n };\n }\n\n private onPointerMove(e: PointerEvent): void {\n const local = this.toLocal(e);\n this.lastPointerScreen = local;\n if (this.press === null || e.pointerId !== this.press.pointerId) return;\n const dx = local.x - this.press.x;\n const dy = local.y - this.press.y;\n if (Math.hypot(dx, dy) > this.slopPx) this.cancelPress();\n }\n\n private onPointerEnd(e: PointerEvent): void {\n this.downPointers.delete(e.pointerId);\n if (this.press !== null && e.pointerId === this.press.pointerId) this.cancelPress();\n }\n\n private cancelPress(): void {\n if (this.press === null) return;\n clearTimeout(this.press.timer);\n this.press = null;\n }\n\n private firePress(): void {\n if (this.press === null) return;\n const screen = { x: this.press.x, y: this.press.y };\n this.press = null;\n // Convert at fire time so the ping lands where the held pointer points now.\n this.emit(this.host.screenToWorld(screen));\n }\n\n private emit(world: Point): boolean {\n if (this.shouldPing && !this.shouldPing()) return false;\n const t = this.now();\n if (t - this.lastEmitAt < this.minIntervalMs) return false;\n this.lastEmitAt = t;\n const emission: PingEmission = {\n x: world.x,\n y: world.y,\n color: this.color,\n durationMs: this.durationMs,\n radius: this.radius,\n };\n for (const listener of this.pingListeners) {\n try {\n listener(emission);\n } catch {\n // A throwing host listener must not break input handling.\n }\n }\n return true;\n }\n}\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' || el.locked || (ctx.isLayerLocked?.(el.layerId) ?? false))\r\n 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' || el.locked || (ctx.isLayerLocked?.(el.layerId) ?? false)) 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' || el.locked || (ctx.isLayerLocked?.(el.layerId) ?? false)) {\r\n return null;\r\n }\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\r\nexport function renderArrowHoverHandle(\r\n canvasCtx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n zoom: number,\r\n): void {\r\n const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);\r\n const radius = HANDLE_RADIUS / zoom;\r\n canvasCtx.fillStyle = '#2196F3';\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.lineWidth = 1.5 / zoom;\r\n canvasCtx.beginPath();\r\n canvasCtx.arc(mid.x, mid.y, radius, 0, Math.PI * 2);\r\n canvasCtx.fill();\r\n canvasCtx.stroke();\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 templateAimKnob(\r\n el: CanvasElement,\r\n zoom: number,\r\n): { origin: Point; knob: Point } | null {\r\n if (el.type !== 'template') return null;\r\n if (\r\n el.templateShape !== 'cone' &&\r\n el.templateShape !== 'line' &&\r\n el.templateShape !== 'rectangle'\r\n )\r\n return null;\r\n const gap = ROTATE_HANDLE_OFFSET / zoom;\r\n const dist = el.radius + gap;\r\n const origin = el.position;\r\n return {\r\n origin,\r\n knob: {\r\n x: origin.x + dist * Math.cos(el.angle),\r\n y: origin.y + dist * Math.sin(el.angle),\r\n },\r\n };\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: {\r\n selectedIds: string[];\r\n store: ElementStore;\r\n zoom: number;\r\n isLayerLocked?: (layerId: string) => boolean;\r\n },\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 const locked = el.locked || (p.isLayerLocked?.(el.layerId) ?? false);\r\n\r\n if (el.type === 'arrow') {\r\n if (!locked) 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 if (!locked) {\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 }\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 if (el.templateShape === 'rectangle') {\r\n if (p.selectedIds.length === 1) {\r\n const cos = Math.cos(el.angle);\r\n const sin = Math.sin(el.angle);\r\n const halfW = (el.width ?? 0) / 2;\r\n const pts: [number, number][] = [\r\n [el.position.x + el.radius * cos, el.position.y + el.radius * sin],\r\n [\r\n el.position.x + (el.radius / 2) * cos + halfW * -sin,\r\n el.position.y + (el.radius / 2) * sin + halfW * cos,\r\n ],\r\n ];\r\n for (const [hx, hy] of pts) {\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 }\r\n }\r\n } else {\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 }\r\n ctx.setLineDash([4 / zoom, 4 / zoom]);\r\n\r\n if (\r\n p.selectedIds.length === 1 &&\r\n (el.templateShape === 'cone' ||\r\n el.templateShape === 'line' ||\r\n el.templateShape === 'rectangle')\r\n ) {\r\n const aim = templateAimKnob(el, zoom);\r\n if (aim) {\r\n ctx.beginPath();\r\n ctx.moveTo(aim.origin.x, aim.origin.y);\r\n ctx.lineTo(aim.knob.x, aim.knob.y);\r\n ctx.stroke();\r\n\r\n ctx.setLineDash([]);\r\n ctx.fillStyle = '#ffffff';\r\n ctx.beginPath();\r\n ctx.arc(aim.knob.x, aim.knob.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\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 templateAimKnob,\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 (\r\n !el ||\r\n el.type !== 'shape' ||\r\n el.shape !== 'line' ||\r\n el.locked ||\r\n (ctx.isLayerLocked?.(el.layerId) ?? false)\r\n )\r\n 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 if (el.templateShape === 'rectangle') 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 hitTestTemplateAimHandle(\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) return null;\r\n const knob = templateAimKnob(el, ctx.camera.zoom);\r\n if (!knob) return null;\r\n const r = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / ctx.camera.zoom;\r\n const dx = world.x - knob.knob.x;\r\n const dy = world.y - knob.knob.y;\r\n return dx * dx + dy * dy <= r * r ? { elementId: id } : null;\r\n}\r\n\r\nexport function hitTestRectangleLengthHandle(\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 || el.type !== 'template' || el.templateShape !== 'rectangle') return null;\r\n const zoom = ctx.camera.zoom;\r\n const r = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / zoom;\r\n const hx = el.position.x + el.radius * Math.cos(el.angle);\r\n const hy = el.position.y + el.radius * Math.sin(el.angle);\r\n const dx = world.x - hx;\r\n const dy = world.y - hy;\r\n return dx * dx + dy * dy <= r * r ? { elementId: id } : null;\r\n}\r\n\r\nexport function hitTestRectangleWidthHandle(\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 || el.type !== 'template' || el.templateShape !== 'rectangle') return null;\r\n const zoom = ctx.camera.zoom;\r\n const r = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / zoom;\r\n const cos = Math.cos(el.angle);\r\n const sin = Math.sin(el.angle);\r\n const halfW = (el.width ?? 0) / 2;\r\n const hx = el.position.x + (el.radius / 2) * cos + halfW * -sin;\r\n const hy = el.position.y + (el.radius / 2) * sin + halfW * cos;\r\n const dx = world.x - hx;\r\n const dy = world.y - hy;\r\n return dx * dx + dy * dy <= r * r ? { elementId: id } : 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 lockAspect: 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 (lockAspect && 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 lockAspect: 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 (lockAspect && 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\r\nexport function computeRectangleLengthResize(\r\n el: TemplateElement,\r\n world: Point,\r\n opts: TemplateResizeOptions,\r\n): Record<string, unknown> | null {\r\n const cos = Math.cos(el.angle);\r\n const sin = Math.sin(el.angle);\r\n let len = (world.x - el.position.x) * cos + (world.y - el.position.y) * sin;\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 len = Math.max(snapUnit, Math.round(len / snapUnit) * snapUnit);\r\n }\r\n len = Math.max(MIN_ELEMENT_SIZE, len);\r\n const updates: Record<string, unknown> = { radius: len };\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 = (len / snapUnit) * el.feetPerCell;\r\n }\r\n return updates;\r\n}\r\n\r\nexport function computeRectangleWidthResize(\r\n el: TemplateElement,\r\n world: Point,\r\n opts: TemplateResizeOptions,\r\n): Record<string, unknown> | null {\r\n const cos = Math.cos(el.angle);\r\n const sin = Math.sin(el.angle);\r\n const perp = Math.abs(-(world.x - el.position.x) * sin + (world.y - el.position.y) * cos);\r\n let width = perp * 2;\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 width = Math.max(snapUnit, Math.round(width / snapUnit) * snapUnit);\r\n }\r\n width = Math.max(MIN_ELEMENT_SIZE, width);\r\n return { width };\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 renderArrowHoverHandle,\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 hitTestTemplateAimHandle,\r\n hitTestRectangleLengthHandle,\r\n hitTestRectangleWidthHandle,\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 {\r\n computeResize,\r\n computeRotatedResize,\r\n computeTemplateResize,\r\n computeRectangleLengthResize,\r\n computeRectangleWidthResize,\r\n} 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: 'aiming-template'; elementId: string }\r\n | { type: 'resizing-rect-length'; elementId: string }\r\n | { type: 'resizing-rect-width'; 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 rectLengthHit = hitTestRectangleLengthHandle(world, ctx, this._selectedIds);\r\n if (rectLengthHit) {\r\n this.mode = { type: 'resizing-rect-length', elementId: rectLengthHit.elementId };\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n const rectWidthHit = hitTestRectangleWidthHandle(world, ctx, this._selectedIds);\r\n if (rectWidthHit) {\r\n this.mode = { type: 'resizing-rect-width', elementId: rectWidthHit.elementId };\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n const aimHit = hitTestTemplateAimHandle(world, ctx, this._selectedIds);\r\n if (aimHit) {\r\n this.mode = { type: 'aiming-template', elementId: aimHit.elementId };\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 (\r\n el &&\r\n el.type === 'shape' &&\r\n el.shape === 'line' &&\r\n !el.locked &&\r\n !(ctx.isLayerLocked?.(el.layerId) ?? false)\r\n ) {\r\n ctx.store.update(el.id, lineFromEndpoints(this.mode.fixed, world));\r\n ctx.requestRender();\r\n }\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 === 'aiming-template') {\r\n const el = ctx.store.getById(this.mode.elementId);\r\n if (el && el.type === 'template' && !el.locked) {\r\n let a = Math.atan2(world.y - el.position.y, world.x - el.position.x);\r\n if (state.shiftKey) {\r\n const snap = ctx.gridType === 'hex' ? Math.PI / 3 : ROTATE_SNAP;\r\n a = Math.round(a / snap) * snap;\r\n }\r\n ctx.store.update(this.mode.elementId, { angle: normalizeAngle(a) });\r\n ctx.requestRender();\r\n }\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'resizing-rect-length' || this.mode.type === 'resizing-rect-width') {\r\n ctx.setCursor?.(this.mode.type === 'resizing-rect-length' ? 'ew-resize' : 'ns-resize');\r\n const el = ctx.store.getById(this.mode.elementId);\r\n if (el && el.type === 'template' && !el.locked) {\r\n const opts = { snapToGrid: ctx.snapToGrid, gridSize: ctx.gridSize, gridType: ctx.gridType };\r\n const patch =\r\n this.mode.type === 'resizing-rect-length'\r\n ? computeRectangleLengthResize(el, world, opts)\r\n : computeRectangleWidthResize(el, world, opts);\r\n if (patch) {\r\n ctx.store.update(this.mode.elementId, patch);\r\n ctx.requestRender();\r\n }\r\n }\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 isLayerLocked: this.ctx.isLayerLocked,\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?.type === 'arrow') {\r\n canvasCtx.save();\r\n canvasCtx.globalAlpha = 0.35;\r\n canvasCtx.setLineDash([]);\r\n renderArrowHoverHandle(canvasCtx, el, this.ctx.camera.zoom);\r\n canvasCtx.restore();\r\n } else 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 (hitTestRectangleLengthHandle(world, ctx, this._selectedIds)) {\r\n ctx.setCursor?.('ew-resize');\r\n return null;\r\n }\r\n if (hitTestRectangleWidthHandle(world, ctx, this._selectedIds)) {\r\n ctx.setCursor?.('ns-resize');\r\n return null;\r\n }\r\n\r\n if (hitTestTemplateAimHandle(world, ctx, this._selectedIds)) {\r\n ctx.setCursor?.('grab');\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 lockAspect = shiftKey !== (el.type === 'image');\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 lockAspect,\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 lockAspect,\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 { ArrowStrokeStyle, 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 strokeStyle?: ArrowStrokeStyle;\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 strokeStyle: ArrowStrokeStyle;\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 this.strokeStyle = options.strokeStyle ?? 'solid';\r\n }\r\n\r\n getOptions(): ArrowToolOptions {\r\n return { color: this.color, width: this.width, strokeStyle: this.strokeStyle };\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 if (options.strokeStyle !== undefined) this.strokeStyle = options.strokeStyle;\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 strokeStyle: this.strokeStyle,\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, TemplateRenderStyle } 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 getHexCellsInRectangle,\r\n drawHexPath,\r\n} from '../elements/hex-fill';\r\nimport { renderTemplateFeetLabel } from '../elements/renderers/template-measure';\r\n\r\nconst MIN_RECT_WIDTH = 20;\r\n\r\nexport function defaultRectWidth(radius: number, scaleUnit: number): number {\r\n if (scaleUnit > 0) return scaleUnit; // one grid cell\r\n return Math.max(MIN_RECT_WIDTH, radius * 0.25);\r\n}\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 renderStyle?: TemplateRenderStyle;\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 feetScaleUnit = 0;\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 renderStyle: TemplateRenderStyle;\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 this.renderStyle = options.renderStyle ?? 'cells';\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 renderStyle: this.renderStyle,\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 if (options.renderStyle !== undefined) this.renderStyle = options.renderStyle;\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 this.feetScaleUnit =\r\n ctx.gridSize && ctx.gridSize > 0\r\n ? ctx.gridType === 'hex'\r\n ? Math.sqrt(3) * ctx.gridSize\r\n : ctx.gridSize\r\n : 0;\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 const width =\r\n this.templateShape === 'rectangle' ? defaultRectWidth(radius, this.feetScaleUnit) : undefined;\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 width,\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 renderStyle: this.renderStyle,\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 && this.renderStyle !== 'geometric') {\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 case 'rectangle': {\r\n const halfW = defaultRectWidth(radius, this.feetScaleUnit) / 2;\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 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 this.drawFeetLabel(ctx, radius);\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 case 'rectangle': {\r\n const widthCells = defaultRectWidth(radius, this.feetScaleUnit) / snapUnit;\r\n hexCells = getHexCellsInRectangle(\r\n center,\r\n angle,\r\n radiusCells,\r\n widthCells,\r\n cellSize,\r\n orientation,\r\n );\r\n break;\r\n }\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 this.templateShape === 'rectangle'\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 this.drawFeetLabel(ctx, radius);\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 drawFeetLabel(ctx: CanvasRenderingContext2D, radius: number): void {\r\n const feet = this.feetScaleUnit > 0 ? (radius / this.feetScaleUnit) * this.feetPerCell : 0;\r\n renderTemplateFeetLabel(ctx, {\r\n position: this.origin,\r\n radius,\r\n angle: this.computeAngle(),\r\n templateShape: this.templateShape,\r\n feet,\r\n color: this.strokeColor,\r\n });\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 { Tool, ToolContext, PointerState } from './types';\r\nimport type { Point } from '../core/types';\r\n\r\nexport interface LaserToolOptions {\r\n name?: string;\r\n color?: string;\r\n width?: number;\r\n fadeMs?: number;\r\n}\r\n\r\n/**\r\n * A coalesced batch of locally drawn trail points, flushed at most once per\r\n * animation frame — the outgoing side of a shared laser pointer. Emissions\r\n * carry world coordinates and the tool's current style so a host can forward\r\n * them as ephemeral presence without duplicating the tool's input handling.\r\n */\r\nexport interface LaserTrailEmission {\r\n /** World-space points recorded since the previous emission, oldest first. */\r\n readonly points: readonly Point[];\r\n readonly color: string;\r\n readonly width: number;\r\n readonly fadeMs: number;\r\n}\r\n\r\ninterface TrailPoint {\r\n x: number;\r\n y: number;\r\n t: number;\r\n}\r\n\r\nconst DEFAULT_COLOR = '#ff3b30';\r\nconst DEFAULT_WIDTH = 4;\r\nconst DEFAULT_FADE_MS = 1200;\r\n\r\nexport class LaserTool implements Tool {\r\n readonly name: string;\r\n private color: string;\r\n private width: number;\r\n private fadeMs: number;\r\n private trail: TrailPoint[] = [];\r\n private rafId: number | null = null;\r\n private drawing = false;\r\n private optionListeners = new Set<() => void>();\r\n private trailListeners = new Set<(emission: LaserTrailEmission) => void>();\r\n private pendingEmission: Point[] = [];\r\n\r\n constructor(options: LaserToolOptions = {}) {\r\n this.name = options.name ?? 'laser';\r\n this.color = options.color ?? DEFAULT_COLOR;\r\n this.width = options.width ?? DEFAULT_WIDTH;\r\n this.fadeMs = options.fadeMs ?? DEFAULT_FADE_MS;\r\n }\r\n\r\n private now(): number {\r\n return performance.now();\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 if (this.rafId !== null) {\r\n cancelAnimationFrame(this.rafId);\r\n this.rafId = null;\r\n }\r\n this.trail = [];\r\n this.drawing = false;\r\n this.pendingEmission = [];\r\n ctx.setCursor?.('default');\r\n ctx.requestRender();\r\n }\r\n\r\n getOptions(): LaserToolOptions {\r\n return {\r\n name: this.name,\r\n color: this.color,\r\n width: this.width,\r\n fadeMs: this.fadeMs,\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 /**\r\n * Subscribes to coalesced trail emissions. Points recorded by pointer input\r\n * are batched and delivered at most once per animation frame, keeping\r\n * outgoing presence packets small. Listeners must not throw; a throwing\r\n * listener is isolated so it cannot stall the fade loop.\r\n */\r\n onTrail(listener: (emission: LaserTrailEmission) => void): () => void {\r\n this.trailListeners.add(listener);\r\n return () => this.trailListeners.delete(listener);\r\n }\r\n\r\n setOptions(options: LaserToolOptions): 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.fadeMs !== undefined) this.fadeMs = options.fadeMs;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.drawing = true;\r\n this.recordPoint(state, ctx);\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.recordPoint(state, ctx);\r\n }\r\n\r\n private recordPoint(state: PointerState, ctx: ToolContext): void {\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.trail.push({ x: world.x, y: world.y, t: this.now() });\r\n if (this.trailListeners.size > 0) {\r\n this.pendingEmission.push({ x: world.x, y: world.y });\r\n }\r\n this.ensureAnimating(ctx);\r\n }\r\n\r\n onPointerUp(_state: PointerState, _ctx: ToolContext): void {\r\n this.drawing = false;\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (this.trail.length < 2) return;\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.color;\r\n ctx.lineWidth = this.width;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n\r\n const now = this.now();\r\n for (let i = 0; i < this.trail.length - 1; i++) {\r\n const a = this.trail[i];\r\n const b = this.trail[i + 1];\r\n if (!a || !b) continue;\r\n const age = now - b.t;\r\n ctx.globalAlpha = Math.max(0, 1 - age / this.fadeMs);\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 }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private ensureAnimating(ctx: ToolContext): void {\r\n if (this.rafId === null) {\r\n this.rafId = requestAnimationFrame(() => this.tick(ctx));\r\n }\r\n }\r\n\r\n private flushEmission(): void {\r\n if (this.pendingEmission.length === 0) return;\r\n const emission: LaserTrailEmission = {\r\n points: this.pendingEmission,\r\n color: this.color,\r\n width: this.width,\r\n fadeMs: this.fadeMs,\r\n };\r\n this.pendingEmission = [];\r\n for (const listener of this.trailListeners) {\r\n try {\r\n listener(emission);\r\n } catch {\r\n // A throwing host listener must not stall the fade/emission loop.\r\n }\r\n }\r\n }\r\n\r\n private tick(ctx: ToolContext): void {\r\n this.flushEmission();\r\n const cutoff = this.now() - this.fadeMs;\r\n this.trail = this.trail.filter((p) => p.t >= cutoff);\r\n if (this.trail.length > 0) {\r\n ctx.requestRender();\r\n this.rafId = requestAnimationFrame(() => this.tick(ctx));\r\n } else {\r\n ctx.requestRender();\r\n this.rafId = null;\r\n }\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 { Tool, ToolContext, PointerState } from './types';\r\nimport { renderPingPulse } from '../canvas/ping-pulse';\r\n\r\nexport interface PingToolOptions {\r\n name?: string;\r\n color?: string;\r\n /** Total pulse animation length in milliseconds. */\r\n durationMs?: number;\r\n /** Maximum ripple radius in world units. */\r\n radius?: number;\r\n /**\r\n * Minimum interval between emitted pings. Taps arriving faster are ignored\r\n * entirely (no local pulse, no emission), so rapid-fire pings cannot starve\r\n * durable sync traffic.\r\n */\r\n minIntervalMs?: number;\r\n}\r\n\r\n/**\r\n * One emitted ping — the outgoing side of a shared \"look here\" marker.\r\n * Emissions carry the world position and the tool's current style so a host\r\n * can forward them as ephemeral presence without duplicating input handling.\r\n */\r\nexport interface PingEmission {\r\n /** World-space ping position. */\r\n readonly x: number;\r\n readonly y: number;\r\n readonly color: string;\r\n readonly durationMs: number;\r\n readonly radius: number;\r\n}\r\n\r\ninterface LocalPing {\r\n x: number;\r\n y: number;\r\n t: number;\r\n}\r\n\r\nconst DEFAULT_COLOR = '#ff3b30';\r\nconst DEFAULT_DURATION_MS = 1800;\r\nconst DEFAULT_RADIUS = 48;\r\nconst DEFAULT_MIN_INTERVAL_MS = 300;\r\n\r\n/**\r\n * Tap or click to ping a world position: a short expanding-pulse animation is\r\n * rendered locally and one `PingEmission` is delivered to `onPing` listeners\r\n * per accepted tap. Pings are ephemeral by contract: they never create\r\n * elements, enter undo history, or touch persisted canvas state — hosts\r\n * forward emissions as presence only.\r\n */\r\nexport class PingTool implements Tool {\r\n readonly name: string;\r\n private color: string;\r\n private durationMs: number;\r\n private radius: number;\r\n private minIntervalMs: number;\r\n private pings: LocalPing[] = [];\r\n private lastEmitAt = -Infinity;\r\n private rafId: number | null = null;\r\n private optionListeners = new Set<() => void>();\r\n private pingListeners = new Set<(emission: PingEmission) => void>();\r\n\r\n constructor(options: PingToolOptions = {}) {\r\n this.name = options.name ?? 'ping';\r\n this.color = options.color ?? DEFAULT_COLOR;\r\n this.durationMs = options.durationMs ?? DEFAULT_DURATION_MS;\r\n this.radius = options.radius ?? DEFAULT_RADIUS;\r\n this.minIntervalMs = options.minIntervalMs ?? DEFAULT_MIN_INTERVAL_MS;\r\n }\r\n\r\n private now(): number {\r\n return performance.now();\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 if (this.rafId !== null) {\r\n cancelAnimationFrame(this.rafId);\r\n this.rafId = null;\r\n }\r\n this.pings = [];\r\n ctx.setCursor?.('default');\r\n ctx.requestRender();\r\n }\r\n\r\n getOptions(): PingToolOptions {\r\n return {\r\n name: this.name,\r\n color: this.color,\r\n durationMs: this.durationMs,\r\n radius: this.radius,\r\n minIntervalMs: this.minIntervalMs,\r\n };\r\n }\r\n\r\n setOptions(options: PingToolOptions): void {\r\n if (options.color !== undefined) this.color = options.color;\r\n if (options.durationMs !== undefined) this.durationMs = options.durationMs;\r\n if (options.radius !== undefined) this.radius = options.radius;\r\n if (options.minIntervalMs !== undefined) this.minIntervalMs = options.minIntervalMs;\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 /**\r\n * Subscribes to accepted pings. Listeners must not throw; a throwing\r\n * listener is isolated so it cannot break the tap handling or other\r\n * listeners.\r\n */\r\n onPing(listener: (emission: PingEmission) => void): () => void {\r\n this.pingListeners.add(listener);\r\n return () => this.pingListeners.delete(listener);\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n const t = this.now();\r\n if (t - this.lastEmitAt < this.minIntervalMs) return;\r\n this.lastEmitAt = t;\r\n\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.pings.push({ x: world.x, y: world.y, t });\r\n const emission: PingEmission = {\r\n x: world.x,\r\n y: world.y,\r\n color: this.color,\r\n durationMs: this.durationMs,\r\n radius: this.radius,\r\n };\r\n for (const listener of this.pingListeners) {\r\n try {\r\n listener(emission);\r\n } catch {\r\n // A throwing host listener must not break tap handling.\r\n }\r\n }\r\n this.ensureAnimating(ctx);\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\r\n // Pings are discrete taps; dragging does nothing.\r\n }\r\n\r\n onPointerUp(_state: PointerState, _ctx: ToolContext): void {\r\n // Nothing to finish; the ping fired on pointer down.\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (this.pings.length === 0) return;\r\n const now = this.now();\r\n for (const ping of this.pings) {\r\n renderPingPulse(ctx, ping.x, ping.y, now - ping.t, {\r\n color: this.color,\r\n durationMs: this.durationMs,\r\n radius: this.radius,\r\n });\r\n }\r\n }\r\n\r\n private ensureAnimating(ctx: ToolContext): void {\r\n if (this.rafId === null) {\r\n this.rafId = requestAnimationFrame(() => this.tick(ctx));\r\n }\r\n }\r\n\r\n private tick(ctx: ToolContext): void {\r\n const cutoff = this.now() - this.durationMs;\r\n this.pings = this.pings.filter((ping) => ping.t > cutoff);\r\n ctx.requestRender();\r\n this.rafId = this.pings.length > 0 ? requestAnimationFrame(() => this.tick(ctx)) : null;\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":["counter","center","minX","minY","minX","minY","center","n","center","cache","center","n","center","center","cache","ARROWHEAD_LENGTH","ARROWHEAD_ANGLE","ARROW_LABEL_FONT_SIZE","WIDTH_QUANTUM","d","center","unionBounds","center","moved","unionBounds","center","n","DEFAULT_COLOR","DEFAULT_COLOR","DEFAULT_DURATION_MS","DEFAULT_RADIUS","DEFAULT_RADIUS","center","HANDLE_HIT_PADDING","center","HANDLE_HIT_PADDING","center","BIND_THRESHOLD","center","DEFAULT_COLOR","DEFAULT_WIDTH","DEFAULT_FADE_MS","DEFAULT_COLOR","DEFAULT_DURATION_MS","DEFAULT_RADIUS","DEFAULT_MIN_INTERVAL_MS"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/snap.ts","../src/elements/note-sanitizer.ts","../src/core/state-serializer.ts","../src/core/storage/local-storage-adapter.ts","../src/core/auto-save.ts","../src/core/storage/memory-adapter.ts","../src/core/storage/indexeddb-adapter.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/pan-inertia.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-measure.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/minimap-transform.ts","../src/canvas/minimap.ts","../src/canvas/viewport-dom.ts","../src/canvas/hybrid-render-surface.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/text-canvas-renderer.ts","../src/canvas/html-export.ts","../src/canvas/export-image.ts","../src/canvas/export-svg.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-rotate.ts","../src/canvas/selection-ops.ts","../src/canvas/grid-controller.ts","../src/canvas/viewport-interactions.ts","../src/canvas/viewport.ts","../src/canvas/remote-laser-overlay.ts","../src/canvas/ping-pulse.ts","../src/canvas/remote-ping-overlay.ts","../src/canvas/measure-render.ts","../src/canvas/remote-measure-overlay.ts","../src/canvas/ping-input.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","../src/tools/laser-tool.ts","../src/tools/ping-tool.ts"],"sourcesContent":["export const VERSION = '0.57.0';\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';\nexport { MemoryAdapter } from './core/storage/memory-adapter';\nexport { LocalStorageAdapter } from './core/storage/local-storage-adapter';\nexport { IndexedDBAdapter } from './core/storage/indexeddb-adapter';\nexport type { StorageAdapter } from './core/storage/storage-adapter';\nexport type { IndexedDBAdapterOptions } from './core/storage/indexeddb-adapter';\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 {\n ViewportOptions,\n GridInfo,\n AlignEdge,\n DistributeAxis,\n RotateDirection,\n} from './canvas/viewport';\nexport { exportImage } from './canvas/export-image';\nexport type {\n ExportAssetError,\n ExportAssetErrorReason,\n ExportImageOptions,\n ExportResourceOptions,\n} from './canvas/export-image';\nexport { exportSvg } from './canvas/export-svg';\nexport type { ExportSvgOptions } from './canvas/export-svg';\nexport type {\n HtmlExportError,\n HtmlExportErrorReason,\n HtmlExportOptions,\n HtmlExportRenderer,\n} from './canvas/html-export';\nexport type { RenderStatsSnapshot } from './canvas/render-stats';\nexport type { OverlayRenderer } from './canvas/render-loop';\nexport {\n RemoteLaserOverlay,\n isLaserTrailPresence,\n toLaserTrailPresence,\n LASER_TRAIL_PRESENCE_KIND,\n} from './canvas/remote-laser-overlay';\nexport type {\n LaserTrailPresence,\n RemoteLaserOverlayHost,\n RemoteLaserOverlayOptions,\n} from './canvas/remote-laser-overlay';\nexport {\n RemotePingOverlay,\n isPingPresence,\n toPingPresence,\n PING_PRESENCE_KIND,\n} from './canvas/remote-ping-overlay';\nexport type {\n PingPresence,\n RemotePingOverlayHost,\n RemotePingOverlayOptions,\n} from './canvas/remote-ping-overlay';\nexport {\n RemoteMeasureOverlay,\n isMeasurePresence,\n toMeasurePresence,\n MEASURE_PRESENCE_KIND,\n} from './canvas/remote-measure-overlay';\nexport type {\n MeasurePresence,\n RemoteMeasureOverlayHost,\n RemoteMeasureOverlayOptions,\n} from './canvas/remote-measure-overlay';\nexport { PingInput } from './canvas/ping-input';\nexport type { PingInputHost, PingInputOptions } from './canvas/ping-input';\n\nexport { ElementStore } from './elements/element-store';\nexport type { ElementUpdateEvent } from './elements/element-store';\nexport type { ElementChangeMeta } 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 getHexCellsInRectangle,\n drawHexPath,\n} from './elements/hex-fill';\nexport type {\n Binding,\n CanvasElement,\n ElementType,\n StrokeElement,\n NoteElement,\n ArrowElement,\n ArrowStrokeStyle,\n ImageElement,\n HtmlElement,\n TextElement,\n ShapeElement,\n ShapeKind,\n GridElement,\n HexOrientation,\n TemplateElement,\n TemplateShape,\n TemplateRenderStyle,\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, MeasureEmission } from './tools/measure-tool';\nexport { TemplateTool } from './tools/template-tool';\nexport type { TemplateToolOptions } from './tools/template-tool';\nexport { LaserTool } from './tools/laser-tool';\nexport type { LaserToolOptions, LaserTrailEmission } from './tools/laser-tool';\nexport { PingTool } from './tools/ping-tool';\nexport type { PingToolOptions, PingEmission } from './tools/ping-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\nconst ELEMENT_TYPES = [\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] as const satisfies readonly CanvasElement['type'][];\r\ntype _ElementTypesAreExhaustive = CanvasElement['type'] extends (typeof ELEMENT_TYPES)[number]\r\n ? true\r\n : never;\r\nconst _elementTypesAreExhaustive: _ElementTypesAreExhaustive = true;\r\nvoid _elementTypesAreExhaustive;\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 (!isRecord(data)) {\r\n throw new Error('Invalid state: expected an object');\r\n }\r\n\r\n const obj = data;\r\n\r\n if (!Number.isInteger(obj['version']) || (obj['version'] as number) < 1) {\r\n throw new Error('Invalid state: missing or invalid version');\r\n }\r\n if ((obj['version'] as number) > CURRENT_VERSION) {\r\n throw new Error(`Invalid state: unsupported version ${String(obj['version'])}`);\r\n }\r\n\r\n if (!isRecord(obj['camera'])) {\r\n throw new Error('Invalid state: missing camera');\r\n }\r\n\r\n const cam = obj['camera'];\r\n if (!isRecord(cam['position'])) {\r\n throw new Error('Invalid state: missing camera.position');\r\n }\r\n\r\n if (!isPoint(cam['position'])) {\r\n throw new Error('Invalid state: camera.position must have finite x and y numbers');\r\n }\r\n\r\n if (!isFiniteNumber(cam['zoom']) || cam['zoom'] <= 0) {\r\n throw new Error('Invalid state: camera.zoom must be a positive finite number');\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 if (obj['layers'] !== undefined && !Array.isArray(obj['layers'])) {\r\n throw new Error('Invalid state: layers must be an array');\r\n }\r\n\r\n const elements = obj['elements'] as unknown[];\r\n const hasLayers = Array.isArray(obj['layers']) && obj['layers'].length > 0;\r\n for (const el of elements) {\r\n if (!isRecord(el)) throw new Error('Invalid element: expected an object');\r\n migrateElement(el, !hasLayers);\r\n }\r\n\r\n if (!hasLayers) {\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 const layers = obj['layers'] as unknown[];\r\n const layerIds = new Set<string>();\r\n for (const layer of layers) {\r\n validateLayer(layer);\r\n if (layerIds.has(layer.id)) throw new Error(`Invalid state: duplicate layer id \"${layer.id}\"`);\r\n layerIds.add(layer.id);\r\n }\r\n\r\n const elementIds = new Set<string>();\r\n for (const el of elements) {\r\n validateElement(el);\r\n if (elementIds.has(el.id)) throw new Error(`Invalid state: duplicate element id \"${el.id}\"`);\r\n elementIds.add(el.id);\r\n if (!layerIds.has(el.layerId)) {\r\n throw new Error(`Invalid element \"${el.id}\": unknown layerId \"${el.layerId}\"`);\r\n }\r\n }\r\n\r\n if (obj['activeLayerId'] !== undefined) {\r\n if (typeof obj['activeLayerId'] !== 'string' || !layerIds.has(obj['activeLayerId'])) {\r\n throw new Error('Invalid state: activeLayerId must reference an existing layer');\r\n }\r\n }\r\n\r\n cleanBindings(elements as Record<string, unknown>[]);\r\n}\r\n\r\nfunction validateElement(el: unknown): asserts el is CanvasElement {\r\n if (!isRecord(el)) {\r\n throw new Error('Invalid element: expected an object');\r\n }\r\n\r\n if (typeof el['id'] !== 'string' || el['id'].length === 0) {\r\n throw new Error('Invalid element: missing id');\r\n }\r\n if (!isEnum(el['type'], ELEMENT_TYPES)) {\r\n throw new Error(`Invalid element: unknown type \"${String(el['type'])}\"`);\r\n }\r\n if (!isFiniteNumber(el['zIndex'])) {\r\n throw new Error(`Invalid element \"${el['id']}\": missing or invalid zIndex`);\r\n }\r\n if (\r\n !isPoint(el['position']) ||\r\n typeof el['locked'] !== 'boolean' ||\r\n typeof el['layerId'] !== 'string' ||\r\n !isOptional(el['groupId'], isString) ||\r\n !isOptional(el['rotation'], isFiniteNumber)\r\n ) {\r\n throw new Error(`Invalid element \"${el['id']}\": invalid base fields or geometry`);\r\n }\r\n\r\n const valid = validateTypeFields(el, el['type']);\r\n if (!valid) throw new Error(`Invalid element \"${el['id']}\": malformed ${el['type']} data`);\r\n}\r\n\r\nfunction validateTypeFields(el: Record<string, unknown>, type: CanvasElement['type']): boolean {\r\n switch (type) {\r\n case 'stroke':\r\n return (\r\n Array.isArray(el['points']) &&\r\n el['points'].every(isStrokePoint) &&\r\n isString(el['color']) &&\r\n isFiniteNumber(el['width']) &&\r\n isFiniteNumber(el['opacity']) &&\r\n isOptionalEnum(el['blendMode'], ['multiply'])\r\n );\r\n case 'note':\r\n return (\r\n isSize(el['size']) &&\r\n isString(el['text']) &&\r\n isString(el['backgroundColor']) &&\r\n isString(el['textColor']) &&\r\n isOptional(el['fontSize'], isFiniteNumber)\r\n );\r\n case 'arrow':\r\n return (\r\n isPoint(el['from']) &&\r\n isPoint(el['to']) &&\r\n isFiniteNumber(el['bend']) &&\r\n isString(el['color']) &&\r\n isFiniteNumber(el['width']) &&\r\n isOptional(el['fromBinding'], isBinding) &&\r\n isOptional(el['toBinding'], isBinding) &&\r\n isOptional(el['cachedControlPoint'], isPoint) &&\r\n isOptional(el['label'], isString) &&\r\n isOptionalEnum(el['strokeStyle'], ['solid', 'dashed', 'dotted'])\r\n );\r\n case 'image':\r\n return isSize(el['size']) && isString(el['src']);\r\n case 'html':\r\n return (\r\n isSize(el['size']) &&\r\n isOptional(el['domId'], isString) &&\r\n isOptional(el['interactive'], isBoolean) &&\r\n isOptional(el['htmlType'], isString) &&\r\n isOptional(el['data'], isRecord)\r\n );\r\n case 'text':\r\n return (\r\n isSize(el['size']) &&\r\n isString(el['text']) &&\r\n isFiniteNumber(el['fontSize']) &&\r\n isString(el['color']) &&\r\n isEnum(el['textAlign'], ['left', 'center', 'right'])\r\n );\r\n case 'shape':\r\n return (\r\n isEnum(el['shape'], ['rectangle', 'ellipse', 'line']) &&\r\n isSize(el['size']) &&\r\n isString(el['strokeColor']) &&\r\n isFiniteNumber(el['strokeWidth']) &&\r\n isString(el['fillColor']) &&\r\n isOptional(el['flip'], isBoolean)\r\n );\r\n case 'grid':\r\n return (\r\n isEnum(el['gridType'], ['square', 'hex']) &&\r\n isEnum(el['hexOrientation'], ['pointy', 'flat']) &&\r\n isFiniteNumber(el['cellSize']) &&\r\n isString(el['strokeColor']) &&\r\n isFiniteNumber(el['strokeWidth']) &&\r\n isFiniteNumber(el['opacity'])\r\n );\r\n case 'template':\r\n return (\r\n isEnum(el['templateShape'], ['circle', 'cone', 'line', 'square', 'rectangle']) &&\r\n isFiniteNumber(el['radius']) &&\r\n isFiniteNumber(el['angle']) &&\r\n isOptional(el['width'], isFiniteNumber) &&\r\n isString(el['fillColor']) &&\r\n isString(el['strokeColor']) &&\r\n isFiniteNumber(el['strokeWidth']) &&\r\n isFiniteNumber(el['opacity']) &&\r\n isOptional(el['feetPerCell'], isFiniteNumber) &&\r\n isOptional(el['radiusFeet'], isFiniteNumber) &&\r\n isOptionalEnum(el['renderStyle'], ['cells', 'geometric'])\r\n );\r\n }\r\n}\r\n\r\nfunction validateLayer(layer: unknown): asserts layer is Layer {\r\n if (\r\n !isRecord(layer) ||\r\n typeof layer['id'] !== 'string' ||\r\n layer['id'].length === 0 ||\r\n typeof layer['name'] !== 'string' ||\r\n typeof layer['visible'] !== 'boolean' ||\r\n typeof layer['locked'] !== 'boolean' ||\r\n !isFiniteNumber(layer['order']) ||\r\n !isFiniteNumber(layer['opacity']) ||\r\n layer['opacity'] < 0 ||\r\n layer['opacity'] > 1\r\n ) {\r\n throw new Error('Invalid state: malformed layer');\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>, useDefaultLayer: boolean): void {\r\n if (obj['layerId'] === undefined || (useDefaultLayer && obj['layerId'] === '')) {\r\n obj['layerId'] = 'default-layer';\r\n }\r\n\r\n if (obj['type'] === 'arrow' && obj['bend'] === undefined) {\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 (pt['pressure'] === undefined) {\r\n pt['pressure'] = 0.5;\r\n }\r\n }\r\n }\r\n\r\n if (obj['type'] === 'shape' && obj['shape'] === undefined) {\r\n obj['shape'] = 'rectangle';\r\n }\r\n\r\n if (obj['type'] === 'note' && obj['textColor'] === undefined) {\r\n obj['textColor'] = '#000000';\r\n }\r\n\r\n if ((obj['type'] === 'note' || obj['type'] === 'text') && typeof obj['text'] === 'string') {\r\n obj['text'] = sanitizeNoteHtml(obj['text']);\r\n }\r\n}\r\n\r\ntype Validator = (value: unknown) => boolean;\r\n\r\nfunction isRecord(value: unknown): value is Record<string, unknown> {\r\n return typeof value === 'object' && value !== null && !Array.isArray(value);\r\n}\r\n\r\nfunction isFiniteNumber(value: unknown): value is number {\r\n return typeof value === 'number' && Number.isFinite(value);\r\n}\r\n\r\nfunction isString(value: unknown): value is string {\r\n return typeof value === 'string';\r\n}\r\n\r\nfunction isBoolean(value: unknown): value is boolean {\r\n return typeof value === 'boolean';\r\n}\r\n\r\nfunction isOptional(value: unknown, validate: Validator): boolean {\r\n return value === undefined || validate(value);\r\n}\r\n\r\nfunction isEnum<const T extends readonly string[]>(value: unknown, values: T): value is T[number] {\r\n return typeof value === 'string' && (values as readonly string[]).includes(value);\r\n}\r\n\r\nfunction isOptionalEnum<const T extends readonly string[]>(value: unknown, values: T): boolean {\r\n return value === undefined || isEnum(value, values);\r\n}\r\n\r\nfunction isPoint(value: unknown): boolean {\r\n return isRecord(value) && isFiniteNumber(value['x']) && isFiniteNumber(value['y']);\r\n}\r\n\r\nfunction isSize(value: unknown): boolean {\r\n return isRecord(value) && isFiniteNumber(value['w']) && isFiniteNumber(value['h']);\r\n}\r\n\r\nfunction isStrokePoint(value: unknown): boolean {\r\n return isRecord(value) && isPoint(value) && isFiniteNumber(value['pressure']);\r\n}\r\n\r\nfunction isBinding(value: unknown): boolean {\r\n return isRecord(value) && typeof value['elementId'] === 'string';\r\n}\r\n","import type { StorageAdapter } from './storage-adapter';\r\n\r\nexport class LocalStorageAdapter implements StorageAdapter {\r\n async load(key: string): Promise<string | null> {\r\n if (typeof localStorage === 'undefined') return null;\r\n return localStorage.getItem(key);\r\n }\r\n async save(key: string, value: string): Promise<void> {\r\n if (typeof localStorage === 'undefined') return;\r\n localStorage.setItem(key, value);\r\n }\r\n async clear(key: string): Promise<void> {\r\n if (typeof localStorage === 'undefined') return;\r\n localStorage.removeItem(key);\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\nimport { LocalStorageAdapter } from './storage/local-storage-adapter';\r\nimport type { StorageAdapter } from './storage/storage-adapter';\r\n\r\nexport interface AutoSaveOptions {\r\n key?: string;\r\n debounceMs?: number;\r\n layerManager?: LayerManager;\r\n adapter?: StorageAdapter;\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 readonly adapter: StorageAdapter;\r\n private timerId: ReturnType<typeof setTimeout> | null = null;\r\n private unsubscribers: (() => void)[] = [];\r\n private readonly onError?: (error: Error) => void;\r\n private saving = false;\r\n private pendingSave = false;\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.adapter = options.adapter ?? new LocalStorageAdapter();\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 async load(): Promise<CanvasState | null> {\r\n const json = await this.adapter.load(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 async clear(): Promise<void> {\r\n await this.adapter.clear(this.key);\r\n }\r\n\r\n private scheduleSave(): void {\r\n this.cancelPending();\r\n this.timerId = setTimeout(() => void 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 async save(): Promise<void> {\r\n if (this.saving) {\r\n this.pendingSave = true;\r\n return;\r\n }\r\n this.saving = true;\r\n try {\r\n const layers = this.layerManager?.snapshot() ?? [];\r\n const state = exportState(this.store.snapshot(), this.camera, layers);\r\n await this.adapter.save(this.key, JSON.stringify(state));\r\n } catch (e) {\r\n this.onError?.(e instanceof Error ? e : new Error(String(e)));\r\n } finally {\r\n this.saving = false;\r\n if (this.pendingSave) {\r\n this.pendingSave = false;\r\n void this.save();\r\n }\r\n }\r\n }\r\n}\r\n","import type { StorageAdapter } from './storage-adapter';\r\n\r\nexport class MemoryAdapter implements StorageAdapter {\r\n private store = new Map<string, string>();\r\n async load(key: string): Promise<string | null> {\r\n return this.store.get(key) ?? null;\r\n }\r\n async save(key: string, value: string): Promise<void> {\r\n this.store.set(key, value);\r\n }\r\n async clear(key: string): Promise<void> {\r\n this.store.delete(key);\r\n }\r\n}\r\n","import type { StorageAdapter } from './storage-adapter';\r\n\r\nexport interface IndexedDBAdapterOptions {\r\n dbName?: string;\r\n storeName?: string;\r\n indexedDB?: IDBFactory;\r\n}\r\n\r\nconst DEFAULT_DB = 'fieldnotes';\r\nconst DEFAULT_STORE = 'state';\r\n\r\nexport class IndexedDBAdapter implements StorageAdapter {\r\n private readonly dbName: string;\r\n private readonly storeName: string;\r\n private readonly idb: IDBFactory | null;\r\n private dbPromise: Promise<IDBDatabase> | null = null;\r\n\r\n constructor(options: IndexedDBAdapterOptions = {}) {\r\n this.dbName = options.dbName ?? DEFAULT_DB;\r\n this.storeName = options.storeName ?? DEFAULT_STORE;\r\n this.idb = options.indexedDB ?? (typeof indexedDB !== 'undefined' ? indexedDB : null);\r\n }\r\n\r\n private open(): Promise<IDBDatabase> {\r\n const idb = this.idb;\r\n if (!idb) return Promise.reject(new Error('IndexedDB unavailable'));\r\n if (!this.dbPromise) {\r\n const storeName = this.storeName;\r\n this.dbPromise = new Promise((resolve, reject) => {\r\n const req = idb.open(this.dbName, 1);\r\n req.onupgradeneeded = () => {\r\n const db = req.result;\r\n if (!db.objectStoreNames.contains(storeName)) db.createObjectStore(storeName);\r\n };\r\n req.onsuccess = () => resolve(req.result);\r\n req.onerror = () => reject(req.error ?? new Error('IndexedDB open failed'));\r\n });\r\n }\r\n return this.dbPromise;\r\n }\r\n\r\n async load(key: string): Promise<string | null> {\r\n if (!this.idb) return null;\r\n const db = await this.open();\r\n return new Promise((resolve, reject) => {\r\n const req = db.transaction(this.storeName, 'readonly').objectStore(this.storeName).get(key);\r\n req.onsuccess = () => {\r\n const v = req.result;\r\n resolve(typeof v === 'string' ? v : null);\r\n };\r\n req.onerror = () => reject(req.error ?? new Error('IndexedDB read failed'));\r\n });\r\n }\r\n\r\n async save(key: string, value: string): Promise<void> {\r\n if (!this.idb) return;\r\n const db = await this.open();\r\n return new Promise((resolve, reject) => {\r\n const tx = db.transaction(this.storeName, 'readwrite');\r\n tx.objectStore(this.storeName).put(value, key);\r\n tx.oncomplete = () => resolve();\r\n tx.onerror = () => reject(tx.error ?? new Error('IndexedDB write failed'));\r\n tx.onabort = () => reject(tx.error ?? new Error('IndexedDB write aborted'));\r\n });\r\n }\r\n\r\n async clear(key: string): Promise<void> {\r\n if (!this.idb) return;\r\n const db = await this.open();\r\n return new Promise((resolve, reject) => {\r\n const tx = db.transaction(this.storeName, 'readwrite');\r\n tx.objectStore(this.storeName).delete(key);\r\n tx.oncomplete = () => resolve();\r\n tx.onerror = () => reject(tx.error ?? new Error('IndexedDB delete failed'));\r\n tx.onabort = () => reject(tx.error ?? new Error('IndexedDB delete aborted'));\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;\r\n\r\nexport function randomClientComponent(): string {\r\n // getRandomValues works in NON-secure contexts (an iPad on http://LAN) — unlike crypto.randomUUID, which\r\n // is secure-context-gated in browsers. Uniqueness, not security.\r\n if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {\r\n const bytes = new Uint8Array(8);\r\n crypto.getRandomValues(bytes);\r\n return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join(''); // 16 hex = 64 bits\r\n }\r\n return Math.random().toString(36).slice(2, 14); // last resort — no crypto at all\r\n}\r\n\r\n// Per-process (per tab/worker) client component — generated ONCE at module load so two clients never collide\r\n// even at counter 0 in the same millisecond.\r\nconst CLIENT = randomClientComponent();\r\n\r\n// Internal (module-exported for tests; NOT in the package barrel — see index.ts / index.test.ts `removed`).\r\nexport function formatId(prefix: string, time: string, counter: string, client: string): string {\r\n return `${prefix}_${time}_${counter}_${client}`;\r\n}\r\n\r\nexport function createId(prefix: string): string {\r\n return formatId(prefix, Date.now().toString(36), (counter++).toString(36), CLIENT);\r\n}\r\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 // The bend handle sits at the curve midpoint (getArrowMidpoint), which is HALF the control-point\r\n // offset. Double the projection so the handle tracks the pointer 1:1 (bend is the control-point offset).\r\n return 2 * ((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 { rotatedAABB } from '../core/geometry';\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\n/** Axis-aligned world bounds covering the element's complete rotated visual footprint. */\r\nexport function getElementVisualBounds(element: CanvasElement): Bounds | null {\r\n const bounds = getElementBounds(element);\r\n if (!bounds) return null;\r\n const rotation = element.rotation ?? 0;\r\n return rotation === 0 ? bounds : rotatedAABB(bounds, rotation);\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 case 'rectangle': {\r\n const halfW = (el.width ?? 0) / 2;\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 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 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 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\nimport type { RotateDirection } from './selection-rotate';\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 rotate?: (direction: RotateDirection) => 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 private selectableElements(ctx: ToolContext): CanvasElement[] {\r\n return ctx.store\r\n .getAll()\r\n .filter(\r\n (el) =>\r\n !el.locked &&\r\n (ctx.isLayerVisible?.(el.layerId) ?? true) &&\r\n !(ctx.isLayerLocked?.(el.layerId) ?? false),\r\n );\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 const recorder = this.deps.getHistoryRecorder();\r\n if (recorder?.currentTransactionId !== this.nudgeTxId) {\r\n recorder?.begin();\r\n this.nudgeTxId = recorder?.currentTransactionId ?? null;\r\n }\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 (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 = this.selectableElements(sel.ctx).map((el) => el.id);\r\n sel.tool.setSelection(ids);\r\n sel.ctx.requestRender();\r\n }\r\n\r\n cycleSelection(direction: 1 | -1): 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') ctx.switchTool?.('select');\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const eligible = this.selectableElements(sel.ctx).filter((el) => el.type !== 'grid');\r\n if (eligible.length === 0) return;\r\n const idxs = sel.tool.selectedIds\r\n .map((id) => eligible.findIndex((e) => e.id === id))\r\n .filter((i) => i >= 0);\r\n const anchor =\r\n idxs.length === 0\r\n ? direction > 0\r\n ? -1\r\n : 0\r\n : direction > 0\r\n ? Math.max(...idxs)\r\n : Math.min(...idxs);\r\n const next = (anchor + direction + eligible.length) % eligible.length;\r\n const target = eligible[next];\r\n if (!target) return;\r\n sel.tool.setSelection([target.id]);\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 rotate(direction: RotateDirection): 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 if (sel.tool.selectedIds.length === 0) return;\r\n this.deps.rotate?.(direction);\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 ['cycle-selection', ['tab']],\r\n ['cycle-selection-reverse', ['shift+tab']],\r\n ['copy', ['mod+c']],\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 ['rotate-cw', ['r']],\r\n ['rotate-ccw', ['shift+r']],\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 addImage: (src: string, world: { x: number; y: number }) => string;\r\n getLastPointerWorld: () => { x: number; y: number } | null;\r\n getCenteredWorld: () => { x: number; y: number };\r\n onPaste?: (e: ClipboardEvent, world: { x: number; y: number }) => 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 window.addEventListener('paste', this.onPaste, { 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 private shouldHandle(target: EventTarget | null): boolean {\r\n const el = target as HTMLElement | null;\r\n if (el?.isContentEditable) return false;\r\n const tag = el?.tagName;\r\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return false;\r\n return this.isInScope();\r\n }\r\n\r\n onKeyDown = (e: KeyboardEvent): void => {\r\n if (!this.shouldHandle(e.target)) 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 onPaste = (e: ClipboardEvent): void => {\r\n if (!this.shouldHandle(e.target)) return;\r\n const items = e.clipboardData?.items;\r\n let file: File | null = null;\r\n if (items) {\r\n for (const it of items) {\r\n if (it.kind === 'file' && it.type.startsWith('image/')) {\r\n file = it.getAsFile();\r\n break;\r\n }\r\n }\r\n }\r\n if (file) {\r\n e.preventDefault();\r\n const world = this.deps.getLastPointerWorld() ?? this.deps.getCenteredWorld();\r\n if (this.deps.onPaste) {\r\n this.deps.onPaste(e, world);\r\n return;\r\n }\r\n const reader = new FileReader();\r\n reader.onload = () => {\r\n if (typeof reader.result === 'string') this.deps.addImage(reader.result, world);\r\n };\r\n reader.readAsDataURL(file);\r\n return;\r\n }\r\n this.deps.actions.paste();\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 'cycle-selection':\r\n e?.preventDefault();\r\n this.deps.actions.cycleSelection(1);\r\n return;\r\n case 'cycle-selection-reverse':\r\n e?.preventDefault();\r\n this.deps.actions.cycleSelection(-1);\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 'rotate-cw':\r\n e?.preventDefault();\r\n this.deps.actions.rotate('cw');\r\n return;\r\n case 'rotate-ccw':\r\n e?.preventDefault();\r\n this.deps.actions.rotate('ccw');\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","export interface PanInertiaDeps {\r\n pan: (dx: number, dy: number) => void;\r\n now: () => number;\r\n requestFrame: (cb: () => void) => number;\r\n cancelFrame: (id: number) => void;\r\n enabled: () => boolean;\r\n}\r\n\r\n// Only the last VELOCITY_WINDOW_MS of drag samples count toward release velocity,\r\n// so a paused or slow finger at release does not produce a coast.\r\nconst VELOCITY_WINDOW_MS = 60;\r\nconst FRICTION = 0.92;\r\nconst MIN_START_SPEED = 2;\r\nconst MIN_STOP_SPEED = 0.3;\r\n\r\ninterface Sample {\r\n dx: number;\r\n dy: number;\r\n t: number;\r\n}\r\n\r\nexport class PanInertia {\r\n private samples: Sample[] = [];\r\n private vx = 0;\r\n private vy = 0;\r\n private rafId: number | null = null;\r\n\r\n constructor(private readonly deps: PanInertiaDeps) {}\r\n\r\n sample(dx: number, dy: number): void {\r\n const t = this.deps.now();\r\n this.samples.push({ dx, dy, t });\r\n this.prune(t);\r\n }\r\n\r\n release(): void {\r\n if (!this.deps.enabled()) {\r\n this.reset();\r\n return;\r\n }\r\n const t = this.deps.now();\r\n this.prune(t);\r\n const recent = this.samples;\r\n if (recent.length === 0) {\r\n this.reset();\r\n return;\r\n }\r\n let sx = 0;\r\n let sy = 0;\r\n for (const s of recent) {\r\n sx += s.dx;\r\n sy += s.dy;\r\n }\r\n this.vx = sx / recent.length;\r\n this.vy = sy / recent.length;\r\n this.samples = [];\r\n if (Math.hypot(this.vx, this.vy) < MIN_START_SPEED) {\r\n this.vx = 0;\r\n this.vy = 0;\r\n return;\r\n }\r\n this.rafId = this.deps.requestFrame(this.step);\r\n }\r\n\r\n cancel(): void {\r\n this.reset();\r\n }\r\n\r\n private step = (): void => {\r\n if (this.rafId === null) return;\r\n this.deps.pan(this.vx, this.vy);\r\n this.vx *= FRICTION;\r\n this.vy *= FRICTION;\r\n if (Math.hypot(this.vx, this.vy) >= MIN_STOP_SPEED) {\r\n this.rafId = this.deps.requestFrame(this.step);\r\n } else {\r\n this.reset();\r\n }\r\n };\r\n\r\n private prune(now: number): void {\r\n const cutoff = now - VELOCITY_WINDOW_MS;\r\n this.samples = this.samples.filter((s) => s.t >= cutoff);\r\n }\r\n\r\n private reset(): void {\r\n if (this.rafId !== null) {\r\n this.deps.cancelFrame(this.rafId);\r\n this.rafId = null;\r\n }\r\n this.samples = [];\r\n this.vx = 0;\r\n this.vy = 0;\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 type { RotateDirection } from './selection-rotate';\r\nimport { InputFilter } from './input-filter';\r\nimport { KeyboardActions } from './keyboard-actions';\r\nimport { KeyboardHandler } from './keyboard-handler';\r\nimport { PanInertia } from './pan-inertia';\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 rotate?: (direction: RotateDirection) => void;\r\n openContextMenu?: (screenPos: Point, world: Point) => void;\r\n shortcuts?: ShortcutOptions;\r\n addImage?: (src: string, world: { x: number; y: number }) => string;\r\n getCenteredWorld?: () => { x: number; y: number };\r\n onPaste?: (event: ClipboardEvent, worldPosition: { x: number; y: number }) => void;\r\n panInertia?: boolean;\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 private readonly panInertia: PanInertia;\r\n private readonly panInertiaEnabled: boolean;\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 rotate: options.rotate,\r\n getLastPointerWorld: () => this.lastPointerWorld(),\r\n });\r\n this.openContextMenu = options.openContextMenu;\r\n this.panInertiaEnabled = options.panInertia ?? true;\r\n this.panInertia = new PanInertia({\r\n pan: (dx, dy) => this.camera.pan(dx, dy),\r\n now: () => (typeof performance !== 'undefined' ? performance.now() : Date.now()),\r\n requestFrame: (cb) =>\r\n typeof requestAnimationFrame !== 'undefined' ? requestAnimationFrame(cb) : 0,\r\n cancelFrame: (id) => {\r\n if (typeof cancelAnimationFrame !== 'undefined') cancelAnimationFrame(id);\r\n },\r\n enabled: () => this.panInertiaEnabled,\r\n });\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 addImage: options.addImage ?? (() => ''),\r\n getLastPointerWorld: () => this.lastPointerWorld(),\r\n getCenteredWorld: options.getCenteredWorld ?? (() => ({ x: 0, y: 0 })),\r\n onPaste: options.onPaste,\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.panInertia.cancel();\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 this.panInertia.cancel();\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.panInertia.cancel();\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 this.panInertia.sample(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 const removedActivePointer = this.activePointers.delete(e.pointerId);\r\n\r\n if (removedActivePointer && this.activePointers.size >= 2) {\r\n // Pointer membership may have changed the first-two navigation pair. Rebaseline before the\r\n // next move so the replacement pointer cannot produce a discontinuous pan or zoom.\r\n this.startPinch();\r\n } else if (this.activePointers.size < 2) {\r\n this.lastPinchDistance = 0;\r\n const remainingPointer = this.activePointers.values().next().value;\r\n if (remainingPointer && this.isPanning) {\r\n this.lastPointer = { ...remainingPointer };\r\n }\r\n }\r\n\r\n if (this.isPanning && this.activePointers.size === 0) {\r\n this.isPanning = false;\r\n this.panInertia.release();\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.panInertia.cancel();\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 const rect = this.element.getBoundingClientRect();\r\n this.camera.zoomAt(newZoom, {\r\n x: center.x - rect.left,\r\n y: center.y - rect.top,\r\n });\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 this.panInertia.sample(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","export interface EventMeta {\r\n origin?: string;\r\n}\r\n\r\nconst EMPTY_META: EventMeta = Object.freeze({});\r\n\r\ntype Listener<T> = (data: T, meta: EventMeta) => 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], meta: EventMeta = EMPTY_META): void {\r\n this.listeners.get(event)?.forEach((listener) => {\r\n try {\r\n listener(data as never, meta);\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\nfunction contains(outer: Bounds, inner: Bounds): boolean {\r\n return (\r\n inner.x >= outer.x &&\r\n inner.x + inner.w <= outer.x + outer.w &&\r\n inner.y >= outer.y &&\r\n inner.y + inner.h <= outer.y + outer.h\r\n );\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 collect(result: Entry[]): void {\r\n result.push(...this.items);\r\n if (this.children) {\r\n for (const child of this.children) {\r\n child.collect(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.expandToFit(bounds);\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 private expandToFit(bounds: Bounds): void {\r\n const current = this.root.bounds;\r\n if (contains(current, bounds)) return;\r\n\r\n const currentRight = current.x + current.w;\r\n const currentBottom = current.y + current.h;\r\n const requiredWidth =\r\n Math.max(currentRight, bounds.x + bounds.w) - Math.min(current.x, bounds.x);\r\n const requiredHeight =\r\n Math.max(currentBottom, bounds.y + bounds.h) - Math.min(current.y, bounds.y);\r\n const width = Math.max(current.w * 2, requiredWidth);\r\n const height = Math.max(current.h * 2, requiredHeight);\r\n const x = bounds.x < current.x ? currentRight - width : current.x;\r\n const y = bounds.y < current.y ? currentBottom - height : current.y;\r\n\r\n const entries: Entry[] = [];\r\n this.root.collect(entries);\r\n this.root = new QuadNode({ x, y, w: width, h: height }, 0);\r\n for (const entry of entries) {\r\n this.root.insert(entry);\r\n }\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 { getElementVisualBounds, 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\nfunction sanitizeRichText(element: CanvasElement): CanvasElement {\r\n if (element.type !== 'note' && element.type !== 'text') return element;\r\n const text = sanitizeNoteHtml(element.text);\r\n return text === element.text ? element : { ...element, text };\r\n}\r\n\r\nexport interface ElementUpdateEvent {\r\n previous: CanvasElement;\r\n current: CanvasElement;\r\n}\r\n\r\nexport interface ElementChangeMeta {\r\n /**\r\n * Identifies what caused the change. `undefined` or `'local'` = a local change (recorded to undo\r\n * history and observed as local). Any other value (e.g. `'remote'`) marks an externally-applied\r\n * change: it is NOT recorded to undo history, and is tagged so observers can avoid re-broadcasting it.\r\n */\r\n origin?: string;\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 return getElementVisualBounds(element);\r\n }\r\n\r\n add(element: CanvasElement, meta?: ElementChangeMeta): void {\r\n element = sanitizeRichText(element);\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, meta);\r\n }\r\n\r\n update(id: string, partial: Partial<CanvasElement>, meta?: ElementChangeMeta): 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' || updated.type === 'text') && '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 }, meta);\r\n }\r\n\r\n remove(id: string, meta?: ElementChangeMeta): 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, meta);\r\n }\r\n\r\n clear(meta?: ElementChangeMeta): 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, meta);\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[], meta?: ElementChangeMeta): void {\r\n const sanitizedElements = elements.map(sanitizeRichText);\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 sanitizedElements) {\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, meta);\r\n for (const el of sanitizedElements) {\r\n this.bus.emit('add', el, meta);\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], meta: ElementChangeMeta) => 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, ArrowStrokeStyle } 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 getArrowDashPattern(strokeStyle: ArrowStrokeStyle | undefined): number[] {\r\n switch (strokeStyle) {\r\n case 'dashed':\r\n return [8, 4];\r\n case 'dotted':\r\n return [2, 4];\r\n default:\r\n return [];\r\n }\r\n}\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 const dash = getArrowDashPattern(arrow.strokeStyle);\r\n if (dash.length > 0) ctx.setLineDash(dash);\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\nexport function 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 getHexCellsInRectangle(\r\n center: Point,\r\n angle: number,\r\n lengthCells: number,\r\n widthCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const nLen = Math.round(lengthCells);\r\n const wCells = Math.max(1, Math.round(widthCells));\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 (nLen <= 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 = nLen * snapUnit;\r\n const halfWidth = (wCells * snapUnit) / 2 + 1e-6;\r\n const iterM = nLen + Math.ceil(wCells / 2) + 1;\r\n const cells: Point[] = [];\r\n\r\n for (let dq = -iterM; dq <= iterM; dq++) {\r\n const rMin = Math.max(-iterM, -dq - iterM);\r\n const rMax = Math.min(iterM, -dq + iterM);\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 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 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 { Point } from '../../core/types';\r\nimport type { TemplateShape } from '../types';\r\n\r\nexport interface TemplateFeetLabelParams {\r\n position: Point;\r\n radius: number;\r\n angle: number;\r\n templateShape: TemplateShape;\r\n feet: number;\r\n color: string;\r\n}\r\n\r\nexport function renderTemplateFeetLabel(\r\n ctx: CanvasRenderingContext2D,\r\n p: TemplateFeetLabelParams,\r\n): void {\r\n if (p.feet <= 0) return;\r\n\r\n const directional =\r\n p.templateShape === 'cone' || p.templateShape === 'line' || p.templateShape === 'rectangle';\r\n const dir = directional ? p.angle : 0;\r\n const length = p.templateShape === 'square' ? p.radius / 2 : p.radius;\r\n const cos = Math.cos(dir);\r\n const sin = Math.sin(dir);\r\n const start = p.position;\r\n const end = { x: start.x + length * cos, y: start.y + length * sin };\r\n const midX = start.x + (length / 2) * cos;\r\n const midY = start.y + (length / 2) * sin;\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 = p.color;\r\n ctx.lineWidth = 1.5;\r\n ctx.moveTo(start.x, start.y);\r\n ctx.lineTo(end.x, end.y);\r\n ctx.stroke();\r\n ctx.setLineDash([]);\r\n\r\n const label = `${Math.round(p.feet)} ft`;\r\n const fontSize = Math.max(10, Math.min(14, p.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 textY = midY - 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(midX - textW / 2, textY - textH, textW, textH, 3);\r\n ctx.fill();\r\n\r\n ctx.fillStyle = p.color;\r\n ctx.fillText(label, midX, textY - padY);\r\n\r\n ctx.restore();\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 getHexCellsInRectangle,\r\n drawHexPath,\r\n} from '../hex-fill';\r\nimport { renderTemplateFeetLabel } from './template-measure';\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' && template.renderStyle !== 'geometric') {\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 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 case 'rectangle': {\r\n const halfW = (template.width ?? 0) / 2;\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 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 if (template.radiusFeet != null && template.radiusFeet > 0) {\r\n renderTemplateFeetLabel(ctx, {\r\n position: template.position,\r\n radius: template.radius,\r\n angle: template.angle,\r\n templateShape: template.templateShape,\r\n feet: template.radiusFeet,\r\n color: template.strokeColor,\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 case 'rectangle': {\r\n const widthCells = (template.width ?? 0) / snapUnit;\r\n cells = getHexCellsInRectangle(\r\n center,\r\n template.angle,\r\n radiusCells,\r\n widthCells,\r\n cellSize,\r\n orientation,\r\n );\r\n break;\r\n }\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 (template.radiusFeet != null && template.radiusFeet > 0) {\r\n renderTemplateFeetLabel(ctx, {\r\n position: template.position,\r\n radius: template.radius,\r\n angle: template.angle,\r\n templateShape: template.templateShape,\r\n feet: template.radiusFeet,\r\n color: template.strokeColor,\r\n });\r\n }\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 ArrowStrokeStyle,\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 TemplateRenderStyle,\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 strokeStyle?: ArrowStrokeStyle;\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 htmlType?: string;\r\n data?: Record<string, unknown>;\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 if (input.strokeStyle !== undefined) result.strokeStyle = input.strokeStyle;\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 if (input.htmlType) el.htmlType = input.htmlType;\r\n if (input.data) el.data = input.data;\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: sanitizeNoteHtml(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 width?: 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 renderStyle?: TemplateRenderStyle;\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 ...(input.renderStyle !== undefined ? { renderStyle: input.renderStyle } : {}),\r\n ...(input.width !== undefined ? { width: input.width } : {}),\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 onInputCallback: ((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 setOnInput(callback: (elementId: string) => void): void {\r\n this.onInputCallback = 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 // The history transaction spans the whole edit session: opened at activate, committed\r\n // here at stop. Live height fits during editing plus the final text write all touch the\r\n // same element, so the recorder coalesces them into one undo step.\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 this.beginHistory?.();\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 this.onInputCallback?.(elementId);\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","import type { Bounds, Point } from '../core/types';\r\n\r\nexport interface MinimapTransform {\r\n scale: number;\r\n offsetX: number;\r\n offsetY: number;\r\n}\r\n\r\nexport function unionBounds(a: Bounds, b: Bounds): Bounds {\r\n const minX = Math.min(a.x, b.x);\r\n const minY = Math.min(a.y, b.y);\r\n const maxX = Math.max(a.x + a.w, b.x + b.w);\r\n const maxY = Math.max(a.y + a.h, b.y + b.h);\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n\r\n// `mapping` is the union of the content bounds and the visible viewport, so the\r\n// minimap always frames both what exists and where the camera is looking.\r\nexport function computeMinimapTransform(\r\n mapping: Bounds,\r\n miniW: number,\r\n miniH: number,\r\n padding: number,\r\n): MinimapTransform {\r\n const availW = Math.max(1, miniW - 2 * padding);\r\n const availH = Math.max(1, miniH - 2 * padding);\r\n const w = Math.max(mapping.w, 1);\r\n const h = Math.max(mapping.h, 1);\r\n const scale = Math.min(availW / w, availH / h);\r\n const offsetX = (miniW - mapping.w * scale) / 2 - mapping.x * scale;\r\n const offsetY = (miniH - mapping.h * scale) / 2 - mapping.y * scale;\r\n return { scale, offsetX, offsetY };\r\n}\r\n\r\nexport function worldToMini(t: MinimapTransform, p: Point): Point {\r\n return { x: p.x * t.scale + t.offsetX, y: p.y * t.scale + t.offsetY };\r\n}\r\n\r\nexport function miniToWorld(t: MinimapTransform, p: Point): Point {\r\n return { x: (p.x - t.offsetX) / t.scale, y: (p.y - t.offsetY) / t.scale };\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport {\r\n computeMinimapTransform,\r\n miniToWorld,\r\n unionBounds,\r\n worldToMini,\r\n type MinimapTransform,\r\n} from './minimap-transform';\r\n\r\nexport interface MinimapDeps {\r\n container: HTMLElement;\r\n getElements: () => CanvasElement[];\r\n getContentBounds: () => Bounds | null;\r\n getViewportRect: () => Bounds;\r\n navigateTo: (worldCenter: Point) => void;\r\n requestFrame: (cb: () => void) => number;\r\n cancelFrame: (id: number) => void;\r\n}\r\n\r\nconst WIDTH = 200;\r\nconst HEIGHT = 140;\r\nconst MARGIN = 16;\r\nconst PADDING = 8;\r\nconst NEUTRAL = 'rgba(100,116,139,0.6)';\r\nconst VIEWPORT_STROKE = '#3b82f6';\r\n\r\nfunction elementColor(el: CanvasElement): string {\r\n return 'color' in el && typeof el.color === 'string' ? el.color : NEUTRAL;\r\n}\r\n\r\nexport class Minimap {\r\n private readonly canvas: HTMLCanvasElement;\r\n private rafId: number | null = null;\r\n private dragging = false;\r\n\r\n constructor(private readonly deps: MinimapDeps) {\r\n const canvas = document.createElement('canvas');\r\n canvas.width = WIDTH;\r\n canvas.height = HEIGHT;\r\n Object.assign(canvas.style, {\r\n position: 'absolute',\r\n right: `${MARGIN}px`,\r\n bottom: `${MARGIN}px`,\r\n width: `${WIDTH}px`,\r\n height: `${HEIGHT}px`,\r\n background: 'rgba(255,255,255,0.85)',\r\n border: '1px solid rgba(0,0,0,0.15)',\r\n borderRadius: '4px',\r\n touchAction: 'none',\r\n cursor: 'pointer',\r\n zIndex: '10',\r\n });\r\n canvas.addEventListener('pointerdown', this.onPointerDown);\r\n canvas.addEventListener('pointermove', this.onPointerMove);\r\n canvas.addEventListener('pointerup', this.onPointerUp);\r\n this.deps.container.appendChild(canvas);\r\n this.canvas = canvas;\r\n }\r\n\r\n scheduleDraw(): void {\r\n if (this.rafId !== null) return;\r\n this.rafId = this.deps.requestFrame(this.draw);\r\n }\r\n\r\n destroy(): void {\r\n if (this.rafId !== null) {\r\n this.deps.cancelFrame(this.rafId);\r\n this.rafId = null;\r\n }\r\n this.canvas.removeEventListener('pointerdown', this.onPointerDown);\r\n this.canvas.removeEventListener('pointermove', this.onPointerMove);\r\n this.canvas.removeEventListener('pointerup', this.onPointerUp);\r\n this.canvas.remove();\r\n }\r\n\r\n private currentTransform(): MinimapTransform {\r\n const viewport = this.deps.getViewportRect();\r\n const content = this.deps.getContentBounds();\r\n const mapping = content ? unionBounds(content, viewport) : viewport;\r\n return computeMinimapTransform(mapping, WIDTH, HEIGHT, PADDING);\r\n }\r\n\r\n private draw = (): void => {\r\n this.rafId = null;\r\n const ctx = this.canvas.getContext('2d');\r\n if (!ctx) return;\r\n const t = this.currentTransform();\r\n const viewport = this.deps.getViewportRect();\r\n ctx.clearRect(0, 0, WIDTH, HEIGHT);\r\n for (const el of this.deps.getElements()) {\r\n const b = getElementBounds(el);\r\n if (!b) continue;\r\n const tl = worldToMini(t, { x: b.x, y: b.y });\r\n ctx.fillStyle = elementColor(el);\r\n ctx.fillRect(tl.x, tl.y, Math.max(1, b.w * t.scale), Math.max(1, b.h * t.scale));\r\n }\r\n const vtl = worldToMini(t, { x: viewport.x, y: viewport.y });\r\n ctx.strokeStyle = VIEWPORT_STROKE;\r\n ctx.lineWidth = 1.5;\r\n ctx.strokeRect(vtl.x, vtl.y, viewport.w * t.scale, viewport.h * t.scale);\r\n };\r\n\r\n private navigateFromEvent(e: PointerEvent): void {\r\n const rect = this.canvas.getBoundingClientRect();\r\n const point = { x: e.clientX - rect.left, y: e.clientY - rect.top };\r\n const world = miniToWorld(this.currentTransform(), point);\r\n this.deps.navigateTo(world);\r\n }\r\n\r\n private onPointerDown = (e: PointerEvent): void => {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n this.dragging = true;\r\n this.canvas.setPointerCapture?.(e.pointerId);\r\n this.navigateFromEvent(e);\r\n };\r\n\r\n private onPointerMove = (e: PointerEvent): void => {\r\n if (!this.dragging) return;\r\n e.stopPropagation();\r\n this.navigateFromEvent(e);\r\n };\r\n\r\n private onPointerUp = (e: PointerEvent): void => {\r\n this.dragging = false;\r\n try {\r\n this.canvas.releasePointerCapture(e.pointerId);\r\n } catch {\r\n // already released\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\r\nexport function createPaintStack(): HTMLDivElement {\r\n const el = createDomLayer();\r\n el.dataset['fieldnotesPaintStack'] = '';\r\n el.style.transformOrigin = '';\r\n return el;\r\n}\r\n","export class HybridRenderSurface {\r\n private readonly canvases = new Map<number, HTMLCanvasElement>();\r\n\r\n constructor(private readonly root: HTMLDivElement) {}\r\n\r\n beginFrame(activeOrders: ReadonlySet<number>, width: number, height: number): void {\r\n for (const [order, canvas] of this.canvases) {\r\n if (!activeOrders.has(order)) {\r\n canvas.remove();\r\n this.canvases.delete(order);\r\n }\r\n }\r\n\r\n for (const order of activeOrders) {\r\n const canvas = this.getCanvas(order);\r\n if (canvas.width !== width) canvas.width = width;\r\n if (canvas.height !== height) canvas.height = height;\r\n canvas.style.zIndex = String(order);\r\n }\r\n }\r\n\r\n getContext(order: number): CanvasRenderingContext2D | null {\r\n return this.getCanvas(order).getContext('2d');\r\n }\r\n\r\n clear(): void {\r\n for (const canvas of this.canvases.values()) canvas.remove();\r\n this.canvases.clear();\r\n }\r\n\r\n private getCanvas(order: number): HTMLCanvasElement {\r\n let canvas = this.canvases.get(order);\r\n if (canvas) return canvas;\r\n\r\n canvas = document.createElement('canvas');\r\n canvas.dataset['paintOrder'] = String(order);\r\n Object.assign(canvas.style, {\r\n position: 'absolute',\r\n inset: '0',\r\n width: '100%',\r\n height: '100%',\r\n pointerEvents: 'none',\r\n });\r\n this.root.appendChild(canvas);\r\n this.canvases.set(order, canvas);\r\n return canvas;\r\n }\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 { EventMeta } from '../core/event-bus';\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\nfunction isExternalChange(meta: EventMeta): boolean {\r\n return meta.origin !== undefined && meta.origin !== 'local';\r\n}\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, meta) => this.onAdd(el, meta)),\r\n store.on('remove', (el, meta) => this.onRemove(el, meta)),\r\n store.on('update', ({ previous, current }, meta) => this.onUpdate(previous, current, meta)),\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, meta: EventMeta): void {\r\n if (isExternalChange(meta)) return;\r\n if (!this.recording) return;\r\n this.record(new AddElementCommand(element));\r\n }\r\n\r\n private onRemove(element: CanvasElement, meta: EventMeta): void {\r\n if (isExternalChange(meta)) return;\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, meta: EventMeta): void {\r\n if (isExternalChange(meta)) return;\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 { parseStyledRuns };\r\nexport type { StyledRun };\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\ninterface LineFragment {\r\n text: string;\r\n font: string;\r\n x: number;\r\n width: number;\r\n fontSize: number;\r\n underline: boolean;\r\n strikethrough: boolean;\r\n}\r\n\r\ninterface LaidOutLine {\r\n y: number;\r\n width: number;\r\n fragments: LineFragment[];\r\n}\r\n\r\nexport function renderStyledRuns(\r\n ctx: CanvasRenderingContext2D,\r\n runs: StyledRun[],\r\n startX: number,\r\n startY: number,\r\n maxWidth: number,\r\n opts: { align?: 'left' | 'center' | 'right'; lineHeight?: number } = {},\r\n): void {\r\n const align = opts.align ?? 'left';\r\n const lhMul = opts.lineHeight ?? 1.3;\r\n ctx.textBaseline = 'top';\r\n\r\n // PASS 1 — lay runs out into lines (no drawing). Wrap behaviour mirrors the\r\n // original single-pass renderer exactly so wrap points are alignment-agnostic.\r\n const lines: LaidOutLine[] = [];\r\n let cursorX = startX;\r\n let lineY = startY;\r\n let lineHeight = 0;\r\n let fragments: LineFragment[] = [];\r\n\r\n const finalizeLine = (): void => {\r\n const last = fragments[fragments.length - 1];\r\n const width = last ? last.x + last.width : 0;\r\n lines.push({ y: lineY, width, fragments });\r\n };\r\n\r\n const breakLine = (runLineHeight: number): void => {\r\n finalizeLine();\r\n lineY += lineHeight;\r\n lineHeight = runLineHeight;\r\n fragments = [];\r\n cursorX = startX;\r\n };\r\n\r\n for (const run of runs) {\r\n const font = buildFontString(run);\r\n ctx.font = font;\r\n const runLineHeight = run.fontSize * lhMul;\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 breakLine(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 breakLine(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 breakLine(runLineHeight);\r\n }\r\n\r\n fragments.push({\r\n text: word,\r\n font,\r\n x: cursorX - startX,\r\n width: metrics.width,\r\n fontSize: run.fontSize,\r\n underline: run.underline,\r\n strikethrough: run.strikethrough,\r\n });\r\n cursorX += metrics.width;\r\n }\r\n }\r\n finalizeLine();\r\n\r\n // PASS 2 — draw each line at its alignment offset. For align 'left' the\r\n // offset is 0, so the absolute x equals the original streaming cursorX.\r\n for (const line of lines) {\r\n const offset =\r\n align === 'center'\r\n ? (maxWidth - line.width) / 2\r\n : align === 'right'\r\n ? maxWidth - line.width\r\n : 0;\r\n for (const fragment of line.fragments) {\r\n ctx.font = fragment.font;\r\n const fx = startX + offset + fragment.x;\r\n ctx.fillText(fragment.text, fx, line.y);\r\n\r\n if (fragment.underline) {\r\n ctx.fillRect(fx, line.y + fragment.fontSize + 1, fragment.width, 1);\r\n }\r\n\r\n if (fragment.strikethrough) {\r\n ctx.fillRect(fx, line.y + fragment.fontSize * 0.55, fragment.width, 1);\r\n }\r\n }\r\n }\r\n}\r\n","import type { TextElement } from '../elements/types';\r\nimport { parseStyledRuns, renderStyledRuns } from './note-canvas-renderer';\r\n\r\nexport function renderTextOnCanvas(ctx: CanvasRenderingContext2D, text: TextElement): void {\r\n const pad = 2; // matches the DOM text padding\r\n ctx.save();\r\n ctx.fillStyle = text.color;\r\n const runs = parseStyledRuns(text.text ?? '', text.fontSize);\r\n renderStyledRuns(ctx, runs, text.position.x + pad, text.position.y + pad, text.size.w - pad * 2, {\r\n align: text.textAlign,\r\n lineHeight: 1.4,\r\n });\r\n ctx.restore();\r\n}\r\n","import type { HtmlElement } from '../elements/types';\r\n\r\nexport type HtmlExportRenderer = (\r\n element: HtmlElement,\r\n) => CanvasImageSource | null | Promise<CanvasImageSource | null>;\r\n\r\nexport type HtmlExportErrorReason = 'unsupported' | 'timeout' | 'render' | 'encode';\r\n\r\nexport interface HtmlExportError {\r\n elementId: string;\r\n htmlType?: string;\r\n reason: HtmlExportErrorReason;\r\n cause?: unknown;\r\n}\r\n\r\nexport interface HtmlExportOptions {\r\n /** Converts an application-owned HTML embed into a ready canvas image source. */\r\n renderHtml?: HtmlExportRenderer;\r\n /** Maximum wait for each HTML renderer. Defaults to 10 seconds. */\r\n htmlTimeoutMs?: number;\r\n /** Called when an HTML embed cannot be rendered or encoded. The export continues. */\r\n onHtmlError?: (error: HtmlExportError) => void;\r\n}\r\n\r\nconst DEFAULT_HTML_TIMEOUT_MS = 10_000;\r\nconst TIMEOUT = Symbol('html-export-timeout');\r\n\r\nexport function validateHtmlExportOptions(options: HtmlExportOptions): number {\r\n const timeoutMs = options.htmlTimeoutMs ?? DEFAULT_HTML_TIMEOUT_MS;\r\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\r\n throw new RangeError('htmlTimeoutMs must be a finite number greater than 0');\r\n }\r\n return timeoutMs;\r\n}\r\n\r\nexport async function renderHtmlElements(\r\n elements: HtmlElement[],\r\n options: HtmlExportOptions,\r\n): Promise<Map<string, CanvasImageSource>> {\r\n const timeoutMs = validateHtmlExportOptions(options);\r\n const sources = new Map<string, CanvasImageSource>();\r\n\r\n await Promise.all(\r\n elements.map(async (element) => {\r\n if (!options.renderHtml) {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'unsupported',\r\n });\r\n return;\r\n }\r\n\r\n let timer: ReturnType<typeof setTimeout> | undefined;\r\n try {\r\n const timeout = new Promise<typeof TIMEOUT>((resolve) => {\r\n timer = setTimeout(() => resolve(TIMEOUT), timeoutMs);\r\n });\r\n const result = await Promise.race([Promise.resolve(options.renderHtml(element)), timeout]);\r\n if (result === TIMEOUT) {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'timeout',\r\n });\r\n return;\r\n }\r\n if (!result) {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'render',\r\n });\r\n return;\r\n }\r\n sources.set(element.id, result);\r\n } catch (cause) {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'render',\r\n cause,\r\n });\r\n } finally {\r\n if (timer !== undefined) clearTimeout(timer);\r\n }\r\n }),\r\n );\r\n\r\n return sources;\r\n}\r\n","import type { CanvasElement, GridElement, HtmlElement } 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\nimport { renderTextOnCanvas } from './text-canvas-renderer';\r\nimport { renderHtmlElements, validateHtmlExportOptions } from './html-export';\r\nimport type { HtmlExportOptions } from './html-export';\r\n\r\nexport interface ExportImageOptions extends ExportResourceOptions, HtmlExportOptions {\r\n scale?: number;\r\n padding?: number;\r\n background?: string;\r\n filter?: (element: CanvasElement) => boolean;\r\n}\r\n\r\nexport type ExportAssetErrorReason = 'load' | 'timeout' | 'encode';\r\n\r\nexport interface ExportAssetError {\r\n elementId: string;\r\n src: string;\r\n reason: ExportAssetErrorReason;\r\n cause?: unknown;\r\n}\r\n\r\nexport interface ExportResourceOptions {\r\n /** Maximum wait for each image asset. Defaults to 10 seconds. */\r\n imageTimeoutMs?: number;\r\n /** Maximum width or height of any allocated export canvas. Defaults to 16,384. */\r\n maxDimension?: number;\r\n /** Maximum pixel count of any allocated export canvas. Defaults to 67,108,864. */\r\n maxPixels?: number;\r\n /** Called when an image cannot be loaded or embedded. The export continues. */\r\n onAssetError?: (error: ExportAssetError) => void;\r\n}\r\n\r\nconst DEFAULT_IMAGE_TIMEOUT_MS = 10_000;\r\nconst DEFAULT_MAX_DIMENSION = 16_384;\r\nconst DEFAULT_MAX_PIXELS = 67_108_864;\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 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 positiveOption(value: number | undefined, fallback: number, name: string): number {\r\n const resolved = value ?? fallback;\r\n if (!Number.isFinite(resolved) || resolved <= 0) {\r\n throw new RangeError(`${name} must be a finite number greater than 0`);\r\n }\r\n return resolved;\r\n}\r\n\r\nfunction nonNegativeOption(value: number | undefined, fallback: number, name: string): number {\r\n const resolved = value ?? fallback;\r\n if (!Number.isFinite(resolved) || resolved < 0) {\r\n throw new RangeError(`${name} must be a finite number greater than or equal to 0`);\r\n }\r\n return resolved;\r\n}\r\n\r\nfunction assertExportSize(\r\n width: number,\r\n height: number,\r\n options: Pick<ExportResourceOptions, 'maxDimension' | 'maxPixels'>,\r\n): void {\r\n const maxDimension = positiveOption(options.maxDimension, DEFAULT_MAX_DIMENSION, 'maxDimension');\r\n const maxPixels = positiveOption(options.maxPixels, DEFAULT_MAX_PIXELS, 'maxPixels');\r\n if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {\r\n throw new RangeError('Export dimensions must be finite numbers greater than 0');\r\n }\r\n if (width > maxDimension || height > maxDimension) {\r\n throw new RangeError(\r\n `Export dimensions ${width}x${height} exceed the maximum dimension of ${maxDimension}`,\r\n );\r\n }\r\n if (width * height > maxPixels) {\r\n throw new RangeError(\r\n `Export size ${width}x${height} exceeds the maximum of ${maxPixels} pixels`,\r\n );\r\n }\r\n}\r\n\r\nfunction validateExportResourceOptions(options: ExportResourceOptions): void {\r\n positiveOption(options.imageTimeoutMs, DEFAULT_IMAGE_TIMEOUT_MS, 'imageTimeoutMs');\r\n positiveOption(options.maxDimension, DEFAULT_MAX_DIMENSION, 'maxDimension');\r\n positiveOption(options.maxPixels, DEFAULT_MAX_PIXELS, 'maxPixels');\r\n}\r\n\r\nfunction loadImages(\r\n elements: CanvasElement[],\r\n options: Pick<ExportResourceOptions, 'imageTimeoutMs' | 'onAssetError'> = {},\r\n): 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 const timeoutMs = positiveOption(\r\n options.imageTimeoutMs,\r\n DEFAULT_IMAGE_TIMEOUT_MS,\r\n 'imageTimeoutMs',\r\n );\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 let settled = false;\r\n const timer = setTimeout(() => {\r\n if (settled) return;\r\n settled = true;\r\n img.onload = null;\r\n img.onerror = null;\r\n options.onAssetError?.({ elementId: el.id, src: el.src, reason: 'timeout' });\r\n done();\r\n }, timeoutMs);\r\n const settle = (): boolean => {\r\n if (settled) return false;\r\n settled = true;\r\n clearTimeout(timer);\r\n img.onload = null;\r\n img.onerror = null;\r\n return true;\r\n };\r\n img.onload = () => {\r\n if (!settle()) return;\r\n cache.set(el.id, img);\r\n done();\r\n };\r\n img.onerror = (cause) => {\r\n if (!settle()) return;\r\n options.onAssetError?.({ elementId: el.id, src: el.src, reason: 'load', cause });\r\n done();\r\n };\r\n img.src = el.src;\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 = positiveOption(options.scale, 2, 'scale');\r\n const padding = nonNegativeOption(options.padding, 0, 'padding');\r\n validateExportResourceOptions(options);\r\n validateHtmlExportOptions(options);\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 width = Math.ceil(bounds.w * scale);\r\n const height = Math.ceil(bounds.h * scale);\r\n assertExportSize(width, height, options);\r\n const imageCache = await loadImages(visibleElements, options);\r\n const htmlElements = visibleElements.filter((el): el is HtmlElement => el.type === 'html');\r\n const htmlSources = await renderHtmlElements(htmlElements, options);\r\n\r\n const canvas = document.createElement('canvas');\r\n canvas.width = width;\r\n canvas.height = height;\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 const renderElement = (target: CanvasRenderingContext2D, el: CanvasElement): void => {\r\n if (el.type === 'note') {\r\n const b = getElementBounds(el);\r\n withRotation(target, el, b ? center(b) : el.position, () => renderNoteOnCanvas(target, el));\r\n return;\r\n }\r\n\r\n if (el.type === 'text') {\r\n const b = getElementBounds(el);\r\n withRotation(target, el, b ? center(b) : el.position, () => renderTextOnCanvas(target, el));\r\n return;\r\n }\r\n\r\n if (el.type === 'html') {\r\n const source = htmlSources.get(el.id);\r\n if (!source) return;\r\n const b = getElementBounds(el);\r\n try {\r\n withRotation(target, el, b ? center(b) : el.position, () =>\r\n target.drawImage(source, el.position.x, el.position.y, el.size.w, el.size.h),\r\n );\r\n } catch (cause) {\r\n options.onHtmlError?.({\r\n elementId: el.id,\r\n htmlType: el.htmlType,\r\n reason: 'render',\r\n cause,\r\n });\r\n }\r\n return;\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(target, el, b ? center(b) : el.position, () =>\r\n target.drawImage(img, el.position.x, el.position.y, el.size.w, el.size.h),\r\n );\r\n }\r\n return;\r\n }\r\n\r\n renderer.renderCanvasElement(target, el);\r\n };\r\n\r\n const layerGroups = new Map<string, CanvasElement[]>();\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 const group = layerGroups.get(el.layerId) ?? [];\r\n group.push(el);\r\n layerGroups.set(el.layerId, group);\r\n }\r\n\r\n for (const [layerId, elements] of layerGroups) {\r\n const opacity = layerManager?.getLayer?.(layerId)?.opacity ?? 1;\r\n if (opacity === 1) {\r\n for (const el of elements) renderElement(ctx, el);\r\n continue;\r\n }\r\n\r\n const layerCanvas = document.createElement('canvas');\r\n layerCanvas.width = canvas.width;\r\n layerCanvas.height = canvas.height;\r\n const layerCtx = layerCanvas.getContext('2d');\r\n if (!layerCtx) continue;\r\n layerCtx.scale(scale, scale);\r\n layerCtx.translate(-bounds.x, -bounds.y);\r\n for (const el of elements) renderElement(layerCtx, el);\r\n\r\n ctx.save();\r\n ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n ctx.globalAlpha = opacity;\r\n ctx.drawImage(layerCanvas, 0, 0);\r\n ctx.restore();\r\n }\r\n\r\n for (const grid of grids) {\r\n ctx.save();\r\n ctx.globalAlpha = layerManager?.getLayer?.(grid.layerId)?.opacity ?? 1;\r\n renderGridForBounds(ctx, grid, bounds);\r\n ctx.restore();\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 {\r\n assertExportSize,\r\n computeBounds,\r\n getElementRect,\r\n loadImages,\r\n nonNegativeOption,\r\n positiveOption,\r\n validateExportResourceOptions,\r\n};\r\n","import type {\r\n CanvasElement,\r\n StrokeElement,\r\n ShapeElement,\r\n ArrowElement,\r\n ImageElement,\r\n TextElement,\r\n NoteElement,\r\n GridElement,\r\n TemplateElement,\r\n HtmlElement,\r\n} from '../elements/types';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport { getStrokeRenderData } from '../elements/stroke-cache';\r\nimport { lineEndpoints } from '../elements/shape-geometry';\r\nimport { getArrowControlPoint, getArrowMidpoint } from '../elements/arrow-geometry';\r\nimport { getArrowRenderGeometry } from '../elements/arrow-render-cache';\r\nimport { getVisualEndpoints, getArrowDashPattern } from '../elements/renderers/arrow-renderer';\r\nimport { getSquareGridLines, getHexVertices, getHexCenters } from '../elements/grid-renderer';\r\nimport {\r\n getHexCellsInRadius,\r\n getHexCellsInCone,\r\n getHexCellsInLine,\r\n getHexCellsInSquare,\r\n getHexCellsInRectangle,\r\n} from '../elements/hex-fill';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { renderNoteOnCanvas } from './note-canvas-renderer';\r\nimport { renderTextOnCanvas } from './text-canvas-renderer';\r\nimport {\r\n assertExportSize,\r\n loadImages,\r\n computeBounds,\r\n nonNegativeOption,\r\n positiveOption,\r\n validateExportResourceOptions,\r\n} from './export-image';\r\nimport type { ExportResourceOptions } from './export-image';\r\nimport { renderHtmlElements, validateHtmlExportOptions } from './html-export';\r\nimport type { HtmlExportOptions } from './html-export';\r\n\r\nexport interface ExportSvgOptions extends ExportResourceOptions, HtmlExportOptions {\r\n padding?: number;\r\n background?: string;\r\n filter?: (el: CanvasElement) => boolean;\r\n rasterScale?: number;\r\n}\r\n\r\ninterface Bounds {\r\n x: number;\r\n y: number;\r\n w: number;\r\n h: number;\r\n}\r\n\r\nconst ARROWHEAD_LENGTH = 12;\r\nconst ARROWHEAD_ANGLE = Math.PI / 6;\r\nconst ARROW_LABEL_FONT_SIZE = 14;\r\n\r\nfunction esc(s: string): string {\r\n return s\r\n .replace(/&/g, '&')\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/\"/g, '"')\r\n .replace(/'/g, ''');\r\n}\r\n\r\nconst n = (v: number): string => (Number.isFinite(v) ? `${Math.round(v * 1000) / 1000}` : '0');\r\n\r\nfunction elementCenter(el: CanvasElement): { x: number; y: number } | null {\r\n const b = getElementBounds(el);\r\n if (!b) return null;\r\n return { x: b.x + b.w / 2, y: b.y + b.h / 2 };\r\n}\r\n\r\n/** Wrap a fragment in a rotation group matching withRotation (radians → degrees). */\r\nfunction withRotationSvg(el: CanvasElement, fragment: string): string {\r\n const angle = el.rotation ?? 0;\r\n if (!angle || !fragment) return fragment;\r\n const c = elementCenter(el);\r\n if (!c) return fragment;\r\n const deg = (angle * 180) / Math.PI;\r\n return `<g transform=\"rotate(${n(deg)} ${n(c.x)} ${n(c.y)})\">${fragment}</g>`;\r\n}\r\n\r\n// Strokes use variable per-point width on the canvas; SVG <path> takes a single\r\n// stroke-width, so we mirror the canvas width-bucketing: segments are grouped by\r\n// quantized width and each bucket becomes one <path> of bezier sub-paths. This\r\n// reproduces the canvas geometry exactly. We rebuild buckets from segments+widths\r\n// (always populated) rather than the Path2D buckets, which are absent under jsdom.\r\nconst WIDTH_QUANTUM = 0.25;\r\n\r\nfunction emitStroke(stroke: StrokeElement): string {\r\n if (stroke.points.length < 2) return '';\r\n const data = getStrokeRenderData(stroke);\r\n const { x: ox, y: oy } = stroke.position;\r\n\r\n const byWidth = new Map<number, string[]>();\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 const q = Math.max(WIDTH_QUANTUM, Math.round(w / WIDTH_QUANTUM) * WIDTH_QUANTUM);\r\n let parts = byWidth.get(q);\r\n if (!parts) {\r\n parts = [];\r\n byWidth.set(q, parts);\r\n }\r\n parts.push(\r\n `M${n(ox + seg.start.x)} ${n(oy + seg.start.y)} C${n(ox + seg.cp1.x)} ${n(oy + seg.cp1.y)} ${n(ox + seg.cp2.x)} ${n(oy + seg.cp2.y)} ${n(ox + seg.end.x)} ${n(oy + seg.end.y)}`,\r\n );\r\n }\r\n\r\n const blend = stroke.blendMode === 'multiply' ? ' style=\"mix-blend-mode:multiply\"' : '';\r\n let out = '';\r\n for (const [width, parts] of byWidth) {\r\n out += `<path d=\"${parts.join(' ')}\" fill=\"none\" stroke=\"${esc(stroke.color)}\" stroke-width=\"${n(width)}\" stroke-linecap=\"round\" stroke-linejoin=\"round\" opacity=\"${n(stroke.opacity)}\"${blend} />`;\r\n }\r\n return out;\r\n}\r\n\r\nfunction emitShape(shape: ShapeElement): string {\r\n const { x, y } = shape.position;\r\n const { w, h } = shape.size;\r\n const fill = shape.fillColor !== 'none' && shape.shape !== 'line' ? esc(shape.fillColor) : 'none';\r\n const stroke = shape.strokeWidth > 0 ? esc(shape.strokeColor) : 'none';\r\n const sw = shape.strokeWidth > 0 ? ` stroke-width=\"${n(shape.strokeWidth)}\"` : '';\r\n\r\n switch (shape.shape) {\r\n case 'rectangle':\r\n return `<rect x=\"${n(x)}\" y=\"${n(y)}\" width=\"${n(w)}\" height=\"${n(h)}\" fill=\"${fill}\" stroke=\"${stroke}\"${sw} />`;\r\n case 'ellipse':\r\n return `<ellipse cx=\"${n(x + w / 2)}\" cy=\"${n(y + h / 2)}\" rx=\"${n(w / 2)}\" ry=\"${n(h / 2)}\" fill=\"${fill}\" stroke=\"${stroke}\"${sw} />`;\r\n case 'line': {\r\n const [a, b] = lineEndpoints(shape);\r\n return `<line x1=\"${n(a.x)}\" y1=\"${n(a.y)}\" x2=\"${n(b.x)}\" y2=\"${n(b.y)}\" stroke=\"${stroke}\"${sw} stroke-linecap=\"round\" />`;\r\n }\r\n }\r\n}\r\n\r\nfunction emitArrow(arrow: ArrowElement, store: ElementStore): string {\r\n const geometry = getArrowRenderGeometry(arrow);\r\n // Bound arrows store from/to at the bound element's CENTER; the canvas renderer\r\n // snaps them to the element EDGE at draw time. Mirror that for PNG/canvas parity.\r\n const { visualFrom: from, visualTo: to } = getVisualEndpoints(arrow, geometry, store);\r\n\r\n let d: string;\r\n if (arrow.bend !== 0) {\r\n const cp = geometry.controlPoint ?? getArrowControlPoint(from, to, arrow.bend);\r\n d = `M${n(from.x)} ${n(from.y)} Q${n(cp.x)} ${n(cp.y)} ${n(to.x)} ${n(to.y)}`;\r\n } else {\r\n d = `M${n(from.x)} ${n(from.y)} L${n(to.x)} ${n(to.y)}`;\r\n }\r\n\r\n const pattern = getArrowDashPattern(arrow.strokeStyle);\r\n const dash = pattern.length > 0 ? ` stroke-dasharray=\"${pattern.join(' ')}\"` : '';\r\n let out = `<path d=\"${d}\" fill=\"none\" stroke=\"${esc(arrow.color)}\" stroke-width=\"${n(arrow.width)}\" stroke-linecap=\"round\"${dash} />`;\r\n\r\n // Arrowhead — mirror arrow-renderer's polygon math (tip at the visual endpoint).\r\n const angle = geometry.tangentEnd;\r\n const p1x = to.x - ARROWHEAD_LENGTH * Math.cos(angle - ARROWHEAD_ANGLE);\r\n const p1y = to.y - ARROWHEAD_LENGTH * Math.sin(angle - ARROWHEAD_ANGLE);\r\n const p2x = to.x - ARROWHEAD_LENGTH * Math.cos(angle + ARROWHEAD_ANGLE);\r\n const p2y = to.y - ARROWHEAD_LENGTH * Math.sin(angle + ARROWHEAD_ANGLE);\r\n out += `<polygon points=\"${n(to.x)},${n(to.y)} ${n(p1x)},${n(p1y)} ${n(p2x)},${n(p2y)}\" fill=\"${esc(arrow.color)}\" />`;\r\n\r\n if (arrow.label && arrow.label.length > 0) {\r\n // Canvas renderer places the label at the raw-endpoint midpoint, not the visual one.\r\n const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);\r\n const approxW = arrow.label.length * ARROW_LABEL_FONT_SIZE * 0.6;\r\n const padX = 6;\r\n const padY = 4;\r\n const lw = approxW + padX * 2;\r\n const lh = ARROW_LABEL_FONT_SIZE + padY * 2;\r\n out += `<rect x=\"${n(mid.x - lw / 2)}\" y=\"${n(mid.y - lh / 2)}\" width=\"${n(lw)}\" height=\"${n(lh)}\" rx=\"4\" fill=\"rgba(255,255,255,0.9)\" />`;\r\n out += `<text x=\"${n(mid.x)}\" y=\"${n(mid.y)}\" font-family=\"system-ui, sans-serif\" font-size=\"${ARROW_LABEL_FONT_SIZE}\" fill=\"#1a1a1a\" text-anchor=\"middle\" dominant-baseline=\"central\">${esc(arrow.label)}</text>`;\r\n }\r\n\r\n return out;\r\n}\r\n\r\nfunction emitImage(image: ImageElement | HtmlElement, dataUri: string | undefined): string {\r\n const href = dataUri ?? ('src' in image ? image.src : '');\r\n if (!href) return '';\r\n const { x, y } = image.position;\r\n const { w, h } = image.size;\r\n return `<image href=\"${esc(href)}\" x=\"${n(x)}\" y=\"${n(y)}\" width=\"${n(w)}\" height=\"${n(h)}\" />`;\r\n}\r\n\r\nfunction emitText(\r\n text: TextElement,\r\n rasterScale: number,\r\n resourceOptions: ExportResourceOptions,\r\n): string {\r\n if (!text.text) return '';\r\n const { x, y } = text.position;\r\n const { w, h } = text.size;\r\n if (typeof document === 'undefined') return '';\r\n\r\n const width = Math.max(1, Math.ceil(w * rasterScale));\r\n const height = Math.max(1, Math.ceil(h * rasterScale));\r\n assertExportSize(width, height, resourceOptions);\r\n const canvas = document.createElement('canvas');\r\n canvas.width = width;\r\n canvas.height = height;\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return '';\r\n\r\n ctx.scale(rasterScale, rasterScale);\r\n ctx.translate(-x, -y);\r\n renderTextOnCanvas(ctx, text);\r\n\r\n let dataUri: string;\r\n try {\r\n dataUri = canvas.toDataURL();\r\n } catch {\r\n return '';\r\n }\r\n if (!dataUri || !dataUri.startsWith('data:')) return '';\r\n\r\n return `<image href=\"${esc(dataUri)}\" x=\"${n(x)}\" y=\"${n(y)}\" width=\"${n(w)}\" height=\"${n(h)}\" />`;\r\n}\r\n\r\nfunction emitNote(\r\n note: NoteElement,\r\n rasterScale: number,\r\n resourceOptions: ExportResourceOptions,\r\n): string {\r\n const { x, y } = note.position;\r\n const { w, h } = note.size;\r\n if (typeof document === 'undefined') return emitNotePlaceholder(note);\r\n\r\n const width = Math.max(1, Math.ceil(w * rasterScale));\r\n const height = Math.max(1, Math.ceil(h * rasterScale));\r\n assertExportSize(width, height, resourceOptions);\r\n const canvas = document.createElement('canvas');\r\n canvas.width = width;\r\n canvas.height = height;\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return emitNotePlaceholder(note);\r\n\r\n ctx.scale(rasterScale, rasterScale);\r\n ctx.translate(-x, -y);\r\n renderNoteOnCanvas(ctx, note);\r\n\r\n let dataUri: string;\r\n try {\r\n dataUri = canvas.toDataURL();\r\n } catch {\r\n return emitNotePlaceholder(note);\r\n }\r\n if (!dataUri || !dataUri.startsWith('data:')) return emitNotePlaceholder(note);\r\n\r\n return `<image href=\"${esc(dataUri)}\" x=\"${n(x)}\" y=\"${n(y)}\" width=\"${n(w)}\" height=\"${n(h)}\" />`;\r\n}\r\n\r\nfunction emitNotePlaceholder(note: NoteElement): string {\r\n const { x, y } = note.position;\r\n const { w, h } = note.size;\r\n return `<rect x=\"${n(x)}\" y=\"${n(y)}\" width=\"${n(w)}\" height=\"${n(h)}\" rx=\"4\" fill=\"${esc(note.backgroundColor)}\" />`;\r\n}\r\n\r\nfunction emitGrid(grid: GridElement, bounds: Bounds): string {\r\n if (grid.cellSize <= 0) return '';\r\n const vb = {\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 const stroke = esc(grid.strokeColor);\r\n const sw = n(grid.strokeWidth);\r\n const op = n(grid.opacity);\r\n\r\n if (grid.gridType === 'hex') {\r\n const centers = getHexCenters(vb, grid.cellSize, grid.hexOrientation);\r\n let d = '';\r\n for (const c of centers) {\r\n const verts = getHexVertices(c.x, c.y, grid.cellSize, grid.hexOrientation);\r\n const first = verts[0];\r\n if (!first) continue;\r\n d += `M${n(first.x)} ${n(first.y)}`;\r\n for (let i = 1; i < verts.length; i++) {\r\n const v = verts[i];\r\n if (v) d += `L${n(v.x)} ${n(v.y)}`;\r\n }\r\n d += 'Z';\r\n }\r\n return `<path d=\"${d}\" fill=\"none\" stroke=\"${stroke}\" stroke-width=\"${sw}\" opacity=\"${op}\" />`;\r\n }\r\n\r\n const { verticals, horizontals } = getSquareGridLines(vb, grid.cellSize);\r\n let d = '';\r\n for (const gx of verticals) d += `M${n(gx)} ${n(vb.minY)}L${n(gx)} ${n(vb.maxY)}`;\r\n for (const gy of horizontals) d += `M${n(vb.minX)} ${n(gy)}L${n(vb.maxX)} ${n(gy)}`;\r\n return `<path d=\"${d}\" fill=\"none\" stroke=\"${stroke}\" stroke-width=\"${sw}\" opacity=\"${op}\" />`;\r\n}\r\n\r\n// Geometric template only (square-grid context). Hex-grid templates fill snapped\r\n// hex cells; we approximate by emitting the cell hex outlines.\r\nfunction emitTemplate(template: TemplateElement, grid: GridElement | undefined): string {\r\n if (grid && grid.gridType === 'hex') {\r\n return emitHexTemplate(template, grid);\r\n }\r\n return emitGeometricTemplate(template);\r\n}\r\n\r\nfunction emitGeometricTemplate(t: TemplateElement): string {\r\n const { x: cx, y: cy } = t.position;\r\n const r = t.radius;\r\n const fill = esc(t.fillColor);\r\n const stroke = esc(t.strokeColor);\r\n const sw = n(t.strokeWidth);\r\n const op = n(t.opacity);\r\n const attrs = `fill=\"${fill}\" stroke=\"${stroke}\" stroke-width=\"${sw}\" opacity=\"${op}\"`;\r\n\r\n switch (t.templateShape) {\r\n case 'circle':\r\n return `<circle cx=\"${n(cx)}\" cy=\"${n(cy)}\" r=\"${n(r)}\" ${attrs} />`;\r\n case 'square':\r\n return `<rect x=\"${n(cx - r / 2)}\" y=\"${n(cy - r / 2)}\" width=\"${n(r)}\" height=\"${n(r)}\" ${attrs} />`;\r\n case 'cone': {\r\n const halfAngle = Math.atan(0.5);\r\n const a0 = t.angle - halfAngle;\r\n const a1 = t.angle + halfAngle;\r\n const p0x = cx + r * Math.cos(a0);\r\n const p0y = cy + r * Math.sin(a0);\r\n const p1x = cx + r * Math.cos(a1);\r\n const p1y = cy + r * Math.sin(a1);\r\n const large = a1 - a0 > Math.PI ? 1 : 0;\r\n return `<path d=\"M${n(cx)} ${n(cy)} L${n(p0x)} ${n(p0y)} A${n(r)} ${n(r)} 0 ${large} 1 ${n(p1x)} ${n(p1y)} Z\" ${attrs} />`;\r\n }\r\n case 'line': {\r\n const halfW = r / 12;\r\n const cos = Math.cos(t.angle);\r\n const sin = Math.sin(t.angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n const pts = [\r\n [cx + perpX, cy + perpY],\r\n [cx + r * cos + perpX, cy + r * sin + perpY],\r\n [cx + r * cos - perpX, cy + r * sin - perpY],\r\n [cx - perpX, cy - perpY],\r\n ]\r\n .map(([px, py]) => `${n(px ?? 0)},${n(py ?? 0)}`)\r\n .join(' ');\r\n return `<polygon points=\"${pts}\" ${attrs} />`;\r\n }\r\n case 'rectangle': {\r\n const halfW = (t.width ?? 0) / 2;\r\n const cos = Math.cos(t.angle);\r\n const sin = Math.sin(t.angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n const pts = [\r\n [cx + perpX, cy + perpY],\r\n [cx + r * cos + perpX, cy + r * sin + perpY],\r\n [cx + r * cos - perpX, cy + r * sin - perpY],\r\n [cx - perpX, cy - perpY],\r\n ]\r\n .map(([px, py]) => `${n(px ?? 0)},${n(py ?? 0)}`)\r\n .join(' ');\r\n return `<polygon points=\"${pts}\" ${attrs} />`;\r\n }\r\n }\r\n}\r\n\r\nfunction emitHexTemplate(t: TemplateElement, grid: GridElement): string {\r\n const cellSize = grid.cellSize;\r\n const orientation = grid.hexOrientation;\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const radiusCells = t.radius / snapUnit;\r\n const center = t.position;\r\n\r\n let cells: { x: number; y: number }[];\r\n switch (t.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, t.angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'line':\r\n cells = getHexCellsInLine(center, t.angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'square':\r\n cells = getHexCellsInSquare(center, radiusCells, cellSize, orientation);\r\n break;\r\n case 'rectangle': {\r\n const widthCells = (t.width ?? 0) / snapUnit;\r\n cells = getHexCellsInRectangle(\r\n center,\r\n t.angle,\r\n radiusCells,\r\n widthCells,\r\n cellSize,\r\n orientation,\r\n );\r\n break;\r\n }\r\n }\r\n\r\n let d = '';\r\n for (const cell of cells) {\r\n const verts = getHexVertices(cell.x, cell.y, cellSize, orientation);\r\n const first = verts[0];\r\n if (!first) continue;\r\n d += `M${n(first.x)} ${n(first.y)}`;\r\n for (let i = 1; i < verts.length; i++) {\r\n const v = verts[i];\r\n if (v) d += `L${n(v.x)} ${n(v.y)}`;\r\n }\r\n d += 'Z';\r\n }\r\n return `<path d=\"${d}\" fill=\"${esc(t.fillColor)}\" stroke=\"${esc(t.strokeColor)}\" stroke-width=\"${n(t.strokeWidth)}\" opacity=\"${n(t.opacity)}\" />`;\r\n}\r\n\r\nexport async function exportSvg(\r\n store: ElementStore,\r\n options: ExportSvgOptions = {},\r\n layerManager?: LayerManager,\r\n): Promise<string> {\r\n const padding = nonNegativeOption(options.padding, 0, 'padding');\r\n const rasterScale = positiveOption(options.rasterScale, 2, 'rasterScale');\r\n validateExportResourceOptions(options);\r\n validateHtmlExportOptions(options);\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 if (filter) visibleElements = visibleElements.filter(filter);\r\n\r\n const bounds = computeBounds(visibleElements, padding);\r\n if (!bounds) {\r\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"0\" height=\"0\" viewBox=\"0 0 0 0\"></svg>`;\r\n }\r\n assertExportSize(Math.ceil(bounds.w), Math.ceil(bounds.h), options);\r\n\r\n // Only remote/blob image srcs need network loading; data: srcs pass through.\r\n const remoteImages = visibleElements.filter(\r\n (el) => el.type === 'image' && !el.src.startsWith('data:'),\r\n );\r\n const imageCache = await loadImages(remoteImages, options);\r\n const imageDataUris = encodeImages(visibleElements, imageCache, rasterScale, options);\r\n const htmlElements = visibleElements.filter((el): el is HtmlElement => el.type === 'html');\r\n const htmlSources = await renderHtmlElements(htmlElements, options);\r\n const htmlDataUris = encodeHtmlElements(htmlElements, htmlSources, rasterScale, options);\r\n\r\n const grids = visibleElements.filter((el): el is GridElement => el.type === 'grid');\r\n const firstGrid = grids[0];\r\n\r\n let body = '';\r\n if (options.background) {\r\n body += `<rect x=\"${n(bounds.x)}\" y=\"${n(bounds.y)}\" width=\"${n(bounds.w)}\" height=\"${n(bounds.h)}\" fill=\"${esc(options.background)}\" />`;\r\n }\r\n\r\n const layerBodies = new Map<string, string>();\r\n for (const el of visibleElements) {\r\n const emitted = emitElement(\r\n el,\r\n imageDataUris,\r\n htmlDataUris,\r\n rasterScale,\r\n firstGrid,\r\n store,\r\n options,\r\n );\r\n layerBodies.set(el.layerId, (layerBodies.get(el.layerId) ?? '') + emitted);\r\n }\r\n for (const [layerId, emitted] of layerBodies) {\r\n const opacity = layerManager?.getLayer?.(layerId)?.opacity ?? 1;\r\n body += opacity === 1 || emitted === '' ? emitted : `<g opacity=\"${n(opacity)}\">${emitted}</g>`;\r\n }\r\n for (const grid of grids) {\r\n const emitted = emitGrid(grid, bounds);\r\n const opacity = layerManager?.getLayer?.(grid.layerId)?.opacity ?? 1;\r\n body += opacity === 1 ? emitted : `<g opacity=\"${n(opacity)}\">${emitted}</g>`;\r\n }\r\n\r\n return (\r\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${n(bounds.w)}\" height=\"${n(bounds.h)}\" ` +\r\n `viewBox=\"${n(bounds.x)} ${n(bounds.y)} ${n(bounds.w)} ${n(bounds.h)}\">${body}</svg>`\r\n );\r\n}\r\n\r\nfunction emitElement(\r\n el: CanvasElement,\r\n imageDataUris: Map<string, string>,\r\n htmlDataUris: Map<string, string>,\r\n rasterScale: number,\r\n firstGrid: GridElement | undefined,\r\n store: ElementStore,\r\n resourceOptions: ExportResourceOptions,\r\n): string {\r\n switch (el.type) {\r\n case 'stroke':\r\n return withRotationSvg(el, emitStroke(el));\r\n case 'shape':\r\n return withRotationSvg(el, emitShape(el));\r\n case 'arrow':\r\n return emitArrow(el, store);\r\n case 'image':\r\n return withRotationSvg(el, emitImage(el, imageDataUris.get(el.id)));\r\n case 'text':\r\n return withRotationSvg(el, emitText(el, rasterScale, resourceOptions));\r\n case 'note':\r\n return withRotationSvg(el, emitNote(el, rasterScale, resourceOptions));\r\n case 'template':\r\n return emitTemplate(el, firstGrid);\r\n case 'grid':\r\n return '';\r\n case 'html':\r\n return withRotationSvg(el, emitImage(el, htmlDataUris.get(el.id)));\r\n default:\r\n return '';\r\n }\r\n}\r\n\r\nfunction encodeHtmlElements(\r\n elements: HtmlElement[],\r\n sources: Map<string, CanvasImageSource>,\r\n rasterScale: number,\r\n options: ExportSvgOptions,\r\n): Map<string, string> {\r\n const encoded = new Map<string, string>();\r\n for (const element of elements) {\r\n const source = sources.get(element.id);\r\n if (!source) continue;\r\n const width = Math.max(1, Math.ceil(element.size.w * rasterScale));\r\n const height = Math.max(1, Math.ceil(element.size.h * rasterScale));\r\n assertExportSize(width, height, options);\r\n if (typeof document === 'undefined') {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'encode',\r\n });\r\n continue;\r\n }\r\n const canvas = document.createElement('canvas');\r\n canvas.width = width;\r\n canvas.height = height;\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'encode',\r\n });\r\n continue;\r\n }\r\n try {\r\n ctx.drawImage(source, 0, 0, width, height);\r\n const dataUri = canvas.toDataURL();\r\n if (dataUri.startsWith('data:')) {\r\n encoded.set(element.id, dataUri);\r\n } else {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'encode',\r\n });\r\n }\r\n } catch (cause) {\r\n options.onHtmlError?.({\r\n elementId: element.id,\r\n htmlType: element.htmlType,\r\n reason: 'encode',\r\n cause,\r\n });\r\n }\r\n }\r\n return encoded;\r\n}\r\n\r\n/** data: srcs pass through; remote/blob srcs are rasterized to data-URIs via the loaded image. */\r\nfunction encodeImages(\r\n elements: CanvasElement[],\r\n imageCache: Map<string, HTMLImageElement>,\r\n rasterScale: number,\r\n resourceOptions: ExportResourceOptions,\r\n): Map<string, string> {\r\n const out = new Map<string, string>();\r\n for (const el of elements) {\r\n if (el.type !== 'image') continue;\r\n if (el.src.startsWith('data:')) {\r\n out.set(el.id, el.src);\r\n continue;\r\n }\r\n const img = imageCache.get(el.id);\r\n if (!img || typeof document === 'undefined') continue;\r\n const width = Math.max(1, Math.ceil(el.size.w * rasterScale));\r\n const height = Math.max(1, Math.ceil(el.size.h * rasterScale));\r\n assertExportSize(width, height, resourceOptions);\r\n const canvas = document.createElement('canvas');\r\n canvas.width = width;\r\n canvas.height = height;\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) {\r\n resourceOptions.onAssetError?.({ elementId: el.id, src: el.src, reason: 'encode' });\r\n continue;\r\n }\r\n try {\r\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height);\r\n const uri = canvas.toDataURL();\r\n if (uri.startsWith('data:')) out.set(el.id, uri);\r\n else resourceOptions.onAssetError?.({ elementId: el.id, src: el.src, reason: 'encode' });\r\n } catch (cause) {\r\n resourceOptions.onAssetError?.({ elementId: el.id, src: el.src, reason: 'encode', cause });\r\n }\r\n }\r\n return out;\r\n}\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 strata = new Map<number, 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 private lastSyncedOpacity = new Map<string, number>();\r\n private cameraTransform = '';\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 setCameraTransform(transform: string): void {\r\n if (transform === this.cameraTransform) return;\r\n this.cameraTransform = transform;\r\n for (const stratum of this.strata.values()) stratum.style.transform = transform;\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 this.lastSyncedOpacity.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, opacity = 1): 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.getStratum(zIndex).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 const lastOpacity = this.lastSyncedOpacity.get(element.id);\r\n if (lastVersion === currentVersion && lastZ === zIndex && lastOpacity === opacity) {\r\n return;\r\n }\r\n }\r\n\r\n if (node.parentElement !== this.getStratum(zIndex)) {\r\n const previousStratum = node.parentElement;\r\n this.getStratum(zIndex).appendChild(node);\r\n if (previousStratum?.childElementCount === 0) {\r\n const previousOrder = Number(previousStratum.dataset['paintOrder']);\r\n previousStratum.remove();\r\n this.strata.delete(previousOrder);\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 this.lastSyncedOpacity.set(element.id, opacity);\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 opacity: String(opacity),\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) {\r\n node.style.display = 'none';\r\n this.lastSyncedVersion.delete(id);\r\n }\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 this.lastSyncedOpacity.delete(id);\r\n const node = this.domNodes.get(id);\r\n if (node) {\r\n const stratum = node.parentElement;\r\n node.remove();\r\n this.domNodes.delete(id);\r\n if (stratum?.childElementCount === 0) {\r\n const order = Number(stratum.dataset['paintOrder']);\r\n stratum.remove();\r\n this.strata.delete(order);\r\n }\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 this.lastSyncedOpacity.clear();\r\n for (const stratum of this.strata.values()) stratum.remove();\r\n this.strata.clear();\r\n }\r\n\r\n private getStratum(order: number): HTMLDivElement {\r\n let stratum = this.strata.get(order);\r\n if (stratum) return stratum;\r\n stratum = document.createElement('div');\r\n stratum.dataset['paintOrder'] = String(order);\r\n Object.assign(stratum.style, {\r\n position: 'absolute',\r\n inset: '0',\r\n width: '100%',\r\n height: '100%',\r\n pointerEvents: 'none',\r\n transformOrigin: '0 0',\r\n transform: this.cameraTransform,\r\n zIndex: String(order),\r\n });\r\n this.domLayer.appendChild(stratum);\r\n this.strata.set(order, stratum);\r\n return stratum;\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 lineHeight: '1.4',\r\n });\r\n node.innerHTML = 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 const text = element.text || '';\r\n if (node.innerHTML !== text) {\r\n node.innerHTML = 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 { getElementVisualBounds, boundsIntersect } from '../elements/element-bounds';\r\nimport { RenderStats } from './render-stats';\r\nimport type { RenderStatsSnapshot } from './render-stats';\r\nimport type { HybridRenderSurface } from './hybrid-render-surface';\r\n\r\n/**\r\n * A world-space draw callback rendered above elements on every frame,\r\n * regardless of which tool is active. The context arrives with the camera\r\n * transform applied; implementations must not assume exclusive context state\r\n * (each renderer is wrapped in save/restore). A throwing renderer is isolated\r\n * per frame and must not break the render loop.\r\n */\r\nexport type OverlayRenderer = (ctx: CanvasRenderingContext2D) => void;\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 hybridSurface: HybridRenderSurface;\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 readonly hybridSurface: HybridRenderSurface;\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 readonly overlays = new Set<OverlayRenderer>();\r\n private gridCacheCanvas: HTMLCanvasElement | null = null;\r\n private gridCacheCtx: CanvasRenderingContext2D | null = null;\r\n private lastGridRefs: CanvasElement[] = [];\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 this.hybridSurface = deps.hybridSurface;\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 this.gridCacheDirty = true;\r\n }\r\n\r\n getStats(): RenderStatsSnapshot {\r\n return this.stats.getSnapshot();\r\n }\r\n\r\n /**\r\n * Registers a viewport overlay drawn beneath the active tool's own overlay.\r\n * Returns an idempotent unsubscribe that also erases the overlay's last\r\n * frame.\r\n */\r\n registerOverlay(draw: OverlayRenderer): () => void {\r\n this.overlays.add(draw);\r\n this.requestRender();\r\n return () => {\r\n if (this.overlays.delete(draw)) this.requestRender();\r\n };\r\n }\r\n\r\n private drawRegisteredOverlays(ctx: CanvasRenderingContext2D): void {\r\n for (const draw of this.overlays) {\r\n ctx.save();\r\n try {\r\n draw(ctx);\r\n } catch {\r\n // One faulty overlay must not take down the frame or its siblings.\r\n } finally {\r\n ctx.restore();\r\n }\r\n }\r\n }\r\n\r\n private compositeLayerCache(\r\n ctx: CanvasRenderingContext2D,\r\n layerId: string,\r\n opacity: number,\r\n ): 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.globalAlpha = opacity;\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 const visibleElements = allElements.filter((element) =>\r\n this.layerManager.isLayerVisible(element.layerId),\r\n );\r\n const firstDomIndex = visibleElements.findIndex((element) =>\r\n this.renderer.isDomElement(element),\r\n );\r\n const hybridActive =\r\n firstDomIndex >= 0 &&\r\n visibleElements\r\n .slice(firstDomIndex + 1)\r\n .some((element) => !this.renderer.isDomElement(element));\r\n const hybridCanvasRuns = new Map<number, CanvasElement[]>();\r\n const hybridOrders = new Set<number>();\r\n let activeHybridOrder: number | null = null;\r\n this.layerGroups.clear();\r\n const gridElements: CanvasElement[] = [];\r\n let paintOrder = 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 const order = ++paintOrder;\r\n\r\n if (this.renderer.isDomElement(element)) {\r\n activeHybridOrder = null;\r\n const layerOpacity = this.layerManager.getLayer?.(element.layerId)?.opacity ?? 1;\r\n const elBounds = getElementVisualBounds(element);\r\n if (elBounds && !boundsIntersect(elBounds, cullingRect)) {\r\n this.domNodeManager.hideDomNode(element.id);\r\n } else {\r\n this.domNodeManager.syncDomNode(element, order, layerOpacity);\r\n }\r\n continue;\r\n }\r\n\r\n if (hybridActive && paintOrder > firstDomIndex + 1 && element.type !== 'grid') {\r\n activeHybridOrder ??= order;\r\n let run = hybridCanvasRuns.get(activeHybridOrder);\r\n if (!run) {\r\n run = [];\r\n hybridCanvasRuns.set(activeHybridOrder, run);\r\n hybridOrders.add(activeHybridOrder);\r\n }\r\n run.push(element);\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 const activeTool = this.toolManager.activeTool;\r\n const overlayOrder = visibleElements.length + 1;\r\n const hasOverlay = activeTool?.renderOverlay !== undefined || this.overlays.size > 0;\r\n if (hybridActive && hasOverlay) hybridOrders.add(overlayOrder);\r\n this.hybridSurface.beginFrame(hybridOrders, this.canvasEl.width, this.canvasEl.height);\r\n\r\n for (const [layerId, elements] of this.layerGroups) {\r\n const isActiveDrawingLayer = layerId === this.activeDrawingLayerId;\r\n const layerOpacity = this.layerManager.getLayer?.(layerId)?.opacity ?? 1;\r\n\r\n if (!this.layerCache.isDirty(layerId)) {\r\n const compT0 = performance.now();\r\n this.compositeLayerCache(ctx, layerId, layerOpacity);\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, layerOpacity);\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 = getElementVisualBounds(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, layerOpacity);\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 gridsChanged =\r\n gridElements.length !== this.lastGridRefs.length ||\r\n gridElements.some((grid, index) => grid !== this.lastGridRefs[index]);\r\n const gridDirty = this.gridCacheDirty || gridsChanged;\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 gc.save();\r\n gc.globalAlpha = this.layerManager.getLayer?.(grid.layerId)?.opacity ?? 1;\r\n this.renderer.renderCanvasElement(gc as CanvasRenderingContext2D, grid);\r\n gc.restore();\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.lastGridRefs = [...gridElements];\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 ctx.save();\r\n ctx.globalAlpha = this.layerManager.getLayer?.(grid.layerId)?.opacity ?? 1;\r\n this.renderer.renderCanvasElement(ctx, grid);\r\n ctx.restore();\r\n }\r\n }\r\n gridMs = performance.now() - gridT0;\r\n } else {\r\n this.lastGridRefs = [];\r\n }\r\n\r\n for (const [order, elements] of hybridCanvasRuns) {\r\n const hybridCtx = this.hybridSurface.getContext(order);\r\n if (!hybridCtx) continue;\r\n hybridCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);\r\n hybridCtx.save();\r\n hybridCtx.scale(dpr, dpr);\r\n hybridCtx.translate(this.camera.position.x, this.camera.position.y);\r\n hybridCtx.scale(this.camera.zoom, this.camera.zoom);\r\n for (const element of elements) {\r\n const elBounds = getElementVisualBounds(element);\r\n if (elBounds && !boundsIntersect(elBounds, cullingRect)) continue;\r\n hybridCtx.save();\r\n hybridCtx.globalAlpha = this.layerManager.getLayer?.(element.layerId)?.opacity ?? 1;\r\n this.renderer.renderCanvasElement(hybridCtx, element);\r\n hybridCtx.restore();\r\n }\r\n hybridCtx.restore();\r\n }\r\n\r\n const overlayT0 = performance.now();\r\n if (hybridActive && hasOverlay) {\r\n const overlayCtx = this.hybridSurface.getContext(overlayOrder);\r\n if (overlayCtx) {\r\n overlayCtx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);\r\n overlayCtx.save();\r\n overlayCtx.scale(dpr, dpr);\r\n overlayCtx.translate(this.camera.position.x, this.camera.position.y);\r\n overlayCtx.scale(this.camera.zoom, this.camera.zoom);\r\n this.drawRegisteredOverlays(overlayCtx);\r\n if (activeTool?.renderOverlay) activeTool.renderOverlay(overlayCtx);\r\n overlayCtx.restore();\r\n }\r\n } else if (hasOverlay) {\r\n this.drawRegisteredOverlays(ctx);\r\n if (activeTool?.renderOverlay) 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 { ArrowStrokeStyle, 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 strokeStyle?: ArrowStrokeStyle;\r\n}\r\n\r\nexport function styleToPatch(element: CanvasElement, style: ElementStyle): Partial<CanvasElement> {\r\n const { color, fillColor, strokeWidth, opacity, fontSize, strokeStyle } = 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 ...(strokeStyle !== undefined ? { strokeStyle } : {}),\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 {\r\n color: element.color,\r\n strokeWidth: element.width,\r\n ...(element.strokeStyle !== undefined ? { strokeStyle: element.strokeStyle } : {}),\r\n };\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 { Bounds, Point } from '../core/types';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { normalizeAngle, rotatePoint, rotatedAABB } from '../core/geometry';\r\n\r\nexport type RotateDirection = 'cw' | 'ccw';\r\n\r\nexport interface BoundedElement {\r\n id: string;\r\n el: CanvasElement;\r\n bounds: Bounds;\r\n}\r\n\r\nexport function 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\nexport function rotationPivot(items: readonly BoundedElement[]): Point {\r\n const first = items[0];\r\n if (items.length === 1 && first) {\r\n return { x: first.bounds.x + first.bounds.w / 2, y: first.bounds.y + first.bounds.h / 2 };\r\n }\r\n const u = unionBounds(items.map((it) => rotatedAABB(it.bounds, it.el.rotation ?? 0)));\r\n return { x: u.x + u.w / 2, y: u.y + u.h / 2 };\r\n}\r\n\r\nexport function rotateElementPatch(\r\n el: CanvasElement,\r\n bounds: Bounds,\r\n pivot: Point,\r\n delta: number,\r\n): Partial<CanvasElement> {\r\n if (el.type === 'arrow') {\r\n const center = { x: bounds.x + bounds.w / 2, y: bounds.y + bounds.h / 2 };\r\n const moved = rotatePoint(center, pivot, delta);\r\n return {\r\n position: { x: el.position.x + moved.x - center.x, y: el.position.y + moved.y - center.y },\r\n from: rotatePoint(el.from, pivot, delta),\r\n to: rotatePoint(el.to, pivot, delta),\r\n };\r\n }\r\n if (el.type === 'template') {\r\n return {\r\n position: rotatePoint(el.position, pivot, delta),\r\n angle: normalizeAngle(el.angle + delta),\r\n };\r\n }\r\n const center = { x: bounds.x + bounds.w / 2, y: bounds.y + bounds.h / 2 };\r\n const moved = rotatePoint(center, pivot, delta);\r\n return {\r\n position: { x: el.position.x + moved.x - center.x, y: el.position.y + moved.y - center.y },\r\n rotation: normalizeAngle((el.rotation ?? 0) + delta),\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\nimport { rotationPivot, rotateElementPatch, unionBounds } from './selection-rotate';\r\nimport type { RotateDirection } from './selection-rotate';\r\n\r\nexport type AlignEdge = 'left' | 'center-x' | 'right' | 'top' | 'middle' | 'bottom';\r\nexport type DistributeAxis = 'horizontal' | 'vertical';\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 const strokeStyle = sharedValue(styles.map((s) => s.strokeStyle));\r\n if (strokeStyle !== undefined) result.strokeStyle = strokeStyle;\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 rotateSelection(direction: RotateDirection): void {\r\n const eligible = this.boundedSelection().filter(({ el }) => this.isMovable(el));\r\n if (eligible.length === 0) return;\r\n const delta = direction === 'cw' ? Math.PI / 2 : -Math.PI / 2;\r\n const pivot = rotationPivot(eligible);\r\n this.deps.recorder.begin();\r\n const moved: string[] = [];\r\n for (const { id, el, bounds } of eligible) {\r\n this.deps.store.update(id, rotateElementPatch(el, bounds, pivot, delta));\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 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';\nimport type { ElementStore } from '../elements/element-store';\nimport type { ElementRenderer } from '../elements/element-renderer';\nimport type { NoteEditor } from '../elements/note-editor';\nimport type { ArrowLabelEditor } from '../elements/arrow-label-editor';\nimport type { InteractMode } from './interact-mode';\nimport type { DomNodeManager } from './dom-node-manager';\nimport type { RenderLoop } from './render-loop';\nimport type { HistoryRecorder } from '../history/history-recorder';\nimport type { CanvasElement, ArrowElement } from '../elements/types';\nimport { DoubleTapDetector } from './double-tap-detector';\nimport { isNearBezier } from '../elements/arrow-geometry';\nimport { isNoteContentEmpty } from '../elements/note-sanitizer';\n\nconst ARROW_HIT_THRESHOLD = 10;\n\nexport interface ViewportInteractionsDeps {\n store: ElementStore;\n camera: Camera;\n wrapper: HTMLDivElement;\n domLayer: HTMLDivElement;\n renderLoop: RenderLoop;\n domNodeManager: DomNodeManager;\n noteEditor: NoteEditor;\n arrowLabelEditor: ArrowLabelEditor;\n interactMode: InteractMode;\n renderer: ElementRenderer;\n recorder: HistoryRecorder;\n requestRender: () => void;\n addImage: (src: string, position: { x: number; y: number }) => string;\n dropHandler?: (event: DragEvent, worldPosition: { x: number; y: number }) => void;\n}\n\nexport class ViewportInteractions {\n private readonly doubleTapDetector = new DoubleTapDetector();\n private tapDownX = 0;\n private tapDownY = 0;\n\n constructor(private readonly deps: ViewportInteractionsDeps) {}\n\n startEditingElement(id: string): void {\n const element = this.deps.store.getById(id);\n if (!element || (element.type !== 'note' && element.type !== 'text')) return;\n\n this.deps.renderLoop.flush();\n\n const node = this.deps.domNodeManager.getNode(id);\n if (node) {\n this.deps.noteEditor.startEditing(node, id, this.deps.store);\n }\n }\n\n liveFitHeight(elementId: string): void {\n const element = this.deps.store.getById(elementId);\n if (!element || (element.type !== 'note' && element.type !== 'text')) return;\n const node = this.deps.domNodeManager.getNode(elementId);\n if (!node) return;\n const measured = node.scrollHeight;\n if (measured > 0 && measured !== element.size.h) {\n this.deps.store.update(elementId, { size: { w: element.size.w, h: measured } });\n }\n }\n\n fitNoteHeight(elementId: string): void {\n const element = this.deps.store.getById(elementId);\n if (!element || element.type !== 'note') return;\n if (isNoteContentEmpty(element.text)) return;\n const node = this.deps.domNodeManager.getNode(elementId);\n if (!node) return;\n const measured = node.scrollHeight;\n if (measured > element.size.h) {\n this.deps.store.update(elementId, { size: { w: element.size.w, h: measured } });\n }\n }\n\n onTextEditStop(elementId: string): void {\n const element = this.deps.store.getById(elementId);\n if (!element) return;\n\n if (element.type === 'note') {\n if (isNoteContentEmpty(element.text)) {\n this.deps.store.remove(elementId);\n return;\n }\n this.liveFitHeight(elementId);\n return;\n }\n\n if (element.type !== 'text') return;\n\n if (!element.text || element.text.trim() === '') {\n this.deps.store.remove(elementId);\n return;\n }\n\n this.liveFitHeight(elementId);\n }\n\n onTapDown = (e: PointerEvent): void => {\n this.tapDownX = e.clientX;\n this.tapDownY = e.clientY;\n };\n\n onDoubleTap = (e: PointerEvent): void => {\n const dx = e.clientX - this.tapDownX;\n const dy = e.clientY - this.tapDownY;\n const moved = Math.sqrt(dx * dx + dy * dy);\n if (moved > 10) return;\n\n if (!this.doubleTapDetector.feed(e)) return;\n if (typeof document.elementFromPoint !== 'function') return;\n\n const el = document.elementFromPoint(e.clientX, e.clientY);\n\n const nodeEl = (el as HTMLElement | null)?.closest<HTMLDivElement>('[data-element-id]');\n if (nodeEl) {\n const elementId = nodeEl.dataset['elementId'];\n if (elementId) {\n const element = this.deps.store.getById(elementId);\n if (element?.type === 'note' || element?.type === 'text') {\n this.startEditingElement(elementId);\n return;\n }\n }\n }\n\n const rect = this.deps.wrapper.getBoundingClientRect();\n const screen = { x: e.clientX - rect.left, y: e.clientY - rect.top };\n const world = this.deps.camera.screenToWorld(screen);\n\n // HTML embeds keep double-tap priority: you double-tapped inside the embed even if an\n // arrow's curve passes nearby. Arrow-label editing only when no embed is hit.\n const hit = this.hitTestWorld(world);\n if (hit?.type === 'html') {\n this.deps.interactMode.startInteracting(hit.id);\n return;\n }\n\n const arrow = this.findArrowAt(world);\n if (arrow) {\n this.startArrowLabelEdit(arrow);\n }\n };\n\n findArrowAt(world: { x: number; y: number }): ArrowElement | undefined {\n const candidates = this.deps.store.queryPoint(world).reverse();\n for (const el of candidates) {\n if (\n el.type === 'arrow' &&\n isNearBezier(world, el.from, el.to, el.bend, ARROW_HIT_THRESHOLD)\n ) {\n return el;\n }\n }\n return undefined;\n }\n\n startArrowLabelEdit(arrow: ArrowElement): void {\n this.deps.arrowLabelEditor.startEditing({\n arrow,\n layer: this.deps.domLayer,\n store: this.deps.store,\n recorder: this.deps.recorder,\n onDone: () => {\n this.deps.renderer.setLabelEditingId(null);\n this.deps.requestRender();\n },\n });\n // Set AFTER startEditing: starting a new edit cleans up any prior session, whose onDone\n // synchronously clears the editing id — so claim suppression for this arrow last.\n this.deps.renderer.setLabelEditingId(arrow.id);\n }\n\n private hitTestWorld(world: { x: number; y: number }): CanvasElement | null {\n const candidates = this.deps.store.queryPoint(world).reverse();\n for (const el of candidates) {\n if (!('size' in el)) continue;\n const { x, y } = el.position;\n const { w, h } = el.size;\n if (world.x >= x && world.x <= x + w && world.y >= y && world.y <= y + h) {\n return el;\n }\n }\n return null;\n }\n\n onDragOver = (e: DragEvent): void => {\n e.preventDefault();\n };\n\n onDrop = (e: DragEvent): void => {\n e.preventDefault();\n const rect = this.deps.wrapper.getBoundingClientRect();\n const screenPos = { x: e.clientX - rect.left, y: e.clientY - rect.top };\n const worldPos = this.deps.camera.screenToWorld(screenPos);\n\n if (this.deps.dropHandler) {\n this.deps.dropHandler(e, worldPos);\n return;\n }\n\n const files = e.dataTransfer?.files;\n if (!files) return;\n\n for (const file of files) {\n if (!file.type.startsWith('image/')) continue;\n\n const reader = new FileReader();\n reader.onload = () => {\n const src = reader.result;\n if (typeof src !== 'string') return;\n this.deps.addImage(src, worldPos);\n };\n reader.readAsDataURL(file);\n }\n };\n}\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 {\r\n CanvasElement,\r\n ArrowElement,\r\n GridElement,\r\n HtmlElement,\r\n ShapeKind,\r\n} 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 { Minimap } from './minimap';\r\nimport { createWrapper, createCanvas, createDomLayer, createPaintStack } from './viewport-dom';\r\nimport { HybridRenderSurface } from './hybrid-render-surface';\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 { exportSvg } from './export-svg';\r\nimport type { ExportSvgOptions } from './export-svg';\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 { OverlayRenderer } 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\nimport type { RotateDirection } from './selection-rotate';\r\n\r\nexport type { AlignEdge, DistributeAxis } from './selection-ops';\r\nexport type { GridInfo } from './grid-controller';\r\nexport type { RotateDirection } from './selection-rotate';\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 onPaste?: (event: ClipboardEvent, 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 /** Coast (inertial glide) after a pan flick. Default `true`. */\r\n panInertia?: boolean;\r\n /** Show an overview minimap (bottom-right) with tap/drag-to-navigate. Default `false`. */\r\n minimap?: 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 paintStack: HTMLDivElement;\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 transactionDepth = 0;\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 private minimap: Minimap | null = null;\r\n private readonly htmlRenderers = new Map<string, (el: HtmlElement) => HTMLElement>();\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.noteEditor.setOnInput((id) => this.interactions.liveFitHeight(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.paintStack = createPaintStack();\r\n this.domLayer = createDomLayer();\r\n this.domLayer.style.zIndex = '2147483647';\r\n\r\n this.wrapper.appendChild(this.canvasEl);\r\n this.wrapper.appendChild(this.paintStack);\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 rotate: (direction) => this.rotateSelection(direction),\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 addImage: (src, world) => this.addImage(src, world),\r\n getCenteredWorld: () => this.centeredPosition({ w: 300, h: 200 }),\r\n onPaste: options.onPaste,\r\n panInertia: options.panInertia,\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 if (options.minimap) {\r\n const visibleEls = () =>\r\n this.store.getAll().filter((el) => this.layerManager.isLayerVisible(el.layerId));\r\n this.minimap = new Minimap({\r\n container: this.wrapper,\r\n getElements: visibleEls,\r\n getContentBounds: () => getElementsBoundingBox(visibleEls()),\r\n getViewportRect: () =>\r\n this.camera.getVisibleRect(this.canvasEl.clientWidth, this.canvasEl.clientHeight),\r\n navigateTo: (w) => {\r\n const z = this.camera.zoom;\r\n this.camera.moveTo(\r\n this.canvasEl.clientWidth / 2 - w.x * z,\r\n this.canvasEl.clientHeight / 2 - w.y * z,\r\n );\r\n },\r\n requestFrame: (cb) =>\r\n typeof requestAnimationFrame !== 'undefined' ? requestAnimationFrame(cb) : 0,\r\n cancelFrame: (id) => {\r\n if (typeof cancelAnimationFrame !== 'undefined') cancelAnimationFrame(id);\r\n },\r\n });\r\n this.minimap.scheduleDraw();\r\n }\r\n\r\n this.domNodeManager = new DomNodeManager({\r\n domLayer: this.paintStack,\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 this.domNodeManager.setCameraTransform(this.camera.toCSSTransform());\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 hybridSurface: new HybridRenderSurface(this.paintStack),\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.minimap?.scheduleDraw();\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.minimap?.scheduleDraw();\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.minimap?.scheduleDraw();\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.minimap?.scheduleDraw();\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.minimap?.scheduleDraw();\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.renderLoop.markAllLayersDirty();\r\n this.minimap?.scheduleDraw();\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 /**\r\n * Registers a world-space overlay drawn above elements on every frame,\r\n * regardless of the active tool — the surface for remote presence visuals\r\n * such as laser trails, cursors, pings, and shared rulers. Overlays draw\r\n * beneath the active tool's own `renderOverlay` and never touch elements,\r\n * history, or persisted state. Returns an idempotent unsubscribe that also\r\n * erases the overlay's last frame.\r\n */\r\n registerOverlay(draw: OverlayRenderer): () => void {\r\n return this.renderLoop.registerOverlay(draw);\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 async exportSVG(options?: ExportSvgOptions): Promise<string> {\r\n return exportSvg(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 for (const el of this.store.getElementsByType('html')) {\r\n if (this.domNodeManager.hasContent(el.id)) continue;\r\n\r\n // Registry first: rebuild the embed from serialized data and mount it via the html branch\r\n // of renderDomContent. This stores content BEFORE the onHtmlElementMount path's hasContent\r\n // check, so a factory-rebuilt element never also gets an empty node from the callback path.\r\n const factory = el.htmlType ? this.htmlRenderers.get(el.htmlType) : undefined;\r\n const rebuilt = factory ? factory(el) : null;\r\n if (rebuilt) {\r\n this.domNodeManager.storeHtmlContent(el.id, rebuilt);\r\n this.domNodeManager.syncDomNode(el);\r\n }\r\n\r\n // Callback still fires for wiring (both fire; registry produces the node, callback wires it).\r\n if (this.onHtmlElementMount) {\r\n if (!rebuilt) 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 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 /**\r\n * Groups synchronous local store and layer mutations into one undo step.\r\n * Nested calls join the outer transaction. If the callback throws, mutations\r\n * already applied remain undoable and the original error is rethrown.\r\n */\r\n transaction<T>(operation: () => T): T {\r\n const isOuterTransaction = this.transactionDepth === 0;\r\n if (isOuterTransaction) {\r\n this.inputHandler.flushPendingHistory();\r\n this.historyRecorder.begin();\r\n }\r\n this.transactionDepth += 1;\r\n try {\r\n return operation();\r\n } finally {\r\n this.transactionDepth -= 1;\r\n if (isOuterTransaction) this.historyRecorder.commit();\r\n }\r\n }\r\n\r\n /** Removes existing elements as one undoable operation and returns the number removed. */\r\n removeElements(ids: Iterable<string>): number {\r\n const existingIds = [...new Set(ids)].filter((id) => this.store.getById(id) !== undefined);\r\n if (existingIds.length === 0) return 0;\r\n this.transaction(() => {\r\n for (const id of existingIds) this.store.remove(id);\r\n });\r\n this.requestRender();\r\n return existingIds.length;\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 opts?: { htmlType?: string; data?: Record<string, unknown> },\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 htmlType: opts?.htmlType,\r\n data: opts?.data,\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 registerHtmlRenderer(htmlType: string, factory: (el: HtmlElement) => HTMLElement): void {\r\n this.htmlRenderers.set(htmlType, factory);\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 items.push({ label: 'Rotate 90° CW', action: 'rotate-cw' });\r\n items.push({ label: 'Rotate 90° CCW', action: 'rotate-ccw' });\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 rotateSelection(direction: RotateDirection): void {\r\n this.selectionOps.rotateSelection(direction);\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.minimap?.destroy();\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 const transform = this.camera.toCSSTransform();\r\n this.domLayer.style.transform = transform;\r\n this.domNodeManager.setCameraTransform(transform);\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 { Point } from '../core/types';\r\nimport type { OverlayRenderer } from './render-loop';\r\nimport type { LaserTrailEmission } from '../tools/laser-tool';\r\n\r\n/**\r\n * The wire shape of a laser-trail presence payload. Presence data is untyped\r\n * on the wire, so hosts discriminate on `kind`; `isLaserTrailPresence`\r\n * validates a received payload before it reaches the overlay. Trails are\r\n * ephemeral by contract: they must travel as presence only — never as\r\n * elements, undo history, persisted canvas state, or durable operations.\r\n */\r\nexport interface LaserTrailPresence {\r\n readonly kind: 'laser';\r\n /** World-space points, oldest first. */\r\n readonly points: readonly Point[];\r\n readonly color?: string;\r\n readonly width?: number;\r\n readonly fadeMs?: number;\r\n}\r\n\r\nexport const LASER_TRAIL_PRESENCE_KIND = 'laser';\r\n\r\nfunction isFinitePoint(value: unknown): value is Point {\r\n if (typeof value !== 'object' || value === null) return false;\r\n const point = value as { x?: unknown; y?: unknown };\r\n return (\r\n typeof point.x === 'number' &&\r\n Number.isFinite(point.x) &&\r\n typeof point.y === 'number' &&\r\n Number.isFinite(point.y)\r\n );\r\n}\r\n\r\nexport function isLaserTrailPresence(data: unknown): data is LaserTrailPresence {\r\n if (typeof data !== 'object' || data === null) return false;\r\n const payload = data as {\r\n kind?: unknown;\r\n points?: unknown;\r\n color?: unknown;\r\n width?: unknown;\r\n fadeMs?: unknown;\r\n };\r\n if (payload.kind !== LASER_TRAIL_PRESENCE_KIND) return false;\r\n if (!Array.isArray(payload.points) || !payload.points.every(isFinitePoint)) return false;\r\n if (payload.color !== undefined && typeof payload.color !== 'string') return false;\r\n if (payload.width !== undefined && !(typeof payload.width === 'number' && payload.width > 0)) {\r\n return false;\r\n }\r\n if (payload.fadeMs !== undefined && !(typeof payload.fadeMs === 'number' && payload.fadeMs > 0)) {\r\n return false;\r\n }\r\n return true;\r\n}\r\n\r\n/** Builds the presence payload for one local `LaserTool` emission. */\r\nexport function toLaserTrailPresence(emission: LaserTrailEmission): LaserTrailPresence {\r\n return {\r\n kind: LASER_TRAIL_PRESENCE_KIND,\r\n points: emission.points.map((point) => ({ x: point.x, y: point.y })),\r\n color: emission.color,\r\n width: emission.width,\r\n fadeMs: emission.fadeMs,\r\n };\r\n}\r\n\r\n/**\r\n * The two viewport capabilities the overlay needs; `Viewport` satisfies it.\r\n */\r\nexport interface RemoteLaserOverlayHost {\r\n registerOverlay(draw: OverlayRenderer): () => void;\r\n requestRender(): void;\r\n}\r\n\r\nexport interface RemoteLaserOverlayOptions {\r\n /** Style fallbacks when a payload omits them. */\r\n color?: string;\r\n width?: number;\r\n fadeMs?: number;\r\n /** Per-sender point cap; oldest points drop first. Default `512`. */\r\n maxPointsPerSender?: number;\r\n}\r\n\r\ninterface RemoteTrailPoint {\r\n x: number;\r\n y: number;\r\n t: number;\r\n}\r\n\r\ninterface RemoteTrail {\r\n points: RemoteTrailPoint[];\r\n color: string;\r\n width: number;\r\n fadeMs: number;\r\n}\r\n\r\nconst DEFAULT_COLOR = '#ff3b30';\r\nconst DEFAULT_WIDTH = 4;\r\nconst DEFAULT_FADE_MS = 1200;\r\nconst DEFAULT_MAX_POINTS = 512;\r\n\r\n/**\r\n * Renders fading laser trails for remote senders through the viewport overlay\r\n * registration, independent of the viewer's active tool. Points are stamped\r\n * with local receive time (remote clocks are never trusted), fade like the\r\n * local `LaserTool`, and a sender's trail disappears immediately on\r\n * `remove()` — wire that to `presence-leave`/disconnect. The controller never\r\n * touches elements, history, or persisted state.\r\n */\r\nexport class RemoteLaserOverlay {\r\n private readonly host: RemoteLaserOverlayHost;\r\n private readonly color: string;\r\n private readonly width: number;\r\n private readonly fadeMs: number;\r\n private readonly maxPointsPerSender: number;\r\n private readonly trails = new Map<string, RemoteTrail>();\r\n private unregister: (() => void) | null;\r\n private rafId: number | null = null;\r\n private disposed = false;\r\n\r\n constructor(host: RemoteLaserOverlayHost, options: RemoteLaserOverlayOptions = {}) {\r\n this.host = host;\r\n this.color = options.color ?? DEFAULT_COLOR;\r\n this.width = options.width ?? DEFAULT_WIDTH;\r\n this.fadeMs = options.fadeMs ?? DEFAULT_FADE_MS;\r\n this.maxPointsPerSender = options.maxPointsPerSender ?? DEFAULT_MAX_POINTS;\r\n this.unregister = host.registerOverlay((ctx) => this.renderTrails(ctx));\r\n }\r\n\r\n private now(): number {\r\n return performance.now();\r\n }\r\n\r\n /**\r\n * Applies a presence payload from `sender` (any opaque per-sender key, e.g.\r\n * the envelope `from`). Non-laser or malformed payloads are ignored and\r\n * reported as `false`, so hosts can feed every presence frame through.\r\n */\r\n apply(sender: string, data: unknown): boolean {\r\n if (this.disposed || !isLaserTrailPresence(data)) return false;\r\n let trail = this.trails.get(sender);\r\n if (!trail) {\r\n trail = { points: [], color: this.color, width: this.width, fadeMs: this.fadeMs };\r\n this.trails.set(sender, trail);\r\n }\r\n trail.color = data.color ?? this.color;\r\n trail.width = data.width ?? this.width;\r\n trail.fadeMs = data.fadeMs ?? this.fadeMs;\r\n const t = this.now();\r\n for (const point of data.points) {\r\n trail.points.push({ x: point.x, y: point.y, t });\r\n }\r\n const excess = trail.points.length - this.maxPointsPerSender;\r\n if (excess > 0) trail.points.splice(0, excess);\r\n this.ensureAnimating();\r\n this.host.requestRender();\r\n return true;\r\n }\r\n\r\n /** Removes a sender's trail immediately (presence-leave/disconnect). */\r\n remove(sender: string): void {\r\n if (this.trails.delete(sender)) this.host.requestRender();\r\n }\r\n\r\n /** Removes every trail immediately. */\r\n clear(): void {\r\n if (this.trails.size === 0) return;\r\n this.trails.clear();\r\n this.host.requestRender();\r\n }\r\n\r\n /** Number of senders with a live (unfaded) trail. */\r\n get activeSenderCount(): number {\r\n return this.trails.size;\r\n }\r\n\r\n /** Unregisters the overlay and stops the fade loop. Idempotent. */\r\n dispose(): void {\r\n if (this.disposed) return;\r\n this.disposed = true;\r\n if (this.rafId !== null) {\r\n cancelAnimationFrame(this.rafId);\r\n this.rafId = null;\r\n }\r\n this.trails.clear();\r\n this.unregister?.();\r\n this.unregister = null;\r\n }\r\n\r\n private ensureAnimating(): void {\r\n if (this.rafId === null) {\r\n this.rafId = requestAnimationFrame(() => this.tick());\r\n }\r\n }\r\n\r\n private tick(): void {\r\n if (this.disposed) return;\r\n const now = this.now();\r\n for (const [sender, trail] of this.trails) {\r\n const cutoff = now - trail.fadeMs;\r\n trail.points = trail.points.filter((point) => point.t >= cutoff);\r\n if (trail.points.length === 0) this.trails.delete(sender);\r\n }\r\n this.host.requestRender();\r\n this.rafId = this.trails.size > 0 ? requestAnimationFrame(() => this.tick()) : null;\r\n }\r\n\r\n private renderTrails(ctx: CanvasRenderingContext2D): void {\r\n if (this.trails.size === 0) return;\r\n const now = this.now();\r\n for (const trail of this.trails.values()) {\r\n if (trail.points.length < 2) continue;\r\n ctx.save();\r\n ctx.strokeStyle = trail.color;\r\n ctx.lineWidth = trail.width;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n for (let i = 0; i < trail.points.length - 1; i++) {\r\n const a = trail.points[i];\r\n const b = trail.points[i + 1];\r\n if (!a || !b) continue;\r\n const age = now - b.t;\r\n ctx.globalAlpha = Math.max(0, 1 - age / trail.fadeMs);\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 }\r\n ctx.restore();\r\n }\r\n }\r\n}\r\n","/**\r\n * Shared expanding-pulse rendering for map pings. Internal helper used by the\r\n * local `PingTool` overlay and the `RemotePingOverlay` so a viewer sees the\r\n * same animation for local and remote pings. Not part of the public API.\r\n */\r\n\r\nexport interface PingPulseStyle {\r\n color: string;\r\n /** Total animation length in milliseconds. */\r\n durationMs: number;\r\n /** Maximum ripple radius in world units. */\r\n radius: number;\r\n}\r\n\r\n/** Ripple start offsets as fractions of the total duration. */\r\nconst RIPPLE_OFFSETS = [0, 0.25] as const;\r\n\r\nfunction easeOutCubic(t: number): number {\r\n const inv = 1 - t;\r\n return 1 - inv * inv * inv;\r\n}\r\n\r\n/**\r\n * Draws one ping at world position (`x`, `y`) given its age. The context is\r\n * already in world space. Draws nothing once `ageMs >= durationMs`.\r\n */\r\nexport function renderPingPulse(\r\n ctx: CanvasRenderingContext2D,\r\n x: number,\r\n y: number,\r\n ageMs: number,\r\n style: PingPulseStyle,\r\n): void {\r\n if (ageMs < 0 || ageMs >= style.durationMs) return;\r\n\r\n ctx.save();\r\n ctx.strokeStyle = style.color;\r\n ctx.fillStyle = style.color;\r\n\r\n for (const offset of RIPPLE_OFFSETS) {\r\n const rippleSpan = style.durationMs * (1 - offset);\r\n const rippleAge = ageMs - style.durationMs * offset;\r\n if (rippleAge < 0) continue;\r\n const progress = Math.min(1, rippleAge / rippleSpan);\r\n const rippleRadius = style.radius * easeOutCubic(progress);\r\n if (rippleRadius <= 0) continue;\r\n ctx.globalAlpha = Math.max(0, 1 - progress);\r\n ctx.lineWidth = Math.max(1.5, style.radius / 12);\r\n ctx.beginPath();\r\n ctx.arc(x, y, rippleRadius, 0, Math.PI * 2);\r\n ctx.stroke();\r\n }\r\n\r\n // Center dot: solid for the first half, then fades with the ripples.\r\n const dotProgress = ageMs / style.durationMs;\r\n ctx.globalAlpha = Math.max(0, 1 - Math.max(0, dotProgress - 0.5) * 2);\r\n ctx.beginPath();\r\n ctx.arc(x, y, Math.max(2, style.radius / 8), 0, Math.PI * 2);\r\n ctx.fill();\r\n\r\n ctx.restore();\r\n}\r\n","import type { OverlayRenderer } from './render-loop';\r\nimport { renderPingPulse } from './ping-pulse';\r\nimport type { PingEmission } from '../tools/ping-tool';\r\n\r\n/**\r\n * The wire shape of a map-ping presence payload. Presence data is untyped on\r\n * the wire, so hosts discriminate on `kind`; `isPingPresence` validates a\r\n * received payload before it reaches the overlay. Pings are ephemeral by\r\n * contract: they must travel as presence only — never as elements, undo\r\n * history, persisted canvas state, or durable operations.\r\n */\r\nexport interface PingPresence {\r\n readonly kind: 'ping';\r\n /** World-space ping position. */\r\n readonly x: number;\r\n readonly y: number;\r\n readonly color?: string;\r\n readonly durationMs?: number;\r\n readonly radius?: number;\r\n}\r\n\r\nexport const PING_PRESENCE_KIND = 'ping';\r\n\r\nexport function isPingPresence(data: unknown): data is PingPresence {\r\n if (typeof data !== 'object' || data === null) return false;\r\n const payload = data as {\r\n kind?: unknown;\r\n x?: unknown;\r\n y?: unknown;\r\n color?: unknown;\r\n durationMs?: unknown;\r\n radius?: unknown;\r\n };\r\n if (payload.kind !== PING_PRESENCE_KIND) return false;\r\n if (typeof payload.x !== 'number' || !Number.isFinite(payload.x)) return false;\r\n if (typeof payload.y !== 'number' || !Number.isFinite(payload.y)) return false;\r\n if (payload.color !== undefined && typeof payload.color !== 'string') return false;\r\n if (\r\n payload.durationMs !== undefined &&\r\n !(\r\n typeof payload.durationMs === 'number' &&\r\n Number.isFinite(payload.durationMs) &&\r\n payload.durationMs > 0\r\n )\r\n ) {\r\n return false;\r\n }\r\n if (\r\n payload.radius !== undefined &&\r\n !(typeof payload.radius === 'number' && Number.isFinite(payload.radius) && payload.radius > 0)\r\n ) {\r\n return false;\r\n }\r\n return true;\r\n}\r\n\r\n/** Builds the presence payload for one local `PingTool` emission. */\r\nexport function toPingPresence(emission: PingEmission): PingPresence {\r\n return {\r\n kind: PING_PRESENCE_KIND,\r\n x: emission.x,\r\n y: emission.y,\r\n color: emission.color,\r\n durationMs: emission.durationMs,\r\n radius: emission.radius,\r\n };\r\n}\r\n\r\n/**\r\n * The two viewport capabilities the overlay needs; `Viewport` satisfies it.\r\n */\r\nexport interface RemotePingOverlayHost {\r\n registerOverlay(draw: OverlayRenderer): () => void;\r\n requestRender(): void;\r\n}\r\n\r\nexport interface RemotePingOverlayOptions {\r\n /** Style fallbacks when a payload omits them. */\r\n color?: string;\r\n durationMs?: number;\r\n radius?: number;\r\n /** Per-sender live-ping cap; oldest pings drop first. Default `8`. */\r\n maxPingsPerSender?: number;\r\n}\r\n\r\ninterface RemotePing {\r\n x: number;\r\n y: number;\r\n t: number;\r\n color: string;\r\n durationMs: number;\r\n radius: number;\r\n}\r\n\r\nconst DEFAULT_COLOR = '#ff3b30';\r\nconst DEFAULT_DURATION_MS = 1800;\r\nconst DEFAULT_RADIUS = 48;\r\nconst DEFAULT_MAX_PINGS = 8;\r\n\r\n/**\r\n * Renders expanding-pulse pings for remote senders through the viewport\r\n * overlay registration, independent of the viewer's active tool. Pings are\r\n * stamped with local receive time (remote clocks are never trusted),\r\n * self-expire when their animation ends, and a sender's pings disappear\r\n * immediately on `remove()` — wire that to `presence-leave`/disconnect. The\r\n * controller never touches elements, history, or persisted state, and it\r\n * never moves the viewer's camera: pings are visual only.\r\n */\r\nexport class RemotePingOverlay {\r\n private readonly host: RemotePingOverlayHost;\r\n private readonly color: string;\r\n private readonly durationMs: number;\r\n private readonly radius: number;\r\n private readonly maxPingsPerSender: number;\r\n private readonly pings = new Map<string, RemotePing[]>();\r\n private unregister: (() => void) | null;\r\n private rafId: number | null = null;\r\n private disposed = false;\r\n\r\n constructor(host: RemotePingOverlayHost, options: RemotePingOverlayOptions = {}) {\r\n this.host = host;\r\n this.color = options.color ?? DEFAULT_COLOR;\r\n this.durationMs = options.durationMs ?? DEFAULT_DURATION_MS;\r\n this.radius = options.radius ?? DEFAULT_RADIUS;\r\n this.maxPingsPerSender = options.maxPingsPerSender ?? DEFAULT_MAX_PINGS;\r\n this.unregister = host.registerOverlay((ctx) => this.renderPings(ctx));\r\n }\r\n\r\n private now(): number {\r\n return performance.now();\r\n }\r\n\r\n /**\r\n * Applies a presence payload from `sender` (any opaque per-sender key, e.g.\r\n * the envelope `from`). Non-ping or malformed payloads are ignored and\r\n * reported as `false`, so hosts can feed every presence frame through.\r\n */\r\n apply(sender: string, data: unknown): boolean {\r\n if (this.disposed || !isPingPresence(data)) return false;\r\n let senderPings = this.pings.get(sender);\r\n if (!senderPings) {\r\n senderPings = [];\r\n this.pings.set(sender, senderPings);\r\n }\r\n senderPings.push({\r\n x: data.x,\r\n y: data.y,\r\n t: this.now(),\r\n color: data.color ?? this.color,\r\n durationMs: data.durationMs ?? this.durationMs,\r\n radius: data.radius ?? this.radius,\r\n });\r\n const excess = senderPings.length - this.maxPingsPerSender;\r\n if (excess > 0) senderPings.splice(0, excess);\r\n this.ensureAnimating();\r\n this.host.requestRender();\r\n return true;\r\n }\r\n\r\n /** Removes a sender's pings immediately (presence-leave/disconnect). */\r\n remove(sender: string): void {\r\n if (this.pings.delete(sender)) this.host.requestRender();\r\n }\r\n\r\n /** Removes every ping immediately. */\r\n clear(): void {\r\n if (this.pings.size === 0) return;\r\n this.pings.clear();\r\n this.host.requestRender();\r\n }\r\n\r\n /** Number of senders with a live (unexpired) ping. */\r\n get activeSenderCount(): number {\r\n return this.pings.size;\r\n }\r\n\r\n /** Unregisters the overlay and stops the animation loop. Idempotent. */\r\n dispose(): void {\r\n if (this.disposed) return;\r\n this.disposed = true;\r\n if (this.rafId !== null) {\r\n cancelAnimationFrame(this.rafId);\r\n this.rafId = null;\r\n }\r\n this.pings.clear();\r\n this.unregister?.();\r\n this.unregister = null;\r\n }\r\n\r\n private ensureAnimating(): void {\r\n if (this.rafId === null) {\r\n this.rafId = requestAnimationFrame(() => this.tick());\r\n }\r\n }\r\n\r\n private tick(): void {\r\n if (this.disposed) return;\r\n const now = this.now();\r\n for (const [sender, senderPings] of this.pings) {\r\n const live = senderPings.filter((ping) => now - ping.t < ping.durationMs);\r\n if (live.length === 0) {\r\n this.pings.delete(sender);\r\n } else {\r\n this.pings.set(sender, live);\r\n }\r\n }\r\n this.host.requestRender();\r\n this.rafId = this.pings.size > 0 ? requestAnimationFrame(() => this.tick()) : null;\r\n }\r\n\r\n private renderPings(ctx: CanvasRenderingContext2D): void {\r\n if (this.pings.size === 0) return;\r\n const now = this.now();\r\n for (const senderPings of this.pings.values()) {\r\n for (const ping of senderPings) {\r\n renderPingPulse(ctx, ping.x, ping.y, now - ping.t, {\r\n color: ping.color,\r\n durationMs: ping.durationMs,\r\n radius: ping.radius,\r\n });\r\n }\r\n }\r\n }\r\n}\r\n","import type { Point } from '../core/types';\n\n/** Label parity contract: local tool and remote overlay must format identically. */\nexport function formatMeasureLabel(feet: number): string {\n return `${Math.round(feet)} ft`;\n}\n\nexport interface MeasureRenderModel {\n readonly start: Point;\n readonly end: Point;\n readonly feet: number;\n readonly color: string;\n}\n\n/**\n * Draws one measurement — dashed segment, endpoint dots, rounded-pill distance\n * label — in world space. Shared by `MeasureTool.renderOverlay` and\n * `RemoteMeasureOverlay` so local and remote rulers stay pixel-identical.\n */\nexport function drawMeasurement(\n ctx: CanvasRenderingContext2D,\n m: MeasureRenderModel,\n opts: { alpha?: number } = {},\n): void {\n ctx.save();\n if (opts.alpha !== undefined) ctx.globalAlpha = opts.alpha;\n\n ctx.strokeStyle = m.color;\n ctx.setLineDash([8, 4]);\n ctx.lineWidth = 2;\n ctx.beginPath();\n ctx.moveTo(m.start.x, m.start.y);\n ctx.lineTo(m.end.x, m.end.y);\n ctx.stroke();\n\n ctx.setLineDash([]);\n ctx.fillStyle = m.color;\n const dotRadius = 4;\n ctx.beginPath();\n ctx.arc(m.start.x, m.start.y, dotRadius, 0, Math.PI * 2);\n ctx.fill();\n ctx.beginPath();\n ctx.arc(m.end.x, m.end.y, dotRadius, 0, Math.PI * 2);\n ctx.fill();\n\n const label = formatMeasureLabel(m.feet);\n const midX = (m.start.x + m.end.x) / 2;\n const midY = (m.start.y + m.end.y) / 2;\n ctx.font = '14px sans-serif';\n const metrics = ctx.measureText(label);\n const padX = 6;\n const padY = 4;\n const textH = 14;\n\n ctx.fillStyle = 'rgba(0, 0, 0, 0.75)';\n ctx.beginPath();\n ctx.roundRect(\n midX - metrics.width / 2 - padX,\n midY - textH / 2 - padY,\n metrics.width + padX * 2,\n textH + padY * 2,\n 4,\n );\n ctx.fill();\n\n ctx.fillStyle = '#FFFFFF';\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n ctx.fillText(label, midX, midY);\n\n ctx.restore();\n}\n","import type { Point } from '../core/types';\nimport type { MeasureEmission } from '../tools/measure-tool';\nimport type { OverlayRenderer } from './render-loop';\nimport { drawMeasurement } from './measure-render';\n\n/**\n * The wire shape of a shared-ruler presence payload. Presence data is untyped\n * on the wire, so hosts discriminate on `kind`; `isMeasurePresence` validates\n * a received payload before it reaches the overlay. Distance is\n * sender-authoritative: receivers render the payload's `feet`/`cells` and\n * never recompute from their own grid. Measurements are ephemeral by\n * contract: presence only — never elements, undo history, persisted canvas\n * state, or durable operations.\n */\nexport type MeasurePresence =\n | {\n readonly kind: 'measure';\n readonly start: Point;\n readonly end: Point;\n readonly cells: number;\n readonly feet: number;\n readonly color?: string;\n }\n | { readonly kind: 'measure'; readonly cleared: true };\n\nexport const MEASURE_PRESENCE_KIND = 'measure';\n\nfunction isFinitePoint(value: unknown): value is Point {\n if (typeof value !== 'object' || value === null) return false;\n const point = value as { x?: unknown; y?: unknown };\n return (\n typeof point.x === 'number' &&\n Number.isFinite(point.x) &&\n typeof point.y === 'number' &&\n Number.isFinite(point.y)\n );\n}\n\nexport function isMeasurePresence(data: unknown): data is MeasurePresence {\n if (typeof data !== 'object' || data === null) return false;\n const payload = data as {\n kind?: unknown;\n cleared?: unknown;\n start?: unknown;\n end?: unknown;\n cells?: unknown;\n feet?: unknown;\n color?: unknown;\n };\n if (payload.kind !== MEASURE_PRESENCE_KIND) return false;\n if ('cleared' in payload) return payload.cleared === true;\n if (!isFinitePoint(payload.start) || !isFinitePoint(payload.end)) return false;\n if (typeof payload.cells !== 'number' || !Number.isFinite(payload.cells)) return false;\n if (typeof payload.feet !== 'number' || !Number.isFinite(payload.feet)) return false;\n if (payload.color !== undefined && typeof payload.color !== 'string') return false;\n return true;\n}\n\n/** Builds the presence payload for one local `MeasureTool` emission. */\nexport function toMeasurePresence(emission: MeasureEmission | null): MeasurePresence {\n if (emission === null) return { kind: MEASURE_PRESENCE_KIND, cleared: true };\n return {\n kind: MEASURE_PRESENCE_KIND,\n start: emission.start,\n end: emission.end,\n cells: emission.cells,\n feet: emission.feet,\n color: emission.color,\n };\n}\n\n/** The two viewport capabilities the overlay needs; `Viewport` satisfies it. */\nexport interface RemoteMeasureOverlayHost {\n registerOverlay(draw: OverlayRenderer): () => void;\n requestRender(): void;\n}\n\nexport interface RemoteMeasureOverlayOptions {\n /** Style fallback when a payload omits `color`. Default `'#FF5722'`. */\n color?: string;\n /** Full-opacity hold after a cleared payload. Default `1500`. */\n holdMs?: number;\n /** Linear fade to 0 after the hold. Default `400`. */\n fadeMs?: number;\n /** Stale active entries are treated as cleared after this. Default `30000`. */\n maxAgeMs?: number;\n}\n\ninterface RemoteMeasurement {\n start: Point;\n end: Point;\n feet: number;\n color: string;\n /** Local receive time of the linger start; `null` while active. */\n clearedAt: number | null;\n expiryTimer: ReturnType<typeof setTimeout> | null;\n}\n\nconst DEFAULT_COLOR = '#FF5722';\nconst DEFAULT_HOLD_MS = 1500;\nconst DEFAULT_FADE_MS = 400;\nconst DEFAULT_MAX_AGE_MS = 30_000;\n\n/**\n * Renders remote shared-ruler measurements through the viewport overlay\n * registration, independent of the viewer's active tool. Entries are stamped\n * with local receive time (remote clocks are never trusted). A cleared\n * payload holds the final measurement for `holdMs`, fades over `fadeMs`, and\n * deletes; presence-leave (`remove`) deletes immediately. An active entry not\n * updated for `maxAgeMs` is expired by a timer — an idle map never renders,\n * so expiry cannot ride on the draw path. The overlay never touches elements,\n * history, or persisted state, and never moves the viewer's camera.\n */\nexport class RemoteMeasureOverlay {\n private readonly host: RemoteMeasureOverlayHost;\n private readonly color: string;\n private readonly holdMs: number;\n private readonly fadeMs: number;\n private readonly maxAgeMs: number;\n private readonly measurements = new Map<string, RemoteMeasurement>();\n private unregister: (() => void) | null;\n private rafId: number | null = null;\n private disposed = false;\n\n constructor(host: RemoteMeasureOverlayHost, options: RemoteMeasureOverlayOptions = {}) {\n this.host = host;\n this.color = options.color ?? DEFAULT_COLOR;\n this.holdMs = options.holdMs ?? DEFAULT_HOLD_MS;\n this.fadeMs = options.fadeMs ?? DEFAULT_FADE_MS;\n this.maxAgeMs = options.maxAgeMs ?? DEFAULT_MAX_AGE_MS;\n this.unregister = host.registerOverlay((ctx) => this.renderMeasurements(ctx));\n }\n\n private now(): number {\n return performance.now();\n }\n\n /**\n * Applies a presence payload from `sender` (any opaque per-sender key, e.g.\n * the envelope `from`). Non-measure or malformed payloads are ignored and\n * reported as `false`, so hosts can feed every presence frame through.\n */\n apply(sender: string, data: unknown): boolean {\n if (this.disposed || !isMeasurePresence(data)) return false;\n if ('cleared' in data) {\n this.beginLinger(sender);\n return true;\n }\n const existing = this.measurements.get(sender);\n if (existing?.expiryTimer != null) clearTimeout(existing.expiryTimer);\n this.measurements.set(sender, {\n start: data.start,\n end: data.end,\n feet: data.feet,\n color: data.color ?? this.color,\n clearedAt: null,\n expiryTimer: setTimeout(() => this.beginLinger(sender), this.maxAgeMs),\n });\n this.host.requestRender();\n return true;\n }\n\n /** Removes a sender's ruler immediately (presence-leave/disconnect). */\n remove(sender: string): void {\n const entry = this.measurements.get(sender);\n if (!entry) return;\n if (entry.expiryTimer != null) clearTimeout(entry.expiryTimer);\n this.measurements.delete(sender);\n this.host.requestRender();\n }\n\n /** Removes every ruler immediately. */\n clear(): void {\n if (this.measurements.size === 0) return;\n for (const entry of this.measurements.values()) {\n if (entry.expiryTimer != null) clearTimeout(entry.expiryTimer);\n }\n this.measurements.clear();\n this.host.requestRender();\n }\n\n /** Number of senders with a visible (active or lingering) ruler. */\n get activeSenderCount(): number {\n return this.measurements.size;\n }\n\n /** Unregisters the overlay, cancels timers, stops animating. Idempotent. */\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n for (const entry of this.measurements.values()) {\n if (entry.expiryTimer != null) clearTimeout(entry.expiryTimer);\n }\n this.measurements.clear();\n this.unregister?.();\n this.unregister = null;\n this.host.requestRender();\n }\n\n private beginLinger(sender: string): void {\n const entry = this.measurements.get(sender);\n if (!entry || entry.clearedAt !== null) return;\n if (entry.expiryTimer != null) {\n clearTimeout(entry.expiryTimer);\n entry.expiryTimer = null;\n }\n entry.clearedAt = this.now();\n this.ensureAnimating();\n this.host.requestRender();\n }\n\n private ensureAnimating(): void {\n if (this.rafId === null) {\n this.rafId = requestAnimationFrame(() => this.tick());\n }\n }\n\n private tick(): void {\n if (this.disposed) return;\n const now = this.now();\n let lingering = 0;\n for (const [sender, entry] of this.measurements) {\n if (entry.clearedAt === null) continue;\n if (now - entry.clearedAt >= this.holdMs + this.fadeMs) {\n this.measurements.delete(sender);\n } else {\n lingering += 1;\n }\n }\n this.host.requestRender();\n this.rafId = lingering > 0 ? requestAnimationFrame(() => this.tick()) : null;\n }\n\n private renderMeasurements(ctx: CanvasRenderingContext2D): void {\n if (this.measurements.size === 0) return;\n const now = this.now();\n for (const entry of this.measurements.values()) {\n let alpha = 1;\n if (entry.clearedAt !== null) {\n const fadeAge = now - entry.clearedAt - this.holdMs;\n if (fadeAge > 0) alpha = Math.max(0, 1 - fadeAge / this.fadeMs);\n }\n drawMeasurement(ctx, entry, { alpha });\n }\n }\n}\n","import type { Point } from '../core/types';\r\nimport type { PingEmission } from '../tools/ping-tool';\r\n\r\n/**\r\n * The one camera capability `PingInput` needs; `Camera` satisfies it. Screen\r\n * coordinates are element-local (the same space `Camera.screenToWorld`\r\n * expects).\r\n */\r\nexport interface PingInputHost {\r\n screenToWorld(screen: Point): Point;\r\n}\r\n\r\nexport interface PingInputOptions {\r\n /**\r\n * Opt-in for the long-press gesture. Off by default: a hidden hold-to-ping\r\n * gesture surprises users outside shared-canvas products, so hosts enable\r\n * it deliberately. The keyboard/programmatic paths (`pingAtPointer`,\r\n * `pingAt`) are always available. Default `false`.\r\n */\r\n longPressEnabled?: boolean;\r\n /** Hold duration before a still press pings. Default `600`. */\r\n longPressMs?: number;\r\n /** Maximum pointer travel while holding; moving further cancels. Default `8`. */\r\n slopPx?: number;\r\n /** Emission style forwarded to hosts; matches `PingTool` defaults. */\r\n color?: string;\r\n durationMs?: number;\r\n radius?: number;\r\n /**\r\n * Minimum interval between emitted pings, shared across the long-press and\r\n * keyboard/programmatic paths. Faster pings are dropped entirely. Default\r\n * `300`.\r\n */\r\n minIntervalMs?: number;\r\n /**\r\n * Host veto consulted at fire time on every path (e.g. return `false` while\r\n * a ping tool is active to avoid double pings). A veto does not consume the\r\n * rate-limit interval.\r\n */\r\n shouldPing?: () => boolean;\r\n}\r\n\r\ninterface PressState {\r\n pointerId: number;\r\n /** Element-local press position; the ping fires here, not where the pointer drifted. */\r\n x: number;\r\n y: number;\r\n timer: ReturnType<typeof setTimeout>;\r\n}\r\n\r\nconst DEFAULT_LONG_PRESS_MS = 600;\r\nconst DEFAULT_SLOP_PX = 8;\r\nconst DEFAULT_COLOR = '#ff3b30';\r\nconst DEFAULT_DURATION_MS = 1800;\r\nconst DEFAULT_RADIUS = 48;\r\nconst DEFAULT_MIN_INTERVAL_MS = 300;\r\n\r\n/**\r\n * Always-available ping input alongside the active tool: long-press-to-ping\r\n * plus keyboard/programmatic pings, independent of `PingTool`.\r\n *\r\n * `PingInput` is a passive observer by contract. Its DOM pointer listeners are\r\n * registered `passive: true` and it never calls `preventDefault`,\r\n * `stopPropagation`, or captures pointers, so the active tool, panning, and\r\n * pinch navigation behave exactly as if it were absent (with a pencil active,\r\n * a still hold pings AND the pencil still draws its dot). It also never\r\n * renders: hosts feed emissions into their own `RemotePingOverlay` under a\r\n * `'self'` sender key. Pings are ephemeral — no elements, no undo history, no\r\n * persisted state, no camera movement.\r\n *\r\n * The long-press gesture is opt-in via `longPressEnabled` (hosts whose users\r\n * would not expect hold-to-ping simply leave it off and keep the keyboard\r\n * paths). When enabled, a long-press arms on the first pointer down (mouse\r\n * primary button, touch, or pen), fires after `longPressMs` at the original\r\n * press position, and\r\n * cancels on movement past `slopPx`, a second pointer (two-finger\r\n * navigation), or pointer up/cancel/leave. Keyboard support is a capability,\r\n * not a binding: hosts call `pingAtPointer()` (last tracked hover position,\r\n * world-converted at call time) or `pingAt(world)` from their own shortcut\r\n * handling.\r\n */\r\nexport class PingInput {\r\n private readonly element: HTMLElement;\r\n private readonly host: PingInputHost;\r\n private longPressEnabled: boolean;\r\n private longPressMs: number;\r\n private slopPx: number;\r\n private color: string;\r\n private durationMs: number;\r\n private radius: number;\r\n private minIntervalMs: number;\r\n private shouldPing: (() => boolean) | undefined;\r\n\r\n private press: PressState | null = null;\r\n private readonly downPointers = new Set<number>();\r\n private lastPointerScreen: Point | null = null;\r\n private lastEmitAt = -Infinity;\r\n private disposed = false;\r\n private optionListeners = new Set<() => void>();\r\n private pingListeners = new Set<(emission: PingEmission) => void>();\r\n\r\n private readonly handlePointerDown = (e: PointerEvent): void => this.onPointerDown(e);\r\n private readonly handlePointerMove = (e: PointerEvent): void => this.onPointerMove(e);\r\n private readonly handlePointerUp = (e: PointerEvent): void => this.onPointerEnd(e);\r\n private readonly handlePointerCancel = (e: PointerEvent): void => this.onPointerEnd(e);\r\n private readonly handlePointerLeave = (e: PointerEvent): void => this.onPointerEnd(e);\r\n\r\n constructor(element: HTMLElement, host: PingInputHost, options: PingInputOptions = {}) {\r\n this.element = element;\r\n this.host = host;\r\n this.longPressEnabled = options.longPressEnabled ?? false;\r\n this.longPressMs = options.longPressMs ?? DEFAULT_LONG_PRESS_MS;\r\n this.slopPx = options.slopPx ?? DEFAULT_SLOP_PX;\r\n this.color = options.color ?? DEFAULT_COLOR;\r\n this.durationMs = options.durationMs ?? DEFAULT_DURATION_MS;\r\n this.radius = options.radius ?? DEFAULT_RADIUS;\r\n this.minIntervalMs = options.minIntervalMs ?? DEFAULT_MIN_INTERVAL_MS;\r\n this.shouldPing = options.shouldPing;\r\n\r\n const opts: AddEventListenerOptions = { passive: true };\r\n element.addEventListener('pointerdown', this.handlePointerDown, opts);\r\n element.addEventListener('pointermove', this.handlePointerMove, opts);\r\n element.addEventListener('pointerup', this.handlePointerUp, opts);\r\n element.addEventListener('pointercancel', this.handlePointerCancel, opts);\r\n element.addEventListener('pointerleave', this.handlePointerLeave, opts);\r\n }\r\n\r\n private now(): number {\r\n return performance.now();\r\n }\r\n\r\n getOptions(): PingInputOptions {\r\n return {\r\n longPressEnabled: this.longPressEnabled,\r\n longPressMs: this.longPressMs,\r\n slopPx: this.slopPx,\r\n color: this.color,\r\n durationMs: this.durationMs,\r\n radius: this.radius,\r\n minIntervalMs: this.minIntervalMs,\r\n ...(this.shouldPing ? { shouldPing: this.shouldPing } : {}),\r\n };\r\n }\r\n\r\n setOptions(options: PingInputOptions): void {\r\n if (options.longPressEnabled !== undefined) {\r\n this.longPressEnabled = options.longPressEnabled;\r\n if (!this.longPressEnabled) this.cancelPress();\r\n }\r\n if (options.longPressMs !== undefined) this.longPressMs = options.longPressMs;\r\n if (options.slopPx !== undefined) this.slopPx = options.slopPx;\r\n if (options.color !== undefined) this.color = options.color;\r\n if (options.durationMs !== undefined) this.durationMs = options.durationMs;\r\n if (options.radius !== undefined) this.radius = options.radius;\r\n if (options.minIntervalMs !== undefined) this.minIntervalMs = options.minIntervalMs;\r\n if (options.shouldPing !== undefined) this.shouldPing = options.shouldPing;\r\n for (const listener of this.optionListeners) listener();\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 /**\r\n * Subscribes to emitted pings. Listeners must not throw; a throwing\r\n * listener is isolated so it cannot break input handling or other\r\n * listeners.\r\n */\r\n onPing(listener: (emission: PingEmission) => void): () => void {\r\n this.pingListeners.add(listener);\r\n return () => this.pingListeners.delete(listener);\r\n }\r\n\r\n /**\r\n * Pings at the last tracked pointer position (hover moves and presses),\r\n * world-converted at call time. Returns `false` when no pointer has been\r\n * seen yet, the host vetoes, or the rate limit drops the ping.\r\n */\r\n pingAtPointer(): boolean {\r\n if (this.disposed || this.lastPointerScreen === null) return false;\r\n return this.emit(this.host.screenToWorld(this.lastPointerScreen));\r\n }\r\n\r\n /** Pings a world position directly. Same veto and rate limit as every path. */\r\n pingAt(world: Point): boolean {\r\n if (this.disposed) return false;\r\n return this.emit(world);\r\n }\r\n\r\n /** Removes all DOM listeners and cancels any pending press. Idempotent. */\r\n dispose(): void {\r\n if (this.disposed) return;\r\n this.disposed = true;\r\n this.cancelPress();\r\n this.downPointers.clear();\r\n this.element.removeEventListener('pointerdown', this.handlePointerDown);\r\n this.element.removeEventListener('pointermove', this.handlePointerMove);\r\n this.element.removeEventListener('pointerup', this.handlePointerUp);\r\n this.element.removeEventListener('pointercancel', this.handlePointerCancel);\r\n this.element.removeEventListener('pointerleave', this.handlePointerLeave);\r\n this.optionListeners.clear();\r\n this.pingListeners.clear();\r\n }\r\n\r\n private toLocal(e: PointerEvent): Point {\r\n const rect = this.element.getBoundingClientRect();\r\n return { x: e.clientX - rect.left, y: e.clientY - rect.top };\r\n }\r\n\r\n private onPointerDown(e: PointerEvent): void {\r\n const local = this.toLocal(e);\r\n this.lastPointerScreen = local;\r\n\r\n const hadPointers = this.downPointers.size > 0;\r\n this.downPointers.add(e.pointerId);\r\n if (hadPointers) {\r\n // A second pointer means navigation, not a press — and the new pointer\r\n // must not arm its own press while others are down.\r\n this.cancelPress();\r\n return;\r\n }\r\n if (!this.longPressEnabled) return;\r\n if (e.pointerType === 'mouse' && e.button !== 0) return;\r\n\r\n this.press = {\r\n pointerId: e.pointerId,\r\n x: local.x,\r\n y: local.y,\r\n timer: setTimeout(() => this.firePress(), this.longPressMs),\r\n };\r\n }\r\n\r\n private onPointerMove(e: PointerEvent): void {\r\n const local = this.toLocal(e);\r\n this.lastPointerScreen = local;\r\n if (this.press === null || e.pointerId !== this.press.pointerId) return;\r\n const dx = local.x - this.press.x;\r\n const dy = local.y - this.press.y;\r\n if (Math.hypot(dx, dy) > this.slopPx) this.cancelPress();\r\n }\r\n\r\n private onPointerEnd(e: PointerEvent): void {\r\n this.downPointers.delete(e.pointerId);\r\n if (this.press !== null && e.pointerId === this.press.pointerId) this.cancelPress();\r\n }\r\n\r\n private cancelPress(): void {\r\n if (this.press === null) return;\r\n clearTimeout(this.press.timer);\r\n this.press = null;\r\n }\r\n\r\n private firePress(): void {\r\n if (this.press === null) return;\r\n const screen = { x: this.press.x, y: this.press.y };\r\n this.press = null;\r\n // Convert at fire time so the ping lands where the held pointer points now.\r\n this.emit(this.host.screenToWorld(screen));\r\n }\r\n\r\n private emit(world: Point): boolean {\r\n if (this.shouldPing && !this.shouldPing()) return false;\r\n const t = this.now();\r\n if (t - this.lastEmitAt < this.minIntervalMs) return false;\r\n this.lastEmitAt = t;\r\n const emission: PingEmission = {\r\n x: world.x,\r\n y: world.y,\r\n color: this.color,\r\n durationMs: this.durationMs,\r\n radius: this.radius,\r\n };\r\n for (const listener of this.pingListeners) {\r\n try {\r\n listener(emission);\r\n } catch {\r\n // A throwing host listener must not break input handling.\r\n }\r\n }\r\n return true;\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' || el.locked || (ctx.isLayerLocked?.(el.layerId) ?? false))\r\n 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' || el.locked || (ctx.isLayerLocked?.(el.layerId) ?? false)) 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' || el.locked || (ctx.isLayerLocked?.(el.layerId) ?? false)) {\r\n return null;\r\n }\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\r\nexport function renderArrowHoverHandle(\r\n canvasCtx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n zoom: number,\r\n): void {\r\n const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);\r\n const radius = HANDLE_RADIUS / zoom;\r\n canvasCtx.fillStyle = '#2196F3';\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.lineWidth = 1.5 / zoom;\r\n canvasCtx.beginPath();\r\n canvasCtx.arc(mid.x, mid.y, radius, 0, Math.PI * 2);\r\n canvasCtx.fill();\r\n canvasCtx.stroke();\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 templateAimKnob(\r\n el: CanvasElement,\r\n zoom: number,\r\n): { origin: Point; knob: Point } | null {\r\n if (el.type !== 'template') return null;\r\n if (\r\n el.templateShape !== 'cone' &&\r\n el.templateShape !== 'line' &&\r\n el.templateShape !== 'rectangle'\r\n )\r\n return null;\r\n const gap = ROTATE_HANDLE_OFFSET / zoom;\r\n const dist = el.radius + gap;\r\n const origin = el.position;\r\n return {\r\n origin,\r\n knob: {\r\n x: origin.x + dist * Math.cos(el.angle),\r\n y: origin.y + dist * Math.sin(el.angle),\r\n },\r\n };\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: {\r\n selectedIds: string[];\r\n store: ElementStore;\r\n zoom: number;\r\n isLayerLocked?: (layerId: string) => boolean;\r\n },\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 const locked = el.locked || (p.isLayerLocked?.(el.layerId) ?? false);\r\n\r\n if (el.type === 'arrow') {\r\n if (!locked) 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 if (!locked) {\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 }\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 if (el.templateShape === 'rectangle') {\r\n if (p.selectedIds.length === 1) {\r\n const cos = Math.cos(el.angle);\r\n const sin = Math.sin(el.angle);\r\n const halfW = (el.width ?? 0) / 2;\r\n const pts: [number, number][] = [\r\n [el.position.x + el.radius * cos, el.position.y + el.radius * sin],\r\n [\r\n el.position.x + (el.radius / 2) * cos + halfW * -sin,\r\n el.position.y + (el.radius / 2) * sin + halfW * cos,\r\n ],\r\n ];\r\n for (const [hx, hy] of pts) {\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 }\r\n }\r\n } else {\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 }\r\n ctx.setLineDash([4 / zoom, 4 / zoom]);\r\n\r\n if (\r\n p.selectedIds.length === 1 &&\r\n (el.templateShape === 'cone' ||\r\n el.templateShape === 'line' ||\r\n el.templateShape === 'rectangle')\r\n ) {\r\n const aim = templateAimKnob(el, zoom);\r\n if (aim) {\r\n ctx.beginPath();\r\n ctx.moveTo(aim.origin.x, aim.origin.y);\r\n ctx.lineTo(aim.knob.x, aim.knob.y);\r\n ctx.stroke();\r\n\r\n ctx.setLineDash([]);\r\n ctx.fillStyle = '#ffffff';\r\n ctx.beginPath();\r\n ctx.arc(aim.knob.x, aim.knob.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\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 templateAimKnob,\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 (\r\n !el ||\r\n el.type !== 'shape' ||\r\n el.shape !== 'line' ||\r\n el.locked ||\r\n (ctx.isLayerLocked?.(el.layerId) ?? false)\r\n )\r\n 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 if (el.templateShape === 'rectangle') 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 hitTestTemplateAimHandle(\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) return null;\r\n const knob = templateAimKnob(el, ctx.camera.zoom);\r\n if (!knob) return null;\r\n const r = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / ctx.camera.zoom;\r\n const dx = world.x - knob.knob.x;\r\n const dy = world.y - knob.knob.y;\r\n return dx * dx + dy * dy <= r * r ? { elementId: id } : null;\r\n}\r\n\r\nexport function hitTestRectangleLengthHandle(\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 || el.type !== 'template' || el.templateShape !== 'rectangle') return null;\r\n const zoom = ctx.camera.zoom;\r\n const r = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / zoom;\r\n const hx = el.position.x + el.radius * Math.cos(el.angle);\r\n const hy = el.position.y + el.radius * Math.sin(el.angle);\r\n const dx = world.x - hx;\r\n const dy = world.y - hy;\r\n return dx * dx + dy * dy <= r * r ? { elementId: id } : null;\r\n}\r\n\r\nexport function hitTestRectangleWidthHandle(\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 || el.type !== 'template' || el.templateShape !== 'rectangle') return null;\r\n const zoom = ctx.camera.zoom;\r\n const r = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / zoom;\r\n const cos = Math.cos(el.angle);\r\n const sin = Math.sin(el.angle);\r\n const halfW = (el.width ?? 0) / 2;\r\n const hx = el.position.x + (el.radius / 2) * cos + halfW * -sin;\r\n const hy = el.position.y + (el.radius / 2) * sin + halfW * cos;\r\n const dx = world.x - hx;\r\n const dy = world.y - hy;\r\n return dx * dx + dy * dy <= r * r ? { elementId: id } : 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 lockAspect: 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 (lockAspect && 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 lockAspect: 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 (lockAspect && 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\r\nexport function computeRectangleLengthResize(\r\n el: TemplateElement,\r\n world: Point,\r\n opts: TemplateResizeOptions,\r\n): Record<string, unknown> | null {\r\n const cos = Math.cos(el.angle);\r\n const sin = Math.sin(el.angle);\r\n let len = (world.x - el.position.x) * cos + (world.y - el.position.y) * sin;\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 len = Math.max(snapUnit, Math.round(len / snapUnit) * snapUnit);\r\n }\r\n len = Math.max(MIN_ELEMENT_SIZE, len);\r\n const updates: Record<string, unknown> = { radius: len };\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 = (len / snapUnit) * el.feetPerCell;\r\n }\r\n return updates;\r\n}\r\n\r\nexport function computeRectangleWidthResize(\r\n el: TemplateElement,\r\n world: Point,\r\n opts: TemplateResizeOptions,\r\n): Record<string, unknown> | null {\r\n const cos = Math.cos(el.angle);\r\n const sin = Math.sin(el.angle);\r\n const perp = Math.abs(-(world.x - el.position.x) * sin + (world.y - el.position.y) * cos);\r\n let width = perp * 2;\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 width = Math.max(snapUnit, Math.round(width / snapUnit) * snapUnit);\r\n }\r\n width = Math.max(MIN_ELEMENT_SIZE, width);\r\n return { width };\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 renderArrowHoverHandle,\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 hitTestTemplateAimHandle,\r\n hitTestRectangleLengthHandle,\r\n hitTestRectangleWidthHandle,\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 {\r\n computeResize,\r\n computeRotatedResize,\r\n computeTemplateResize,\r\n computeRectangleLengthResize,\r\n computeRectangleWidthResize,\r\n} 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: 'aiming-template'; elementId: string }\r\n | { type: 'resizing-rect-length'; elementId: string }\r\n | { type: 'resizing-rect-width'; 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 rectLengthHit = hitTestRectangleLengthHandle(world, ctx, this._selectedIds);\r\n if (rectLengthHit) {\r\n this.mode = { type: 'resizing-rect-length', elementId: rectLengthHit.elementId };\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n const rectWidthHit = hitTestRectangleWidthHandle(world, ctx, this._selectedIds);\r\n if (rectWidthHit) {\r\n this.mode = { type: 'resizing-rect-width', elementId: rectWidthHit.elementId };\r\n ctx.requestRender();\r\n return;\r\n }\r\n\r\n const aimHit = hitTestTemplateAimHandle(world, ctx, this._selectedIds);\r\n if (aimHit) {\r\n this.mode = { type: 'aiming-template', elementId: aimHit.elementId };\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 (\r\n el &&\r\n el.type === 'shape' &&\r\n el.shape === 'line' &&\r\n !el.locked &&\r\n !(ctx.isLayerLocked?.(el.layerId) ?? false)\r\n ) {\r\n ctx.store.update(el.id, lineFromEndpoints(this.mode.fixed, world));\r\n ctx.requestRender();\r\n }\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 === 'aiming-template') {\r\n const el = ctx.store.getById(this.mode.elementId);\r\n if (el && el.type === 'template' && !el.locked) {\r\n let a = Math.atan2(world.y - el.position.y, world.x - el.position.x);\r\n if (state.shiftKey) {\r\n const snap = ctx.gridType === 'hex' ? Math.PI / 3 : ROTATE_SNAP;\r\n a = Math.round(a / snap) * snap;\r\n }\r\n ctx.store.update(this.mode.elementId, { angle: normalizeAngle(a) });\r\n ctx.requestRender();\r\n }\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'resizing-rect-length' || this.mode.type === 'resizing-rect-width') {\r\n ctx.setCursor?.(this.mode.type === 'resizing-rect-length' ? 'ew-resize' : 'ns-resize');\r\n const el = ctx.store.getById(this.mode.elementId);\r\n if (el && el.type === 'template' && !el.locked) {\r\n const opts = { snapToGrid: ctx.snapToGrid, gridSize: ctx.gridSize, gridType: ctx.gridType };\r\n const patch =\r\n this.mode.type === 'resizing-rect-length'\r\n ? computeRectangleLengthResize(el, world, opts)\r\n : computeRectangleWidthResize(el, world, opts);\r\n if (patch) {\r\n ctx.store.update(this.mode.elementId, patch);\r\n ctx.requestRender();\r\n }\r\n }\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 isLayerLocked: this.ctx.isLayerLocked,\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?.type === 'arrow') {\r\n canvasCtx.save();\r\n canvasCtx.globalAlpha = 0.35;\r\n canvasCtx.setLineDash([]);\r\n renderArrowHoverHandle(canvasCtx, el, this.ctx.camera.zoom);\r\n canvasCtx.restore();\r\n } else 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 (hitTestRectangleLengthHandle(world, ctx, this._selectedIds)) {\r\n ctx.setCursor?.('ew-resize');\r\n return null;\r\n }\r\n if (hitTestRectangleWidthHandle(world, ctx, this._selectedIds)) {\r\n ctx.setCursor?.('ns-resize');\r\n return null;\r\n }\r\n\r\n if (hitTestTemplateAimHandle(world, ctx, this._selectedIds)) {\r\n ctx.setCursor?.('grab');\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 lockAspect = shiftKey !== (el.type === 'image');\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 lockAspect,\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 lockAspect,\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 { ArrowStrokeStyle, 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 strokeStyle?: ArrowStrokeStyle;\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 strokeStyle: ArrowStrokeStyle;\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 this.strokeStyle = options.strokeStyle ?? 'solid';\r\n }\r\n\r\n getOptions(): ArrowToolOptions {\r\n return { color: this.color, width: this.width, strokeStyle: this.strokeStyle };\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 if (options.strokeStyle !== undefined) this.strokeStyle = options.strokeStyle;\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 strokeStyle: this.strokeStyle,\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';\nimport type { HexOrientation } from '../elements/types';\nimport type { Tool, ToolContext, PointerState } from './types';\nimport { snapPoint, snapToHexCenter } from '../core/snap';\nimport { getHexDistance } from '../elements/hex-fill';\nimport { drawMeasurement } from '../canvas/measure-render';\n\nexport interface MeasureToolOptions {\n feetPerCell?: number;\n color?: string;\n}\n\nexport interface Measurement {\n start: Point;\n end: Point;\n worldDistance: number;\n cells: number;\n feet: number;\n}\n\n/**\n * A raf-coalesced snapshot of the in-progress measurement — the outgoing\n * side of a shared live ruler. Emissions carry world coordinates, derived\n * distance, and the tool's current color so a host can forward them as\n * ephemeral presence without duplicating the tool's input handling.\n * Ephemeral by contract: presence only — never elements, history, or\n * persisted state.\n */\nexport interface MeasureEmission {\n readonly start: Point;\n readonly end: Point;\n readonly worldDistance: number;\n readonly cells: number;\n readonly feet: number;\n readonly color: string;\n}\n\nexport class MeasureTool implements Tool {\n readonly name = 'measure';\n private start: Point | null = null;\n private end: Point | null = null;\n private gridSize = 1;\n private gridType: 'square' | 'hex' | undefined;\n private hexOrientation: HexOrientation | undefined;\n private feetPerCell: number;\n private color: string;\n private optionListeners = new Set<() => void>();\n private measurementListeners = new Set<(emission: MeasureEmission | null) => void>();\n private emissionRafId: number | null = null;\n\n constructor(options: MeasureToolOptions = {}) {\n this.feetPerCell = options.feetPerCell ?? 5;\n this.color = options.color ?? '#FF5722';\n }\n\n getOptions(): MeasureToolOptions {\n return { feetPerCell: this.feetPerCell, color: this.color };\n }\n\n setOptions(options: MeasureToolOptions): void {\n if (options.feetPerCell !== undefined) this.feetPerCell = options.feetPerCell;\n if (options.color !== undefined) this.color = options.color;\n this.notifyOptionsChange();\n }\n\n onOptionsChange(listener: () => void): () => void {\n this.optionListeners.add(listener);\n return () => this.optionListeners.delete(listener);\n }\n\n /**\n * Subscribes to raf-coalesced measurement snapshots. While a measurement is\n * in progress, listeners receive at most one snapshot per animation frame\n * carrying the latest state; `null` is delivered synchronously when the\n * measurement clears (pointer-up or deactivate). Emissions are ephemeral by\n * contract: presence only — never elements, history, or persisted state.\n */\n onMeasurement(listener: (emission: MeasureEmission | null) => void): () => void {\n this.measurementListeners.add(listener);\n return () => this.measurementListeners.delete(listener);\n }\n\n onPointerDown(state: PointerState, ctx: ToolContext): void {\n this.gridSize = ctx.gridSize ?? 1;\n this.gridType = ctx.gridType;\n this.hexOrientation = ctx.hexOrientation;\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\n this.start = this.snapToGrid(world, ctx);\n this.end = { ...this.start };\n this.scheduleEmission();\n }\n\n onPointerMove(state: PointerState, ctx: ToolContext): void {\n if (!this.start) return;\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\n this.end = this.snapToGrid(world, ctx);\n ctx.requestRender();\n this.scheduleEmission();\n }\n\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\n if (!this.start) return;\n this.start = null;\n this.end = null;\n ctx.requestRender();\n this.emitClear();\n }\n\n onDeactivate(_ctx: ToolContext): void {\n const wasActive = this.start !== null;\n this.start = null;\n this.end = null;\n if (wasActive) this.emitClear();\n }\n\n getMeasurement(): Measurement | null {\n if (!this.start || !this.end) return null;\n const dx = this.end.x - this.start.x;\n const dy = this.end.y - this.start.y;\n const worldDistance = Math.sqrt(dx * dx + dy * dy);\n\n let cells: number;\n if (this.gridType === 'hex' && this.hexOrientation) {\n cells = getHexDistance(this.start, this.end, this.gridSize, this.hexOrientation);\n } else {\n const snapUnit = this.gridSize;\n cells = worldDistance / snapUnit;\n }\n\n const feet = cells * this.feetPerCell;\n return {\n start: { ...this.start },\n end: { ...this.end },\n worldDistance,\n cells,\n feet,\n };\n }\n\n renderOverlay(ctx: CanvasRenderingContext2D): void {\n const m = this.getMeasurement();\n if (!m) return;\n drawMeasurement(ctx, { start: m.start, end: m.end, feet: m.feet, color: this.color });\n }\n\n private snapToGrid(point: Point, ctx: ToolContext): Point {\n if (!ctx.gridSize) return point;\n if (ctx.gridType === 'hex' && ctx.hexOrientation) {\n return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);\n }\n if (ctx.gridType === 'square') {\n return snapPoint(point, ctx.gridSize);\n }\n if (ctx.snapToGrid) {\n return snapPoint(point, ctx.gridSize);\n }\n return point;\n }\n\n private notifyOptionsChange(): void {\n for (const listener of this.optionListeners) listener();\n }\n\n private scheduleEmission(): void {\n if (this.measurementListeners.size === 0) return;\n if (this.emissionRafId !== null) return;\n this.emissionRafId = requestAnimationFrame(() => {\n this.emissionRafId = null;\n const m = this.getMeasurement();\n if (!m) return; // cleared before the frame; the sync null already went out\n this.emit({ ...m, color: this.color });\n });\n }\n\n private emitClear(): void {\n if (this.emissionRafId !== null) {\n cancelAnimationFrame(this.emissionRafId);\n this.emissionRafId = null;\n }\n if (this.measurementListeners.size === 0) return;\n this.emit(null);\n }\n\n private emit(emission: MeasureEmission | null): void {\n for (const listener of this.measurementListeners) {\n try {\n listener(emission);\n } catch {\n // A throwing host listener must not break measurement input.\n }\n }\n }\n}\n","import type { Point } from '../core/types';\r\nimport type { TemplateShape, HexOrientation, TemplateRenderStyle } 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 getHexCellsInRectangle,\r\n drawHexPath,\r\n} from '../elements/hex-fill';\r\nimport { renderTemplateFeetLabel } from '../elements/renderers/template-measure';\r\n\r\nconst MIN_RECT_WIDTH = 20;\r\n\r\nexport function defaultRectWidth(radius: number, scaleUnit: number): number {\r\n if (scaleUnit > 0) return scaleUnit; // one grid cell\r\n return Math.max(MIN_RECT_WIDTH, radius * 0.25);\r\n}\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 renderStyle?: TemplateRenderStyle;\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 feetScaleUnit = 0;\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 renderStyle: TemplateRenderStyle;\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 this.renderStyle = options.renderStyle ?? 'cells';\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 renderStyle: this.renderStyle,\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 if (options.renderStyle !== undefined) this.renderStyle = options.renderStyle;\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 this.feetScaleUnit =\r\n ctx.gridSize && ctx.gridSize > 0\r\n ? ctx.gridType === 'hex'\r\n ? Math.sqrt(3) * ctx.gridSize\r\n : ctx.gridSize\r\n : 0;\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 const width =\r\n this.templateShape === 'rectangle' ? defaultRectWidth(radius, this.feetScaleUnit) : undefined;\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 width,\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 renderStyle: this.renderStyle,\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 && this.renderStyle !== 'geometric') {\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 case 'rectangle': {\r\n const halfW = defaultRectWidth(radius, this.feetScaleUnit) / 2;\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 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 this.drawFeetLabel(ctx, radius);\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 case 'rectangle': {\r\n const widthCells = defaultRectWidth(radius, this.feetScaleUnit) / snapUnit;\r\n hexCells = getHexCellsInRectangle(\r\n center,\r\n angle,\r\n radiusCells,\r\n widthCells,\r\n cellSize,\r\n orientation,\r\n );\r\n break;\r\n }\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 this.templateShape === 'rectangle'\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 this.drawFeetLabel(ctx, radius);\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 drawFeetLabel(ctx: CanvasRenderingContext2D, radius: number): void {\r\n const feet = this.feetScaleUnit > 0 ? (radius / this.feetScaleUnit) * this.feetPerCell : 0;\r\n renderTemplateFeetLabel(ctx, {\r\n position: this.origin,\r\n radius,\r\n angle: this.computeAngle(),\r\n templateShape: this.templateShape,\r\n feet,\r\n color: this.strokeColor,\r\n });\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 { Tool, ToolContext, PointerState } from './types';\r\nimport type { Point } from '../core/types';\r\n\r\nexport interface LaserToolOptions {\r\n name?: string;\r\n color?: string;\r\n width?: number;\r\n fadeMs?: number;\r\n}\r\n\r\n/**\r\n * A coalesced batch of locally drawn trail points, flushed at most once per\r\n * animation frame — the outgoing side of a shared laser pointer. Emissions\r\n * carry world coordinates and the tool's current style so a host can forward\r\n * them as ephemeral presence without duplicating the tool's input handling.\r\n */\r\nexport interface LaserTrailEmission {\r\n /** World-space points recorded since the previous emission, oldest first. */\r\n readonly points: readonly Point[];\r\n readonly color: string;\r\n readonly width: number;\r\n readonly fadeMs: number;\r\n}\r\n\r\ninterface TrailPoint {\r\n x: number;\r\n y: number;\r\n t: number;\r\n}\r\n\r\nconst DEFAULT_COLOR = '#ff3b30';\r\nconst DEFAULT_WIDTH = 4;\r\nconst DEFAULT_FADE_MS = 1200;\r\n\r\nexport class LaserTool implements Tool {\r\n readonly name: string;\r\n private color: string;\r\n private width: number;\r\n private fadeMs: number;\r\n private trail: TrailPoint[] = [];\r\n private rafId: number | null = null;\r\n private drawing = false;\r\n private optionListeners = new Set<() => void>();\r\n private trailListeners = new Set<(emission: LaserTrailEmission) => void>();\r\n private pendingEmission: Point[] = [];\r\n\r\n constructor(options: LaserToolOptions = {}) {\r\n this.name = options.name ?? 'laser';\r\n this.color = options.color ?? DEFAULT_COLOR;\r\n this.width = options.width ?? DEFAULT_WIDTH;\r\n this.fadeMs = options.fadeMs ?? DEFAULT_FADE_MS;\r\n }\r\n\r\n private now(): number {\r\n return performance.now();\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 if (this.rafId !== null) {\r\n cancelAnimationFrame(this.rafId);\r\n this.rafId = null;\r\n }\r\n this.trail = [];\r\n this.drawing = false;\r\n this.pendingEmission = [];\r\n ctx.setCursor?.('default');\r\n ctx.requestRender();\r\n }\r\n\r\n getOptions(): LaserToolOptions {\r\n return {\r\n name: this.name,\r\n color: this.color,\r\n width: this.width,\r\n fadeMs: this.fadeMs,\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 /**\r\n * Subscribes to coalesced trail emissions. Points recorded by pointer input\r\n * are batched and delivered at most once per animation frame, keeping\r\n * outgoing presence packets small. Listeners must not throw; a throwing\r\n * listener is isolated so it cannot stall the fade loop.\r\n */\r\n onTrail(listener: (emission: LaserTrailEmission) => void): () => void {\r\n this.trailListeners.add(listener);\r\n return () => this.trailListeners.delete(listener);\r\n }\r\n\r\n setOptions(options: LaserToolOptions): 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.fadeMs !== undefined) this.fadeMs = options.fadeMs;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.drawing = true;\r\n this.recordPoint(state, ctx);\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.recordPoint(state, ctx);\r\n }\r\n\r\n private recordPoint(state: PointerState, ctx: ToolContext): void {\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.trail.push({ x: world.x, y: world.y, t: this.now() });\r\n if (this.trailListeners.size > 0) {\r\n this.pendingEmission.push({ x: world.x, y: world.y });\r\n }\r\n this.ensureAnimating(ctx);\r\n }\r\n\r\n onPointerUp(_state: PointerState, _ctx: ToolContext): void {\r\n this.drawing = false;\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (this.trail.length < 2) return;\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.color;\r\n ctx.lineWidth = this.width;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n\r\n const now = this.now();\r\n for (let i = 0; i < this.trail.length - 1; i++) {\r\n const a = this.trail[i];\r\n const b = this.trail[i + 1];\r\n if (!a || !b) continue;\r\n const age = now - b.t;\r\n ctx.globalAlpha = Math.max(0, 1 - age / this.fadeMs);\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 }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private ensureAnimating(ctx: ToolContext): void {\r\n if (this.rafId === null) {\r\n this.rafId = requestAnimationFrame(() => this.tick(ctx));\r\n }\r\n }\r\n\r\n private flushEmission(): void {\r\n if (this.pendingEmission.length === 0) return;\r\n const emission: LaserTrailEmission = {\r\n points: this.pendingEmission,\r\n color: this.color,\r\n width: this.width,\r\n fadeMs: this.fadeMs,\r\n };\r\n this.pendingEmission = [];\r\n for (const listener of this.trailListeners) {\r\n try {\r\n listener(emission);\r\n } catch {\r\n // A throwing host listener must not stall the fade/emission loop.\r\n }\r\n }\r\n }\r\n\r\n private tick(ctx: ToolContext): void {\r\n this.flushEmission();\r\n const cutoff = this.now() - this.fadeMs;\r\n this.trail = this.trail.filter((p) => p.t >= cutoff);\r\n if (this.trail.length > 0) {\r\n ctx.requestRender();\r\n this.rafId = requestAnimationFrame(() => this.tick(ctx));\r\n } else {\r\n ctx.requestRender();\r\n this.rafId = null;\r\n }\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 { Tool, ToolContext, PointerState } from './types';\r\nimport { renderPingPulse } from '../canvas/ping-pulse';\r\n\r\nexport interface PingToolOptions {\r\n name?: string;\r\n color?: string;\r\n /** Total pulse animation length in milliseconds. */\r\n durationMs?: number;\r\n /** Maximum ripple radius in world units. */\r\n radius?: number;\r\n /**\r\n * Minimum interval between emitted pings. Taps arriving faster are ignored\r\n * entirely (no local pulse, no emission), so rapid-fire pings cannot starve\r\n * durable sync traffic.\r\n */\r\n minIntervalMs?: number;\r\n}\r\n\r\n/**\r\n * One emitted ping — the outgoing side of a shared \"look here\" marker.\r\n * Emissions carry the world position and the tool's current style so a host\r\n * can forward them as ephemeral presence without duplicating input handling.\r\n */\r\nexport interface PingEmission {\r\n /** World-space ping position. */\r\n readonly x: number;\r\n readonly y: number;\r\n readonly color: string;\r\n readonly durationMs: number;\r\n readonly radius: number;\r\n}\r\n\r\ninterface LocalPing {\r\n x: number;\r\n y: number;\r\n t: number;\r\n}\r\n\r\nconst DEFAULT_COLOR = '#ff3b30';\r\nconst DEFAULT_DURATION_MS = 1800;\r\nconst DEFAULT_RADIUS = 48;\r\nconst DEFAULT_MIN_INTERVAL_MS = 300;\r\n\r\n/**\r\n * Tap or click to ping a world position: a short expanding-pulse animation is\r\n * rendered locally and one `PingEmission` is delivered to `onPing` listeners\r\n * per accepted tap. Pings are ephemeral by contract: they never create\r\n * elements, enter undo history, or touch persisted canvas state — hosts\r\n * forward emissions as presence only.\r\n */\r\nexport class PingTool implements Tool {\r\n readonly name: string;\r\n private color: string;\r\n private durationMs: number;\r\n private radius: number;\r\n private minIntervalMs: number;\r\n private pings: LocalPing[] = [];\r\n private lastEmitAt = -Infinity;\r\n private rafId: number | null = null;\r\n private optionListeners = new Set<() => void>();\r\n private pingListeners = new Set<(emission: PingEmission) => void>();\r\n\r\n constructor(options: PingToolOptions = {}) {\r\n this.name = options.name ?? 'ping';\r\n this.color = options.color ?? DEFAULT_COLOR;\r\n this.durationMs = options.durationMs ?? DEFAULT_DURATION_MS;\r\n this.radius = options.radius ?? DEFAULT_RADIUS;\r\n this.minIntervalMs = options.minIntervalMs ?? DEFAULT_MIN_INTERVAL_MS;\r\n }\r\n\r\n private now(): number {\r\n return performance.now();\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 if (this.rafId !== null) {\r\n cancelAnimationFrame(this.rafId);\r\n this.rafId = null;\r\n }\r\n this.pings = [];\r\n ctx.setCursor?.('default');\r\n ctx.requestRender();\r\n }\r\n\r\n getOptions(): PingToolOptions {\r\n return {\r\n name: this.name,\r\n color: this.color,\r\n durationMs: this.durationMs,\r\n radius: this.radius,\r\n minIntervalMs: this.minIntervalMs,\r\n };\r\n }\r\n\r\n setOptions(options: PingToolOptions): void {\r\n if (options.color !== undefined) this.color = options.color;\r\n if (options.durationMs !== undefined) this.durationMs = options.durationMs;\r\n if (options.radius !== undefined) this.radius = options.radius;\r\n if (options.minIntervalMs !== undefined) this.minIntervalMs = options.minIntervalMs;\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 /**\r\n * Subscribes to accepted pings. Listeners must not throw; a throwing\r\n * listener is isolated so it cannot break the tap handling or other\r\n * listeners.\r\n */\r\n onPing(listener: (emission: PingEmission) => void): () => void {\r\n this.pingListeners.add(listener);\r\n return () => this.pingListeners.delete(listener);\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n const t = this.now();\r\n if (t - this.lastEmitAt < this.minIntervalMs) return;\r\n this.lastEmitAt = t;\r\n\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.pings.push({ x: world.x, y: world.y, t });\r\n const emission: PingEmission = {\r\n x: world.x,\r\n y: world.y,\r\n color: this.color,\r\n durationMs: this.durationMs,\r\n radius: this.radius,\r\n };\r\n for (const listener of this.pingListeners) {\r\n try {\r\n listener(emission);\r\n } catch {\r\n // A throwing host listener must not break tap handling.\r\n }\r\n }\r\n this.ensureAnimating(ctx);\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\r\n // Pings are discrete taps; dragging does nothing.\r\n }\r\n\r\n onPointerUp(_state: PointerState, _ctx: ToolContext): void {\r\n // Nothing to finish; the ping fired on pointer down.\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (this.pings.length === 0) return;\r\n const now = this.now();\r\n for (const ping of this.pings) {\r\n renderPingPulse(ctx, ping.x, ping.y, now - ping.t, {\r\n color: this.color,\r\n durationMs: this.durationMs,\r\n radius: this.radius,\r\n });\r\n }\r\n }\r\n\r\n private ensureAnimating(ctx: ToolContext): void {\r\n if (this.rafId === null) {\r\n this.rafId = requestAnimationFrame(() => this.tick(ctx));\r\n }\r\n }\r\n\r\n private tick(ctx: ToolContext): void {\r\n const cutoff = this.now() - this.durationMs;\r\n this.pings = this.pings.filter((ping) => ping.t > cutoff);\r\n ctx.requestRender();\r\n this.rafId = this.pings.length > 0 ? requestAnimationFrame(() => this.tick(ctx)) : null;\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":["counter","center","minX","minY","minX","minY","center","n","center","cache","center","n","center","center","cache","ARROWHEAD_LENGTH","ARROWHEAD_ANGLE","ARROW_LABEL_FONT_SIZE","WIDTH_QUANTUM","d","center","unionBounds","center","moved","unionBounds","center","n","DEFAULT_COLOR","isFinitePoint","DEFAULT_COLOR","DEFAULT_FADE_MS","DEFAULT_COLOR","DEFAULT_DURATION_MS","DEFAULT_RADIUS","DEFAULT_RADIUS","center","HANDLE_HIT_PADDING","center","HANDLE_HIT_PADDING","center","BIND_THRESHOLD","center","DEFAULT_COLOR","DEFAULT_WIDTH","DEFAULT_FADE_MS","DEFAULT_COLOR","DEFAULT_DURATION_MS","DEFAULT_RADIUS","DEFAULT_MIN_INTERVAL_MS"]}
|