@fieldnotes/core 0.26.0 → 0.27.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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/snap.ts","../src/elements/note-sanitizer.ts","../src/core/state-serializer.ts","../src/core/auto-save.ts","../src/canvas/camera.ts","../src/canvas/input-filter.ts","../src/elements/create-id.ts","../src/core/geometry.ts","../src/elements/arrow-geometry.ts","../src/elements/element-bounds.ts","../src/elements/bounds.ts","../src/canvas/keyboard-actions.ts","../src/canvas/shortcut-map.ts","../src/canvas/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/arrow-render-cache.ts","../src/elements/arrow-binding.ts","../src/elements/grid-renderer.ts","../src/elements/hex-fill.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/tools/tool-manager.ts","../src/history/history-stack.ts","../src/history/commands.ts","../src/history/layer-commands.ts","../src/history/history-recorder.ts","../src/canvas/note-canvas-renderer.ts","../src/canvas/export-image.ts","../src/layers/layer-manager.ts","../src/canvas/interact-mode.ts","../src/canvas/double-tap-detector.ts","../src/canvas/dom-node-manager.ts","../src/canvas/render-stats.ts","../src/canvas/render-loop.ts","../src/canvas/layer-cache.ts","../src/canvas/margin-viewport.ts","../src/canvas/viewport.ts","../src/tools/hand-tool.ts","../src/tools/pencil-tool.ts","../src/elements/stroke-hit.ts","../src/tools/eraser-tool.ts","../src/tools/arrow-handles.ts","../src/tools/select-tool.ts","../src/tools/arrow-tool.ts","../src/tools/note-tool.ts","../src/tools/text-tool.ts","../src/tools/image-tool.ts","../src/tools/shape-tool.ts","../src/tools/measure-tool.ts","../src/tools/template-tool.ts","../src/index.ts"],"sourcesContent":["import type { Point } from './types';\r\nimport type { HexOrientation } from '../elements/types';\r\nimport type { ToolContext } from '../tools/types';\r\n\r\nexport function snapPoint(point: Point, gridSize: number): Point {\r\n return {\r\n x: Math.round(point.x / gridSize) * gridSize || 0,\r\n y: Math.round(point.y / gridSize) * gridSize || 0,\r\n };\r\n}\r\n\r\nexport function snapToHexCenter(\r\n point: Point,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point {\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * cellSize;\r\n const rowH = 1.5 * cellSize;\r\n const row = Math.round(point.y / rowH);\r\n const offsetX = row % 2 !== 0 ? hexW / 2 : 0;\r\n const col = Math.round((point.x - offsetX) / hexW);\r\n return { x: col * hexW + offsetX || 0, y: row * rowH || 0 };\r\n } else {\r\n const hexH = Math.sqrt(3) * cellSize;\r\n const colW = 1.5 * cellSize;\r\n const col = Math.round(point.x / colW);\r\n const offsetY = col % 2 !== 0 ? hexH / 2 : 0;\r\n const row = Math.round((point.y - offsetY) / hexH);\r\n return { x: col * colW || 0, y: row * hexH + offsetY || 0 };\r\n }\r\n}\r\n\r\nexport function smartSnap(point: Point, ctx: ToolContext): Point {\r\n if (!ctx.snapToGrid || !ctx.gridSize) return point;\r\n if (ctx.gridType === 'hex' && ctx.hexOrientation) {\r\n return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);\r\n }\r\n return snapPoint(point, ctx.gridSize);\r\n}\r\n","interface RunStyle {\r\n bold: boolean;\r\n italic: boolean;\r\n underline: boolean;\r\n strikethrough: boolean;\r\n fontSize: number;\r\n}\r\n\r\nexport interface StyledRun extends RunStyle {\r\n text: string;\r\n}\r\n\r\nconst BOLD_TAGS = new Set(['b', 'strong']);\r\nconst ITALIC_TAGS = new Set(['i', 'em']);\r\nconst UNDERLINE_TAGS = new Set(['u']);\r\nconst STRIKE_TAGS = new Set(['s', 'strike', 'del']);\r\nconst BLOCK_TAGS = new Set(['div']);\r\n\r\nexport function parseStyledRuns(html: string, baseFontSize: number): StyledRun[] {\r\n if (!html) return [];\r\n\r\n const doc = new DOMParser().parseFromString(html, 'text/html');\r\n const runs: StyledRun[] = [];\r\n const baseStyle: RunStyle = {\r\n bold: false,\r\n italic: false,\r\n underline: false,\r\n strikethrough: false,\r\n fontSize: baseFontSize,\r\n };\r\n\r\n walkNodes(doc.body, baseStyle, runs);\r\n return runs;\r\n}\r\n\r\nfunction walkNodes(node: Node, style: RunStyle, runs: StyledRun[]): void {\r\n for (const child of Array.from(node.childNodes)) {\r\n if (child.nodeType === Node.TEXT_NODE) {\r\n const text = child.textContent ?? '';\r\n if (text) {\r\n runs.push({ text, ...style });\r\n }\r\n continue;\r\n }\r\n\r\n if (child.nodeType !== Node.ELEMENT_NODE) continue;\r\n\r\n const el = child as Element;\r\n const tag = el.tagName.toLowerCase();\r\n\r\n if (tag === 'br') {\r\n runs.push({ text: '\\n', ...style });\r\n continue;\r\n }\r\n\r\n if (BLOCK_TAGS.has(tag) && runs.length > 0) {\r\n const lastRun = runs[runs.length - 1];\r\n if (lastRun && !lastRun.text.endsWith('\\n')) {\r\n runs.push({ text: '\\n', ...style });\r\n }\r\n }\r\n\r\n const childStyle = { ...style };\r\n if (BOLD_TAGS.has(tag)) childStyle.bold = true;\r\n if (ITALIC_TAGS.has(tag)) childStyle.italic = true;\r\n if (UNDERLINE_TAGS.has(tag)) childStyle.underline = true;\r\n if (STRIKE_TAGS.has(tag)) childStyle.strikethrough = true;\r\n\r\n if (tag === 'span') {\r\n const fontSize = (el as HTMLElement).style.fontSize;\r\n if (fontSize) {\r\n childStyle.fontSize = parseInt(fontSize, 10) || style.fontSize;\r\n }\r\n }\r\n\r\n walkNodes(el, childStyle, runs);\r\n }\r\n}\r\n\r\nconst ALLOWED_TAGS = new Set([\r\n 'b',\r\n 'strong',\r\n 'i',\r\n 'em',\r\n 'u',\r\n 's',\r\n 'strike',\r\n 'del',\r\n 'span',\r\n 'br',\r\n 'div',\r\n]);\r\n\r\nexport function sanitizeNoteHtml(html: string): string {\r\n if (!html) return '';\r\n\r\n const doc = new DOMParser().parseFromString(html, 'text/html');\r\n sanitizeNode(doc.body);\r\n return doc.body.innerHTML;\r\n}\r\n\r\nfunction sanitizeNode(node: Node): void {\r\n const children = Array.from(node.childNodes);\r\n\r\n for (const child of children) {\r\n if (child.nodeType === Node.TEXT_NODE) continue;\r\n\r\n if (child.nodeType !== Node.ELEMENT_NODE) {\r\n child.remove();\r\n continue;\r\n }\r\n\r\n const el = child as Element;\r\n const tag = el.tagName.toLowerCase();\r\n\r\n if (!ALLOWED_TAGS.has(tag)) {\r\n const fragment = document.createDocumentFragment();\r\n while (el.firstChild) {\r\n fragment.appendChild(el.firstChild);\r\n }\r\n node.replaceChild(fragment, el);\r\n sanitizeNode(node);\r\n return;\r\n }\r\n\r\n sanitizeAttributes(el, tag);\r\n sanitizeNode(el);\r\n }\r\n}\r\n\r\nexport function isNoteContentEmpty(html: string): boolean {\r\n if (!html) return true;\r\n const doc = new DOMParser().parseFromString(html, 'text/html');\r\n const text = doc.body.textContent ?? '';\r\n return text.replace(/\\u00a0/g, ' ').trim().length === 0;\r\n}\r\n\r\nfunction sanitizeAttributes(el: Element, tag: string): void {\r\n const attrs = Array.from(el.attributes);\r\n for (const attr of attrs) {\r\n if (tag === 'span' && attr.name === 'style') {\r\n const fontSize = (el as HTMLElement).style.fontSize;\r\n if (fontSize) {\r\n el.setAttribute('style', `font-size: ${fontSize};`);\r\n } else {\r\n el.removeAttribute('style');\r\n }\r\n continue;\r\n }\r\n el.removeAttribute(attr.name);\r\n }\r\n}\r\n","import type { CanvasElement } from '../elements/types';\r\nimport type { Point } from './types';\r\nimport type { Layer } from '../layers/types';\r\nimport { sanitizeNoteHtml } from '../elements/note-sanitizer';\r\n\r\nexport interface CanvasState {\r\n version: number;\r\n camera: {\r\n position: Point;\r\n zoom: number;\r\n };\r\n elements: CanvasElement[];\r\n layers?: Layer[];\r\n activeLayerId?: string;\r\n}\r\n\r\nconst CURRENT_VERSION = 2;\r\n\r\nexport function exportState(\r\n elements: CanvasElement[],\r\n camera: { position: Point; zoom: number },\r\n layers: Layer[] = [],\r\n activeLayerId?: string,\r\n): CanvasState {\r\n const state: CanvasState = {\r\n version: CURRENT_VERSION,\r\n camera: {\r\n position: { ...camera.position },\r\n zoom: camera.zoom,\r\n },\r\n elements: elements.map((el) => {\r\n const clone = structuredClone(el);\r\n if (clone.type === 'arrow') {\r\n delete clone.cachedControlPoint;\r\n }\r\n return clone;\r\n }),\r\n layers: layers.map((l) => ({ ...l })),\r\n };\r\n if (activeLayerId) state.activeLayerId = activeLayerId;\r\n return state;\r\n}\r\n\r\nexport function parseState(json: string): CanvasState {\r\n const data: unknown = JSON.parse(json);\r\n validateState(data);\r\n return data;\r\n}\r\n\r\nfunction validateState(data: unknown): asserts data is CanvasState {\r\n if (!data || typeof data !== 'object') {\r\n throw new Error('Invalid state: expected an object');\r\n }\r\n\r\n const obj = data as Record<string, unknown>;\r\n\r\n if (typeof obj['version'] !== 'number') {\r\n throw new Error('Invalid state: missing or invalid version');\r\n }\r\n\r\n if (!obj['camera'] || typeof obj['camera'] !== 'object') {\r\n throw new Error('Invalid state: missing camera');\r\n }\r\n\r\n const cam = obj['camera'] as Record<string, unknown>;\r\n if (!cam['position'] || typeof cam['position'] !== 'object') {\r\n throw new Error('Invalid state: missing camera.position');\r\n }\r\n\r\n const pos = cam['position'] as Record<string, unknown>;\r\n if (typeof pos['x'] !== 'number' || typeof pos['y'] !== 'number') {\r\n throw new Error('Invalid state: camera.position must have x and y numbers');\r\n }\r\n\r\n if (typeof cam['zoom'] !== 'number') {\r\n throw new Error('Invalid state: missing camera.zoom');\r\n }\r\n\r\n if (!Array.isArray(obj['elements'])) {\r\n throw new Error('Invalid state: elements must be an array');\r\n }\r\n\r\n for (const el of obj['elements'] as unknown[]) {\r\n validateElement(el);\r\n migrateElement(el as unknown as Record<string, unknown>);\r\n }\r\n\r\n cleanBindings(obj['elements'] as Record<string, unknown>[]);\r\n\r\n const layers = obj['layers'];\r\n if (!Array.isArray(layers) || layers.length === 0) {\r\n obj['layers'] = [\r\n {\r\n id: 'default-layer',\r\n name: 'Layer 1',\r\n visible: true,\r\n locked: false,\r\n order: 0,\r\n opacity: 1.0,\r\n },\r\n ];\r\n }\r\n}\r\n\r\nconst VALID_TYPES = new Set([\r\n 'stroke',\r\n 'note',\r\n 'arrow',\r\n 'image',\r\n 'html',\r\n 'text',\r\n 'shape',\r\n 'grid',\r\n 'template',\r\n]);\r\n\r\nfunction validateElement(el: unknown): asserts el is CanvasElement {\r\n if (!el || typeof el !== 'object') {\r\n throw new Error('Invalid element: expected an object');\r\n }\r\n\r\n const obj = el as Record<string, unknown>;\r\n\r\n if (typeof obj['id'] !== 'string') {\r\n throw new Error('Invalid element: missing id');\r\n }\r\n\r\n if (typeof obj['type'] !== 'string' || !VALID_TYPES.has(obj['type'])) {\r\n throw new Error(`Invalid element: unknown type \"${String(obj['type'])}\"`);\r\n }\r\n\r\n if (typeof obj['zIndex'] !== 'number') {\r\n throw new Error('Invalid element: missing zIndex');\r\n }\r\n}\r\n\r\nfunction cleanBindings(elements: Record<string, unknown>[]): void {\r\n const ids = new Set(elements.map((el) => el['id'] as string));\r\n\r\n for (const el of elements) {\r\n if (el['type'] !== 'arrow') continue;\r\n\r\n const fromBinding = el['fromBinding'] as Record<string, unknown> | undefined;\r\n if (fromBinding && !ids.has(fromBinding['elementId'] as string)) {\r\n el['fromBinding'] = undefined;\r\n }\r\n\r\n const toBinding = el['toBinding'] as Record<string, unknown> | undefined;\r\n if (toBinding && !ids.has(toBinding['elementId'] as string)) {\r\n el['toBinding'] = undefined;\r\n }\r\n }\r\n}\r\n\r\nfunction migrateElement(obj: Record<string, unknown>): void {\r\n if (typeof obj['layerId'] !== 'string') {\r\n obj['layerId'] = 'default-layer';\r\n }\r\n\r\n if (obj['type'] === 'arrow' && typeof obj['bend'] !== 'number') {\r\n obj['bend'] = 0;\r\n }\r\n\r\n if (obj['type'] === 'stroke' && Array.isArray(obj['points'])) {\r\n for (const pt of obj['points'] as Record<string, unknown>[]) {\r\n if (typeof pt['pressure'] !== 'number') {\r\n pt['pressure'] = 0.5;\r\n }\r\n }\r\n }\r\n\r\n if (obj['type'] === 'shape' && typeof obj['shape'] !== 'string') {\r\n obj['shape'] = 'rectangle';\r\n }\r\n\r\n if (obj['type'] === 'note' && typeof obj['textColor'] !== 'string') {\r\n obj['textColor'] = '#000000';\r\n }\r\n\r\n if (obj['type'] === 'note' && typeof obj['text'] === 'string') {\r\n obj['text'] = sanitizeNoteHtml(obj['text']);\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { Camera } from '../canvas/camera';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport { exportState, parseState } from './state-serializer';\r\nimport type { CanvasState } from './state-serializer';\r\n\r\nexport interface AutoSaveOptions {\r\n key?: string;\r\n debounceMs?: number;\r\n layerManager?: LayerManager;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\nconst DEFAULT_KEY = 'fieldnotes-autosave';\r\nconst DEFAULT_DEBOUNCE_MS = 1000;\r\n\r\nexport class AutoSave {\r\n private readonly key: string;\r\n private readonly debounceMs: number;\r\n private readonly layerManager?: LayerManager;\r\n private timerId: ReturnType<typeof setTimeout> | null = null;\r\n private unsubscribers: (() => void)[] = [];\r\n private readonly onError?: (error: Error) => void;\r\n\r\n constructor(\r\n private readonly store: ElementStore,\r\n private readonly camera: Camera,\r\n options: AutoSaveOptions = {},\r\n ) {\r\n this.key = options.key ?? DEFAULT_KEY;\r\n this.debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\r\n this.layerManager = options.layerManager;\r\n this.onError = options.onError;\r\n }\r\n\r\n start(): void {\r\n const schedule = () => this.scheduleSave();\r\n\r\n this.unsubscribers = [\r\n this.store.on('add', schedule),\r\n this.store.on('remove', schedule),\r\n this.store.on('update', schedule),\r\n this.camera.onChange(schedule),\r\n ];\r\n if (this.layerManager) {\r\n this.unsubscribers.push(this.layerManager.on('change', schedule));\r\n }\r\n }\r\n\r\n stop(): void {\r\n this.cancelPending();\r\n this.unsubscribers.forEach((fn) => fn());\r\n this.unsubscribers = [];\r\n }\r\n\r\n load(): CanvasState | null {\r\n if (typeof localStorage === 'undefined') return null;\r\n\r\n const json = localStorage.getItem(this.key);\r\n if (!json) return null;\r\n\r\n try {\r\n return parseState(json);\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n clear(): void {\r\n if (typeof localStorage === 'undefined') return;\r\n localStorage.removeItem(this.key);\r\n }\r\n\r\n private scheduleSave(): void {\r\n this.cancelPending();\r\n this.timerId = setTimeout(() => this.save(), this.debounceMs);\r\n }\r\n\r\n private cancelPending(): void {\r\n if (this.timerId !== null) {\r\n clearTimeout(this.timerId);\r\n this.timerId = null;\r\n }\r\n }\r\n\r\n private save(): void {\r\n if (typeof localStorage === 'undefined') return;\r\n\r\n const layers = this.layerManager?.snapshot() ?? [];\r\n const state = exportState(this.store.snapshot(), this.camera, layers);\r\n try {\r\n localStorage.setItem(this.key, JSON.stringify(state));\r\n } catch (e) {\r\n console.warn('Auto-save failed: storage quota exceeded. State too large for localStorage.');\r\n this.onError?.(e instanceof Error ? e : new Error(String(e)));\r\n }\r\n }\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\n\r\nexport interface CameraOptions {\r\n minZoom?: number;\r\n maxZoom?: number;\r\n}\r\n\r\nexport interface CameraChangeInfo {\r\n panned: boolean;\r\n zoomed: boolean;\r\n}\r\n\r\nconst DEFAULT_MIN_ZOOM = 0.1;\r\nconst DEFAULT_MAX_ZOOM = 10;\r\n\r\nexport class Camera {\r\n private x = 0;\r\n private y = 0;\r\n private z = 1;\r\n private readonly minZoom: number;\r\n private readonly maxZoom: number;\r\n private changeListeners = new Set<(info: CameraChangeInfo) => void>();\r\n\r\n constructor(options: CameraOptions = {}) {\r\n this.minZoom = options.minZoom ?? DEFAULT_MIN_ZOOM;\r\n this.maxZoom = options.maxZoom ?? DEFAULT_MAX_ZOOM;\r\n }\r\n\r\n get position(): Point {\r\n return { x: this.x, y: this.y };\r\n }\r\n\r\n get zoom(): number {\r\n return this.z;\r\n }\r\n\r\n pan(dx: number, dy: number): void {\r\n this.x += dx;\r\n this.y += dy;\r\n this.notifyPan();\r\n }\r\n\r\n moveTo(x: number, y: number): void {\r\n this.x = x;\r\n this.y = y;\r\n this.notifyPan();\r\n }\r\n\r\n setZoom(level: number): void {\r\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, level));\r\n this.notifyZoom();\r\n }\r\n\r\n zoomAt(level: number, screenPoint: Point): void {\r\n const before = this.screenToWorld(screenPoint);\r\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, level));\r\n const after = this.screenToWorld(screenPoint);\r\n this.x += (after.x - before.x) * this.z;\r\n this.y += (after.y - before.y) * this.z;\r\n this.notifyPanAndZoom();\r\n }\r\n\r\n screenToWorld(screen: Point): Point {\r\n return {\r\n x: (screen.x - this.x) / this.z,\r\n y: (screen.y - this.y) / this.z,\r\n };\r\n }\r\n\r\n worldToScreen(world: Point): Point {\r\n return {\r\n x: world.x * this.z + this.x,\r\n y: world.y * this.z + this.y,\r\n };\r\n }\r\n\r\n getVisibleRect(canvasWidth: number, canvasHeight: number): Bounds {\r\n const topLeft = this.screenToWorld({ x: 0, y: 0 });\r\n const bottomRight = this.screenToWorld({ x: canvasWidth, y: canvasHeight });\r\n return {\r\n x: topLeft.x,\r\n y: topLeft.y,\r\n w: bottomRight.x - topLeft.x,\r\n h: bottomRight.y - topLeft.y,\r\n };\r\n }\r\n\r\n fitToContent(boundingBox: Bounds, canvasWidth: number, canvasHeight: number, padding = 40): void {\r\n if (boundingBox.w === 0 && boundingBox.h === 0) return;\r\n\r\n const scaleX = canvasWidth / (boundingBox.w + 2 * padding);\r\n const scaleY = canvasHeight / (boundingBox.h + 2 * padding);\r\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, Math.min(scaleX, scaleY)));\r\n this.x = (canvasWidth - boundingBox.w * this.z) / 2 - boundingBox.x * this.z;\r\n this.y = (canvasHeight - boundingBox.h * this.z) / 2 - boundingBox.y * this.z;\r\n this.notifyPanAndZoom();\r\n }\r\n\r\n toCSSTransform(): string {\r\n return `translate3d(${this.x}px, ${this.y}px, 0) scale(${this.z})`;\r\n }\r\n\r\n onChange(listener: (info: CameraChangeInfo) => void): () => void {\r\n this.changeListeners.add(listener);\r\n return () => this.changeListeners.delete(listener);\r\n }\r\n\r\n private notifyPan(): void {\r\n this.changeListeners.forEach((fn) => fn({ panned: true, zoomed: false }));\r\n }\r\n\r\n private notifyZoom(): void {\r\n this.changeListeners.forEach((fn) => fn({ panned: false, zoomed: true }));\r\n }\r\n\r\n private notifyPanAndZoom(): void {\r\n this.changeListeners.forEach((fn) => fn({ panned: true, zoomed: true }));\r\n }\r\n}\r\n","export type FilterAction = 'dispatch' | 'suppress' | 'defer';\r\n\r\nexport interface FilteredEvent {\r\n event: PointerEvent;\r\n action: FilterAction;\r\n}\r\n\r\nexport interface FilteredUpEvent extends FilteredEvent {\r\n pendingTap?: { x: number; y: number };\r\n}\r\n\r\nexport class InputFilter {\r\n private activePenId: number | null = null;\r\n private pendingTap: { pointerId: number; x: number; y: number } | null = null;\r\n\r\n static readonly MIN_MOVE_DISTANCE = 3;\r\n\r\n filterDown(e: PointerEvent): FilteredEvent {\r\n if (e.pointerType === 'pen') {\r\n this.activePenId = e.pointerId;\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n if (e.pointerType === 'touch' && this.activePenId !== null) {\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n if (e.pointerType === 'touch') {\r\n this.pendingTap = { pointerId: e.pointerId, x: e.clientX, y: e.clientY };\r\n return { event: e, action: 'defer' };\r\n }\r\n\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n filterMove(e: PointerEvent): FilteredEvent {\r\n if (e.pointerType === 'touch' && this.activePenId !== null) {\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {\r\n const dx = e.clientX - this.pendingTap.x;\r\n const dy = e.clientY - this.pendingTap.y;\r\n if (dx * dx + dy * dy > InputFilter.MIN_MOVE_DISTANCE * InputFilter.MIN_MOVE_DISTANCE) {\r\n this.pendingTap = null;\r\n return { event: e, action: 'dispatch' };\r\n }\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n filterUp(e: PointerEvent): FilteredUpEvent {\r\n if (e.pointerId === this.activePenId) {\r\n this.activePenId = null;\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n if (e.pointerType === 'touch' && this.activePenId !== null) {\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {\r\n const tap = { x: this.pendingTap.x, y: this.pendingTap.y };\r\n this.pendingTap = null;\r\n return { event: e, action: 'dispatch', pendingTap: tap };\r\n }\r\n\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n reset(): void {\r\n this.activePenId = null;\r\n this.pendingTap = null;\r\n }\r\n}\r\n","let counter = 0;\n\nexport function createId(prefix: string): string {\n return `${prefix}_${Date.now().toString(36)}_${(counter++).toString(36)}`;\n}\n","import type { Point } 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","import type { Bounds, Point } from '../core/types';\r\nimport { distSqToSegment } from '../core/geometry';\r\n\r\nexport function getArrowControlPoint(from: Point, to: Point, bend: number): Point {\r\n const midX = (from.x + to.x) / 2;\r\n const midY = (from.y + to.y) / 2;\r\n\r\n if (bend === 0) return { x: midX, y: midY };\r\n\r\n const dx = to.x - from.x;\r\n const dy = to.y - from.y;\r\n const len = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (len === 0) return { x: midX, y: midY };\r\n\r\n const perpX = -dy / len;\r\n const perpY = dx / len;\r\n\r\n return {\r\n x: midX + perpX * bend,\r\n y: midY + perpY * bend,\r\n };\r\n}\r\n\r\nexport function getArrowMidpoint(from: Point, to: Point, bend: number): Point {\r\n const cp = getArrowControlPoint(from, to, bend);\r\n return {\r\n x: 0.25 * from.x + 0.5 * cp.x + 0.25 * to.x,\r\n y: 0.25 * from.y + 0.5 * cp.y + 0.25 * to.y,\r\n };\r\n}\r\n\r\nexport function getBendFromPoint(from: Point, to: Point, dragPoint: Point): number {\r\n const midX = (from.x + to.x) / 2;\r\n const midY = (from.y + to.y) / 2;\r\n\r\n const dx = to.x - from.x;\r\n const dy = to.y - from.y;\r\n const len = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (len === 0) return 0;\r\n\r\n const perpX = -dy / len;\r\n const perpY = dx / len;\r\n\r\n return (dragPoint.x - midX) * perpX + (dragPoint.y - midY) * perpY;\r\n}\r\n\r\nexport function getArrowTangentAngle(from: Point, to: Point, bend: number, t: number): number {\r\n const cp = getArrowControlPoint(from, to, bend);\r\n\r\n const tangentX = 2 * (1 - t) * (cp.x - from.x) + 2 * t * (to.x - cp.x);\r\n const tangentY = 2 * (1 - t) * (cp.y - from.y) + 2 * t * (to.y - cp.y);\r\n\r\n return Math.atan2(tangentY, tangentX);\r\n}\r\n\r\nexport function isNearBezier(\r\n point: Point,\r\n from: Point,\r\n to: Point,\r\n bend: number,\r\n threshold: number,\r\n): boolean {\r\n if (bend === 0) return isNearLine(point, from, to, threshold);\r\n\r\n const cp = getArrowControlPoint(from, to, bend);\r\n const segments = 20;\r\n\r\n for (let i = 0; i < segments; i++) {\r\n const t0 = i / segments;\r\n const t1 = (i + 1) / segments;\r\n const a = bezierPoint(from, cp, to, t0);\r\n const b = bezierPoint(from, cp, to, t1);\r\n if (isNearLine(point, a, b, threshold)) return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\nexport function getArrowBounds(from: Point, to: Point, bend: number): Bounds {\r\n if (bend === 0) {\r\n const minX = Math.min(from.x, to.x);\r\n const minY = Math.min(from.y, to.y);\r\n return {\r\n x: minX,\r\n y: minY,\r\n w: Math.abs(to.x - from.x),\r\n h: Math.abs(to.y - from.y),\r\n };\r\n }\r\n\r\n const cp = getArrowControlPoint(from, to, bend);\r\n const steps = 20;\r\n let minX = Math.min(from.x, to.x);\r\n let minY = Math.min(from.y, to.y);\r\n let maxX = Math.max(from.x, to.x);\r\n let maxY = Math.max(from.y, to.y);\r\n\r\n for (let i = 1; i < steps; i++) {\r\n const t = i / steps;\r\n const p = bezierPoint(from, cp, to, t);\r\n if (p.x < minX) minX = p.x;\r\n if (p.y < minY) minY = p.y;\r\n if (p.x > maxX) maxX = p.x;\r\n if (p.y > maxY) maxY = p.y;\r\n }\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n\r\nfunction bezierPoint(from: Point, cp: Point, to: Point, t: number): Point {\r\n const mt = 1 - t;\r\n return {\r\n x: mt * mt * from.x + 2 * mt * t * cp.x + t * t * to.x,\r\n y: mt * mt * from.y + 2 * mt * t * cp.y + t * t * to.y,\r\n };\r\n}\r\n\r\nfunction isNearLine(point: Point, a: Point, b: Point, threshold: number): boolean {\r\n return distSqToSegment(point, a, b) <= threshold * threshold;\r\n}\r\n","import type { Bounds } from '../core/types';\r\nimport type { CanvasElement, TemplateElement } from './types';\r\nimport { getArrowControlPoint } from './arrow-geometry';\r\n\r\n// Cache stroke bounds via WeakMap.\r\n// May miss after ElementStore.update() creates new object via spread,\r\n// acceptable since stroke points never change after commit.\r\nconst strokeBoundsCache = new WeakMap<CanvasElement, Bounds>();\r\n\r\nexport function getElementBounds(element: CanvasElement): Bounds | null {\r\n if (element.type === 'grid') return null;\r\n\r\n if ('size' in element) {\r\n return {\r\n x: element.position.x,\r\n y: element.position.y,\r\n w: element.size.w,\r\n h: element.size.h,\r\n };\r\n }\r\n\r\n if (element.type === 'stroke') {\r\n if (element.points.length === 0) return null;\r\n\r\n const cached = strokeBoundsCache.get(element);\r\n if (cached) return cached;\r\n\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n\r\n for (const p of element.points) {\r\n const px = p.x + element.position.x;\r\n const py = p.y + element.position.y;\r\n if (px < minX) minX = px;\r\n if (py < minY) minY = py;\r\n if (px > maxX) maxX = px;\r\n if (py > maxY) maxY = py;\r\n }\r\n\r\n const bounds: Bounds = { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n strokeBoundsCache.set(element, bounds);\r\n return bounds;\r\n }\r\n\r\n if (element.type === 'arrow') {\r\n return getArrowBoundsAnalytical(element.from, element.to, element.bend);\r\n }\r\n\r\n if (element.type === 'template') {\r\n return getTemplateBounds(element);\r\n }\r\n\r\n return null;\r\n}\r\n\r\nfunction getArrowBoundsAnalytical(\r\n from: { x: number; y: number },\r\n to: { x: number; y: number },\r\n bend: number,\r\n): Bounds {\r\n if (bend === 0) {\r\n const minX = Math.min(from.x, to.x);\r\n const minY = Math.min(from.y, to.y);\r\n return {\r\n x: minX,\r\n y: minY,\r\n w: Math.abs(to.x - from.x),\r\n h: Math.abs(to.y - from.y),\r\n };\r\n }\r\n\r\n const cp = getArrowControlPoint(from, to, bend);\r\n\r\n let minX = Math.min(from.x, to.x);\r\n let maxX = Math.max(from.x, to.x);\r\n let minY = Math.min(from.y, to.y);\r\n let maxY = Math.max(from.y, to.y);\r\n\r\n // Analytical extrema for quadratic bezier: t = (P0 - P1) / (P0 - 2*P1 + P2)\r\n const tx = from.x - 2 * cp.x + to.x;\r\n if (tx !== 0) {\r\n const t = (from.x - cp.x) / tx;\r\n if (t > 0 && t < 1) {\r\n const mt = 1 - t;\r\n const x = mt * mt * from.x + 2 * mt * t * cp.x + t * t * to.x;\r\n if (x < minX) minX = x;\r\n if (x > maxX) maxX = x;\r\n }\r\n }\r\n\r\n const ty = from.y - 2 * cp.y + to.y;\r\n if (ty !== 0) {\r\n const t = (from.y - cp.y) / ty;\r\n if (t > 0 && t < 1) {\r\n const mt = 1 - t;\r\n const y = mt * mt * from.y + 2 * mt * t * cp.y + t * t * to.y;\r\n if (y < minY) minY = y;\r\n if (y > maxY) maxY = y;\r\n }\r\n }\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n\r\nfunction getTemplateBounds(el: TemplateElement): Bounds {\r\n const { x: cx, y: cy } = el.position;\r\n const r = el.radius;\r\n\r\n switch (el.templateShape) {\r\n case 'circle':\r\n return { x: cx - r, y: cy - r, w: 2 * r, h: 2 * r };\r\n\r\n case 'square':\r\n return { x: cx - r / 2, y: cy - r / 2, w: r, h: r };\r\n\r\n case 'cone': {\r\n const halfAngle = Math.atan(0.5);\r\n const tipX = cx;\r\n const tipY = cy;\r\n const leftX = cx + r * Math.cos(el.angle - halfAngle);\r\n const leftY = cy + r * Math.sin(el.angle - halfAngle);\r\n const rightX = cx + r * Math.cos(el.angle + halfAngle);\r\n const rightY = cy + r * Math.sin(el.angle + halfAngle);\r\n const farX = cx + r * Math.cos(el.angle);\r\n const farY = cy + r * Math.sin(el.angle);\r\n\r\n const xs = [tipX, leftX, rightX, farX];\r\n const ys = [tipY, leftY, rightY, farY];\r\n\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n\r\n for (let i = 0; i < xs.length; i++) {\r\n const px = xs[i];\r\n const py = ys[i];\r\n if (px !== undefined && px < minX) minX = px;\r\n if (px !== undefined && px > maxX) maxX = px;\r\n if (py !== undefined && py < minY) minY = py;\r\n if (py !== undefined && py > maxY) maxY = py;\r\n }\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n }\r\n\r\n case 'line': {\r\n const halfW = r / 12;\r\n const cos = Math.cos(el.angle);\r\n const sin = Math.sin(el.angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n\r\n const x0 = cx + perpX;\r\n const y0 = cy + perpY;\r\n const x1 = cx + r * cos + perpX;\r\n const y1 = cy + r * sin + perpY;\r\n const x2 = cx + r * cos - perpX;\r\n const y2 = cy + r * sin - perpY;\r\n const x3 = cx - perpX;\r\n const y3 = cy - perpY;\r\n\r\n const minX = Math.min(x0, x1, x2, x3);\r\n const minY = Math.min(y0, y1, y2, y3);\r\n const maxX = Math.max(x0, x1, x2, x3);\r\n const maxY = Math.max(y0, y1, y2, y3);\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n }\r\n }\r\n}\r\n\r\nexport function transferStrokeBounds(prev: CanvasElement, next: CanvasElement): void {\r\n if (prev.type !== 'stroke' || next.type !== 'stroke') return;\r\n if (prev.points !== next.points) return;\r\n if (prev.position.x !== next.position.x || prev.position.y !== next.position.y) return;\r\n const bounds = strokeBoundsCache.get(prev);\r\n if (bounds) strokeBoundsCache.set(next, bounds);\r\n}\r\n\r\nexport function boundsIntersect(a: Bounds, b: Bounds): boolean {\r\n return a.x <= b.x + b.w && a.x + a.w >= b.x && a.y <= b.y + b.h && a.y + a.h >= b.y;\r\n}\r\n","import type { Bounds } from '../core/types';\r\nimport type { CanvasElement } from './types';\r\nimport { getElementBounds } from './element-bounds';\r\n\r\nexport function getElementsBoundingBox(elements: CanvasElement[]): Bounds | null {\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n let found = false;\r\n\r\n for (const el of elements) {\r\n const b = getElementBounds(el);\r\n if (!b) continue;\r\n found = true;\r\n if (b.x < minX) minX = b.x;\r\n if (b.y < minY) minY = b.y;\r\n if (b.x + b.w > maxX) maxX = b.x + b.w;\r\n if (b.y + b.h > maxY) maxY = b.y + b.h;\r\n }\r\n\r\n if (!found) return null;\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n","import type { ToolManager } from '../tools/tool-manager';\r\nimport type { ToolContext } from '../tools/types';\r\nimport type { SelectTool } from '../tools/select-tool';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport type { HistoryStack } from '../history/history-stack';\r\nimport type { CanvasElement, ArrowElement } from '../elements/types';\r\nimport type { Point } from '../core/types';\r\nimport { createId } from '../elements/create-id';\r\nimport { getElementsBoundingBox } from '../elements/bounds';\r\n\r\nexport interface KeyboardActionsDeps {\r\n getToolManager: () => ToolManager | null;\r\n getToolContext: () => ToolContext | null;\r\n getHistoryRecorder: () => HistoryRecorder | null;\r\n getHistoryStack: () => HistoryStack | null;\r\n isToolActive: () => boolean;\r\n fitToContent?: () => void;\r\n getLastPointerWorld?: () => Point | null;\r\n}\r\n\r\nexport class KeyboardActions {\r\n private clipboard: CanvasElement[] = [];\r\n private pasteCount = 0;\r\n private nudgeTimer: ReturnType<typeof setTimeout> | null = null;\r\n private nudgeTxId: number | null = null;\r\n\r\n constructor(private readonly deps: KeyboardActionsDeps) {}\r\n\r\n dispose(): void {\r\n this.flushPendingNudge();\r\n }\r\n\r\n private selectTool(): { tool: SelectTool; ctx: ToolContext } | null {\r\n const tm = this.deps.getToolManager();\r\n const ctx = this.deps.getToolContext();\r\n if (!tm || !ctx) return null;\r\n const tool = tm.activeTool;\r\n if (tool?.name !== 'select') return null;\r\n return { tool: tool as SelectTool, ctx };\r\n }\r\n\r\n nudge(dx: number, dy: number, byCell: boolean): boolean {\r\n if (this.deps.isToolActive()) return false;\r\n const sel = this.selectTool();\r\n if (!sel) return false;\r\n if (sel.tool.selectedIds.length === 0) return false;\r\n\r\n const step = byCell ? (sel.ctx.gridSize ?? 10) : 1;\r\n if (this.nudgeTimer === null) {\r\n const recorder = this.deps.getHistoryRecorder();\r\n recorder?.begin();\r\n this.nudgeTxId = recorder?.currentTransactionId ?? null;\r\n } else {\r\n clearTimeout(this.nudgeTimer);\r\n }\r\n const moved = sel.tool.nudgeSelection(dx * step, dy * step, sel.ctx);\r\n this.nudgeTimer = setTimeout(() => this.flushPendingNudge(), 400);\r\n return moved;\r\n }\r\n\r\n flushPendingNudge(): void {\r\n if (this.nudgeTimer === null) return;\r\n clearTimeout(this.nudgeTimer);\r\n this.nudgeTimer = null;\r\n const recorder = this.deps.getHistoryRecorder();\r\n if (this.nudgeTxId === null || recorder?.currentTransactionId === this.nudgeTxId) {\r\n recorder?.commit();\r\n }\r\n this.nudgeTxId = null;\r\n }\r\n\r\n deleteSelected(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const ids = sel.tool.selectedIds;\r\n if (ids.length === 0) return;\r\n const recorder = this.deps.getHistoryRecorder();\r\n recorder?.begin();\r\n for (const id of ids) {\r\n sel.ctx.store.remove(id);\r\n }\r\n recorder?.commit();\r\n sel.ctx.requestRender();\r\n }\r\n\r\n undo(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n const ctx = this.deps.getToolContext();\r\n const stack = this.deps.getHistoryStack();\r\n if (!stack || !ctx) return;\r\n const recorder = this.deps.getHistoryRecorder();\r\n recorder?.pause();\r\n stack.undo(ctx.store);\r\n recorder?.resume();\r\n ctx.requestRender();\r\n }\r\n\r\n redo(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n const ctx = this.deps.getToolContext();\r\n const stack = this.deps.getHistoryStack();\r\n if (!stack || !ctx) return;\r\n const recorder = this.deps.getHistoryRecorder();\r\n recorder?.pause();\r\n stack.redo(ctx.store);\r\n recorder?.resume();\r\n ctx.requestRender();\r\n }\r\n\r\n copy(): void {\r\n if (this.deps.isToolActive()) return;\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const ids = sel.tool.selectedIds;\r\n if (ids.length === 0) return;\r\n this.clipboard = [];\r\n for (const id of ids) {\r\n const el = sel.ctx.store.getById(id);\r\n if (el) this.clipboard.push(structuredClone(el));\r\n }\r\n this.pasteCount = 0;\r\n }\r\n\r\n paste(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n if (this.clipboard.length === 0) return;\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n\r\n const cursor = this.deps.getLastPointerWorld?.() ?? null;\r\n if (cursor) {\r\n const bbox = getElementsBoundingBox(this.clipboard);\r\n if (bbox) {\r\n const centerX = bbox.x + bbox.w / 2;\r\n const centerY = bbox.y + bbox.h / 2;\r\n this.insertClones(this.clipboard, { x: cursor.x - centerX, y: cursor.y - centerY }, sel);\r\n return;\r\n }\r\n }\r\n\r\n this.pasteCount++;\r\n this.insertClones(this.clipboard, { x: this.pasteCount * 20, y: this.pasteCount * 20 }, sel);\r\n }\r\n\r\n duplicate(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const source: CanvasElement[] = [];\r\n for (const id of sel.tool.selectedIds) {\r\n const el = sel.ctx.store.getById(id);\r\n if (el) source.push(el);\r\n }\r\n if (source.length === 0) return;\r\n this.insertClones(source, { x: 20, y: 20 }, sel);\r\n }\r\n\r\n deselect(): void {\r\n if (this.deps.isToolActive()) return;\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n if (sel.tool.selectedIds.length === 0) return;\r\n sel.tool.setSelection([]);\r\n sel.ctx.requestRender();\r\n }\r\n\r\n selectAll(): void {\r\n if (this.deps.isToolActive()) return;\r\n const tm = this.deps.getToolManager();\r\n const ctx = this.deps.getToolContext();\r\n if (!tm || !ctx) return;\r\n if (tm.activeTool?.name !== 'select') {\r\n ctx.switchTool?.('select');\r\n }\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const ids = sel.ctx.store\r\n .getAll()\r\n .filter(\r\n (el) =>\r\n !el.locked &&\r\n (sel.ctx.isLayerVisible?.(el.layerId) ?? true) &&\r\n !(sel.ctx.isLayerLocked?.(el.layerId) ?? false),\r\n )\r\n .map((el) => el.id);\r\n sel.tool.setSelection(ids);\r\n sel.ctx.requestRender();\r\n }\r\n\r\n zoomToFit(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.deps.fitToContent?.();\r\n }\r\n\r\n 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 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 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 as ArrowElement;\r\n arrow.from = { x: arrow.from.x + offset.x, y: arrow.from.y + offset.y };\r\n arrow.to = { x: arrow.to.x + offset.x, y: arrow.to.y + offset.y };\r\n delete arrow.cachedControlPoint;\r\n\r\n if (arrow.fromBinding) {\r\n const newTarget = idMap.get(arrow.fromBinding.elementId);\r\n if (newTarget) {\r\n arrow.fromBinding = { elementId: newTarget };\r\n } else {\r\n delete arrow.fromBinding;\r\n }\r\n }\r\n if (arrow.toBinding) {\r\n const newTarget = idMap.get(arrow.toBinding.elementId);\r\n if (newTarget) {\r\n arrow.toBinding = { elementId: newTarget };\r\n } else {\r\n delete arrow.toBinding;\r\n }\r\n }\r\n }\r\n\r\n if (sel.ctx.activeLayerId) {\r\n clone.layerId = sel.ctx.activeLayerId;\r\n }\r\n\r\n sel.ctx.store.add(clone);\r\n newIds.push(clone.id);\r\n }\r\n\r\n recorder?.commit();\r\n sel.tool.setSelection(newIds);\r\n sel.ctx.requestRender();\r\n }\r\n}\r\n","export type ShortcutBindings = Record<string, string | string[] | null>;\r\n\r\nexport interface ShortcutOptions {\r\n scope?: 'focus' | 'window';\r\n bindings?: ShortcutBindings;\r\n}\r\n\r\nexport interface ShortcutsApi {\r\n rebind(action: string, bindings: string | string[] | null): void;\r\n disable(action: string): void;\r\n reset(action?: string): void;\r\n getBindings(): Record<string, string[]>;\r\n}\r\n\r\ninterface ParsedBinding {\r\n mod: boolean;\r\n ctrl: boolean;\r\n meta: boolean;\r\n shift: boolean;\r\n alt: boolean;\r\n key: string;\r\n digit: boolean;\r\n}\r\n\r\nconst DEFAULT_BINDINGS: readonly (readonly [string, readonly string[]])[] = [\r\n ['delete', ['delete', 'backspace']],\r\n ['deselect', ['escape']],\r\n ['undo', ['mod+z']],\r\n ['redo', ['mod+y', 'mod+shift+z']],\r\n ['select-all', ['mod+a']],\r\n ['copy', ['mod+c']],\r\n ['paste', ['mod+v']],\r\n ['duplicate', ['mod+d']],\r\n ['z-forward', [']']],\r\n ['z-backward', ['[']],\r\n ['z-front', ['mod+]']],\r\n ['z-back', ['mod+[']],\r\n ['zoom-fit', ['shift+1']],\r\n ['zoom-in', ['mod+=']],\r\n ['zoom-out', ['mod+-']],\r\n ['zoom-reset', ['mod+0']],\r\n ['nudge-left', ['arrowleft']],\r\n ['nudge-right', ['arrowright']],\r\n ['nudge-up', ['arrowup']],\r\n ['nudge-down', ['arrowdown']],\r\n ['tool:select', ['v']],\r\n ['tool:hand', ['h']],\r\n ['tool:pencil', ['p']],\r\n ['tool:eraser', ['e']],\r\n ['tool:arrow', ['a']],\r\n ['tool:note', ['n']],\r\n ['tool:text', ['t']],\r\n ['tool:shape', ['s']],\r\n ['tool:measure', ['m']],\r\n ['tool:template', ['g']],\r\n];\r\n\r\nconst ALLOW_SHIFT = new Set(['nudge-left', 'nudge-right', 'nudge-up', 'nudge-down']);\r\nconst MODIFIERS = new Set(['mod', 'ctrl', 'meta', 'shift', 'alt']);\r\n\r\nfunction parseBinding(binding: string): ParsedBinding {\r\n const parts = binding.toLowerCase().split('+');\r\n const key = parts.pop();\r\n if (key === undefined || key.length === 0 || MODIFIERS.has(key)) {\r\n throw new Error(`Invalid shortcut binding \"${binding}\": missing key`);\r\n }\r\n const normalizedKey = key === 'space' ? ' ' : key;\r\n const parsed: ParsedBinding = {\r\n mod: false,\r\n ctrl: false,\r\n meta: false,\r\n shift: false,\r\n alt: false,\r\n key: normalizedKey,\r\n digit: /^[0-9]$/.test(normalizedKey),\r\n };\r\n for (const part of parts) {\r\n switch (part) {\r\n case 'mod':\r\n parsed.mod = true;\r\n break;\r\n case 'ctrl':\r\n parsed.ctrl = true;\r\n break;\r\n case 'meta':\r\n parsed.meta = true;\r\n break;\r\n case 'shift':\r\n parsed.shift = true;\r\n break;\r\n case 'alt':\r\n parsed.alt = true;\r\n break;\r\n default:\r\n throw new Error(`Invalid shortcut binding \"${binding}\": unknown modifier \"${part}\"`);\r\n }\r\n }\r\n if (parsed.mod && (parsed.ctrl || parsed.meta)) {\r\n throw new Error(\r\n `Invalid shortcut binding \"${binding}\": \"mod\" already means Ctrl or Cmd; don't combine it with ctrl/meta`,\r\n );\r\n }\r\n return parsed;\r\n}\r\n\r\nfunction bindingMatches(p: ParsedBinding, e: KeyboardEvent, allowShift: boolean): boolean {\r\n if (p.mod) {\r\n if (!e.ctrlKey && !e.metaKey) return false;\r\n } else if (e.ctrlKey !== p.ctrl || e.metaKey !== p.meta) {\r\n return false;\r\n }\r\n if (!allowShift && e.shiftKey !== p.shift) return false;\r\n if (e.altKey !== p.alt) return false;\r\n return p.digit ? e.code === `Digit${p.key}` : e.key.toLowerCase() === p.key;\r\n}\r\n\r\nfunction toArray(bindings: string | string[] | null): string[] {\r\n if (bindings === null) return [];\r\n return Array.isArray(bindings) ? [...bindings] : [bindings];\r\n}\r\n\r\nexport class ShortcutMap implements ShortcutsApi {\r\n private raw = new Map<string, string[]>();\r\n private parsed = new Map<string, ParsedBinding[]>();\r\n\r\n constructor(overrides?: ShortcutBindings) {\r\n this.applyDefaults();\r\n if (overrides) {\r\n for (const [action, bindings] of Object.entries(overrides)) {\r\n this.rebind(action, bindings);\r\n }\r\n }\r\n }\r\n\r\n /** First matching action in registration order wins when bindings conflict. */\r\n match(e: KeyboardEvent): string | null {\r\n for (const [action, parsedList] of this.parsed) {\r\n const allowShift = ALLOW_SHIFT.has(action);\r\n for (const p of parsedList) {\r\n if (bindingMatches(p, e, allowShift)) return action;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n rebind(action: string, bindings: string | string[] | null): void {\r\n const list = toArray(bindings);\r\n const parsedList = list.map(parseBinding);\r\n this.raw.set(action, list);\r\n this.parsed.set(action, parsedList);\r\n }\r\n\r\n disable(action: string): void {\r\n this.rebind(action, null);\r\n }\r\n\r\n reset(action?: string): void {\r\n if (action === undefined) {\r\n this.raw.clear();\r\n this.parsed.clear();\r\n this.applyDefaults();\r\n return;\r\n }\r\n const def = DEFAULT_BINDINGS.find(([name]) => name === action);\r\n if (def) {\r\n this.rebind(action, [...def[1]]);\r\n } else if (this.raw.has(action)) {\r\n this.raw.delete(action);\r\n this.parsed.delete(action);\r\n }\r\n }\r\n\r\n getBindings(): Record<string, string[]> {\r\n const out: Record<string, string[]> = {};\r\n for (const [action, list] of this.raw) {\r\n out[action] = [...list];\r\n }\r\n return out;\r\n }\r\n\r\n private applyDefaults(): void {\r\n for (const [action, bindings] of DEFAULT_BINDINGS) {\r\n this.rebind(action, [...bindings]);\r\n }\r\n }\r\n}\r\n","import type { Camera } from './camera';\r\nimport type { ToolManager } from '../tools/tool-manager';\r\nimport type { ToolContext, PointerState } from '../tools/types';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport type { HistoryStack } from '../history/history-stack';\r\nimport type { ShortcutOptions, ShortcutsApi } from './shortcut-map';\r\nimport { InputFilter } from './input-filter';\r\nimport { KeyboardActions } from './keyboard-actions';\r\nimport { ShortcutMap } from './shortcut-map';\r\n\r\nconst ZOOM_SENSITIVITY = 0.001;\r\nconst ZOOM_STEP = 1.2;\r\nconst MIDDLE_BUTTON = 1;\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 InputHandlerOptions {\r\n toolManager?: ToolManager;\r\n toolContext?: ToolContext;\r\n historyRecorder?: HistoryRecorder;\r\n historyStack?: HistoryStack;\r\n fitToContent?: () => void;\r\n shortcuts?: ShortcutOptions;\r\n}\r\n\r\nexport class InputHandler {\r\n private isPanning = false;\r\n private lastPointer = { x: 0, y: 0 };\r\n private spaceHeld = false;\r\n private activePointers = new Map<number, { x: number; y: number }>();\r\n private lastPinchDistance = 0;\r\n private lastPinchCenter = { x: 0, y: 0 };\r\n private toolManager: ToolManager | null;\r\n private toolContext: ToolContext | null;\r\n private historyRecorder: HistoryRecorder | null;\r\n private historyStack: HistoryStack | null;\r\n private isToolActive = false;\r\n private lastPointerEvent: PointerEvent | null = null;\r\n private readonly inputFilter = new InputFilter();\r\n private deferredDown: PointerEvent | null = null;\r\n private readonly abortController = new AbortController();\r\n private readonly actions: KeyboardActions;\r\n private readonly shortcutMap: ShortcutMap;\r\n private readonly scope: 'focus' | 'window';\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 getLastPointerWorld: () => this.lastPointerWorld(),\r\n });\r\n this.shortcutMap = new ShortcutMap(options.shortcuts?.bindings);\r\n this.scope = options.shortcuts?.scope ?? 'focus';\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.shortcutMap;\r\n }\r\n\r\n destroy(): void {\r\n this.actions.dispose();\r\n this.abortController.abort();\r\n this.inputFilter.reset();\r\n this.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 window.addEventListener('keydown', this.onKeyDown, opts);\r\n window.addEventListener('keyup', this.onKeyUp, opts);\r\n }\r\n\r\n private viewportCenter(): { x: number; y: number } {\r\n const rect = this.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.camera.zoomAt(this.camera.zoom * factor, this.viewportCenter());\r\n }\r\n\r\n private zoomToLevel(level: number): void {\r\n this.camera.zoomAt(level, this.viewportCenter());\r\n }\r\n\r\n private onWheel = (e: WheelEvent): void => {\r\n e.preventDefault();\r\n const rect = this.element.getBoundingClientRect();\r\n const zoomFactor = 1 - e.deltaY * ZOOM_SENSITIVITY;\r\n const newZoom = this.camera.zoom * zoomFactor;\r\n this.camera.zoomAt(newZoom, {\r\n x: e.clientX - rect.left,\r\n y: e.clientY - rect.top,\r\n });\r\n };\r\n\r\n private onPointerDown = (e: PointerEvent): void => {\r\n this.focusSelf();\r\n this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });\r\n\r\n this.element.setPointerCapture?.(e.pointerId);\r\n\r\n if (this.activePointers.size === 2) {\r\n this.startPinch();\r\n this.cancelToolIfActive(e);\r\n return;\r\n }\r\n\r\n if (e.button === MIDDLE_BUTTON || (e.button === 0 && this.spaceHeld)) {\r\n this.isPanning = true;\r\n this.lastPointer = { x: e.clientX, y: e.clientY };\r\n return;\r\n }\r\n\r\n if (\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 return;\r\n }\r\n this.dispatchToolDown(e);\r\n }\r\n };\r\n\r\n private onPointerMove = (e: PointerEvent): void => {\r\n this.lastPointerEvent = e;\r\n\r\n if (this.activePointers.has(e.pointerId)) {\r\n this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });\r\n }\r\n\r\n if (this.activePointers.size === 2) {\r\n this.handlePinchMove();\r\n return;\r\n }\r\n\r\n if (this.isPanning) {\r\n const dx = e.clientX - this.lastPointer.x;\r\n const dy = e.clientY - this.lastPointer.y;\r\n this.lastPointer = { x: e.clientX, y: e.clientY };\r\n this.camera.pan(dx, dy);\r\n return;\r\n }\r\n\r\n if (e.pointerType === 'pen' && !this.activePointers.has(e.pointerId)) {\r\n this.dispatchToolHover(e);\r\n } else if (this.isToolActive) {\r\n this.dispatchToolMove(e);\r\n } else if (this.deferredDown) {\r\n const result = this.inputFilter.filterMove(e);\r\n if (result.action === 'dispatch') {\r\n this.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 try {\r\n this.element.releasePointerCapture(e.pointerId);\r\n } catch {\r\n // Already released (e.g., pointercancel fired first)\r\n }\r\n this.activePointers.delete(e.pointerId);\r\n\r\n if (this.activePointers.size < 2) {\r\n this.lastPinchDistance = 0;\r\n }\r\n\r\n if (this.isPanning && this.activePointers.size === 0) {\r\n this.isPanning = false;\r\n }\r\n\r\n const upResult = this.inputFilter.filterUp(e);\r\n\r\n if (this.isToolActive) {\r\n this.dispatchToolUp(e);\r\n this.isToolActive = false;\r\n } else if (this.deferredDown && upResult.pendingTap) {\r\n this.dispatchToolDown(this.deferredDown);\r\n this.dispatchToolUp(e);\r\n this.deferredDown = null;\r\n } else {\r\n this.deferredDown = null;\r\n }\r\n };\r\n\r\n private onKeyDown = (e: KeyboardEvent): void => {\r\n const target = e.target as HTMLElement | null;\r\n if (target?.isContentEditable) return;\r\n const tag = target?.tagName;\r\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return;\r\n if (!this.isInScope()) return;\r\n\r\n if (e.key === ' ') {\r\n this.spaceHeld = 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 private onKeyUp = (e: KeyboardEvent): void => {\r\n if (e.key === ' ') {\r\n this.spaceHeld = false;\r\n if (this.activePointers.size === 0) {\r\n if (this.lastPointerEvent) {\r\n this.dispatchToolHover(this.lastPointerEvent);\r\n } else {\r\n this.toolContext?.setCursor?.('default');\r\n }\r\n }\r\n }\r\n };\r\n\r\n private runAction(action: string, e: KeyboardEvent): void {\r\n switch (action) {\r\n case 'delete':\r\n e.preventDefault();\r\n this.actions.deleteSelected();\r\n return;\r\n case 'deselect':\r\n this.actions.deselect();\r\n return;\r\n case 'undo':\r\n e.preventDefault();\r\n this.actions.undo();\r\n return;\r\n case 'redo':\r\n e.preventDefault();\r\n this.actions.redo();\r\n return;\r\n case 'select-all':\r\n e.preventDefault();\r\n this.actions.selectAll();\r\n return;\r\n case 'copy':\r\n e.preventDefault();\r\n this.actions.copy();\r\n return;\r\n case 'paste':\r\n e.preventDefault();\r\n this.actions.paste();\r\n return;\r\n case 'duplicate':\r\n e.preventDefault();\r\n this.actions.duplicate();\r\n return;\r\n case 'z-forward':\r\n e.preventDefault();\r\n this.actions.zOrder('forward');\r\n return;\r\n case 'z-backward':\r\n e.preventDefault();\r\n this.actions.zOrder('backward');\r\n return;\r\n case 'z-front':\r\n e.preventDefault();\r\n this.actions.zOrder('front');\r\n return;\r\n case 'z-back':\r\n e.preventDefault();\r\n this.actions.zOrder('back');\r\n return;\r\n case 'zoom-fit':\r\n e.preventDefault();\r\n this.actions.zoomToFit();\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.actions.nudge(delta[0], delta[1], e.shiftKey)) {\r\n e.preventDefault();\r\n }\r\n return;\r\n }\r\n default:\r\n if (action.startsWith('tool:')) {\r\n if (this.isToolActive) return;\r\n e.preventDefault();\r\n this.toolContext?.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 startPinch(): void {\r\n this.inputFilter.reset();\r\n this.deferredDown = null;\r\n this.isPanning = true;\r\n const [a, b] = this.getPinchPoints();\r\n this.lastPinchDistance = this.distance(a, b);\r\n this.lastPinchCenter = this.midpoint(a, b);\r\n this.lastPointer = { ...this.lastPinchCenter };\r\n }\r\n\r\n private handlePinchMove(): void {\r\n const [a, b] = this.getPinchPoints();\r\n const dist = this.distance(a, b);\r\n const center = this.midpoint(a, b);\r\n\r\n if (this.lastPinchDistance > 0) {\r\n const scale = dist / this.lastPinchDistance;\r\n const newZoom = this.camera.zoom * scale;\r\n this.camera.zoomAt(newZoom, center);\r\n }\r\n\r\n const dx = center.x - this.lastPointer.x;\r\n const dy = center.y - this.lastPointer.y;\r\n this.camera.pan(dx, dy);\r\n\r\n this.lastPinchDistance = dist;\r\n this.lastPinchCenter = center;\r\n this.lastPointer = { ...center };\r\n }\r\n\r\n private getPinchPoints(): [{ x: number; y: number }, { x: number; y: number }] {\r\n const pts = [...this.activePointers.values()];\r\n return [pts[0] ?? { x: 0, y: 0 }, pts[1] ?? { x: 0, y: 0 }];\r\n }\r\n\r\n private distance(a: { x: number; y: number }, b: { x: number; y: number }): number {\r\n const dx = a.x - b.x;\r\n const dy = a.y - b.y;\r\n return Math.sqrt(dx * dx + dy * dy);\r\n }\r\n\r\n private midpoint(\r\n a: { x: number; y: number },\r\n b: { x: number; y: number },\r\n ): { x: number; y: number } {\r\n return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\r\n }\r\n\r\n private lastPointerWorld(): { x: number; y: number } | null {\r\n const e = this.lastPointerEvent;\r\n if (!e) return null;\r\n const rect = this.element.getBoundingClientRect();\r\n return this.camera.screenToWorld({ x: e.clientX - rect.left, y: e.clientY - rect.top });\r\n }\r\n\r\n private 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 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","import type { Camera } from './camera';\r\n\r\nexport type BackgroundPattern = 'dots' | 'grid' | 'none';\r\n\r\nexport interface BackgroundOptions {\r\n pattern?: BackgroundPattern;\r\n spacing?: number;\r\n color?: string;\r\n dotRadius?: number;\r\n lineWidth?: number;\r\n}\r\n\r\nconst MIN_PATTERN_SPACING = 16;\r\n\r\nconst DEFAULTS = {\r\n pattern: 'dots' as BackgroundPattern,\r\n spacing: 24,\r\n color: '#d0d0d0',\r\n dotRadius: 1,\r\n lineWidth: 0.5,\r\n};\r\n\r\nexport class Background {\r\n private readonly pattern: BackgroundPattern;\r\n private readonly spacing: number;\r\n private readonly color: string;\r\n private readonly dotRadius: number;\r\n private readonly lineWidth: number;\r\n private cachedCanvas: OffscreenCanvas | HTMLCanvasElement | null = null;\r\n private cachedCtx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null = null;\r\n private lastZoom = -1;\r\n private lastOffsetX = -Infinity;\r\n private lastOffsetY = -Infinity;\r\n private lastWidth = 0;\r\n private lastHeight = 0;\r\n\r\n constructor(options: BackgroundOptions = {}) {\r\n this.pattern = options.pattern ?? DEFAULTS.pattern;\r\n this.spacing = options.spacing ?? DEFAULTS.spacing;\r\n this.color = options.color ?? DEFAULTS.color;\r\n this.dotRadius = options.dotRadius ?? DEFAULTS.dotRadius;\r\n this.lineWidth = options.lineWidth ?? DEFAULTS.lineWidth;\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, camera: Camera): void {\r\n const { width, height } = ctx.canvas;\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n const cssWidth = width / dpr;\r\n const cssHeight = height / dpr;\r\n\r\n ctx.save();\r\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n ctx.clearRect(0, 0, cssWidth, cssHeight);\r\n\r\n if (this.pattern === 'none') {\r\n ctx.restore();\r\n return;\r\n }\r\n\r\n const spacing = this.adaptSpacing(this.spacing, camera.zoom);\r\n const keyZoom = camera.zoom;\r\n const keyX = Math.floor(camera.position.x % spacing);\r\n const keyY = Math.floor(camera.position.y % spacing);\r\n\r\n if (\r\n this.cachedCanvas !== null &&\r\n keyZoom === this.lastZoom &&\r\n keyX === this.lastOffsetX &&\r\n keyY === this.lastOffsetY &&\r\n cssWidth === this.lastWidth &&\r\n cssHeight === this.lastHeight\r\n ) {\r\n ctx.drawImage(this.cachedCanvas as CanvasImageSource, 0, 0);\r\n ctx.restore();\r\n return;\r\n }\r\n\r\n this.ensureCachedCanvas(cssWidth, cssHeight, dpr);\r\n\r\n if (this.cachedCtx === null) {\r\n // Fallback: render directly when offscreen canvas is unavailable (e.g. jsdom)\r\n if (this.pattern === 'dots') {\r\n this.renderDots(ctx, camera, cssWidth, cssHeight);\r\n } else if (this.pattern === 'grid') {\r\n this.renderGrid(ctx, camera, cssWidth, cssHeight);\r\n }\r\n ctx.restore();\r\n return;\r\n }\r\n\r\n const offCtx = this.cachedCtx as CanvasRenderingContext2D;\r\n offCtx.clearRect(0, 0, cssWidth, cssHeight);\r\n if (this.pattern === 'dots') {\r\n this.renderDots(offCtx, camera, cssWidth, cssHeight);\r\n } else if (this.pattern === 'grid') {\r\n this.renderGrid(offCtx, camera, cssWidth, cssHeight);\r\n }\r\n\r\n this.lastZoom = keyZoom;\r\n this.lastOffsetX = keyX;\r\n this.lastOffsetY = keyY;\r\n this.lastWidth = cssWidth;\r\n this.lastHeight = cssHeight;\r\n\r\n ctx.drawImage(this.cachedCanvas as CanvasImageSource, 0, 0);\r\n ctx.restore();\r\n }\r\n\r\n private ensureCachedCanvas(cssWidth: number, cssHeight: number, dpr: number): void {\r\n if (\r\n this.cachedCanvas !== null &&\r\n this.lastWidth === cssWidth &&\r\n this.lastHeight === cssHeight\r\n ) {\r\n return;\r\n }\r\n\r\n const physWidth = Math.round(cssWidth * dpr);\r\n const physHeight = Math.round(cssHeight * dpr);\r\n\r\n if (typeof OffscreenCanvas !== 'undefined') {\r\n this.cachedCanvas = new OffscreenCanvas(physWidth, physHeight);\r\n } else if (typeof document !== 'undefined') {\r\n const el = document.createElement('canvas');\r\n el.width = physWidth;\r\n el.height = physHeight;\r\n this.cachedCanvas = el;\r\n } else {\r\n // No offscreen canvas support available; fall back to direct rendering\r\n this.cachedCanvas = null;\r\n this.cachedCtx = null;\r\n return;\r\n }\r\n\r\n const offCtx = this.cachedCanvas.getContext('2d');\r\n if (offCtx !== null) {\r\n (offCtx as CanvasRenderingContext2D).scale(dpr, dpr);\r\n }\r\n this.cachedCtx = offCtx as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;\r\n\r\n // Force re-render on next frame since canvas was recreated\r\n this.lastZoom = -1;\r\n }\r\n\r\n private adaptSpacing(baseSpacing: number, zoom: number): number {\r\n let spacing = baseSpacing * zoom;\r\n while (spacing < MIN_PATTERN_SPACING) {\r\n spacing *= 2;\r\n }\r\n return spacing;\r\n }\r\n\r\n private renderDots(\r\n ctx: CanvasRenderingContext2D,\r\n camera: Camera,\r\n width: number,\r\n height: number,\r\n ): void {\r\n const spacing = this.adaptSpacing(this.spacing, camera.zoom);\r\n const offsetX = camera.position.x % spacing;\r\n const offsetY = camera.position.y % spacing;\r\n const radius = this.dotRadius * Math.min(camera.zoom, 2);\r\n\r\n ctx.fillStyle = this.color;\r\n ctx.beginPath();\r\n\r\n for (let x = offsetX; x < width; x += spacing) {\r\n for (let y = offsetY; y < height; y += spacing) {\r\n ctx.moveTo(x + radius, y);\r\n ctx.arc(x, y, radius, 0, Math.PI * 2);\r\n }\r\n }\r\n\r\n ctx.fill();\r\n }\r\n\r\n private renderGrid(\r\n ctx: CanvasRenderingContext2D,\r\n camera: Camera,\r\n width: number,\r\n height: number,\r\n ): void {\r\n const spacing = this.adaptSpacing(this.spacing, camera.zoom);\r\n const offsetX = camera.position.x % spacing;\r\n const offsetY = camera.position.y % spacing;\r\n const lineW = this.lineWidth * Math.min(camera.zoom, 2);\r\n\r\n ctx.fillStyle = this.color;\r\n\r\n for (let x = offsetX; x < width; x += spacing) {\r\n ctx.fillRect(x, 0, lineW, height);\r\n }\r\n\r\n for (let y = offsetY; y < height; y += spacing) {\r\n ctx.fillRect(0, y, width, lineW);\r\n }\r\n }\r\n}\r\n","type Listener<T> = (data: T) => void;\r\n\r\nexport class EventBus<TEvents extends { [K in keyof TEvents]: TEvents[K] }> {\r\n private listeners = new Map<keyof TEvents, Set<Listener<never>>>();\r\n\r\n on<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): () => void {\r\n const existing = this.listeners.get(event);\r\n if (existing) {\r\n existing.add(listener as Listener<never>);\r\n } else {\r\n const set = new Set<Listener<never>>([listener as Listener<never>]);\r\n this.listeners.set(event, set);\r\n }\r\n return () => this.off(event, listener);\r\n }\r\n\r\n off<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): void {\r\n this.listeners.get(event)?.delete(listener as Listener<never>);\r\n }\r\n\r\n emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void {\r\n this.listeners.get(event)?.forEach((listener) => {\r\n try {\r\n listener(data as never);\r\n } catch (err) {\r\n console.error(`[fieldnotes] listener error for \"${String(event)}\"`, err);\r\n }\r\n });\r\n }\r\n\r\n clear(): void {\r\n this.listeners.clear();\r\n }\r\n}\r\n","import type { Bounds, Point } from './types';\r\n\r\ninterface Entry {\r\n id: string;\r\n bounds: Bounds;\r\n}\r\n\r\nconst MAX_ITEMS = 8;\r\nconst MAX_DEPTH = 8;\r\n\r\nfunction intersects(a: Bounds, b: Bounds): boolean {\r\n return a.x <= b.x + b.w && a.x + a.w >= b.x && a.y <= b.y + b.h && a.y + a.h >= b.y;\r\n}\r\n\r\nclass QuadNode {\r\n items: Entry[] = [];\r\n children: QuadNode[] | null = null;\r\n\r\n constructor(\r\n readonly bounds: Bounds,\r\n readonly depth: number,\r\n ) {}\r\n\r\n insert(entry: Entry): void {\r\n if (this.children) {\r\n const idx = this.getChildIndex(entry.bounds);\r\n if (idx !== -1) {\r\n const child = this.children[idx];\r\n if (child) child.insert(entry);\r\n return;\r\n }\r\n this.items.push(entry);\r\n return;\r\n }\r\n\r\n this.items.push(entry);\r\n\r\n if (this.items.length > MAX_ITEMS && this.depth < MAX_DEPTH) {\r\n this.split();\r\n }\r\n }\r\n\r\n remove(id: string): boolean {\r\n const idx = this.items.findIndex((e) => e.id === id);\r\n if (idx !== -1) {\r\n this.items.splice(idx, 1);\r\n return true;\r\n }\r\n\r\n if (this.children) {\r\n for (const child of this.children) {\r\n if (child.remove(id)) {\r\n this.collapseIfEmpty();\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n query(rect: Bounds, result: string[]): void {\r\n if (!intersects(this.bounds, rect)) return;\r\n\r\n for (const item of this.items) {\r\n if (intersects(item.bounds, rect)) {\r\n result.push(item.id);\r\n }\r\n }\r\n\r\n if (this.children) {\r\n for (const child of this.children) {\r\n child.query(rect, result);\r\n }\r\n }\r\n }\r\n\r\n private getChildIndex(itemBounds: Bounds): number {\r\n const midX = this.bounds.x + this.bounds.w / 2;\r\n const midY = this.bounds.y + this.bounds.h / 2;\r\n\r\n const left = itemBounds.x >= this.bounds.x && itemBounds.x + itemBounds.w <= midX;\r\n const right =\r\n itemBounds.x >= midX && itemBounds.x + itemBounds.w <= this.bounds.x + this.bounds.w;\r\n const top = itemBounds.y >= this.bounds.y && itemBounds.y + itemBounds.h <= midY;\r\n const bottom =\r\n itemBounds.y >= midY && itemBounds.y + itemBounds.h <= this.bounds.y + this.bounds.h;\r\n\r\n if (left && top) return 0;\r\n if (right && top) return 1;\r\n if (left && bottom) return 2;\r\n if (right && bottom) return 3;\r\n\r\n return -1;\r\n }\r\n\r\n private split(): void {\r\n const { x, y, w, h } = this.bounds;\r\n const halfW = w / 2;\r\n const halfH = h / 2;\r\n const d = this.depth + 1;\r\n\r\n this.children = [\r\n new QuadNode({ x, y, w: halfW, h: halfH }, d),\r\n new QuadNode({ x: x + halfW, y, w: halfW, h: halfH }, d),\r\n new QuadNode({ x, y: y + halfH, w: halfW, h: halfH }, d),\r\n new QuadNode({ x: x + halfW, y: y + halfH, w: halfW, h: halfH }, d),\r\n ];\r\n\r\n const remaining: Entry[] = [];\r\n for (const item of this.items) {\r\n const idx = this.getChildIndex(item.bounds);\r\n if (idx !== -1) {\r\n const target = this.children[idx];\r\n if (target) target.insert(item);\r\n } else {\r\n remaining.push(item);\r\n }\r\n }\r\n this.items = remaining;\r\n }\r\n\r\n private collapseIfEmpty(): void {\r\n if (!this.children) return;\r\n let totalItems = this.items.length;\r\n for (const child of this.children) {\r\n if (child.children) return;\r\n totalItems += child.items.length;\r\n }\r\n if (totalItems <= MAX_ITEMS) {\r\n for (const child of this.children) {\r\n this.items.push(...child.items);\r\n }\r\n this.children = null;\r\n }\r\n }\r\n}\r\n\r\nexport class Quadtree {\r\n private root: QuadNode;\r\n private _size = 0;\r\n private readonly worldBounds: Bounds;\r\n\r\n constructor(worldBounds: Bounds) {\r\n this.worldBounds = worldBounds;\r\n this.root = new QuadNode(worldBounds, 0);\r\n }\r\n\r\n get size(): number {\r\n return this._size;\r\n }\r\n\r\n insert(id: string, bounds: Bounds): void {\r\n this.root.insert({ id, bounds });\r\n this._size++;\r\n }\r\n\r\n remove(id: string): void {\r\n if (this.root.remove(id)) {\r\n this._size--;\r\n }\r\n }\r\n\r\n update(id: string, newBounds: Bounds): void {\r\n this.remove(id);\r\n this.insert(id, newBounds);\r\n }\r\n\r\n query(rect: Bounds): string[] {\r\n const result: string[] = [];\r\n this.root.query(rect, result);\r\n return result;\r\n }\r\n\r\n queryPoint(point: Point): string[] {\r\n return this.query({ x: point.x, y: point.y, w: 0, h: 0 });\r\n }\r\n\r\n clear(): void {\r\n this.root = new QuadNode(this.worldBounds, 0);\r\n this._size = 0;\r\n }\r\n}\r\n","import type { Point, StrokePoint } from '../core/types';\r\n\r\nexport interface CurveSegment {\r\n start: StrokePoint;\r\n cp1: Point;\r\n cp2: Point;\r\n end: StrokePoint;\r\n}\r\n\r\nconst MIN_PRESSURE_SCALE = 0.2;\r\n\r\nexport function pressureToWidth(pressure: number, baseWidth: number): number {\r\n return baseWidth * (MIN_PRESSURE_SCALE + (1 - MIN_PRESSURE_SCALE) * pressure);\r\n}\r\n\r\nexport function simplifyPoints(points: StrokePoint[], tolerance: number): StrokePoint[] {\r\n if (points.length <= 2) return points.slice();\r\n return rdp(points, 0, points.length - 1, tolerance);\r\n}\r\n\r\nfunction rdp(points: StrokePoint[], start: number, end: number, tolerance: number): StrokePoint[] {\r\n const first = points[start];\r\n const last = points[end];\r\n if (!first || !last) return [];\r\n\r\n if (end - start <= 1) return [first, last];\r\n\r\n let maxDist = 0;\r\n let maxIndex = start;\r\n\r\n for (let i = start + 1; i < end; i++) {\r\n const pt = points[i];\r\n if (!pt) continue;\r\n const dist = perpendicularDistance(pt, first, last);\r\n if (dist > maxDist) {\r\n maxDist = dist;\r\n maxIndex = i;\r\n }\r\n }\r\n\r\n if (maxDist <= tolerance) return [first, last];\r\n\r\n const left = rdp(points, start, maxIndex, tolerance);\r\n const right = rdp(points, maxIndex, end, tolerance);\r\n\r\n return left.concat(right.slice(1));\r\n}\r\n\r\nfunction perpendicularDistance(pt: Point, lineStart: Point, lineEnd: Point): number {\r\n const dx = lineEnd.x - lineStart.x;\r\n const dy = lineEnd.y - lineStart.y;\r\n const lenSq = dx * dx + dy * dy;\r\n\r\n if (lenSq === 0) {\r\n const ex = pt.x - lineStart.x;\r\n const ey = pt.y - lineStart.y;\r\n return Math.sqrt(ex * ex + ey * ey);\r\n }\r\n\r\n const num = Math.abs(dy * pt.x - dx * pt.y + lineEnd.x * lineStart.y - lineEnd.y * lineStart.x);\r\n return num / Math.sqrt(lenSq);\r\n}\r\n\r\nexport function smoothToSegments(points: StrokePoint[]): CurveSegment[] {\r\n if (points.length < 2) return [];\r\n\r\n if (points.length === 2) {\r\n const p0 = points[0];\r\n const p1 = points[1];\r\n if (!p0 || !p1) return [];\r\n const mx = (p0.x + p1.x) / 2;\r\n const my = (p0.y + p1.y) / 2;\r\n return [{ start: p0, cp1: { x: mx, y: my }, cp2: { x: mx, y: my }, end: p1 }];\r\n }\r\n\r\n const segments: CurveSegment[] = [];\r\n const n = points.length;\r\n\r\n for (let i = 0; i < n - 1; i++) {\r\n const p0 = points[Math.max(0, i - 1)];\r\n const p1 = points[i];\r\n const p2 = points[i + 1];\r\n const p3 = points[Math.min(n - 1, i + 2)];\r\n if (!p0 || !p1 || !p2 || !p3) continue;\r\n\r\n const cp1: Point = {\r\n x: p1.x + (p2.x - p0.x) / 6,\r\n y: p1.y + (p2.y - p0.y) / 6,\r\n };\r\n const cp2: Point = {\r\n x: p2.x - (p3.x - p1.x) / 6,\r\n y: p2.y - (p3.y - p1.y) / 6,\r\n };\r\n\r\n segments.push({ start: p1, cp1, cp2, end: p2 });\r\n }\r\n\r\n return segments;\r\n}\r\n","import type { CanvasElement, StrokeElement } 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 { getElementBounds, transferStrokeBounds } from './element-bounds';\r\nimport { getArrowControlPoint } from './arrow-geometry';\r\nimport { sanitizeNoteHtml } from './note-sanitizer';\r\nimport { computeStrokeSegments, transferStrokeRenderData } from './stroke-cache';\r\nimport type { ArrowElement, CanvasElement, ElementType, NoteElement } from './types';\r\n\r\nexport interface ElementUpdateEvent {\r\n previous: CanvasElement;\r\n current: CanvasElement;\r\n}\r\n\r\ninterface ElementStoreEvents {\r\n add: CanvasElement;\r\n remove: CanvasElement;\r\n update: ElementUpdateEvent;\r\n clear: null;\r\n}\r\n\r\nexport class ElementStore {\r\n private elements = new Map<string, CanvasElement>();\r\n private bus = new EventBus<ElementStoreEvents>();\r\n private layerOrderMap = new Map<string, number>();\r\n private spatialIndex = new Quadtree({ x: -100000, y: -100000, w: 200000, h: 200000 });\r\n private sortedCache: CanvasElement[] | null = null;\r\n private _versions = new Map<string, number>();\r\n\r\n get count(): number {\r\n return this.elements.size;\r\n }\r\n\r\n getVersion(id: string): number {\r\n return this._versions.get(id) ?? -1;\r\n }\r\n\r\n setLayerOrder(order: Map<string, number>): void {\r\n this.layerOrderMap = new Map(order);\r\n this.sortedCache = null;\r\n }\r\n\r\n getAll(): CanvasElement[] {\r\n if (this.sortedCache) return this.sortedCache;\r\n this.sortedCache = [...this.elements.values()].sort((a, b) => {\r\n const layerA = this.layerOrderMap.get(a.layerId) ?? 0;\r\n const layerB = this.layerOrderMap.get(b.layerId) ?? 0;\r\n if (layerA !== layerB) return layerA - layerB;\r\n return a.zIndex - b.zIndex;\r\n });\r\n return this.sortedCache;\r\n }\r\n\r\n getById(id: string): CanvasElement | undefined {\r\n return this.elements.get(id);\r\n }\r\n\r\n getElementsByType<T extends ElementType>(type: T): Extract<CanvasElement, { type: T }>[] {\r\n return this.getAll().filter(\r\n (el): el is Extract<CanvasElement, { type: T }> => el.type === type,\r\n );\r\n }\r\n\r\n add(element: CanvasElement): void {\r\n this.sortedCache = null;\r\n this._versions.set(element.id, 0);\r\n this.elements.set(element.id, element);\r\n const bounds = getElementBounds(element);\r\n if (bounds) this.spatialIndex.insert(element.id, bounds);\r\n this.bus.emit('add', element);\r\n }\r\n\r\n update(id: string, partial: Partial<CanvasElement>): void {\r\n const existing = this.elements.get(id);\r\n if (!existing) return;\r\n this.sortedCache = null;\r\n this._versions.set(id, (this._versions.get(id) ?? 0) + 1);\r\n\r\n // Shallow spread preserves the points array identity when `partial` omits points;\r\n // transferStrokeRenderData/transferStrokeBounds rely on that reference equality.\r\n const updated = { ...existing, ...partial, id: existing.id, type: existing.type };\r\n\r\n if (updated.type === 'stroke' && existing.type === 'stroke') {\r\n transferStrokeRenderData(existing, updated as CanvasElement);\r\n transferStrokeBounds(existing, updated as CanvasElement);\r\n }\r\n\r\n if (updated.type === 'arrow') {\r\n const arrow = updated as ArrowElement;\r\n arrow.cachedControlPoint = getArrowControlPoint(arrow.from, arrow.to, arrow.bend);\r\n }\r\n\r\n if (updated.type === 'note' && 'text' in partial) {\r\n (updated as NoteElement).text = sanitizeNoteHtml((updated as NoteElement).text);\r\n }\r\n\r\n this.elements.set(id, updated as CanvasElement);\r\n\r\n const newBounds = getElementBounds(updated as CanvasElement);\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 as CanvasElement });\r\n }\r\n\r\n remove(id: string): void {\r\n const element = this.elements.get(id);\r\n if (!element) return;\r\n this.sortedCache = null;\r\n this._versions.delete(id);\r\n\r\n this.elements.delete(id);\r\n this.spatialIndex.remove(id);\r\n this.bus.emit('remove', element);\r\n }\r\n\r\n clear(): void {\r\n this.sortedCache = null;\r\n this._versions.clear();\r\n this.elements.clear();\r\n this.spatialIndex.clear();\r\n this.bus.emit('clear', null);\r\n }\r\n\r\n snapshot(): CanvasElement[] {\r\n return this.getAll().map((el) => ({ ...el }));\r\n }\r\n\r\n loadSnapshot(elements: CanvasElement[]): void {\r\n this.sortedCache = null;\r\n this._versions.clear();\r\n this.elements.clear();\r\n this.spatialIndex.clear();\r\n for (const el of elements) {\r\n this.elements.set(el.id, el);\r\n this._versions.set(el.id, 0);\r\n const bounds = getElementBounds(el);\r\n if (bounds) this.spatialIndex.insert(el.id, bounds);\r\n if (el.type === 'stroke') {\r\n computeStrokeSegments(el);\r\n }\r\n if (el.type === 'arrow' && el.bend !== 0 && !el.cachedControlPoint) {\r\n el.cachedControlPoint = getArrowControlPoint(el.from, el.to, el.bend);\r\n }\r\n }\r\n this.bus.emit('clear', null);\r\n for (const el of elements) {\r\n this.bus.emit('add', el);\r\n }\r\n }\r\n\r\n bringToFront(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const siblings = [...this.elements.values()].filter(\r\n (e) => e.layerId === el.layerId && e.id !== id,\r\n );\r\n if (siblings.length === 0) return;\r\n const maxZ = Math.max(...siblings.map((e) => e.zIndex));\r\n if (el.zIndex >= maxZ) return;\r\n this.update(id, { zIndex: maxZ + 1 });\r\n }\r\n\r\n sendToBack(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const siblings = [...this.elements.values()].filter(\r\n (e) => e.layerId === el.layerId && e.id !== id,\r\n );\r\n if (siblings.length === 0) return;\r\n const minZ = Math.min(...siblings.map((e) => e.zIndex));\r\n if (el.zIndex <= minZ) return;\r\n this.update(id, { zIndex: minZ - 1 });\r\n }\r\n\r\n bringForward(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const sorted = [...this.elements.values()]\r\n .filter((e) => e.layerId === el.layerId)\r\n .sort((a, b) => a.zIndex - b.zIndex);\r\n const idx = sorted.findIndex((e) => e.id === id);\r\n if (idx < 0 || idx >= sorted.length - 1) return;\r\n const next = sorted[idx + 1];\r\n if (!next) return;\r\n const myZ = el.zIndex;\r\n const nextZ = next.zIndex;\r\n this.update(id, { zIndex: nextZ });\r\n this.update(next.id, { zIndex: myZ });\r\n }\r\n\r\n sendBackward(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const sorted = [...this.elements.values()]\r\n .filter((e) => e.layerId === el.layerId)\r\n .sort((a, b) => a.zIndex - b.zIndex);\r\n const idx = sorted.findIndex((e) => e.id === id);\r\n if (idx <= 0) return;\r\n const prev = sorted[idx - 1];\r\n if (!prev) return;\r\n const myZ = el.zIndex;\r\n const prevZ = prev.zIndex;\r\n this.update(id, { zIndex: prevZ });\r\n this.update(prev.id, { zIndex: myZ });\r\n }\r\n\r\n queryRect(rect: Bounds): CanvasElement[] {\r\n const ids = this.spatialIndex.query(rect);\r\n const elements: CanvasElement[] = [];\r\n for (const id of ids) {\r\n const el = this.elements.get(id);\r\n if (el) elements.push(el);\r\n }\r\n return elements.sort((a, b) => {\r\n const layerA = this.layerOrderMap.get(a.layerId) ?? 0;\r\n const layerB = this.layerOrderMap.get(b.layerId) ?? 0;\r\n if (layerA !== layerB) return layerA - layerB;\r\n return a.zIndex - b.zIndex;\r\n });\r\n }\r\n\r\n queryPoint(point: Point): CanvasElement[] {\r\n return this.queryRect({ x: point.x, y: point.y, w: 0, h: 0 });\r\n }\r\n\r\n on<K extends keyof ElementStoreEvents>(\r\n event: K,\r\n listener: (data: ElementStoreEvents[K]) => void,\r\n ): () => void {\r\n return this.bus.on(event, listener);\r\n }\r\n\r\n onChange(listener: () => void): () => void {\r\n const unsubs = [\r\n this.bus.on('add', listener),\r\n this.bus.on('remove', listener),\r\n this.bus.on('update', listener),\r\n this.bus.on('clear', listener),\r\n ];\r\n return () => unsubs.forEach((fn) => fn());\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\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\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 { 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 { Point } from '../core/types';\r\nimport type { HexOrientation } from './types';\r\n\r\ninterface HexCoord {\r\n col: number;\r\n row: number;\r\n}\r\n\r\nfunction offsetToCube(\r\n col: number,\r\n row: number,\r\n orientation: HexOrientation,\r\n): { q: number; r: number } {\r\n if (orientation === 'pointy') {\r\n return { q: col - (row - (row & 1)) / 2, r: row };\r\n }\r\n return { q: col, r: row - (col - (col & 1)) / 2 };\r\n}\r\n\r\nfunction cubeToOffset(q: number, r: number, orientation: HexOrientation): HexCoord {\r\n if (orientation === 'pointy') {\r\n return { col: q + (r - (r & 1)) / 2, row: r };\r\n }\r\n return { col: q, row: r + (q - (q & 1)) / 2 };\r\n}\r\n\r\nfunction offsetToPixel(\r\n col: number,\r\n row: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point {\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * cellSize;\r\n const rowH = 1.5 * cellSize;\r\n const offsetX = row % 2 !== 0 ? hexW / 2 : 0;\r\n return { x: col * hexW + offsetX, y: row * rowH };\r\n }\r\n const hexH = Math.sqrt(3) * cellSize;\r\n const colW = 1.5 * cellSize;\r\n const offsetY = col % 2 !== 0 ? hexH / 2 : 0;\r\n return { x: col * colW, y: row * hexH + offsetY };\r\n}\r\n\r\nfunction pixelToOffset(\r\n x: number,\r\n y: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): HexCoord {\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * cellSize;\r\n const rowH = 1.5 * cellSize;\r\n const row = Math.round(y / rowH);\r\n const offsetX = row % 2 !== 0 ? hexW / 2 : 0;\r\n return { col: Math.round((x - offsetX) / hexW), row };\r\n }\r\n const hexH = Math.sqrt(3) * cellSize;\r\n const colW = 1.5 * cellSize;\r\n const col = Math.round(x / colW);\r\n const offsetY = col % 2 !== 0 ? hexH / 2 : 0;\r\n return { col, row: Math.round((y - offsetY) / hexH) };\r\n}\r\n\r\nfunction enumerateHexRing(\r\n centerQ: number,\r\n centerR: number,\r\n n: number,\r\n orientation: HexOrientation,\r\n cellSize: number,\r\n): Point[] {\r\n const cells: Point[] = [];\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n const absQ = centerQ + dq;\r\n const absR = centerR + dr;\r\n const off = cubeToOffset(absQ, absR, orientation);\r\n cells.push(offsetToPixel(off.col, off.row, cellSize, orientation));\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function getHexDistance(\r\n a: Point,\r\n b: Point,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): number {\r\n const offA = pixelToOffset(a.x, a.y, cellSize, orientation);\r\n const offB = pixelToOffset(b.x, b.y, cellSize, orientation);\r\n const cubeA = offsetToCube(offA.col, offA.row, orientation);\r\n const cubeB = offsetToCube(offB.col, offB.row, orientation);\r\n const dq = cubeA.q - cubeB.q;\r\n const dr = cubeA.r - cubeB.r;\r\n const ds = -dq - dr;\r\n return Math.max(Math.abs(dq), Math.abs(dr), Math.abs(ds));\r\n}\r\n\r\nexport function getHexCellsInRadius(\r\n center: Point,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n if (n <= 0) {\r\n return [offsetToPixel(off.col, off.row, cellSize, orientation)];\r\n }\r\n return enumerateHexRing(cube.q, cube.r, n, orientation, cellSize);\r\n}\r\n\r\nexport function getHexCellsInCone(\r\n center: Point,\r\n angle: number,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n const centerPixel = offsetToPixel(off.col, off.row, cellSize, orientation);\r\n\r\n if (n <= 0) return [centerPixel];\r\n\r\n const vertexOffset = orientation === 'pointy' ? Math.PI / 6 : 0;\r\n const step = Math.PI / 3;\r\n const snappedAngle = Math.round((angle - vertexOffset) / step) * step + vertexOffset;\r\n\r\n const halfAngle = Math.PI / 6 + 1e-6;\r\n const cells: Point[] = [centerPixel];\r\n\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n if (dq === 0 && dr === 0) continue;\r\n const absQ = cube.q + dq;\r\n const absR = cube.r + dr;\r\n const pixel = offsetToPixel(\r\n cubeToOffset(absQ, absR, orientation).col,\r\n cubeToOffset(absQ, absR, orientation).row,\r\n cellSize,\r\n orientation,\r\n );\r\n\r\n const dx = pixel.x - centerPixel.x;\r\n const dy = pixel.y - centerPixel.y;\r\n let diff = Math.atan2(dy, dx) - snappedAngle;\r\n if (diff > Math.PI) diff -= 2 * Math.PI;\r\n if (diff < -Math.PI) diff += 2 * Math.PI;\r\n\r\n if (Math.abs(diff) <= halfAngle) {\r\n cells.push(pixel);\r\n }\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function getHexCellsInLine(\r\n center: Point,\r\n angle: number,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n const centerPixel = offsetToPixel(off.col, off.row, cellSize, orientation);\r\n\r\n if (n <= 0) return [centerPixel];\r\n\r\n const vertexOffset = orientation === 'pointy' ? Math.PI / 6 : 0;\r\n const step = Math.PI / 3;\r\n const snappedAngle = Math.round((angle - vertexOffset) / step) * step + vertexOffset;\r\n\r\n const cos = Math.cos(snappedAngle);\r\n const sin = Math.sin(snappedAngle);\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const lineLength = n * snapUnit;\r\n const halfWidth = snapUnit * 0.5 + 1e-6;\r\n const cells: Point[] = [];\r\n\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n const absQ = cube.q + dq;\r\n const absR = cube.r + dr;\r\n const pixel = offsetToPixel(\r\n cubeToOffset(absQ, absR, orientation).col,\r\n cubeToOffset(absQ, absR, orientation).row,\r\n cellSize,\r\n orientation,\r\n );\r\n\r\n const dx = pixel.x - centerPixel.x;\r\n const dy = pixel.y - centerPixel.y;\r\n const along = dx * cos + dy * sin;\r\n const perp = Math.abs(-dx * sin + dy * cos);\r\n\r\n if (along >= -snapUnit * 0.1 && along <= lineLength + snapUnit * 0.1 && perp <= halfWidth) {\r\n cells.push(pixel);\r\n }\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function getHexCellsInSquare(\r\n center: Point,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n const centerPixel = offsetToPixel(off.col, off.row, cellSize, orientation);\r\n\r\n if (n <= 0) return [centerPixel];\r\n\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const halfSide = (n * snapUnit) / 2;\r\n const cells: Point[] = [];\r\n\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n const absQ = cube.q + dq;\r\n const absR = cube.r + dr;\r\n const pixel = offsetToPixel(\r\n cubeToOffset(absQ, absR, orientation).col,\r\n cubeToOffset(absQ, absR, orientation).row,\r\n cellSize,\r\n orientation,\r\n );\r\n\r\n if (\r\n Math.abs(pixel.x - centerPixel.x) <= halfSide &&\r\n Math.abs(pixel.y - centerPixel.y) <= halfSide\r\n ) {\r\n cells.push(pixel);\r\n }\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function drawHexPath(\r\n ctx: CanvasRenderingContext2D,\r\n cx: number,\r\n cy: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): void {\r\n const angleOffset = orientation === 'pointy' ? Math.PI / 6 : 0;\r\n ctx.moveTo(cx + cellSize * Math.cos(angleOffset), cy + cellSize * Math.sin(angleOffset));\r\n for (let i = 1; i < 6; i++) {\r\n const a = angleOffset + (Math.PI / 3) * i;\r\n ctx.lineTo(cx + cellSize * Math.cos(a), cy + cellSize * Math.sin(a));\r\n }\r\n ctx.closePath();\r\n}\r\n","import type {\r\n CanvasElement,\r\n StrokeElement,\r\n ArrowElement,\r\n ShapeElement,\r\n ImageElement,\r\n GridElement,\r\n TemplateElement,\r\n} from './types';\r\nimport { getArrowRenderGeometry } from './arrow-render-cache';\r\nimport { getEdgeIntersection } from './arrow-binding';\r\nimport { getElementBounds } from './element-bounds';\r\nimport { getStrokeRenderData } from './stroke-cache';\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\nimport {\r\n getHexCellsInRadius,\r\n getHexCellsInCone,\r\n getHexCellsInLine,\r\n getHexCellsInSquare,\r\n drawHexPath,\r\n} from './hex-fill';\r\n\r\nconst DOM_ELEMENT_TYPES = new Set(['note', 'html', 'text']);\r\nconst ARROWHEAD_LENGTH = 12;\r\nconst ARROWHEAD_ANGLE = Math.PI / 6;\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\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 isDomElement(element: CanvasElement): boolean {\r\n return DOM_ELEMENT_TYPES.has(element.type);\r\n }\r\n\r\n renderCanvasElement(ctx: CanvasRenderingContext2D, element: CanvasElement): void {\r\n switch (element.type) {\r\n case 'stroke':\r\n this.renderStroke(ctx, element);\r\n break;\r\n case 'arrow':\r\n this.renderArrow(ctx, element);\r\n break;\r\n case 'shape':\r\n this.renderShape(ctx, element);\r\n break;\r\n case 'image':\r\n this.renderImage(ctx, element);\r\n break;\r\n case 'grid':\r\n this.renderGrid(ctx, element);\r\n break;\r\n case 'template':\r\n this.renderTemplate(ctx, element);\r\n break;\r\n }\r\n }\r\n\r\n private renderStroke(ctx: CanvasRenderingContext2D, stroke: StrokeElement): void {\r\n if (stroke.points.length < 2) return;\r\n\r\n ctx.save();\r\n ctx.translate(stroke.position.x, stroke.position.y);\r\n ctx.strokeStyle = stroke.color;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n ctx.globalAlpha = stroke.opacity;\r\n\r\n const 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\r\n private renderArrow(ctx: CanvasRenderingContext2D, arrow: ArrowElement): void {\r\n const geometry = getArrowRenderGeometry(arrow);\r\n const { visualFrom, visualTo } = this.getVisualEndpoints(arrow, geometry);\r\n\r\n ctx.save();\r\n ctx.strokeStyle = arrow.color;\r\n ctx.lineWidth = arrow.width;\r\n ctx.lineCap = 'round';\r\n\r\n if (arrow.fromBinding || arrow.toBinding) {\r\n ctx.setLineDash([8, 4]);\r\n }\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(visualFrom.x, visualFrom.y);\r\n\r\n if (arrow.bend !== 0) {\r\n const cp = geometry.controlPoint;\r\n if (cp) {\r\n ctx.quadraticCurveTo(cp.x, cp.y, visualTo.x, visualTo.y);\r\n }\r\n } else {\r\n ctx.lineTo(visualTo.x, visualTo.y);\r\n }\r\n ctx.stroke();\r\n\r\n this.renderArrowhead(ctx, arrow, visualTo, geometry.tangentEnd);\r\n ctx.restore();\r\n }\r\n\r\n private 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\n private getVisualEndpoints(\r\n arrow: ArrowElement,\r\n geometry: ReturnType<typeof getArrowRenderGeometry>,\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 (!this.store) return { visualFrom, visualTo };\r\n\r\n if (arrow.fromBinding) {\r\n const el = this.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 = this.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\r\n private renderShape(ctx: CanvasRenderingContext2D, shape: ShapeElement): void {\r\n ctx.save();\r\n\r\n if (shape.fillColor !== 'none') {\r\n ctx.fillStyle = shape.fillColor;\r\n this.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 this.strokeShapePath(ctx, shape);\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private 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\n private 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 }\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 renderTemplate(ctx: CanvasRenderingContext2D, template: TemplateElement): void {\r\n const grid = this.store?.getElementsByType('grid')[0];\r\n if (grid && grid.gridType === 'hex') {\r\n this.renderHexTemplate(ctx, template, grid.cellSize, grid.hexOrientation);\r\n return;\r\n }\r\n\r\n this.renderGeometricTemplate(ctx, template);\r\n }\r\n\r\n private renderGeometricTemplate(ctx: CanvasRenderingContext2D, template: TemplateElement): void {\r\n const { x: cx, y: cy } = template.position;\r\n const r = template.radius;\r\n\r\n ctx.save();\r\n ctx.globalAlpha = template.opacity;\r\n ctx.fillStyle = template.fillColor;\r\n ctx.strokeStyle = template.strokeColor;\r\n ctx.lineWidth = template.strokeWidth;\r\n\r\n switch (template.templateShape) {\r\n case 'circle':\r\n ctx.beginPath();\r\n ctx.arc(cx, cy, r, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.stroke();\r\n if (template.radiusFeet != null && template.radiusFeet > 0) {\r\n this.renderRadiusMarker(ctx, cx, cy, r, template.radiusFeet);\r\n }\r\n break;\r\n\r\n case 'square':\r\n ctx.fillRect(cx - r / 2, cy - r / 2, r, r);\r\n ctx.strokeRect(cx - r / 2, cy - r / 2, r, r);\r\n break;\r\n\r\n case 'cone': {\r\n const halfAngle = Math.atan(0.5);\r\n ctx.beginPath();\r\n ctx.moveTo(cx, cy);\r\n ctx.arc(cx, cy, r, template.angle - halfAngle, template.angle + halfAngle);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n\r\n case 'line': {\r\n const halfW = r / 12;\r\n const cos = Math.cos(template.angle);\r\n const sin = Math.sin(template.angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(cx + perpX, cy + perpY);\r\n ctx.lineTo(cx + r * cos + perpX, cy + r * sin + perpY);\r\n ctx.lineTo(cx + r * cos - perpX, cy + r * sin - perpY);\r\n ctx.lineTo(cx - perpX, cy - perpY);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private renderHexTemplate(\r\n ctx: CanvasRenderingContext2D,\r\n template: TemplateElement,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n ): void {\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const radiusCells = template.radius / snapUnit;\r\n const center = template.position;\r\n\r\n let cells: { x: number; y: number }[];\r\n switch (template.templateShape) {\r\n case 'circle':\r\n cells = getHexCellsInRadius(center, radiusCells, cellSize, orientation);\r\n break;\r\n case 'cone':\r\n cells = getHexCellsInCone(center, template.angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'line':\r\n cells = getHexCellsInLine(center, template.angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'square':\r\n cells = getHexCellsInSquare(center, radiusCells, cellSize, orientation);\r\n break;\r\n }\r\n\r\n ctx.save();\r\n ctx.globalAlpha = template.opacity;\r\n\r\n ctx.beginPath();\r\n for (const cell of cells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.fillStyle = template.fillColor;\r\n ctx.fill();\r\n\r\n ctx.beginPath();\r\n for (const cell of cells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.strokeStyle = template.strokeColor;\r\n ctx.lineWidth = template.strokeWidth;\r\n ctx.stroke();\r\n\r\n {\r\n ctx.globalAlpha = Math.min(template.opacity + 0.1, 1);\r\n ctx.beginPath();\r\n drawHexPath(ctx, center.x, center.y, cellSize, orientation);\r\n ctx.fillStyle = template.strokeColor;\r\n ctx.fill();\r\n ctx.strokeStyle = template.strokeColor;\r\n ctx.lineWidth = template.strokeWidth;\r\n ctx.stroke();\r\n }\r\n\r\n if (\r\n template.templateShape === 'circle' &&\r\n template.radiusFeet != null &&\r\n template.radiusFeet > 0\r\n ) {\r\n const r = template.radius;\r\n this.renderRadiusMarker(ctx, center.x, center.y, r, template.radiusFeet);\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private renderRadiusMarker(\r\n ctx: CanvasRenderingContext2D,\r\n cx: number,\r\n cy: number,\r\n r: number,\r\n feet: number,\r\n ): void {\r\n const markerColor = ctx.strokeStyle as string;\r\n\r\n ctx.save();\r\n ctx.globalAlpha = 1;\r\n\r\n ctx.beginPath();\r\n ctx.setLineDash([4, 4]);\r\n ctx.strokeStyle = markerColor;\r\n ctx.lineWidth = 1.5;\r\n ctx.moveTo(cx, cy);\r\n ctx.lineTo(cx + r, cy);\r\n ctx.stroke();\r\n ctx.setLineDash([]);\r\n\r\n const label = `${Math.round(feet)} ft`;\r\n const fontSize = Math.max(10, Math.min(14, r * 0.15));\r\n ctx.font = `bold ${fontSize}px system-ui, sans-serif`;\r\n ctx.textAlign = 'center';\r\n ctx.textBaseline = 'bottom';\r\n const textX = cx + r / 2;\r\n const textY = cy - 4;\r\n\r\n const metrics = ctx.measureText(label);\r\n const padX = 4;\r\n const padY = 2;\r\n const textW = metrics.width + padX * 2;\r\n const textH = fontSize + padY * 2;\r\n\r\n ctx.fillStyle = 'rgba(255, 255, 255, 0.85)';\r\n ctx.beginPath();\r\n ctx.roundRect(textX - textW / 2, textY - textH, textW, textH, 3);\r\n ctx.fill();\r\n\r\n ctx.fillStyle = markerColor;\r\n ctx.fillText(label, textX, textY - padY);\r\n\r\n ctx.restore();\r\n }\r\n\r\n private renderImage(ctx: CanvasRenderingContext2D, image: ImageElement): void {\r\n if (this.imageCache.get(image.src) === 'failed') {\r\n this.renderImagePlaceholder(ctx, image);\r\n return;\r\n }\r\n const img = this.getImage(image.src);\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\n private 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\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 private getImage(src: string): ImageBitmap | HTMLImageElement | null {\r\n const cached = this.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 this.imageCache.set(src, img);\r\n img.onload = () => {\r\n this.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 this.imageCache.set(src, bitmap);\r\n this.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 this.imageCache.set(src, 'failed');\r\n this.onImageError?.(src, event);\r\n this.onImageLoad?.();\r\n };\r\n return null;\r\n }\r\n}\r\n","import type { Point, Size, StrokePoint } from '../core/types';\r\nimport type {\r\n Binding,\r\n StrokeElement,\r\n NoteElement,\r\n ArrowElement,\r\n ImageElement,\r\n HtmlElement,\r\n TextElement,\r\n ShapeElement,\r\n ShapeKind,\r\n GridElement,\r\n HexOrientation,\r\n TemplateElement,\r\n TemplateShape,\r\n} from './types';\r\nimport { createId } from './create-id';\r\nimport { getArrowControlPoint } from './arrow-geometry';\r\nimport { sanitizeNoteHtml } from './note-sanitizer';\r\n\r\nexport const DEFAULT_NOTE_FONT_SIZE = 18;\r\n\r\ninterface BaseDefaults {\r\n position?: Point;\r\n zIndex?: number;\r\n locked?: boolean;\r\n layerId?: string;\r\n}\r\n\r\ninterface StrokeInput extends BaseDefaults {\r\n points: StrokePoint[];\r\n color?: string;\r\n width?: number;\r\n opacity?: number;\r\n}\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}\r\n\r\ninterface ImageInput extends BaseDefaults {\r\n position: Point;\r\n size: Size;\r\n src: string;\r\n}\r\n\r\ninterface HtmlInput extends BaseDefaults {\r\n position: Point;\r\n size: Size;\r\n domId?: string;\r\n interactive?: boolean;\r\n}\r\n\r\ninterface TextInput extends BaseDefaults {\r\n position: Point;\r\n size?: Size;\r\n text?: string;\r\n fontSize?: number;\r\n color?: string;\r\n textAlign?: 'left' | 'center' | 'right';\r\n}\r\n\r\nexport function createStroke(input: StrokeInput): StrokeElement {\r\n return {\r\n id: createId('stroke'),\r\n type: 'stroke',\r\n position: input.position ?? { x: 0, y: 0 },\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n 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}\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 return result;\r\n}\r\n\r\nexport function createImage(input: ImageInput): ImageElement {\r\n return {\r\n id: createId('image'),\r\n type: 'image',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n size: input.size,\r\n src: input.src,\r\n };\r\n}\r\n\r\nexport function createHtmlElement(input: HtmlInput): HtmlElement {\r\n const el: HtmlElement = {\r\n id: createId('html'),\r\n type: 'html',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n size: input.size,\r\n };\r\n if (input.domId) el.domId = input.domId;\r\n if (input.interactive) el.interactive = input.interactive;\r\n return el;\r\n}\r\n\r\ninterface ShapeInput extends BaseDefaults {\r\n position: Point;\r\n size: Size;\r\n shape?: ShapeKind;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n fillColor?: string;\r\n}\r\n\r\nexport function createShape(input: ShapeInput): ShapeElement {\r\n return {\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}\r\n\r\ninterface GridInput extends BaseDefaults {\r\n gridType?: 'square' | 'hex';\r\n hexOrientation?: HexOrientation;\r\n cellSize?: number;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n}\r\n\r\nexport function createGrid(input: GridInput): GridElement {\r\n return {\r\n id: createId('grid'),\r\n type: 'grid',\r\n position: input.position ?? { x: 0, y: 0 },\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n gridType: input.gridType ?? 'square',\r\n hexOrientation: input.hexOrientation ?? 'pointy',\r\n cellSize: input.cellSize ?? 40,\r\n strokeColor: input.strokeColor ?? '#000000',\r\n strokeWidth: input.strokeWidth ?? 1,\r\n opacity: input.opacity ?? 1,\r\n };\r\n}\r\n\r\nexport function createText(input: TextInput): TextElement {\r\n return {\r\n id: createId('text'),\r\n type: 'text',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n size: input.size ?? { w: 200, h: 28 },\r\n text: input.text ?? '',\r\n fontSize: input.fontSize ?? 16,\r\n color: input.color ?? '#1a1a1a',\r\n textAlign: input.textAlign ?? 'left',\r\n };\r\n}\r\n\r\ninterface TemplateInput extends BaseDefaults {\r\n position: Point;\r\n templateShape: TemplateShape;\r\n radius: number;\r\n angle?: number;\r\n fillColor?: string;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n feetPerCell?: number;\r\n radiusFeet?: number;\r\n}\r\n\r\nexport function createTemplate(input: TemplateInput): TemplateElement {\r\n return {\r\n id: createId('template'),\r\n type: 'template',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n templateShape: input.templateShape,\r\n radius: input.radius,\r\n angle: input.angle ?? 0,\r\n fillColor: input.fillColor ?? 'rgba(255, 87, 34, 0.2)',\r\n strokeColor: input.strokeColor ?? '#FF5722',\r\n strokeWidth: input.strokeWidth ?? 2,\r\n opacity: input.opacity ?? 0.6,\r\n feetPerCell: input.feetPerCell,\r\n radiusFeet: input.radiusFeet,\r\n };\r\n}\r\n","export interface ActiveFormats {\r\n bold: boolean;\r\n italic: boolean;\r\n underline: boolean;\r\n strikethrough: boolean;\r\n}\r\n\r\nexport function toggleBold(): void {\r\n document.execCommand('bold');\r\n}\r\n\r\nexport function toggleItalic(): void {\r\n document.execCommand('italic');\r\n}\r\n\r\nexport function toggleUnderline(): void {\r\n document.execCommand('underline');\r\n}\r\n\r\nexport function toggleStrikethrough(): void {\r\n document.execCommand('strikeThrough');\r\n}\r\n\r\nexport function setFontSize(size: number): void {\r\n const sel = window.getSelection();\r\n if (!sel || sel.rangeCount === 0) return;\r\n\r\n const range = sel.getRangeAt(0);\r\n if (range.collapsed) return;\r\n\r\n const span = document.createElement('span');\r\n span.style.fontSize = `${size}px`;\r\n try {\r\n range.surroundContents(span);\r\n } catch {\r\n span.appendChild(range.extractContents());\r\n range.insertNode(span);\r\n }\r\n}\r\n\r\nexport function getActiveFormats(): ActiveFormats {\r\n const query = (cmd: string): boolean => {\r\n try {\r\n return document.queryCommandState(cmd);\r\n } catch {\r\n return false;\r\n }\r\n };\r\n\r\n return {\r\n bold: query('bold'),\r\n italic: query('italic'),\r\n underline: query('underline'),\r\n strikethrough: query('strikeThrough'),\r\n };\r\n}\r\n","import { DEFAULT_NOTE_FONT_SIZE } from './element-factory';\r\nimport { setFontSize, getActiveFormats } from './note-formatting';\r\n\r\nconst TOOLBAR_HEIGHT = 52;\r\nconst TOOLBAR_GAP = 4;\r\n\r\ninterface FormatButton {\r\n label: string;\r\n format: string;\r\n command: string;\r\n}\r\n\r\nconst FORMAT_BUTTONS: FormatButton[] = [\r\n { label: 'B', format: 'bold', command: 'bold' },\r\n { label: 'I', format: 'italic', command: 'italic' },\r\n { label: 'U', format: 'underline', command: 'underline' },\r\n { label: 'S', format: 'strikethrough', command: 'strikeThrough' },\r\n];\r\n\r\nexport interface FontSizePreset {\r\n label: string;\r\n size: number;\r\n}\r\n\r\nexport const DEFAULT_FONT_SIZE_PRESETS: FontSizePreset[] = [\r\n { label: 'Small', size: 14 },\r\n { label: 'Normal', size: 18 },\r\n { label: 'Large', size: 24 },\r\n { label: 'Heading', size: 32 },\r\n];\r\n\r\nexport class NoteToolbar {\r\n private el: HTMLDivElement | null = null;\r\n private anchor: HTMLElement | null = null;\r\n private selectionListener: (() => void) | null = null;\r\n private readonly fontSizePresets: FontSizePreset[];\r\n\r\n constructor(fontSizePresets?: FontSizePreset[]) {\r\n this.fontSizePresets = fontSizePresets ?? DEFAULT_FONT_SIZE_PRESETS;\r\n }\r\n\r\n show(anchor: HTMLElement): void {\r\n this.hide();\r\n this.anchor = anchor;\r\n this.el = this.createToolbarElement();\r\n document.body.appendChild(this.el);\r\n this.positionToolbar(anchor);\r\n this.selectionListener = () => this.updateActiveStates();\r\n document.addEventListener('selectionchange', this.selectionListener);\r\n }\r\n\r\n hide(): void {\r\n if (this.selectionListener) {\r\n document.removeEventListener('selectionchange', this.selectionListener);\r\n this.selectionListener = null;\r\n }\r\n if (this.el) {\r\n this.el.remove();\r\n this.el = null;\r\n }\r\n this.anchor = null;\r\n }\r\n\r\n getElement(): HTMLDivElement | null {\r\n return this.el;\r\n }\r\n\r\n updatePosition(anchor: HTMLElement): void {\r\n if (this.el) {\r\n this.positionToolbar(anchor);\r\n }\r\n }\r\n\r\n private createToolbarElement(): HTMLDivElement {\r\n const toolbar = document.createElement('div');\r\n toolbar.dataset['noteToolbar'] = '';\r\n Object.assign(toolbar.style, {\r\n position: 'fixed',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '2px',\r\n padding: '2px 4px',\r\n background: '#fff',\r\n border: '1px solid #ccc',\r\n borderRadius: '4px',\r\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\r\n zIndex: '10000',\r\n height: `${TOOLBAR_HEIGHT}px`,\r\n userSelect: 'none',\r\n });\r\n\r\n for (const btn of FORMAT_BUTTONS) {\r\n toolbar.appendChild(this.createFormatButton(btn));\r\n }\r\n\r\n toolbar.appendChild(this.createFontSizeSelect());\r\n\r\n return toolbar;\r\n }\r\n\r\n private createFormatButton(config: FormatButton): HTMLButtonElement {\r\n const btn = document.createElement('button');\r\n btn.dataset['format'] = config.format;\r\n btn.textContent = config.label;\r\n Object.assign(btn.style, {\r\n border: '1px solid transparent',\r\n borderRadius: '3px',\r\n background: 'none',\r\n cursor: 'pointer',\r\n padding: '2px 6px',\r\n fontSize: '13px',\r\n fontWeight: config.format === 'bold' ? 'bold' : 'normal',\r\n fontStyle: config.format === 'italic' ? 'italic' : 'normal',\r\n textDecoration:\r\n config.format === 'underline'\r\n ? 'underline'\r\n : config.format === 'strikethrough'\r\n ? 'line-through'\r\n : 'none',\r\n minWidth: '44px',\r\n height: '44px',\r\n lineHeight: '44px',\r\n });\r\n\r\n btn.addEventListener('pointerdown', (e) => {\r\n e.preventDefault();\r\n document.execCommand(config.command);\r\n this.updateActiveStates();\r\n });\r\n\r\n return btn;\r\n }\r\n\r\n private createFontSizeSelect(): HTMLSelectElement {\r\n const select = document.createElement('select');\r\n Object.assign(select.style, {\r\n border: '1px solid #ccc',\r\n borderRadius: '3px',\r\n background: '#fff',\r\n cursor: 'pointer',\r\n padding: '2px',\r\n fontSize: '12px',\r\n height: '44px',\r\n marginLeft: '4px',\r\n });\r\n\r\n for (const preset of this.fontSizePresets) {\r\n const option = document.createElement('option');\r\n option.value = String(preset.size);\r\n option.textContent = preset.label;\r\n select.appendChild(option);\r\n }\r\n\r\n select.value = String(DEFAULT_NOTE_FONT_SIZE);\r\n\r\n select.addEventListener('pointerdown', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n select.addEventListener('change', () => {\r\n setFontSize(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 positionToolbar(anchor: HTMLElement): void {\r\n if (!this.el) return;\r\n\r\n const rect = anchor.getBoundingClientRect();\r\n const toolbarWidth = this.el.offsetWidth || 200;\r\n\r\n let top = rect.top - TOOLBAR_HEIGHT - TOOLBAR_GAP;\r\n if (top < 0) {\r\n top = rect.bottom + TOOLBAR_GAP;\r\n }\r\n\r\n let left = rect.left + (rect.width - toolbarWidth) / 2;\r\n left = Math.max(4, left);\r\n\r\n Object.assign(this.el.style, {\r\n top: `${top}px`,\r\n left: `${left}px`,\r\n });\r\n }\r\n\r\n private updateActiveStates(): void {\r\n if (!this.el) return;\r\n\r\n const active = getActiveFormats();\r\n for (const config of FORMAT_BUTTONS) {\r\n const btn = this.el.querySelector(`[data-format=\"${config.format}\"]`) as HTMLElement | null;\r\n if (!btn) continue;\r\n\r\n const isActive = active[config.format as keyof typeof active] ?? false;\r\n btn.style.background = isActive ? '#e0e0e0' : 'none';\r\n btn.style.borderColor = isActive ? '#bbb' : 'transparent';\r\n }\r\n }\r\n}\r\n","import type { ElementStore } from './element-store';\r\nimport { NoteToolbar } from './note-toolbar';\r\nimport type { FontSizePreset } from './note-toolbar';\r\nimport { sanitizeNoteHtml } from './note-sanitizer';\r\nimport { toggleBold, toggleItalic, toggleUnderline } from './note-formatting';\r\n\r\nconst FORMAT_SHORTCUTS: Record<string, () => void> = {\r\n b: toggleBold,\r\n i: toggleItalic,\r\n u: toggleUnderline,\r\n};\r\n\r\nexport interface NoteEditorOptions {\r\n fontSizePresets?: FontSizePreset[];\r\n toolbar?: boolean;\r\n placeholder?: string;\r\n}\r\n\r\nfunction ensureEditorStyles(): void {\r\n if (document.querySelector('style[data-fieldnotes-editor]')) return;\r\n const style = document.createElement('style');\r\n style.setAttribute('data-fieldnotes-editor', '');\r\n style.textContent = `[data-fn-placeholder][data-fn-empty='true']::before {\r\n content: attr(data-fn-placeholder);\r\n color: #9e9e9e;\r\n position: absolute;\r\n pointer-events: none;\r\n}`;\r\n document.head.appendChild(style);\r\n}\r\n\r\nfunction isNodeEmpty(node: HTMLElement): boolean {\r\n const text = node.textContent ?? '';\r\n return text.replace(/\\u00a0/g, ' ').trim().length === 0;\r\n}\r\n\r\nexport class NoteEditor {\r\n private editingId: string | null = null;\r\n private editingNode: HTMLDivElement | null = null;\r\n private blurHandler: ((e: FocusEvent) => void) | null = null;\r\n private keyHandler: ((e: KeyboardEvent) => void) | null = null;\r\n private pointerHandler: ((e: PointerEvent) => void) | null = null;\r\n private inputHandler: (() => void) | null = null;\r\n private pendingEditId: string | null = null;\r\n private onStopCallback: ((elementId: string) => void) | null = null;\r\n private beginHistory: (() => void) | null = null;\r\n private commitHistory: (() => void) | null = null;\r\n private toolbar: NoteToolbar | null;\r\n private readonly placeholder: string;\r\n\r\n constructor(options?: NoteEditorOptions) {\r\n this.toolbar = options?.toolbar === false ? null : new NoteToolbar(options?.fontSizePresets);\r\n this.placeholder = options?.placeholder ?? 'Type…';\r\n }\r\n\r\n get isEditing(): boolean {\r\n return this.editingId !== null;\r\n }\r\n\r\n get editingElementId(): string | null {\r\n return this.editingId;\r\n }\r\n\r\n setOnStop(callback: (elementId: string) => void): void {\r\n this.onStopCallback = callback;\r\n }\r\n\r\n setHistoryHooks(begin: () => void, commit: () => void): void {\r\n this.beginHistory = begin;\r\n this.commitHistory = commit;\r\n }\r\n\r\n startEditing(node: HTMLDivElement, elementId: string, store: ElementStore): void {\r\n if (this.editingId === elementId) return;\r\n\r\n if (this.editingId) {\r\n this.stopEditing(store);\r\n }\r\n\r\n this.pendingEditId = elementId;\r\n\r\n requestAnimationFrame(() => {\r\n if (this.pendingEditId !== elementId) return;\r\n this.pendingEditId = null;\r\n this.activateEditing(node, elementId, store);\r\n });\r\n }\r\n\r\n stopEditing(store: ElementStore): void {\r\n this.pendingEditId = null;\r\n\r\n if (!this.editingId || !this.editingNode) return;\r\n\r\n if (this.blurHandler) {\r\n this.editingNode.removeEventListener('blur', this.blurHandler);\r\n }\r\n if (this.keyHandler) {\r\n this.editingNode.removeEventListener('keydown', this.keyHandler);\r\n }\r\n if (this.pointerHandler) {\r\n this.editingNode.removeEventListener('pointerdown', this.pointerHandler);\r\n }\r\n if (this.inputHandler) {\r\n this.editingNode.removeEventListener('input', this.inputHandler);\r\n }\r\n this.editingNode.removeAttribute('data-fn-placeholder');\r\n this.editingNode.removeAttribute('data-fn-empty');\r\n\r\n const text = sanitizeNoteHtml(this.editingNode.innerHTML);\r\n const current = store.getById(this.editingId);\r\n const textChanged =\r\n !!current && (current.type === 'note' || current.type === 'text') && current.text !== text;\r\n\r\n this.editingNode.contentEditable = 'false';\r\n Object.assign(this.editingNode.style, {\r\n userSelect: 'none',\r\n cursor: 'default',\r\n });\r\n\r\n this.toolbar?.hide();\r\n\r\n // One history transaction spans the text write and the onStop height-fit/cleanup,\r\n // so a single note/text edit collapses to one undo step (both touch the same element).\r\n this.beginHistory?.();\r\n if (textChanged) {\r\n store.update(this.editingId, { text });\r\n }\r\n if (this.editingId && this.onStopCallback) {\r\n this.onStopCallback(this.editingId);\r\n }\r\n this.commitHistory?.();\r\n\r\n this.editingId = null;\r\n this.editingNode = null;\r\n this.blurHandler = null;\r\n this.keyHandler = null;\r\n this.pointerHandler = null;\r\n this.inputHandler = null;\r\n }\r\n\r\n destroy(store: ElementStore): void {\r\n this.pendingEditId = null;\r\n if (this.isEditing) {\r\n this.stopEditing(store);\r\n }\r\n }\r\n\r\n updateToolbarPosition(): void {\r\n if (this.editingNode) {\r\n this.toolbar?.updatePosition(this.editingNode);\r\n }\r\n }\r\n\r\n private activateEditing(node: HTMLDivElement, elementId: string, store: ElementStore): void {\r\n this.editingId = elementId;\r\n this.editingNode = node;\r\n\r\n node.contentEditable = 'true';\r\n Object.assign(node.style, {\r\n userSelect: 'text',\r\n cursor: 'text',\r\n outline: 'none',\r\n });\r\n node.focus();\r\n\r\n const selection = window.getSelection?.();\r\n if (selection) {\r\n const range = document.createRange();\r\n range.selectNodeContents(node);\r\n range.collapse(false);\r\n selection.removeAllRanges();\r\n selection.addRange(range);\r\n }\r\n\r\n ensureEditorStyles();\r\n node.setAttribute('data-fn-placeholder', this.placeholder);\r\n node.setAttribute('data-fn-empty', String(isNodeEmpty(node)));\r\n this.inputHandler = () => {\r\n node.setAttribute('data-fn-empty', String(isNodeEmpty(node)));\r\n };\r\n node.addEventListener('input', this.inputHandler);\r\n\r\n this.toolbar?.show(node);\r\n\r\n this.blurHandler = (e: FocusEvent) => {\r\n const related = e.relatedTarget as Node | null;\r\n if (related && this.toolbar?.getElement()?.contains(related)) return;\r\n this.stopEditing(store);\r\n };\r\n this.keyHandler = (e: KeyboardEvent) => {\r\n if ((e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) {\r\n const action = FORMAT_SHORTCUTS[e.key.toLowerCase()];\r\n if (action) {\r\n e.preventDefault();\r\n action();\r\n return;\r\n }\r\n }\r\n if (e.key === 'Escape') {\r\n node.blur();\r\n }\r\n e.stopPropagation();\r\n };\r\n this.pointerHandler = (e: PointerEvent) => {\r\n e.stopPropagation();\r\n };\r\n\r\n node.addEventListener('blur', this.blurHandler);\r\n node.addEventListener('keydown', this.keyHandler);\r\n node.addEventListener('pointerdown', this.pointerHandler);\r\n }\r\n}\r\n","import type { Tool, ToolContext, PointerState } from './types';\r\n\r\nexport class ToolManager {\r\n private tools = new Map<string, Tool>();\r\n private current: Tool | null = null;\r\n private changeListeners = new Set<(name: string) => void>();\r\n\r\n get activeTool(): Tool | null {\r\n return this.current;\r\n }\r\n\r\n get toolNames(): string[] {\r\n return [...this.tools.keys()];\r\n }\r\n\r\n register(tool: Tool): void {\r\n this.tools.set(tool.name, tool);\r\n }\r\n\r\n getTool<T extends Tool = Tool>(name: string): T | undefined {\r\n return this.tools.get(name) as T | undefined;\r\n }\r\n\r\n setTool(name: string, ctx: ToolContext): void {\r\n const tool = this.tools.get(name);\r\n if (!tool) return;\r\n\r\n this.current?.onDeactivate?.(ctx);\r\n this.current = tool;\r\n this.current.onActivate?.(ctx);\r\n this.changeListeners.forEach((fn) => fn(name));\r\n }\r\n\r\n handlePointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.current?.onPointerDown(state, ctx);\r\n }\r\n\r\n handlePointerMove(state: PointerState, ctx: ToolContext): void {\r\n this.current?.onPointerMove(state, ctx);\r\n }\r\n\r\n handlePointerUp(state: PointerState, ctx: ToolContext): void {\r\n this.current?.onPointerUp(state, ctx);\r\n }\r\n\r\n onChange(listener: (name: string) => void): () => void {\r\n this.changeListeners.add(listener);\r\n return () => this.changeListeners.delete(listener);\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\nimport type { Command } from './types';\n\nexport interface HistoryStackOptions {\n maxSize?: number;\n}\n\nconst DEFAULT_MAX_SIZE = 100;\n\nexport class HistoryStack {\n private undoStack: Command[] = [];\n private redoStack: Command[] = [];\n private readonly maxSize: number;\n private changeListeners = new Set<() => void>();\n\n constructor(options: HistoryStackOptions = {}) {\n this.maxSize = options.maxSize ?? DEFAULT_MAX_SIZE;\n }\n\n get canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n get canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n get undoCount(): number {\n return this.undoStack.length;\n }\n\n get redoCount(): number {\n return this.redoStack.length;\n }\n\n push(command: Command): void {\n this.undoStack.push(command);\n this.redoStack = [];\n\n if (this.undoStack.length > this.maxSize) {\n this.undoStack.shift();\n }\n\n this.notifyChange();\n }\n\n undo(store: ElementStore): boolean {\n const command = this.undoStack.pop();\n if (!command) return false;\n\n command.undo(store);\n this.redoStack.push(command);\n this.notifyChange();\n return true;\n }\n\n redo(store: ElementStore): boolean {\n const command = this.redoStack.pop();\n if (!command) return false;\n\n command.execute(store);\n this.undoStack.push(command);\n this.notifyChange();\n return true;\n }\n\n clear(): void {\n this.undoStack = [];\n this.redoStack = [];\n this.notifyChange();\n }\n\n onChange(listener: () => void): () => void {\n this.changeListeners.add(listener);\n return () => this.changeListeners.delete(listener);\n }\n\n private notifyChange(): void {\n this.changeListeners.forEach((fn) => fn());\n }\n}\n","import type { CanvasElement } from '../elements/types';\nimport type { ElementStore } from '../elements/element-store';\nimport type { Command } from './types';\n\nexport class AddElementCommand implements Command {\n private readonly element: CanvasElement;\n\n constructor(element: CanvasElement) {\n this.element = { ...element };\n }\n\n execute(store: ElementStore): void {\n store.add(this.element);\n }\n\n undo(store: ElementStore): void {\n store.remove(this.element.id);\n }\n}\n\nexport class RemoveElementCommand implements Command {\n private readonly element: CanvasElement;\n\n constructor(element: CanvasElement) {\n this.element = { ...element };\n }\n\n execute(store: ElementStore): void {\n store.remove(this.element.id);\n }\n\n undo(store: ElementStore): void {\n store.add(this.element);\n }\n}\n\nexport class UpdateElementCommand implements Command {\n constructor(\n private readonly id: string,\n private readonly previous: CanvasElement,\n private readonly current: CanvasElement,\n ) {}\n\n execute(store: ElementStore): void {\n store.update(this.id, { ...this.current });\n }\n\n undo(store: ElementStore): void {\n store.update(this.id, { ...this.previous });\n }\n}\n\nexport class BatchCommand implements Command {\n readonly commands: readonly Command[];\n\n constructor(commands: Command[]) {\n this.commands = [...commands];\n }\n\n execute(store: ElementStore): void {\n for (const cmd of this.commands) {\n cmd.execute(store);\n }\n }\n\n undo(store: ElementStore): void {\n for (let i = this.commands.length - 1; i >= 0; i--) {\n this.commands[i]?.undo(store);\n }\n }\n}\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { Command } from './types';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport type { Layer } from '../layers/types';\r\n\r\nexport class CreateLayerCommand implements Command {\r\n constructor(\r\n private readonly manager: LayerManager,\r\n private readonly layer: Layer,\r\n ) {}\r\n\r\n execute(_store: ElementStore): void {\r\n this.manager.addLayerDirect(this.layer);\r\n }\r\n\r\n undo(_store: ElementStore): void {\r\n this.manager.removeLayerDirect(this.layer.id);\r\n }\r\n}\r\n\r\nexport class RemoveLayerCommand implements Command {\r\n constructor(\r\n private readonly manager: LayerManager,\r\n private readonly layer: Layer,\r\n ) {}\r\n\r\n execute(_store: ElementStore): void {\r\n this.manager.removeLayerDirect(this.layer.id);\r\n }\r\n\r\n undo(_store: ElementStore): void {\r\n this.manager.addLayerDirect(this.layer);\r\n }\r\n}\r\n\r\nexport class UpdateLayerCommand implements Command {\r\n constructor(\r\n private readonly manager: LayerManager,\r\n private readonly layerId: string,\r\n private readonly previous: Layer,\r\n private readonly current: Layer,\r\n ) {}\r\n\r\n execute(_store: ElementStore): void {\r\n this.manager.updateLayerDirect(this.layerId, { ...this.current });\r\n }\r\n\r\n undo(_store: ElementStore): void {\r\n this.manager.updateLayerDirect(this.layerId, { ...this.previous });\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport type { Command } from './types';\r\nimport type { HistoryStack } from './history-stack';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport type { Layer } from '../layers/types';\r\nimport {\r\n AddElementCommand,\r\n RemoveElementCommand,\r\n UpdateElementCommand,\r\n BatchCommand,\r\n} from './commands';\r\nimport { CreateLayerCommand, RemoveLayerCommand, UpdateLayerCommand } from './layer-commands';\r\n\r\nexport class HistoryRecorder {\r\n private recording = true;\r\n private transaction: Command[] | null = null;\r\n private generation = 0;\r\n private updateSnapshots = new Map<string, CanvasElement>();\r\n private unsubscribers: (() => void)[];\r\n\r\n constructor(\r\n private readonly store: ElementStore,\r\n private readonly stack: HistoryStack,\r\n private readonly layerManager?: LayerManager,\r\n ) {\r\n this.unsubscribers = [\r\n store.on('add', (el) => this.onAdd(el)),\r\n store.on('remove', (el) => this.onRemove(el)),\r\n store.on('update', ({ previous, current }) => this.onUpdate(previous, current)),\r\n ];\r\n\r\n if (layerManager) {\r\n this.unsubscribers.push(\r\n layerManager.on('create', (layer) => this.onLayerCreate(layer)),\r\n layerManager.on('remove', (layer) => this.onLayerRemove(layer)),\r\n layerManager.on('update', ({ previous, current }) => this.onLayerUpdate(previous, current)),\r\n );\r\n }\r\n }\r\n\r\n pause(): void {\r\n this.recording = false;\r\n }\r\n\r\n resume(): void {\r\n this.recording = true;\r\n }\r\n\r\n begin(): void {\r\n if (this.transaction !== null) {\r\n this.commit();\r\n }\r\n this.transaction = [];\r\n this.updateSnapshots.clear();\r\n this.generation += 1;\r\n }\r\n\r\n get currentTransactionId(): number | null {\r\n return this.transaction !== null ? this.generation : null;\r\n }\r\n\r\n commit(): void {\r\n if (!this.transaction) return;\r\n\r\n const finalCommands = this.flushUpdateSnapshots();\r\n const all = [...this.transaction, ...finalCommands];\r\n this.transaction = null;\r\n this.updateSnapshots.clear();\r\n\r\n if (all.length === 0) return;\r\n const first = all[0];\r\n this.stack.push(all.length === 1 && first ? first : new BatchCommand(all));\r\n }\r\n\r\n rollback(): void {\r\n this.transaction = null;\r\n this.updateSnapshots.clear();\r\n }\r\n\r\n destroy(): void {\r\n this.unsubscribers.forEach((fn) => fn());\r\n }\r\n\r\n private record(command: Command): void {\r\n if (this.transaction) {\r\n this.transaction.push(command);\r\n } else {\r\n this.stack.push(command);\r\n }\r\n }\r\n\r\n private onAdd(element: CanvasElement): void {\r\n if (!this.recording) return;\r\n this.record(new AddElementCommand(element));\r\n }\r\n\r\n private onRemove(element: CanvasElement): void {\r\n if (!this.recording) return;\r\n\r\n if (this.transaction && this.updateSnapshots.has(element.id)) {\r\n this.updateSnapshots.delete(element.id);\r\n }\r\n\r\n this.record(new RemoveElementCommand(element));\r\n }\r\n\r\n private onUpdate(previous: CanvasElement, current: CanvasElement): void {\r\n if (!this.recording) return;\r\n\r\n if (this.transaction) {\r\n if (!this.updateSnapshots.has(current.id)) {\r\n this.updateSnapshots.set(current.id, { ...previous });\r\n }\r\n } else {\r\n this.stack.push(new UpdateElementCommand(current.id, previous, current));\r\n }\r\n }\r\n\r\n private onLayerCreate(layer: Layer): void {\r\n if (!this.recording) return;\r\n if (!this.layerManager) return;\r\n this.record(new CreateLayerCommand(this.layerManager, layer));\r\n }\r\n\r\n private onLayerRemove(layer: Layer): void {\r\n if (!this.recording) return;\r\n if (!this.layerManager) return;\r\n this.record(new RemoveLayerCommand(this.layerManager, layer));\r\n }\r\n\r\n private onLayerUpdate(previous: Layer, current: Layer): void {\r\n if (!this.recording) return;\r\n if (!this.layerManager) return;\r\n this.record(new UpdateLayerCommand(this.layerManager, current.id, previous, current));\r\n }\r\n\r\n private flushUpdateSnapshots(): Command[] {\r\n const commands: Command[] = [];\r\n for (const [id, previous] of this.updateSnapshots) {\r\n const current = this.store.getById(id);\r\n if (current) {\r\n commands.push(new UpdateElementCommand(id, previous, current));\r\n }\r\n }\r\n return commands;\r\n }\r\n}\r\n","import type { NoteElement } from '../elements/types';\r\nimport { DEFAULT_NOTE_FONT_SIZE } from '../elements/element-factory';\r\nimport { parseStyledRuns } from '../elements/note-sanitizer';\r\nimport type { StyledRun } from '../elements/note-sanitizer';\r\n\r\nexport function renderNoteOnCanvas(ctx: CanvasRenderingContext2D, note: NoteElement): void {\r\n const { x, y } = note.position;\r\n const { w, h } = note.size;\r\n const r = 4;\r\n const pad = 8;\r\n const baseFontSize = note.fontSize ?? DEFAULT_NOTE_FONT_SIZE;\r\n\r\n ctx.save();\r\n ctx.fillStyle = note.backgroundColor;\r\n ctx.beginPath();\r\n ctx.moveTo(x + r, y);\r\n ctx.lineTo(x + w - r, y);\r\n ctx.arcTo(x + w, y, x + w, y + r, r);\r\n ctx.lineTo(x + w, y + h - r);\r\n ctx.arcTo(x + w, y + h, x + w - r, y + h, r);\r\n ctx.lineTo(x + r, y + h);\r\n ctx.arcTo(x, y + h, x, y + h - r, r);\r\n ctx.lineTo(x, y + r);\r\n ctx.arcTo(x, y, x + r, y, r);\r\n ctx.closePath();\r\n ctx.fill();\r\n\r\n if (note.text) {\r\n ctx.fillStyle = note.textColor;\r\n const runs = parseStyledRuns(note.text, baseFontSize);\r\n renderStyledRuns(ctx, runs, x + pad, y + pad, w - pad * 2);\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nfunction buildFontString(run: StyledRun): string {\r\n const style = run.italic ? 'italic' : 'normal';\r\n const weight = run.bold ? 'bold' : 'normal';\r\n return `${style} ${weight} ${run.fontSize}px system-ui, sans-serif`;\r\n}\r\n\r\nfunction renderStyledRuns(\r\n ctx: CanvasRenderingContext2D,\r\n runs: StyledRun[],\r\n startX: number,\r\n startY: number,\r\n maxWidth: number,\r\n): void {\r\n ctx.textBaseline = 'top';\r\n let cursorX = startX;\r\n let cursorY = startY;\r\n let lineHeight = 0;\r\n\r\n for (const run of runs) {\r\n ctx.font = buildFontString(run);\r\n const runLineHeight = run.fontSize * 1.3;\r\n lineHeight = Math.max(lineHeight, runLineHeight);\r\n\r\n const words = run.text.split(/(\\n| )/);\r\n for (const word of words) {\r\n if (word === '\\n') {\r\n cursorX = startX;\r\n cursorY += lineHeight;\r\n lineHeight = runLineHeight;\r\n continue;\r\n }\r\n if (word === ' ') {\r\n const spaceWidth = ctx.measureText(' ').width;\r\n if (cursorX + spaceWidth > startX + maxWidth && cursorX > startX) {\r\n cursorX = startX;\r\n cursorY += lineHeight;\r\n lineHeight = runLineHeight;\r\n } else {\r\n cursorX += spaceWidth;\r\n }\r\n continue;\r\n }\r\n if (!word) continue;\r\n\r\n const metrics = ctx.measureText(word);\r\n if (cursorX + metrics.width > startX + maxWidth && cursorX > startX) {\r\n cursorX = startX;\r\n cursorY += lineHeight;\r\n lineHeight = runLineHeight;\r\n }\r\n\r\n ctx.fillText(word, cursorX, cursorY);\r\n\r\n if (run.underline) {\r\n const underY = cursorY + run.fontSize + 1;\r\n ctx.fillRect(cursorX, underY, metrics.width, 1);\r\n }\r\n\r\n if (run.strikethrough) {\r\n const strikeY = cursorY + run.fontSize * 0.55;\r\n ctx.fillRect(cursorX, strikeY, metrics.width, 1);\r\n }\r\n\r\n cursorX += metrics.width;\r\n }\r\n }\r\n}\r\n","import type { CanvasElement, TextElement, GridElement } from '../elements/types';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport { ElementRenderer } from '../elements/element-renderer';\r\nimport { getArrowBounds } from '../elements/arrow-geometry';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { renderSquareGrid, renderHexGrid } from '../elements/grid-renderer';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport { renderNoteOnCanvas } from './note-canvas-renderer';\r\n\r\nexport interface ExportImageOptions {\r\n scale?: number;\r\n padding?: number;\r\n background?: string;\r\n filter?: (element: CanvasElement) => boolean;\r\n}\r\n\r\ninterface Rect {\r\n x: number;\r\n y: number;\r\n w: number;\r\n h: number;\r\n}\r\n\r\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 return getStrokeBounds(el);\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 { x: el.position.x, y: el.position.y, w: el.size.w, h: el.size.h };\r\n }\r\n return null;\r\n default:\r\n return null;\r\n }\r\n}\r\n\r\nfunction computeBounds(\r\n elements: CanvasElement[],\r\n padding: number,\r\n): { x: number; y: number; w: number; h: number } | null {\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n let found = false;\r\n\r\n for (const el of elements) {\r\n const rect = getElementRect(el);\r\n if (!rect) continue;\r\n found = true;\r\n minX = Math.min(minX, rect.x);\r\n minY = Math.min(minY, rect.y);\r\n maxX = Math.max(maxX, rect.x + rect.w);\r\n maxY = Math.max(maxY, rect.y + rect.h);\r\n }\r\n\r\n if (!found) return null;\r\n\r\n return {\r\n x: minX - padding,\r\n y: minY - padding,\r\n w: maxX - minX + padding * 2,\r\n h: maxY - minY + padding * 2,\r\n };\r\n}\r\n\r\nfunction renderTextOnCanvas(ctx: CanvasRenderingContext2D, text: TextElement): void {\r\n if (!text.text) return;\r\n\r\n ctx.save();\r\n ctx.fillStyle = text.color;\r\n ctx.font = `${text.fontSize}px system-ui, sans-serif`;\r\n ctx.textBaseline = 'top';\r\n ctx.textAlign = text.textAlign;\r\n\r\n const pad = 2;\r\n let textX = text.position.x + pad;\r\n if (text.textAlign === 'center') {\r\n textX = text.position.x + text.size.w / 2;\r\n } else if (text.textAlign === 'right') {\r\n textX = text.position.x + text.size.w - pad;\r\n }\r\n\r\n const lineHeight = text.fontSize * 1.4;\r\n const lines = text.text.split('\\n');\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i];\r\n if (line !== undefined) {\r\n ctx.fillText(line, textX, text.position.y + pad + i * lineHeight);\r\n }\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nfunction renderGridForBounds(\r\n ctx: CanvasRenderingContext2D,\r\n grid: GridElement,\r\n bounds: { x: number; y: number; w: number; h: number },\r\n): void {\r\n const visibleBounds = {\r\n minX: bounds.x,\r\n minY: bounds.y,\r\n maxX: bounds.x + bounds.w,\r\n maxY: bounds.y + bounds.h,\r\n };\r\n\r\n if (grid.gridType === 'hex') {\r\n renderHexGrid(\r\n ctx,\r\n visibleBounds,\r\n grid.cellSize,\r\n grid.hexOrientation,\r\n grid.strokeColor,\r\n grid.strokeWidth,\r\n grid.opacity,\r\n );\r\n } else {\r\n renderSquareGrid(\r\n ctx,\r\n visibleBounds,\r\n grid.cellSize,\r\n grid.strokeColor,\r\n grid.strokeWidth,\r\n grid.opacity,\r\n );\r\n }\r\n}\r\n\r\nfunction loadImages(elements: CanvasElement[]): Promise<Map<string, HTMLImageElement>> {\r\n const imageElements = elements.filter(\r\n (el): el is CanvasElement & { src: string } => el.type === 'image' && 'src' in el,\r\n );\r\n\r\n const cache = new Map<string, HTMLImageElement>();\r\n if (imageElements.length === 0) return Promise.resolve(cache);\r\n\r\n return new Promise((resolve) => {\r\n let remaining = imageElements.length;\r\n const done = () => {\r\n remaining--;\r\n if (remaining <= 0) resolve(cache);\r\n };\r\n\r\n for (const el of imageElements) {\r\n const img = new Image();\r\n img.crossOrigin = 'anonymous';\r\n img.onload = () => {\r\n cache.set(el.id, img);\r\n done();\r\n };\r\n img.onerror = done;\r\n const sep = el.src.includes('?') ? '&' : '?';\r\n img.src = `${el.src}${sep}_cors=1`;\r\n }\r\n });\r\n}\r\n\r\nexport async function exportImage(\r\n store: ElementStore,\r\n options: ExportImageOptions = {},\r\n layerManager?: LayerManager,\r\n): Promise<Blob | null> {\r\n const scale = options.scale ?? 2;\r\n const padding = options.padding ?? 0;\r\n const background = options.background ?? '#ffffff';\r\n const filter = options.filter;\r\n\r\n const allElements = store.getAll();\r\n let visibleElements = layerManager\r\n ? allElements.filter((el) => layerManager.isLayerVisible(el.layerId))\r\n : allElements;\r\n\r\n if (filter) {\r\n visibleElements = visibleElements.filter(filter);\r\n }\r\n\r\n const bounds = computeBounds(visibleElements, padding);\r\n if (!bounds) return null;\r\n\r\n const imageCache = await loadImages(visibleElements);\r\n\r\n const canvas = document.createElement('canvas');\r\n canvas.width = Math.ceil(bounds.w * scale);\r\n canvas.height = Math.ceil(bounds.h * scale);\r\n\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return null;\r\n\r\n ctx.scale(scale, scale);\r\n ctx.translate(-bounds.x, -bounds.y);\r\n\r\n ctx.fillStyle = background;\r\n ctx.fillRect(bounds.x, bounds.y, bounds.w, bounds.h);\r\n\r\n const renderer = new ElementRenderer();\r\n renderer.setStore(store);\r\n\r\n const grids: GridElement[] = [];\r\n\r\n for (const el of visibleElements) {\r\n if (el.type === 'grid') {\r\n grids.push(el);\r\n continue;\r\n }\r\n\r\n if (el.type === 'note') {\r\n renderNoteOnCanvas(ctx, el);\r\n continue;\r\n }\r\n\r\n if (el.type === 'text') {\r\n renderTextOnCanvas(ctx, el);\r\n continue;\r\n }\r\n\r\n if (el.type === 'html') {\r\n continue;\r\n }\r\n\r\n if (el.type === 'image') {\r\n const img = imageCache.get(el.id);\r\n if (img) {\r\n ctx.drawImage(img, el.position.x, el.position.y, el.size.w, el.size.h);\r\n }\r\n continue;\r\n }\r\n\r\n renderer.renderCanvasElement(ctx, el);\r\n }\r\n\r\n for (const grid of grids) {\r\n renderGridForBounds(ctx, grid, bounds);\r\n }\r\n\r\n return new Promise((resolve) => {\r\n canvas.toBlob((blob) => resolve(blob), 'image/png');\r\n });\r\n}\r\n\r\nexport { computeBounds, getElementRect };\r\n","import { EventBus } from '../core/event-bus';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { Layer } from './types';\r\nimport { createId } from '../elements/create-id';\r\n\r\ninterface LayerManagerEvents {\r\n change: null;\r\n create: Layer;\r\n remove: Layer;\r\n update: { previous: Layer; current: Layer };\r\n}\r\n\r\nexport class LayerManager {\r\n private layers = new Map<string, Layer>();\r\n private _activeLayerId: string;\r\n private bus = new EventBus<LayerManagerEvents>();\r\n\r\n constructor(private readonly store: ElementStore) {\r\n const defaultLayer: Layer = {\r\n id: createId('layer'),\r\n name: 'Layer 1',\r\n visible: true,\r\n locked: false,\r\n order: 0,\r\n opacity: 1.0,\r\n };\r\n this.layers.set(defaultLayer.id, defaultLayer);\r\n this._activeLayerId = defaultLayer.id;\r\n this.syncLayerOrder();\r\n }\r\n\r\n get activeLayer(): Layer {\r\n const layer = this.layers.get(this._activeLayerId);\r\n if (!layer) throw new Error('Active layer not found');\r\n return { ...layer };\r\n }\r\n\r\n get activeLayerId(): string {\r\n return this._activeLayerId;\r\n }\r\n\r\n getLayers(): Layer[] {\r\n return [...this.layers.values()].sort((a, b) => a.order - b.order).map((l) => ({ ...l }));\r\n }\r\n\r\n getLayer(id: string): Layer | undefined {\r\n const layer = this.layers.get(id);\r\n return layer ? { ...layer } : undefined;\r\n }\r\n\r\n isLayerVisible(id: string): boolean {\r\n return this.layers.get(id)?.visible ?? true;\r\n }\r\n\r\n isLayerLocked(id: string): boolean {\r\n return this.layers.get(id)?.locked ?? false;\r\n }\r\n\r\n createLayer(name?: string): Layer {\r\n const maxOrder = Math.max(...[...this.layers.values()].map((l) => l.order), -1);\r\n const autoName = name ?? `Layer ${this.layers.size + 1}`;\r\n const layer: Layer = {\r\n id: createId('layer'),\r\n name: autoName,\r\n visible: true,\r\n locked: false,\r\n order: maxOrder + 1,\r\n opacity: 1.0,\r\n };\r\n this.addLayerDirect(layer);\r\n return { ...layer };\r\n }\r\n\r\n removeLayer(id: string): void {\r\n if (this.layers.size <= 1) {\r\n throw new Error('Cannot remove the last layer');\r\n }\r\n if (this._activeLayerId === id) {\r\n const remaining = [...this.layers.values()]\r\n .filter((l) => l.id !== id)\r\n .sort((a, b) => b.order - a.order);\r\n const fallback = remaining[0];\r\n if (fallback) this._activeLayerId = fallback.id;\r\n }\r\n const elements = this.store.getAll().filter((el) => el.layerId === id);\r\n for (const el of elements) {\r\n this.store.update(el.id, { layerId: this._activeLayerId });\r\n }\r\n this.removeLayerDirect(id);\r\n }\r\n\r\n renameLayer(id: string, name: string): void {\r\n this.updateLayerDirect(id, { name });\r\n }\r\n\r\n reorderLayer(id: string, newOrder: number): void {\r\n if (!this.layers.has(id)) return;\r\n this.updateLayerDirect(id, { order: newOrder });\r\n }\r\n\r\n setLayerVisible(id: string, visible: boolean): boolean {\r\n if (!visible && id === this._activeLayerId) {\r\n const fallback = this.findFallbackLayer(id);\r\n if (!fallback) return false;\r\n this._activeLayerId = fallback.id;\r\n }\r\n this.updateLayerDirect(id, { visible });\r\n return true;\r\n }\r\n\r\n setLayerLocked(id: string, locked: boolean): boolean {\r\n if (locked && id === this._activeLayerId) {\r\n const fallback = this.findFallbackLayer(id);\r\n if (!fallback) return false;\r\n this._activeLayerId = fallback.id;\r\n }\r\n this.updateLayerDirect(id, { locked });\r\n return true;\r\n }\r\n\r\n setLayerOpacity(id: string, opacity: number): void {\r\n if (!this.layers.has(id)) return;\r\n this.updateLayerDirect(id, { opacity: Math.max(0, Math.min(1, opacity)) });\r\n }\r\n\r\n setActiveLayer(id: string): void {\r\n if (!this.layers.has(id)) return;\r\n this._activeLayerId = id;\r\n this.bus.emit('change', null);\r\n }\r\n\r\n moveElementToLayer(elementId: string, layerId: string): void {\r\n if (!this.layers.has(layerId)) return;\r\n this.store.update(elementId, { layerId });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n snapshot(): Layer[] {\r\n return this.getLayers();\r\n }\r\n\r\n loadSnapshot(layers: Layer[]): void {\r\n this.layers.clear();\r\n for (const layer of layers) {\r\n this.layers.set(layer.id, { ...layer });\r\n }\r\n const first = this.getLayers()[0];\r\n if (first) this._activeLayerId = first.id;\r\n this.syncLayerOrder();\r\n this.bus.emit('change', null);\r\n }\r\n\r\n on<K extends keyof LayerManagerEvents>(\r\n event: K,\r\n callback: (data: LayerManagerEvents[K]) => void,\r\n ): () => void {\r\n return this.bus.on(event, callback);\r\n }\r\n\r\n addLayerDirect(layer: Layer): void {\r\n this.layers.set(layer.id, { ...layer });\r\n this.syncLayerOrder();\r\n this.bus.emit('create', { ...layer });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n removeLayerDirect(id: string): void {\r\n const layer = this.layers.get(id);\r\n this.layers.delete(id);\r\n this.syncLayerOrder();\r\n if (layer) this.bus.emit('remove', { ...layer });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n updateLayerDirect(id: string, props: Omit<Partial<Layer>, 'id'>): void {\r\n const layer = this.layers.get(id);\r\n if (!layer) return;\r\n const previous = { ...layer };\r\n Object.assign(layer, props);\r\n if ('order' in props) this.syncLayerOrder();\r\n this.bus.emit('update', { previous, current: { ...layer } });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n private syncLayerOrder(): void {\r\n const order = new Map<string, number>();\r\n for (const layer of this.layers.values()) {\r\n order.set(layer.id, layer.order);\r\n }\r\n this.store.setLayerOrder(order);\r\n }\r\n\r\n private findFallbackLayer(excludeId: string): Layer | undefined {\r\n return [...this.layers.values()]\r\n .filter((l) => l.id !== excludeId && l.visible && !l.locked)\r\n .sort((a, b) => b.order - a.order)[0];\r\n }\r\n}\r\n","export interface InteractModeDeps {\r\n getNode: (id: string) => HTMLDivElement | undefined;\r\n}\r\n\r\nexport class InteractMode {\r\n private interactingElementId: string | null = null;\r\n private readonly getNode: (id: string) => HTMLDivElement | undefined;\r\n\r\n constructor(deps: InteractModeDeps) {\r\n this.getNode = deps.getNode;\r\n }\r\n\r\n startInteracting(id: string): void {\r\n this.stopInteracting();\r\n const node = this.getNode(id);\r\n if (!node) return;\r\n\r\n this.interactingElementId = id;\r\n node.style.pointerEvents = 'auto';\r\n node.addEventListener('pointerdown', this.onNodePointerDown);\r\n\r\n window.addEventListener('keydown', this.onKeyDown);\r\n window.addEventListener('pointerdown', this.onPointerDown);\r\n }\r\n\r\n stopInteracting(): void {\r\n if (!this.interactingElementId) return;\r\n\r\n const node = this.getNode(this.interactingElementId);\r\n if (node) {\r\n node.style.pointerEvents = 'none';\r\n node.removeEventListener('pointerdown', this.onNodePointerDown);\r\n }\r\n\r\n this.interactingElementId = null;\r\n window.removeEventListener('keydown', this.onKeyDown);\r\n window.removeEventListener('pointerdown', this.onPointerDown);\r\n }\r\n\r\n isInteracting(): boolean {\r\n return this.interactingElementId !== null;\r\n }\r\n\r\n destroy(): void {\r\n this.stopInteracting();\r\n }\r\n\r\n private onNodePointerDown = (e: PointerEvent): void => {\r\n e.stopPropagation();\r\n };\r\n\r\n private onKeyDown = (e: KeyboardEvent): void => {\r\n if (e.key === 'Escape') {\r\n this.stopInteracting();\r\n }\r\n };\r\n\r\n private onPointerDown = (e: PointerEvent): void => {\r\n if (!this.interactingElementId) return;\r\n const target = e.target;\r\n if (!(target instanceof Element)) {\r\n this.stopInteracting();\r\n return;\r\n }\r\n\r\n const node = this.getNode(this.interactingElementId);\r\n if (node && !node.contains(target)) {\r\n this.stopInteracting();\r\n }\r\n };\r\n}\r\n","export interface DoubleTapDetectorOptions {\r\n timeout?: number;\r\n maxDistance?: number;\r\n}\r\n\r\nconst DEFAULT_TIMEOUT = 300;\r\nconst DEFAULT_MAX_DISTANCE = 20;\r\n\r\nexport class DoubleTapDetector {\r\n private readonly timeout: number;\r\n private readonly maxDistance: number;\r\n private lastTapTime = 0;\r\n private lastTapX = 0;\r\n private lastTapY = 0;\r\n private hasPendingTap = false;\r\n\r\n constructor(options?: DoubleTapDetectorOptions) {\r\n this.timeout = options?.timeout ?? DEFAULT_TIMEOUT;\r\n this.maxDistance = options?.maxDistance ?? DEFAULT_MAX_DISTANCE;\r\n }\r\n\r\n feed(e: PointerEvent): boolean {\r\n const now = Date.now();\r\n const x = e.clientX;\r\n const y = e.clientY;\r\n\r\n if (this.hasPendingTap) {\r\n const elapsed = now - this.lastTapTime;\r\n const dx = x - this.lastTapX;\r\n const dy = y - this.lastTapY;\r\n const dist = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (elapsed <= this.timeout && dist <= this.maxDistance) {\r\n this.reset();\r\n return true;\r\n }\r\n }\r\n\r\n this.lastTapTime = now;\r\n this.lastTapX = x;\r\n this.lastTapY = y;\r\n this.hasPendingTap = true;\r\n return false;\r\n }\r\n\r\n reset(): void {\r\n this.hasPendingTap = false;\r\n this.lastTapTime = 0;\r\n this.lastTapX = 0;\r\n this.lastTapY = 0;\r\n }\r\n}\r\n","import type { CanvasElement } from '../elements/types';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport { DEFAULT_NOTE_FONT_SIZE } from '../elements/element-factory';\r\nimport { DoubleTapDetector } from './double-tap-detector';\r\nexport interface DomNodeManagerDeps {\r\n domLayer: HTMLDivElement;\r\n onEditRequest: (id: string) => void;\r\n isEditingElement: (id: string) => boolean;\r\n getVersion?: (id: string) => number;\r\n}\r\n\r\nexport class DomNodeManager {\r\n private domNodes = new Map<string, HTMLDivElement>();\r\n private htmlContent = new Map<string, HTMLElement>();\r\n private readonly domLayer: HTMLDivElement;\r\n private readonly onEditRequest: (id: string) => void;\r\n private readonly isEditingElement: (id: string) => boolean;\r\n private readonly getVersion: ((id: string) => number) | null;\r\n private lastSyncedVersion = new Map<string, number>();\r\n private lastSyncedZIndex = new Map<string, number>();\r\n\r\n constructor(deps: DomNodeManagerDeps) {\r\n this.domLayer = deps.domLayer;\r\n this.onEditRequest = deps.onEditRequest;\r\n this.isEditingElement = deps.isEditingElement;\r\n this.getVersion = deps.getVersion ?? null;\r\n }\r\n\r\n getNode(id: string): HTMLDivElement | undefined {\r\n return this.domNodes.get(id);\r\n }\r\n\r\n storeHtmlContent(elementId: string, dom: HTMLElement): void {\r\n this.htmlContent.set(elementId, dom);\r\n }\r\n\r\n hasContent(elementId: string): boolean {\r\n return this.htmlContent.has(elementId);\r\n }\r\n\r\n resetHtmlContent(elementId: string): void {\r\n this.htmlContent.delete(elementId);\r\n this.lastSyncedVersion.delete(elementId);\r\n this.lastSyncedZIndex.delete(elementId);\r\n const node = this.domNodes.get(elementId);\r\n if (!node) return;\r\n while (node.firstChild) {\r\n node.removeChild(node.firstChild);\r\n }\r\n delete node.dataset['initialized'];\r\n }\r\n\r\n syncDomNode(element: CanvasElement, zIndex = 0): void {\r\n let node = this.domNodes.get(element.id);\r\n if (!node) {\r\n node = document.createElement('div');\r\n node.dataset['elementId'] = element.id;\r\n Object.assign(node.style, {\r\n position: 'absolute',\r\n pointerEvents: 'auto',\r\n });\r\n this.domLayer.appendChild(node);\r\n this.domNodes.set(element.id, node);\r\n } else if (this.getVersion) {\r\n const currentVersion = this.getVersion(element.id);\r\n const lastVersion = this.lastSyncedVersion.get(element.id);\r\n const lastZ = this.lastSyncedZIndex.get(element.id);\r\n if (lastVersion === currentVersion && lastZ === zIndex) {\r\n return;\r\n }\r\n }\r\n\r\n if (this.getVersion) {\r\n this.lastSyncedVersion.set(element.id, this.getVersion(element.id));\r\n this.lastSyncedZIndex.set(element.id, zIndex);\r\n }\r\n\r\n const size = 'size' in element ? element.size : null;\r\n Object.assign(node.style, {\r\n display: 'block',\r\n left: `${element.position.x}px`,\r\n top: `${element.position.y}px`,\r\n width: size ? `${size.w}px` : 'auto',\r\n height: size ? `${size.h}px` : 'auto',\r\n zIndex: String(zIndex),\r\n });\r\n\r\n this.renderDomContent(node, element);\r\n }\r\n\r\n hideDomNode(id: string): void {\r\n const node = this.domNodes.get(id);\r\n if (node) node.style.display = 'none';\r\n }\r\n\r\n removeDomNode(id: string): void {\r\n this.htmlContent.delete(id);\r\n this.lastSyncedVersion.delete(id);\r\n this.lastSyncedZIndex.delete(id);\r\n const node = this.domNodes.get(id);\r\n if (node) {\r\n node.remove();\r\n this.domNodes.delete(id);\r\n }\r\n }\r\n\r\n clearDomNodes(): void {\r\n this.domNodes.forEach((node) => node.remove());\r\n this.domNodes.clear();\r\n this.htmlContent.clear();\r\n this.lastSyncedVersion.clear();\r\n this.lastSyncedZIndex.clear();\r\n }\r\n\r\n reattachHtmlContent(store: ElementStore): void {\r\n for (const el of store.getElementsByType('html')) {\r\n if (el.domId) {\r\n const dom = document.getElementById(el.domId);\r\n if (dom) {\r\n this.htmlContent.set(el.id, dom);\r\n }\r\n }\r\n }\r\n }\r\n\r\n private renderDomContent(node: HTMLDivElement, element: CanvasElement): void {\r\n if (element.type === 'note') {\r\n if (!node.dataset['initialized']) {\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n backgroundColor: element.backgroundColor,\r\n color: element.textColor,\r\n padding: '8px',\r\n borderRadius: '4px',\r\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\r\n fontSize: `${element.fontSize ?? DEFAULT_NOTE_FONT_SIZE}px`,\r\n overflow: 'hidden',\r\n cursor: 'default',\r\n userSelect: 'none',\r\n wordWrap: 'break-word',\r\n });\r\n node.innerHTML = element.text || '';\r\n\r\n const detector = new DoubleTapDetector();\r\n node.addEventListener('pointerup', (e) => {\r\n if (detector.feed(e)) {\r\n e.stopPropagation();\r\n const id = node.dataset['elementId'];\r\n if (id) this.onEditRequest(id);\r\n }\r\n });\r\n }\r\n\r\n if (!this.isEditingElement(element.id)) {\r\n const text = element.text || '';\r\n if (node.innerHTML !== text) {\r\n node.innerHTML = text;\r\n }\r\n node.style.backgroundColor = element.backgroundColor;\r\n node.style.color = element.textColor;\r\n node.style.fontSize = `${element.fontSize ?? DEFAULT_NOTE_FONT_SIZE}px`;\r\n }\r\n }\r\n\r\n if (element.type === 'html') {\r\n if (!node.dataset['initialized']) {\r\n const content = this.htmlContent.get(element.id);\r\n if (content) {\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n overflow: 'hidden',\r\n pointerEvents: element.interactive ? 'auto' : 'none',\r\n });\r\n node.appendChild(content);\r\n }\r\n } else {\r\n node.style.pointerEvents = element.interactive ? 'auto' : 'none';\r\n }\r\n }\r\n\r\n if (element.type === 'text') {\r\n if (!node.dataset['initialized']) {\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n padding: '2px',\r\n fontSize: `${element.fontSize}px`,\r\n color: element.color,\r\n textAlign: element.textAlign,\r\n background: 'none',\r\n border: 'none',\r\n boxShadow: 'none',\r\n overflow: 'visible',\r\n cursor: 'default',\r\n userSelect: 'none',\r\n wordWrap: 'break-word',\r\n whiteSpace: 'pre-wrap',\r\n lineHeight: '1.4',\r\n });\r\n node.textContent = element.text || '';\r\n\r\n const detector = new DoubleTapDetector();\r\n node.addEventListener('pointerup', (e) => {\r\n if (detector.feed(e)) {\r\n e.stopPropagation();\r\n const id = node.dataset['elementId'];\r\n if (id) this.onEditRequest(id);\r\n }\r\n });\r\n }\r\n\r\n if (!this.isEditingElement(element.id)) {\r\n if (node.textContent !== element.text) {\r\n node.textContent = element.text || '';\r\n }\r\n Object.assign(node.style, {\r\n fontSize: `${element.fontSize}px`,\r\n color: element.color,\r\n textAlign: element.textAlign,\r\n });\r\n }\r\n }\r\n }\r\n}\r\n","const SAMPLE_SIZE = 60;\r\n\r\nexport interface RenderStatsSnapshot {\r\n fps: number;\r\n avgFrameMs: number;\r\n p95FrameMs: number;\r\n lastFrameMs: number;\r\n lastGridMs: number;\r\n layersMs: number;\r\n backgroundMs: number;\r\n compositeMs: number;\r\n overlayMs: number;\r\n frameCount: number;\r\n}\r\n\r\ninterface FrameBreakdown {\r\n gridMs?: number;\r\n layersMs?: number;\r\n backgroundMs?: number;\r\n compositeMs?: number;\r\n overlayMs?: number;\r\n}\r\n\r\nexport class RenderStats {\r\n private frameTimes: number[] = [];\r\n private frameCount = 0;\r\n private _lastGridMs = 0;\r\n private _lastLayersMs = 0;\r\n private _lastBackgroundMs = 0;\r\n private _lastCompositeMs = 0;\r\n private _lastOverlayMs = 0;\r\n\r\n recordFrame(durationMs: number, breakdown?: FrameBreakdown): void {\r\n this.frameCount++;\r\n this.frameTimes.push(durationMs);\r\n if (this.frameTimes.length > SAMPLE_SIZE) {\r\n this.frameTimes.shift();\r\n }\r\n if (breakdown !== undefined) {\r\n if (breakdown.gridMs !== undefined) this._lastGridMs = breakdown.gridMs;\r\n if (breakdown.layersMs !== undefined) this._lastLayersMs = breakdown.layersMs;\r\n if (breakdown.backgroundMs !== undefined) this._lastBackgroundMs = breakdown.backgroundMs;\r\n if (breakdown.compositeMs !== undefined) this._lastCompositeMs = breakdown.compositeMs;\r\n if (breakdown.overlayMs !== undefined) this._lastOverlayMs = breakdown.overlayMs;\r\n }\r\n }\r\n\r\n getSnapshot(): RenderStatsSnapshot {\r\n const times = this.frameTimes;\r\n if (times.length === 0) {\r\n return {\r\n fps: 0,\r\n avgFrameMs: 0,\r\n p95FrameMs: 0,\r\n lastFrameMs: 0,\r\n lastGridMs: 0,\r\n layersMs: 0,\r\n backgroundMs: 0,\r\n compositeMs: 0,\r\n overlayMs: 0,\r\n frameCount: 0,\r\n };\r\n }\r\n\r\n const avg = times.reduce((a, b) => a + b, 0) / times.length;\r\n const sorted = [...times].sort((a, b) => a - b);\r\n const p95Index = Math.min(Math.floor(sorted.length * 0.95), sorted.length - 1);\r\n const lastFrame = times[times.length - 1] ?? 0;\r\n\r\n return {\r\n fps: avg > 0 ? Math.round(1000 / avg) : 0,\r\n avgFrameMs: Math.round(avg * 100) / 100,\r\n p95FrameMs: Math.round((sorted[p95Index] ?? 0) * 100) / 100,\r\n lastFrameMs: Math.round(lastFrame * 100) / 100,\r\n lastGridMs: Math.round(this._lastGridMs * 100) / 100,\r\n layersMs: Math.round(this._lastLayersMs * 100) / 100,\r\n backgroundMs: Math.round(this._lastBackgroundMs * 100) / 100,\r\n compositeMs: Math.round(this._lastCompositeMs * 100) / 100,\r\n overlayMs: Math.round(this._lastOverlayMs * 100) / 100,\r\n frameCount: this.frameCount,\r\n };\r\n }\r\n\r\n reset(): void {\r\n this.frameTimes = [];\r\n this.frameCount = 0;\r\n }\r\n}\r\n","import type { Camera } from './camera';\r\nimport type { Background } from './background';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { ElementRenderer } from '../elements/element-renderer';\r\nimport type { ToolManager } from '../tools/tool-manager';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport type { DomNodeManager } from './dom-node-manager';\r\nimport type { LayerCache } from './layer-cache';\r\nimport type { MarginViewport } from './margin-viewport';\r\nimport type { Bounds } from '../core/types';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { getElementBounds, boundsIntersect } from '../elements/element-bounds';\r\nimport { RenderStats } from './render-stats';\r\nimport type { RenderStatsSnapshot } from './render-stats';\r\n\r\nexport interface RenderLoopDeps {\r\n canvasEl: HTMLCanvasElement;\r\n camera: Camera;\r\n background: Background;\r\n store: ElementStore;\r\n renderer: ElementRenderer;\r\n toolManager: ToolManager;\r\n layerManager: LayerManager;\r\n domNodeManager: DomNodeManager;\r\n layerCache: LayerCache;\r\n marginViewport: MarginViewport;\r\n}\r\n\r\nexport class RenderLoop {\r\n private needsRender = false;\r\n private animFrameId = 0;\r\n private readonly canvasEl: HTMLCanvasElement;\r\n private readonly camera: Camera;\r\n private readonly background: Background;\r\n private readonly store: ElementStore;\r\n private readonly renderer: ElementRenderer;\r\n private readonly toolManager: ToolManager;\r\n private readonly layerManager: LayerManager;\r\n private readonly domNodeManager: DomNodeManager;\r\n private readonly layerCache: LayerCache;\r\n private readonly marginViewport: MarginViewport;\r\n private activeDrawingLayerId: string | null = null;\r\n private gridCacheDirty = true; // set on recenter/viewport-change; consumed by the grid block\r\n private readonly stats = new RenderStats();\r\n private layerGroups = new Map<string, CanvasElement[]>();\r\n private gridCacheCanvas: HTMLCanvasElement | null = null;\r\n private gridCacheCtx: CanvasRenderingContext2D | null = null;\r\n private lastGridRef: unknown = null;\r\n\r\n constructor(deps: RenderLoopDeps) {\r\n this.canvasEl = deps.canvasEl;\r\n this.camera = deps.camera;\r\n this.background = deps.background;\r\n this.store = deps.store;\r\n this.renderer = deps.renderer;\r\n this.toolManager = deps.toolManager;\r\n this.layerManager = deps.layerManager;\r\n this.domNodeManager = deps.domNodeManager;\r\n this.layerCache = deps.layerCache;\r\n this.marginViewport = deps.marginViewport;\r\n }\r\n\r\n requestRender(): void {\r\n this.needsRender = true;\r\n }\r\n\r\n flush(): void {\r\n if (this.needsRender) {\r\n this.render();\r\n this.needsRender = false;\r\n }\r\n }\r\n\r\n start(): void {\r\n const loop = (): void => {\r\n if (this.needsRender) {\r\n this.render();\r\n this.needsRender = false;\r\n }\r\n this.animFrameId = requestAnimationFrame(loop);\r\n };\r\n this.animFrameId = requestAnimationFrame(loop);\r\n }\r\n\r\n stop(): void {\r\n cancelAnimationFrame(this.animFrameId);\r\n }\r\n\r\n setCanvasSize(width: number, height: number): void {\r\n this.canvasEl.width = width;\r\n this.canvasEl.height = height;\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n this.marginViewport.setViewport(width / dpr, height / dpr, dpr);\r\n this.layerCache.resize();\r\n }\r\n\r\n setActiveDrawingLayer(layerId: string | null): void {\r\n this.activeDrawingLayerId = layerId;\r\n }\r\n\r\n markLayerDirty(layerId: string): void {\r\n this.layerCache.markDirty(layerId);\r\n }\r\n\r\n markAllLayersDirty(): void {\r\n this.layerCache.markAllDirty();\r\n }\r\n\r\n getStats(): RenderStatsSnapshot {\r\n return this.stats.getSnapshot();\r\n }\r\n\r\n private compositeLayerCache(ctx: CanvasRenderingContext2D, layerId: string): void {\r\n const cached = this.layerCache.getCanvas(layerId);\r\n const offset = this.marginViewport.compositeOffset(\r\n this.camera.position.x,\r\n this.camera.position.y,\r\n );\r\n ctx.save();\r\n ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n ctx.drawImage(cached as CanvasImageSource, offset.x, offset.y);\r\n ctx.restore();\r\n }\r\n\r\n private ensureGridCache(): void {\r\n const w = this.marginViewport.physicalWidth();\r\n const h = this.marginViewport.physicalHeight();\r\n if (\r\n this.gridCacheCanvas !== null &&\r\n this.gridCacheCanvas.width === w &&\r\n this.gridCacheCanvas.height === h\r\n ) {\r\n return;\r\n }\r\n\r\n if (typeof OffscreenCanvas !== 'undefined') {\r\n this.gridCacheCanvas = new OffscreenCanvas(w, h) as unknown as HTMLCanvasElement;\r\n } else if (typeof document !== 'undefined') {\r\n const el = document.createElement('canvas');\r\n el.width = w;\r\n el.height = h;\r\n this.gridCacheCanvas = el;\r\n } else {\r\n this.gridCacheCanvas = null;\r\n this.gridCacheCtx = null;\r\n return;\r\n }\r\n\r\n this.gridCacheCtx = this.gridCacheCanvas.getContext('2d') as CanvasRenderingContext2D | null;\r\n }\r\n\r\n private render(): void {\r\n const t0 = performance.now();\r\n const ctx = this.canvasEl.getContext('2d');\r\n if (!ctx) return;\r\n\r\n let layersMs = 0;\r\n let compositeMs = 0;\r\n let gridMs = 0;\r\n\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n const cssWidth = this.canvasEl.clientWidth;\r\n const cssHeight = this.canvasEl.clientHeight;\r\n\r\n // idempotent; catches resizes that bypass setCanvasSize\r\n this.marginViewport.setViewport(cssWidth, cssHeight, dpr);\r\n\r\n const currentZoom = this.camera.zoom;\r\n const currentCamX = this.camera.position.x;\r\n const currentCamY = this.camera.position.y;\r\n if (this.marginViewport.needsRecenter(currentCamX, currentCamY, currentZoom)) {\r\n this.marginViewport.recenter(currentCamX, currentCamY, currentZoom);\r\n this.layerCache.markAllDirty();\r\n this.gridCacheDirty = true;\r\n }\r\n\r\n ctx.save();\r\n ctx.scale(dpr, dpr);\r\n\r\n this.renderer.setCanvasSize(cssWidth, cssHeight);\r\n const hasGridElement = this.store.getElementsByType('grid').length > 0;\r\n const bgT0 = performance.now();\r\n if (hasGridElement) {\r\n ctx.save();\r\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n ctx.clearRect(0, 0, cssWidth, cssHeight);\r\n ctx.restore();\r\n } else {\r\n this.background.render(ctx, this.camera);\r\n }\r\n const backgroundMs = performance.now() - bgT0;\r\n\r\n ctx.save();\r\n ctx.translate(this.camera.position.x, this.camera.position.y);\r\n ctx.scale(this.camera.zoom, this.camera.zoom);\r\n\r\n const cullBounds = this.marginViewport.cachedWorldBounds();\r\n const cullPad = Math.max(cullBounds.w, cullBounds.h) * 0.05;\r\n const cullingRect: Bounds = {\r\n x: cullBounds.x - cullPad,\r\n y: cullBounds.y - cullPad,\r\n w: cullBounds.w + cullPad * 2,\r\n h: cullBounds.h + cullPad * 2,\r\n };\r\n\r\n const allElements = this.store.getAll();\r\n this.layerGroups.clear();\r\n const gridElements: CanvasElement[] = [];\r\n let domZIndex = 0;\r\n\r\n for (const element of allElements) {\r\n if (!this.layerManager.isLayerVisible(element.layerId)) {\r\n if (this.renderer.isDomElement(element)) {\r\n this.domNodeManager.hideDomNode(element.id);\r\n }\r\n continue;\r\n }\r\n\r\n if (this.renderer.isDomElement(element)) {\r\n const elBounds = getElementBounds(element);\r\n if (elBounds && !boundsIntersect(elBounds, cullingRect)) {\r\n this.domNodeManager.hideDomNode(element.id);\r\n } else {\r\n this.domNodeManager.syncDomNode(element, domZIndex++);\r\n }\r\n continue;\r\n }\r\n\r\n // Grids are viewport-filling; handled via anchored cache below\r\n if (element.type === 'grid') {\r\n gridElements.push(element);\r\n continue;\r\n }\r\n\r\n let group = this.layerGroups.get(element.layerId);\r\n if (!group) {\r\n group = [];\r\n this.layerGroups.set(element.layerId, group);\r\n }\r\n group.push(element);\r\n }\r\n\r\n for (const [layerId, elements] of this.layerGroups) {\r\n const isActiveDrawingLayer = layerId === this.activeDrawingLayerId;\r\n\r\n if (!this.layerCache.isDirty(layerId)) {\r\n const compT0 = performance.now();\r\n this.compositeLayerCache(ctx, layerId);\r\n compositeMs += performance.now() - compT0;\r\n continue;\r\n }\r\n\r\n if (isActiveDrawingLayer) {\r\n const compT0 = performance.now();\r\n this.compositeLayerCache(ctx, layerId);\r\n compositeMs += performance.now() - compT0;\r\n continue;\r\n }\r\n\r\n const offCtx = this.layerCache.getContext(layerId);\r\n if (offCtx) {\r\n const layerT0 = performance.now();\r\n const offCanvas = this.layerCache.getCanvas(layerId);\r\n offCtx.clearRect(0, 0, offCanvas.width, offCanvas.height);\r\n offCtx.save();\r\n this.marginViewport.applyRenderTransform(offCtx);\r\n for (const element of elements) {\r\n const elBounds = getElementBounds(element);\r\n if (elBounds && !boundsIntersect(elBounds, cullingRect)) continue;\r\n this.renderer.renderCanvasElement(offCtx as CanvasRenderingContext2D, element);\r\n }\r\n offCtx.restore();\r\n this.layerCache.markClean(layerId);\r\n layersMs += performance.now() - layerT0;\r\n\r\n const compT0 = performance.now();\r\n this.compositeLayerCache(ctx, layerId);\r\n compositeMs += performance.now() - compT0;\r\n }\r\n }\r\n\r\n // Render grids on top of layer elements\r\n if (gridElements.length > 0) {\r\n const gridT0 = performance.now();\r\n const gridRef = gridElements[0];\r\n const gridDirty = this.gridCacheDirty || gridRef !== this.lastGridRef;\r\n\r\n if (gridDirty) {\r\n this.ensureGridCache();\r\n if (this.gridCacheCtx && this.gridCacheCanvas) {\r\n const cb = this.marginViewport.cachedWorldBounds();\r\n this.renderer.setGridBoundsOverride({\r\n minX: cb.x,\r\n minY: cb.y,\r\n maxX: cb.x + cb.w,\r\n maxY: cb.y + cb.h,\r\n });\r\n const gc = this.gridCacheCtx;\r\n gc.clearRect(0, 0, this.gridCacheCanvas.width, this.gridCacheCanvas.height);\r\n gc.save();\r\n this.marginViewport.applyRenderTransform(gc);\r\n try {\r\n for (const grid of gridElements) {\r\n this.renderer.renderCanvasElement(gc as CanvasRenderingContext2D, grid);\r\n }\r\n } finally {\r\n gc.restore();\r\n this.renderer.setGridBoundsOverride(null);\r\n }\r\n }\r\n this.gridCacheDirty = false;\r\n this.lastGridRef = gridRef;\r\n }\r\n\r\n if (this.gridCacheCanvas) {\r\n const offset = this.marginViewport.compositeOffset(\r\n this.camera.position.x,\r\n this.camera.position.y,\r\n );\r\n ctx.save();\r\n ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n ctx.drawImage(this.gridCacheCanvas as CanvasImageSource, offset.x, offset.y);\r\n ctx.restore();\r\n } else {\r\n for (const grid of gridElements) {\r\n this.renderer.renderCanvasElement(ctx, grid);\r\n }\r\n }\r\n gridMs = performance.now() - gridT0;\r\n }\r\n\r\n const overlayT0 = performance.now();\r\n const activeTool = this.toolManager.activeTool;\r\n if (activeTool?.renderOverlay) {\r\n activeTool.renderOverlay(ctx);\r\n }\r\n const overlayMs = performance.now() - overlayT0;\r\n\r\n ctx.restore();\r\n ctx.restore();\r\n\r\n this.stats.recordFrame(performance.now() - t0, {\r\n gridMs,\r\n layersMs,\r\n backgroundMs,\r\n compositeMs,\r\n overlayMs,\r\n });\r\n }\r\n}\r\n","import type { MarginViewport } from './margin-viewport';\r\n\r\nfunction createOffscreenCanvas(width: number, height: number): HTMLCanvasElement | OffscreenCanvas {\r\n if (typeof OffscreenCanvas !== 'undefined') {\r\n return new OffscreenCanvas(width, height);\r\n }\r\n const canvas = document.createElement('canvas');\r\n canvas.width = width;\r\n canvas.height = height;\r\n return canvas;\r\n}\r\n\r\nexport class LayerCache {\r\n private canvases = new Map<string, HTMLCanvasElement | OffscreenCanvas>();\r\n private dirtyFlags = new Map<string, boolean>();\r\n\r\n constructor(private readonly viewport: MarginViewport) {}\r\n\r\n isDirty(layerId: string): boolean {\r\n return this.dirtyFlags.get(layerId) !== false;\r\n }\r\n\r\n markDirty(layerId: string): void {\r\n this.dirtyFlags.set(layerId, true);\r\n }\r\n\r\n markClean(layerId: string): void {\r\n this.dirtyFlags.set(layerId, false);\r\n }\r\n\r\n markAllDirty(): void {\r\n for (const [id] of this.dirtyFlags) {\r\n this.dirtyFlags.set(id, true);\r\n }\r\n }\r\n\r\n getCanvas(layerId: string): HTMLCanvasElement | OffscreenCanvas {\r\n let canvas = this.canvases.get(layerId);\r\n if (!canvas) {\r\n canvas = createOffscreenCanvas(this.viewport.physicalWidth(), this.viewport.physicalHeight());\r\n this.canvases.set(layerId, canvas);\r\n this.dirtyFlags.set(layerId, true);\r\n }\r\n return canvas;\r\n }\r\n\r\n getContext(layerId: string): CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null {\r\n const canvas = this.getCanvas(layerId);\r\n return canvas.getContext('2d') as\r\n | CanvasRenderingContext2D\r\n | OffscreenCanvasRenderingContext2D\r\n | null;\r\n }\r\n\r\n resize(): void {\r\n const w = this.viewport.physicalWidth();\r\n const h = this.viewport.physicalHeight();\r\n for (const [id, canvas] of this.canvases) {\r\n canvas.width = w;\r\n canvas.height = h;\r\n this.dirtyFlags.set(id, true);\r\n }\r\n }\r\n\r\n clear(): void {\r\n this.canvases.clear();\r\n this.dirtyFlags.clear();\r\n }\r\n}\r\n","import type { Bounds } from '../core/types';\r\n\r\n/**\r\n * Owns the cache anchor (the camera state the screen-space caches were last rendered at)\r\n * and the margin geometry. Pure — holds no canvas. Caches render a region inflated by\r\n * `marginPx` on every side, so a pan within the margin is an offset-blit, not a re-raster.\r\n *\r\n * Call setViewport(cssW, cssH, dpr) before physicalWidth/Height, applyRenderTransform, or compositeOffset — they read the stored dpr.\r\n */\r\nexport class MarginViewport {\r\n private cssW = 0;\r\n private cssH = 0;\r\n private dpr = 1;\r\n private anchorCamX = 0;\r\n private anchorCamY = 0;\r\n private anchorZoom = Number.NaN; // sentinel → first needsRecenter is true\r\n private viewportDirty = true;\r\n\r\n constructor(private marginPx: number) {}\r\n\r\n setMargin(marginPx: number): void {\r\n if (marginPx !== this.marginPx) {\r\n this.marginPx = marginPx;\r\n this.viewportDirty = true;\r\n }\r\n }\r\n\r\n setViewport(cssW: number, cssH: number, dpr: number): void {\r\n if (cssW !== this.cssW || cssH !== this.cssH || dpr !== this.dpr) {\r\n this.cssW = cssW;\r\n this.cssH = cssH;\r\n this.dpr = dpr;\r\n this.viewportDirty = true;\r\n }\r\n }\r\n\r\n physicalWidth(): number {\r\n return Math.round((this.cssW + 2 * this.marginPx) * this.dpr);\r\n }\r\n\r\n physicalHeight(): number {\r\n return Math.round((this.cssH + 2 * this.marginPx) * this.dpr);\r\n }\r\n\r\n needsRecenter(camX: number, camY: number, zoom: number): boolean {\r\n return (\r\n this.viewportDirty ||\r\n zoom !== this.anchorZoom ||\r\n Math.abs(camX - this.anchorCamX) > this.marginPx ||\r\n Math.abs(camY - this.anchorCamY) > this.marginPx\r\n );\r\n }\r\n\r\n recenter(camX: number, camY: number, zoom: number): void {\r\n this.anchorCamX = camX;\r\n this.anchorCamY = camY;\r\n this.anchorZoom = zoom;\r\n this.viewportDirty = false;\r\n }\r\n\r\n /** Applies dpr scale + anchor-relative world transform. setViewport must have been called first. */\r\n applyRenderTransform(ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D): void {\r\n ctx.scale(this.dpr, this.dpr);\r\n ctx.translate(this.marginPx + this.anchorCamX, this.marginPx + this.anchorCamY);\r\n ctx.scale(this.anchorZoom, this.anchorZoom);\r\n }\r\n\r\n // Device-px destination for drawImage(cache, x, y).\r\n // A world point P sits in the cache at CSS x `margin + anchorCamX + P*zoom`; it must land on\r\n // screen at `camX + P*zoom`; so the blit offset is `camX - anchorCamX - margin` (CSS) * dpr.\r\n compositeOffset(camX: number, camY: number): { x: number; y: number } {\r\n return {\r\n x: (camX - this.anchorCamX - this.marginPx) * this.dpr,\r\n y: (camY - this.anchorCamY - this.marginPx) * this.dpr,\r\n };\r\n }\r\n\r\n // World-space bounds of the whole cached region at the anchor (cull rect for re-renders).\r\n cachedWorldBounds(): Bounds {\r\n const z = this.anchorZoom;\r\n return {\r\n x: (-this.marginPx - this.anchorCamX) / z,\r\n y: (-this.marginPx - this.anchorCamY) / z,\r\n w: (this.cssW + 2 * this.marginPx) / z,\r\n h: (this.cssH + 2 * this.marginPx) / z,\r\n };\r\n }\r\n}\r\n","import { Camera } from './camera';\r\nimport type { CameraOptions } from './camera';\r\nimport { InputHandler } from './input-handler';\r\nimport type { ShortcutOptions, ShortcutsApi } from './shortcut-map';\r\nimport { Background } from './background';\r\nimport type { BackgroundOptions } from './background';\r\nimport { ElementStore } from '../elements/element-store';\r\nimport { ElementRenderer } from '../elements/element-renderer';\r\nimport { NoteEditor } from '../elements/note-editor';\r\nimport type { FontSizePreset } from '../elements/note-toolbar';\r\nimport type { CanvasElement, ArrowElement, GridElement } from '../elements/types';\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 { ToolManager } from '../tools/tool-manager';\r\nimport type { ToolContext } from '../tools/types';\r\nimport { HistoryStack } from '../history/history-stack';\r\nimport { HistoryRecorder } from '../history/history-recorder';\r\nimport { createImage, createHtmlElement, createGrid } from '../elements/element-factory';\r\nimport { exportState as exportCanvasState, parseState } from '../core/state-serializer';\r\nimport { exportImage } from './export-image';\r\nimport type { ExportImageOptions } from './export-image';\r\nimport type { CanvasState } from '../core/state-serializer';\r\nimport { LayerManager } from '../layers/layer-manager';\r\nimport { InteractMode } from './interact-mode';\r\nimport { DomNodeManager } from './dom-node-manager';\r\nimport { DoubleTapDetector } from './double-tap-detector';\r\nimport { RenderLoop } from './render-loop';\r\nimport type { RenderStatsSnapshot } from './render-stats';\r\nimport { LayerCache } from './layer-cache';\r\nimport { MarginViewport } from './margin-viewport';\r\nimport { isNoteContentEmpty } from '../elements/note-sanitizer';\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 ViewportOptions {\r\n camera?: CameraOptions;\r\n background?: BackgroundOptions;\r\n fontSizePresets?: FontSizePreset[];\r\n toolbar?: boolean;\r\n placeholder?: string;\r\n shortcuts?: ShortcutOptions;\r\n onHtmlElementMount?: (\r\n elementId: string,\r\n domId: string | undefined,\r\n container: HTMLDivElement,\r\n ) => void;\r\n onDrop?: (event: DragEvent, worldPosition: { x: number; y: number }) => void;\r\n onImageError?: (info: { src: string; elementIds: string[]; cause?: unknown }) => void;\r\n /** CSS-pixel margin cached beyond the viewport. Default `256`. Set `0` to disable. */\r\n panBufferMargin?: number;\r\n}\r\n\r\nexport class Viewport {\r\n readonly camera: Camera;\r\n readonly store: ElementStore;\r\n readonly layerManager: LayerManager;\r\n readonly toolManager: ToolManager;\r\n readonly history: HistoryStack;\r\n readonly domLayer: HTMLDivElement;\r\n private readonly canvasEl: HTMLCanvasElement;\r\n private readonly wrapper: HTMLDivElement;\r\n private readonly unsubCamera: () => void;\r\n private readonly unsubStore: (() => void)[];\r\n private readonly inputHandler: InputHandler;\r\n private readonly background: Background;\r\n private readonly renderer: ElementRenderer;\r\n private readonly noteEditor: NoteEditor;\r\n private readonly historyRecorder: HistoryRecorder;\r\n readonly toolContext: ToolContext;\r\n private readonly marginViewport: MarginViewport;\r\n private resizeObserver: ResizeObserver | null = null;\r\n private _snapToGrid = 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 gridChangeListeners = new Set<(info: GridInfo | null) => void>();\r\n private readonly doubleTapDetector = new DoubleTapDetector();\r\n private tapDownX = 0;\r\n private tapDownY = 0;\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.onTextEditStop(id));\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\r\n this.wrapper = this.createWrapper();\r\n this.canvasEl = this.createCanvas();\r\n this.domLayer = this.createDomLayer();\r\n\r\n this.wrapper.appendChild(this.canvasEl);\r\n this.wrapper.appendChild(this.domLayer);\r\n this.container.appendChild(this.wrapper);\r\n\r\n this.toolContext = {\r\n camera: this.camera,\r\n store: this.store,\r\n requestRender: () => this.requestRender(),\r\n switchTool: (name: string) => this.toolManager.setTool(name, this.toolContext),\r\n editElement: (id: string) => this.startEditingElement(id),\r\n fitNoteHeight: (id: string) => this.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 };\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 shortcuts: options.shortcuts,\r\n });\r\n\r\n this.domNodeManager = new DomNodeManager({\r\n domLayer: this.domLayer,\r\n onEditRequest: (id) => this.startEditingElement(id),\r\n isEditingElement: (id) =>\r\n this.noteEditor.isEditing && this.noteEditor.editingElementId === id,\r\n getVersion: (id) => this.store.getVersion(id),\r\n });\r\n\r\n this.interactMode = new InteractMode({\r\n getNode: (id) => this.domNodeManager.getNode(id),\r\n });\r\n\r\n this.marginViewport = new MarginViewport(options.panBufferMargin ?? 256);\r\n this.marginViewport.setViewport(\r\n this.canvasEl.clientWidth || 800,\r\n this.canvasEl.clientHeight || 600,\r\n typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1,\r\n );\r\n const layerCache = new LayerCache(this.marginViewport);\r\n\r\n this.renderLoop = new RenderLoop({\r\n canvasEl: this.canvasEl,\r\n camera: this.camera,\r\n background: this.background,\r\n store: this.store,\r\n renderer: this.renderer,\r\n toolManager: this.toolManager,\r\n layerManager: this.layerManager,\r\n domNodeManager: this.domNodeManager,\r\n layerCache,\r\n marginViewport: this.marginViewport,\r\n });\r\n\r\n this.unsubCamera = this.camera.onChange(() => {\r\n this.applyCameraTransform();\r\n this.noteEditor.updateToolbarPosition();\r\n this.requestRender();\r\n });\r\n\r\n this.unsubStore = [\r\n this.store.on('add', (el) => {\r\n if (el.type === 'grid') this.syncGridContext();\r\n this.renderLoop.markLayerDirty(el.layerId);\r\n this.requestRender();\r\n }),\r\n this.store.on('remove', (el) => {\r\n if (el.type === 'grid') this.syncGridContext();\r\n this.unbindArrowsFrom(el);\r\n this.domNodeManager.removeDomNode(el.id);\r\n this.renderLoop.markLayerDirty(el.layerId);\r\n this.requestRender();\r\n }),\r\n this.store.on('update', ({ previous, current }) => {\r\n if (current.type === 'grid') this.syncGridContext();\r\n this.renderLoop.markLayerDirty(current.layerId);\r\n if (previous.layerId !== current.layerId) {\r\n this.renderLoop.markLayerDirty(previous.layerId);\r\n }\r\n this.requestRender();\r\n }),\r\n this.store.on('clear', () => {\r\n this.domNodeManager.clearDomNodes();\r\n this.renderLoop.markAllLayersDirty();\r\n this.syncGridContext();\r\n this.requestRender();\r\n }),\r\n ];\r\n\r\n this.layerManager.on('change', () => {\r\n this.toolContext.activeLayerId = this.layerManager.activeLayerId;\r\n this.requestRender();\r\n });\r\n\r\n this.wrapper.addEventListener('pointerdown', this.onTapDown);\r\n this.wrapper.addEventListener('pointerup', this.onDoubleTap);\r\n this.wrapper.addEventListener('dragover', this.onDragOver);\r\n this.wrapper.addEventListener('drop', this.onDrop);\r\n this.observeResize();\r\n this.syncCanvasSize();\r\n this.renderLoop.start();\r\n this.syncGridContext();\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 fitToContent(padding = 40): void {\r\n if (this.wrapper.clientWidth === 0 || this.wrapper.clientHeight === 0) return;\r\n const visibleElements = this.store\r\n .getAll()\r\n .filter((el) => this.layerManager.isLayerVisible(el.layerId));\r\n const bbox = getElementsBoundingBox(visibleElements);\r\n if (!bbox) return;\r\n this.camera.fitToContent(bbox, this.wrapper.clientWidth, this.wrapper.clientHeight, padding);\r\n }\r\n\r\n requestRender(): void {\r\n this.renderLoop.requestRender();\r\n }\r\n\r\n exportState(): CanvasState {\r\n return exportCanvasState(\r\n this.store.snapshot(),\r\n this.camera,\r\n this.layerManager.snapshot(),\r\n this.layerManager.activeLayerId,\r\n );\r\n }\r\n\r\n exportJSON(): string {\r\n return JSON.stringify(this.exportState());\r\n }\r\n\r\n async exportImage(options?: ExportImageOptions): Promise<Blob | null> {\r\n return exportImage(this.store, options, this.layerManager);\r\n }\r\n\r\n loadState(state: CanvasState): void {\r\n this.inputHandler.flushPendingHistory();\r\n this.historyRecorder.pause();\r\n this.noteEditor.destroy(this.store);\r\n this.domNodeManager.clearDomNodes();\r\n this.store.loadSnapshot(state.elements);\r\n if (state.layers && state.layers.length > 0) {\r\n this.layerManager.loadSnapshot(state.layers);\r\n }\r\n if (state.activeLayerId) {\r\n this.layerManager.setActiveLayer(state.activeLayerId);\r\n }\r\n this.domNodeManager.reattachHtmlContent(this.store);\r\n if (this.onHtmlElementMount) {\r\n for (const el of this.store.getElementsByType('html')) {\r\n if (!this.domNodeManager.hasContent(el.id)) {\r\n this.domNodeManager.syncDomNode(el);\r\n const node = this.domNodeManager.getNode(el.id);\r\n if (node) {\r\n this.onHtmlElementMount(el.id, el.domId, node);\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n overflow: 'hidden',\r\n pointerEvents: el.interactive ? 'auto' : 'none',\r\n });\r\n }\r\n }\r\n }\r\n }\r\n this.history.clear();\r\n this.historyRecorder.resume();\r\n this.camera.moveTo(state.camera.position.x, state.camera.position.y);\r\n this.camera.setZoom(state.camera.zoom);\r\n }\r\n\r\n loadJSON(json: string): void {\r\n this.loadState(parseState(json));\r\n }\r\n\r\n setTool(name: string): void {\r\n if (!this.toolManager.getTool(name)) {\r\n console.warn(`[fieldnotes] setTool: no tool registered as \"${name}\"`);\r\n return;\r\n }\r\n this.toolManager.setTool(name, this.toolContext);\r\n }\r\n\r\n get shortcuts(): ShortcutsApi {\r\n return this.inputHandler.shortcuts;\r\n }\r\n\r\n undo(): boolean {\r\n this.inputHandler.flushPendingHistory();\r\n this.historyRecorder.pause();\r\n const result = this.history.undo(this.store);\r\n this.historyRecorder.resume();\r\n if (result) this.requestRender();\r\n return result;\r\n }\r\n\r\n redo(): boolean {\r\n this.inputHandler.flushPendingHistory();\r\n this.historyRecorder.pause();\r\n const result = this.history.redo(this.store);\r\n this.historyRecorder.resume();\r\n if (result) this.requestRender();\r\n return result;\r\n }\r\n\r\n addImage(src: string, position: { x: number; y: number }, size = { w: 300, h: 200 }): string {\r\n const image = createImage({ position, size, src, layerId: this.layerManager.activeLayerId });\r\n this.historyRecorder.begin();\r\n this.store.add(image);\r\n this.historyRecorder.commit();\r\n this.requestRender();\r\n return image.id;\r\n }\r\n\r\n addHtmlElement(\r\n dom: HTMLElement,\r\n position: { x: number; y: number },\r\n size = { w: 200, h: 150 },\r\n ): string {\r\n const domId = dom.id || undefined;\r\n const el = createHtmlElement({\r\n position,\r\n size,\r\n domId,\r\n layerId: this.layerManager.activeLayerId,\r\n });\r\n this.domNodeManager.storeHtmlContent(el.id, dom);\r\n this.historyRecorder.begin();\r\n this.store.add(el);\r\n this.historyRecorder.commit();\r\n this.requestRender();\r\n return el.id;\r\n }\r\n\r\n removeLayer(id: string): void {\r\n this.historyRecorder.begin();\r\n this.layerManager.removeLayer(id);\r\n this.historyRecorder.commit();\r\n }\r\n\r\n updateHtmlElement(id: string, newContent: HTMLElement): void {\r\n const el = this.store.getById(id);\r\n if (!el) throw new Error(`Element not found: ${id}`);\r\n if (el.type !== 'html') throw new Error(`Element ${id} is not an HTML element`);\r\n this.domNodeManager.resetHtmlContent(id);\r\n this.domNodeManager.storeHtmlContent(id, newContent);\r\n this.requestRender();\r\n }\r\n\r\n addGrid(input: {\r\n gridType?: 'square' | 'hex';\r\n hexOrientation?: 'pointy' | 'flat';\r\n cellSize?: number;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n }): string {\r\n const existing = this.store.getElementsByType('grid')[0];\r\n this.historyRecorder.begin();\r\n if (existing) {\r\n this.store.remove(existing.id);\r\n }\r\n const grid = createGrid({ ...input, layerId: this.layerManager.activeLayerId });\r\n this.store.add(grid);\r\n this.historyRecorder.commit();\r\n this.requestRender();\r\n return grid.id;\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 const grid = this.store.getElementsByType('grid')[0];\r\n if (!grid) return;\r\n this.historyRecorder.begin();\r\n this.store.update(grid.id, updates);\r\n this.historyRecorder.commit();\r\n this.requestRender();\r\n }\r\n\r\n removeGrid(): void {\r\n const grid = this.store.getElementsByType('grid')[0];\r\n if (!grid) return;\r\n this.historyRecorder.begin();\r\n this.store.remove(grid.id);\r\n this.historyRecorder.commit();\r\n this.requestRender();\r\n }\r\n\r\n getGridInfo(): GridInfo | null {\r\n const grid = this.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 onGridChange(listener: (info: GridInfo | null) => void): () => void {\r\n this.gridChangeListeners.add(listener);\r\n return () => {\r\n this.gridChangeListeners.delete(listener);\r\n };\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.historyRecorder.destroy();\r\n this.wrapper.removeEventListener('pointerdown', this.onTapDown);\r\n this.wrapper.removeEventListener('pointerup', this.onDoubleTap);\r\n this.wrapper.removeEventListener('dragover', this.onDragOver);\r\n this.wrapper.removeEventListener('drop', this.onDrop);\r\n this.inputHandler.destroy();\r\n this.unsubCamera();\r\n this.unsubStore.forEach((fn) => fn());\r\n this.resizeObserver?.disconnect();\r\n this.resizeObserver = null;\r\n this.wrapper.remove();\r\n }\r\n\r\n private startEditingElement(id: string): void {\r\n const element = this.store.getById(id);\r\n if (!element || (element.type !== 'note' && element.type !== 'text')) return;\r\n\r\n this.renderLoop.flush();\r\n\r\n const node = this.domNodeManager.getNode(id);\r\n if (node) {\r\n this.noteEditor.startEditing(node, id, this.store);\r\n }\r\n }\r\n\r\n private fitNoteHeight(elementId: string): void {\r\n const element = this.store.getById(elementId);\r\n if (!element || element.type !== 'note') return;\r\n if (isNoteContentEmpty(element.text)) return;\r\n const node = this.domNodeManager.getNode(elementId);\r\n if (!node) return;\r\n const measured = node.scrollHeight;\r\n if (measured > element.size.h) {\r\n this.store.update(elementId, { size: { w: element.size.w, h: measured } });\r\n }\r\n }\r\n\r\n private onTextEditStop(elementId: string): void {\r\n const element = this.store.getById(elementId);\r\n if (!element) return;\r\n\r\n if (element.type === 'note') {\r\n if (isNoteContentEmpty(element.text)) {\r\n this.store.remove(elementId);\r\n return;\r\n }\r\n this.fitNoteHeight(elementId);\r\n return;\r\n }\r\n\r\n if (element.type !== 'text') return;\r\n\r\n if (!element.text || element.text.trim() === '') {\r\n this.store.remove(elementId);\r\n return;\r\n }\r\n\r\n const node = this.domNodeManager.getNode(elementId);\r\n if (node && 'size' in element) {\r\n const measured = node.scrollHeight;\r\n if (measured !== element.size.h) {\r\n this.store.update(elementId, { size: { w: element.size.w, h: measured } });\r\n }\r\n }\r\n }\r\n\r\n private onTapDown = (e: PointerEvent): void => {\r\n this.tapDownX = e.clientX;\r\n this.tapDownY = e.clientY;\r\n };\r\n\r\n private onDoubleTap = (e: PointerEvent): void => {\r\n const dx = e.clientX - this.tapDownX;\r\n const dy = e.clientY - this.tapDownY;\r\n const moved = Math.sqrt(dx * dx + dy * dy);\r\n if (moved > 10) return;\r\n\r\n if (!this.doubleTapDetector.feed(e)) return;\r\n if (typeof document.elementFromPoint !== 'function') return;\r\n\r\n const el = document.elementFromPoint(e.clientX, e.clientY);\r\n\r\n const nodeEl = (el as HTMLElement | null)?.closest<HTMLDivElement>('[data-element-id]');\r\n if (nodeEl) {\r\n const elementId = nodeEl.dataset['elementId'];\r\n if (elementId) {\r\n const element = this.store.getById(elementId);\r\n if (element?.type === 'note' || element?.type === 'text') {\r\n this.startEditingElement(elementId);\r\n return;\r\n }\r\n }\r\n }\r\n\r\n const rect = this.wrapper.getBoundingClientRect();\r\n const screen = { x: e.clientX - rect.left, y: e.clientY - rect.top };\r\n const world = this.camera.screenToWorld(screen);\r\n const hit = this.hitTestWorld(world);\r\n if (hit?.type === 'html') {\r\n this.interactMode.startInteracting(hit.id);\r\n }\r\n };\r\n\r\n private hitTestWorld(world: { x: number; y: number }): CanvasElement | null {\r\n const candidates = this.store.queryPoint(world).reverse();\r\n for (const el of candidates) {\r\n if (!('size' in el)) continue;\r\n const { x, y } = el.position;\r\n const { w, h } = el.size;\r\n if (world.x >= x && world.x <= x + w && world.y >= y && world.y <= y + h) {\r\n return el;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n stopInteracting(): void {\r\n this.interactMode.stopInteracting();\r\n }\r\n\r\n private onDragOver = (e: DragEvent): void => {\r\n e.preventDefault();\r\n };\r\n\r\n private onDrop = (e: DragEvent): void => {\r\n e.preventDefault();\r\n const rect = this.wrapper.getBoundingClientRect();\r\n const screenPos = { x: e.clientX - rect.left, y: e.clientY - rect.top };\r\n const worldPos = this.camera.screenToWorld(screenPos);\r\n\r\n if (this.dropHandler) {\r\n this.dropHandler(e, worldPos);\r\n return;\r\n }\r\n\r\n const files = e.dataTransfer?.files;\r\n if (!files) return;\r\n\r\n for (const file of files) {\r\n if (!file.type.startsWith('image/')) continue;\r\n\r\n const reader = new FileReader();\r\n reader.onload = () => {\r\n const src = reader.result;\r\n if (typeof src !== 'string') return;\r\n this.addImage(src, worldPos);\r\n };\r\n reader.readAsDataURL(file);\r\n }\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 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\n private createCanvas(): HTMLCanvasElement {\r\n const el = document.createElement('canvas');\r\n Object.assign(el.style, {\r\n position: 'absolute',\r\n top: '0',\r\n left: '0',\r\n width: '100%',\r\n height: '100%',\r\n });\r\n return el;\r\n }\r\n\r\n private createDomLayer(): HTMLDivElement {\r\n const el = document.createElement('div');\r\n Object.assign(el.style, {\r\n position: 'absolute',\r\n top: '0',\r\n left: '0',\r\n width: '100%',\r\n height: '100%',\r\n pointerEvents: 'none',\r\n transformOrigin: '0 0',\r\n });\r\n return el;\r\n }\r\n\r\n private applyCameraTransform(): void {\r\n this.domLayer.style.transform = this.camera.toCSSTransform();\r\n }\r\n\r\n private syncCanvasSize(): void {\r\n const rect = this.container.getBoundingClientRect();\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n this.renderLoop.setCanvasSize(rect.width * dpr, rect.height * dpr);\r\n this.requestRender();\r\n }\r\n\r\n private syncGridContext(): void {\r\n const grid = this.store.getElementsByType('grid')[0];\r\n if (grid) {\r\n this.toolContext.gridSize = grid.cellSize;\r\n this.toolContext.gridType = grid.gridType;\r\n this.toolContext.hexOrientation = grid.hexOrientation;\r\n } else {\r\n this.toolContext.gridSize = this._gridSize;\r\n this.toolContext.gridType = undefined;\r\n this.toolContext.hexOrientation = undefined;\r\n }\r\n this.notifyGridChangeListeners();\r\n }\r\n\r\n private notifyGridChangeListeners(): void {\r\n const info = this.getGridInfo();\r\n for (const listener of this.gridChangeListeners) {\r\n listener(info);\r\n }\r\n }\r\n\r\n private observeResize(): void {\r\n if (typeof ResizeObserver === 'undefined') return;\r\n this.resizeObserver = new ResizeObserver(() => this.syncCanvasSize());\r\n this.resizeObserver.observe(this.container);\r\n }\r\n}\r\n","import type { Tool, ToolContext, PointerState } from './types';\n\nexport class HandTool implements Tool {\n readonly name = 'hand';\n private panning = false;\n private lastScreen = { x: 0, y: 0 };\n\n onActivate(ctx: ToolContext): void {\n ctx.setCursor?.('grab');\n }\n\n onDeactivate(ctx: ToolContext): void {\n ctx.setCursor?.('default');\n }\n\n onPointerDown(state: PointerState, ctx: ToolContext): void {\n this.panning = true;\n this.lastScreen = { x: state.x, y: state.y };\n ctx.setCursor?.('grabbing');\n }\n\n onPointerMove(state: PointerState, ctx: ToolContext): void {\n if (!this.panning) return;\n const dx = state.x - this.lastScreen.x;\n const dy = state.y - this.lastScreen.y;\n this.lastScreen = { x: state.x, y: state.y };\n ctx.camera.pan(dx, dy);\n }\n\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\n this.panning = false;\n ctx.setCursor?.('grab');\n }\n}\n","import type { StrokePoint } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createStroke } from '../elements/element-factory';\r\nimport { simplifyPoints, smoothToSegments, pressureToWidth } from '../elements/stroke-smoothing';\r\nimport { computeStrokeSegments } from '../elements/stroke-cache';\r\n\r\nexport interface PencilToolOptions {\r\n color?: string;\r\n width?: number;\r\n smoothing?: number;\r\n minPointDistance?: number;\r\n progressiveSimplifyThreshold?: number;\r\n}\r\n\r\nconst MIN_POINTS_FOR_STROKE = 2;\r\nconst DEFAULT_SMOOTHING = 1.5;\r\nconst DEFAULT_PRESSURE = 0.5;\r\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 = 'pencil';\r\n private drawing = false;\r\n private points: StrokePoint[] = [];\r\n private color: string;\r\n private width: number;\r\n private smoothing: number;\r\n private minPointDistance: number;\r\n private progressiveThreshold: number;\r\n private nextSimplifyAt: number;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: PencilToolOptions = {}) {\r\n this.color = options.color ?? '#000000';\r\n this.width = options.width ?? 2;\r\n this.smoothing = options.smoothing ?? DEFAULT_SMOOTHING;\r\n 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 }\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 };\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 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 });\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 ctx.globalAlpha = 0.8;\r\n\r\n const segments = smoothToSegments(this.points);\r\n for (const seg of segments) {\r\n const w =\r\n (pressureToWidth(seg.start.pressure, this.width) +\r\n pressureToWidth(seg.end.pressure, this.width)) /\r\n 2;\r\n ctx.lineWidth = w;\r\n ctx.beginPath();\r\n ctx.moveTo(seg.start.x, seg.start.y);\r\n ctx.bezierCurveTo(seg.cp1.x, seg.cp1.y, seg.cp2.x, seg.cp2.y, seg.end.x, seg.end.y);\r\n ctx.stroke();\r\n }\r\n\r\n ctx.restore();\r\n }\r\n}\r\n","import type { Point } from '../core/types';\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 { 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\n\r\nexport interface EraserToolOptions {\r\n radius?: number;\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 readonly radius: number;\r\n private readonly cursor: string;\r\n\r\n constructor(options: EraserToolOptions = {}) {\r\n this.radius = options.radius ?? DEFAULT_RADIUS;\r\n this.cursor = makeEraserCursor(this.radius);\r\n }\r\n\r\n getOptions(): EraserToolOptions {\r\n return { radius: this.radius };\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 queryBounds: Bounds = {\r\n x: world.x - this.radius,\r\n y: world.y - this.radius,\r\n w: this.radius * 2,\r\n h: this.radius * 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)) {\r\n ctx.store.remove(el.id);\r\n erased = true;\r\n }\r\n }\r\n\r\n if (erased) ctx.requestRender();\r\n }\r\n\r\n private strokeIntersects(stroke: StrokeElement, point: Point): boolean {\r\n return hitTestStroke(stroke, point, this.radius);\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { ArrowElement, CanvasElement } from '../elements/types';\r\nimport type { ToolContext } from './types';\r\nimport { getArrowMidpoint, getBendFromPoint } from '../elements/arrow-geometry';\r\nimport { findBindTarget, getElementCenter } from '../elements/arrow-binding';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\n\r\nconst BIND_THRESHOLD = 20;\r\n\r\nexport type ArrowHandle = 'start' | 'mid' | 'end';\r\n\r\nconst HANDLE_RADIUS = 5;\r\nconst HANDLE_HIT_PADDING = 4;\r\n\r\nconst ARROW_HANDLE_CURSORS: Record<ArrowHandle, string> = {\r\n start: 'crosshair',\r\n end: 'crosshair',\r\n mid: 'grab',\r\n};\r\n\r\nexport function getArrowHandleCursor(handle: ArrowHandle, active: boolean): string {\r\n if (handle === 'mid' && active) return 'grabbing';\r\n return ARROW_HANDLE_CURSORS[handle];\r\n}\r\n\r\nexport function getArrowHandlePositions(arrow: ArrowElement): [ArrowHandle, Point][] {\r\n const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);\r\n return [\r\n ['start', arrow.from],\r\n ['mid', mid],\r\n ['end', arrow.to],\r\n ];\r\n}\r\n\r\nexport function hitTestArrowHandles(\r\n world: Point,\r\n selectedIds: string[],\r\n ctx: ToolContext,\r\n): { elementId: string; handle: ArrowHandle } | null {\r\n if (selectedIds.length === 0) return null;\r\n\r\n const zoom = ctx.camera.zoom;\r\n const hitRadius = (HANDLE_RADIUS + HANDLE_HIT_PADDING) / zoom;\r\n\r\n for (const id of selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || el.type !== 'arrow') continue;\r\n\r\n const handles = getArrowHandlePositions(el);\r\n for (const [handle, pos] of handles) {\r\n const dx = world.x - pos.x;\r\n const dy = world.y - pos.y;\r\n if (dx * dx + dy * dy <= hitRadius * hitRadius) {\r\n return { elementId: id, handle };\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport function applyArrowHandleDrag(\r\n handle: ArrowHandle,\r\n elementId: string,\r\n world: Point,\r\n ctx: ToolContext,\r\n): void {\r\n const el = ctx.store.getById(elementId);\r\n if (!el || el.type !== 'arrow') return;\r\n\r\n const threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n\r\n const layerFilter = (candidate: CanvasElement) => candidate.layerId === el.layerId;\r\n\r\n switch (handle) {\r\n case 'start': {\r\n const excludeId = el.toBinding?.elementId;\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);\r\n if (target) {\r\n const center = getElementCenter(target);\r\n ctx.store.update(elementId, {\r\n from: center,\r\n position: center,\r\n fromBinding: { elementId: target.id },\r\n });\r\n } else {\r\n ctx.store.update(elementId, {\r\n from: { x: world.x, y: world.y },\r\n position: { x: world.x, y: world.y },\r\n fromBinding: undefined,\r\n });\r\n }\r\n break;\r\n }\r\n case 'end': {\r\n const excludeId = el.fromBinding?.elementId;\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);\r\n if (target) {\r\n const center = getElementCenter(target);\r\n ctx.store.update(elementId, {\r\n to: center,\r\n toBinding: { elementId: target.id },\r\n });\r\n } else {\r\n ctx.store.update(elementId, {\r\n to: { x: world.x, y: world.y },\r\n toBinding: undefined,\r\n });\r\n }\r\n break;\r\n }\r\n case 'mid': {\r\n const bend = getBendFromPoint(el.from, el.to, world);\r\n ctx.store.update(elementId, { bend });\r\n break;\r\n }\r\n }\r\n\r\n ctx.requestRender();\r\n}\r\n\r\nexport function getArrowHandleDragTarget(\r\n handle: ArrowHandle,\r\n elementId: string,\r\n world: Point,\r\n ctx: ToolContext,\r\n): { x: number; y: number; w: number; h: number } | null {\r\n if (handle === 'mid') return null;\r\n\r\n const el = ctx.store.getById(elementId);\r\n if (!el || el.type !== 'arrow') return null;\r\n\r\n const threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n const excludeId = handle === 'start' ? el.toBinding?.elementId : el.fromBinding?.elementId;\r\n const layerFilter = (candidate: CanvasElement) => candidate.layerId === el.layerId;\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);\r\n if (!target) return null;\r\n\r\n return getElementBounds(target);\r\n}\r\n\r\nexport function renderArrowHandles(\r\n canvasCtx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n zoom: number,\r\n): void {\r\n const radius = HANDLE_RADIUS / zoom;\r\n const handles = getArrowHandlePositions(arrow);\r\n\r\n canvasCtx.setLineDash([]);\r\n canvasCtx.lineWidth = 1.5 / zoom;\r\n\r\n for (const [handle, pos] of handles) {\r\n canvasCtx.fillStyle = handle === 'mid' ? '#2196F3' : '#ffffff';\r\n canvasCtx.strokeStyle = '#2196F3';\r\n\r\n canvasCtx.beginPath();\r\n canvasCtx.arc(pos.x, pos.y, radius, 0, Math.PI * 2);\r\n canvasCtx.fill();\r\n canvasCtx.stroke();\r\n }\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { smartSnap } from '../core/snap';\r\nimport type { CanvasElement, ArrowElement } from '../elements/types';\r\nimport { isNearBezier } from '../elements/arrow-geometry';\r\nimport { findBoundArrows, updateBoundArrow } from '../elements/arrow-binding';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { hitTestStroke } from '../elements/stroke-hit';\r\nimport {\r\n type ArrowHandle,\r\n hitTestArrowHandles,\r\n applyArrowHandleDrag,\r\n renderArrowHandles,\r\n getArrowHandleCursor,\r\n getArrowHandleDragTarget,\r\n} from './arrow-handles';\r\n\r\ntype HandlePosition = 'nw' | 'ne' | 'sw' | 'se';\r\n\r\nconst HANDLE_SIZE = 8;\r\nconst HANDLE_HIT_PADDING = 4;\r\nconst SELECTION_PAD = 4;\r\nconst MIN_ELEMENT_SIZE = 20;\r\n\r\nconst HANDLE_CURSORS: Record<HandlePosition, string> = {\r\n nw: 'nwse-resize',\r\n se: 'nwse-resize',\r\n ne: 'nesw-resize',\r\n sw: 'nesw-resize',\r\n};\r\n\r\ntype Mode =\r\n | { type: 'idle' }\r\n | { type: 'dragging' }\r\n | { type: 'marquee'; start: Point }\r\n | { type: 'resizing'; elementId: string; handle: HandlePosition }\r\n | { type: 'resizing-template'; elementId: string }\r\n | { type: 'arrow-handle'; elementId: string; handle: ArrowHandle };\r\n\r\nexport class SelectTool implements Tool {\r\n readonly name = 'select';\r\n private _selectedIds: string[] = [];\r\n private mode: Mode = { type: 'idle' };\r\n private lastWorld: Point = { x: 0, y: 0 };\r\n private currentWorld: Point = { x: 0, y: 0 };\r\n private ctx: ToolContext | null = null;\r\n private pendingSingleSelectId: string | null = null;\r\n private hasDragged = false;\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 setSelection(ids: string[]): void {\r\n this._selectedIds = ids;\r\n this.ctx?.requestRender();\r\n }\r\n\r\n get isMarqueeActive(): boolean {\r\n return this.mode.type === 'marquee';\r\n }\r\n\r\n onActivate(ctx: ToolContext): void {\r\n this.ctx = ctx;\r\n }\r\n\r\n onDeactivate(ctx: ToolContext): void {\r\n this._selectedIds = [];\r\n this.mode = { type: 'idle' };\r\n this.hoveredId = 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 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 templateResizeHit = this.hitTestTemplateResizeHandle(world, ctx);\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 resizeHit = this.hitTestResizeHandle(world, ctx);\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 = this.hitTest(world, ctx);\r\n if (hit) {\r\n const alreadySelected = this._selectedIds.includes(hit.id);\r\n if (state.shiftKey) {\r\n if (alreadySelected) {\r\n this._selectedIds = this._selectedIds.filter((id) => id !== hit.id);\r\n this.mode = { type: 'idle' };\r\n } else {\r\n this._selectedIds = [...this._selectedIds, hit.id];\r\n this.mode = hit.locked ? { type: 'idle' } : { type: 'dragging' };\r\n }\r\n } else {\r\n if (!alreadySelected) {\r\n this._selectedIds = [hit.id];\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._selectedIds = [];\r\n this.mode = { type: 'marquee', start: world };\r\n }\r\n\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.currentWorld = world;\r\n\r\n if (this.mode.type === 'arrow-handle') {\r\n ctx.setCursor?.(getArrowHandleCursor(this.mode.handle, true));\r\n applyArrowHandleDrag(this.mode.handle, this.mode.elementId, world, ctx);\r\n return;\r\n }\r\n\r\n if (this.mode.type === 'resizing-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 === '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 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 + dx, y: el.position.y + dy },\r\n from: { x: el.from.x + dx, y: el.from.y + dy },\r\n to: { x: el.to.x + dx, y: el.to.y + dy },\r\n });\r\n } else if (ctx.gridType && 'size' in el) {\r\n const centerX = el.position.x + el.size.w / 2 + dx;\r\n const centerY = el.position.y + el.size.h / 2 + dy;\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 + dx, y: el.position.y + dy },\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._selectedIds = this.findElementsInRect(rect, ctx);\r\n }\r\n ctx.requestRender();\r\n }\r\n\r\n if (!this.hasDragged && this.pendingSingleSelectId !== null) {\r\n this._selectedIds = [this.pendingSingleSelectId];\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 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 this.renderMarquee(canvasCtx);\r\n this.renderSelectionBoxes(canvasCtx);\r\n\r\n if (this.mode.type === 'arrow-handle' && this.ctx) {\r\n const target = getArrowHandleDragTarget(\r\n this.mode.handle,\r\n this.mode.elementId,\r\n this.currentWorld,\r\n this.ctx,\r\n );\r\n if (target) {\r\n canvasCtx.save();\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.lineWidth = 2 / this.ctx.camera.zoom;\r\n canvasCtx.setLineDash([]);\r\n canvasCtx.strokeRect(target.x, target.y, target.w, target.h);\r\n canvasCtx.restore();\r\n }\r\n }\r\n\r\n if (this.hoveredId && this.ctx && this.mode.type === 'idle') {\r\n if (!this._selectedIds.includes(this.hoveredId)) {\r\n const el = this.ctx.store.getById(this.hoveredId);\r\n if (el) {\r\n const b = getElementBounds(el);\r\n if (b) {\r\n canvasCtx.save();\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.globalAlpha = 0.35;\r\n canvasCtx.lineWidth = 1.5 / this.ctx.camera.zoom;\r\n canvasCtx.setLineDash([]);\r\n canvasCtx.strokeRect(b.x, b.y, b.w, b.h);\r\n canvasCtx.restore();\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n private updateArrowsBoundTo(ids: Iterable<string>, ctx: ToolContext): void {\r\n const movedNonArrowIds = new Set<string>();\r\n for (const id of ids) {\r\n const el = ctx.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 updatedArrows = new Set<string>();\r\n for (const id of movedNonArrowIds) {\r\n const boundArrows = findBoundArrows(id, ctx.store);\r\n for (const ba of boundArrows) {\r\n if (updatedArrows.has(ba.id)) continue;\r\n updatedArrows.add(ba.id);\r\n const updates = updateBoundArrow(ba, ctx.store);\r\n if (updates) ctx.store.update(ba.id, updates);\r\n }\r\n }\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\r\n if (el.type === 'arrow') {\r\n if (el.fromBinding || el.toBinding) continue;\r\n ctx.store.update(id, {\r\n position: { x: el.position.x + dx, y: el.position.y + dy },\r\n from: { x: el.from.x + dx, y: el.from.y + dy },\r\n to: { x: el.to.x + dx, y: el.to.y + dy },\r\n });\r\n } else {\r\n ctx.store.update(id, {\r\n position: { x: el.position.x + dx, y: el.position.y + dy },\r\n });\r\n }\r\n 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 const templateResizeHit = this.hitTestTemplateResizeHandle(world, ctx);\r\n if (templateResizeHit) {\r\n ctx.setCursor?.('nwse-resize');\r\n return null;\r\n }\r\n\r\n const resizeHit = this.hitTestResizeHandle(world, ctx);\r\n if (resizeHit) {\r\n ctx.setCursor?.(HANDLE_CURSORS[resizeHit.handle]);\r\n return null;\r\n }\r\n\r\n const hit = this.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 { handle } = this.mode;\r\n const dx = world.x - this.lastWorld.x;\r\n const dy = world.y - this.lastWorld.y;\r\n this.lastWorld = world;\r\n\r\n let { x, y, w, h } = { x: el.position.x, y: el.position.y, w: el.size.w, h: el.size.h };\r\n\r\n switch (handle) {\r\n case 'se':\r\n w += dx;\r\n h += dy;\r\n break;\r\n case 'sw':\r\n x += dx;\r\n w -= dx;\r\n h += dy;\r\n break;\r\n case 'ne':\r\n y += dy;\r\n w += dx;\r\n h -= dy;\r\n break;\r\n case 'nw':\r\n x += dx;\r\n y += dy;\r\n w -= dx;\r\n h -= dy;\r\n break;\r\n }\r\n\r\n if (shiftKey && this.resizeAspectRatio > 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 / this.resizeAspectRatio;\r\n } else {\r\n w = h * this.resizeAspectRatio;\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 ctx.store.update(this.mode.elementId, {\r\n position: { x, y },\r\n size: { w, h },\r\n });\r\n\r\n this.updateArrowsBoundTo([this.mode.elementId], ctx);\r\n\r\n ctx.requestRender();\r\n }\r\n\r\n private hitTestResizeHandle(\r\n world: Point,\r\n ctx: ToolContext,\r\n ): { elementId: string; handle: HandlePosition } | null {\r\n if (this._selectedIds.length === 0) return null;\r\n\r\n const zoom = ctx.camera.zoom;\r\n const handleHalf = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / zoom;\r\n\r\n for (const id of this._selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || !('size' in el)) continue;\r\n\r\n const bounds = getElementBounds(el);\r\n if (!bounds) continue;\r\n\r\n const corners = this.getHandlePositions(bounds);\r\n for (const [handle, pos] of corners) {\r\n if (Math.abs(world.x - pos.x) <= handleHalf && Math.abs(world.y - pos.y) <= handleHalf) {\r\n return { elementId: id, handle };\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private getHandlePositions(bounds: 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\n private renderMarquee(canvasCtx: CanvasRenderingContext2D): void {\r\n if (this.mode.type !== 'marquee') return;\r\n\r\n const rect = this.getMarqueeRect();\r\n if (!rect) return;\r\n\r\n canvasCtx.save();\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.fillStyle = 'rgba(33, 150, 243, 0.08)';\r\n canvasCtx.lineWidth = 1;\r\n canvasCtx.setLineDash([4, 4]);\r\n canvasCtx.strokeRect(rect.x, rect.y, rect.w, rect.h);\r\n canvasCtx.fillRect(rect.x, rect.y, rect.w, rect.h);\r\n canvasCtx.restore();\r\n }\r\n\r\n private renderSelectionBoxes(canvasCtx: CanvasRenderingContext2D): void {\r\n if (this._selectedIds.length === 0 || !this.ctx) return;\r\n\r\n const zoom = this.ctx.camera.zoom;\r\n const handleWorldSize = HANDLE_SIZE / zoom;\r\n\r\n canvasCtx.save();\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.lineWidth = 1.5 / zoom;\r\n canvasCtx.setLineDash([4 / zoom, 4 / zoom]);\r\n\r\n for (const id of this._selectedIds) {\r\n const el = this.ctx.store.getById(id);\r\n if (!el) continue;\r\n\r\n if (el.type === 'arrow') {\r\n renderArrowHandles(canvasCtx, el, zoom);\r\n this.renderBindingHighlights(canvasCtx, el, zoom);\r\n continue;\r\n }\r\n\r\n const bounds = getElementBounds(el);\r\n if (!bounds) continue;\r\n\r\n const pad = SELECTION_PAD / zoom;\r\n canvasCtx.strokeRect(bounds.x - pad, bounds.y - pad, bounds.w + pad * 2, bounds.h + pad * 2);\r\n\r\n if ('size' in el) {\r\n canvasCtx.setLineDash([]);\r\n canvasCtx.fillStyle = '#ffffff';\r\n const corners = this.getHandlePositions(bounds);\r\n for (const [, pos] of corners) {\r\n canvasCtx.fillRect(\r\n pos.x - handleWorldSize / 2,\r\n pos.y - handleWorldSize / 2,\r\n handleWorldSize,\r\n handleWorldSize,\r\n );\r\n canvasCtx.strokeRect(\r\n pos.x - handleWorldSize / 2,\r\n pos.y - handleWorldSize / 2,\r\n handleWorldSize,\r\n handleWorldSize,\r\n );\r\n }\r\n canvasCtx.setLineDash([4 / zoom, 4 / zoom]);\r\n } else if (el.type === 'template') {\r\n canvasCtx.setLineDash([]);\r\n canvasCtx.fillStyle = '#ffffff';\r\n const hx = bounds.x + bounds.w;\r\n const hy = bounds.y + bounds.h;\r\n canvasCtx.fillRect(\r\n hx - handleWorldSize / 2,\r\n hy - handleWorldSize / 2,\r\n handleWorldSize,\r\n handleWorldSize,\r\n );\r\n canvasCtx.strokeRect(\r\n hx - handleWorldSize / 2,\r\n hy - handleWorldSize / 2,\r\n handleWorldSize,\r\n handleWorldSize,\r\n );\r\n canvasCtx.setLineDash([4 / zoom, 4 / zoom]);\r\n }\r\n }\r\n\r\n canvasCtx.restore();\r\n }\r\n\r\n private renderBindingHighlights(\r\n canvasCtx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n zoom: number,\r\n ): void {\r\n if (!this.ctx) return;\r\n if (!arrow.fromBinding && !arrow.toBinding) return;\r\n\r\n const pad = SELECTION_PAD / zoom;\r\n\r\n canvasCtx.save();\r\n canvasCtx.strokeStyle = '#2196F3';\r\n canvasCtx.lineWidth = 2 / zoom;\r\n canvasCtx.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 = this.ctx.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 canvasCtx.strokeRect(bounds.x - pad, bounds.y - pad, bounds.w + pad * 2, bounds.h + pad * 2);\r\n }\r\n\r\n canvasCtx.restore();\r\n }\r\n\r\n private hitTestTemplateResizeHandle(world: Point, ctx: ToolContext): string | null {\r\n if (this._selectedIds.length === 0) return null;\r\n\r\n const zoom = ctx.camera.zoom;\r\n const handleHalf = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / zoom;\r\n\r\n for (const id of this._selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || el.type !== 'template') continue;\r\n\r\n const bounds = getElementBounds(el);\r\n if (!bounds) continue;\r\n\r\n const hx = bounds.x + bounds.w;\r\n const hy = bounds.y + bounds.h;\r\n if (Math.abs(world.x - hx) <= handleHalf && Math.abs(world.y - hy) <= handleHalf) {\r\n return id;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\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 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 (ctx.snapToGrid && ctx.gridSize && ctx.gridSize > 0) {\r\n const snapUnit = ctx.gridType === 'hex' ? Math.sqrt(3) * ctx.gridSize : ctx.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 && ctx.gridSize && ctx.gridSize > 0) {\r\n const snapUnit = ctx.gridType === 'hex' ? Math.sqrt(3) * ctx.gridSize : ctx.gridSize;\r\n updates.radiusFeet = (newRadius / snapUnit) * el.feetPerCell;\r\n }\r\n\r\n ctx.store.update(this.mode.elementId, updates);\r\n ctx.requestRender();\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 private 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 && this.rectsOverlap(marquee, bounds)) {\r\n ids.push(el.id);\r\n }\r\n }\r\n return ids;\r\n }\r\n\r\n private rectsOverlap(a: 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\n private 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 (this.isInsideBounds(world, el)) return el;\r\n }\r\n return null;\r\n }\r\n\r\n private isInsideBounds(point: Point, el: CanvasElement): boolean {\r\n if (el.type === 'grid') return false;\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\n","import type { Point } from '../core/types';\r\nimport type { Binding, CanvasElement } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createArrow } from '../elements/element-factory';\r\nimport { findBindTarget, getElementCenter } from '../elements/arrow-binding';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nconst BIND_THRESHOLD = 20;\r\n\r\nexport interface ArrowToolOptions {\r\n color?: string;\r\n width?: number;\r\n}\r\n\r\nexport class ArrowTool implements Tool {\r\n readonly name = 'arrow';\r\n private drawing = false;\r\n private start: Point = { x: 0, y: 0 };\r\n private end: Point = { x: 0, y: 0 };\r\n private color: string;\r\n private width: number;\r\n private fromBinding: Binding | undefined;\r\n private fromTarget: CanvasElement | null = null;\r\n private toTarget: CanvasElement | null = null;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: ArrowToolOptions = {}) {\r\n this.color = options.color ?? '#000000';\r\n this.width = options.width ?? 2;\r\n }\r\n\r\n getOptions(): ArrowToolOptions {\r\n return { color: this.color, width: this.width };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n setOptions(options: ArrowToolOptions): void {\r\n if (options.color !== undefined) this.color = options.color;\r\n if (options.width !== undefined) this.width = options.width;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n\r\n private layerFilter(ctx: ToolContext): ((el: CanvasElement) => boolean) | undefined {\r\n const activeLayerId = ctx.activeLayerId;\r\n if (!activeLayerId && !ctx.isLayerVisible && !ctx.isLayerLocked) return undefined;\r\n return (el: CanvasElement) => {\r\n if (activeLayerId && el.layerId !== activeLayerId) return false;\r\n if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) return false;\r\n if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) return false;\r\n return true;\r\n };\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.drawing = true;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n const filter = this.layerFilter(ctx);\r\n\r\n const target = findBindTarget(world, ctx.store, threshold, undefined, filter);\r\n if (target) {\r\n this.start = getElementCenter(target);\r\n this.fromBinding = { elementId: target.id };\r\n this.fromTarget = target;\r\n } else {\r\n this.start = smartSnap(world, ctx);\r\n this.fromBinding = undefined;\r\n this.fromTarget = null;\r\n }\r\n this.end = { ...this.start };\r\n this.toTarget = null;\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n const excludeId = this.fromBinding?.elementId;\r\n const filter = this.layerFilter(ctx);\r\n\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, filter);\r\n if (target) {\r\n this.end = getElementCenter(target);\r\n this.toTarget = target;\r\n } else {\r\n this.end = smartSnap(world, ctx);\r\n this.toTarget = null;\r\n }\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.drawing = false;\r\n\r\n if (this.start.x === this.end.x && this.start.y === this.end.y) return;\r\n\r\n const arrow = createArrow({\r\n from: this.start,\r\n to: this.end,\r\n position: this.start,\r\n color: this.color,\r\n width: this.width,\r\n fromBinding: this.fromBinding,\r\n toBinding: this.toTarget ? { elementId: this.toTarget.id } : undefined,\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(arrow);\r\n this.fromTarget = null;\r\n this.toTarget = null;\r\n ctx.requestRender();\r\n ctx.switchTool?.('select');\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (!this.drawing) return;\r\n if (this.start.x === this.end.x && this.start.y === this.end.y) return;\r\n\r\n ctx.save();\r\n\r\n if (this.fromTarget) {\r\n const bounds = getElementBounds(this.fromTarget);\r\n if (bounds) {\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.lineWidth = 2;\r\n ctx.setLineDash([]);\r\n ctx.strokeRect(bounds.x, bounds.y, bounds.w, bounds.h);\r\n }\r\n }\r\n\r\n if (this.toTarget) {\r\n const bounds = getElementBounds(this.toTarget);\r\n if (bounds) {\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.lineWidth = 2;\r\n ctx.setLineDash([]);\r\n ctx.strokeRect(bounds.x, bounds.y, bounds.w, bounds.h);\r\n }\r\n }\r\n\r\n ctx.strokeStyle = this.color;\r\n ctx.lineWidth = this.width;\r\n ctx.lineCap = 'round';\r\n ctx.globalAlpha = 0.6;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(this.start.x, this.start.y);\r\n ctx.lineTo(this.end.x, this.end.y);\r\n ctx.stroke();\r\n\r\n const angle = Math.atan2(this.end.y - this.start.y, this.end.x - this.start.x);\r\n const headLen = 12;\r\n const headAngle = Math.PI / 6;\r\n\r\n ctx.fillStyle = this.color;\r\n ctx.beginPath();\r\n ctx.moveTo(this.end.x, this.end.y);\r\n ctx.lineTo(\r\n this.end.x - headLen * Math.cos(angle - headAngle),\r\n this.end.y - headLen * Math.sin(angle - headAngle),\r\n );\r\n ctx.lineTo(\r\n this.end.x - headLen * Math.cos(angle + headAngle),\r\n this.end.y - headLen * Math.sin(angle + headAngle),\r\n );\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n}\r\n","import type { Size } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createNote, DEFAULT_NOTE_FONT_SIZE } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nexport interface NoteToolOptions {\r\n backgroundColor?: string;\r\n textColor?: string;\r\n size?: Size;\r\n fontSize?: number;\r\n}\r\n\r\nexport class NoteTool implements Tool {\r\n readonly name = 'note';\r\n private backgroundColor: string;\r\n private textColor: string;\r\n private size: Size;\r\n private fontSize: number;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: NoteToolOptions = {}) {\r\n this.backgroundColor = options.backgroundColor ?? '#ffeb3b';\r\n this.textColor = options.textColor ?? '#000000';\r\n this.size = options.size ?? { w: 200, h: 100 };\r\n this.fontSize = options.fontSize ?? DEFAULT_NOTE_FONT_SIZE;\r\n }\r\n\r\n getOptions(): NoteToolOptions {\r\n return {\r\n backgroundColor: this.backgroundColor,\r\n textColor: this.textColor,\r\n size: { ...this.size },\r\n fontSize: this.fontSize,\r\n };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n setOptions(options: NoteToolOptions): void {\r\n if (options.backgroundColor !== undefined) this.backgroundColor = options.backgroundColor;\r\n if (options.textColor !== undefined) this.textColor = options.textColor;\r\n if (options.size !== undefined) this.size = options.size;\r\n if (options.fontSize !== undefined) this.fontSize = options.fontSize;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n\r\n onPointerDown(_state: PointerState, _ctx: ToolContext): void {\r\n // Note is placed on pointer up\r\n }\r\n\r\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\r\n // No drag behavior for note placement\r\n }\r\n\r\n onPointerUp(state: PointerState, ctx: ToolContext): void {\r\n let world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n world = smartSnap(world, ctx);\r\n const note = createNote({\r\n position: world,\r\n size: { ...this.size },\r\n backgroundColor: this.backgroundColor,\r\n textColor: this.textColor,\r\n fontSize: this.fontSize,\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(note);\r\n ctx.requestRender();\r\n\r\n ctx.switchTool?.('select');\r\n ctx.editElement?.(note.id);\r\n }\r\n}\r\n","import type { Tool, ToolContext, PointerState } from './types';\r\nimport { createText } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nexport interface TextToolOptions {\r\n fontSize?: number;\r\n color?: string;\r\n textAlign?: 'left' | 'center' | 'right';\r\n}\r\n\r\nexport class TextTool implements Tool {\r\n readonly name = 'text';\r\n private fontSize: number;\r\n private color: string;\r\n private textAlign: 'left' | 'center' | 'right';\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: TextToolOptions = {}) {\r\n this.fontSize = options.fontSize ?? 16;\r\n this.color = options.color ?? '#1a1a1a';\r\n this.textAlign = options.textAlign ?? 'left';\r\n }\r\n\r\n getOptions(): TextToolOptions {\r\n return { fontSize: this.fontSize, color: this.color, textAlign: this.textAlign };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n setOptions(options: TextToolOptions): void {\r\n if (options.fontSize !== undefined) this.fontSize = options.fontSize;\r\n if (options.color !== undefined) this.color = options.color;\r\n if (options.textAlign !== undefined) this.textAlign = options.textAlign;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n\r\n onActivate(ctx: ToolContext): void {\r\n ctx.setCursor?.('text');\r\n }\r\n\r\n onDeactivate(ctx: ToolContext): void {\r\n ctx.setCursor?.('default');\r\n }\r\n\r\n onPointerDown(_state: PointerState, _ctx: ToolContext): void {\r\n // Text is placed on pointer up\r\n }\r\n\r\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\r\n // No drag behavior for text placement\r\n }\r\n\r\n onPointerUp(state: PointerState, ctx: ToolContext): void {\r\n let world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n world = smartSnap(world, ctx);\r\n const textEl = createText({\r\n position: world,\r\n fontSize: this.fontSize,\r\n color: this.color,\r\n textAlign: this.textAlign,\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(textEl);\r\n ctx.requestRender();\r\n\r\n ctx.switchTool?.('select');\r\n ctx.editElement?.(textEl.id);\r\n }\r\n}\r\n","import type { Size } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createImage } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nexport interface ImageToolOptions {\r\n size?: Size;\r\n}\r\n\r\nexport class ImageTool implements Tool {\r\n readonly name = 'image';\r\n private size: Size;\r\n private src: string | null = null;\r\n\r\n constructor(options: ImageToolOptions = {}) {\r\n this.size = options.size ?? { w: 300, h: 200 };\r\n }\r\n\r\n setSrc(src: string): void {\r\n this.src = src;\r\n }\r\n\r\n onPointerDown(_state: PointerState, _ctx: ToolContext): void {\r\n // No action on pointer down — image is placed on pointer up\r\n }\r\n\r\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\r\n // No action on pointer move\r\n }\r\n\r\n onPointerUp(state: PointerState, ctx: ToolContext): void {\r\n if (!this.src) return;\r\n\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const snapped = smartSnap(world, ctx);\r\n const image = createImage({\r\n position: {\r\n x: snapped.x - this.size.w / 2,\r\n y: snapped.y - this.size.h / 2,\r\n },\r\n size: { ...this.size },\r\n src: this.src,\r\n });\r\n ctx.store.add(image);\r\n ctx.requestRender();\r\n\r\n this.src = null;\r\n ctx.switchTool?.('select');\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { ShapeKind } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createShape } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\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 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 if (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 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 }\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) {\r\n const side = Math.max(w, h);\r\n w = side;\r\n h = side;\r\n x = this.end.x >= this.start.x ? this.start.x : this.start.x - side;\r\n y = this.end.y >= this.start.y ? this.start.y : this.start.y - side;\r\n }\r\n\r\n return { position: { x, y }, size: { w, h } };\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n\r\n private snap(point: Point, ctx: ToolContext): Point {\r\n return smartSnap(point, ctx);\r\n }\r\n\r\n private onKeyDown = (e: KeyboardEvent): void => {\r\n if (e.key === 'Shift') this.shiftHeld = true;\r\n };\r\n\r\n private onKeyUp = (e: KeyboardEvent): void => {\r\n if (e.key === 'Shift') this.shiftHeld = false;\r\n };\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { HexOrientation } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { snapPoint, snapToHexCenter } from '../core/snap';\r\nimport { getHexDistance } from '../elements/hex-fill';\r\n\r\nexport interface MeasureToolOptions {\r\n feetPerCell?: number;\r\n}\r\n\r\nexport interface Measurement {\r\n start: Point;\r\n end: Point;\r\n worldDistance: number;\r\n cells: number;\r\n feet: number;\r\n}\r\n\r\nexport class MeasureTool implements Tool {\r\n readonly name = 'measure';\r\n private start: Point | null = null;\r\n private end: Point | null = null;\r\n private gridSize = 1;\r\n private gridType: 'square' | 'hex' | undefined;\r\n private hexOrientation: HexOrientation | undefined;\r\n private feetPerCell: number;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: MeasureToolOptions = {}) {\r\n this.feetPerCell = options.feetPerCell ?? 5;\r\n }\r\n\r\n getOptions(): MeasureToolOptions {\r\n return { feetPerCell: this.feetPerCell };\r\n }\r\n\r\n setOptions(options: MeasureToolOptions): void {\r\n if (options.feetPerCell !== undefined) this.feetPerCell = options.feetPerCell;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.gridSize = ctx.gridSize ?? 1;\r\n this.gridType = ctx.gridType;\r\n this.hexOrientation = ctx.hexOrientation;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.start = this.snapToGrid(world, ctx);\r\n this.end = { ...this.start };\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.start) return;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.end = this.snapToGrid(world, ctx);\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\r\n if (!this.start) return;\r\n this.start = null;\r\n this.end = null;\r\n ctx.requestRender();\r\n }\r\n\r\n onDeactivate(_ctx: ToolContext): void {\r\n this.start = null;\r\n this.end = null;\r\n }\r\n\r\n getMeasurement(): Measurement | null {\r\n if (!this.start || !this.end) return null;\r\n const dx = this.end.x - this.start.x;\r\n const dy = this.end.y - this.start.y;\r\n const worldDistance = Math.sqrt(dx * dx + dy * dy);\r\n\r\n let cells: number;\r\n if (this.gridType === 'hex' && this.hexOrientation) {\r\n cells = getHexDistance(this.start, this.end, this.gridSize, this.hexOrientation);\r\n } else {\r\n const snapUnit = this.gridSize;\r\n cells = worldDistance / snapUnit;\r\n }\r\n\r\n const feet = cells * this.feetPerCell;\r\n return {\r\n start: { ...this.start },\r\n end: { ...this.end },\r\n worldDistance,\r\n cells,\r\n feet,\r\n };\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n const m = this.getMeasurement();\r\n if (!m) return;\r\n\r\n ctx.save();\r\n\r\n ctx.strokeStyle = '#FF5722';\r\n ctx.setLineDash([8, 4]);\r\n ctx.lineWidth = 2;\r\n ctx.beginPath();\r\n ctx.moveTo(m.start.x, m.start.y);\r\n ctx.lineTo(m.end.x, m.end.y);\r\n ctx.stroke();\r\n\r\n ctx.setLineDash([]);\r\n ctx.fillStyle = '#FF5722';\r\n const dotRadius = 4;\r\n ctx.beginPath();\r\n ctx.arc(m.start.x, m.start.y, dotRadius, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.beginPath();\r\n ctx.arc(m.end.x, m.end.y, dotRadius, 0, Math.PI * 2);\r\n ctx.fill();\r\n\r\n const label = `${Math.round(m.feet)} ft`;\r\n const midX = (m.start.x + m.end.x) / 2;\r\n const midY = (m.start.y + m.end.y) / 2;\r\n ctx.font = '14px sans-serif';\r\n const metrics = ctx.measureText(label);\r\n const padX = 6;\r\n const padY = 4;\r\n const textH = 14;\r\n\r\n ctx.fillStyle = 'rgba(0, 0, 0, 0.75)';\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n midX - metrics.width / 2 - padX,\r\n midY - textH / 2 - padY,\r\n metrics.width + padX * 2,\r\n textH + padY * 2,\r\n 4,\r\n );\r\n ctx.fill();\r\n\r\n ctx.fillStyle = '#FFFFFF';\r\n ctx.textAlign = 'center';\r\n ctx.textBaseline = 'middle';\r\n ctx.fillText(label, midX, midY);\r\n\r\n ctx.restore();\r\n }\r\n\r\n private snapToGrid(point: Point, ctx: ToolContext): Point {\r\n if (!ctx.gridSize) return point;\r\n if (ctx.gridType === 'hex' && ctx.hexOrientation) {\r\n return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);\r\n }\r\n if (ctx.gridType === 'square') {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n if (ctx.snapToGrid) {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n return point;\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { TemplateShape, HexOrientation } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createTemplate } from '../elements/element-factory';\r\nimport { snapPoint, snapToHexCenter } from '../core/snap';\r\nimport {\r\n getHexCellsInRadius,\r\n getHexCellsInCone,\r\n getHexCellsInLine,\r\n getHexCellsInSquare,\r\n drawHexPath,\r\n} from '../elements/hex-fill';\r\n\r\nexport interface TemplateToolOptions {\r\n templateShape?: TemplateShape;\r\n fillColor?: string;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n feetPerCell?: number;\r\n}\r\n\r\nexport class TemplateTool implements Tool {\r\n readonly name = 'template';\r\n private drawing = false;\r\n private origin: Point = { x: 0, y: 0 };\r\n private current: Point = { x: 0, y: 0 };\r\n private gridSize = 1;\r\n private gridType: 'square' | 'hex' | undefined;\r\n private hexOrientation: HexOrientation | undefined;\r\n private snapEnabled = false;\r\n private templateShape: TemplateShape;\r\n private fillColor: string;\r\n private strokeColor: string;\r\n private strokeWidth: number;\r\n private opacity: number;\r\n private feetPerCell: number;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: TemplateToolOptions = {}) {\r\n this.templateShape = options.templateShape ?? 'circle';\r\n this.fillColor = options.fillColor ?? 'rgba(255, 87, 34, 0.2)';\r\n this.strokeColor = options.strokeColor ?? '#FF5722';\r\n this.strokeWidth = options.strokeWidth ?? 2;\r\n this.opacity = options.opacity ?? 0.6;\r\n this.feetPerCell = options.feetPerCell ?? 5;\r\n }\r\n\r\n getOptions(): TemplateToolOptions {\r\n return {\r\n templateShape: this.templateShape,\r\n fillColor: this.fillColor,\r\n strokeColor: this.strokeColor,\r\n strokeWidth: this.strokeWidth,\r\n opacity: this.opacity,\r\n feetPerCell: this.feetPerCell,\r\n };\r\n }\r\n\r\n setOptions(options: TemplateToolOptions): void {\r\n if (options.templateShape !== undefined) this.templateShape = options.templateShape;\r\n if (options.fillColor !== undefined) this.fillColor = options.fillColor;\r\n if (options.strokeColor !== undefined) this.strokeColor = options.strokeColor;\r\n if (options.strokeWidth !== undefined) this.strokeWidth = options.strokeWidth;\r\n if (options.opacity !== undefined) this.opacity = options.opacity;\r\n if (options.feetPerCell !== undefined) this.feetPerCell = options.feetPerCell;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.drawing = true;\r\n this.gridSize = ctx.gridSize ?? 1;\r\n this.gridType = ctx.gridType;\r\n this.hexOrientation = ctx.hexOrientation;\r\n this.snapEnabled = !!ctx.gridType || (ctx.snapToGrid ?? false);\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.origin = this.snapToGrid(world, ctx);\r\n this.current = { ...this.origin };\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.current = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.drawing = false;\r\n\r\n const radius = this.computeRadius();\r\n if (radius <= 0) return;\r\n\r\n const angle = this.computeAngle();\r\n const gridSize = ctx.gridSize;\r\n const snapUnit =\r\n gridSize && gridSize > 0 ? (ctx.gridType === 'hex' ? Math.sqrt(3) * gridSize : gridSize) : 0;\r\n const cells = snapUnit > 0 ? radius / snapUnit : 0;\r\n const radiusFeet = cells * this.feetPerCell;\r\n\r\n const element = createTemplate({\r\n position: { ...this.origin },\r\n templateShape: this.templateShape,\r\n radius,\r\n angle,\r\n fillColor: this.fillColor,\r\n strokeColor: this.strokeColor,\r\n strokeWidth: this.strokeWidth,\r\n opacity: this.opacity,\r\n feetPerCell: this.feetPerCell,\r\n radiusFeet: radiusFeet > 0 ? radiusFeet : undefined,\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(element);\r\n ctx.requestRender();\r\n ctx.switchTool?.('select');\r\n }\r\n\r\n onDeactivate(_ctx: ToolContext): void {\r\n this.drawing = false;\r\n this.origin = { x: 0, y: 0 };\r\n this.current = { x: 0, y: 0 };\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (!this.drawing) return;\r\n\r\n const radius = this.computeRadius();\r\n if (radius <= 0) return;\r\n\r\n if (this.gridType === 'hex' && this.hexOrientation) {\r\n this.renderHexOverlay(ctx, radius);\r\n return;\r\n }\r\n\r\n this.renderGeometricOverlay(ctx, radius);\r\n }\r\n\r\n private renderGeometricOverlay(ctx: CanvasRenderingContext2D, radius: number): void {\r\n const cx = this.origin.x;\r\n const cy = this.origin.y;\r\n const angle = this.computeAngle();\r\n\r\n ctx.save();\r\n ctx.globalAlpha = 0.4;\r\n ctx.fillStyle = this.fillColor;\r\n ctx.strokeStyle = this.strokeColor;\r\n ctx.lineWidth = this.strokeWidth;\r\n\r\n switch (this.templateShape) {\r\n case 'circle':\r\n ctx.beginPath();\r\n ctx.arc(cx, cy, radius, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n\r\n case 'square':\r\n ctx.fillRect(cx - radius / 2, cy - radius / 2, radius, radius);\r\n ctx.strokeRect(cx - radius / 2, cy - radius / 2, radius, radius);\r\n break;\r\n\r\n case 'cone': {\r\n const halfAngle = Math.atan(0.5);\r\n ctx.beginPath();\r\n ctx.moveTo(cx, cy);\r\n ctx.arc(cx, cy, radius, angle - halfAngle, angle + halfAngle);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n\r\n case 'line': {\r\n const halfW = radius / 12;\r\n const cos = Math.cos(angle);\r\n const sin = Math.sin(angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(cx + perpX, cy + perpY);\r\n ctx.lineTo(cx + radius * cos + perpX, cy + radius * sin + perpY);\r\n ctx.lineTo(cx + radius * cos - perpX, cy + radius * sin - perpY);\r\n ctx.lineTo(cx - perpX, cy - perpY);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private renderHexOverlay(ctx: CanvasRenderingContext2D, radius: number): void {\r\n const orientation = this.hexOrientation;\r\n if (!orientation) return;\r\n const cellSize = this.gridSize;\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const radiusCells = radius / snapUnit;\r\n const angle = this.computeAngle();\r\n const center = this.origin;\r\n\r\n let hexCells: Point[];\r\n switch (this.templateShape) {\r\n case 'circle':\r\n hexCells = getHexCellsInRadius(center, radiusCells, cellSize, orientation);\r\n break;\r\n case 'cone':\r\n hexCells = getHexCellsInCone(center, angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'line':\r\n hexCells = getHexCellsInLine(center, angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'square':\r\n hexCells = getHexCellsInSquare(center, radiusCells, cellSize, orientation);\r\n break;\r\n }\r\n\r\n ctx.save();\r\n ctx.globalAlpha = 0.4;\r\n\r\n ctx.beginPath();\r\n for (const cell of hexCells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.fillStyle = this.fillColor;\r\n ctx.fill();\r\n\r\n ctx.beginPath();\r\n for (const cell of hexCells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.strokeStyle = this.strokeColor;\r\n ctx.lineWidth = this.strokeWidth;\r\n ctx.stroke();\r\n\r\n if (\r\n this.templateShape === 'cone' ||\r\n this.templateShape === 'line' ||\r\n this.templateShape === 'circle' ||\r\n this.templateShape === 'square'\r\n ) {\r\n ctx.globalAlpha = 0.5;\r\n ctx.beginPath();\r\n drawHexPath(ctx, center.x, center.y, cellSize, orientation);\r\n ctx.fillStyle = this.strokeColor;\r\n ctx.fill();\r\n ctx.strokeStyle = this.strokeColor;\r\n ctx.lineWidth = this.strokeWidth;\r\n ctx.stroke();\r\n }\r\n\r\n if (this.templateShape === 'circle') {\r\n const feet = radiusCells * this.feetPerCell;\r\n if (feet > 0) {\r\n ctx.globalAlpha = 1;\r\n const label = `${Math.round(feet)} ft`;\r\n const fontSize = Math.max(10, Math.min(14, radius * 0.15));\r\n ctx.font = `bold ${fontSize}px system-ui, sans-serif`;\r\n ctx.textAlign = 'center';\r\n ctx.textBaseline = 'bottom';\r\n const textX = center.x;\r\n const textY = center.y - 4;\r\n\r\n const metrics = ctx.measureText(label);\r\n const padX = 4;\r\n const padY = 2;\r\n const textW = metrics.width + padX * 2;\r\n const textH = fontSize + padY * 2;\r\n\r\n ctx.fillStyle = 'rgba(255, 255, 255, 0.85)';\r\n ctx.beginPath();\r\n ctx.roundRect(textX - textW / 2, textY - textH, textW, textH, 3);\r\n ctx.fill();\r\n\r\n ctx.fillStyle = this.strokeColor;\r\n ctx.fillText(label, textX, textY - padY);\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private computeRadius(): number {\r\n const dx = this.current.x - this.origin.x;\r\n const dy = this.current.y - this.origin.y;\r\n const raw = Math.sqrt(dx * dx + dy * dy);\r\n if (this.snapEnabled && this.gridSize > 0) {\r\n const snapUnit = this.gridType === 'hex' ? Math.sqrt(3) * this.gridSize : this.gridSize;\r\n return Math.max(snapUnit, Math.round(raw / snapUnit) * snapUnit);\r\n }\r\n return raw;\r\n }\r\n\r\n private computeAngle(): number {\r\n const dx = this.current.x - this.origin.x;\r\n const dy = this.current.y - this.origin.y;\r\n return Math.atan2(dy, dx);\r\n }\r\n\r\n private snapToGrid(point: Point, ctx: ToolContext): Point {\r\n if (!ctx.gridSize) return point;\r\n if (ctx.gridType === 'hex' && ctx.hexOrientation) {\r\n return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);\r\n }\r\n if (ctx.gridType === 'square') {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n if (ctx.snapToGrid) {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n return point;\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n}\r\n","export const VERSION = '0.26.0';\r\n\r\nexport type { Point, StrokePoint, Size, Bounds } from './core/types';\r\nexport { snapPoint, smartSnap, snapToHexCenter } from './core/snap';\r\nexport type { CanvasState } from './core/state-serializer';\r\nexport { AutoSave } from './core/auto-save';\r\nexport type { AutoSaveOptions } from './core/auto-save';\r\n\r\nexport { Camera } from './canvas/camera';\r\nexport type { CameraOptions, CameraChangeInfo } from './canvas/camera';\r\nexport type { BackgroundOptions, BackgroundPattern } from './canvas/background';\r\nexport type { ShortcutOptions, ShortcutBindings, ShortcutsApi } from './canvas/shortcut-map';\r\nexport { Viewport } from './canvas/viewport';\r\nexport type { ViewportOptions, GridInfo } from './canvas/viewport';\r\nexport { exportImage } from './canvas/export-image';\r\nexport type { ExportImageOptions } from './canvas/export-image';\r\nexport type { RenderStatsSnapshot } from './canvas/render-stats';\r\n\r\nexport { ElementStore } from './elements/element-store';\r\nexport type { ElementUpdateEvent } from './elements/element-store';\r\nexport type { FontSizePreset } from './elements/note-toolbar';\r\nexport {\r\n toggleBold,\r\n toggleItalic,\r\n toggleUnderline,\r\n toggleStrikethrough,\r\n setFontSize,\r\n getActiveFormats,\r\n} from './elements/note-formatting';\r\nexport type { ActiveFormats } from './elements/note-formatting';\r\nexport {\r\n createStroke,\r\n createNote,\r\n createArrow,\r\n createImage,\r\n createHtmlElement,\r\n createText,\r\n createShape,\r\n createGrid,\r\n createTemplate,\r\n DEFAULT_NOTE_FONT_SIZE,\r\n} from './elements/element-factory';\r\nexport {\r\n getArrowControlPoint,\r\n getArrowMidpoint,\r\n getBendFromPoint,\r\n getArrowTangentAngle,\r\n isNearBezier,\r\n getArrowBounds,\r\n} from './elements/arrow-geometry';\r\nexport { getElementBounds, boundsIntersect } from './elements/element-bounds';\r\nexport { getElementsBoundingBox } from './elements/bounds';\r\nexport {\r\n getHexDistance,\r\n getHexCellsInRadius,\r\n getHexCellsInCone,\r\n getHexCellsInLine,\r\n getHexCellsInSquare,\r\n drawHexPath,\r\n} from './elements/hex-fill';\r\nexport type {\r\n Binding,\r\n CanvasElement,\r\n ElementType,\r\n StrokeElement,\r\n NoteElement,\r\n ArrowElement,\r\n ImageElement,\r\n HtmlElement,\r\n TextElement,\r\n ShapeElement,\r\n ShapeKind,\r\n GridElement,\r\n HexOrientation,\r\n TemplateElement,\r\n TemplateShape,\r\n} from './elements/types';\r\n\r\nexport type { Command } from './history/types';\r\nexport { HistoryStack } from './history/history-stack';\r\nexport type { HistoryStackOptions } from './history/history-stack';\r\n\r\nexport { ToolManager } from './tools/tool-manager';\r\nexport { HandTool } from './tools/hand-tool';\r\nexport { PencilTool } from './tools/pencil-tool';\r\nexport type { PencilToolOptions } from './tools/pencil-tool';\r\nexport { EraserTool } from './tools/eraser-tool';\r\nexport type { EraserToolOptions } from './tools/eraser-tool';\r\nexport { SelectTool } from './tools/select-tool';\r\nexport { ArrowTool } from './tools/arrow-tool';\r\nexport type { ArrowToolOptions } from './tools/arrow-tool';\r\nexport { NoteTool } from './tools/note-tool';\r\nexport type { NoteToolOptions } from './tools/note-tool';\r\nexport { TextTool } from './tools/text-tool';\r\nexport type { TextToolOptions } from './tools/text-tool';\r\nexport { ImageTool } from './tools/image-tool';\r\nexport type { ImageToolOptions } from './tools/image-tool';\r\nexport { ShapeTool } from './tools/shape-tool';\r\nexport type { ShapeToolOptions } from './tools/shape-tool';\r\nexport { MeasureTool } from './tools/measure-tool';\r\nexport type { MeasureToolOptions, Measurement } from './tools/measure-tool';\r\nexport { TemplateTool } from './tools/template-tool';\r\nexport type { TemplateToolOptions } from './tools/template-tool';\r\nexport type { Tool, ToolContext, PointerState, ToolName } from './tools/types';\r\n\r\nexport { LayerManager } from './layers/layer-manager';\r\nexport type { Layer } from './layers/types';\r\n"],"mappings":";AAIO,SAAS,UAAU,OAAc,UAAyB;AAC/D,SAAO;AAAA,IACL,GAAG,KAAK,MAAM,MAAM,IAAI,QAAQ,IAAI,YAAY;AAAA,IAChD,GAAG,KAAK,MAAM,MAAM,IAAI,QAAQ,IAAI,YAAY;AAAA,EAClD;AACF;AAEO,SAAS,gBACd,OACA,UACA,aACO;AACP,MAAI,gBAAgB,UAAU;AAC5B,UAAM,OAAO,KAAK,KAAK,CAAC,IAAI;AAC5B,UAAM,OAAO,MAAM;AACnB,UAAM,MAAM,KAAK,MAAM,MAAM,IAAI,IAAI;AACrC,UAAM,UAAU,MAAM,MAAM,IAAI,OAAO,IAAI;AAC3C,UAAM,MAAM,KAAK,OAAO,MAAM,IAAI,WAAW,IAAI;AACjD,WAAO,EAAE,GAAG,MAAM,OAAO,WAAW,GAAG,GAAG,MAAM,QAAQ,EAAE;AAAA,EAC5D,OAAO;AACL,UAAM,OAAO,KAAK,KAAK,CAAC,IAAI;AAC5B,UAAM,OAAO,MAAM;AACnB,UAAM,MAAM,KAAK,MAAM,MAAM,IAAI,IAAI;AACrC,UAAM,UAAU,MAAM,MAAM,IAAI,OAAO,IAAI;AAC3C,UAAM,MAAM,KAAK,OAAO,MAAM,IAAI,WAAW,IAAI;AACjD,WAAO,EAAE,GAAG,MAAM,QAAQ,GAAG,GAAG,MAAM,OAAO,WAAW,EAAE;AAAA,EAC5D;AACF;AAEO,SAAS,UAAU,OAAc,KAAyB;AAC/D,MAAI,CAAC,IAAI,cAAc,CAAC,IAAI,SAAU,QAAO;AAC7C,MAAI,IAAI,aAAa,SAAS,IAAI,gBAAgB;AAChD,WAAO,gBAAgB,OAAO,IAAI,UAAU,IAAI,cAAc;AAAA,EAChE;AACA,SAAO,UAAU,OAAO,IAAI,QAAQ;AACtC;;;AC3BA,IAAM,YAAY,oBAAI,IAAI,CAAC,KAAK,QAAQ,CAAC;AACzC,IAAM,cAAc,oBAAI,IAAI,CAAC,KAAK,IAAI,CAAC;AACvC,IAAM,iBAAiB,oBAAI,IAAI,CAAC,GAAG,CAAC;AACpC,IAAM,cAAc,oBAAI,IAAI,CAAC,KAAK,UAAU,KAAK,CAAC;AAClD,IAAM,aAAa,oBAAI,IAAI,CAAC,KAAK,CAAC;AAE3B,SAAS,gBAAgB,MAAc,cAAmC;AAC/E,MAAI,CAAC,KAAM,QAAO,CAAC;AAEnB,QAAM,MAAM,IAAI,UAAU,EAAE,gBAAgB,MAAM,WAAW;AAC7D,QAAM,OAAoB,CAAC;AAC3B,QAAM,YAAsB;AAAA,IAC1B,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAEA,YAAU,IAAI,MAAM,WAAW,IAAI;AACnC,SAAO;AACT;AAEA,SAAS,UAAU,MAAY,OAAiB,MAAyB;AACvE,aAAW,SAAS,MAAM,KAAK,KAAK,UAAU,GAAG;AAC/C,QAAI,MAAM,aAAa,KAAK,WAAW;AACrC,YAAM,OAAO,MAAM,eAAe;AAClC,UAAI,MAAM;AACR,aAAK,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;AAAA,MAC9B;AACA;AAAA,IACF;AAEA,QAAI,MAAM,aAAa,KAAK,aAAc;AAE1C,UAAM,KAAK;AACX,UAAM,MAAM,GAAG,QAAQ,YAAY;AAEnC,QAAI,QAAQ,MAAM;AAChB,WAAK,KAAK,EAAE,MAAM,MAAM,GAAG,MAAM,CAAC;AAClC;AAAA,IACF;AAEA,QAAI,WAAW,IAAI,GAAG,KAAK,KAAK,SAAS,GAAG;AAC1C,YAAM,UAAU,KAAK,KAAK,SAAS,CAAC;AACpC,UAAI,WAAW,CAAC,QAAQ,KAAK,SAAS,IAAI,GAAG;AAC3C,aAAK,KAAK,EAAE,MAAM,MAAM,GAAG,MAAM,CAAC;AAAA,MACpC;AAAA,IACF;AAEA,UAAM,aAAa,EAAE,GAAG,MAAM;AAC9B,QAAI,UAAU,IAAI,GAAG,EAAG,YAAW,OAAO;AAC1C,QAAI,YAAY,IAAI,GAAG,EAAG,YAAW,SAAS;AAC9C,QAAI,eAAe,IAAI,GAAG,EAAG,YAAW,YAAY;AACpD,QAAI,YAAY,IAAI,GAAG,EAAG,YAAW,gBAAgB;AAErD,QAAI,QAAQ,QAAQ;AAClB,YAAM,WAAY,GAAmB,MAAM;AAC3C,UAAI,UAAU;AACZ,mBAAW,WAAW,SAAS,UAAU,EAAE,KAAK,MAAM;AAAA,MACxD;AAAA,IACF;AAEA,cAAU,IAAI,YAAY,IAAI;AAAA,EAChC;AACF;AAEA,IAAM,eAAe,oBAAI,IAAI;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,SAAS,iBAAiB,MAAsB;AACrD,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,MAAM,IAAI,UAAU,EAAE,gBAAgB,MAAM,WAAW;AAC7D,eAAa,IAAI,IAAI;AACrB,SAAO,IAAI,KAAK;AAClB;AAEA,SAAS,aAAa,MAAkB;AACtC,QAAM,WAAW,MAAM,KAAK,KAAK,UAAU;AAE3C,aAAW,SAAS,UAAU;AAC5B,QAAI,MAAM,aAAa,KAAK,UAAW;AAEvC,QAAI,MAAM,aAAa,KAAK,cAAc;AACxC,YAAM,OAAO;AACb;AAAA,IACF;AAEA,UAAM,KAAK;AACX,UAAM,MAAM,GAAG,QAAQ,YAAY;AAEnC,QAAI,CAAC,aAAa,IAAI,GAAG,GAAG;AAC1B,YAAM,WAAW,SAAS,uBAAuB;AACjD,aAAO,GAAG,YAAY;AACpB,iBAAS,YAAY,GAAG,UAAU;AAAA,MACpC;AACA,WAAK,aAAa,UAAU,EAAE;AAC9B,mBAAa,IAAI;AACjB;AAAA,IACF;AAEA,uBAAmB,IAAI,GAAG;AAC1B,iBAAa,EAAE;AAAA,EACjB;AACF;AAEO,SAAS,mBAAmB,MAAuB;AACxD,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,MAAM,IAAI,UAAU,EAAE,gBAAgB,MAAM,WAAW;AAC7D,QAAM,OAAO,IAAI,KAAK,eAAe;AACrC,SAAO,KAAK,QAAQ,WAAW,GAAG,EAAE,KAAK,EAAE,WAAW;AACxD;AAEA,SAAS,mBAAmB,IAAa,KAAmB;AAC1D,QAAM,QAAQ,MAAM,KAAK,GAAG,UAAU;AACtC,aAAW,QAAQ,OAAO;AACxB,QAAI,QAAQ,UAAU,KAAK,SAAS,SAAS;AAC3C,YAAM,WAAY,GAAmB,MAAM;AAC3C,UAAI,UAAU;AACZ,WAAG,aAAa,SAAS,cAAc,QAAQ,GAAG;AAAA,MACpD,OAAO;AACL,WAAG,gBAAgB,OAAO;AAAA,MAC5B;AACA;AAAA,IACF;AACA,OAAG,gBAAgB,KAAK,IAAI;AAAA,EAC9B;AACF;;;ACvIA,IAAM,kBAAkB;AAEjB,SAAS,YACd,UACA,QACA,SAAkB,CAAC,GACnB,eACa;AACb,QAAM,QAAqB;AAAA,IACzB,SAAS;AAAA,IACT,QAAQ;AAAA,MACN,UAAU,EAAE,GAAG,OAAO,SAAS;AAAA,MAC/B,MAAM,OAAO;AAAA,IACf;AAAA,IACA,UAAU,SAAS,IAAI,CAAC,OAAO;AAC7B,YAAM,QAAQ,gBAAgB,EAAE;AAChC,UAAI,MAAM,SAAS,SAAS;AAC1B,eAAO,MAAM;AAAA,MACf;AACA,aAAO;AAAA,IACT,CAAC;AAAA,IACD,QAAQ,OAAO,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;AAAA,EACtC;AACA,MAAI,cAAe,OAAM,gBAAgB;AACzC,SAAO;AACT;AAEO,SAAS,WAAW,MAA2B;AACpD,QAAM,OAAgB,KAAK,MAAM,IAAI;AACrC,gBAAc,IAAI;AAClB,SAAO;AACT;AAEA,SAAS,cAAc,MAA4C;AACjE,MAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrC,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAEA,QAAM,MAAM;AAEZ,MAAI,OAAO,IAAI,SAAS,MAAM,UAAU;AACtC,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AAEA,MAAI,CAAC,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,MAAM,UAAU;AACvD,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AAEA,QAAM,MAAM,IAAI,QAAQ;AACxB,MAAI,CAAC,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,MAAM,UAAU;AAC3D,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AAEA,QAAM,MAAM,IAAI,UAAU;AAC1B,MAAI,OAAO,IAAI,GAAG,MAAM,YAAY,OAAO,IAAI,GAAG,MAAM,UAAU;AAChE,UAAM,IAAI,MAAM,0DAA0D;AAAA,EAC5E;AAEA,MAAI,OAAO,IAAI,MAAM,MAAM,UAAU;AACnC,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACtD;AAEA,MAAI,CAAC,MAAM,QAAQ,IAAI,UAAU,CAAC,GAAG;AACnC,UAAM,IAAI,MAAM,0CAA0C;AAAA,EAC5D;AAEA,aAAW,MAAM,IAAI,UAAU,GAAgB;AAC7C,oBAAgB,EAAE;AAClB,mBAAe,EAAwC;AAAA,EACzD;AAEA,gBAAc,IAAI,UAAU,CAA8B;AAE1D,QAAM,SAAS,IAAI,QAAQ;AAC3B,MAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,WAAW,GAAG;AACjD,QAAI,QAAQ,IAAI;AAAA,MACd;AAAA,QACE,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,cAAc,oBAAI,IAAI;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,gBAAgB,IAA0C;AACjE,MAAI,CAAC,MAAM,OAAO,OAAO,UAAU;AACjC,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACvD;AAEA,QAAM,MAAM;AAEZ,MAAI,OAAO,IAAI,IAAI,MAAM,UAAU;AACjC,UAAM,IAAI,MAAM,6BAA6B;AAAA,EAC/C;AAEA,MAAI,OAAO,IAAI,MAAM,MAAM,YAAY,CAAC,YAAY,IAAI,IAAI,MAAM,CAAC,GAAG;AACpE,UAAM,IAAI,MAAM,kCAAkC,OAAO,IAAI,MAAM,CAAC,CAAC,GAAG;AAAA,EAC1E;AAEA,MAAI,OAAO,IAAI,QAAQ,MAAM,UAAU;AACrC,UAAM,IAAI,MAAM,iCAAiC;AAAA,EACnD;AACF;AAEA,SAAS,cAAc,UAA2C;AAChE,QAAM,MAAM,IAAI,IAAI,SAAS,IAAI,CAAC,OAAO,GAAG,IAAI,CAAW,CAAC;AAE5D,aAAW,MAAM,UAAU;AACzB,QAAI,GAAG,MAAM,MAAM,QAAS;AAE5B,UAAM,cAAc,GAAG,aAAa;AACpC,QAAI,eAAe,CAAC,IAAI,IAAI,YAAY,WAAW,CAAW,GAAG;AAC/D,SAAG,aAAa,IAAI;AAAA,IACtB;AAEA,UAAM,YAAY,GAAG,WAAW;AAChC,QAAI,aAAa,CAAC,IAAI,IAAI,UAAU,WAAW,CAAW,GAAG;AAC3D,SAAG,WAAW,IAAI;AAAA,IACpB;AAAA,EACF;AACF;AAEA,SAAS,eAAe,KAAoC;AAC1D,MAAI,OAAO,IAAI,SAAS,MAAM,UAAU;AACtC,QAAI,SAAS,IAAI;AAAA,EACnB;AAEA,MAAI,IAAI,MAAM,MAAM,WAAW,OAAO,IAAI,MAAM,MAAM,UAAU;AAC9D,QAAI,MAAM,IAAI;AAAA,EAChB;AAEA,MAAI,IAAI,MAAM,MAAM,YAAY,MAAM,QAAQ,IAAI,QAAQ,CAAC,GAAG;AAC5D,eAAW,MAAM,IAAI,QAAQ,GAAgC;AAC3D,UAAI,OAAO,GAAG,UAAU,MAAM,UAAU;AACtC,WAAG,UAAU,IAAI;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,IAAI,MAAM,MAAM,WAAW,OAAO,IAAI,OAAO,MAAM,UAAU;AAC/D,QAAI,OAAO,IAAI;AAAA,EACjB;AAEA,MAAI,IAAI,MAAM,MAAM,UAAU,OAAO,IAAI,WAAW,MAAM,UAAU;AAClE,QAAI,WAAW,IAAI;AAAA,EACrB;AAEA,MAAI,IAAI,MAAM,MAAM,UAAU,OAAO,IAAI,MAAM,MAAM,UAAU;AAC7D,QAAI,MAAM,IAAI,iBAAiB,IAAI,MAAM,CAAC;AAAA,EAC5C;AACF;;;ACzKA,IAAM,cAAc;AACpB,IAAM,sBAAsB;AAErB,IAAM,WAAN,MAAe;AAAA,EAQpB,YACmB,OACA,QACjB,UAA2B,CAAC,GAC5B;AAHiB;AACA;AAGjB,SAAK,MAAM,QAAQ,OAAO;AAC1B,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,eAAe,QAAQ;AAC5B,SAAK,UAAU,QAAQ;AAAA,EACzB;AAAA,EAhBiB;AAAA,EACA;AAAA,EACA;AAAA,EACT,UAAgD;AAAA,EAChD,gBAAgC,CAAC;AAAA,EACxB;AAAA,EAajB,QAAc;AACZ,UAAM,WAAW,MAAM,KAAK,aAAa;AAEzC,SAAK,gBAAgB;AAAA,MACnB,KAAK,MAAM,GAAG,OAAO,QAAQ;AAAA,MAC7B,KAAK,MAAM,GAAG,UAAU,QAAQ;AAAA,MAChC,KAAK,MAAM,GAAG,UAAU,QAAQ;AAAA,MAChC,KAAK,OAAO,SAAS,QAAQ;AAAA,IAC/B;AACA,QAAI,KAAK,cAAc;AACrB,WAAK,cAAc,KAAK,KAAK,aAAa,GAAG,UAAU,QAAQ,CAAC;AAAA,IAClE;AAAA,EACF;AAAA,EAEA,OAAa;AACX,SAAK,cAAc;AACnB,SAAK,cAAc,QAAQ,CAAC,OAAO,GAAG,CAAC;AACvC,SAAK,gBAAgB,CAAC;AAAA,EACxB;AAAA,EAEA,OAA2B;AACzB,QAAI,OAAO,iBAAiB,YAAa,QAAO;AAEhD,UAAM,OAAO,aAAa,QAAQ,KAAK,GAAG;AAC1C,QAAI,CAAC,KAAM,QAAO;AAElB,QAAI;AACF,aAAO,WAAW,IAAI;AAAA,IACxB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,QAAI,OAAO,iBAAiB,YAAa;AACzC,iBAAa,WAAW,KAAK,GAAG;AAAA,EAClC;AAAA,EAEQ,eAAqB;AAC3B,SAAK,cAAc;AACnB,SAAK,UAAU,WAAW,MAAM,KAAK,KAAK,GAAG,KAAK,UAAU;AAAA,EAC9D;AAAA,EAEQ,gBAAsB;AAC5B,QAAI,KAAK,YAAY,MAAM;AACzB,mBAAa,KAAK,OAAO;AACzB,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAAA,EAEQ,OAAa;AACnB,QAAI,OAAO,iBAAiB,YAAa;AAEzC,UAAM,SAAS,KAAK,cAAc,SAAS,KAAK,CAAC;AACjD,UAAM,QAAQ,YAAY,KAAK,MAAM,SAAS,GAAG,KAAK,QAAQ,MAAM;AACpE,QAAI;AACF,mBAAa,QAAQ,KAAK,KAAK,KAAK,UAAU,KAAK,CAAC;AAAA,IACtD,SAAS,GAAG;AACV,cAAQ,KAAK,6EAA6E;AAC1F,WAAK,UAAU,aAAa,QAAQ,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC;AAAA,IAC9D;AAAA,EACF;AACF;;;ACrFA,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AAElB,IAAM,SAAN,MAAa;AAAA,EACV,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACK;AAAA,EACA;AAAA,EACT,kBAAkB,oBAAI,IAAsC;AAAA,EAEpE,YAAY,UAAyB,CAAC,GAAG;AACvC,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,UAAU,QAAQ,WAAW;AAAA,EACpC;AAAA,EAEA,IAAI,WAAkB;AACpB,WAAO,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,EAAE;AAAA,EAChC;AAAA,EAEA,IAAI,OAAe;AACjB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,IAAY,IAAkB;AAChC,SAAK,KAAK;AACV,SAAK,KAAK;AACV,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,OAAO,GAAW,GAAiB;AACjC,SAAK,IAAI;AACT,SAAK,IAAI;AACT,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,QAAQ,OAAqB;AAC3B,SAAK,IAAI,KAAK,IAAI,KAAK,SAAS,KAAK,IAAI,KAAK,SAAS,KAAK,CAAC;AAC7D,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,OAAO,OAAe,aAA0B;AAC9C,UAAM,SAAS,KAAK,cAAc,WAAW;AAC7C,SAAK,IAAI,KAAK,IAAI,KAAK,SAAS,KAAK,IAAI,KAAK,SAAS,KAAK,CAAC;AAC7D,UAAM,QAAQ,KAAK,cAAc,WAAW;AAC5C,SAAK,MAAM,MAAM,IAAI,OAAO,KAAK,KAAK;AACtC,SAAK,MAAM,MAAM,IAAI,OAAO,KAAK,KAAK;AACtC,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEA,cAAc,QAAsB;AAClC,WAAO;AAAA,MACL,IAAI,OAAO,IAAI,KAAK,KAAK,KAAK;AAAA,MAC9B,IAAI,OAAO,IAAI,KAAK,KAAK,KAAK;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,cAAc,OAAqB;AACjC,WAAO;AAAA,MACL,GAAG,MAAM,IAAI,KAAK,IAAI,KAAK;AAAA,MAC3B,GAAG,MAAM,IAAI,KAAK,IAAI,KAAK;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,eAAe,aAAqB,cAA8B;AAChE,UAAM,UAAU,KAAK,cAAc,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AACjD,UAAM,cAAc,KAAK,cAAc,EAAE,GAAG,aAAa,GAAG,aAAa,CAAC;AAC1E,WAAO;AAAA,MACL,GAAG,QAAQ;AAAA,MACX,GAAG,QAAQ;AAAA,MACX,GAAG,YAAY,IAAI,QAAQ;AAAA,MAC3B,GAAG,YAAY,IAAI,QAAQ;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,aAAa,aAAqB,aAAqB,cAAsB,UAAU,IAAU;AAC/F,QAAI,YAAY,MAAM,KAAK,YAAY,MAAM,EAAG;AAEhD,UAAM,SAAS,eAAe,YAAY,IAAI,IAAI;AAClD,UAAM,SAAS,gBAAgB,YAAY,IAAI,IAAI;AACnD,SAAK,IAAI,KAAK,IAAI,KAAK,SAAS,KAAK,IAAI,KAAK,SAAS,KAAK,IAAI,QAAQ,MAAM,CAAC,CAAC;AAChF,SAAK,KAAK,cAAc,YAAY,IAAI,KAAK,KAAK,IAAI,YAAY,IAAI,KAAK;AAC3E,SAAK,KAAK,eAAe,YAAY,IAAI,KAAK,KAAK,IAAI,YAAY,IAAI,KAAK;AAC5E,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEA,iBAAyB;AACvB,WAAO,eAAe,KAAK,CAAC,OAAO,KAAK,CAAC,gBAAgB,KAAK,CAAC;AAAA,EACjE;AAAA,EAEA,SAAS,UAAwD;AAC/D,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO,MAAM,KAAK,gBAAgB,OAAO,QAAQ;AAAA,EACnD;AAAA,EAEQ,YAAkB;AACxB,SAAK,gBAAgB,QAAQ,CAAC,OAAO,GAAG,EAAE,QAAQ,MAAM,QAAQ,MAAM,CAAC,CAAC;AAAA,EAC1E;AAAA,EAEQ,aAAmB;AACzB,SAAK,gBAAgB,QAAQ,CAAC,OAAO,GAAG,EAAE,QAAQ,OAAO,QAAQ,KAAK,CAAC,CAAC;AAAA,EAC1E;AAAA,EAEQ,mBAAyB;AAC/B,SAAK,gBAAgB,QAAQ,CAAC,OAAO,GAAG,EAAE,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC;AAAA,EACzE;AACF;;;AC3GO,IAAM,cAAN,MAAM,aAAY;AAAA,EACf,cAA6B;AAAA,EAC7B,aAAiE;AAAA,EAEzE,OAAgB,oBAAoB;AAAA,EAEpC,WAAW,GAAgC;AACzC,QAAI,EAAE,gBAAgB,OAAO;AAC3B,WAAK,cAAc,EAAE;AACrB,aAAO,EAAE,OAAO,GAAG,QAAQ,WAAW;AAAA,IACxC;AAEA,QAAI,EAAE,gBAAgB,WAAW,KAAK,gBAAgB,MAAM;AAC1D,aAAO,EAAE,OAAO,GAAG,QAAQ,WAAW;AAAA,IACxC;AAEA,QAAI,EAAE,gBAAgB,SAAS;AAC7B,WAAK,aAAa,EAAE,WAAW,EAAE,WAAW,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ;AACvE,aAAO,EAAE,OAAO,GAAG,QAAQ,QAAQ;AAAA,IACrC;AAEA,WAAO,EAAE,OAAO,GAAG,QAAQ,WAAW;AAAA,EACxC;AAAA,EAEA,WAAW,GAAgC;AACzC,QAAI,EAAE,gBAAgB,WAAW,KAAK,gBAAgB,MAAM;AAC1D,aAAO,EAAE,OAAO,GAAG,QAAQ,WAAW;AAAA,IACxC;AAEA,QAAI,KAAK,cAAc,EAAE,cAAc,KAAK,WAAW,WAAW;AAChE,YAAM,KAAK,EAAE,UAAU,KAAK,WAAW;AACvC,YAAM,KAAK,EAAE,UAAU,KAAK,WAAW;AACvC,UAAI,KAAK,KAAK,KAAK,KAAK,aAAY,oBAAoB,aAAY,mBAAmB;AACrF,aAAK,aAAa;AAClB,eAAO,EAAE,OAAO,GAAG,QAAQ,WAAW;AAAA,MACxC;AACA,aAAO,EAAE,OAAO,GAAG,QAAQ,WAAW;AAAA,IACxC;AAEA,WAAO,EAAE,OAAO,GAAG,QAAQ,WAAW;AAAA,EACxC;AAAA,EAEA,SAAS,GAAkC;AACzC,QAAI,EAAE,cAAc,KAAK,aAAa;AACpC,WAAK,cAAc;AACnB,aAAO,EAAE,OAAO,GAAG,QAAQ,WAAW;AAAA,IACxC;AAEA,QAAI,EAAE,gBAAgB,WAAW,KAAK,gBAAgB,MAAM;AAC1D,aAAO,EAAE,OAAO,GAAG,QAAQ,WAAW;AAAA,IACxC;AAEA,QAAI,KAAK,cAAc,EAAE,cAAc,KAAK,WAAW,WAAW;AAChE,YAAM,MAAM,EAAE,GAAG,KAAK,WAAW,GAAG,GAAG,KAAK,WAAW,EAAE;AACzD,WAAK,aAAa;AAClB,aAAO,EAAE,OAAO,GAAG,QAAQ,YAAY,YAAY,IAAI;AAAA,IACzD;AAEA,WAAO,EAAE,OAAO,GAAG,QAAQ,WAAW;AAAA,EACxC;AAAA,EAEA,QAAc;AACZ,SAAK,cAAc;AACnB,SAAK,aAAa;AAAA,EACpB;AACF;;;AC5EA,IAAI,UAAU;AAEP,SAAS,SAAS,QAAwB;AAC/C,SAAO,GAAG,MAAM,IAAI,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,KAAK,WAAW,SAAS,EAAE,CAAC;AACzE;;;ACFO,SAAS,gBAAgB,GAAU,GAAU,GAAkB;AACpE,QAAM,MAAM,EAAE,IAAI,EAAE;AACpB,QAAM,MAAM,EAAE,IAAI,EAAE;AACpB,QAAM,MAAM,EAAE,IAAI,EAAE;AACpB,QAAM,MAAM,EAAE,IAAI,EAAE;AACpB,QAAM,QAAQ,MAAM,MAAM,MAAM;AAChC,MAAI,UAAU,GAAG;AACf,WAAO,MAAM,MAAM,MAAM;AAAA,EAC3B;AACA,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,MAAM,MAAM,OAAO,KAAK,CAAC;AAClE,QAAM,KAAK,EAAE,KAAK,EAAE,IAAI,IAAI;AAC5B,QAAM,KAAK,EAAE,KAAK,EAAE,IAAI,IAAI;AAC5B,SAAO,KAAK,KAAK,KAAK;AACxB;;;ACZO,SAAS,qBAAqB,MAAa,IAAW,MAAqB;AAChF,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK;AAC/B,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK;AAE/B,MAAI,SAAS,EAAG,QAAO,EAAE,GAAG,MAAM,GAAG,KAAK;AAE1C,QAAM,KAAK,GAAG,IAAI,KAAK;AACvB,QAAM,KAAK,GAAG,IAAI,KAAK;AACvB,QAAM,MAAM,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAEvC,MAAI,QAAQ,EAAG,QAAO,EAAE,GAAG,MAAM,GAAG,KAAK;AAEzC,QAAM,QAAQ,CAAC,KAAK;AACpB,QAAM,QAAQ,KAAK;AAEnB,SAAO;AAAA,IACL,GAAG,OAAO,QAAQ;AAAA,IAClB,GAAG,OAAO,QAAQ;AAAA,EACpB;AACF;AAEO,SAAS,iBAAiB,MAAa,IAAW,MAAqB;AAC5E,QAAM,KAAK,qBAAqB,MAAM,IAAI,IAAI;AAC9C,SAAO;AAAA,IACL,GAAG,OAAO,KAAK,IAAI,MAAM,GAAG,IAAI,OAAO,GAAG;AAAA,IAC1C,GAAG,OAAO,KAAK,IAAI,MAAM,GAAG,IAAI,OAAO,GAAG;AAAA,EAC5C;AACF;AAEO,SAAS,iBAAiB,MAAa,IAAW,WAA0B;AACjF,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK;AAC/B,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK;AAE/B,QAAM,KAAK,GAAG,IAAI,KAAK;AACvB,QAAM,KAAK,GAAG,IAAI,KAAK;AACvB,QAAM,MAAM,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAEvC,MAAI,QAAQ,EAAG,QAAO;AAEtB,QAAM,QAAQ,CAAC,KAAK;AACpB,QAAM,QAAQ,KAAK;AAEnB,UAAQ,UAAU,IAAI,QAAQ,SAAS,UAAU,IAAI,QAAQ;AAC/D;AAEO,SAAS,qBAAqB,MAAa,IAAW,MAAc,GAAmB;AAC5F,QAAM,KAAK,qBAAqB,MAAM,IAAI,IAAI;AAE9C,QAAM,WAAW,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,KAAK,IAAI,KAAK,GAAG,IAAI,GAAG;AACpE,QAAM,WAAW,KAAK,IAAI,MAAM,GAAG,IAAI,KAAK,KAAK,IAAI,KAAK,GAAG,IAAI,GAAG;AAEpE,SAAO,KAAK,MAAM,UAAU,QAAQ;AACtC;AAEO,SAAS,aACd,OACA,MACA,IACA,MACA,WACS;AACT,MAAI,SAAS,EAAG,QAAO,WAAW,OAAO,MAAM,IAAI,SAAS;AAE5D,QAAM,KAAK,qBAAqB,MAAM,IAAI,IAAI;AAC9C,QAAM,WAAW;AAEjB,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,UAAM,KAAK,IAAI;AACf,UAAM,MAAM,IAAI,KAAK;AACrB,UAAM,IAAI,YAAY,MAAM,IAAI,IAAI,EAAE;AACtC,UAAM,IAAI,YAAY,MAAM,IAAI,IAAI,EAAE;AACtC,QAAI,WAAW,OAAO,GAAG,GAAG,SAAS,EAAG,QAAO;AAAA,EACjD;AAEA,SAAO;AACT;AAEO,SAAS,eAAe,MAAa,IAAW,MAAsB;AAC3E,MAAI,SAAS,GAAG;AACd,UAAMA,QAAO,KAAK,IAAI,KAAK,GAAG,GAAG,CAAC;AAClC,UAAMC,QAAO,KAAK,IAAI,KAAK,GAAG,GAAG,CAAC;AAClC,WAAO;AAAA,MACL,GAAGD;AAAA,MACH,GAAGC;AAAA,MACH,GAAG,KAAK,IAAI,GAAG,IAAI,KAAK,CAAC;AAAA,MACzB,GAAG,KAAK,IAAI,GAAG,IAAI,KAAK,CAAC;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,KAAK,qBAAqB,MAAM,IAAI,IAAI;AAC9C,QAAM,QAAQ;AACd,MAAI,OAAO,KAAK,IAAI,KAAK,GAAG,GAAG,CAAC;AAChC,MAAI,OAAO,KAAK,IAAI,KAAK,GAAG,GAAG,CAAC;AAChC,MAAI,OAAO,KAAK,IAAI,KAAK,GAAG,GAAG,CAAC;AAChC,MAAI,OAAO,KAAK,IAAI,KAAK,GAAG,GAAG,CAAC;AAEhC,WAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,UAAM,IAAI,IAAI;AACd,UAAM,IAAI,YAAY,MAAM,IAAI,IAAI,CAAC;AACrC,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AAAA,EAC3B;AAEA,SAAO,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,MAAM,GAAG,OAAO,KAAK;AAC5D;AAEA,SAAS,YAAY,MAAa,IAAW,IAAW,GAAkB;AACxE,QAAM,KAAK,IAAI;AACf,SAAO;AAAA,IACL,GAAG,KAAK,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG;AAAA,IACrD,GAAG,KAAK,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG;AAAA,EACvD;AACF;AAEA,SAAS,WAAW,OAAc,GAAU,GAAU,WAA4B;AAChF,SAAO,gBAAgB,OAAO,GAAG,CAAC,KAAK,YAAY;AACrD;;;AClHA,IAAM,oBAAoB,oBAAI,QAA+B;AAEtD,SAAS,iBAAiB,SAAuC;AACtE,MAAI,QAAQ,SAAS,OAAQ,QAAO;AAEpC,MAAI,UAAU,SAAS;AACrB,WAAO;AAAA,MACL,GAAG,QAAQ,SAAS;AAAA,MACpB,GAAG,QAAQ,SAAS;AAAA,MACpB,GAAG,QAAQ,KAAK;AAAA,MAChB,GAAG,QAAQ,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,UAAU;AAC7B,QAAI,QAAQ,OAAO,WAAW,EAAG,QAAO;AAExC,UAAM,SAAS,kBAAkB,IAAI,OAAO;AAC5C,QAAI,OAAQ,QAAO;AAEnB,QAAI,OAAO;AACX,QAAI,OAAO;AACX,QAAI,OAAO;AACX,QAAI,OAAO;AAEX,eAAW,KAAK,QAAQ,QAAQ;AAC9B,YAAM,KAAK,EAAE,IAAI,QAAQ,SAAS;AAClC,YAAM,KAAK,EAAE,IAAI,QAAQ,SAAS;AAClC,UAAI,KAAK,KAAM,QAAO;AACtB,UAAI,KAAK,KAAM,QAAO;AACtB,UAAI,KAAK,KAAM,QAAO;AACtB,UAAI,KAAK,KAAM,QAAO;AAAA,IACxB;AAEA,UAAM,SAAiB,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,MAAM,GAAG,OAAO,KAAK;AAC1E,sBAAkB,IAAI,SAAS,MAAM;AACrC,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,SAAS,SAAS;AAC5B,WAAO,yBAAyB,QAAQ,MAAM,QAAQ,IAAI,QAAQ,IAAI;AAAA,EACxE;AAEA,MAAI,QAAQ,SAAS,YAAY;AAC/B,WAAO,kBAAkB,OAAO;AAAA,EAClC;AAEA,SAAO;AACT;AAEA,SAAS,yBACP,MACA,IACA,MACQ;AACR,MAAI,SAAS,GAAG;AACd,UAAMC,QAAO,KAAK,IAAI,KAAK,GAAG,GAAG,CAAC;AAClC,UAAMC,QAAO,KAAK,IAAI,KAAK,GAAG,GAAG,CAAC;AAClC,WAAO;AAAA,MACL,GAAGD;AAAA,MACH,GAAGC;AAAA,MACH,GAAG,KAAK,IAAI,GAAG,IAAI,KAAK,CAAC;AAAA,MACzB,GAAG,KAAK,IAAI,GAAG,IAAI,KAAK,CAAC;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,KAAK,qBAAqB,MAAM,IAAI,IAAI;AAE9C,MAAI,OAAO,KAAK,IAAI,KAAK,GAAG,GAAG,CAAC;AAChC,MAAI,OAAO,KAAK,IAAI,KAAK,GAAG,GAAG,CAAC;AAChC,MAAI,OAAO,KAAK,IAAI,KAAK,GAAG,GAAG,CAAC;AAChC,MAAI,OAAO,KAAK,IAAI,KAAK,GAAG,GAAG,CAAC;AAGhC,QAAM,KAAK,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG;AAClC,MAAI,OAAO,GAAG;AACZ,UAAM,KAAK,KAAK,IAAI,GAAG,KAAK;AAC5B,QAAI,IAAI,KAAK,IAAI,GAAG;AAClB,YAAM,KAAK,IAAI;AACf,YAAM,IAAI,KAAK,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG;AAC5D,UAAI,IAAI,KAAM,QAAO;AACrB,UAAI,IAAI,KAAM,QAAO;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,KAAK,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG;AAClC,MAAI,OAAO,GAAG;AACZ,UAAM,KAAK,KAAK,IAAI,GAAG,KAAK;AAC5B,QAAI,IAAI,KAAK,IAAI,GAAG;AAClB,YAAM,KAAK,IAAI;AACf,YAAM,IAAI,KAAK,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG;AAC5D,UAAI,IAAI,KAAM,QAAO;AACrB,UAAI,IAAI,KAAM,QAAO;AAAA,IACvB;AAAA,EACF;AAEA,SAAO,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,MAAM,GAAG,OAAO,KAAK;AAC5D;AAEA,SAAS,kBAAkB,IAA6B;AACtD,QAAM,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG;AAC5B,QAAM,IAAI,GAAG;AAEb,UAAQ,GAAG,eAAe;AAAA,IACxB,KAAK;AACH,aAAO,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,GAAG,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE;AAAA,IAEpD,KAAK;AACH,aAAO,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,GAAG,GAAG,GAAG,GAAG,EAAE;AAAA,IAEpD,KAAK,QAAQ;AACX,YAAM,YAAY,KAAK,KAAK,GAAG;AAC/B,YAAM,OAAO;AACb,YAAM,OAAO;AACb,YAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,GAAG,QAAQ,SAAS;AACpD,YAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,GAAG,QAAQ,SAAS;AACpD,YAAM,SAAS,KAAK,IAAI,KAAK,IAAI,GAAG,QAAQ,SAAS;AACrD,YAAM,SAAS,KAAK,IAAI,KAAK,IAAI,GAAG,QAAQ,SAAS;AACrD,YAAM,OAAO,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK;AACvC,YAAM,OAAO,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK;AAEvC,YAAM,KAAK,CAAC,MAAM,OAAO,QAAQ,IAAI;AACrC,YAAM,KAAK,CAAC,MAAM,OAAO,QAAQ,IAAI;AAErC,UAAI,OAAO;AACX,UAAI,OAAO;AACX,UAAI,OAAO;AACX,UAAI,OAAO;AAEX,eAAS,IAAI,GAAG,IAAI,GAAG,QAAQ,KAAK;AAClC,cAAM,KAAK,GAAG,CAAC;AACf,cAAM,KAAK,GAAG,CAAC;AACf,YAAI,OAAO,UAAa,KAAK,KAAM,QAAO;AAC1C,YAAI,OAAO,UAAa,KAAK,KAAM,QAAO;AAC1C,YAAI,OAAO,UAAa,KAAK,KAAM,QAAO;AAC1C,YAAI,OAAO,UAAa,KAAK,KAAM,QAAO;AAAA,MAC5C;AAEA,aAAO,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,MAAM,GAAG,OAAO,KAAK;AAAA,IAC5D;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,QAAQ,IAAI;AAClB,YAAM,MAAM,KAAK,IAAI,GAAG,KAAK;AAC7B,YAAM,MAAM,KAAK,IAAI,GAAG,KAAK;AAC7B,YAAM,QAAQ,CAAC,MAAM;AACrB,YAAM,QAAQ,MAAM;AAEpB,YAAM,KAAK,KAAK;AAChB,YAAM,KAAK,KAAK;AAChB,YAAM,KAAK,KAAK,IAAI,MAAM;AAC1B,YAAM,KAAK,KAAK,IAAI,MAAM;AAC1B,YAAM,KAAK,KAAK,IAAI,MAAM;AAC1B,YAAM,KAAK,KAAK,IAAI,MAAM;AAC1B,YAAM,KAAK,KAAK;AAChB,YAAM,KAAK,KAAK;AAEhB,YAAM,OAAO,KAAK,IAAI,IAAI,IAAI,IAAI,EAAE;AACpC,YAAM,OAAO,KAAK,IAAI,IAAI,IAAI,IAAI,EAAE;AACpC,YAAM,OAAO,KAAK,IAAI,IAAI,IAAI,IAAI,EAAE;AACpC,YAAM,OAAO,KAAK,IAAI,IAAI,IAAI,IAAI,EAAE;AAEpC,aAAO,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,MAAM,GAAG,OAAO,KAAK;AAAA,IAC5D;AAAA,EACF;AACF;AAEO,SAAS,qBAAqB,MAAqB,MAA2B;AACnF,MAAI,KAAK,SAAS,YAAY,KAAK,SAAS,SAAU;AACtD,MAAI,KAAK,WAAW,KAAK,OAAQ;AACjC,MAAI,KAAK,SAAS,MAAM,KAAK,SAAS,KAAK,KAAK,SAAS,MAAM,KAAK,SAAS,EAAG;AAChF,QAAM,SAAS,kBAAkB,IAAI,IAAI;AACzC,MAAI,OAAQ,mBAAkB,IAAI,MAAM,MAAM;AAChD;AAEO,SAAS,gBAAgB,GAAW,GAAoB;AAC7D,SAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE;AACpF;;;ACpLO,SAAS,uBAAuB,UAA0C;AAC/E,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,QAAQ;AAEZ,aAAW,MAAM,UAAU;AACzB,UAAM,IAAI,iBAAiB,EAAE;AAC7B,QAAI,CAAC,EAAG;AACR,YAAQ;AACR,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,KAAM,QAAO,EAAE;AACzB,QAAI,EAAE,IAAI,EAAE,IAAI,KAAM,QAAO,EAAE,IAAI,EAAE;AACrC,QAAI,EAAE,IAAI,EAAE,IAAI,KAAM,QAAO,EAAE,IAAI,EAAE;AAAA,EACvC;AAEA,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,MAAM,GAAG,OAAO,KAAK;AAC5D;;;ACHO,IAAM,kBAAN,MAAsB;AAAA,EAM3B,YAA6B,MAA2B;AAA3B;AAAA,EAA4B;AAAA,EALjD,YAA6B,CAAC;AAAA,EAC9B,aAAa;AAAA,EACb,aAAmD;AAAA,EACnD,YAA2B;AAAA,EAInC,UAAgB;AACd,SAAK,kBAAkB;AAAA,EACzB;AAAA,EAEQ,aAA4D;AAClE,UAAM,KAAK,KAAK,KAAK,eAAe;AACpC,UAAM,MAAM,KAAK,KAAK,eAAe;AACrC,QAAI,CAAC,MAAM,CAAC,IAAK,QAAO;AACxB,UAAM,OAAO,GAAG;AAChB,QAAI,MAAM,SAAS,SAAU,QAAO;AACpC,WAAO,EAAE,MAA0B,IAAI;AAAA,EACzC;AAAA,EAEA,MAAM,IAAY,IAAY,QAA0B;AACtD,QAAI,KAAK,KAAK,aAAa,EAAG,QAAO;AACrC,UAAM,MAAM,KAAK,WAAW;AAC5B,QAAI,CAAC,IAAK,QAAO;AACjB,QAAI,IAAI,KAAK,YAAY,WAAW,EAAG,QAAO;AAE9C,UAAM,OAAO,SAAU,IAAI,IAAI,YAAY,KAAM;AACjD,QAAI,KAAK,eAAe,MAAM;AAC5B,YAAM,WAAW,KAAK,KAAK,mBAAmB;AAC9C,gBAAU,MAAM;AAChB,WAAK,YAAY,UAAU,wBAAwB;AAAA,IACrD,OAAO;AACL,mBAAa,KAAK,UAAU;AAAA,IAC9B;AACA,UAAM,QAAQ,IAAI,KAAK,eAAe,KAAK,MAAM,KAAK,MAAM,IAAI,GAAG;AACnE,SAAK,aAAa,WAAW,MAAM,KAAK,kBAAkB,GAAG,GAAG;AAChE,WAAO;AAAA,EACT;AAAA,EAEA,oBAA0B;AACxB,QAAI,KAAK,eAAe,KAAM;AAC9B,iBAAa,KAAK,UAAU;AAC5B,SAAK,aAAa;AAClB,UAAM,WAAW,KAAK,KAAK,mBAAmB;AAC9C,QAAI,KAAK,cAAc,QAAQ,UAAU,yBAAyB,KAAK,WAAW;AAChF,gBAAU,OAAO;AAAA,IACnB;AACA,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,iBAAuB;AACrB,QAAI,KAAK,KAAK,aAAa,EAAG;AAC9B,SAAK,kBAAkB;AACvB,UAAM,MAAM,KAAK,WAAW;AAC5B,QAAI,CAAC,IAAK;AACV,UAAM,MAAM,IAAI,KAAK;AACrB,QAAI,IAAI,WAAW,EAAG;AACtB,UAAM,WAAW,KAAK,KAAK,mBAAmB;AAC9C,cAAU,MAAM;AAChB,eAAW,MAAM,KAAK;AACpB,UAAI,IAAI,MAAM,OAAO,EAAE;AAAA,IACzB;AACA,cAAU,OAAO;AACjB,QAAI,IAAI,cAAc;AAAA,EACxB;AAAA,EAEA,OAAa;AACX,QAAI,KAAK,KAAK,aAAa,EAAG;AAC9B,SAAK,kBAAkB;AACvB,UAAM,MAAM,KAAK,KAAK,eAAe;AACrC,UAAM,QAAQ,KAAK,KAAK,gBAAgB;AACxC,QAAI,CAAC,SAAS,CAAC,IAAK;AACpB,UAAM,WAAW,KAAK,KAAK,mBAAmB;AAC9C,cAAU,MAAM;AAChB,UAAM,KAAK,IAAI,KAAK;AACpB,cAAU,OAAO;AACjB,QAAI,cAAc;AAAA,EACpB;AAAA,EAEA,OAAa;AACX,QAAI,KAAK,KAAK,aAAa,EAAG;AAC9B,SAAK,kBAAkB;AACvB,UAAM,MAAM,KAAK,KAAK,eAAe;AACrC,UAAM,QAAQ,KAAK,KAAK,gBAAgB;AACxC,QAAI,CAAC,SAAS,CAAC,IAAK;AACpB,UAAM,WAAW,KAAK,KAAK,mBAAmB;AAC9C,cAAU,MAAM;AAChB,UAAM,KAAK,IAAI,KAAK;AACpB,cAAU,OAAO;AACjB,QAAI,cAAc;AAAA,EACpB;AAAA,EAEA,OAAa;AACX,QAAI,KAAK,KAAK,aAAa,EAAG;AAC9B,UAAM,MAAM,KAAK,WAAW;AAC5B,QAAI,CAAC,IAAK;AACV,UAAM,MAAM,IAAI,KAAK;AACrB,QAAI,IAAI,WAAW,EAAG;AACtB,SAAK,YAAY,CAAC;AAClB,eAAW,MAAM,KAAK;AACpB,YAAM,KAAK,IAAI,IAAI,MAAM,QAAQ,EAAE;AACnC,UAAI,GAAI,MAAK,UAAU,KAAK,gBAAgB,EAAE,CAAC;AAAA,IACjD;AACA,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,QAAc;AACZ,QAAI,KAAK,KAAK,aAAa,EAAG;AAC9B,SAAK,kBAAkB;AACvB,QAAI,KAAK,UAAU,WAAW,EAAG;AACjC,UAAM,MAAM,KAAK,WAAW;AAC5B,QAAI,CAAC,IAAK;AAEV,UAAM,SAAS,KAAK,KAAK,sBAAsB,KAAK;AACpD,QAAI,QAAQ;AACV,YAAM,OAAO,uBAAuB,KAAK,SAAS;AAClD,UAAI,MAAM;AACR,cAAM,UAAU,KAAK,IAAI,KAAK,IAAI;AAClC,cAAM,UAAU,KAAK,IAAI,KAAK,IAAI;AAClC,aAAK,aAAa,KAAK,WAAW,EAAE,GAAG,OAAO,IAAI,SAAS,GAAG,OAAO,IAAI,QAAQ,GAAG,GAAG;AACvF;AAAA,MACF;AAAA,IACF;AAEA,SAAK;AACL,SAAK,aAAa,KAAK,WAAW,EAAE,GAAG,KAAK,aAAa,IAAI,GAAG,KAAK,aAAa,GAAG,GAAG,GAAG;AAAA,EAC7F;AAAA,EAEA,YAAkB;AAChB,QAAI,KAAK,KAAK,aAAa,EAAG;AAC9B,SAAK,kBAAkB;AACvB,UAAM,MAAM,KAAK,WAAW;AAC5B,QAAI,CAAC,IAAK;AACV,UAAM,SAA0B,CAAC;AACjC,eAAW,MAAM,IAAI,KAAK,aAAa;AACrC,YAAM,KAAK,IAAI,IAAI,MAAM,QAAQ,EAAE;AACnC,UAAI,GAAI,QAAO,KAAK,EAAE;AAAA,IACxB;AACA,QAAI,OAAO,WAAW,EAAG;AACzB,SAAK,aAAa,QAAQ,EAAE,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG;AAAA,EACjD;AAAA,EAEA,WAAiB;AACf,QAAI,KAAK,KAAK,aAAa,EAAG;AAC9B,UAAM,MAAM,KAAK,WAAW;AAC5B,QAAI,CAAC,IAAK;AACV,QAAI,IAAI,KAAK,YAAY,WAAW,EAAG;AACvC,QAAI,KAAK,aAAa,CAAC,CAAC;AACxB,QAAI,IAAI,cAAc;AAAA,EACxB;AAAA,EAEA,YAAkB;AAChB,QAAI,KAAK,KAAK,aAAa,EAAG;AAC9B,UAAM,KAAK,KAAK,KAAK,eAAe;AACpC,UAAM,MAAM,KAAK,KAAK,eAAe;AACrC,QAAI,CAAC,MAAM,CAAC,IAAK;AACjB,QAAI,GAAG,YAAY,SAAS,UAAU;AACpC,UAAI,aAAa,QAAQ;AAAA,IAC3B;AACA,UAAM,MAAM,KAAK,WAAW;AAC5B,QAAI,CAAC,IAAK;AACV,UAAM,MAAM,IAAI,IAAI,MACjB,OAAO,EACP;AAAA,MACC,CAAC,OACC,CAAC,GAAG,WACH,IAAI,IAAI,iBAAiB,GAAG,OAAO,KAAK,SACzC,EAAE,IAAI,IAAI,gBAAgB,GAAG,OAAO,KAAK;AAAA,IAC7C,EACC,IAAI,CAAC,OAAO,GAAG,EAAE;AACpB,QAAI,KAAK,aAAa,GAAG;AACzB,QAAI,IAAI,cAAc;AAAA,EACxB;AAAA,EAEA,YAAkB;AAChB,QAAI,KAAK,KAAK,aAAa,EAAG;AAC9B,SAAK,KAAK,eAAe;AAAA,EAC3B;AAAA,EAEA,OAAO,WAA4D;AACjE,QAAI,KAAK,KAAK,aAAa,EAAG;AAC9B,SAAK,kBAAkB;AACvB,UAAM,MAAM,KAAK,WAAW;AAC5B,QAAI,CAAC,IAAK;AACV,UAAM,MAAM,IAAI,KAAK;AACrB,QAAI,IAAI,WAAW,EAAG;AACtB,UAAM,WAAW,KAAK,KAAK,mBAAmB;AAC9C,cAAU,MAAM;AAChB,eAAW,MAAM,KAAK;AACpB,cAAQ,WAAW;AAAA,QACjB,KAAK;AACH,cAAI,IAAI,MAAM,aAAa,EAAE;AAC7B;AAAA,QACF,KAAK;AACH,cAAI,IAAI,MAAM,aAAa,EAAE;AAC7B;AAAA,QACF,KAAK;AACH,cAAI,IAAI,MAAM,aAAa,EAAE;AAC7B;AAAA,QACF,KAAK;AACH,cAAI,IAAI,MAAM,WAAW,EAAE;AAC3B;AAAA,MACJ;AAAA,IACF;AACA,cAAU,OAAO;AACjB,QAAI,IAAI,cAAc;AAAA,EACxB;AAAA,EAEQ,aACN,QACA,QACA,KACM;AACN,UAAM,QAAQ,oBAAI,IAAoB;AACtC,eAAW,MAAM,QAAQ;AACvB,YAAM,IAAI,GAAG,IAAI,SAAS,GAAG,IAAI,CAAC;AAAA,IACpC;AAEA,UAAM,SAAmB,CAAC;AAC1B,UAAM,WAAW,KAAK,KAAK,mBAAmB;AAC9C,cAAU,MAAM;AAEhB,eAAW,MAAM,QAAQ;AACvB,YAAM,QAAQ,gBAAgB,EAAE;AAChC,YAAM,QAAQ,MAAM,IAAI,GAAG,EAAE;AAC7B,UAAI,CAAC,MAAO;AACZ,YAAM,KAAK;AACX,YAAM,WAAW,EAAE,GAAG,MAAM,SAAS,IAAI,OAAO,GAAG,GAAG,MAAM,SAAS,IAAI,OAAO,EAAE;AAElF,UAAI,MAAM,SAAS,SAAS;AAC1B,cAAM,QAAQ;AACd,cAAM,OAAO,EAAE,GAAG,MAAM,KAAK,IAAI,OAAO,GAAG,GAAG,MAAM,KAAK,IAAI,OAAO,EAAE;AACtE,cAAM,KAAK,EAAE,GAAG,MAAM,GAAG,IAAI,OAAO,GAAG,GAAG,MAAM,GAAG,IAAI,OAAO,EAAE;AAChE,eAAO,MAAM;AAEb,YAAI,MAAM,aAAa;AACrB,gBAAM,YAAY,MAAM,IAAI,MAAM,YAAY,SAAS;AACvD,cAAI,WAAW;AACb,kBAAM,cAAc,EAAE,WAAW,UAAU;AAAA,UAC7C,OAAO;AACL,mBAAO,MAAM;AAAA,UACf;AAAA,QACF;AACA,YAAI,MAAM,WAAW;AACnB,gBAAM,YAAY,MAAM,IAAI,MAAM,UAAU,SAAS;AACrD,cAAI,WAAW;AACb,kBAAM,YAAY,EAAE,WAAW,UAAU;AAAA,UAC3C,OAAO;AACL,mBAAO,MAAM;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAEA,UAAI,IAAI,IAAI,eAAe;AACzB,cAAM,UAAU,IAAI,IAAI;AAAA,MAC1B;AAEA,UAAI,IAAI,MAAM,IAAI,KAAK;AACvB,aAAO,KAAK,MAAM,EAAE;AAAA,IACtB;AAEA,cAAU,OAAO;AACjB,QAAI,KAAK,aAAa,MAAM;AAC5B,QAAI,IAAI,cAAc;AAAA,EACxB;AACF;;;ACtQA,IAAM,mBAAsE;AAAA,EAC1E,CAAC,UAAU,CAAC,UAAU,WAAW,CAAC;AAAA,EAClC,CAAC,YAAY,CAAC,QAAQ,CAAC;AAAA,EACvB,CAAC,QAAQ,CAAC,OAAO,CAAC;AAAA,EAClB,CAAC,QAAQ,CAAC,SAAS,aAAa,CAAC;AAAA,EACjC,CAAC,cAAc,CAAC,OAAO,CAAC;AAAA,EACxB,CAAC,QAAQ,CAAC,OAAO,CAAC;AAAA,EAClB,CAAC,SAAS,CAAC,OAAO,CAAC;AAAA,EACnB,CAAC,aAAa,CAAC,OAAO,CAAC;AAAA,EACvB,CAAC,aAAa,CAAC,GAAG,CAAC;AAAA,EACnB,CAAC,cAAc,CAAC,GAAG,CAAC;AAAA,EACpB,CAAC,WAAW,CAAC,OAAO,CAAC;AAAA,EACrB,CAAC,UAAU,CAAC,OAAO,CAAC;AAAA,EACpB,CAAC,YAAY,CAAC,SAAS,CAAC;AAAA,EACxB,CAAC,WAAW,CAAC,OAAO,CAAC;AAAA,EACrB,CAAC,YAAY,CAAC,OAAO,CAAC;AAAA,EACtB,CAAC,cAAc,CAAC,OAAO,CAAC;AAAA,EACxB,CAAC,cAAc,CAAC,WAAW,CAAC;AAAA,EAC5B,CAAC,eAAe,CAAC,YAAY,CAAC;AAAA,EAC9B,CAAC,YAAY,CAAC,SAAS,CAAC;AAAA,EACxB,CAAC,cAAc,CAAC,WAAW,CAAC;AAAA,EAC5B,CAAC,eAAe,CAAC,GAAG,CAAC;AAAA,EACrB,CAAC,aAAa,CAAC,GAAG,CAAC;AAAA,EACnB,CAAC,eAAe,CAAC,GAAG,CAAC;AAAA,EACrB,CAAC,eAAe,CAAC,GAAG,CAAC;AAAA,EACrB,CAAC,cAAc,CAAC,GAAG,CAAC;AAAA,EACpB,CAAC,aAAa,CAAC,GAAG,CAAC;AAAA,EACnB,CAAC,aAAa,CAAC,GAAG,CAAC;AAAA,EACnB,CAAC,cAAc,CAAC,GAAG,CAAC;AAAA,EACpB,CAAC,gBAAgB,CAAC,GAAG,CAAC;AAAA,EACtB,CAAC,iBAAiB,CAAC,GAAG,CAAC;AACzB;AAEA,IAAM,cAAc,oBAAI,IAAI,CAAC,cAAc,eAAe,YAAY,YAAY,CAAC;AACnF,IAAM,YAAY,oBAAI,IAAI,CAAC,OAAO,QAAQ,QAAQ,SAAS,KAAK,CAAC;AAEjE,SAAS,aAAa,SAAgC;AACpD,QAAM,QAAQ,QAAQ,YAAY,EAAE,MAAM,GAAG;AAC7C,QAAM,MAAM,MAAM,IAAI;AACtB,MAAI,QAAQ,UAAa,IAAI,WAAW,KAAK,UAAU,IAAI,GAAG,GAAG;AAC/D,UAAM,IAAI,MAAM,6BAA6B,OAAO,gBAAgB;AAAA,EACtE;AACA,QAAM,gBAAgB,QAAQ,UAAU,MAAM;AAC9C,QAAM,SAAwB;AAAA,IAC5B,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,KAAK;AAAA,IACL,OAAO,UAAU,KAAK,aAAa;AAAA,EACrC;AACA,aAAW,QAAQ,OAAO;AACxB,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO,MAAM;AACb;AAAA,MACF,KAAK;AACH,eAAO,OAAO;AACd;AAAA,MACF,KAAK;AACH,eAAO,OAAO;AACd;AAAA,MACF,KAAK;AACH,eAAO,QAAQ;AACf;AAAA,MACF,KAAK;AACH,eAAO,MAAM;AACb;AAAA,MACF;AACE,cAAM,IAAI,MAAM,6BAA6B,OAAO,wBAAwB,IAAI,GAAG;AAAA,IACvF;AAAA,EACF;AACA,MAAI,OAAO,QAAQ,OAAO,QAAQ,OAAO,OAAO;AAC9C,UAAM,IAAI;AAAA,MACR,6BAA6B,OAAO;AAAA,IACtC;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,eAAe,GAAkB,GAAkB,YAA8B;AACxF,MAAI,EAAE,KAAK;AACT,QAAI,CAAC,EAAE,WAAW,CAAC,EAAE,QAAS,QAAO;AAAA,EACvC,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM;AACvD,WAAO;AAAA,EACT;AACA,MAAI,CAAC,cAAc,EAAE,aAAa,EAAE,MAAO,QAAO;AAClD,MAAI,EAAE,WAAW,EAAE,IAAK,QAAO;AAC/B,SAAO,EAAE,QAAQ,EAAE,SAAS,QAAQ,EAAE,GAAG,KAAK,EAAE,IAAI,YAAY,MAAM,EAAE;AAC1E;AAEA,SAAS,QAAQ,UAA8C;AAC7D,MAAI,aAAa,KAAM,QAAO,CAAC;AAC/B,SAAO,MAAM,QAAQ,QAAQ,IAAI,CAAC,GAAG,QAAQ,IAAI,CAAC,QAAQ;AAC5D;AAEO,IAAM,cAAN,MAA0C;AAAA,EACvC,MAAM,oBAAI,IAAsB;AAAA,EAChC,SAAS,oBAAI,IAA6B;AAAA,EAElD,YAAY,WAA8B;AACxC,SAAK,cAAc;AACnB,QAAI,WAAW;AACb,iBAAW,CAAC,QAAQ,QAAQ,KAAK,OAAO,QAAQ,SAAS,GAAG;AAC1D,aAAK,OAAO,QAAQ,QAAQ;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,GAAiC;AACrC,eAAW,CAAC,QAAQ,UAAU,KAAK,KAAK,QAAQ;AAC9C,YAAM,aAAa,YAAY,IAAI,MAAM;AACzC,iBAAW,KAAK,YAAY;AAC1B,YAAI,eAAe,GAAG,GAAG,UAAU,EAAG,QAAO;AAAA,MAC/C;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,QAAgB,UAA0C;AAC/D,UAAM,OAAO,QAAQ,QAAQ;AAC7B,UAAM,aAAa,KAAK,IAAI,YAAY;AACxC,SAAK,IAAI,IAAI,QAAQ,IAAI;AACzB,SAAK,OAAO,IAAI,QAAQ,UAAU;AAAA,EACpC;AAAA,EAEA,QAAQ,QAAsB;AAC5B,SAAK,OAAO,QAAQ,IAAI;AAAA,EAC1B;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,WAAW,QAAW;AACxB,WAAK,IAAI,MAAM;AACf,WAAK,OAAO,MAAM;AAClB,WAAK,cAAc;AACnB;AAAA,IACF;AACA,UAAM,MAAM,iBAAiB,KAAK,CAAC,CAAC,IAAI,MAAM,SAAS,MAAM;AAC7D,QAAI,KAAK;AACP,WAAK,OAAO,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;AAAA,IACjC,WAAW,KAAK,IAAI,IAAI,MAAM,GAAG;AAC/B,WAAK,IAAI,OAAO,MAAM;AACtB,WAAK,OAAO,OAAO,MAAM;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,cAAwC;AACtC,UAAM,MAAgC,CAAC;AACvC,eAAW,CAAC,QAAQ,IAAI,KAAK,KAAK,KAAK;AACrC,UAAI,MAAM,IAAI,CAAC,GAAG,IAAI;AAAA,IACxB;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAsB;AAC5B,eAAW,CAAC,QAAQ,QAAQ,KAAK,kBAAkB;AACjD,WAAK,OAAO,QAAQ,CAAC,GAAG,QAAQ,CAAC;AAAA,IACnC;AAAA,EACF;AACF;;;AC/KA,IAAM,mBAAmB;AACzB,IAAM,YAAY;AAClB,IAAM,gBAAgB;AAEtB,IAAM,eAA0D;AAAA,EAC9D,cAAc,CAAC,IAAI,CAAC;AAAA,EACpB,eAAe,CAAC,GAAG,CAAC;AAAA,EACpB,YAAY,CAAC,GAAG,EAAE;AAAA,EAClB,cAAc,CAAC,GAAG,CAAC;AACrB;AAWO,IAAM,eAAN,MAAmB;AAAA,EAoBxB,YACmB,SACA,QACjB,UAA+B,CAAC,GAChC;AAHiB;AACA;AAGjB,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,kBAAkB,QAAQ,mBAAmB;AAClD,SAAK,eAAe,QAAQ,gBAAgB;AAC5C,SAAK,UAAU,IAAI,gBAAgB;AAAA,MACjC,gBAAgB,MAAM,KAAK;AAAA,MAC3B,gBAAgB,MAAM,KAAK;AAAA,MAC3B,oBAAoB,MAAM,KAAK;AAAA,MAC/B,iBAAiB,MAAM,KAAK;AAAA,MAC5B,cAAc,MAAM,KAAK;AAAA,MACzB,cAAc,QAAQ;AAAA,MACtB,qBAAqB,MAAM,KAAK,iBAAiB;AAAA,IACnD,CAAC;AACD,SAAK,cAAc,IAAI,YAAY,QAAQ,WAAW,QAAQ;AAC9D,SAAK,QAAQ,QAAQ,WAAW,SAAS;AACzC,SAAK,QAAQ,MAAM,cAAc;AACjC,QAAI,KAAK,UAAU,SAAS;AAC1B,WAAK,QAAQ,WAAW;AAExB,WAAK,QAAQ,MAAM,UAAU;AAAA,IAC/B;AACA,SAAK,KAAK;AAAA,EACZ;AAAA,EA9CQ,YAAY;AAAA,EACZ,cAAc,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC3B,YAAY;AAAA,EACZ,iBAAiB,oBAAI,IAAsC;AAAA,EAC3D,oBAAoB;AAAA,EACpB,kBAAkB,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,mBAAwC;AAAA,EAC/B,cAAc,IAAI,YAAY;AAAA,EACvC,eAAoC;AAAA,EAC3B,kBAAkB,IAAI,gBAAgB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EA+BjB,eAAe,aAA0B,aAAgC;AACvE,SAAK,cAAc;AACnB,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,sBAA4B;AAC1B,SAAK,QAAQ,kBAAkB;AAAA,EACjC;AAAA,EAEA,IAAI,YAA0B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,UAAgB;AACd,SAAK,QAAQ,QAAQ;AACrB,SAAK,gBAAgB,MAAM;AAC3B,SAAK,YAAY,MAAM;AACvB,SAAK,eAAe;AACpB,SAAK,mBAAmB;AACxB,QAAI,KAAK,UAAU,SAAS;AAC1B,WAAK,QAAQ,gBAAgB,UAAU;AACvC,WAAK,QAAQ,MAAM,UAAU;AAAA,IAC/B;AAAA,EACF;AAAA,EAEQ,OAAa;AACnB,UAAM,OAAO,EAAE,QAAQ,KAAK,gBAAgB,OAAO;AAEnD,SAAK,QAAQ,iBAAiB,SAAS,KAAK,SAAS,EAAE,GAAG,MAAM,SAAS,MAAM,CAAC;AAChF,SAAK,QAAQ,iBAAiB,eAAe,KAAK,eAAe,IAAI;AACrE,SAAK,QAAQ,iBAAiB,eAAe,KAAK,eAAe,IAAI;AACrE,SAAK,QAAQ,iBAAiB,aAAa,KAAK,aAAa,IAAI;AACjE,SAAK,QAAQ,iBAAiB,gBAAgB,KAAK,gBAAgB,IAAI;AACvE,SAAK,QAAQ,iBAAiB,iBAAiB,KAAK,aAAa,IAAI;AACrE,WAAO,iBAAiB,WAAW,KAAK,WAAW,IAAI;AACvD,WAAO,iBAAiB,SAAS,KAAK,SAAS,IAAI;AAAA,EACrD;AAAA,EAEQ,iBAA2C;AACjD,UAAM,OAAO,KAAK,QAAQ,sBAAsB;AAChD,WAAO,EAAE,GAAG,KAAK,QAAQ,GAAG,GAAG,KAAK,SAAS,EAAE;AAAA,EACjD;AAAA,EAEQ,aAAa,QAAsB;AACzC,SAAK,OAAO,OAAO,KAAK,OAAO,OAAO,QAAQ,KAAK,eAAe,CAAC;AAAA,EACrE;AAAA,EAEQ,YAAY,OAAqB;AACvC,SAAK,OAAO,OAAO,OAAO,KAAK,eAAe,CAAC;AAAA,EACjD;AAAA,EAEQ,UAAU,CAAC,MAAwB;AACzC,MAAE,eAAe;AACjB,UAAM,OAAO,KAAK,QAAQ,sBAAsB;AAChD,UAAM,aAAa,IAAI,EAAE,SAAS;AAClC,UAAM,UAAU,KAAK,OAAO,OAAO;AACnC,SAAK,OAAO,OAAO,SAAS;AAAA,MAC1B,GAAG,EAAE,UAAU,KAAK;AAAA,MACpB,GAAG,EAAE,UAAU,KAAK;AAAA,IACtB,CAAC;AAAA,EACH;AAAA,EAEQ,gBAAgB,CAAC,MAA0B;AACjD,SAAK,UAAU;AACf,SAAK,eAAe,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ,CAAC;AAEnE,SAAK,QAAQ,oBAAoB,EAAE,SAAS;AAE5C,QAAI,KAAK,eAAe,SAAS,GAAG;AAClC,WAAK,WAAW;AAChB,WAAK,mBAAmB,CAAC;AACzB;AAAA,IACF;AAEA,QAAI,EAAE,WAAW,iBAAkB,EAAE,WAAW,KAAK,KAAK,WAAY;AACpE,WAAK,YAAY;AACjB,WAAK,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ;AAChD;AAAA,IACF;AAEA,QACE,KAAK,eAAe,SAAS,MAC5B,EAAE,WAAW,KAAK,EAAE,gBAAgB,WAAW,EAAE,gBAAgB,QAClE;AACA,YAAM,SAAS,KAAK,YAAY,WAAW,CAAC;AAC5C,UAAI,OAAO,WAAW,WAAY;AAClC,UAAI,OAAO,WAAW,SAAS;AAC7B,aAAK,eAAe;AACpB;AAAA,MACF;AACA,WAAK,iBAAiB,CAAC;AAAA,IACzB;AAAA,EACF;AAAA,EAEQ,gBAAgB,CAAC,MAA0B;AACjD,SAAK,mBAAmB;AAExB,QAAI,KAAK,eAAe,IAAI,EAAE,SAAS,GAAG;AACxC,WAAK,eAAe,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ,CAAC;AAAA,IACrE;AAEA,QAAI,KAAK,eAAe,SAAS,GAAG;AAClC,WAAK,gBAAgB;AACrB;AAAA,IACF;AAEA,QAAI,KAAK,WAAW;AAClB,YAAM,KAAK,EAAE,UAAU,KAAK,YAAY;AACxC,YAAM,KAAK,EAAE,UAAU,KAAK,YAAY;AACxC,WAAK,cAAc,EAAE,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ;AAChD,WAAK,OAAO,IAAI,IAAI,EAAE;AACtB;AAAA,IACF;AAEA,QAAI,EAAE,gBAAgB,SAAS,CAAC,KAAK,eAAe,IAAI,EAAE,SAAS,GAAG;AACpE,WAAK,kBAAkB,CAAC;AAAA,IAC1B,WAAW,KAAK,cAAc;AAC5B,WAAK,iBAAiB,CAAC;AAAA,IACzB,WAAW,KAAK,cAAc;AAC5B,YAAM,SAAS,KAAK,YAAY,WAAW,CAAC;AAC5C,UAAI,OAAO,WAAW,YAAY;AAChC,aAAK,iBAAiB,KAAK,YAAY;AACvC,aAAK,eAAe;AACpB,aAAK,iBAAiB,CAAC;AAAA,MACzB;AAAA,IACF,WAAW,KAAK,eAAe,SAAS,GAAG;AACzC,WAAK,kBAAkB,CAAC;AAAA,IAC1B;AAAA,EACF;AAAA,EAEQ,cAAc,CAAC,MAA0B;AAC/C,QAAI;AACF,WAAK,QAAQ,sBAAsB,EAAE,SAAS;AAAA,IAChD,QAAQ;AAAA,IAER;AACA,SAAK,eAAe,OAAO,EAAE,SAAS;AAEtC,QAAI,KAAK,eAAe,OAAO,GAAG;AAChC,WAAK,oBAAoB;AAAA,IAC3B;AAEA,QAAI,KAAK,aAAa,KAAK,eAAe,SAAS,GAAG;AACpD,WAAK,YAAY;AAAA,IACnB;AAEA,UAAM,WAAW,KAAK,YAAY,SAAS,CAAC;AAE5C,QAAI,KAAK,cAAc;AACrB,WAAK,eAAe,CAAC;AACrB,WAAK,eAAe;AAAA,IACtB,WAAW,KAAK,gBAAgB,SAAS,YAAY;AACnD,WAAK,iBAAiB,KAAK,YAAY;AACvC,WAAK,eAAe,CAAC;AACrB,WAAK,eAAe;AAAA,IACtB,OAAO;AACL,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,YAAY,CAAC,MAA2B;AAC9C,UAAM,SAAS,EAAE;AACjB,QAAI,QAAQ,kBAAmB;AAC/B,UAAM,MAAM,QAAQ;AACpB,QAAI,QAAQ,WAAW,QAAQ,cAAc,QAAQ,SAAU;AAC/D,QAAI,CAAC,KAAK,UAAU,EAAG;AAEvB,QAAI,EAAE,QAAQ,KAAK;AACjB,WAAK,YAAY;AAAA,IACnB;AACA,UAAM,SAAS,KAAK,YAAY,MAAM,CAAC;AACvC,QAAI,WAAW,MAAM;AACnB,WAAK,UAAU,QAAQ,CAAC;AAAA,IAC1B;AAAA,EACF;AAAA,EAEQ,UAAU,CAAC,MAA2B;AAC5C,QAAI,EAAE,QAAQ,KAAK;AACjB,WAAK,YAAY;AACjB,UAAI,KAAK,eAAe,SAAS,GAAG;AAClC,YAAI,KAAK,kBAAkB;AACzB,eAAK,kBAAkB,KAAK,gBAAgB;AAAA,QAC9C,OAAO;AACL,eAAK,aAAa,YAAY,SAAS;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,UAAU,QAAgB,GAAwB;AACxD,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,QAAQ,eAAe;AAC5B;AAAA,MACF,KAAK;AACH,aAAK,QAAQ,SAAS;AACtB;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,QAAQ,KAAK;AAClB;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,QAAQ,KAAK;AAClB;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,QAAQ,UAAU;AACvB;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,QAAQ,KAAK;AAClB;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,QAAQ,MAAM;AACnB;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,QAAQ,UAAU;AACvB;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,QAAQ,OAAO,SAAS;AAC7B;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,QAAQ,OAAO,UAAU;AAC9B;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,QAAQ,OAAO,OAAO;AAC3B;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,QAAQ,OAAO,MAAM;AAC1B;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,QAAQ,UAAU;AACvB;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,aAAa,SAAS;AAC3B;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,aAAa,IAAI,SAAS;AAC/B;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,aAAK,YAAY,CAAC;AAClB;AAAA,MACF,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,cAAc;AACjB,cAAM,QAAQ,aAAa,MAAM;AACjC,YAAI,SAAS,KAAK,QAAQ,MAAM,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,EAAE,QAAQ,GAAG;AAC/D,YAAE,eAAe;AAAA,QACnB;AACA;AAAA,MACF;AAAA,MACA;AACE,YAAI,OAAO,WAAW,OAAO,GAAG;AAC9B,cAAI,KAAK,aAAc;AACvB,YAAE,eAAe;AACjB,eAAK,aAAa,aAAa,OAAO,MAAM,QAAQ,MAAM,CAAC;AAC3D;AAAA,QACF;AACA,gBAAQ,KAAK,yCAAyC,MAAM,GAAG;AAAA,IACnE;AAAA,EACF;AAAA,EAEQ,aAAmB;AACzB,SAAK,YAAY,MAAM;AACvB,SAAK,eAAe;AACpB,SAAK,YAAY;AACjB,UAAM,CAAC,GAAG,CAAC,IAAI,KAAK,eAAe;AACnC,SAAK,oBAAoB,KAAK,SAAS,GAAG,CAAC;AAC3C,SAAK,kBAAkB,KAAK,SAAS,GAAG,CAAC;AACzC,SAAK,cAAc,EAAE,GAAG,KAAK,gBAAgB;AAAA,EAC/C;AAAA,EAEQ,kBAAwB;AAC9B,UAAM,CAAC,GAAG,CAAC,IAAI,KAAK,eAAe;AACnC,UAAM,OAAO,KAAK,SAAS,GAAG,CAAC;AAC/B,UAAM,SAAS,KAAK,SAAS,GAAG,CAAC;AAEjC,QAAI,KAAK,oBAAoB,GAAG;AAC9B,YAAM,QAAQ,OAAO,KAAK;AAC1B,YAAM,UAAU,KAAK,OAAO,OAAO;AACnC,WAAK,OAAO,OAAO,SAAS,MAAM;AAAA,IACpC;AAEA,UAAM,KAAK,OAAO,IAAI,KAAK,YAAY;AACvC,UAAM,KAAK,OAAO,IAAI,KAAK,YAAY;AACvC,SAAK,OAAO,IAAI,IAAI,EAAE;AAEtB,SAAK,oBAAoB;AACzB,SAAK,kBAAkB;AACvB,SAAK,cAAc,EAAE,GAAG,OAAO;AAAA,EACjC;AAAA,EAEQ,iBAAuE;AAC7E,UAAM,MAAM,CAAC,GAAG,KAAK,eAAe,OAAO,CAAC;AAC5C,WAAO,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AAAA,EAC5D;AAAA,EAEQ,SAAS,GAA6B,GAAqC;AACjF,UAAM,KAAK,EAAE,IAAI,EAAE;AACnB,UAAM,KAAK,EAAE,IAAI,EAAE;AACnB,WAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAAA,EACpC;AAAA,EAEQ,SACN,GACA,GAC0B;AAC1B,WAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE;AAAA,EAClD;AAAA,EAEQ,mBAAoD;AAC1D,UAAM,IAAI,KAAK;AACf,QAAI,CAAC,EAAG,QAAO;AACf,UAAM,OAAO,KAAK,QAAQ,sBAAsB;AAChD,WAAO,KAAK,OAAO,cAAc,EAAE,GAAG,EAAE,UAAU,KAAK,MAAM,GAAG,EAAE,UAAU,KAAK,IAAI,CAAC;AAAA,EACxF;AAAA,EAEQ,iBAAiB,CAAC,MAA0B;AAClD,SAAK,mBAAmB;AACxB,SAAK,YAAY,CAAC;AAAA,EACpB;AAAA,EAEQ,eAAe,GAA+B;AACpD,UAAM,OAAO,KAAK,QAAQ,sBAAsB;AAChD,WAAO;AAAA,MACL,GAAG,EAAE,UAAU,KAAK;AAAA,MACpB,GAAG,EAAE,UAAU,KAAK;AAAA,MACpB,UAAU,EAAE;AAAA,MACZ,aAAa,EAAE,gBAAgB,WAAW,EAAE,gBAAgB,QAAQ,EAAE,cAAc;AAAA,MACpF,UAAU,EAAE;AAAA,IACd;AAAA,EACF;AAAA,EAEQ,iBAAiB,GAAuB;AAC9C,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK,YAAa;AAC5C,SAAK,QAAQ,kBAAkB;AAC/B,SAAK,iBAAiB,MAAM;AAC5B,SAAK,eAAe;AACpB,SAAK,YAAY,kBAAkB,KAAK,eAAe,CAAC,GAAG,KAAK,WAAW;AAAA,EAC7E;AAAA,EAEQ,iBAAiB,GAAuB;AAC9C,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK,YAAa;AAC5C,SAAK,YAAY,kBAAkB,KAAK,eAAe,CAAC,GAAG,KAAK,WAAW;AAAA,EAC7E;AAAA,EAEQ,kBAAkB,GAAuB;AAC/C,QAAI,CAAC,KAAK,aAAa,cAAc,CAAC,KAAK,YAAa;AACxD,UAAM,OAAO,KAAK,YAAY;AAC9B,QAAI,KAAK,SAAS;AAChB,WAAK,QAAQ,KAAK,eAAe,CAAC,GAAG,KAAK,WAAW;AAAA,IACvD;AAAA,EACF;AAAA,EAEQ,eAAe,GAAuB;AAC5C,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK,YAAa;AAC5C,SAAK,YAAY,gBAAgB,KAAK,eAAe,CAAC,GAAG,KAAK,WAAW;AACzE,SAAK,iBAAiB,OAAO;AAAA,EAC/B;AAAA,EAEQ,YAAqB;AAC3B,QAAI,KAAK,UAAU,SAAU,QAAO;AACpC,UAAM,SAAS,SAAS;AACxB,WAAO,WAAW,KAAK,WAAW,KAAK,QAAQ,SAAS,MAAM;AAAA,EAChE;AAAA,EAEQ,YAAkB;AACxB,QAAI,KAAK,UAAU,WAAW,KAAK,UAAU,EAAG;AAChD,SAAK,QAAQ,MAAM,EAAE,eAAe,KAAK,CAAC;AAAA,EAC5C;AAAA,EAEQ,mBAAmB,GAAuB;AAChD,QAAI,KAAK,cAAc;AACrB,WAAK,eAAe,CAAC;AACrB,WAAK,eAAe;AAAA,IACtB;AACA,SAAK,eAAe;AAAA,EACtB;AACF;;;AC1cA,IAAM,sBAAsB;AAE5B,IAAM,WAAW;AAAA,EACf,SAAS;AAAA,EACT,SAAS;AAAA,EACT,OAAO;AAAA,EACP,WAAW;AAAA,EACX,WAAW;AACb;AAEO,IAAM,aAAN,MAAiB;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,eAA2D;AAAA,EAC3D,YAAiF;AAAA,EACjF,WAAW;AAAA,EACX,cAAc;AAAA,EACd,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,aAAa;AAAA,EAErB,YAAY,UAA6B,CAAC,GAAG;AAC3C,SAAK,UAAU,QAAQ,WAAW,SAAS;AAC3C,SAAK,UAAU,QAAQ,WAAW,SAAS;AAC3C,SAAK,QAAQ,QAAQ,SAAS,SAAS;AACvC,SAAK,YAAY,QAAQ,aAAa,SAAS;AAC/C,SAAK,YAAY,QAAQ,aAAa,SAAS;AAAA,EACjD;AAAA,EAEA,OAAO,KAA+B,QAAsB;AAC1D,UAAM,EAAE,OAAO,OAAO,IAAI,IAAI;AAC9B,UAAM,MAAM,OAAO,qBAAqB,cAAc,mBAAmB;AACzE,UAAM,WAAW,QAAQ;AACzB,UAAM,YAAY,SAAS;AAE3B,QAAI,KAAK;AACT,QAAI,aAAa,KAAK,GAAG,GAAG,KAAK,GAAG,CAAC;AACrC,QAAI,UAAU,GAAG,GAAG,UAAU,SAAS;AAEvC,QAAI,KAAK,YAAY,QAAQ;AAC3B,UAAI,QAAQ;AACZ;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,aAAa,KAAK,SAAS,OAAO,IAAI;AAC3D,UAAM,UAAU,OAAO;AACvB,UAAM,OAAO,KAAK,MAAM,OAAO,SAAS,IAAI,OAAO;AACnD,UAAM,OAAO,KAAK,MAAM,OAAO,SAAS,IAAI,OAAO;AAEnD,QACE,KAAK,iBAAiB,QACtB,YAAY,KAAK,YACjB,SAAS,KAAK,eACd,SAAS,KAAK,eACd,aAAa,KAAK,aAClB,cAAc,KAAK,YACnB;AACA,UAAI,UAAU,KAAK,cAAmC,GAAG,CAAC;AAC1D,UAAI,QAAQ;AACZ;AAAA,IACF;AAEA,SAAK,mBAAmB,UAAU,WAAW,GAAG;AAEhD,QAAI,KAAK,cAAc,MAAM;AAE3B,UAAI,KAAK,YAAY,QAAQ;AAC3B,aAAK,WAAW,KAAK,QAAQ,UAAU,SAAS;AAAA,MAClD,WAAW,KAAK,YAAY,QAAQ;AAClC,aAAK,WAAW,KAAK,QAAQ,UAAU,SAAS;AAAA,MAClD;AACA,UAAI,QAAQ;AACZ;AAAA,IACF;AAEA,UAAM,SAAS,KAAK;AACpB,WAAO,UAAU,GAAG,GAAG,UAAU,SAAS;AAC1C,QAAI,KAAK,YAAY,QAAQ;AAC3B,WAAK,WAAW,QAAQ,QAAQ,UAAU,SAAS;AAAA,IACrD,WAAW,KAAK,YAAY,QAAQ;AAClC,WAAK,WAAW,QAAQ,QAAQ,UAAU,SAAS;AAAA,IACrD;AAEA,SAAK,WAAW;AAChB,SAAK,cAAc;AACnB,SAAK,cAAc;AACnB,SAAK,YAAY;AACjB,SAAK,aAAa;AAElB,QAAI,UAAU,KAAK,cAAmC,GAAG,CAAC;AAC1D,QAAI,QAAQ;AAAA,EACd;AAAA,EAEQ,mBAAmB,UAAkB,WAAmB,KAAmB;AACjF,QACE,KAAK,iBAAiB,QACtB,KAAK,cAAc,YACnB,KAAK,eAAe,WACpB;AACA;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,MAAM,WAAW,GAAG;AAC3C,UAAM,aAAa,KAAK,MAAM,YAAY,GAAG;AAE7C,QAAI,OAAO,oBAAoB,aAAa;AAC1C,WAAK,eAAe,IAAI,gBAAgB,WAAW,UAAU;AAAA,IAC/D,WAAW,OAAO,aAAa,aAAa;AAC1C,YAAM,KAAK,SAAS,cAAc,QAAQ;AAC1C,SAAG,QAAQ;AACX,SAAG,SAAS;AACZ,WAAK,eAAe;AAAA,IACtB,OAAO;AAEL,WAAK,eAAe;AACpB,WAAK,YAAY;AACjB;AAAA,IACF;AAEA,UAAM,SAAS,KAAK,aAAa,WAAW,IAAI;AAChD,QAAI,WAAW,MAAM;AACnB,MAAC,OAAoC,MAAM,KAAK,GAAG;AAAA,IACrD;AACA,SAAK,YAAY;AAGjB,SAAK,WAAW;AAAA,EAClB;AAAA,EAEQ,aAAa,aAAqB,MAAsB;AAC9D,QAAI,UAAU,cAAc;AAC5B,WAAO,UAAU,qBAAqB;AACpC,iBAAW;AAAA,IACb;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,WACN,KACA,QACA,OACA,QACM;AACN,UAAM,UAAU,KAAK,aAAa,KAAK,SAAS,OAAO,IAAI;AAC3D,UAAM,UAAU,OAAO,SAAS,IAAI;AACpC,UAAM,UAAU,OAAO,SAAS,IAAI;AACpC,UAAM,SAAS,KAAK,YAAY,KAAK,IAAI,OAAO,MAAM,CAAC;AAEvD,QAAI,YAAY,KAAK;AACrB,QAAI,UAAU;AAEd,aAAS,IAAI,SAAS,IAAI,OAAO,KAAK,SAAS;AAC7C,eAAS,IAAI,SAAS,IAAI,QAAQ,KAAK,SAAS;AAC9C,YAAI,OAAO,IAAI,QAAQ,CAAC;AACxB,YAAI,IAAI,GAAG,GAAG,QAAQ,GAAG,KAAK,KAAK,CAAC;AAAA,MACtC;AAAA,IACF;AAEA,QAAI,KAAK;AAAA,EACX;AAAA,EAEQ,WACN,KACA,QACA,OACA,QACM;AACN,UAAM,UAAU,KAAK,aAAa,KAAK,SAAS,OAAO,IAAI;AAC3D,UAAM,UAAU,OAAO,SAAS,IAAI;AACpC,UAAM,UAAU,OAAO,SAAS,IAAI;AACpC,UAAM,QAAQ,KAAK,YAAY,KAAK,IAAI,OAAO,MAAM,CAAC;AAEtD,QAAI,YAAY,KAAK;AAErB,aAAS,IAAI,SAAS,IAAI,OAAO,KAAK,SAAS;AAC7C,UAAI,SAAS,GAAG,GAAG,OAAO,MAAM;AAAA,IAClC;AAEA,aAAS,IAAI,SAAS,IAAI,QAAQ,KAAK,SAAS;AAC9C,UAAI,SAAS,GAAG,GAAG,OAAO,KAAK;AAAA,IACjC;AAAA,EACF;AACF;;;ACnMO,IAAM,WAAN,MAAqE;AAAA,EAClE,YAAY,oBAAI,IAAyC;AAAA,EAEjE,GAA4B,OAAU,UAA4C;AAChF,UAAM,WAAW,KAAK,UAAU,IAAI,KAAK;AACzC,QAAI,UAAU;AACZ,eAAS,IAAI,QAA2B;AAAA,IAC1C,OAAO;AACL,YAAM,MAAM,oBAAI,IAAqB,CAAC,QAA2B,CAAC;AAClE,WAAK,UAAU,IAAI,OAAO,GAAG;AAAA,IAC/B;AACA,WAAO,MAAM,KAAK,IAAI,OAAO,QAAQ;AAAA,EACvC;AAAA,EAEA,IAA6B,OAAU,UAAsC;AAC3E,SAAK,UAAU,IAAI,KAAK,GAAG,OAAO,QAA2B;AAAA,EAC/D;AAAA,EAEA,KAA8B,OAAU,MAAwB;AAC9D,SAAK,UAAU,IAAI,KAAK,GAAG,QAAQ,CAAC,aAAa;AAC/C,UAAI;AACF,iBAAS,IAAa;AAAA,MACxB,SAAS,KAAK;AACZ,gBAAQ,MAAM,oCAAoC,OAAO,KAAK,CAAC,KAAK,GAAG;AAAA,MACzE;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,QAAc;AACZ,SAAK,UAAU,MAAM;AAAA,EACvB;AACF;;;AC1BA,IAAM,YAAY;AAClB,IAAM,YAAY;AAElB,SAAS,WAAW,GAAW,GAAoB;AACjD,SAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE;AACpF;AAEA,IAAM,WAAN,MAAM,UAAS;AAAA,EAIb,YACW,QACA,OACT;AAFS;AACA;AAAA,EACR;AAAA,EANH,QAAiB,CAAC;AAAA,EAClB,WAA8B;AAAA,EAO9B,OAAO,OAAoB;AACzB,QAAI,KAAK,UAAU;AACjB,YAAM,MAAM,KAAK,cAAc,MAAM,MAAM;AAC3C,UAAI,QAAQ,IAAI;AACd,cAAM,QAAQ,KAAK,SAAS,GAAG;AAC/B,YAAI,MAAO,OAAM,OAAO,KAAK;AAC7B;AAAA,MACF;AACA,WAAK,MAAM,KAAK,KAAK;AACrB;AAAA,IACF;AAEA,SAAK,MAAM,KAAK,KAAK;AAErB,QAAI,KAAK,MAAM,SAAS,aAAa,KAAK,QAAQ,WAAW;AAC3D,WAAK,MAAM;AAAA,IACb;AAAA,EACF;AAAA,EAEA,OAAO,IAAqB;AAC1B,UAAM,MAAM,KAAK,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AACnD,QAAI,QAAQ,IAAI;AACd,WAAK,MAAM,OAAO,KAAK,CAAC;AACxB,aAAO;AAAA,IACT;AAEA,QAAI,KAAK,UAAU;AACjB,iBAAW,SAAS,KAAK,UAAU;AACjC,YAAI,MAAM,OAAO,EAAE,GAAG;AACpB,eAAK,gBAAgB;AACrB,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,MAAc,QAAwB;AAC1C,QAAI,CAAC,WAAW,KAAK,QAAQ,IAAI,EAAG;AAEpC,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,WAAW,KAAK,QAAQ,IAAI,GAAG;AACjC,eAAO,KAAK,KAAK,EAAE;AAAA,MACrB;AAAA,IACF;AAEA,QAAI,KAAK,UAAU;AACjB,iBAAW,SAAS,KAAK,UAAU;AACjC,cAAM,MAAM,MAAM,MAAM;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,cAAc,YAA4B;AAChD,UAAM,OAAO,KAAK,OAAO,IAAI,KAAK,OAAO,IAAI;AAC7C,UAAM,OAAO,KAAK,OAAO,IAAI,KAAK,OAAO,IAAI;AAE7C,UAAM,OAAO,WAAW,KAAK,KAAK,OAAO,KAAK,WAAW,IAAI,WAAW,KAAK;AAC7E,UAAM,QACJ,WAAW,KAAK,QAAQ,WAAW,IAAI,WAAW,KAAK,KAAK,OAAO,IAAI,KAAK,OAAO;AACrF,UAAM,MAAM,WAAW,KAAK,KAAK,OAAO,KAAK,WAAW,IAAI,WAAW,KAAK;AAC5E,UAAM,SACJ,WAAW,KAAK,QAAQ,WAAW,IAAI,WAAW,KAAK,KAAK,OAAO,IAAI,KAAK,OAAO;AAErF,QAAI,QAAQ,IAAK,QAAO;AACxB,QAAI,SAAS,IAAK,QAAO;AACzB,QAAI,QAAQ,OAAQ,QAAO;AAC3B,QAAI,SAAS,OAAQ,QAAO;AAE5B,WAAO;AAAA,EACT;AAAA,EAEQ,QAAc;AACpB,UAAM,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,KAAK;AAC5B,UAAM,QAAQ,IAAI;AAClB,UAAM,QAAQ,IAAI;AAClB,UAAM,IAAI,KAAK,QAAQ;AAEvB,SAAK,WAAW;AAAA,MACd,IAAI,UAAS,EAAE,GAAG,GAAG,GAAG,OAAO,GAAG,MAAM,GAAG,CAAC;AAAA,MAC5C,IAAI,UAAS,EAAE,GAAG,IAAI,OAAO,GAAG,GAAG,OAAO,GAAG,MAAM,GAAG,CAAC;AAAA,MACvD,IAAI,UAAS,EAAE,GAAG,GAAG,IAAI,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,CAAC;AAAA,MACvD,IAAI,UAAS,EAAE,GAAG,IAAI,OAAO,GAAG,IAAI,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,CAAC;AAAA,IACpE;AAEA,UAAM,YAAqB,CAAC;AAC5B,eAAW,QAAQ,KAAK,OAAO;AAC7B,YAAM,MAAM,KAAK,cAAc,KAAK,MAAM;AAC1C,UAAI,QAAQ,IAAI;AACd,cAAM,SAAS,KAAK,SAAS,GAAG;AAChC,YAAI,OAAQ,QAAO,OAAO,IAAI;AAAA,MAChC,OAAO;AACL,kBAAU,KAAK,IAAI;AAAA,MACrB;AAAA,IACF;AACA,SAAK,QAAQ;AAAA,EACf;AAAA,EAEQ,kBAAwB;AAC9B,QAAI,CAAC,KAAK,SAAU;AACpB,QAAI,aAAa,KAAK,MAAM;AAC5B,eAAW,SAAS,KAAK,UAAU;AACjC,UAAI,MAAM,SAAU;AACpB,oBAAc,MAAM,MAAM;AAAA,IAC5B;AACA,QAAI,cAAc,WAAW;AAC3B,iBAAW,SAAS,KAAK,UAAU;AACjC,aAAK,MAAM,KAAK,GAAG,MAAM,KAAK;AAAA,MAChC;AACA,WAAK,WAAW;AAAA,IAClB;AAAA,EACF;AACF;AAEO,IAAM,WAAN,MAAe;AAAA,EACZ;AAAA,EACA,QAAQ;AAAA,EACC;AAAA,EAEjB,YAAY,aAAqB;AAC/B,SAAK,cAAc;AACnB,SAAK,OAAO,IAAI,SAAS,aAAa,CAAC;AAAA,EACzC;AAAA,EAEA,IAAI,OAAe;AACjB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,OAAO,IAAY,QAAsB;AACvC,SAAK,KAAK,OAAO,EAAE,IAAI,OAAO,CAAC;AAC/B,SAAK;AAAA,EACP;AAAA,EAEA,OAAO,IAAkB;AACvB,QAAI,KAAK,KAAK,OAAO,EAAE,GAAG;AACxB,WAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEA,OAAO,IAAY,WAAyB;AAC1C,SAAK,OAAO,EAAE;AACd,SAAK,OAAO,IAAI,SAAS;AAAA,EAC3B;AAAA,EAEA,MAAM,MAAwB;AAC5B,UAAM,SAAmB,CAAC;AAC1B,SAAK,KAAK,MAAM,MAAM,MAAM;AAC5B,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,OAAwB;AACjC,WAAO,KAAK,MAAM,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC;AAAA,EAC1D;AAAA,EAEA,QAAc;AACZ,SAAK,OAAO,IAAI,SAAS,KAAK,aAAa,CAAC;AAC5C,SAAK,QAAQ;AAAA,EACf;AACF;;;AC7KA,IAAM,qBAAqB;AAEpB,SAAS,gBAAgB,UAAkB,WAA2B;AAC3E,SAAO,aAAa,sBAAsB,IAAI,sBAAsB;AACtE;AAEO,SAAS,eAAe,QAAuB,WAAkC;AACtF,MAAI,OAAO,UAAU,EAAG,QAAO,OAAO,MAAM;AAC5C,SAAO,IAAI,QAAQ,GAAG,OAAO,SAAS,GAAG,SAAS;AACpD;AAEA,SAAS,IAAI,QAAuB,OAAe,KAAa,WAAkC;AAChG,QAAM,QAAQ,OAAO,KAAK;AAC1B,QAAM,OAAO,OAAO,GAAG;AACvB,MAAI,CAAC,SAAS,CAAC,KAAM,QAAO,CAAC;AAE7B,MAAI,MAAM,SAAS,EAAG,QAAO,CAAC,OAAO,IAAI;AAEzC,MAAI,UAAU;AACd,MAAI,WAAW;AAEf,WAAS,IAAI,QAAQ,GAAG,IAAI,KAAK,KAAK;AACpC,UAAM,KAAK,OAAO,CAAC;AACnB,QAAI,CAAC,GAAI;AACT,UAAM,OAAO,sBAAsB,IAAI,OAAO,IAAI;AAClD,QAAI,OAAO,SAAS;AAClB,gBAAU;AACV,iBAAW;AAAA,IACb;AAAA,EACF;AAEA,MAAI,WAAW,UAAW,QAAO,CAAC,OAAO,IAAI;AAE7C,QAAM,OAAO,IAAI,QAAQ,OAAO,UAAU,SAAS;AACnD,QAAM,QAAQ,IAAI,QAAQ,UAAU,KAAK,SAAS;AAElD,SAAO,KAAK,OAAO,MAAM,MAAM,CAAC,CAAC;AACnC;AAEA,SAAS,sBAAsB,IAAW,WAAkB,SAAwB;AAClF,QAAM,KAAK,QAAQ,IAAI,UAAU;AACjC,QAAM,KAAK,QAAQ,IAAI,UAAU;AACjC,QAAM,QAAQ,KAAK,KAAK,KAAK;AAE7B,MAAI,UAAU,GAAG;AACf,UAAM,KAAK,GAAG,IAAI,UAAU;AAC5B,UAAM,KAAK,GAAG,IAAI,UAAU;AAC5B,WAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAAA,EACpC;AAEA,QAAM,MAAM,KAAK,IAAI,KAAK,GAAG,IAAI,KAAK,GAAG,IAAI,QAAQ,IAAI,UAAU,IAAI,QAAQ,IAAI,UAAU,CAAC;AAC9F,SAAO,MAAM,KAAK,KAAK,KAAK;AAC9B;AAEO,SAAS,iBAAiB,QAAuC;AACtE,MAAI,OAAO,SAAS,EAAG,QAAO,CAAC;AAE/B,MAAI,OAAO,WAAW,GAAG;AACvB,UAAM,KAAK,OAAO,CAAC;AACnB,UAAM,KAAK,OAAO,CAAC;AACnB,QAAI,CAAC,MAAM,CAAC,GAAI,QAAO,CAAC;AACxB,UAAM,MAAM,GAAG,IAAI,GAAG,KAAK;AAC3B,UAAM,MAAM,GAAG,IAAI,GAAG,KAAK;AAC3B,WAAO,CAAC,EAAE,OAAO,IAAI,KAAK,EAAE,GAAG,IAAI,GAAG,GAAG,GAAG,KAAK,EAAE,GAAG,IAAI,GAAG,GAAG,GAAG,KAAK,GAAG,CAAC;AAAA,EAC9E;AAEA,QAAM,WAA2B,CAAC;AAClC,QAAM,IAAI,OAAO;AAEjB,WAAS,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK;AAC9B,UAAM,KAAK,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC,CAAC;AACpC,UAAM,KAAK,OAAO,CAAC;AACnB,UAAM,KAAK,OAAO,IAAI,CAAC;AACvB,UAAM,KAAK,OAAO,KAAK,IAAI,IAAI,GAAG,IAAI,CAAC,CAAC;AACxC,QAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAI;AAE9B,UAAM,MAAa;AAAA,MACjB,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK;AAAA,MAC1B,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK;AAAA,IAC5B;AACA,UAAM,MAAa;AAAA,MACjB,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK;AAAA,MAC1B,GAAG,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK;AAAA,IAC5B;AAEA,aAAS,KAAK,EAAE,OAAO,IAAI,KAAK,KAAK,KAAK,GAAG,CAAC;AAAA,EAChD;AAEA,SAAO;AACT;;;ACjFA,IAAM,QAAQ,oBAAI,QAAyC;AAE3D,IAAM,gBAAgB;AAEtB,SAAS,kBAAkB,UAA0B,QAA8C;AACjG,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,QAAM,UAAU,oBAAI,IAAoB;AACxC,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,MAAM,SAAS,CAAC;AACtB,UAAM,IAAI,OAAO,CAAC;AAClB,QAAI,CAAC,OAAO,MAAM,OAAW;AAC7B,UAAM,IAAI,KAAK,IAAI,eAAe,KAAK,MAAM,IAAI,aAAa,IAAI,aAAa;AAC/E,QAAI,OAAO,QAAQ,IAAI,CAAC;AACxB,QAAI,CAAC,MAAM;AACT,aAAO,IAAI,OAAO;AAClB,cAAQ,IAAI,GAAG,IAAI;AAAA,IACrB;AAEA,SAAK,OAAO,IAAI,MAAM,GAAG,IAAI,MAAM,CAAC;AACpC,SAAK,cAAc,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,CAAC;AAAA,EACrF;AACA,SAAO,CAAC,GAAG,QAAQ,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,IAAI,OAAO,EAAE,OAAO,KAAK,EAAE;AACxE;AAEO,SAAS,sBAAsB,QAAyC;AAC7E,QAAM,WAAW,iBAAiB,OAAO,MAAM;AAC/C,QAAM,SAAmB,CAAC;AAE1B,aAAW,OAAO,UAAU;AAC1B,UAAM,KACH,gBAAgB,IAAI,MAAM,UAAU,OAAO,KAAK,IAC/C,gBAAgB,IAAI,IAAI,UAAU,OAAO,KAAK,KAChD;AACF,WAAO,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,OAAyB,EAAE,UAAU,QAAQ,SAAS,kBAAkB,UAAU,MAAM,EAAE;AAChG,QAAM,IAAI,QAAQ,IAAI;AACtB,SAAO;AACT;AAEO,SAAS,oBAAoB,QAAyC;AAC3E,QAAM,SAAS,MAAM,IAAI,MAAM;AAC/B,MAAI,OAAQ,QAAO;AACnB,SAAO,sBAAsB,MAAM;AACrC;AAEO,SAAS,yBAAyB,MAAqB,MAA2B;AACvF,MAAI,KAAK,SAAS,YAAY,KAAK,SAAS,SAAU;AACtD,MAAI,KAAK,WAAW,KAAK,OAAQ;AACjC,QAAM,OAAO,MAAM,IAAI,IAAI;AAC3B,MAAI,KAAM,OAAM,IAAI,MAAM,IAAI;AAChC;;;AChDO,IAAM,eAAN,MAAmB;AAAA,EAChB,WAAW,oBAAI,IAA2B;AAAA,EAC1C,MAAM,IAAI,SAA6B;AAAA,EACvC,gBAAgB,oBAAI,IAAoB;AAAA,EACxC,eAAe,IAAI,SAAS,EAAE,GAAG,MAAS,GAAG,MAAS,GAAG,KAAQ,GAAG,IAAO,CAAC;AAAA,EAC5E,cAAsC;AAAA,EACtC,YAAY,oBAAI,IAAoB;AAAA,EAE5C,IAAI,QAAgB;AAClB,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA,EAEA,WAAW,IAAoB;AAC7B,WAAO,KAAK,UAAU,IAAI,EAAE,KAAK;AAAA,EACnC;AAAA,EAEA,cAAc,OAAkC;AAC9C,SAAK,gBAAgB,IAAI,IAAI,KAAK;AAClC,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,SAA0B;AACxB,QAAI,KAAK,YAAa,QAAO,KAAK;AAClC,SAAK,cAAc,CAAC,GAAG,KAAK,SAAS,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM;AAC5D,YAAM,SAAS,KAAK,cAAc,IAAI,EAAE,OAAO,KAAK;AACpD,YAAM,SAAS,KAAK,cAAc,IAAI,EAAE,OAAO,KAAK;AACpD,UAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,aAAO,EAAE,SAAS,EAAE;AAAA,IACtB,CAAC;AACD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAQ,IAAuC;AAC7C,WAAO,KAAK,SAAS,IAAI,EAAE;AAAA,EAC7B;AAAA,EAEA,kBAAyC,MAAgD;AACvF,WAAO,KAAK,OAAO,EAAE;AAAA,MACnB,CAAC,OAAkD,GAAG,SAAS;AAAA,IACjE;AAAA,EACF;AAAA,EAEA,IAAI,SAA8B;AAChC,SAAK,cAAc;AACnB,SAAK,UAAU,IAAI,QAAQ,IAAI,CAAC;AAChC,SAAK,SAAS,IAAI,QAAQ,IAAI,OAAO;AACrC,UAAM,SAAS,iBAAiB,OAAO;AACvC,QAAI,OAAQ,MAAK,aAAa,OAAO,QAAQ,IAAI,MAAM;AACvD,SAAK,IAAI,KAAK,OAAO,OAAO;AAAA,EAC9B;AAAA,EAEA,OAAO,IAAY,SAAuC;AACxD,UAAM,WAAW,KAAK,SAAS,IAAI,EAAE;AACrC,QAAI,CAAC,SAAU;AACf,SAAK,cAAc;AACnB,SAAK,UAAU,IAAI,KAAK,KAAK,UAAU,IAAI,EAAE,KAAK,KAAK,CAAC;AAIxD,UAAM,UAAU,EAAE,GAAG,UAAU,GAAG,SAAS,IAAI,SAAS,IAAI,MAAM,SAAS,KAAK;AAEhF,QAAI,QAAQ,SAAS,YAAY,SAAS,SAAS,UAAU;AAC3D,+BAAyB,UAAU,OAAwB;AAC3D,2BAAqB,UAAU,OAAwB;AAAA,IACzD;AAEA,QAAI,QAAQ,SAAS,SAAS;AAC5B,YAAM,QAAQ;AACd,YAAM,qBAAqB,qBAAqB,MAAM,MAAM,MAAM,IAAI,MAAM,IAAI;AAAA,IAClF;AAEA,QAAI,QAAQ,SAAS,UAAU,UAAU,SAAS;AAChD,MAAC,QAAwB,OAAO,iBAAkB,QAAwB,IAAI;AAAA,IAChF;AAEA,SAAK,SAAS,IAAI,IAAI,OAAwB;AAE9C,UAAM,YAAY,iBAAiB,OAAwB;AAC3D,QAAI,WAAW;AACb,WAAK,aAAa,OAAO,IAAI,SAAS;AAAA,IACxC;AAEA,SAAK,IAAI,KAAK,UAAU,EAAE,UAAU,UAAU,SAAS,QAAyB,CAAC;AAAA,EACnF;AAAA,EAEA,OAAO,IAAkB;AACvB,UAAM,UAAU,KAAK,SAAS,IAAI,EAAE;AACpC,QAAI,CAAC,QAAS;AACd,SAAK,cAAc;AACnB,SAAK,UAAU,OAAO,EAAE;AAExB,SAAK,SAAS,OAAO,EAAE;AACvB,SAAK,aAAa,OAAO,EAAE;AAC3B,SAAK,IAAI,KAAK,UAAU,OAAO;AAAA,EACjC;AAAA,EAEA,QAAc;AACZ,SAAK,cAAc;AACnB,SAAK,UAAU,MAAM;AACrB,SAAK,SAAS,MAAM;AACpB,SAAK,aAAa,MAAM;AACxB,SAAK,IAAI,KAAK,SAAS,IAAI;AAAA,EAC7B;AAAA,EAEA,WAA4B;AAC1B,WAAO,KAAK,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,GAAG,EAAE;AAAA,EAC9C;AAAA,EAEA,aAAa,UAAiC;AAC5C,SAAK,cAAc;AACnB,SAAK,UAAU,MAAM;AACrB,SAAK,SAAS,MAAM;AACpB,SAAK,aAAa,MAAM;AACxB,eAAW,MAAM,UAAU;AACzB,WAAK,SAAS,IAAI,GAAG,IAAI,EAAE;AAC3B,WAAK,UAAU,IAAI,GAAG,IAAI,CAAC;AAC3B,YAAM,SAAS,iBAAiB,EAAE;AAClC,UAAI,OAAQ,MAAK,aAAa,OAAO,GAAG,IAAI,MAAM;AAClD,UAAI,GAAG,SAAS,UAAU;AACxB,8BAAsB,EAAE;AAAA,MAC1B;AACA,UAAI,GAAG,SAAS,WAAW,GAAG,SAAS,KAAK,CAAC,GAAG,oBAAoB;AAClE,WAAG,qBAAqB,qBAAqB,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI;AAAA,MACtE;AAAA,IACF;AACA,SAAK,IAAI,KAAK,SAAS,IAAI;AAC3B,eAAW,MAAM,UAAU;AACzB,WAAK,IAAI,KAAK,OAAO,EAAE;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,aAAa,IAAkB;AAC7B,UAAM,KAAK,KAAK,SAAS,IAAI,EAAE;AAC/B,QAAI,CAAC,GAAI;AACT,UAAM,WAAW,CAAC,GAAG,KAAK,SAAS,OAAO,CAAC,EAAE;AAAA,MAC3C,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,EAAE,OAAO;AAAA,IAC9C;AACA,QAAI,SAAS,WAAW,EAAG;AAC3B,UAAM,OAAO,KAAK,IAAI,GAAG,SAAS,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AACtD,QAAI,GAAG,UAAU,KAAM;AACvB,SAAK,OAAO,IAAI,EAAE,QAAQ,OAAO,EAAE,CAAC;AAAA,EACtC;AAAA,EAEA,WAAW,IAAkB;AAC3B,UAAM,KAAK,KAAK,SAAS,IAAI,EAAE;AAC/B,QAAI,CAAC,GAAI;AACT,UAAM,WAAW,CAAC,GAAG,KAAK,SAAS,OAAO,CAAC,EAAE;AAAA,MAC3C,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,EAAE,OAAO;AAAA,IAC9C;AACA,QAAI,SAAS,WAAW,EAAG;AAC3B,UAAM,OAAO,KAAK,IAAI,GAAG,SAAS,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AACtD,QAAI,GAAG,UAAU,KAAM;AACvB,SAAK,OAAO,IAAI,EAAE,QAAQ,OAAO,EAAE,CAAC;AAAA,EACtC;AAAA,EAEA,aAAa,IAAkB;AAC7B,UAAM,KAAK,KAAK,SAAS,IAAI,EAAE;AAC/B,QAAI,CAAC,GAAI;AACT,UAAM,SAAS,CAAC,GAAG,KAAK,SAAS,OAAO,CAAC,EACtC,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,EACtC,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AACrC,UAAM,MAAM,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AAC/C,QAAI,MAAM,KAAK,OAAO,OAAO,SAAS,EAAG;AACzC,UAAM,OAAO,OAAO,MAAM,CAAC;AAC3B,QAAI,CAAC,KAAM;AACX,UAAM,MAAM,GAAG;AACf,UAAM,QAAQ,KAAK;AACnB,SAAK,OAAO,IAAI,EAAE,QAAQ,MAAM,CAAC;AACjC,SAAK,OAAO,KAAK,IAAI,EAAE,QAAQ,IAAI,CAAC;AAAA,EACtC;AAAA,EAEA,aAAa,IAAkB;AAC7B,UAAM,KAAK,KAAK,SAAS,IAAI,EAAE;AAC/B,QAAI,CAAC,GAAI;AACT,UAAM,SAAS,CAAC,GAAG,KAAK,SAAS,OAAO,CAAC,EACtC,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,EACtC,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AACrC,UAAM,MAAM,OAAO,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AAC/C,QAAI,OAAO,EAAG;AACd,UAAM,OAAO,OAAO,MAAM,CAAC;AAC3B,QAAI,CAAC,KAAM;AACX,UAAM,MAAM,GAAG;AACf,UAAM,QAAQ,KAAK;AACnB,SAAK,OAAO,IAAI,EAAE,QAAQ,MAAM,CAAC;AACjC,SAAK,OAAO,KAAK,IAAI,EAAE,QAAQ,IAAI,CAAC;AAAA,EACtC;AAAA,EAEA,UAAU,MAA+B;AACvC,UAAM,MAAM,KAAK,aAAa,MAAM,IAAI;AACxC,UAAM,WAA4B,CAAC;AACnC,eAAW,MAAM,KAAK;AACpB,YAAM,KAAK,KAAK,SAAS,IAAI,EAAE;AAC/B,UAAI,GAAI,UAAS,KAAK,EAAE;AAAA,IAC1B;AACA,WAAO,SAAS,KAAK,CAAC,GAAG,MAAM;AAC7B,YAAM,SAAS,KAAK,cAAc,IAAI,EAAE,OAAO,KAAK;AACpD,YAAM,SAAS,KAAK,cAAc,IAAI,EAAE,OAAO,KAAK;AACpD,UAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,aAAO,EAAE,SAAS,EAAE;AAAA,IACtB,CAAC;AAAA,EACH;AAAA,EAEA,WAAW,OAA+B;AACxC,WAAO,KAAK,UAAU,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC;AAAA,EAC9D;AAAA,EAEA,GACE,OACA,UACY;AACZ,WAAO,KAAK,IAAI,GAAG,OAAO,QAAQ;AAAA,EACpC;AAAA,EAEA,SAAS,UAAkC;AACzC,UAAM,SAAS;AAAA,MACb,KAAK,IAAI,GAAG,OAAO,QAAQ;AAAA,MAC3B,KAAK,IAAI,GAAG,UAAU,QAAQ;AAAA,MAC9B,KAAK,IAAI,GAAG,UAAU,QAAQ;AAAA,MAC9B,KAAK,IAAI,GAAG,SAAS,QAAQ;AAAA,IAC/B;AACA,WAAO,MAAM,OAAO,QAAQ,CAAC,OAAO,GAAG,CAAC;AAAA,EAC1C;AACF;;;ACvOA,IAAMC,SAAQ,oBAAI,QAA2C;AAEtD,SAAS,uBAAuB,OAA0C;AAC/E,QAAM,MAAMA,OAAM,IAAI,KAAK;AAC3B,MAAI,IAAK,QAAO;AAChB,QAAM,WAAgC;AAAA,IACpC,cACE,MAAM,SAAS,IACV,MAAM,sBAAsB,qBAAqB,MAAM,MAAM,MAAM,IAAI,MAAM,IAAI,IAClF;AAAA,IACN,cAAc,qBAAqB,MAAM,MAAM,MAAM,IAAI,MAAM,MAAM,CAAC;AAAA,IACtE,YAAY,qBAAqB,MAAM,MAAM,MAAM,IAAI,MAAM,MAAM,CAAC;AAAA,EACtE;AACA,EAAAA,OAAM,IAAI,OAAO,QAAQ;AACzB,SAAO;AACT;;;ACrBA,IAAM,iBAAiB,oBAAI,IAAI,CAAC,QAAQ,QAAQ,SAAS,QAAQ,OAAO,CAAC;AAElE,SAAS,WAAW,SAAiC;AAC1D,SAAO,eAAe,IAAI,QAAQ,IAAI;AACxC;AAEO,SAAS,iBAAiB,SAA+B;AAC9D,MAAI,EAAE,UAAU,UAAU;AACxB,UAAM,IAAI,MAAM,mCAAmC,QAAQ,IAAI,eAAe;AAAA,EAChF;AACA,SAAO;AAAA,IACL,GAAG,QAAQ,SAAS,IAAI,QAAQ,KAAK,IAAI;AAAA,IACzC,GAAG,QAAQ,SAAS,IAAI,QAAQ,KAAK,IAAI;AAAA,EAC3C;AACF;AAEO,SAAS,oBAAoB,QAAgB,cAA4B;AAC9E,QAAM,KAAK,OAAO,IAAI,OAAO,IAAI;AACjC,QAAM,KAAK,OAAO,IAAI,OAAO,IAAI;AACjC,QAAM,KAAK,aAAa,IAAI;AAC5B,QAAM,KAAK,aAAa,IAAI;AAE5B,MAAI,OAAO,KAAK,OAAO,EAAG,QAAO,EAAE,GAAG,IAAI,GAAG,GAAG;AAEhD,QAAM,QAAQ,OAAO,IAAI;AACzB,QAAM,QAAQ,OAAO,IAAI;AAEzB,QAAM,SAAS,OAAO,IAAI,QAAQ,KAAK,IAAI,EAAE,IAAI;AACjD,QAAM,SAAS,OAAO,IAAI,QAAQ,KAAK,IAAI,EAAE,IAAI;AACjD,QAAM,QAAQ,KAAK,IAAI,QAAQ,MAAM;AAErC,SAAO;AAAA,IACL,GAAG,KAAK,KAAK;AAAA,IACb,GAAG,KAAK,KAAK;AAAA,EACf;AACF;AAEO,SAAS,eACd,OACA,OACA,WACA,WACA,QACsB;AACtB,MAAI,UAAgC;AACpC,MAAI,cAAc;AAElB,aAAW,MAAM,MAAM,OAAO,GAAG;AAC/B,QAAI,CAAC,WAAW,EAAE,EAAG;AACrB,QAAI,aAAa,GAAG,OAAO,UAAW;AACtC,QAAI,UAAU,CAAC,OAAO,EAAE,EAAG;AAE3B,UAAM,SAAS,iBAAiB,EAAE;AAClC,QAAI,CAAC,OAAQ;AAEb,UAAM,OAAO,aAAa,OAAO,MAAM;AACvC,QAAI,QAAQ,aAAa,OAAO,aAAa;AAC3C,gBAAU;AACV,oBAAc;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,aAAa,OAAc,QAAwB;AAC1D,QAAM,WAAW,KAAK,IAAI,OAAO,GAAG,KAAK,IAAI,MAAM,GAAG,OAAO,IAAI,OAAO,CAAC,CAAC;AAC1E,QAAM,WAAW,KAAK,IAAI,OAAO,GAAG,KAAK,IAAI,MAAM,GAAG,OAAO,IAAI,OAAO,CAAC,CAAC;AAC1E,SAAO,KAAK,MAAM,MAAM,IAAI,UAAU,MAAM,IAAI,QAAQ;AAC1D;AAEO,SAAS,gBAAgB,WAAmB,OAAqC;AACtF,SAAO,MACJ,kBAAkB,OAAO,EACzB,OAAO,CAAC,MAAM,EAAE,aAAa,cAAc,aAAa,EAAE,WAAW,cAAc,SAAS;AACjG;AAEO,SAAS,iBACd,OACA,OAC8B;AAC9B,MAAI,CAAC,MAAM,eAAe,CAAC,MAAM,UAAW,QAAO;AAEnD,QAAM,UAAiC,CAAC;AAExC,MAAI,MAAM,aAAa;AACrB,UAAM,KAAK,MAAM,QAAQ,MAAM,YAAY,SAAS;AACpD,QAAI,IAAI;AACN,YAAM,SAAS,iBAAiB,EAAE;AAClC,cAAQ,OAAO;AACf,cAAQ,WAAW;AAAA,IACrB;AAAA,EACF;AAEA,MAAI,MAAM,WAAW;AACnB,UAAM,KAAK,MAAM,QAAQ,MAAM,UAAU,SAAS;AAClD,QAAI,IAAI;AACN,cAAQ,KAAK,iBAAiB,EAAE;AAAA,IAClC;AAAA,EACF;AAEA,SAAO,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,UAAU;AACrD;;;AC9FO,SAAS,mBAAmB,QAAuB,UAAmC;AAC3F,MAAI,YAAY,EAAG,QAAO,EAAE,WAAW,CAAC,GAAG,aAAa,CAAC,EAAE;AAE3D,QAAM,YAAsB,CAAC;AAC7B,QAAM,SAAS,KAAK,MAAM,OAAO,OAAO,QAAQ,IAAI;AACpD,QAAM,OAAO,KAAK,KAAK,OAAO,OAAO,QAAQ,IAAI;AACjD,WAAS,IAAI,QAAQ,KAAK,MAAM,KAAK,UAAU;AAC7C,cAAU,KAAK,CAAC;AAAA,EAClB;AAEA,QAAM,cAAwB,CAAC;AAC/B,QAAM,SAAS,KAAK,MAAM,OAAO,OAAO,QAAQ,IAAI;AACpD,QAAM,OAAO,KAAK,KAAK,OAAO,OAAO,QAAQ,IAAI;AACjD,WAAS,IAAI,QAAQ,KAAK,MAAM,KAAK,UAAU;AAC7C,gBAAY,KAAK,CAAC;AAAA,EACpB;AAEA,SAAO,EAAE,WAAW,YAAY;AAClC;AA6EO,SAAS,iBACd,KACA,QACA,UACA,aACA,aACA,SACM;AACN,MAAI,YAAY,EAAG;AAEnB,QAAM,EAAE,WAAW,YAAY,IAAI,mBAAmB,QAAQ,QAAQ;AAEtE,MAAI,KAAK;AACT,MAAI,cAAc;AAClB,MAAI,YAAY;AAChB,MAAI,cAAc;AAClB,MAAI,UAAU;AAEd,aAAW,KAAK,WAAW;AACzB,QAAI,OAAO,GAAG,OAAO,IAAI;AACzB,QAAI,OAAO,GAAG,OAAO,IAAI;AAAA,EAC3B;AACA,aAAW,KAAK,aAAa;AAC3B,QAAI,OAAO,OAAO,MAAM,CAAC;AACzB,QAAI,OAAO,OAAO,MAAM,CAAC;AAAA,EAC3B;AAEA,MAAI,OAAO;AACX,MAAI,QAAQ;AACd;AAEO,SAAS,cACd,KACA,QACA,UACA,aACA,aACA,aACA,SACM;AACN,MAAI,YAAY,EAAG;AAGnB,QAAM,cAAc,gBAAgB,WAAW,CAAC,KAAK,KAAK,IAAI;AAC9D,QAAM,MAAM,WAAW,KAAK,IAAI,WAAW;AAC3C,QAAM,MAAM,WAAW,KAAK,IAAI,WAAW;AAC3C,QAAM,MAAM,WAAW,KAAK,IAAI,KAAK,KAAK,IAAI,WAAW;AACzD,QAAM,MAAM,WAAW,KAAK,IAAI,KAAK,KAAK,IAAI,WAAW;AACzD,QAAM,MAAM,WAAW,KAAK,IAAK,IAAI,KAAK,KAAM,IAAI,WAAW;AAC/D,QAAM,MAAM,WAAW,KAAK,IAAK,IAAI,KAAK,KAAM,IAAI,WAAW;AAC/D,QAAM,MAAM,WAAW,KAAK,IAAI,KAAK,KAAK,WAAW;AACrD,QAAM,MAAM,WAAW,KAAK,IAAI,KAAK,KAAK,WAAW;AACrD,QAAM,MAAM,WAAW,KAAK,IAAK,IAAI,KAAK,KAAM,IAAI,WAAW;AAC/D,QAAM,MAAM,WAAW,KAAK,IAAK,IAAI,KAAK,KAAM,IAAI,WAAW;AAC/D,QAAM,MAAM,WAAW,KAAK,IAAK,IAAI,KAAK,KAAM,IAAI,WAAW;AAC/D,QAAM,MAAM,WAAW,KAAK,IAAK,IAAI,KAAK,KAAM,IAAI,WAAW;AAE/D,MAAI,KAAK;AACT,MAAI,cAAc;AAClB,MAAI,YAAY;AAChB,MAAI,cAAc;AAClB,MAAI,UAAU;AAGd,MAAI,gBAAgB,UAAU;AAC5B,UAAM,OAAO,KAAK,KAAK,CAAC,IAAI;AAC5B,UAAM,OAAO,MAAM;AAEnB,UAAM,WAAW,KAAK,OAAO,OAAO,OAAO,YAAY,IAAI;AAC3D,UAAM,SAAS,KAAK,MAAM,OAAO,OAAO,YAAY,IAAI;AACxD,UAAM,WAAW,KAAK,OAAO,OAAO,OAAO,QAAQ,IAAI;AACvD,UAAM,SAAS,KAAK,MAAM,OAAO,OAAO,QAAQ,IAAI;AAEpD,aAAS,MAAM,UAAU,OAAO,QAAQ,OAAO;AAC7C,YAAM,OAAO,MAAM,MAAM,IAAI,OAAO,IAAI;AACxC,eAAS,MAAM,UAAU,OAAO,QAAQ,OAAO;AAC7C,cAAM,KAAK,MAAM,OAAO;AACxB,cAAM,KAAK,MAAM;AACjB,YAAI,OAAO,KAAK,KAAK,KAAK,GAAG;AAC7B,YAAI,OAAO,KAAK,KAAK,KAAK,GAAG;AAC7B,YAAI,OAAO,KAAK,KAAK,KAAK,GAAG;AAC7B,YAAI,OAAO,KAAK,KAAK,KAAK,GAAG;AAC7B,YAAI,OAAO,KAAK,KAAK,KAAK,GAAG;AAC7B,YAAI,OAAO,KAAK,KAAK,KAAK,GAAG;AAC7B,YAAI,UAAU;AAAA,MAChB;AAAA,IACF;AAAA,EACF,OAAO;AACL,UAAM,OAAO,KAAK,KAAK,CAAC,IAAI;AAC5B,UAAM,OAAO,MAAM;AAEnB,UAAM,WAAW,KAAK,OAAO,OAAO,OAAO,YAAY,IAAI;AAC3D,UAAM,SAAS,KAAK,MAAM,OAAO,OAAO,YAAY,IAAI;AACxD,UAAM,WAAW,KAAK,OAAO,OAAO,OAAO,QAAQ,IAAI;AACvD,UAAM,SAAS,KAAK,MAAM,OAAO,OAAO,QAAQ,IAAI;AAEpD,aAAS,MAAM,UAAU,OAAO,QAAQ,OAAO;AAC7C,YAAM,OAAO,MAAM,MAAM,IAAI,OAAO,IAAI;AACxC,eAAS,MAAM,UAAU,OAAO,QAAQ,OAAO;AAC7C,cAAM,KAAK,MAAM;AACjB,cAAM,KAAK,MAAM,OAAO;AACxB,YAAI,OAAO,KAAK,KAAK,KAAK,GAAG;AAC7B,YAAI,OAAO,KAAK,KAAK,KAAK,GAAG;AAC7B,YAAI,OAAO,KAAK,KAAK,KAAK,GAAG;AAC7B,YAAI,OAAO,KAAK,KAAK,KAAK,GAAG;AAC7B,YAAI,OAAO,KAAK,KAAK,KAAK,GAAG;AAC7B,YAAI,OAAO,KAAK,KAAK,KAAK,GAAG;AAC7B,YAAI,UAAU;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,OAAO;AACX,MAAI,QAAQ;AACd;AAQO,SAAS,kBACd,UACA,aACA,aACA,aACA,SACA,OACoB;AACpB,MAAI;AACJ,MAAI;AACJ,MAAI,gBAAgB,UAAU;AAC5B,YAAQ,KAAK,KAAK,CAAC,IAAI;AACvB,YAAQ,IAAI;AAAA,EACd,OAAO;AACL,YAAQ,IAAI;AACZ,YAAQ,KAAK,KAAK,CAAC,IAAI;AAAA,EACzB;AAEA,QAAM,MAAM,KAAK,KAAK,QAAQ,KAAK;AACnC,QAAM,MAAM,KAAK,KAAK,QAAQ,KAAK;AACnC,MAAI,OAAO,KAAK,OAAO,EAAG,QAAO;AAEjC,MAAI;AACJ,MAAI,OAAO,oBAAoB,aAAa;AAC1C,aAAS,IAAI,gBAAgB,KAAK,GAAG;AAAA,EACvC,WAAW,OAAO,aAAa,aAAa;AAC1C,UAAM,KAAK,SAAS,cAAc,QAAQ;AAC1C,OAAG,QAAQ;AACX,OAAG,SAAS;AACZ,aAAS;AAAA,EACX,OAAO;AACL,WAAO;AAAA,EACT;AAEA,QAAM,KAAK,OAAO,WAAW,IAAI;AACjC,MAAI,CAAC,GAAI,QAAO;AAEhB,KAAG,MAAM,OAAO,KAAK;AACrB,KAAG,UAAU;AACb,KAAG,KAAK,GAAG,GAAG,OAAO,KAAK;AAC1B,KAAG,KAAK;AAER,QAAM,cAAc,gBAAgB,WAAW,CAAC,KAAK,KAAK,IAAI;AAC9D,QAAM,MAAM,WAAW,KAAK,IAAI,WAAW;AAC3C,QAAM,MAAM,WAAW,KAAK,IAAI,WAAW;AAC3C,QAAM,MAAM,WAAW,KAAK,IAAI,KAAK,KAAK,IAAI,WAAW;AACzD,QAAM,MAAM,WAAW,KAAK,IAAI,KAAK,KAAK,IAAI,WAAW;AACzD,QAAM,MAAM,WAAW,KAAK,IAAK,IAAI,KAAK,KAAM,IAAI,WAAW;AAC/D,QAAM,MAAM,WAAW,KAAK,IAAK,IAAI,KAAK,KAAM,IAAI,WAAW;AAC/D,QAAM,MAAM,WAAW,KAAK,IAAI,KAAK,KAAK,WAAW;AACrD,QAAM,MAAM,WAAW,KAAK,IAAI,KAAK,KAAK,WAAW;AACrD,QAAM,MAAM,WAAW,KAAK,IAAK,IAAI,KAAK,KAAM,IAAI,WAAW;AAC/D,QAAM,MAAM,WAAW,KAAK,IAAK,IAAI,KAAK,KAAM,IAAI,WAAW;AAC/D,QAAM,MAAM,WAAW,KAAK,IAAK,IAAI,KAAK,KAAM,IAAI,WAAW;AAC/D,QAAM,MAAM,WAAW,KAAK,IAAK,IAAI,KAAK,KAAM,IAAI,WAAW;AAE/D,KAAG,cAAc;AACjB,KAAG,YAAY;AACf,KAAG,cAAc;AACjB,KAAG,UAAU;AAEb,MAAI,gBAAgB,UAAU;AAC5B,UAAM,OAAO;AACb,UAAM,OAAO,MAAM;AACnB,aAAS,MAAM,IAAI,OAAO,GAAG,OAAO;AAClC,YAAM,OAAO,MAAM,MAAM,IAAI,OAAO,IAAI;AACxC,eAAS,MAAM,IAAI,OAAO,GAAG,OAAO;AAClC,cAAM,KAAK,MAAM,OAAO;AACxB,cAAM,KAAK,MAAM;AACjB,WAAG,OAAO,KAAK,KAAK,KAAK,GAAG;AAC5B,WAAG,OAAO,KAAK,KAAK,KAAK,GAAG;AAC5B,WAAG,OAAO,KAAK,KAAK,KAAK,GAAG;AAC5B,WAAG,OAAO,KAAK,KAAK,KAAK,GAAG;AAC5B,WAAG,OAAO,KAAK,KAAK,KAAK,GAAG;AAC5B,WAAG,OAAO,KAAK,KAAK,KAAK,GAAG;AAC5B,WAAG,UAAU;AAAA,MACf;AAAA,IACF;AAAA,EACF,OAAO;AACL,UAAM,OAAO;AACb,UAAM,OAAO,MAAM;AACnB,aAAS,MAAM,IAAI,OAAO,GAAG,OAAO;AAClC,YAAM,OAAO,MAAM,MAAM,IAAI,OAAO,IAAI;AACxC,eAAS,MAAM,IAAI,OAAO,GAAG,OAAO;AAClC,cAAM,KAAK,MAAM;AACjB,cAAM,KAAK,MAAM,OAAO;AACxB,WAAG,OAAO,KAAK,KAAK,KAAK,GAAG;AAC5B,WAAG,OAAO,KAAK,KAAK,KAAK,GAAG;AAC5B,WAAG,OAAO,KAAK,KAAK,KAAK,GAAG;AAC5B,WAAG,OAAO,KAAK,KAAK,KAAK,GAAG;AAC5B,WAAG,OAAO,KAAK,KAAK,KAAK,GAAG;AAC5B,WAAG,OAAO,KAAK,KAAK,KAAK,GAAG;AAC5B,WAAG,UAAU;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,KAAG,OAAO;AACV,SAAO,EAAE,QAAQ,OAAO,MAAM;AAChC;AAEO,SAAS,mBACd,KACA,QACA,UACA,MACM;AACN,QAAM,EAAE,OAAO,MAAM,IAAI;AAEzB,QAAM,WAAW,KAAK,MAAM,OAAO,OAAO,KAAK,IAAI;AACnD,QAAM,SAAS,KAAK,KAAK,OAAO,OAAO,KAAK,IAAI;AAChD,QAAM,WAAW,KAAK,MAAM,OAAO,OAAO,KAAK,IAAI;AACnD,QAAM,SAAS,KAAK,KAAK,OAAO,OAAO,KAAK,IAAI;AAEhD,WAAS,MAAM,UAAU,OAAO,QAAQ,OAAO;AAC7C,aAAS,MAAM,UAAU,OAAO,QAAQ,OAAO;AAC7C,UAAI,UAAU,KAAK,QAA6B,MAAM,OAAO,MAAM,OAAO,OAAO,KAAK;AAAA,IACxF;AAAA,EACF;AACF;;;ACtVA,SAAS,aACP,KACA,KACA,aAC0B;AAC1B,MAAI,gBAAgB,UAAU;AAC5B,WAAO,EAAE,GAAG,OAAO,OAAO,MAAM,MAAM,GAAG,GAAG,IAAI;AAAA,EAClD;AACA,SAAO,EAAE,GAAG,KAAK,GAAG,OAAO,OAAO,MAAM,MAAM,EAAE;AAClD;AAEA,SAAS,aAAa,GAAW,GAAW,aAAuC;AACjF,MAAI,gBAAgB,UAAU;AAC5B,WAAO,EAAE,KAAK,KAAK,KAAK,IAAI,MAAM,GAAG,KAAK,EAAE;AAAA,EAC9C;AACA,SAAO,EAAE,KAAK,GAAG,KAAK,KAAK,KAAK,IAAI,MAAM,EAAE;AAC9C;AAEA,SAAS,cACP,KACA,KACA,UACA,aACO;AACP,MAAI,gBAAgB,UAAU;AAC5B,UAAM,OAAO,KAAK,KAAK,CAAC,IAAI;AAC5B,UAAM,OAAO,MAAM;AACnB,UAAM,UAAU,MAAM,MAAM,IAAI,OAAO,IAAI;AAC3C,WAAO,EAAE,GAAG,MAAM,OAAO,SAAS,GAAG,MAAM,KAAK;AAAA,EAClD;AACA,QAAM,OAAO,KAAK,KAAK,CAAC,IAAI;AAC5B,QAAM,OAAO,MAAM;AACnB,QAAM,UAAU,MAAM,MAAM,IAAI,OAAO,IAAI;AAC3C,SAAO,EAAE,GAAG,MAAM,MAAM,GAAG,MAAM,OAAO,QAAQ;AAClD;AAEA,SAAS,cACP,GACA,GACA,UACA,aACU;AACV,MAAI,gBAAgB,UAAU;AAC5B,UAAM,OAAO,KAAK,KAAK,CAAC,IAAI;AAC5B,UAAM,OAAO,MAAM;AACnB,UAAM,MAAM,KAAK,MAAM,IAAI,IAAI;AAC/B,UAAM,UAAU,MAAM,MAAM,IAAI,OAAO,IAAI;AAC3C,WAAO,EAAE,KAAK,KAAK,OAAO,IAAI,WAAW,IAAI,GAAG,IAAI;AAAA,EACtD;AACA,QAAM,OAAO,KAAK,KAAK,CAAC,IAAI;AAC5B,QAAM,OAAO,MAAM;AACnB,QAAM,MAAM,KAAK,MAAM,IAAI,IAAI;AAC/B,QAAM,UAAU,MAAM,MAAM,IAAI,OAAO,IAAI;AAC3C,SAAO,EAAE,KAAK,KAAK,KAAK,OAAO,IAAI,WAAW,IAAI,EAAE;AACtD;AAEA,SAAS,iBACP,SACA,SACA,GACA,aACA,UACS;AACT,QAAM,QAAiB,CAAC;AACxB,WAAS,KAAK,CAAC,GAAG,MAAM,GAAG,MAAM;AAC/B,UAAM,OAAO,KAAK,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AACjC,UAAM,OAAO,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC;AAChC,aAAS,KAAK,MAAM,MAAM,MAAM,MAAM;AACpC,YAAM,OAAO,UAAU;AACvB,YAAM,OAAO,UAAU;AACvB,YAAM,MAAM,aAAa,MAAM,MAAM,WAAW;AAChD,YAAM,KAAK,cAAc,IAAI,KAAK,IAAI,KAAK,UAAU,WAAW,CAAC;AAAA,IACnE;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,eACd,GACA,GACA,UACA,aACQ;AACR,QAAM,OAAO,cAAc,EAAE,GAAG,EAAE,GAAG,UAAU,WAAW;AAC1D,QAAM,OAAO,cAAc,EAAE,GAAG,EAAE,GAAG,UAAU,WAAW;AAC1D,QAAM,QAAQ,aAAa,KAAK,KAAK,KAAK,KAAK,WAAW;AAC1D,QAAM,QAAQ,aAAa,KAAK,KAAK,KAAK,KAAK,WAAW;AAC1D,QAAM,KAAK,MAAM,IAAI,MAAM;AAC3B,QAAM,KAAK,MAAM,IAAI,MAAM;AAC3B,QAAM,KAAK,CAAC,KAAK;AACjB,SAAO,KAAK,IAAI,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC;AAC1D;AAEO,SAAS,oBACd,QACA,aACA,UACA,aACS;AACT,QAAM,IAAI,KAAK,MAAM,WAAW;AAChC,QAAM,MAAM,cAAc,OAAO,GAAG,OAAO,GAAG,UAAU,WAAW;AACnE,QAAM,OAAO,aAAa,IAAI,KAAK,IAAI,KAAK,WAAW;AACvD,MAAI,KAAK,GAAG;AACV,WAAO,CAAC,cAAc,IAAI,KAAK,IAAI,KAAK,UAAU,WAAW,CAAC;AAAA,EAChE;AACA,SAAO,iBAAiB,KAAK,GAAG,KAAK,GAAG,GAAG,aAAa,QAAQ;AAClE;AAEO,SAAS,kBACd,QACA,OACA,aACA,UACA,aACS;AACT,QAAM,IAAI,KAAK,MAAM,WAAW;AAChC,QAAM,MAAM,cAAc,OAAO,GAAG,OAAO,GAAG,UAAU,WAAW;AACnE,QAAM,OAAO,aAAa,IAAI,KAAK,IAAI,KAAK,WAAW;AACvD,QAAM,cAAc,cAAc,IAAI,KAAK,IAAI,KAAK,UAAU,WAAW;AAEzE,MAAI,KAAK,EAAG,QAAO,CAAC,WAAW;AAE/B,QAAM,eAAe,gBAAgB,WAAW,KAAK,KAAK,IAAI;AAC9D,QAAM,OAAO,KAAK,KAAK;AACvB,QAAM,eAAe,KAAK,OAAO,QAAQ,gBAAgB,IAAI,IAAI,OAAO;AAExE,QAAM,YAAY,KAAK,KAAK,IAAI;AAChC,QAAM,QAAiB,CAAC,WAAW;AAEnC,WAAS,KAAK,CAAC,GAAG,MAAM,GAAG,MAAM;AAC/B,UAAM,OAAO,KAAK,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AACjC,UAAM,OAAO,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC;AAChC,aAAS,KAAK,MAAM,MAAM,MAAM,MAAM;AACpC,UAAI,OAAO,KAAK,OAAO,EAAG;AAC1B,YAAM,OAAO,KAAK,IAAI;AACtB,YAAM,OAAO,KAAK,IAAI;AACtB,YAAM,QAAQ;AAAA,QACZ,aAAa,MAAM,MAAM,WAAW,EAAE;AAAA,QACtC,aAAa,MAAM,MAAM,WAAW,EAAE;AAAA,QACtC;AAAA,QACA;AAAA,MACF;AAEA,YAAM,KAAK,MAAM,IAAI,YAAY;AACjC,YAAM,KAAK,MAAM,IAAI,YAAY;AACjC,UAAI,OAAO,KAAK,MAAM,IAAI,EAAE,IAAI;AAChC,UAAI,OAAO,KAAK,GAAI,SAAQ,IAAI,KAAK;AACrC,UAAI,OAAO,CAAC,KAAK,GAAI,SAAQ,IAAI,KAAK;AAEtC,UAAI,KAAK,IAAI,IAAI,KAAK,WAAW;AAC/B,cAAM,KAAK,KAAK;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,kBACd,QACA,OACA,aACA,UACA,aACS;AACT,QAAM,IAAI,KAAK,MAAM,WAAW;AAChC,QAAM,MAAM,cAAc,OAAO,GAAG,OAAO,GAAG,UAAU,WAAW;AACnE,QAAM,OAAO,aAAa,IAAI,KAAK,IAAI,KAAK,WAAW;AACvD,QAAM,cAAc,cAAc,IAAI,KAAK,IAAI,KAAK,UAAU,WAAW;AAEzE,MAAI,KAAK,EAAG,QAAO,CAAC,WAAW;AAE/B,QAAM,eAAe,gBAAgB,WAAW,KAAK,KAAK,IAAI;AAC9D,QAAM,OAAO,KAAK,KAAK;AACvB,QAAM,eAAe,KAAK,OAAO,QAAQ,gBAAgB,IAAI,IAAI,OAAO;AAExE,QAAM,MAAM,KAAK,IAAI,YAAY;AACjC,QAAM,MAAM,KAAK,IAAI,YAAY;AACjC,QAAM,WAAW,KAAK,KAAK,CAAC,IAAI;AAChC,QAAM,aAAa,IAAI;AACvB,QAAM,YAAY,WAAW,MAAM;AACnC,QAAM,QAAiB,CAAC;AAExB,WAAS,KAAK,CAAC,GAAG,MAAM,GAAG,MAAM;AAC/B,UAAM,OAAO,KAAK,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AACjC,UAAM,OAAO,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC;AAChC,aAAS,KAAK,MAAM,MAAM,MAAM,MAAM;AACpC,YAAM,OAAO,KAAK,IAAI;AACtB,YAAM,OAAO,KAAK,IAAI;AACtB,YAAM,QAAQ;AAAA,QACZ,aAAa,MAAM,MAAM,WAAW,EAAE;AAAA,QACtC,aAAa,MAAM,MAAM,WAAW,EAAE;AAAA,QACtC;AAAA,QACA;AAAA,MACF;AAEA,YAAM,KAAK,MAAM,IAAI,YAAY;AACjC,YAAM,KAAK,MAAM,IAAI,YAAY;AACjC,YAAM,QAAQ,KAAK,MAAM,KAAK;AAC9B,YAAM,OAAO,KAAK,IAAI,CAAC,KAAK,MAAM,KAAK,GAAG;AAE1C,UAAI,SAAS,CAAC,WAAW,OAAO,SAAS,aAAa,WAAW,OAAO,QAAQ,WAAW;AACzF,cAAM,KAAK,KAAK;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,oBACd,QACA,aACA,UACA,aACS;AACT,QAAM,IAAI,KAAK,MAAM,WAAW;AAChC,QAAM,MAAM,cAAc,OAAO,GAAG,OAAO,GAAG,UAAU,WAAW;AACnE,QAAM,OAAO,aAAa,IAAI,KAAK,IAAI,KAAK,WAAW;AACvD,QAAM,cAAc,cAAc,IAAI,KAAK,IAAI,KAAK,UAAU,WAAW;AAEzE,MAAI,KAAK,EAAG,QAAO,CAAC,WAAW;AAE/B,QAAM,WAAW,KAAK,KAAK,CAAC,IAAI;AAChC,QAAM,WAAY,IAAI,WAAY;AAClC,QAAM,QAAiB,CAAC;AAExB,WAAS,KAAK,CAAC,GAAG,MAAM,GAAG,MAAM;AAC/B,UAAM,OAAO,KAAK,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AACjC,UAAM,OAAO,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC;AAChC,aAAS,KAAK,MAAM,MAAM,MAAM,MAAM;AACpC,YAAM,OAAO,KAAK,IAAI;AACtB,YAAM,OAAO,KAAK,IAAI;AACtB,YAAM,QAAQ;AAAA,QACZ,aAAa,MAAM,MAAM,WAAW,EAAE;AAAA,QACtC,aAAa,MAAM,MAAM,WAAW,EAAE;AAAA,QACtC;AAAA,QACA;AAAA,MACF;AAEA,UACE,KAAK,IAAI,MAAM,IAAI,YAAY,CAAC,KAAK,YACrC,KAAK,IAAI,MAAM,IAAI,YAAY,CAAC,KAAK,UACrC;AACA,cAAM,KAAK,KAAK;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,YACd,KACA,IACA,IACA,UACA,aACM;AACN,QAAM,cAAc,gBAAgB,WAAW,KAAK,KAAK,IAAI;AAC7D,MAAI,OAAO,KAAK,WAAW,KAAK,IAAI,WAAW,GAAG,KAAK,WAAW,KAAK,IAAI,WAAW,CAAC;AACvF,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,IAAI,cAAe,KAAK,KAAK,IAAK;AACxC,QAAI,OAAO,KAAK,WAAW,KAAK,IAAI,CAAC,GAAG,KAAK,WAAW,KAAK,IAAI,CAAC,CAAC;AAAA,EACrE;AACA,MAAI,UAAU;AAChB;;;AChPA,IAAM,oBAAoB,oBAAI,IAAI,CAAC,QAAQ,QAAQ,MAAM,CAAC;AAC1D,IAAM,mBAAmB;AACzB,IAAM,kBAAkB,KAAK,KAAK;AAE3B,IAAM,kBAAN,MAAsB;AAAA,EACnB,QAA6B;AAAA,EAC7B,aAAa,oBAAI,IAAuD;AAAA,EACxE,cAAmC;AAAA,EACnC,eAAgE;AAAA,EAChE,SAAwB;AAAA,EACxB,aAA8C;AAAA,EAC9C,eAAmC;AAAA,EACnC,kBAAkB;AAAA,EAClB,qBACN;AAAA,EAEF,SAAS,OAA2B;AAClC,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,eAAe,UAA4B;AACzC,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,gBAAgB,UAAwD;AACtE,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,UAAU,QAAsB;AAC9B,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,cAAc,GAAW,GAAiB;AACxC,SAAK,aAAa,EAAE,GAAG,EAAE;AAAA,EAC3B;AAAA,EAEA,sBACE,QACM;AACN,SAAK,qBAAqB;AAAA,EAC5B;AAAA,EAEA,aAAa,SAAiC;AAC5C,WAAO,kBAAkB,IAAI,QAAQ,IAAI;AAAA,EAC3C;AAAA,EAEA,oBAAoB,KAA+B,SAA8B;AAC/E,YAAQ,QAAQ,MAAM;AAAA,MACpB,KAAK;AACH,aAAK,aAAa,KAAK,OAAO;AAC9B;AAAA,MACF,KAAK;AACH,aAAK,YAAY,KAAK,OAAO;AAC7B;AAAA,MACF,KAAK;AACH,aAAK,YAAY,KAAK,OAAO;AAC7B;AAAA,MACF,KAAK;AACH,aAAK,YAAY,KAAK,OAAO;AAC7B;AAAA,MACF,KAAK;AACH,aAAK,WAAW,KAAK,OAAO;AAC5B;AAAA,MACF,KAAK;AACH,aAAK,eAAe,KAAK,OAAO;AAChC;AAAA,IACJ;AAAA,EACF;AAAA,EAEQ,aAAa,KAA+B,QAA6B;AAC/E,QAAI,OAAO,OAAO,SAAS,EAAG;AAE9B,QAAI,KAAK;AACT,QAAI,UAAU,OAAO,SAAS,GAAG,OAAO,SAAS,CAAC;AAClD,QAAI,cAAc,OAAO;AACzB,QAAI,UAAU;AACd,QAAI,WAAW;AACf,QAAI,cAAc,OAAO;AAEzB,UAAM,OAAO,oBAAoB,MAAM;AACvC,QAAI,KAAK,SAAS;AAChB,iBAAW,UAAU,KAAK,SAAS;AACjC,YAAI,YAAY,OAAO;AACvB,YAAI,OAAO,OAAO,IAAI;AAAA,MACxB;AAAA,IACF,OAAO;AACL,eAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;AAC7C,cAAM,MAAM,KAAK,SAAS,CAAC;AAC3B,cAAM,IAAI,KAAK,OAAO,CAAC;AACvB,YAAI,CAAC,OAAO,MAAM,OAAW;AAC7B,YAAI,YAAY;AAChB,YAAI,UAAU;AACd,YAAI,OAAO,IAAI,MAAM,GAAG,IAAI,MAAM,CAAC;AACnC,YAAI,cAAc,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,CAAC;AAClF,YAAI,OAAO;AAAA,MACb;AAAA,IACF;AAEA,QAAI,QAAQ;AAAA,EACd;AAAA,EAEQ,YAAY,KAA+B,OAA2B;AAC5E,UAAM,WAAW,uBAAuB,KAAK;AAC7C,UAAM,EAAE,YAAY,SAAS,IAAI,KAAK,mBAAmB,OAAO,QAAQ;AAExE,QAAI,KAAK;AACT,QAAI,cAAc,MAAM;AACxB,QAAI,YAAY,MAAM;AACtB,QAAI,UAAU;AAEd,QAAI,MAAM,eAAe,MAAM,WAAW;AACxC,UAAI,YAAY,CAAC,GAAG,CAAC,CAAC;AAAA,IACxB;AAEA,QAAI,UAAU;AACd,QAAI,OAAO,WAAW,GAAG,WAAW,CAAC;AAErC,QAAI,MAAM,SAAS,GAAG;AACpB,YAAM,KAAK,SAAS;AACpB,UAAI,IAAI;AACN,YAAI,iBAAiB,GAAG,GAAG,GAAG,GAAG,SAAS,GAAG,SAAS,CAAC;AAAA,MACzD;AAAA,IACF,OAAO;AACL,UAAI,OAAO,SAAS,GAAG,SAAS,CAAC;AAAA,IACnC;AACA,QAAI,OAAO;AAEX,SAAK,gBAAgB,KAAK,OAAO,UAAU,SAAS,UAAU;AAC9D,QAAI,QAAQ;AAAA,EACd;AAAA,EAEQ,gBACN,KACA,OACA,KACA,OACM;AACN,QAAI,UAAU;AACd,QAAI,OAAO,IAAI,GAAG,IAAI,CAAC;AACvB,QAAI;AAAA,MACF,IAAI,IAAI,mBAAmB,KAAK,IAAI,QAAQ,eAAe;AAAA,MAC3D,IAAI,IAAI,mBAAmB,KAAK,IAAI,QAAQ,eAAe;AAAA,IAC7D;AACA,QAAI;AAAA,MACF,IAAI,IAAI,mBAAmB,KAAK,IAAI,QAAQ,eAAe;AAAA,MAC3D,IAAI,IAAI,mBAAmB,KAAK,IAAI,QAAQ,eAAe;AAAA,IAC7D;AACA,QAAI,UAAU;AACd,QAAI,YAAY,MAAM;AACtB,QAAI,KAAK;AAAA,EACX;AAAA,EAEQ,mBACN,OACA,UAIA;AACA,QAAI,aAAa,MAAM;AACvB,QAAI,WAAW,MAAM;AAErB,QAAI,CAAC,KAAK,MAAO,QAAO,EAAE,YAAY,SAAS;AAE/C,QAAI,MAAM,aAAa;AACrB,YAAM,KAAK,KAAK,MAAM,QAAQ,MAAM,YAAY,SAAS;AACzD,UAAI,IAAI;AACN,cAAM,SAAS,iBAAiB,EAAE;AAClC,YAAI,QAAQ;AACV,gBAAM,eAAe,SAAS;AAC9B,gBAAM,YAAY;AAAA,YAChB,GAAG,MAAM,KAAK,IAAI,KAAK,IAAI,YAAY,IAAI;AAAA,YAC3C,GAAG,MAAM,KAAK,IAAI,KAAK,IAAI,YAAY,IAAI;AAAA,UAC7C;AACA,uBAAa,oBAAoB,QAAQ,SAAS;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,WAAW;AACnB,YAAM,KAAK,KAAK,MAAM,QAAQ,MAAM,UAAU,SAAS;AACvD,UAAI,IAAI;AACN,cAAM,SAAS,iBAAiB,EAAE;AAClC,YAAI,QAAQ;AACV,gBAAM,eAAe,SAAS;AAG9B,gBAAM,YAAY;AAAA,YAChB,GAAG,MAAM,GAAG,IAAI,KAAK,IAAI,YAAY,IAAI;AAAA,YACzC,GAAG,MAAM,GAAG,IAAI,KAAK,IAAI,YAAY,IAAI;AAAA,UAC3C;AACA,qBAAW,oBAAoB,QAAQ,SAAS;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,YAAY,SAAS;AAAA,EAChC;AAAA,EAEQ,YAAY,KAA+B,OAA2B;AAC5E,QAAI,KAAK;AAET,QAAI,MAAM,cAAc,QAAQ;AAC9B,UAAI,YAAY,MAAM;AACtB,WAAK,cAAc,KAAK,KAAK;AAAA,IAC/B;AAEA,QAAI,MAAM,cAAc,GAAG;AACzB,UAAI,cAAc,MAAM;AACxB,UAAI,YAAY,MAAM;AACtB,WAAK,gBAAgB,KAAK,KAAK;AAAA,IACjC;AAEA,QAAI,QAAQ;AAAA,EACd;AAAA,EAEQ,cAAc,KAA+B,OAA2B;AAC9E,YAAQ,MAAM,OAAO;AAAA,MACnB,KAAK;AACH,YAAI,SAAS,MAAM,SAAS,GAAG,MAAM,SAAS,GAAG,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3E;AAAA,MACF,KAAK,WAAW;AACd,cAAM,KAAK,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI;AAC7C,cAAM,KAAK,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI;AAC7C,YAAI,UAAU;AACd,YAAI,QAAQ,IAAI,IAAI,MAAM,KAAK,IAAI,GAAG,MAAM,KAAK,IAAI,GAAG,GAAG,GAAG,KAAK,KAAK,CAAC;AACzE,YAAI,KAAK;AACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBAAgB,KAA+B,OAA2B;AAChF,YAAQ,MAAM,OAAO;AAAA,MACnB,KAAK;AACH,YAAI,WAAW,MAAM,SAAS,GAAG,MAAM,SAAS,GAAG,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC;AAC7E;AAAA,MACF,KAAK,WAAW;AACd,cAAM,KAAK,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI;AAC7C,cAAM,KAAK,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI;AAC7C,YAAI,UAAU;AACd,YAAI,QAAQ,IAAI,IAAI,MAAM,KAAK,IAAI,GAAG,MAAM,KAAK,IAAI,GAAG,GAAG,GAAG,KAAK,KAAK,CAAC;AACzE,YAAI,OAAO;AACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,WAAW,KAA+B,MAAyB;AACzE,UAAM,aAAa,KAAK;AACxB,QAAI,CAAC,WAAY;AAEjB,UAAM,MAAM,KAAK;AACjB,QAAI,CAAC,IAAK;AAEV,UAAM,SACJ,KAAK,uBACJ,MAAM;AACL,YAAM,UAAU,IAAI,cAAc,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AAChD,YAAM,cAAc,IAAI,cAAc,EAAE,GAAG,WAAW,GAAG,GAAG,WAAW,EAAE,CAAC;AAC1E,aAAO;AAAA,QACL,MAAM,QAAQ;AAAA,QACd,MAAM,QAAQ;AAAA,QACd,MAAM,YAAY;AAAA,QAClB,MAAM,YAAY;AAAA,MACpB;AAAA,IACF,GAAG;AAEL,QAAI,KAAK,aAAa,OAAO;AAC3B,YAAM,MAAM,OAAO,qBAAqB,cAAc,mBAAmB;AACzE,YAAM,QAAQ,IAAI,OAAO;AACzB,YAAM,OAAO,KAAK;AAAA,QAChB,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,MACF;AACA,UAAI,MAAM;AACR,2BAAmB,KAAK,QAAQ,KAAK,UAAU,IAAI;AAAA,MACrD,OAAO;AACL;AAAA,UACE;AAAA,UACA;AAAA,UACA,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,QACP;AAAA,MACF;AAAA,IACF,OAAO;AACL;AAAA,QACE;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,eAAe,KAA+B,UAAiC;AACrF,UAAM,OAAO,KAAK,OAAO,kBAAkB,MAAM,EAAE,CAAC;AACpD,QAAI,QAAQ,KAAK,aAAa,OAAO;AACnC,WAAK,kBAAkB,KAAK,UAAU,KAAK,UAAU,KAAK,cAAc;AACxE;AAAA,IACF;AAEA,SAAK,wBAAwB,KAAK,QAAQ;AAAA,EAC5C;AAAA,EAEQ,wBAAwB,KAA+B,UAAiC;AAC9F,UAAM,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI,SAAS;AAClC,UAAM,IAAI,SAAS;AAEnB,QAAI,KAAK;AACT,QAAI,cAAc,SAAS;AAC3B,QAAI,YAAY,SAAS;AACzB,QAAI,cAAc,SAAS;AAC3B,QAAI,YAAY,SAAS;AAEzB,YAAQ,SAAS,eAAe;AAAA,MAC9B,KAAK;AACH,YAAI,UAAU;AACd,YAAI,IAAI,IAAI,IAAI,GAAG,GAAG,KAAK,KAAK,CAAC;AACjC,YAAI,KAAK;AACT,YAAI,OAAO;AACX,YAAI,SAAS,cAAc,QAAQ,SAAS,aAAa,GAAG;AAC1D,eAAK,mBAAmB,KAAK,IAAI,IAAI,GAAG,SAAS,UAAU;AAAA,QAC7D;AACA;AAAA,MAEF,KAAK;AACH,YAAI,SAAS,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,GAAG,CAAC;AACzC,YAAI,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,GAAG,CAAC;AAC3C;AAAA,MAEF,KAAK,QAAQ;AACX,cAAM,YAAY,KAAK,KAAK,GAAG;AAC/B,YAAI,UAAU;AACd,YAAI,OAAO,IAAI,EAAE;AACjB,YAAI,IAAI,IAAI,IAAI,GAAG,SAAS,QAAQ,WAAW,SAAS,QAAQ,SAAS;AACzE,YAAI,UAAU;AACd,YAAI,KAAK;AACT,YAAI,OAAO;AACX;AAAA,MACF;AAAA,MAEA,KAAK,QAAQ;AACX,cAAM,QAAQ,IAAI;AAClB,cAAM,MAAM,KAAK,IAAI,SAAS,KAAK;AACnC,cAAM,MAAM,KAAK,IAAI,SAAS,KAAK;AACnC,cAAM,QAAQ,CAAC,MAAM;AACrB,cAAM,QAAQ,MAAM;AAEpB,YAAI,UAAU;AACd,YAAI,OAAO,KAAK,OAAO,KAAK,KAAK;AACjC,YAAI,OAAO,KAAK,IAAI,MAAM,OAAO,KAAK,IAAI,MAAM,KAAK;AACrD,YAAI,OAAO,KAAK,IAAI,MAAM,OAAO,KAAK,IAAI,MAAM,KAAK;AACrD,YAAI,OAAO,KAAK,OAAO,KAAK,KAAK;AACjC,YAAI,UAAU;AACd,YAAI,KAAK;AACT,YAAI,OAAO;AACX;AAAA,MACF;AAAA,IACF;AAEA,QAAI,QAAQ;AAAA,EACd;AAAA,EAEQ,kBACN,KACA,UACA,UACA,aACM;AACN,UAAM,WAAW,KAAK,KAAK,CAAC,IAAI;AAChC,UAAM,cAAc,SAAS,SAAS;AACtC,UAAM,SAAS,SAAS;AAExB,QAAI;AACJ,YAAQ,SAAS,eAAe;AAAA,MAC9B,KAAK;AACH,gBAAQ,oBAAoB,QAAQ,aAAa,UAAU,WAAW;AACtE;AAAA,MACF,KAAK;AACH,gBAAQ,kBAAkB,QAAQ,SAAS,OAAO,aAAa,UAAU,WAAW;AACpF;AAAA,MACF,KAAK;AACH,gBAAQ,kBAAkB,QAAQ,SAAS,OAAO,aAAa,UAAU,WAAW;AACpF;AAAA,MACF,KAAK;AACH,gBAAQ,oBAAoB,QAAQ,aAAa,UAAU,WAAW;AACtE;AAAA,IACJ;AAEA,QAAI,KAAK;AACT,QAAI,cAAc,SAAS;AAE3B,QAAI,UAAU;AACd,eAAW,QAAQ,OAAO;AACxB,kBAAY,KAAK,KAAK,GAAG,KAAK,GAAG,UAAU,WAAW;AAAA,IACxD;AACA,QAAI,YAAY,SAAS;AACzB,QAAI,KAAK;AAET,QAAI,UAAU;AACd,eAAW,QAAQ,OAAO;AACxB,kBAAY,KAAK,KAAK,GAAG,KAAK,GAAG,UAAU,WAAW;AAAA,IACxD;AACA,QAAI,cAAc,SAAS;AAC3B,QAAI,YAAY,SAAS;AACzB,QAAI,OAAO;AAEX;AACE,UAAI,cAAc,KAAK,IAAI,SAAS,UAAU,KAAK,CAAC;AACpD,UAAI,UAAU;AACd,kBAAY,KAAK,OAAO,GAAG,OAAO,GAAG,UAAU,WAAW;AAC1D,UAAI,YAAY,SAAS;AACzB,UAAI,KAAK;AACT,UAAI,cAAc,SAAS;AAC3B,UAAI,YAAY,SAAS;AACzB,UAAI,OAAO;AAAA,IACb;AAEA,QACE,SAAS,kBAAkB,YAC3B,SAAS,cAAc,QACvB,SAAS,aAAa,GACtB;AACA,YAAM,IAAI,SAAS;AACnB,WAAK,mBAAmB,KAAK,OAAO,GAAG,OAAO,GAAG,GAAG,SAAS,UAAU;AAAA,IACzE;AAEA,QAAI,QAAQ;AAAA,EACd;AAAA,EAEQ,mBACN,KACA,IACA,IACA,GACA,MACM;AACN,UAAM,cAAc,IAAI;AAExB,QAAI,KAAK;AACT,QAAI,cAAc;AAElB,QAAI,UAAU;AACd,QAAI,YAAY,CAAC,GAAG,CAAC,CAAC;AACtB,QAAI,cAAc;AAClB,QAAI,YAAY;AAChB,QAAI,OAAO,IAAI,EAAE;AACjB,QAAI,OAAO,KAAK,GAAG,EAAE;AACrB,QAAI,OAAO;AACX,QAAI,YAAY,CAAC,CAAC;AAElB,UAAM,QAAQ,GAAG,KAAK,MAAM,IAAI,CAAC;AACjC,UAAM,WAAW,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,CAAC;AACpD,QAAI,OAAO,QAAQ,QAAQ;AAC3B,QAAI,YAAY;AAChB,QAAI,eAAe;AACnB,UAAM,QAAQ,KAAK,IAAI;AACvB,UAAM,QAAQ,KAAK;AAEnB,UAAM,UAAU,IAAI,YAAY,KAAK;AACrC,UAAM,OAAO;AACb,UAAM,OAAO;AACb,UAAM,QAAQ,QAAQ,QAAQ,OAAO;AACrC,UAAM,QAAQ,WAAW,OAAO;AAEhC,QAAI,YAAY;AAChB,QAAI,UAAU;AACd,QAAI,UAAU,QAAQ,QAAQ,GAAG,QAAQ,OAAO,OAAO,OAAO,CAAC;AAC/D,QAAI,KAAK;AAET,QAAI,YAAY;AAChB,QAAI,SAAS,OAAO,OAAO,QAAQ,IAAI;AAEvC,QAAI,QAAQ;AAAA,EACd;AAAA,EAEQ,YAAY,KAA+B,OAA2B;AAC5E,QAAI,KAAK,WAAW,IAAI,MAAM,GAAG,MAAM,UAAU;AAC/C,WAAK,uBAAuB,KAAK,KAAK;AACtC;AAAA,IACF;AACA,UAAM,MAAM,KAAK,SAAS,MAAM,GAAG;AACnC,QAAI,CAAC,IAAK;AACV,QAAI;AAAA,MACF;AAAA,MACA,MAAM,SAAS;AAAA,MACf,MAAM,SAAS;AAAA,MACf,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,IACb;AAAA,EACF;AAAA,EAEQ,uBAAuB,KAA+B,OAA2B;AACvF,UAAM,EAAE,GAAG,EAAE,IAAI,MAAM;AACvB,UAAM,EAAE,GAAG,EAAE,IAAI,MAAM;AACvB,QAAI,KAAK;AACT,QAAI,YAAY;AAChB,QAAI,SAAS,GAAG,GAAG,GAAG,CAAC;AACvB,QAAI,cAAc;AAClB,QAAI,YAAY;AAChB,QAAI,WAAW,GAAG,GAAG,GAAG,CAAC;AAEzB,UAAM,QAAQ,KAAK,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC;AACvC,UAAM,KAAK,IAAI,IAAI;AACnB,UAAM,KAAK,IAAI,IAAI;AACnB,QAAI,cAAc;AAClB,QAAI,YAAY;AAChB,QAAI,UAAU;AACd,QAAI,IAAI,IAAI,IAAI,QAAQ,GAAG,GAAG,KAAK,KAAK,CAAC;AACzC,QAAI,OAAO,KAAK,QAAQ,GAAG,KAAK,QAAQ,CAAC;AACzC,QAAI,OAAO,KAAK,QAAQ,GAAG,KAAK,QAAQ,CAAC;AACzC,QAAI,OAAO;AACX,QAAI,QAAQ;AAAA,EACd;AAAA,EAEQ,WACN,UACA,aACA,aACA,aACA,SACA,OACoB;AACpB,UAAM,MAAM,GAAG,QAAQ,IAAI,WAAW,IAAI,WAAW,IAAI,WAAW,IAAI,OAAO,IAAI,KAAK;AACxF,QAAI,KAAK,oBAAoB,OAAO,KAAK,cAAc;AACrD,aAAO,KAAK;AAAA,IACd;AACA,UAAM,OAAO,kBAAkB,UAAU,aAAa,aAAa,aAAa,SAAS,KAAK;AAC9F,QAAI,MAAM;AACR,WAAK,eAAe;AACpB,WAAK,kBAAkB;AAAA,IACzB;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,SAAS,KAAoD;AACnE,UAAM,SAAS,KAAK,WAAW,IAAI,GAAG;AACtC,QAAI,QAAQ;AACV,UAAI,WAAW,SAAU,QAAO;AAChC,UAAI,kBAAkB,iBAAkB,QAAO,OAAO,WAAW,SAAS;AAC1E,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,IAAI,MAAM;AACtB,QAAI,MAAM;AACV,SAAK,WAAW,IAAI,KAAK,GAAG;AAC5B,QAAI,SAAS,MAAM;AACjB,WAAK,cAAc;AAEnB,UAAI,OAAO,sBAAsB,aAAa;AAC5C,0BAAkB,GAAG,EAClB,KAAK,CAAC,WAAW;AAChB,eAAK,WAAW,IAAI,KAAK,MAAM;AAC/B,eAAK,cAAc;AAAA,QACrB,CAAC,EACA,MAAM,MAAM;AAAA,QAEb,CAAC;AAAA,MACL;AAAA,IACF;AACA,QAAI,UAAU,CAAC,UAAU;AAEvB,WAAK,WAAW,IAAI,KAAK,QAAQ;AACjC,WAAK,eAAe,KAAK,KAAK;AAC9B,WAAK,cAAc;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AACF;;;AC7kBO,IAAM,yBAAyB;AAyD/B,SAAS,aAAa,OAAmC;AAC9D,SAAO;AAAA,IACL,IAAI,SAAS,QAAQ;AAAA,IACrB,MAAM;AAAA,IACN,UAAU,MAAM,YAAY,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACzC,QAAQ,MAAM,UAAU;AAAA,IACxB,QAAQ,MAAM,UAAU;AAAA,IACxB,SAAS,MAAM,WAAW;AAAA,IAC1B,QAAQ,MAAM;AAAA,IACd,OAAO,MAAM,SAAS;AAAA,IACtB,OAAO,MAAM,SAAS;AAAA,IACtB,SAAS,MAAM,WAAW;AAAA,EAC5B;AACF;AAEO,SAAS,WAAW,OAA+B;AACxD,SAAO;AAAA,IACL,IAAI,SAAS,MAAM;AAAA,IACnB,MAAM;AAAA,IACN,UAAU,MAAM;AAAA,IAChB,QAAQ,MAAM,UAAU;AAAA,IACxB,QAAQ,MAAM,UAAU;AAAA,IACxB,SAAS,MAAM,WAAW;AAAA,IAC1B,MAAM,MAAM,QAAQ,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,IACrC,MAAM,iBAAiB,MAAM,QAAQ,EAAE;AAAA,IACvC,iBAAiB,MAAM,mBAAmB;AAAA,IAC1C,WAAW,MAAM,aAAa;AAAA,IAC9B,UAAU,MAAM,YAAY;AAAA,EAC9B;AACF;AAEO,SAAS,YAAY,OAAiC;AAC3D,QAAM,OAAO,MAAM,QAAQ;AAC3B,QAAM,SAAuB;AAAA,IAC3B,IAAI,SAAS,OAAO;AAAA,IACpB,MAAM;AAAA,IACN,UAAU,MAAM,YAAY,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACzC,QAAQ,MAAM,UAAU;AAAA,IACxB,QAAQ,MAAM,UAAU;AAAA,IACxB,SAAS,MAAM,WAAW;AAAA,IAC1B,MAAM,MAAM;AAAA,IACZ,IAAI,MAAM;AAAA,IACV;AAAA,IACA,OAAO,MAAM,SAAS;AAAA,IACtB,OAAO,MAAM,SAAS;AAAA,IACtB,oBAAoB,qBAAqB,MAAM,MAAM,MAAM,IAAI,IAAI;AAAA,EACrE;AACA,MAAI,MAAM,YAAa,QAAO,cAAc,MAAM;AAClD,MAAI,MAAM,UAAW,QAAO,YAAY,MAAM;AAC9C,SAAO;AACT;AAEO,SAAS,YAAY,OAAiC;AAC3D,SAAO;AAAA,IACL,IAAI,SAAS,OAAO;AAAA,IACpB,MAAM;AAAA,IACN,UAAU,MAAM;AAAA,IAChB,QAAQ,MAAM,UAAU;AAAA,IACxB,QAAQ,MAAM,UAAU;AAAA,IACxB,SAAS,MAAM,WAAW;AAAA,IAC1B,MAAM,MAAM;AAAA,IACZ,KAAK,MAAM;AAAA,EACb;AACF;AAEO,SAAS,kBAAkB,OAA+B;AAC/D,QAAM,KAAkB;AAAA,IACtB,IAAI,SAAS,MAAM;AAAA,IACnB,MAAM;AAAA,IACN,UAAU,MAAM;AAAA,IAChB,QAAQ,MAAM,UAAU;AAAA,IACxB,QAAQ,MAAM,UAAU;AAAA,IACxB,SAAS,MAAM,WAAW;AAAA,IAC1B,MAAM,MAAM;AAAA,EACd;AACA,MAAI,MAAM,MAAO,IAAG,QAAQ,MAAM;AAClC,MAAI,MAAM,YAAa,IAAG,cAAc,MAAM;AAC9C,SAAO;AACT;AAWO,SAAS,YAAY,OAAiC;AAC3D,SAAO;AAAA,IACL,IAAI,SAAS,OAAO;AAAA,IACpB,MAAM;AAAA,IACN,UAAU,MAAM;AAAA,IAChB,QAAQ,MAAM,UAAU;AAAA,IACxB,QAAQ,MAAM,UAAU;AAAA,IACxB,SAAS,MAAM,WAAW;AAAA,IAC1B,OAAO,MAAM,SAAS;AAAA,IACtB,MAAM,MAAM;AAAA,IACZ,aAAa,MAAM,eAAe;AAAA,IAClC,aAAa,MAAM,eAAe;AAAA,IAClC,WAAW,MAAM,aAAa;AAAA,EAChC;AACF;AAWO,SAAS,WAAW,OAA+B;AACxD,SAAO;AAAA,IACL,IAAI,SAAS,MAAM;AAAA,IACnB,MAAM;AAAA,IACN,UAAU,MAAM,YAAY,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACzC,QAAQ,MAAM,UAAU;AAAA,IACxB,QAAQ,MAAM,UAAU;AAAA,IACxB,SAAS,MAAM,WAAW;AAAA,IAC1B,UAAU,MAAM,YAAY;AAAA,IAC5B,gBAAgB,MAAM,kBAAkB;AAAA,IACxC,UAAU,MAAM,YAAY;AAAA,IAC5B,aAAa,MAAM,eAAe;AAAA,IAClC,aAAa,MAAM,eAAe;AAAA,IAClC,SAAS,MAAM,WAAW;AAAA,EAC5B;AACF;AAEO,SAAS,WAAW,OAA+B;AACxD,SAAO;AAAA,IACL,IAAI,SAAS,MAAM;AAAA,IACnB,MAAM;AAAA,IACN,UAAU,MAAM;AAAA,IAChB,QAAQ,MAAM,UAAU;AAAA,IACxB,QAAQ,MAAM,UAAU;AAAA,IACxB,SAAS,MAAM,WAAW;AAAA,IAC1B,MAAM,MAAM,QAAQ,EAAE,GAAG,KAAK,GAAG,GAAG;AAAA,IACpC,MAAM,MAAM,QAAQ;AAAA,IACpB,UAAU,MAAM,YAAY;AAAA,IAC5B,OAAO,MAAM,SAAS;AAAA,IACtB,WAAW,MAAM,aAAa;AAAA,EAChC;AACF;AAeO,SAAS,eAAe,OAAuC;AACpE,SAAO;AAAA,IACL,IAAI,SAAS,UAAU;AAAA,IACvB,MAAM;AAAA,IACN,UAAU,MAAM;AAAA,IAChB,QAAQ,MAAM,UAAU;AAAA,IACxB,QAAQ,MAAM,UAAU;AAAA,IACxB,SAAS,MAAM,WAAW;AAAA,IAC1B,eAAe,MAAM;AAAA,IACrB,QAAQ,MAAM;AAAA,IACd,OAAO,MAAM,SAAS;AAAA,IACtB,WAAW,MAAM,aAAa;AAAA,IAC9B,aAAa,MAAM,eAAe;AAAA,IAClC,aAAa,MAAM,eAAe;AAAA,IAClC,SAAS,MAAM,WAAW;AAAA,IAC1B,aAAa,MAAM;AAAA,IACnB,YAAY,MAAM;AAAA,EACpB;AACF;;;ACxPO,SAAS,aAAmB;AACjC,WAAS,YAAY,MAAM;AAC7B;AAEO,SAAS,eAAqB;AACnC,WAAS,YAAY,QAAQ;AAC/B;AAEO,SAAS,kBAAwB;AACtC,WAAS,YAAY,WAAW;AAClC;AAEO,SAAS,sBAA4B;AAC1C,WAAS,YAAY,eAAe;AACtC;AAEO,SAAS,YAAY,MAAoB;AAC9C,QAAM,MAAM,OAAO,aAAa;AAChC,MAAI,CAAC,OAAO,IAAI,eAAe,EAAG;AAElC,QAAM,QAAQ,IAAI,WAAW,CAAC;AAC9B,MAAI,MAAM,UAAW;AAErB,QAAM,OAAO,SAAS,cAAc,MAAM;AAC1C,OAAK,MAAM,WAAW,GAAG,IAAI;AAC7B,MAAI;AACF,UAAM,iBAAiB,IAAI;AAAA,EAC7B,QAAQ;AACN,SAAK,YAAY,MAAM,gBAAgB,CAAC;AACxC,UAAM,WAAW,IAAI;AAAA,EACvB;AACF;AAEO,SAAS,mBAAkC;AAChD,QAAM,QAAQ,CAAC,QAAyB;AACtC,QAAI;AACF,aAAO,SAAS,kBAAkB,GAAG;AAAA,IACvC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,MAAM,MAAM;AAAA,IAClB,QAAQ,MAAM,QAAQ;AAAA,IACtB,WAAW,MAAM,WAAW;AAAA,IAC5B,eAAe,MAAM,eAAe;AAAA,EACtC;AACF;;;ACpDA,IAAM,iBAAiB;AACvB,IAAM,cAAc;AAQpB,IAAM,iBAAiC;AAAA,EACrC,EAAE,OAAO,KAAK,QAAQ,QAAQ,SAAS,OAAO;AAAA,EAC9C,EAAE,OAAO,KAAK,QAAQ,UAAU,SAAS,SAAS;AAAA,EAClD,EAAE,OAAO,KAAK,QAAQ,aAAa,SAAS,YAAY;AAAA,EACxD,EAAE,OAAO,KAAK,QAAQ,iBAAiB,SAAS,gBAAgB;AAClE;AAOO,IAAM,4BAA8C;AAAA,EACzD,EAAE,OAAO,SAAS,MAAM,GAAG;AAAA,EAC3B,EAAE,OAAO,UAAU,MAAM,GAAG;AAAA,EAC5B,EAAE,OAAO,SAAS,MAAM,GAAG;AAAA,EAC3B,EAAE,OAAO,WAAW,MAAM,GAAG;AAC/B;AAEO,IAAM,cAAN,MAAkB;AAAA,EACf,KAA4B;AAAA,EAC5B,SAA6B;AAAA,EAC7B,oBAAyC;AAAA,EAChC;AAAA,EAEjB,YAAY,iBAAoC;AAC9C,SAAK,kBAAkB,mBAAmB;AAAA,EAC5C;AAAA,EAEA,KAAK,QAA2B;AAC9B,SAAK,KAAK;AACV,SAAK,SAAS;AACd,SAAK,KAAK,KAAK,qBAAqB;AACpC,aAAS,KAAK,YAAY,KAAK,EAAE;AACjC,SAAK,gBAAgB,MAAM;AAC3B,SAAK,oBAAoB,MAAM,KAAK,mBAAmB;AACvD,aAAS,iBAAiB,mBAAmB,KAAK,iBAAiB;AAAA,EACrE;AAAA,EAEA,OAAa;AACX,QAAI,KAAK,mBAAmB;AAC1B,eAAS,oBAAoB,mBAAmB,KAAK,iBAAiB;AACtE,WAAK,oBAAoB;AAAA,IAC3B;AACA,QAAI,KAAK,IAAI;AACX,WAAK,GAAG,OAAO;AACf,WAAK,KAAK;AAAA,IACZ;AACA,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,aAAoC;AAClC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,eAAe,QAA2B;AACxC,QAAI,KAAK,IAAI;AACX,WAAK,gBAAgB,MAAM;AAAA,IAC7B;AAAA,EACF;AAAA,EAEQ,uBAAuC;AAC7C,UAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,YAAQ,QAAQ,aAAa,IAAI;AACjC,WAAO,OAAO,QAAQ,OAAO;AAAA,MAC3B,UAAU;AAAA,MACV,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,KAAK;AAAA,MACL,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,QAAQ,GAAG,cAAc;AAAA,MACzB,YAAY;AAAA,IACd,CAAC;AAED,eAAW,OAAO,gBAAgB;AAChC,cAAQ,YAAY,KAAK,mBAAmB,GAAG,CAAC;AAAA,IAClD;AAEA,YAAQ,YAAY,KAAK,qBAAqB,CAAC;AAE/C,WAAO;AAAA,EACT;AAAA,EAEQ,mBAAmB,QAAyC;AAClE,UAAM,MAAM,SAAS,cAAc,QAAQ;AAC3C,QAAI,QAAQ,QAAQ,IAAI,OAAO;AAC/B,QAAI,cAAc,OAAO;AACzB,WAAO,OAAO,IAAI,OAAO;AAAA,MACvB,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,UAAU;AAAA,MACV,YAAY,OAAO,WAAW,SAAS,SAAS;AAAA,MAChD,WAAW,OAAO,WAAW,WAAW,WAAW;AAAA,MACnD,gBACE,OAAO,WAAW,cACd,cACA,OAAO,WAAW,kBAChB,iBACA;AAAA,MACR,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,YAAY;AAAA,IACd,CAAC;AAED,QAAI,iBAAiB,eAAe,CAAC,MAAM;AACzC,QAAE,eAAe;AACjB,eAAS,YAAY,OAAO,OAAO;AACnC,WAAK,mBAAmB;AAAA,IAC1B,CAAC;AAED,WAAO;AAAA,EACT;AAAA,EAEQ,uBAA0C;AAChD,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,OAAO,OAAO,OAAO;AAAA,MAC1B,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,YAAY;AAAA,IACd,CAAC;AAED,eAAW,UAAU,KAAK,iBAAiB;AACzC,YAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,aAAO,QAAQ,OAAO,OAAO,IAAI;AACjC,aAAO,cAAc,OAAO;AAC5B,aAAO,YAAY,MAAM;AAAA,IAC3B;AAEA,WAAO,QAAQ,OAAO,sBAAsB;AAE5C,WAAO,iBAAiB,eAAe,CAAC,MAAM;AAC5C,QAAE,gBAAgB;AAAA,IACpB,CAAC;AAED,WAAO,iBAAiB,UAAU,MAAM;AACtC,kBAAY,OAAO,OAAO,KAAK,CAAC;AAChC,WAAK,mBAAmB;AACxB,WAAK,QAAQ,MAAM;AAAA,IACrB,CAAC;AAED,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAgB,QAA2B;AACjD,QAAI,CAAC,KAAK,GAAI;AAEd,UAAM,OAAO,OAAO,sBAAsB;AAC1C,UAAM,eAAe,KAAK,GAAG,eAAe;AAE5C,QAAI,MAAM,KAAK,MAAM,iBAAiB;AACtC,QAAI,MAAM,GAAG;AACX,YAAM,KAAK,SAAS;AAAA,IACtB;AAEA,QAAI,OAAO,KAAK,QAAQ,KAAK,QAAQ,gBAAgB;AACrD,WAAO,KAAK,IAAI,GAAG,IAAI;AAEvB,WAAO,OAAO,KAAK,GAAG,OAAO;AAAA,MAC3B,KAAK,GAAG,GAAG;AAAA,MACX,MAAM,GAAG,IAAI;AAAA,IACf,CAAC;AAAA,EACH;AAAA,EAEQ,qBAA2B;AACjC,QAAI,CAAC,KAAK,GAAI;AAEd,UAAM,SAAS,iBAAiB;AAChC,eAAW,UAAU,gBAAgB;AACnC,YAAM,MAAM,KAAK,GAAG,cAAc,iBAAiB,OAAO,MAAM,IAAI;AACpE,UAAI,CAAC,IAAK;AAEV,YAAM,WAAW,OAAO,OAAO,MAA6B,KAAK;AACjE,UAAI,MAAM,aAAa,WAAW,YAAY;AAC9C,UAAI,MAAM,cAAc,WAAW,SAAS;AAAA,IAC9C;AAAA,EACF;AACF;;;ACnMA,IAAM,mBAA+C;AAAA,EACnD,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AAQA,SAAS,qBAA2B;AAClC,MAAI,SAAS,cAAc,+BAA+B,EAAG;AAC7D,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,aAAa,0BAA0B,EAAE;AAC/C,QAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAMpB,WAAS,KAAK,YAAY,KAAK;AACjC;AAEA,SAAS,YAAY,MAA4B;AAC/C,QAAM,OAAO,KAAK,eAAe;AACjC,SAAO,KAAK,QAAQ,WAAW,GAAG,EAAE,KAAK,EAAE,WAAW;AACxD;AAEO,IAAM,aAAN,MAAiB;AAAA,EACd,YAA2B;AAAA,EAC3B,cAAqC;AAAA,EACrC,cAAgD;AAAA,EAChD,aAAkD;AAAA,EAClD,iBAAqD;AAAA,EACrD,eAAoC;AAAA,EACpC,gBAA+B;AAAA,EAC/B,iBAAuD;AAAA,EACvD,eAAoC;AAAA,EACpC,gBAAqC;AAAA,EACrC;AAAA,EACS;AAAA,EAEjB,YAAY,SAA6B;AACvC,SAAK,UAAU,SAAS,YAAY,QAAQ,OAAO,IAAI,YAAY,SAAS,eAAe;AAC3F,SAAK,cAAc,SAAS,eAAe;AAAA,EAC7C;AAAA,EAEA,IAAI,YAAqB;AACvB,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA,EAEA,IAAI,mBAAkC;AACpC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,UAAU,UAA6C;AACrD,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEA,gBAAgB,OAAmB,QAA0B;AAC3D,SAAK,eAAe;AACpB,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,aAAa,MAAsB,WAAmB,OAA2B;AAC/E,QAAI,KAAK,cAAc,UAAW;AAElC,QAAI,KAAK,WAAW;AAClB,WAAK,YAAY,KAAK;AAAA,IACxB;AAEA,SAAK,gBAAgB;AAErB,0BAAsB,MAAM;AAC1B,UAAI,KAAK,kBAAkB,UAAW;AACtC,WAAK,gBAAgB;AACrB,WAAK,gBAAgB,MAAM,WAAW,KAAK;AAAA,IAC7C,CAAC;AAAA,EACH;AAAA,EAEA,YAAY,OAA2B;AACrC,SAAK,gBAAgB;AAErB,QAAI,CAAC,KAAK,aAAa,CAAC,KAAK,YAAa;AAE1C,QAAI,KAAK,aAAa;AACpB,WAAK,YAAY,oBAAoB,QAAQ,KAAK,WAAW;AAAA,IAC/D;AACA,QAAI,KAAK,YAAY;AACnB,WAAK,YAAY,oBAAoB,WAAW,KAAK,UAAU;AAAA,IACjE;AACA,QAAI,KAAK,gBAAgB;AACvB,WAAK,YAAY,oBAAoB,eAAe,KAAK,cAAc;AAAA,IACzE;AACA,QAAI,KAAK,cAAc;AACrB,WAAK,YAAY,oBAAoB,SAAS,KAAK,YAAY;AAAA,IACjE;AACA,SAAK,YAAY,gBAAgB,qBAAqB;AACtD,SAAK,YAAY,gBAAgB,eAAe;AAEhD,UAAM,OAAO,iBAAiB,KAAK,YAAY,SAAS;AACxD,UAAM,UAAU,MAAM,QAAQ,KAAK,SAAS;AAC5C,UAAM,cACJ,CAAC,CAAC,YAAY,QAAQ,SAAS,UAAU,QAAQ,SAAS,WAAW,QAAQ,SAAS;AAExF,SAAK,YAAY,kBAAkB;AACnC,WAAO,OAAO,KAAK,YAAY,OAAO;AAAA,MACpC,YAAY;AAAA,MACZ,QAAQ;AAAA,IACV,CAAC;AAED,SAAK,SAAS,KAAK;AAInB,SAAK,eAAe;AACpB,QAAI,aAAa;AACf,YAAM,OAAO,KAAK,WAAW,EAAE,KAAK,CAAC;AAAA,IACvC;AACA,QAAI,KAAK,aAAa,KAAK,gBAAgB;AACzC,WAAK,eAAe,KAAK,SAAS;AAAA,IACpC;AACA,SAAK,gBAAgB;AAErB,SAAK,YAAY;AACjB,SAAK,cAAc;AACnB,SAAK,cAAc;AACnB,SAAK,aAAa;AAClB,SAAK,iBAAiB;AACtB,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,QAAQ,OAA2B;AACjC,SAAK,gBAAgB;AACrB,QAAI,KAAK,WAAW;AAClB,WAAK,YAAY,KAAK;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,wBAA8B;AAC5B,QAAI,KAAK,aAAa;AACpB,WAAK,SAAS,eAAe,KAAK,WAAW;AAAA,IAC/C;AAAA,EACF;AAAA,EAEQ,gBAAgB,MAAsB,WAAmB,OAA2B;AAC1F,SAAK,YAAY;AACjB,SAAK,cAAc;AAEnB,SAAK,kBAAkB;AACvB,WAAO,OAAO,KAAK,OAAO;AAAA,MACxB,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AACD,SAAK,MAAM;AAEX,UAAM,YAAY,OAAO,eAAe;AACxC,QAAI,WAAW;AACb,YAAM,QAAQ,SAAS,YAAY;AACnC,YAAM,mBAAmB,IAAI;AAC7B,YAAM,SAAS,KAAK;AACpB,gBAAU,gBAAgB;AAC1B,gBAAU,SAAS,KAAK;AAAA,IAC1B;AAEA,uBAAmB;AACnB,SAAK,aAAa,uBAAuB,KAAK,WAAW;AACzD,SAAK,aAAa,iBAAiB,OAAO,YAAY,IAAI,CAAC,CAAC;AAC5D,SAAK,eAAe,MAAM;AACxB,WAAK,aAAa,iBAAiB,OAAO,YAAY,IAAI,CAAC,CAAC;AAAA,IAC9D;AACA,SAAK,iBAAiB,SAAS,KAAK,YAAY;AAEhD,SAAK,SAAS,KAAK,IAAI;AAEvB,SAAK,cAAc,CAAC,MAAkB;AACpC,YAAM,UAAU,EAAE;AAClB,UAAI,WAAW,KAAK,SAAS,WAAW,GAAG,SAAS,OAAO,EAAG;AAC9D,WAAK,YAAY,KAAK;AAAA,IACxB;AACA,SAAK,aAAa,CAAC,MAAqB;AACtC,WAAK,EAAE,WAAW,EAAE,YAAY,CAAC,EAAE,YAAY,CAAC,EAAE,QAAQ;AACxD,cAAM,SAAS,iBAAiB,EAAE,IAAI,YAAY,CAAC;AACnD,YAAI,QAAQ;AACV,YAAE,eAAe;AACjB,iBAAO;AACP;AAAA,QACF;AAAA,MACF;AACA,UAAI,EAAE,QAAQ,UAAU;AACtB,aAAK,KAAK;AAAA,MACZ;AACA,QAAE,gBAAgB;AAAA,IACpB;AACA,SAAK,iBAAiB,CAAC,MAAoB;AACzC,QAAE,gBAAgB;AAAA,IACpB;AAEA,SAAK,iBAAiB,QAAQ,KAAK,WAAW;AAC9C,SAAK,iBAAiB,WAAW,KAAK,UAAU;AAChD,SAAK,iBAAiB,eAAe,KAAK,cAAc;AAAA,EAC1D;AACF;;;ACjNO,IAAM,cAAN,MAAkB;AAAA,EACf,QAAQ,oBAAI,IAAkB;AAAA,EAC9B,UAAuB;AAAA,EACvB,kBAAkB,oBAAI,IAA4B;AAAA,EAE1D,IAAI,aAA0B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,YAAsB;AACxB,WAAO,CAAC,GAAG,KAAK,MAAM,KAAK,CAAC;AAAA,EAC9B;AAAA,EAEA,SAAS,MAAkB;AACzB,SAAK,MAAM,IAAI,KAAK,MAAM,IAAI;AAAA,EAChC;AAAA,EAEA,QAA+B,MAA6B;AAC1D,WAAO,KAAK,MAAM,IAAI,IAAI;AAAA,EAC5B;AAAA,EAEA,QAAQ,MAAc,KAAwB;AAC5C,UAAM,OAAO,KAAK,MAAM,IAAI,IAAI;AAChC,QAAI,CAAC,KAAM;AAEX,SAAK,SAAS,eAAe,GAAG;AAChC,SAAK,UAAU;AACf,SAAK,QAAQ,aAAa,GAAG;AAC7B,SAAK,gBAAgB,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;AAAA,EAC/C;AAAA,EAEA,kBAAkB,OAAqB,KAAwB;AAC7D,SAAK,SAAS,cAAc,OAAO,GAAG;AAAA,EACxC;AAAA,EAEA,kBAAkB,OAAqB,KAAwB;AAC7D,SAAK,SAAS,cAAc,OAAO,GAAG;AAAA,EACxC;AAAA,EAEA,gBAAgB,OAAqB,KAAwB;AAC3D,SAAK,SAAS,YAAY,OAAO,GAAG;AAAA,EACtC;AAAA,EAEA,SAAS,UAA8C;AACrD,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO,MAAM,KAAK,gBAAgB,OAAO,QAAQ;AAAA,EACnD;AACF;;;AC1CA,IAAM,mBAAmB;AAElB,IAAM,eAAN,MAAmB;AAAA,EAChB,YAAuB,CAAC;AAAA,EACxB,YAAuB,CAAC;AAAA,EACf;AAAA,EACT,kBAAkB,oBAAI,IAAgB;AAAA,EAE9C,YAAY,UAA+B,CAAC,GAAG;AAC7C,SAAK,UAAU,QAAQ,WAAW;AAAA,EACpC;AAAA,EAEA,IAAI,UAAmB;AACrB,WAAO,KAAK,UAAU,SAAS;AAAA,EACjC;AAAA,EAEA,IAAI,UAAmB;AACrB,WAAO,KAAK,UAAU,SAAS;AAAA,EACjC;AAAA,EAEA,IAAI,YAAoB;AACtB,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,IAAI,YAAoB;AACtB,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,KAAK,SAAwB;AAC3B,SAAK,UAAU,KAAK,OAAO;AAC3B,SAAK,YAAY,CAAC;AAElB,QAAI,KAAK,UAAU,SAAS,KAAK,SAAS;AACxC,WAAK,UAAU,MAAM;AAAA,IACvB;AAEA,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,KAAK,OAA8B;AACjC,UAAM,UAAU,KAAK,UAAU,IAAI;AACnC,QAAI,CAAC,QAAS,QAAO;AAErB,YAAQ,KAAK,KAAK;AAClB,SAAK,UAAU,KAAK,OAAO;AAC3B,SAAK,aAAa;AAClB,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,OAA8B;AACjC,UAAM,UAAU,KAAK,UAAU,IAAI;AACnC,QAAI,CAAC,QAAS,QAAO;AAErB,YAAQ,QAAQ,KAAK;AACrB,SAAK,UAAU,KAAK,OAAO;AAC3B,SAAK,aAAa;AAClB,WAAO;AAAA,EACT;AAAA,EAEA,QAAc;AACZ,SAAK,YAAY,CAAC;AAClB,SAAK,YAAY,CAAC;AAClB,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,SAAS,UAAkC;AACzC,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO,MAAM,KAAK,gBAAgB,OAAO,QAAQ;AAAA,EACnD;AAAA,EAEQ,eAAqB;AAC3B,SAAK,gBAAgB,QAAQ,CAAC,OAAO,GAAG,CAAC;AAAA,EAC3C;AACF;;;AC5EO,IAAM,oBAAN,MAA2C;AAAA,EAC/B;AAAA,EAEjB,YAAY,SAAwB;AAClC,SAAK,UAAU,EAAE,GAAG,QAAQ;AAAA,EAC9B;AAAA,EAEA,QAAQ,OAA2B;AACjC,UAAM,IAAI,KAAK,OAAO;AAAA,EACxB;AAAA,EAEA,KAAK,OAA2B;AAC9B,UAAM,OAAO,KAAK,QAAQ,EAAE;AAAA,EAC9B;AACF;AAEO,IAAM,uBAAN,MAA8C;AAAA,EAClC;AAAA,EAEjB,YAAY,SAAwB;AAClC,SAAK,UAAU,EAAE,GAAG,QAAQ;AAAA,EAC9B;AAAA,EAEA,QAAQ,OAA2B;AACjC,UAAM,OAAO,KAAK,QAAQ,EAAE;AAAA,EAC9B;AAAA,EAEA,KAAK,OAA2B;AAC9B,UAAM,IAAI,KAAK,OAAO;AAAA,EACxB;AACF;AAEO,IAAM,uBAAN,MAA8C;AAAA,EACnD,YACmB,IACA,UACA,SACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAEH,QAAQ,OAA2B;AACjC,UAAM,OAAO,KAAK,IAAI,EAAE,GAAG,KAAK,QAAQ,CAAC;AAAA,EAC3C;AAAA,EAEA,KAAK,OAA2B;AAC9B,UAAM,OAAO,KAAK,IAAI,EAAE,GAAG,KAAK,SAAS,CAAC;AAAA,EAC5C;AACF;AAEO,IAAM,eAAN,MAAsC;AAAA,EAClC;AAAA,EAET,YAAY,UAAqB;AAC/B,SAAK,WAAW,CAAC,GAAG,QAAQ;AAAA,EAC9B;AAAA,EAEA,QAAQ,OAA2B;AACjC,eAAW,OAAO,KAAK,UAAU;AAC/B,UAAI,QAAQ,KAAK;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,KAAK,OAA2B;AAC9B,aAAS,IAAI,KAAK,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAClD,WAAK,SAAS,CAAC,GAAG,KAAK,KAAK;AAAA,IAC9B;AAAA,EACF;AACF;;;ACjEO,IAAM,qBAAN,MAA4C;AAAA,EACjD,YACmB,SACA,OACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAEH,QAAQ,QAA4B;AAClC,SAAK,QAAQ,eAAe,KAAK,KAAK;AAAA,EACxC;AAAA,EAEA,KAAK,QAA4B;AAC/B,SAAK,QAAQ,kBAAkB,KAAK,MAAM,EAAE;AAAA,EAC9C;AACF;AAEO,IAAM,qBAAN,MAA4C;AAAA,EACjD,YACmB,SACA,OACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAEH,QAAQ,QAA4B;AAClC,SAAK,QAAQ,kBAAkB,KAAK,MAAM,EAAE;AAAA,EAC9C;AAAA,EAEA,KAAK,QAA4B;AAC/B,SAAK,QAAQ,eAAe,KAAK,KAAK;AAAA,EACxC;AACF;AAEO,IAAM,qBAAN,MAA4C;AAAA,EACjD,YACmB,SACA,SACA,UACA,SACjB;AAJiB;AACA;AACA;AACA;AAAA,EAChB;AAAA,EAEH,QAAQ,QAA4B;AAClC,SAAK,QAAQ,kBAAkB,KAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,CAAC;AAAA,EAClE;AAAA,EAEA,KAAK,QAA4B;AAC/B,SAAK,QAAQ,kBAAkB,KAAK,SAAS,EAAE,GAAG,KAAK,SAAS,CAAC;AAAA,EACnE;AACF;;;ACpCO,IAAM,kBAAN,MAAsB;AAAA,EAO3B,YACmB,OACA,OACA,cACjB;AAHiB;AACA;AACA;AAEjB,SAAK,gBAAgB;AAAA,MACnB,MAAM,GAAG,OAAO,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;AAAA,MACtC,MAAM,GAAG,UAAU,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;AAAA,MAC5C,MAAM,GAAG,UAAU,CAAC,EAAE,UAAU,QAAQ,MAAM,KAAK,SAAS,UAAU,OAAO,CAAC;AAAA,IAChF;AAEA,QAAI,cAAc;AAChB,WAAK,cAAc;AAAA,QACjB,aAAa,GAAG,UAAU,CAAC,UAAU,KAAK,cAAc,KAAK,CAAC;AAAA,QAC9D,aAAa,GAAG,UAAU,CAAC,UAAU,KAAK,cAAc,KAAK,CAAC;AAAA,QAC9D,aAAa,GAAG,UAAU,CAAC,EAAE,UAAU,QAAQ,MAAM,KAAK,cAAc,UAAU,OAAO,CAAC;AAAA,MAC5F;AAAA,IACF;AAAA,EACF;AAAA,EAxBQ,YAAY;AAAA,EACZ,cAAgC;AAAA,EAChC,aAAa;AAAA,EACb,kBAAkB,oBAAI,IAA2B;AAAA,EACjD;AAAA,EAsBR,QAAc;AACZ,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,SAAe;AACb,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,QAAc;AACZ,QAAI,KAAK,gBAAgB,MAAM;AAC7B,WAAK,OAAO;AAAA,IACd;AACA,SAAK,cAAc,CAAC;AACpB,SAAK,gBAAgB,MAAM;AAC3B,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,IAAI,uBAAsC;AACxC,WAAO,KAAK,gBAAgB,OAAO,KAAK,aAAa;AAAA,EACvD;AAAA,EAEA,SAAe;AACb,QAAI,CAAC,KAAK,YAAa;AAEvB,UAAM,gBAAgB,KAAK,qBAAqB;AAChD,UAAM,MAAM,CAAC,GAAG,KAAK,aAAa,GAAG,aAAa;AAClD,SAAK,cAAc;AACnB,SAAK,gBAAgB,MAAM;AAE3B,QAAI,IAAI,WAAW,EAAG;AACtB,UAAM,QAAQ,IAAI,CAAC;AACnB,SAAK,MAAM,KAAK,IAAI,WAAW,KAAK,QAAQ,QAAQ,IAAI,aAAa,GAAG,CAAC;AAAA,EAC3E;AAAA,EAEA,WAAiB;AACf,SAAK,cAAc;AACnB,SAAK,gBAAgB,MAAM;AAAA,EAC7B;AAAA,EAEA,UAAgB;AACd,SAAK,cAAc,QAAQ,CAAC,OAAO,GAAG,CAAC;AAAA,EACzC;AAAA,EAEQ,OAAO,SAAwB;AACrC,QAAI,KAAK,aAAa;AACpB,WAAK,YAAY,KAAK,OAAO;AAAA,IAC/B,OAAO;AACL,WAAK,MAAM,KAAK,OAAO;AAAA,IACzB;AAAA,EACF;AAAA,EAEQ,MAAM,SAA8B;AAC1C,QAAI,CAAC,KAAK,UAAW;AACrB,SAAK,OAAO,IAAI,kBAAkB,OAAO,CAAC;AAAA,EAC5C;AAAA,EAEQ,SAAS,SAA8B;AAC7C,QAAI,CAAC,KAAK,UAAW;AAErB,QAAI,KAAK,eAAe,KAAK,gBAAgB,IAAI,QAAQ,EAAE,GAAG;AAC5D,WAAK,gBAAgB,OAAO,QAAQ,EAAE;AAAA,IACxC;AAEA,SAAK,OAAO,IAAI,qBAAqB,OAAO,CAAC;AAAA,EAC/C;AAAA,EAEQ,SAAS,UAAyB,SAA8B;AACtE,QAAI,CAAC,KAAK,UAAW;AAErB,QAAI,KAAK,aAAa;AACpB,UAAI,CAAC,KAAK,gBAAgB,IAAI,QAAQ,EAAE,GAAG;AACzC,aAAK,gBAAgB,IAAI,QAAQ,IAAI,EAAE,GAAG,SAAS,CAAC;AAAA,MACtD;AAAA,IACF,OAAO;AACL,WAAK,MAAM,KAAK,IAAI,qBAAqB,QAAQ,IAAI,UAAU,OAAO,CAAC;AAAA,IACzE;AAAA,EACF;AAAA,EAEQ,cAAc,OAAoB;AACxC,QAAI,CAAC,KAAK,UAAW;AACrB,QAAI,CAAC,KAAK,aAAc;AACxB,SAAK,OAAO,IAAI,mBAAmB,KAAK,cAAc,KAAK,CAAC;AAAA,EAC9D;AAAA,EAEQ,cAAc,OAAoB;AACxC,QAAI,CAAC,KAAK,UAAW;AACrB,QAAI,CAAC,KAAK,aAAc;AACxB,SAAK,OAAO,IAAI,mBAAmB,KAAK,cAAc,KAAK,CAAC;AAAA,EAC9D;AAAA,EAEQ,cAAc,UAAiB,SAAsB;AAC3D,QAAI,CAAC,KAAK,UAAW;AACrB,QAAI,CAAC,KAAK,aAAc;AACxB,SAAK,OAAO,IAAI,mBAAmB,KAAK,cAAc,QAAQ,IAAI,UAAU,OAAO,CAAC;AAAA,EACtF;AAAA,EAEQ,uBAAkC;AACxC,UAAM,WAAsB,CAAC;AAC7B,eAAW,CAAC,IAAI,QAAQ,KAAK,KAAK,iBAAiB;AACjD,YAAM,UAAU,KAAK,MAAM,QAAQ,EAAE;AACrC,UAAI,SAAS;AACX,iBAAS,KAAK,IAAI,qBAAqB,IAAI,UAAU,OAAO,CAAC;AAAA,MAC/D;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;;;AC9IO,SAAS,mBAAmB,KAA+B,MAAyB;AACzF,QAAM,EAAE,GAAG,EAAE,IAAI,KAAK;AACtB,QAAM,EAAE,GAAG,EAAE,IAAI,KAAK;AACtB,QAAM,IAAI;AACV,QAAM,MAAM;AACZ,QAAM,eAAe,KAAK,YAAY;AAEtC,MAAI,KAAK;AACT,MAAI,YAAY,KAAK;AACrB,MAAI,UAAU;AACd,MAAI,OAAO,IAAI,GAAG,CAAC;AACnB,MAAI,OAAO,IAAI,IAAI,GAAG,CAAC;AACvB,MAAI,MAAM,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,CAAC;AACnC,MAAI,OAAO,IAAI,GAAG,IAAI,IAAI,CAAC;AAC3B,MAAI,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,GAAG,CAAC;AAC3C,MAAI,OAAO,IAAI,GAAG,IAAI,CAAC;AACvB,MAAI,MAAM,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,GAAG,CAAC;AACnC,MAAI,OAAO,GAAG,IAAI,CAAC;AACnB,MAAI,MAAM,GAAG,GAAG,IAAI,GAAG,GAAG,CAAC;AAC3B,MAAI,UAAU;AACd,MAAI,KAAK;AAET,MAAI,KAAK,MAAM;AACb,QAAI,YAAY,KAAK;AACrB,UAAM,OAAO,gBAAgB,KAAK,MAAM,YAAY;AACpD,qBAAiB,KAAK,MAAM,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM,CAAC;AAAA,EAC3D;AAEA,MAAI,QAAQ;AACd;AAEA,SAAS,gBAAgB,KAAwB;AAC/C,QAAM,QAAQ,IAAI,SAAS,WAAW;AACtC,QAAM,SAAS,IAAI,OAAO,SAAS;AACnC,SAAO,GAAG,KAAK,IAAI,MAAM,IAAI,IAAI,QAAQ;AAC3C;AAEA,SAAS,iBACP,KACA,MACA,QACA,QACA,UACM;AACN,MAAI,eAAe;AACnB,MAAI,UAAU;AACd,MAAI,UAAU;AACd,MAAI,aAAa;AAEjB,aAAW,OAAO,MAAM;AACtB,QAAI,OAAO,gBAAgB,GAAG;AAC9B,UAAM,gBAAgB,IAAI,WAAW;AACrC,iBAAa,KAAK,IAAI,YAAY,aAAa;AAE/C,UAAM,QAAQ,IAAI,KAAK,MAAM,QAAQ;AACrC,eAAW,QAAQ,OAAO;AACxB,UAAI,SAAS,MAAM;AACjB,kBAAU;AACV,mBAAW;AACX,qBAAa;AACb;AAAA,MACF;AACA,UAAI,SAAS,KAAK;AAChB,cAAM,aAAa,IAAI,YAAY,GAAG,EAAE;AACxC,YAAI,UAAU,aAAa,SAAS,YAAY,UAAU,QAAQ;AAChE,oBAAU;AACV,qBAAW;AACX,uBAAa;AAAA,QACf,OAAO;AACL,qBAAW;AAAA,QACb;AACA;AAAA,MACF;AACA,UAAI,CAAC,KAAM;AAEX,YAAM,UAAU,IAAI,YAAY,IAAI;AACpC,UAAI,UAAU,QAAQ,QAAQ,SAAS,YAAY,UAAU,QAAQ;AACnE,kBAAU;AACV,mBAAW;AACX,qBAAa;AAAA,MACf;AAEA,UAAI,SAAS,MAAM,SAAS,OAAO;AAEnC,UAAI,IAAI,WAAW;AACjB,cAAM,SAAS,UAAU,IAAI,WAAW;AACxC,YAAI,SAAS,SAAS,QAAQ,QAAQ,OAAO,CAAC;AAAA,MAChD;AAEA,UAAI,IAAI,eAAe;AACrB,cAAM,UAAU,UAAU,IAAI,WAAW;AACzC,YAAI,SAAS,SAAS,SAAS,QAAQ,OAAO,CAAC;AAAA,MACjD;AAEA,iBAAW,QAAQ;AAAA,IACrB;AAAA,EACF;AACF;;;AC/EA,SAAS,gBAAgB,IAAgC;AACvD,MAAI,GAAG,SAAS,SAAU,QAAO;AACjC,MAAI,GAAG,OAAO,WAAW,EAAG,QAAO;AAEnC,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AAEX,aAAW,KAAK,GAAG,QAAQ;AACzB,UAAM,KAAK,GAAG,SAAS,IAAI,EAAE;AAC7B,UAAM,KAAK,GAAG,SAAS,IAAI,EAAE;AAC7B,WAAO,KAAK,IAAI,MAAM,EAAE;AACxB,WAAO,KAAK,IAAI,MAAM,EAAE;AACxB,WAAO,KAAK,IAAI,MAAM,EAAE;AACxB,WAAO,KAAK,IAAI,MAAM,EAAE;AAAA,EAC1B;AAEA,QAAM,MAAM,GAAG,QAAQ;AACvB,SAAO;AAAA,IACL,GAAG,OAAO;AAAA,IACV,GAAG,OAAO;AAAA,IACV,GAAG,OAAO,OAAO,GAAG;AAAA,IACpB,GAAG,OAAO,OAAO,GAAG;AAAA,EACtB;AACF;AAEA,SAAS,eAAe,IAAgC;AACtD,UAAQ,GAAG,MAAM;AAAA,IACf,KAAK;AACH,aAAO,gBAAgB,EAAE;AAAA,IAC3B,KAAK,SAAS;AACZ,YAAM,IAAI,eAAe,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI;AAChD,YAAM,MAAM,GAAG,QAAQ,IAAI;AAC3B,aAAO,EAAE,GAAG,EAAE,IAAI,KAAK,GAAG,EAAE,IAAI,KAAK,GAAG,EAAE,IAAI,MAAM,GAAG,GAAG,EAAE,IAAI,MAAM,EAAE;AAAA,IAC1E;AAAA,IACA,KAAK;AACH,aAAO;AAAA,IACT,KAAK,YAAY;AACf,YAAM,SAAS,iBAAiB,EAAE;AAClC,UAAI,CAAC,OAAQ,QAAO;AACpB,aAAO;AAAA,IACT;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,UAAI,UAAU,IAAI;AAChB,eAAO,EAAE,GAAG,GAAG,SAAS,GAAG,GAAG,GAAG,SAAS,GAAG,GAAG,GAAG,KAAK,GAAG,GAAG,GAAG,KAAK,EAAE;AAAA,MAC1E;AACA,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,cACP,UACA,SACuD;AACvD,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,QAAQ;AAEZ,aAAW,MAAM,UAAU;AACzB,UAAM,OAAO,eAAe,EAAE;AAC9B,QAAI,CAAC,KAAM;AACX,YAAQ;AACR,WAAO,KAAK,IAAI,MAAM,KAAK,CAAC;AAC5B,WAAO,KAAK,IAAI,MAAM,KAAK,CAAC;AAC5B,WAAO,KAAK,IAAI,MAAM,KAAK,IAAI,KAAK,CAAC;AACrC,WAAO,KAAK,IAAI,MAAM,KAAK,IAAI,KAAK,CAAC;AAAA,EACvC;AAEA,MAAI,CAAC,MAAO,QAAO;AAEnB,SAAO;AAAA,IACL,GAAG,OAAO;AAAA,IACV,GAAG,OAAO;AAAA,IACV,GAAG,OAAO,OAAO,UAAU;AAAA,IAC3B,GAAG,OAAO,OAAO,UAAU;AAAA,EAC7B;AACF;AAEA,SAAS,mBAAmB,KAA+B,MAAyB;AAClF,MAAI,CAAC,KAAK,KAAM;AAEhB,MAAI,KAAK;AACT,MAAI,YAAY,KAAK;AACrB,MAAI,OAAO,GAAG,KAAK,QAAQ;AAC3B,MAAI,eAAe;AACnB,MAAI,YAAY,KAAK;AAErB,QAAM,MAAM;AACZ,MAAI,QAAQ,KAAK,SAAS,IAAI;AAC9B,MAAI,KAAK,cAAc,UAAU;AAC/B,YAAQ,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;AAAA,EAC1C,WAAW,KAAK,cAAc,SAAS;AACrC,YAAQ,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;AAAA,EAC1C;AAEA,QAAM,aAAa,KAAK,WAAW;AACnC,QAAM,QAAQ,KAAK,KAAK,MAAM,IAAI;AAClC,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,SAAS,QAAW;AACtB,UAAI,SAAS,MAAM,OAAO,KAAK,SAAS,IAAI,MAAM,IAAI,UAAU;AAAA,IAClE;AAAA,EACF;AAEA,MAAI,QAAQ;AACd;AAEA,SAAS,oBACP,KACA,MACA,QACM;AACN,QAAM,gBAAgB;AAAA,IACpB,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,IACb,MAAM,OAAO,IAAI,OAAO;AAAA,IACxB,MAAM,OAAO,IAAI,OAAO;AAAA,EAC1B;AAEA,MAAI,KAAK,aAAa,OAAO;AAC3B;AAAA,MACE;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF,OAAO;AACL;AAAA,MACE;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AACF;AAEA,SAAS,WAAW,UAAmE;AACrF,QAAM,gBAAgB,SAAS;AAAA,IAC7B,CAAC,OAA8C,GAAG,SAAS,WAAW,SAAS;AAAA,EACjF;AAEA,QAAMC,SAAQ,oBAAI,IAA8B;AAChD,MAAI,cAAc,WAAW,EAAG,QAAO,QAAQ,QAAQA,MAAK;AAE5D,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI,YAAY,cAAc;AAC9B,UAAM,OAAO,MAAM;AACjB;AACA,UAAI,aAAa,EAAG,SAAQA,MAAK;AAAA,IACnC;AAEA,eAAW,MAAM,eAAe;AAC9B,YAAM,MAAM,IAAI,MAAM;AACtB,UAAI,cAAc;AAClB,UAAI,SAAS,MAAM;AACjB,QAAAA,OAAM,IAAI,GAAG,IAAI,GAAG;AACpB,aAAK;AAAA,MACP;AACA,UAAI,UAAU;AACd,YAAM,MAAM,GAAG,IAAI,SAAS,GAAG,IAAI,MAAM;AACzC,UAAI,MAAM,GAAG,GAAG,GAAG,GAAG,GAAG;AAAA,IAC3B;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,YACpB,OACA,UAA8B,CAAC,GAC/B,cACsB;AACtB,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,SAAS,QAAQ;AAEvB,QAAM,cAAc,MAAM,OAAO;AACjC,MAAI,kBAAkB,eAClB,YAAY,OAAO,CAAC,OAAO,aAAa,eAAe,GAAG,OAAO,CAAC,IAClE;AAEJ,MAAI,QAAQ;AACV,sBAAkB,gBAAgB,OAAO,MAAM;AAAA,EACjD;AAEA,QAAM,SAAS,cAAc,iBAAiB,OAAO;AACrD,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,aAAa,MAAM,WAAW,eAAe;AAEnD,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,QAAQ,KAAK,KAAK,OAAO,IAAI,KAAK;AACzC,SAAO,SAAS,KAAK,KAAK,OAAO,IAAI,KAAK;AAE1C,QAAM,MAAM,OAAO,WAAW,IAAI;AAClC,MAAI,CAAC,IAAK,QAAO;AAEjB,MAAI,MAAM,OAAO,KAAK;AACtB,MAAI,UAAU,CAAC,OAAO,GAAG,CAAC,OAAO,CAAC;AAElC,MAAI,YAAY;AAChB,MAAI,SAAS,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAEnD,QAAM,WAAW,IAAI,gBAAgB;AACrC,WAAS,SAAS,KAAK;AAEvB,QAAM,QAAuB,CAAC;AAE9B,aAAW,MAAM,iBAAiB;AAChC,QAAI,GAAG,SAAS,QAAQ;AACtB,YAAM,KAAK,EAAE;AACb;AAAA,IACF;AAEA,QAAI,GAAG,SAAS,QAAQ;AACtB,yBAAmB,KAAK,EAAE;AAC1B;AAAA,IACF;AAEA,QAAI,GAAG,SAAS,QAAQ;AACtB,yBAAmB,KAAK,EAAE;AAC1B;AAAA,IACF;AAEA,QAAI,GAAG,SAAS,QAAQ;AACtB;AAAA,IACF;AAEA,QAAI,GAAG,SAAS,SAAS;AACvB,YAAM,MAAM,WAAW,IAAI,GAAG,EAAE;AAChC,UAAI,KAAK;AACP,YAAI,UAAU,KAAK,GAAG,SAAS,GAAG,GAAG,SAAS,GAAG,GAAG,KAAK,GAAG,GAAG,KAAK,CAAC;AAAA,MACvE;AACA;AAAA,IACF;AAEA,aAAS,oBAAoB,KAAK,EAAE;AAAA,EACtC;AAEA,aAAW,QAAQ,OAAO;AACxB,wBAAoB,KAAK,MAAM,MAAM;AAAA,EACvC;AAEA,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,WAAO,OAAO,CAAC,SAAS,QAAQ,IAAI,GAAG,WAAW;AAAA,EACpD,CAAC;AACH;;;AC9QO,IAAM,eAAN,MAAmB;AAAA,EAKxB,YAA6B,OAAqB;AAArB;AAC3B,UAAM,eAAsB;AAAA,MAC1B,IAAI,SAAS,OAAO;AAAA,MACpB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AACA,SAAK,OAAO,IAAI,aAAa,IAAI,YAAY;AAC7C,SAAK,iBAAiB,aAAa;AACnC,SAAK,eAAe;AAAA,EACtB;AAAA,EAhBQ,SAAS,oBAAI,IAAmB;AAAA,EAChC;AAAA,EACA,MAAM,IAAI,SAA6B;AAAA,EAgB/C,IAAI,cAAqB;AACvB,UAAM,QAAQ,KAAK,OAAO,IAAI,KAAK,cAAc;AACjD,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,wBAAwB;AACpD,WAAO,EAAE,GAAG,MAAM;AAAA,EACpB;AAAA,EAEA,IAAI,gBAAwB;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,YAAqB;AACnB,WAAO,CAAC,GAAG,KAAK,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;AAAA,EAC1F;AAAA,EAEA,SAAS,IAA+B;AACtC,UAAM,QAAQ,KAAK,OAAO,IAAI,EAAE;AAChC,WAAO,QAAQ,EAAE,GAAG,MAAM,IAAI;AAAA,EAChC;AAAA,EAEA,eAAe,IAAqB;AAClC,WAAO,KAAK,OAAO,IAAI,EAAE,GAAG,WAAW;AAAA,EACzC;AAAA,EAEA,cAAc,IAAqB;AACjC,WAAO,KAAK,OAAO,IAAI,EAAE,GAAG,UAAU;AAAA,EACxC;AAAA,EAEA,YAAY,MAAsB;AAChC,UAAM,WAAW,KAAK,IAAI,GAAG,CAAC,GAAG,KAAK,OAAO,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,GAAG,EAAE;AAC9E,UAAM,WAAW,QAAQ,SAAS,KAAK,OAAO,OAAO,CAAC;AACtD,UAAM,QAAe;AAAA,MACnB,IAAI,SAAS,OAAO;AAAA,MACpB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,OAAO,WAAW;AAAA,MAClB,SAAS;AAAA,IACX;AACA,SAAK,eAAe,KAAK;AACzB,WAAO,EAAE,GAAG,MAAM;AAAA,EACpB;AAAA,EAEA,YAAY,IAAkB;AAC5B,QAAI,KAAK,OAAO,QAAQ,GAAG;AACzB,YAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AACA,QAAI,KAAK,mBAAmB,IAAI;AAC9B,YAAM,YAAY,CAAC,GAAG,KAAK,OAAO,OAAO,CAAC,EACvC,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,EACzB,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AACnC,YAAM,WAAW,UAAU,CAAC;AAC5B,UAAI,SAAU,MAAK,iBAAiB,SAAS;AAAA,IAC/C;AACA,UAAM,WAAW,KAAK,MAAM,OAAO,EAAE,OAAO,CAAC,OAAO,GAAG,YAAY,EAAE;AACrE,eAAW,MAAM,UAAU;AACzB,WAAK,MAAM,OAAO,GAAG,IAAI,EAAE,SAAS,KAAK,eAAe,CAAC;AAAA,IAC3D;AACA,SAAK,kBAAkB,EAAE;AAAA,EAC3B;AAAA,EAEA,YAAY,IAAY,MAAoB;AAC1C,SAAK,kBAAkB,IAAI,EAAE,KAAK,CAAC;AAAA,EACrC;AAAA,EAEA,aAAa,IAAY,UAAwB;AAC/C,QAAI,CAAC,KAAK,OAAO,IAAI,EAAE,EAAG;AAC1B,SAAK,kBAAkB,IAAI,EAAE,OAAO,SAAS,CAAC;AAAA,EAChD;AAAA,EAEA,gBAAgB,IAAY,SAA2B;AACrD,QAAI,CAAC,WAAW,OAAO,KAAK,gBAAgB;AAC1C,YAAM,WAAW,KAAK,kBAAkB,EAAE;AAC1C,UAAI,CAAC,SAAU,QAAO;AACtB,WAAK,iBAAiB,SAAS;AAAA,IACjC;AACA,SAAK,kBAAkB,IAAI,EAAE,QAAQ,CAAC;AACtC,WAAO;AAAA,EACT;AAAA,EAEA,eAAe,IAAY,QAA0B;AACnD,QAAI,UAAU,OAAO,KAAK,gBAAgB;AACxC,YAAM,WAAW,KAAK,kBAAkB,EAAE;AAC1C,UAAI,CAAC,SAAU,QAAO;AACtB,WAAK,iBAAiB,SAAS;AAAA,IACjC;AACA,SAAK,kBAAkB,IAAI,EAAE,OAAO,CAAC;AACrC,WAAO;AAAA,EACT;AAAA,EAEA,gBAAgB,IAAY,SAAuB;AACjD,QAAI,CAAC,KAAK,OAAO,IAAI,EAAE,EAAG;AAC1B,SAAK,kBAAkB,IAAI,EAAE,SAAS,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC;AAAA,EAC3E;AAAA,EAEA,eAAe,IAAkB;AAC/B,QAAI,CAAC,KAAK,OAAO,IAAI,EAAE,EAAG;AAC1B,SAAK,iBAAiB;AACtB,SAAK,IAAI,KAAK,UAAU,IAAI;AAAA,EAC9B;AAAA,EAEA,mBAAmB,WAAmB,SAAuB;AAC3D,QAAI,CAAC,KAAK,OAAO,IAAI,OAAO,EAAG;AAC/B,SAAK,MAAM,OAAO,WAAW,EAAE,QAAQ,CAAC;AACxC,SAAK,IAAI,KAAK,UAAU,IAAI;AAAA,EAC9B;AAAA,EAEA,WAAoB;AAClB,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,aAAa,QAAuB;AAClC,SAAK,OAAO,MAAM;AAClB,eAAW,SAAS,QAAQ;AAC1B,WAAK,OAAO,IAAI,MAAM,IAAI,EAAE,GAAG,MAAM,CAAC;AAAA,IACxC;AACA,UAAM,QAAQ,KAAK,UAAU,EAAE,CAAC;AAChC,QAAI,MAAO,MAAK,iBAAiB,MAAM;AACvC,SAAK,eAAe;AACpB,SAAK,IAAI,KAAK,UAAU,IAAI;AAAA,EAC9B;AAAA,EAEA,GACE,OACA,UACY;AACZ,WAAO,KAAK,IAAI,GAAG,OAAO,QAAQ;AAAA,EACpC;AAAA,EAEA,eAAe,OAAoB;AACjC,SAAK,OAAO,IAAI,MAAM,IAAI,EAAE,GAAG,MAAM,CAAC;AACtC,SAAK,eAAe;AACpB,SAAK,IAAI,KAAK,UAAU,EAAE,GAAG,MAAM,CAAC;AACpC,SAAK,IAAI,KAAK,UAAU,IAAI;AAAA,EAC9B;AAAA,EAEA,kBAAkB,IAAkB;AAClC,UAAM,QAAQ,KAAK,OAAO,IAAI,EAAE;AAChC,SAAK,OAAO,OAAO,EAAE;AACrB,SAAK,eAAe;AACpB,QAAI,MAAO,MAAK,IAAI,KAAK,UAAU,EAAE,GAAG,MAAM,CAAC;AAC/C,SAAK,IAAI,KAAK,UAAU,IAAI;AAAA,EAC9B;AAAA,EAEA,kBAAkB,IAAY,OAAyC;AACrE,UAAM,QAAQ,KAAK,OAAO,IAAI,EAAE;AAChC,QAAI,CAAC,MAAO;AACZ,UAAM,WAAW,EAAE,GAAG,MAAM;AAC5B,WAAO,OAAO,OAAO,KAAK;AAC1B,QAAI,WAAW,MAAO,MAAK,eAAe;AAC1C,SAAK,IAAI,KAAK,UAAU,EAAE,UAAU,SAAS,EAAE,GAAG,MAAM,EAAE,CAAC;AAC3D,SAAK,IAAI,KAAK,UAAU,IAAI;AAAA,EAC9B;AAAA,EAEQ,iBAAuB;AAC7B,UAAM,QAAQ,oBAAI,IAAoB;AACtC,eAAW,SAAS,KAAK,OAAO,OAAO,GAAG;AACxC,YAAM,IAAI,MAAM,IAAI,MAAM,KAAK;AAAA,IACjC;AACA,SAAK,MAAM,cAAc,KAAK;AAAA,EAChC;AAAA,EAEQ,kBAAkB,WAAsC;AAC9D,WAAO,CAAC,GAAG,KAAK,OAAO,OAAO,CAAC,EAC5B,OAAO,CAAC,MAAM,EAAE,OAAO,aAAa,EAAE,WAAW,CAAC,EAAE,MAAM,EAC1D,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAAA,EACxC;AACF;;;ACjMO,IAAM,eAAN,MAAmB;AAAA,EAChB,uBAAsC;AAAA,EAC7B;AAAA,EAEjB,YAAY,MAAwB;AAClC,SAAK,UAAU,KAAK;AAAA,EACtB;AAAA,EAEA,iBAAiB,IAAkB;AACjC,SAAK,gBAAgB;AACrB,UAAM,OAAO,KAAK,QAAQ,EAAE;AAC5B,QAAI,CAAC,KAAM;AAEX,SAAK,uBAAuB;AAC5B,SAAK,MAAM,gBAAgB;AAC3B,SAAK,iBAAiB,eAAe,KAAK,iBAAiB;AAE3D,WAAO,iBAAiB,WAAW,KAAK,SAAS;AACjD,WAAO,iBAAiB,eAAe,KAAK,aAAa;AAAA,EAC3D;AAAA,EAEA,kBAAwB;AACtB,QAAI,CAAC,KAAK,qBAAsB;AAEhC,UAAM,OAAO,KAAK,QAAQ,KAAK,oBAAoB;AACnD,QAAI,MAAM;AACR,WAAK,MAAM,gBAAgB;AAC3B,WAAK,oBAAoB,eAAe,KAAK,iBAAiB;AAAA,IAChE;AAEA,SAAK,uBAAuB;AAC5B,WAAO,oBAAoB,WAAW,KAAK,SAAS;AACpD,WAAO,oBAAoB,eAAe,KAAK,aAAa;AAAA,EAC9D;AAAA,EAEA,gBAAyB;AACvB,WAAO,KAAK,yBAAyB;AAAA,EACvC;AAAA,EAEA,UAAgB;AACd,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEQ,oBAAoB,CAAC,MAA0B;AACrD,MAAE,gBAAgB;AAAA,EACpB;AAAA,EAEQ,YAAY,CAAC,MAA2B;AAC9C,QAAI,EAAE,QAAQ,UAAU;AACtB,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA,EAEQ,gBAAgB,CAAC,MAA0B;AACjD,QAAI,CAAC,KAAK,qBAAsB;AAChC,UAAM,SAAS,EAAE;AACjB,QAAI,EAAE,kBAAkB,UAAU;AAChC,WAAK,gBAAgB;AACrB;AAAA,IACF;AAEA,UAAM,OAAO,KAAK,QAAQ,KAAK,oBAAoB;AACnD,QAAI,QAAQ,CAAC,KAAK,SAAS,MAAM,GAAG;AAClC,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AACF;;;ACjEA,IAAM,kBAAkB;AACxB,IAAM,uBAAuB;AAEtB,IAAM,oBAAN,MAAwB;AAAA,EACZ;AAAA,EACA;AAAA,EACT,cAAc;AAAA,EACd,WAAW;AAAA,EACX,WAAW;AAAA,EACX,gBAAgB;AAAA,EAExB,YAAY,SAAoC;AAC9C,SAAK,UAAU,SAAS,WAAW;AACnC,SAAK,cAAc,SAAS,eAAe;AAAA,EAC7C;AAAA,EAEA,KAAK,GAA0B;AAC7B,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,IAAI,EAAE;AACZ,UAAM,IAAI,EAAE;AAEZ,QAAI,KAAK,eAAe;AACtB,YAAM,UAAU,MAAM,KAAK;AAC3B,YAAM,KAAK,IAAI,KAAK;AACpB,YAAM,KAAK,IAAI,KAAK;AACpB,YAAM,OAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAExC,UAAI,WAAW,KAAK,WAAW,QAAQ,KAAK,aAAa;AACvD,aAAK,MAAM;AACX,eAAO;AAAA,MACT;AAAA,IACF;AAEA,SAAK,cAAc;AACnB,SAAK,WAAW;AAChB,SAAK,WAAW;AAChB,SAAK,gBAAgB;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,QAAc;AACZ,SAAK,gBAAgB;AACrB,SAAK,cAAc;AACnB,SAAK,WAAW;AAChB,SAAK,WAAW;AAAA,EAClB;AACF;;;ACxCO,IAAM,iBAAN,MAAqB;AAAA,EAClB,WAAW,oBAAI,IAA4B;AAAA,EAC3C,cAAc,oBAAI,IAAyB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,oBAAoB,oBAAI,IAAoB;AAAA,EAC5C,mBAAmB,oBAAI,IAAoB;AAAA,EAEnD,YAAY,MAA0B;AACpC,SAAK,WAAW,KAAK;AACrB,SAAK,gBAAgB,KAAK;AAC1B,SAAK,mBAAmB,KAAK;AAC7B,SAAK,aAAa,KAAK,cAAc;AAAA,EACvC;AAAA,EAEA,QAAQ,IAAwC;AAC9C,WAAO,KAAK,SAAS,IAAI,EAAE;AAAA,EAC7B;AAAA,EAEA,iBAAiB,WAAmB,KAAwB;AAC1D,SAAK,YAAY,IAAI,WAAW,GAAG;AAAA,EACrC;AAAA,EAEA,WAAW,WAA4B;AACrC,WAAO,KAAK,YAAY,IAAI,SAAS;AAAA,EACvC;AAAA,EAEA,iBAAiB,WAAyB;AACxC,SAAK,YAAY,OAAO,SAAS;AACjC,SAAK,kBAAkB,OAAO,SAAS;AACvC,SAAK,iBAAiB,OAAO,SAAS;AACtC,UAAM,OAAO,KAAK,SAAS,IAAI,SAAS;AACxC,QAAI,CAAC,KAAM;AACX,WAAO,KAAK,YAAY;AACtB,WAAK,YAAY,KAAK,UAAU;AAAA,IAClC;AACA,WAAO,KAAK,QAAQ,aAAa;AAAA,EACnC;AAAA,EAEA,YAAY,SAAwB,SAAS,GAAS;AACpD,QAAI,OAAO,KAAK,SAAS,IAAI,QAAQ,EAAE;AACvC,QAAI,CAAC,MAAM;AACT,aAAO,SAAS,cAAc,KAAK;AACnC,WAAK,QAAQ,WAAW,IAAI,QAAQ;AACpC,aAAO,OAAO,KAAK,OAAO;AAAA,QACxB,UAAU;AAAA,QACV,eAAe;AAAA,MACjB,CAAC;AACD,WAAK,SAAS,YAAY,IAAI;AAC9B,WAAK,SAAS,IAAI,QAAQ,IAAI,IAAI;AAAA,IACpC,WAAW,KAAK,YAAY;AAC1B,YAAM,iBAAiB,KAAK,WAAW,QAAQ,EAAE;AACjD,YAAM,cAAc,KAAK,kBAAkB,IAAI,QAAQ,EAAE;AACzD,YAAM,QAAQ,KAAK,iBAAiB,IAAI,QAAQ,EAAE;AAClD,UAAI,gBAAgB,kBAAkB,UAAU,QAAQ;AACtD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,KAAK,YAAY;AACnB,WAAK,kBAAkB,IAAI,QAAQ,IAAI,KAAK,WAAW,QAAQ,EAAE,CAAC;AAClE,WAAK,iBAAiB,IAAI,QAAQ,IAAI,MAAM;AAAA,IAC9C;AAEA,UAAM,OAAO,UAAU,UAAU,QAAQ,OAAO;AAChD,WAAO,OAAO,KAAK,OAAO;AAAA,MACxB,SAAS;AAAA,MACT,MAAM,GAAG,QAAQ,SAAS,CAAC;AAAA,MAC3B,KAAK,GAAG,QAAQ,SAAS,CAAC;AAAA,MAC1B,OAAO,OAAO,GAAG,KAAK,CAAC,OAAO;AAAA,MAC9B,QAAQ,OAAO,GAAG,KAAK,CAAC,OAAO;AAAA,MAC/B,QAAQ,OAAO,MAAM;AAAA,IACvB,CAAC;AAED,SAAK,iBAAiB,MAAM,OAAO;AAAA,EACrC;AAAA,EAEA,YAAY,IAAkB;AAC5B,UAAM,OAAO,KAAK,SAAS,IAAI,EAAE;AACjC,QAAI,KAAM,MAAK,MAAM,UAAU;AAAA,EACjC;AAAA,EAEA,cAAc,IAAkB;AAC9B,SAAK,YAAY,OAAO,EAAE;AAC1B,SAAK,kBAAkB,OAAO,EAAE;AAChC,SAAK,iBAAiB,OAAO,EAAE;AAC/B,UAAM,OAAO,KAAK,SAAS,IAAI,EAAE;AACjC,QAAI,MAAM;AACR,WAAK,OAAO;AACZ,WAAK,SAAS,OAAO,EAAE;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,gBAAsB;AACpB,SAAK,SAAS,QAAQ,CAAC,SAAS,KAAK,OAAO,CAAC;AAC7C,SAAK,SAAS,MAAM;AACpB,SAAK,YAAY,MAAM;AACvB,SAAK,kBAAkB,MAAM;AAC7B,SAAK,iBAAiB,MAAM;AAAA,EAC9B;AAAA,EAEA,oBAAoB,OAA2B;AAC7C,eAAW,MAAM,MAAM,kBAAkB,MAAM,GAAG;AAChD,UAAI,GAAG,OAAO;AACZ,cAAM,MAAM,SAAS,eAAe,GAAG,KAAK;AAC5C,YAAI,KAAK;AACP,eAAK,YAAY,IAAI,GAAG,IAAI,GAAG;AAAA,QACjC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,iBAAiB,MAAsB,SAA8B;AAC3E,QAAI,QAAQ,SAAS,QAAQ;AAC3B,UAAI,CAAC,KAAK,QAAQ,aAAa,GAAG;AAChC,aAAK,QAAQ,aAAa,IAAI;AAC9B,eAAO,OAAO,KAAK,OAAO;AAAA,UACxB,iBAAiB,QAAQ;AAAA,UACzB,OAAO,QAAQ;AAAA,UACf,SAAS;AAAA,UACT,cAAc;AAAA,UACd,WAAW;AAAA,UACX,UAAU,GAAG,QAAQ,YAAY,sBAAsB;AAAA,UACvD,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,UAAU;AAAA,QACZ,CAAC;AACD,aAAK,YAAY,QAAQ,QAAQ;AAEjC,cAAM,WAAW,IAAI,kBAAkB;AACvC,aAAK,iBAAiB,aAAa,CAAC,MAAM;AACxC,cAAI,SAAS,KAAK,CAAC,GAAG;AACpB,cAAE,gBAAgB;AAClB,kBAAM,KAAK,KAAK,QAAQ,WAAW;AACnC,gBAAI,GAAI,MAAK,cAAc,EAAE;AAAA,UAC/B;AAAA,QACF,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,KAAK,iBAAiB,QAAQ,EAAE,GAAG;AACtC,cAAM,OAAO,QAAQ,QAAQ;AAC7B,YAAI,KAAK,cAAc,MAAM;AAC3B,eAAK,YAAY;AAAA,QACnB;AACA,aAAK,MAAM,kBAAkB,QAAQ;AACrC,aAAK,MAAM,QAAQ,QAAQ;AAC3B,aAAK,MAAM,WAAW,GAAG,QAAQ,YAAY,sBAAsB;AAAA,MACrE;AAAA,IACF;AAEA,QAAI,QAAQ,SAAS,QAAQ;AAC3B,UAAI,CAAC,KAAK,QAAQ,aAAa,GAAG;AAChC,cAAM,UAAU,KAAK,YAAY,IAAI,QAAQ,EAAE;AAC/C,YAAI,SAAS;AACX,eAAK,QAAQ,aAAa,IAAI;AAC9B,iBAAO,OAAO,KAAK,OAAO;AAAA,YACxB,UAAU;AAAA,YACV,eAAe,QAAQ,cAAc,SAAS;AAAA,UAChD,CAAC;AACD,eAAK,YAAY,OAAO;AAAA,QAC1B;AAAA,MACF,OAAO;AACL,aAAK,MAAM,gBAAgB,QAAQ,cAAc,SAAS;AAAA,MAC5D;AAAA,IACF;AAEA,QAAI,QAAQ,SAAS,QAAQ;AAC3B,UAAI,CAAC,KAAK,QAAQ,aAAa,GAAG;AAChC,aAAK,QAAQ,aAAa,IAAI;AAC9B,eAAO,OAAO,KAAK,OAAO;AAAA,UACxB,SAAS;AAAA,UACT,UAAU,GAAG,QAAQ,QAAQ;AAAA,UAC7B,OAAO,QAAQ;AAAA,UACf,WAAW,QAAQ;AAAA,UACnB,YAAY;AAAA,UACZ,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,YAAY;AAAA,QACd,CAAC;AACD,aAAK,cAAc,QAAQ,QAAQ;AAEnC,cAAM,WAAW,IAAI,kBAAkB;AACvC,aAAK,iBAAiB,aAAa,CAAC,MAAM;AACxC,cAAI,SAAS,KAAK,CAAC,GAAG;AACpB,cAAE,gBAAgB;AAClB,kBAAM,KAAK,KAAK,QAAQ,WAAW;AACnC,gBAAI,GAAI,MAAK,cAAc,EAAE;AAAA,UAC/B;AAAA,QACF,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,KAAK,iBAAiB,QAAQ,EAAE,GAAG;AACtC,YAAI,KAAK,gBAAgB,QAAQ,MAAM;AACrC,eAAK,cAAc,QAAQ,QAAQ;AAAA,QACrC;AACA,eAAO,OAAO,KAAK,OAAO;AAAA,UACxB,UAAU,GAAG,QAAQ,QAAQ;AAAA,UAC7B,OAAO,QAAQ;AAAA,UACf,WAAW,QAAQ;AAAA,QACrB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;;;AC9NA,IAAM,cAAc;AAuBb,IAAM,cAAN,MAAkB;AAAA,EACf,aAAuB,CAAC;AAAA,EACxB,aAAa;AAAA,EACb,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EAEzB,YAAY,YAAoB,WAAkC;AAChE,SAAK;AACL,SAAK,WAAW,KAAK,UAAU;AAC/B,QAAI,KAAK,WAAW,SAAS,aAAa;AACxC,WAAK,WAAW,MAAM;AAAA,IACxB;AACA,QAAI,cAAc,QAAW;AAC3B,UAAI,UAAU,WAAW,OAAW,MAAK,cAAc,UAAU;AACjE,UAAI,UAAU,aAAa,OAAW,MAAK,gBAAgB,UAAU;AACrE,UAAI,UAAU,iBAAiB,OAAW,MAAK,oBAAoB,UAAU;AAC7E,UAAI,UAAU,gBAAgB,OAAW,MAAK,mBAAmB,UAAU;AAC3E,UAAI,UAAU,cAAc,OAAW,MAAK,iBAAiB,UAAU;AAAA,IACzE;AAAA,EACF;AAAA,EAEA,cAAmC;AACjC,UAAM,QAAQ,KAAK;AACnB,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO;AAAA,QACL,KAAK;AAAA,QACL,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,cAAc;AAAA,QACd,aAAa;AAAA,QACb,WAAW;AAAA,QACX,YAAY;AAAA,MACd;AAAA,IACF;AAEA,UAAM,MAAM,MAAM,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,MAAM;AACrD,UAAM,SAAS,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAC9C,UAAM,WAAW,KAAK,IAAI,KAAK,MAAM,OAAO,SAAS,IAAI,GAAG,OAAO,SAAS,CAAC;AAC7E,UAAM,YAAY,MAAM,MAAM,SAAS,CAAC,KAAK;AAE7C,WAAO;AAAA,MACL,KAAK,MAAM,IAAI,KAAK,MAAM,MAAO,GAAG,IAAI;AAAA,MACxC,YAAY,KAAK,MAAM,MAAM,GAAG,IAAI;AAAA,MACpC,YAAY,KAAK,OAAO,OAAO,QAAQ,KAAK,KAAK,GAAG,IAAI;AAAA,MACxD,aAAa,KAAK,MAAM,YAAY,GAAG,IAAI;AAAA,MAC3C,YAAY,KAAK,MAAM,KAAK,cAAc,GAAG,IAAI;AAAA,MACjD,UAAU,KAAK,MAAM,KAAK,gBAAgB,GAAG,IAAI;AAAA,MACjD,cAAc,KAAK,MAAM,KAAK,oBAAoB,GAAG,IAAI;AAAA,MACzD,aAAa,KAAK,MAAM,KAAK,mBAAmB,GAAG,IAAI;AAAA,MACvD,WAAW,KAAK,MAAM,KAAK,iBAAiB,GAAG,IAAI;AAAA,MACnD,YAAY,KAAK;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,SAAK,aAAa,CAAC;AACnB,SAAK,aAAa;AAAA,EACpB;AACF;;;AC3DO,IAAM,aAAN,MAAiB;AAAA,EACd,cAAc;AAAA,EACd,cAAc;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,uBAAsC;AAAA,EACtC,iBAAiB;AAAA;AAAA,EACR,QAAQ,IAAI,YAAY;AAAA,EACjC,cAAc,oBAAI,IAA6B;AAAA,EAC/C,kBAA4C;AAAA,EAC5C,eAAgD;AAAA,EAChD,cAAuB;AAAA,EAE/B,YAAY,MAAsB;AAChC,SAAK,WAAW,KAAK;AACrB,SAAK,SAAS,KAAK;AACnB,SAAK,aAAa,KAAK;AACvB,SAAK,QAAQ,KAAK;AAClB,SAAK,WAAW,KAAK;AACrB,SAAK,cAAc,KAAK;AACxB,SAAK,eAAe,KAAK;AACzB,SAAK,iBAAiB,KAAK;AAC3B,SAAK,aAAa,KAAK;AACvB,SAAK,iBAAiB,KAAK;AAAA,EAC7B;AAAA,EAEA,gBAAsB;AACpB,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,QAAc;AACZ,QAAI,KAAK,aAAa;AACpB,WAAK,OAAO;AACZ,WAAK,cAAc;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,UAAM,OAAO,MAAY;AACvB,UAAI,KAAK,aAAa;AACpB,aAAK,OAAO;AACZ,aAAK,cAAc;AAAA,MACrB;AACA,WAAK,cAAc,sBAAsB,IAAI;AAAA,IAC/C;AACA,SAAK,cAAc,sBAAsB,IAAI;AAAA,EAC/C;AAAA,EAEA,OAAa;AACX,yBAAqB,KAAK,WAAW;AAAA,EACvC;AAAA,EAEA,cAAc,OAAe,QAAsB;AACjD,SAAK,SAAS,QAAQ;AACtB,SAAK,SAAS,SAAS;AACvB,UAAM,MAAM,OAAO,qBAAqB,cAAc,mBAAmB;AACzE,SAAK,eAAe,YAAY,QAAQ,KAAK,SAAS,KAAK,GAAG;AAC9D,SAAK,WAAW,OAAO;AAAA,EACzB;AAAA,EAEA,sBAAsB,SAA8B;AAClD,SAAK,uBAAuB;AAAA,EAC9B;AAAA,EAEA,eAAe,SAAuB;AACpC,SAAK,WAAW,UAAU,OAAO;AAAA,EACnC;AAAA,EAEA,qBAA2B;AACzB,SAAK,WAAW,aAAa;AAAA,EAC/B;AAAA,EAEA,WAAgC;AAC9B,WAAO,KAAK,MAAM,YAAY;AAAA,EAChC;AAAA,EAEQ,oBAAoB,KAA+B,SAAuB;AAChF,UAAM,SAAS,KAAK,WAAW,UAAU,OAAO;AAChD,UAAM,SAAS,KAAK,eAAe;AAAA,MACjC,KAAK,OAAO,SAAS;AAAA,MACrB,KAAK,OAAO,SAAS;AAAA,IACvB;AACA,QAAI,KAAK;AACT,QAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACjC,QAAI,UAAU,QAA6B,OAAO,GAAG,OAAO,CAAC;AAC7D,QAAI,QAAQ;AAAA,EACd;AAAA,EAEQ,kBAAwB;AAC9B,UAAM,IAAI,KAAK,eAAe,cAAc;AAC5C,UAAM,IAAI,KAAK,eAAe,eAAe;AAC7C,QACE,KAAK,oBAAoB,QACzB,KAAK,gBAAgB,UAAU,KAC/B,KAAK,gBAAgB,WAAW,GAChC;AACA;AAAA,IACF;AAEA,QAAI,OAAO,oBAAoB,aAAa;AAC1C,WAAK,kBAAkB,IAAI,gBAAgB,GAAG,CAAC;AAAA,IACjD,WAAW,OAAO,aAAa,aAAa;AAC1C,YAAM,KAAK,SAAS,cAAc,QAAQ;AAC1C,SAAG,QAAQ;AACX,SAAG,SAAS;AACZ,WAAK,kBAAkB;AAAA,IACzB,OAAO;AACL,WAAK,kBAAkB;AACvB,WAAK,eAAe;AACpB;AAAA,IACF;AAEA,SAAK,eAAe,KAAK,gBAAgB,WAAW,IAAI;AAAA,EAC1D;AAAA,EAEQ,SAAe;AACrB,UAAM,KAAK,YAAY,IAAI;AAC3B,UAAM,MAAM,KAAK,SAAS,WAAW,IAAI;AACzC,QAAI,CAAC,IAAK;AAEV,QAAI,WAAW;AACf,QAAI,cAAc;AAClB,QAAI,SAAS;AAEb,UAAM,MAAM,OAAO,qBAAqB,cAAc,mBAAmB;AACzE,UAAM,WAAW,KAAK,SAAS;AAC/B,UAAM,YAAY,KAAK,SAAS;AAGhC,SAAK,eAAe,YAAY,UAAU,WAAW,GAAG;AAExD,UAAM,cAAc,KAAK,OAAO;AAChC,UAAM,cAAc,KAAK,OAAO,SAAS;AACzC,UAAM,cAAc,KAAK,OAAO,SAAS;AACzC,QAAI,KAAK,eAAe,cAAc,aAAa,aAAa,WAAW,GAAG;AAC5E,WAAK,eAAe,SAAS,aAAa,aAAa,WAAW;AAClE,WAAK,WAAW,aAAa;AAC7B,WAAK,iBAAiB;AAAA,IACxB;AAEA,QAAI,KAAK;AACT,QAAI,MAAM,KAAK,GAAG;AAElB,SAAK,SAAS,cAAc,UAAU,SAAS;AAC/C,UAAM,iBAAiB,KAAK,MAAM,kBAAkB,MAAM,EAAE,SAAS;AACrE,UAAM,OAAO,YAAY,IAAI;AAC7B,QAAI,gBAAgB;AAClB,UAAI,KAAK;AACT,UAAI,aAAa,KAAK,GAAG,GAAG,KAAK,GAAG,CAAC;AACrC,UAAI,UAAU,GAAG,GAAG,UAAU,SAAS;AACvC,UAAI,QAAQ;AAAA,IACd,OAAO;AACL,WAAK,WAAW,OAAO,KAAK,KAAK,MAAM;AAAA,IACzC;AACA,UAAM,eAAe,YAAY,IAAI,IAAI;AAEzC,QAAI,KAAK;AACT,QAAI,UAAU,KAAK,OAAO,SAAS,GAAG,KAAK,OAAO,SAAS,CAAC;AAC5D,QAAI,MAAM,KAAK,OAAO,MAAM,KAAK,OAAO,IAAI;AAE5C,UAAM,aAAa,KAAK,eAAe,kBAAkB;AACzD,UAAM,UAAU,KAAK,IAAI,WAAW,GAAG,WAAW,CAAC,IAAI;AACvD,UAAM,cAAsB;AAAA,MAC1B,GAAG,WAAW,IAAI;AAAA,MAClB,GAAG,WAAW,IAAI;AAAA,MAClB,GAAG,WAAW,IAAI,UAAU;AAAA,MAC5B,GAAG,WAAW,IAAI,UAAU;AAAA,IAC9B;AAEA,UAAM,cAAc,KAAK,MAAM,OAAO;AACtC,SAAK,YAAY,MAAM;AACvB,UAAM,eAAgC,CAAC;AACvC,QAAI,YAAY;AAEhB,eAAW,WAAW,aAAa;AACjC,UAAI,CAAC,KAAK,aAAa,eAAe,QAAQ,OAAO,GAAG;AACtD,YAAI,KAAK,SAAS,aAAa,OAAO,GAAG;AACvC,eAAK,eAAe,YAAY,QAAQ,EAAE;AAAA,QAC5C;AACA;AAAA,MACF;AAEA,UAAI,KAAK,SAAS,aAAa,OAAO,GAAG;AACvC,cAAM,WAAW,iBAAiB,OAAO;AACzC,YAAI,YAAY,CAAC,gBAAgB,UAAU,WAAW,GAAG;AACvD,eAAK,eAAe,YAAY,QAAQ,EAAE;AAAA,QAC5C,OAAO;AACL,eAAK,eAAe,YAAY,SAAS,WAAW;AAAA,QACtD;AACA;AAAA,MACF;AAGA,UAAI,QAAQ,SAAS,QAAQ;AAC3B,qBAAa,KAAK,OAAO;AACzB;AAAA,MACF;AAEA,UAAI,QAAQ,KAAK,YAAY,IAAI,QAAQ,OAAO;AAChD,UAAI,CAAC,OAAO;AACV,gBAAQ,CAAC;AACT,aAAK,YAAY,IAAI,QAAQ,SAAS,KAAK;AAAA,MAC7C;AACA,YAAM,KAAK,OAAO;AAAA,IACpB;AAEA,eAAW,CAAC,SAAS,QAAQ,KAAK,KAAK,aAAa;AAClD,YAAM,uBAAuB,YAAY,KAAK;AAE9C,UAAI,CAAC,KAAK,WAAW,QAAQ,OAAO,GAAG;AACrC,cAAM,SAAS,YAAY,IAAI;AAC/B,aAAK,oBAAoB,KAAK,OAAO;AACrC,uBAAe,YAAY,IAAI,IAAI;AACnC;AAAA,MACF;AAEA,UAAI,sBAAsB;AACxB,cAAM,SAAS,YAAY,IAAI;AAC/B,aAAK,oBAAoB,KAAK,OAAO;AACrC,uBAAe,YAAY,IAAI,IAAI;AACnC;AAAA,MACF;AAEA,YAAM,SAAS,KAAK,WAAW,WAAW,OAAO;AACjD,UAAI,QAAQ;AACV,cAAM,UAAU,YAAY,IAAI;AAChC,cAAM,YAAY,KAAK,WAAW,UAAU,OAAO;AACnD,eAAO,UAAU,GAAG,GAAG,UAAU,OAAO,UAAU,MAAM;AACxD,eAAO,KAAK;AACZ,aAAK,eAAe,qBAAqB,MAAM;AAC/C,mBAAW,WAAW,UAAU;AAC9B,gBAAM,WAAW,iBAAiB,OAAO;AACzC,cAAI,YAAY,CAAC,gBAAgB,UAAU,WAAW,EAAG;AACzD,eAAK,SAAS,oBAAoB,QAAoC,OAAO;AAAA,QAC/E;AACA,eAAO,QAAQ;AACf,aAAK,WAAW,UAAU,OAAO;AACjC,oBAAY,YAAY,IAAI,IAAI;AAEhC,cAAM,SAAS,YAAY,IAAI;AAC/B,aAAK,oBAAoB,KAAK,OAAO;AACrC,uBAAe,YAAY,IAAI,IAAI;AAAA,MACrC;AAAA,IACF;AAGA,QAAI,aAAa,SAAS,GAAG;AAC3B,YAAM,SAAS,YAAY,IAAI;AAC/B,YAAM,UAAU,aAAa,CAAC;AAC9B,YAAM,YAAY,KAAK,kBAAkB,YAAY,KAAK;AAE1D,UAAI,WAAW;AACb,aAAK,gBAAgB;AACrB,YAAI,KAAK,gBAAgB,KAAK,iBAAiB;AAC7C,gBAAM,KAAK,KAAK,eAAe,kBAAkB;AACjD,eAAK,SAAS,sBAAsB;AAAA,YAClC,MAAM,GAAG;AAAA,YACT,MAAM,GAAG;AAAA,YACT,MAAM,GAAG,IAAI,GAAG;AAAA,YAChB,MAAM,GAAG,IAAI,GAAG;AAAA,UAClB,CAAC;AACD,gBAAM,KAAK,KAAK;AAChB,aAAG,UAAU,GAAG,GAAG,KAAK,gBAAgB,OAAO,KAAK,gBAAgB,MAAM;AAC1E,aAAG,KAAK;AACR,eAAK,eAAe,qBAAqB,EAAE;AAC3C,cAAI;AACF,uBAAW,QAAQ,cAAc;AAC/B,mBAAK,SAAS,oBAAoB,IAAgC,IAAI;AAAA,YACxE;AAAA,UACF,UAAE;AACA,eAAG,QAAQ;AACX,iBAAK,SAAS,sBAAsB,IAAI;AAAA,UAC1C;AAAA,QACF;AACA,aAAK,iBAAiB;AACtB,aAAK,cAAc;AAAA,MACrB;AAEA,UAAI,KAAK,iBAAiB;AACxB,cAAM,SAAS,KAAK,eAAe;AAAA,UACjC,KAAK,OAAO,SAAS;AAAA,UACrB,KAAK,OAAO,SAAS;AAAA,QACvB;AACA,YAAI,KAAK;AACT,YAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACjC,YAAI,UAAU,KAAK,iBAAsC,OAAO,GAAG,OAAO,CAAC;AAC3E,YAAI,QAAQ;AAAA,MACd,OAAO;AACL,mBAAW,QAAQ,cAAc;AAC/B,eAAK,SAAS,oBAAoB,KAAK,IAAI;AAAA,QAC7C;AAAA,MACF;AACA,eAAS,YAAY,IAAI,IAAI;AAAA,IAC/B;AAEA,UAAM,YAAY,YAAY,IAAI;AAClC,UAAM,aAAa,KAAK,YAAY;AACpC,QAAI,YAAY,eAAe;AAC7B,iBAAW,cAAc,GAAG;AAAA,IAC9B;AACA,UAAM,YAAY,YAAY,IAAI,IAAI;AAEtC,QAAI,QAAQ;AACZ,QAAI,QAAQ;AAEZ,SAAK,MAAM,YAAY,YAAY,IAAI,IAAI,IAAI;AAAA,MAC7C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AC3VA,SAAS,sBAAsB,OAAe,QAAqD;AACjG,MAAI,OAAO,oBAAoB,aAAa;AAC1C,WAAO,IAAI,gBAAgB,OAAO,MAAM;AAAA,EAC1C;AACA,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,QAAQ;AACf,SAAO,SAAS;AAChB,SAAO;AACT;AAEO,IAAM,aAAN,MAAiB;AAAA,EAItB,YAA6B,UAA0B;AAA1B;AAAA,EAA2B;AAAA,EAHhD,WAAW,oBAAI,IAAiD;AAAA,EAChE,aAAa,oBAAI,IAAqB;AAAA,EAI9C,QAAQ,SAA0B;AAChC,WAAO,KAAK,WAAW,IAAI,OAAO,MAAM;AAAA,EAC1C;AAAA,EAEA,UAAU,SAAuB;AAC/B,SAAK,WAAW,IAAI,SAAS,IAAI;AAAA,EACnC;AAAA,EAEA,UAAU,SAAuB;AAC/B,SAAK,WAAW,IAAI,SAAS,KAAK;AAAA,EACpC;AAAA,EAEA,eAAqB;AACnB,eAAW,CAAC,EAAE,KAAK,KAAK,YAAY;AAClC,WAAK,WAAW,IAAI,IAAI,IAAI;AAAA,IAC9B;AAAA,EACF;AAAA,EAEA,UAAU,SAAsD;AAC9D,QAAI,SAAS,KAAK,SAAS,IAAI,OAAO;AACtC,QAAI,CAAC,QAAQ;AACX,eAAS,sBAAsB,KAAK,SAAS,cAAc,GAAG,KAAK,SAAS,eAAe,CAAC;AAC5F,WAAK,SAAS,IAAI,SAAS,MAAM;AACjC,WAAK,WAAW,IAAI,SAAS,IAAI;AAAA,IACnC;AACA,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,SAAsF;AAC/F,UAAM,SAAS,KAAK,UAAU,OAAO;AACrC,WAAO,OAAO,WAAW,IAAI;AAAA,EAI/B;AAAA,EAEA,SAAe;AACb,UAAM,IAAI,KAAK,SAAS,cAAc;AACtC,UAAM,IAAI,KAAK,SAAS,eAAe;AACvC,eAAW,CAAC,IAAI,MAAM,KAAK,KAAK,UAAU;AACxC,aAAO,QAAQ;AACf,aAAO,SAAS;AAChB,WAAK,WAAW,IAAI,IAAI,IAAI;AAAA,IAC9B;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,SAAK,SAAS,MAAM;AACpB,SAAK,WAAW,MAAM;AAAA,EACxB;AACF;;;AC3DO,IAAM,iBAAN,MAAqB;AAAA,EAS1B,YAAoB,UAAkB;AAAlB;AAAA,EAAmB;AAAA,EAR/B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa,OAAO;AAAA;AAAA,EACpB,gBAAgB;AAAA,EAIxB,UAAU,UAAwB;AAChC,QAAI,aAAa,KAAK,UAAU;AAC9B,WAAK,WAAW;AAChB,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,YAAY,MAAc,MAAc,KAAmB;AACzD,QAAI,SAAS,KAAK,QAAQ,SAAS,KAAK,QAAQ,QAAQ,KAAK,KAAK;AAChE,WAAK,OAAO;AACZ,WAAK,OAAO;AACZ,WAAK,MAAM;AACX,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,gBAAwB;AACtB,WAAO,KAAK,OAAO,KAAK,OAAO,IAAI,KAAK,YAAY,KAAK,GAAG;AAAA,EAC9D;AAAA,EAEA,iBAAyB;AACvB,WAAO,KAAK,OAAO,KAAK,OAAO,IAAI,KAAK,YAAY,KAAK,GAAG;AAAA,EAC9D;AAAA,EAEA,cAAc,MAAc,MAAc,MAAuB;AAC/D,WACE,KAAK,iBACL,SAAS,KAAK,cACd,KAAK,IAAI,OAAO,KAAK,UAAU,IAAI,KAAK,YACxC,KAAK,IAAI,OAAO,KAAK,UAAU,IAAI,KAAK;AAAA,EAE5C;AAAA,EAEA,SAAS,MAAc,MAAc,MAAoB;AACvD,SAAK,aAAa;AAClB,SAAK,aAAa;AAClB,SAAK,aAAa;AAClB,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA,EAGA,qBAAqB,KAAyE;AAC5F,QAAI,MAAM,KAAK,KAAK,KAAK,GAAG;AAC5B,QAAI,UAAU,KAAK,WAAW,KAAK,YAAY,KAAK,WAAW,KAAK,UAAU;AAC9E,QAAI,MAAM,KAAK,YAAY,KAAK,UAAU;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,MAAc,MAAwC;AACpE,WAAO;AAAA,MACL,IAAI,OAAO,KAAK,aAAa,KAAK,YAAY,KAAK;AAAA,MACnD,IAAI,OAAO,KAAK,aAAa,KAAK,YAAY,KAAK;AAAA,IACrD;AAAA,EACF;AAAA;AAAA,EAGA,oBAA4B;AAC1B,UAAM,IAAI,KAAK;AACf,WAAO;AAAA,MACL,IAAI,CAAC,KAAK,WAAW,KAAK,cAAc;AAAA,MACxC,IAAI,CAAC,KAAK,WAAW,KAAK,cAAc;AAAA,MACxC,IAAI,KAAK,OAAO,IAAI,KAAK,YAAY;AAAA,MACrC,IAAI,KAAK,OAAO,IAAI,KAAK,YAAY;AAAA,IACvC;AAAA,EACF;AACF;;;AC5BO,IAAM,WAAN,MAAe;AAAA,EAsCpB,YACmB,WACjB,UAA2B,CAAC,GAC5B;AAFiB;AAGjB,SAAK,SAAS,IAAI,OAAO,QAAQ,MAAM;AACvC,SAAK,aAAa,IAAI,WAAW,QAAQ,UAAU;AACnD,SAAK,YAAY,QAAQ,YAAY,WAAW;AAChD,SAAK,QAAQ,IAAI,aAAa;AAC9B,SAAK,eAAe,IAAI,aAAa,KAAK,KAAK;AAC/C,SAAK,cAAc,IAAI,YAAY;AACnC,SAAK,WAAW,IAAI,gBAAgB;AACpC,SAAK,SAAS,SAAS,KAAK,KAAK;AACjC,SAAK,SAAS,UAAU,KAAK,MAAM;AACnC,SAAK,SAAS,eAAe,MAAM;AACjC,WAAK,WAAW,mBAAmB;AACnC,WAAK,cAAc;AAAA,IACrB,CAAC;AACD,SAAK,SAAS,gBAAgB,CAAC,KAAK,UAAU;AAC5C,YAAM,aAAuB,CAAC;AAC9B,iBAAW,MAAM,KAAK,MAAM,OAAO,GAAG;AACpC,YAAI,GAAG,SAAS,WAAW,GAAG,QAAQ,IAAK,YAAW,KAAK,GAAG,EAAE;AAAA,MAClE;AACA,UAAI,QAAQ,cAAc;AACxB,gBAAQ,aAAa,EAAE,KAAK,YAAY,MAAM,CAAC;AAAA,MACjD,OAAO;AACL,gBAAQ,KAAK,sCAAsC,GAAG,EAAE;AAAA,MAC1D;AAAA,IACF,CAAC;AACD,SAAK,aAAa,IAAI,WAAW;AAAA,MAC/B,iBAAiB,QAAQ;AAAA,MACzB,SAAS,QAAQ;AAAA,MACjB,aAAa,QAAQ;AAAA,IACvB,CAAC;AACD,SAAK,WAAW,UAAU,CAAC,OAAO,KAAK,eAAe,EAAE,CAAC;AACzD,SAAK,WAAW;AAAA,MACd,MAAM,KAAK,gBAAgB,MAAM;AAAA,MACjC,MAAM,KAAK,gBAAgB,OAAO;AAAA,IACpC;AACA,SAAK,qBAAqB,QAAQ;AAClC,SAAK,cAAc,QAAQ;AAC3B,SAAK,UAAU,IAAI,aAAa;AAChC,SAAK,kBAAkB,IAAI,gBAAgB,KAAK,OAAO,KAAK,SAAS,KAAK,YAAY;AAEtF,SAAK,UAAU,KAAK,cAAc;AAClC,SAAK,WAAW,KAAK,aAAa;AAClC,SAAK,WAAW,KAAK,eAAe;AAEpC,SAAK,QAAQ,YAAY,KAAK,QAAQ;AACtC,SAAK,QAAQ,YAAY,KAAK,QAAQ;AACtC,SAAK,UAAU,YAAY,KAAK,OAAO;AAEvC,SAAK,cAAc;AAAA,MACjB,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK;AAAA,MACZ,eAAe,MAAM,KAAK,cAAc;AAAA,MACxC,YAAY,CAAC,SAAiB,KAAK,YAAY,QAAQ,MAAM,KAAK,WAAW;AAAA,MAC7E,aAAa,CAAC,OAAe,KAAK,oBAAoB,EAAE;AAAA,MACxD,eAAe,CAAC,OAAe,KAAK,cAAc,EAAE;AAAA,MACpD,WAAW,CAAC,WAAmB;AAC7B,aAAK,QAAQ,MAAM,SAAS;AAAA,MAC9B;AAAA,MACA,YAAY;AAAA,MACZ,UAAU,KAAK;AAAA,MACf,eAAe,KAAK,aAAa;AAAA,MACjC,gBAAgB,CAAC,OAAe,KAAK,aAAa,eAAe,EAAE;AAAA,MACnE,eAAe,CAAC,OAAe,KAAK,aAAa,cAAc,EAAE;AAAA,IACnE;AAEA,SAAK,eAAe,IAAI,aAAa,KAAK,SAAS,KAAK,QAAQ;AAAA,MAC9D,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,iBAAiB,KAAK;AAAA,MACtB,cAAc,KAAK;AAAA,MACnB,cAAc,MAAM,KAAK,aAAa;AAAA,MACtC,WAAW,QAAQ;AAAA,IACrB,CAAC;AAED,SAAK,iBAAiB,IAAI,eAAe;AAAA,MACvC,UAAU,KAAK;AAAA,MACf,eAAe,CAAC,OAAO,KAAK,oBAAoB,EAAE;AAAA,MAClD,kBAAkB,CAAC,OACjB,KAAK,WAAW,aAAa,KAAK,WAAW,qBAAqB;AAAA,MACpE,YAAY,CAAC,OAAO,KAAK,MAAM,WAAW,EAAE;AAAA,IAC9C,CAAC;AAED,SAAK,eAAe,IAAI,aAAa;AAAA,MACnC,SAAS,CAAC,OAAO,KAAK,eAAe,QAAQ,EAAE;AAAA,IACjD,CAAC;AAED,SAAK,iBAAiB,IAAI,eAAe,QAAQ,mBAAmB,GAAG;AACvE,SAAK,eAAe;AAAA,MAClB,KAAK,SAAS,eAAe;AAAA,MAC7B,KAAK,SAAS,gBAAgB;AAAA,MAC9B,OAAO,qBAAqB,cAAc,mBAAmB;AAAA,IAC/D;AACA,UAAM,aAAa,IAAI,WAAW,KAAK,cAAc;AAErD,SAAK,aAAa,IAAI,WAAW;AAAA,MAC/B,UAAU,KAAK;AAAA,MACf,QAAQ,KAAK;AAAA,MACb,YAAY,KAAK;AAAA,MACjB,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK;AAAA,MACf,aAAa,KAAK;AAAA,MAClB,cAAc,KAAK;AAAA,MACnB,gBAAgB,KAAK;AAAA,MACrB;AAAA,MACA,gBAAgB,KAAK;AAAA,IACvB,CAAC;AAED,SAAK,cAAc,KAAK,OAAO,SAAS,MAAM;AAC5C,WAAK,qBAAqB;AAC1B,WAAK,WAAW,sBAAsB;AACtC,WAAK,cAAc;AAAA,IACrB,CAAC;AAED,SAAK,aAAa;AAAA,MAChB,KAAK,MAAM,GAAG,OAAO,CAAC,OAAO;AAC3B,YAAI,GAAG,SAAS,OAAQ,MAAK,gBAAgB;AAC7C,aAAK,WAAW,eAAe,GAAG,OAAO;AACzC,aAAK,cAAc;AAAA,MACrB,CAAC;AAAA,MACD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO;AAC9B,YAAI,GAAG,SAAS,OAAQ,MAAK,gBAAgB;AAC7C,aAAK,iBAAiB,EAAE;AACxB,aAAK,eAAe,cAAc,GAAG,EAAE;AACvC,aAAK,WAAW,eAAe,GAAG,OAAO;AACzC,aAAK,cAAc;AAAA,MACrB,CAAC;AAAA,MACD,KAAK,MAAM,GAAG,UAAU,CAAC,EAAE,UAAU,QAAQ,MAAM;AACjD,YAAI,QAAQ,SAAS,OAAQ,MAAK,gBAAgB;AAClD,aAAK,WAAW,eAAe,QAAQ,OAAO;AAC9C,YAAI,SAAS,YAAY,QAAQ,SAAS;AACxC,eAAK,WAAW,eAAe,SAAS,OAAO;AAAA,QACjD;AACA,aAAK,cAAc;AAAA,MACrB,CAAC;AAAA,MACD,KAAK,MAAM,GAAG,SAAS,MAAM;AAC3B,aAAK,eAAe,cAAc;AAClC,aAAK,WAAW,mBAAmB;AACnC,aAAK,gBAAgB;AACrB,aAAK,cAAc;AAAA,MACrB,CAAC;AAAA,IACH;AAEA,SAAK,aAAa,GAAG,UAAU,MAAM;AACnC,WAAK,YAAY,gBAAgB,KAAK,aAAa;AACnD,WAAK,cAAc;AAAA,IACrB,CAAC;AAED,SAAK,QAAQ,iBAAiB,eAAe,KAAK,SAAS;AAC3D,SAAK,QAAQ,iBAAiB,aAAa,KAAK,WAAW;AAC3D,SAAK,QAAQ,iBAAiB,YAAY,KAAK,UAAU;AACzD,SAAK,QAAQ,iBAAiB,QAAQ,KAAK,MAAM;AACjD,SAAK,cAAc;AACnB,SAAK,eAAe;AACpB,SAAK,WAAW,MAAM;AACtB,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAnMS;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACQ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACR;AAAA,EACQ;AAAA,EACT,iBAAwC;AAAA,EACxC,cAAc;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAKA;AAAA,EAIA,sBAAsB,oBAAI,IAAqC;AAAA,EAC/D,oBAAoB,IAAI,kBAAkB;AAAA,EACnD,WAAW;AAAA,EACX,WAAW;AAAA,EAkKnB,IAAI,MAAuC;AACzC,WAAO,KAAK,SAAS,WAAW,IAAI;AAAA,EACtC;AAAA,EAEA,IAAI,aAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,cAAc,SAAwB;AACpC,SAAK,cAAc;AACnB,SAAK,YAAY,aAAa;AAAA,EAChC;AAAA,EAEA,aAAa,UAAU,IAAU;AAC/B,QAAI,KAAK,QAAQ,gBAAgB,KAAK,KAAK,QAAQ,iBAAiB,EAAG;AACvE,UAAM,kBAAkB,KAAK,MAC1B,OAAO,EACP,OAAO,CAAC,OAAO,KAAK,aAAa,eAAe,GAAG,OAAO,CAAC;AAC9D,UAAM,OAAO,uBAAuB,eAAe;AACnD,QAAI,CAAC,KAAM;AACX,SAAK,OAAO,aAAa,MAAM,KAAK,QAAQ,aAAa,KAAK,QAAQ,cAAc,OAAO;AAAA,EAC7F;AAAA,EAEA,gBAAsB;AACpB,SAAK,WAAW,cAAc;AAAA,EAChC;AAAA,EAEA,cAA2B;AACzB,WAAO;AAAA,MACL,KAAK,MAAM,SAAS;AAAA,MACpB,KAAK;AAAA,MACL,KAAK,aAAa,SAAS;AAAA,MAC3B,KAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,aAAqB;AACnB,WAAO,KAAK,UAAU,KAAK,YAAY,CAAC;AAAA,EAC1C;AAAA,EAEA,MAAM,YAAY,SAAoD;AACpE,WAAO,YAAY,KAAK,OAAO,SAAS,KAAK,YAAY;AAAA,EAC3D;AAAA,EAEA,UAAU,OAA0B;AAClC,SAAK,aAAa,oBAAoB;AACtC,SAAK,gBAAgB,MAAM;AAC3B,SAAK,WAAW,QAAQ,KAAK,KAAK;AAClC,SAAK,eAAe,cAAc;AAClC,SAAK,MAAM,aAAa,MAAM,QAAQ;AACtC,QAAI,MAAM,UAAU,MAAM,OAAO,SAAS,GAAG;AAC3C,WAAK,aAAa,aAAa,MAAM,MAAM;AAAA,IAC7C;AACA,QAAI,MAAM,eAAe;AACvB,WAAK,aAAa,eAAe,MAAM,aAAa;AAAA,IACtD;AACA,SAAK,eAAe,oBAAoB,KAAK,KAAK;AAClD,QAAI,KAAK,oBAAoB;AAC3B,iBAAW,MAAM,KAAK,MAAM,kBAAkB,MAAM,GAAG;AACrD,YAAI,CAAC,KAAK,eAAe,WAAW,GAAG,EAAE,GAAG;AAC1C,eAAK,eAAe,YAAY,EAAE;AAClC,gBAAM,OAAO,KAAK,eAAe,QAAQ,GAAG,EAAE;AAC9C,cAAI,MAAM;AACR,iBAAK,mBAAmB,GAAG,IAAI,GAAG,OAAO,IAAI;AAC7C,iBAAK,QAAQ,aAAa,IAAI;AAC9B,mBAAO,OAAO,KAAK,OAAO;AAAA,cACxB,UAAU;AAAA,cACV,eAAe,GAAG,cAAc,SAAS;AAAA,YAC3C,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,SAAK,QAAQ,MAAM;AACnB,SAAK,gBAAgB,OAAO;AAC5B,SAAK,OAAO,OAAO,MAAM,OAAO,SAAS,GAAG,MAAM,OAAO,SAAS,CAAC;AACnE,SAAK,OAAO,QAAQ,MAAM,OAAO,IAAI;AAAA,EACvC;AAAA,EAEA,SAAS,MAAoB;AAC3B,SAAK,UAAU,WAAW,IAAI,CAAC;AAAA,EACjC;AAAA,EAEA,QAAQ,MAAoB;AAC1B,QAAI,CAAC,KAAK,YAAY,QAAQ,IAAI,GAAG;AACnC,cAAQ,KAAK,gDAAgD,IAAI,GAAG;AACpE;AAAA,IACF;AACA,SAAK,YAAY,QAAQ,MAAM,KAAK,WAAW;AAAA,EACjD;AAAA,EAEA,IAAI,YAA0B;AAC5B,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA,EAEA,OAAgB;AACd,SAAK,aAAa,oBAAoB;AACtC,SAAK,gBAAgB,MAAM;AAC3B,UAAM,SAAS,KAAK,QAAQ,KAAK,KAAK,KAAK;AAC3C,SAAK,gBAAgB,OAAO;AAC5B,QAAI,OAAQ,MAAK,cAAc;AAC/B,WAAO;AAAA,EACT;AAAA,EAEA,OAAgB;AACd,SAAK,aAAa,oBAAoB;AACtC,SAAK,gBAAgB,MAAM;AAC3B,UAAM,SAAS,KAAK,QAAQ,KAAK,KAAK,KAAK;AAC3C,SAAK,gBAAgB,OAAO;AAC5B,QAAI,OAAQ,MAAK,cAAc;AAC/B,WAAO;AAAA,EACT;AAAA,EAEA,SAAS,KAAa,UAAoC,OAAO,EAAE,GAAG,KAAK,GAAG,IAAI,GAAW;AAC3F,UAAM,QAAQ,YAAY,EAAE,UAAU,MAAM,KAAK,SAAS,KAAK,aAAa,cAAc,CAAC;AAC3F,SAAK,gBAAgB,MAAM;AAC3B,SAAK,MAAM,IAAI,KAAK;AACpB,SAAK,gBAAgB,OAAO;AAC5B,SAAK,cAAc;AACnB,WAAO,MAAM;AAAA,EACf;AAAA,EAEA,eACE,KACA,UACA,OAAO,EAAE,GAAG,KAAK,GAAG,IAAI,GAChB;AACR,UAAM,QAAQ,IAAI,MAAM;AACxB,UAAM,KAAK,kBAAkB;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,KAAK,aAAa;AAAA,IAC7B,CAAC;AACD,SAAK,eAAe,iBAAiB,GAAG,IAAI,GAAG;AAC/C,SAAK,gBAAgB,MAAM;AAC3B,SAAK,MAAM,IAAI,EAAE;AACjB,SAAK,gBAAgB,OAAO;AAC5B,SAAK,cAAc;AACnB,WAAO,GAAG;AAAA,EACZ;AAAA,EAEA,YAAY,IAAkB;AAC5B,SAAK,gBAAgB,MAAM;AAC3B,SAAK,aAAa,YAAY,EAAE;AAChC,SAAK,gBAAgB,OAAO;AAAA,EAC9B;AAAA,EAEA,kBAAkB,IAAY,YAA+B;AAC3D,UAAM,KAAK,KAAK,MAAM,QAAQ,EAAE;AAChC,QAAI,CAAC,GAAI,OAAM,IAAI,MAAM,sBAAsB,EAAE,EAAE;AACnD,QAAI,GAAG,SAAS,OAAQ,OAAM,IAAI,MAAM,WAAW,EAAE,yBAAyB;AAC9E,SAAK,eAAe,iBAAiB,EAAE;AACvC,SAAK,eAAe,iBAAiB,IAAI,UAAU;AACnD,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,QAAQ,OAOG;AACT,UAAM,WAAW,KAAK,MAAM,kBAAkB,MAAM,EAAE,CAAC;AACvD,SAAK,gBAAgB,MAAM;AAC3B,QAAI,UAAU;AACZ,WAAK,MAAM,OAAO,SAAS,EAAE;AAAA,IAC/B;AACA,UAAM,OAAO,WAAW,EAAE,GAAG,OAAO,SAAS,KAAK,aAAa,cAAc,CAAC;AAC9E,SAAK,MAAM,IAAI,IAAI;AACnB,SAAK,gBAAgB,OAAO;AAC5B,SAAK,cAAc;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,WACE,SAMM;AACN,UAAM,OAAO,KAAK,MAAM,kBAAkB,MAAM,EAAE,CAAC;AACnD,QAAI,CAAC,KAAM;AACX,SAAK,gBAAgB,MAAM;AAC3B,SAAK,MAAM,OAAO,KAAK,IAAI,OAAO;AAClC,SAAK,gBAAgB,OAAO;AAC5B,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,aAAmB;AACjB,UAAM,OAAO,KAAK,MAAM,kBAAkB,MAAM,EAAE,CAAC;AACnD,QAAI,CAAC,KAAM;AACX,SAAK,gBAAgB,MAAM;AAC3B,SAAK,MAAM,OAAO,KAAK,EAAE;AACzB,SAAK,gBAAgB,OAAO;AAC5B,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,cAA+B;AAC7B,UAAM,OAAO,KAAK,MAAM,kBAAkB,MAAM,EAAE,CAAC;AACnD,QAAI,CAAC,KAAM,QAAO;AAClB,WAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf,gBAAgB,KAAK;AAAA,MACrB,UAAU,KAAK;AAAA,MACf,YAAY,KAAK,aAAa,QAAQ,KAAK,WAAW,KAAK,WAAW;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,aAAa,UAAuD;AAClE,SAAK,oBAAoB,IAAI,QAAQ;AACrC,WAAO,MAAM;AACX,WAAK,oBAAoB,OAAO,QAAQ;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,iBAAsC;AACpC,WAAO,KAAK,WAAW,SAAS;AAAA,EAClC;AAAA,EAEA,eAAe,aAAa,KAAkB;AAC5C,UAAM,KAAK,YAAY,MAAM;AAC3B,YAAM,IAAI,KAAK,eAAe;AAC9B,cAAQ;AAAA,QACN,oBAAoB,EAAE,GAAG,UAAU,EAAE,UAAU,UAAU,EAAE,UAAU,WAAW,EAAE,UAAU,aAAa,EAAE,QAAQ,WAAW,EAAE,WAAW,SAAS,EAAE,YAAY,cAAc,EAAE,SAAS;AAAA,MAC7L;AAAA,IACF,GAAG,UAAU;AACb,WAAO,MAAM,cAAc,EAAE;AAAA,EAC/B;AAAA,EAEA,UAAgB;AACd,SAAK,WAAW,KAAK;AACrB,SAAK,aAAa,QAAQ;AAC1B,SAAK,WAAW,QAAQ,KAAK,KAAK;AAClC,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,QAAQ,oBAAoB,eAAe,KAAK,SAAS;AAC9D,SAAK,QAAQ,oBAAoB,aAAa,KAAK,WAAW;AAC9D,SAAK,QAAQ,oBAAoB,YAAY,KAAK,UAAU;AAC5D,SAAK,QAAQ,oBAAoB,QAAQ,KAAK,MAAM;AACpD,SAAK,aAAa,QAAQ;AAC1B,SAAK,YAAY;AACjB,SAAK,WAAW,QAAQ,CAAC,OAAO,GAAG,CAAC;AACpC,SAAK,gBAAgB,WAAW;AAChC,SAAK,iBAAiB;AACtB,SAAK,QAAQ,OAAO;AAAA,EACtB;AAAA,EAEQ,oBAAoB,IAAkB;AAC5C,UAAM,UAAU,KAAK,MAAM,QAAQ,EAAE;AACrC,QAAI,CAAC,WAAY,QAAQ,SAAS,UAAU,QAAQ,SAAS,OAAS;AAEtE,SAAK,WAAW,MAAM;AAEtB,UAAM,OAAO,KAAK,eAAe,QAAQ,EAAE;AAC3C,QAAI,MAAM;AACR,WAAK,WAAW,aAAa,MAAM,IAAI,KAAK,KAAK;AAAA,IACnD;AAAA,EACF;AAAA,EAEQ,cAAc,WAAyB;AAC7C,UAAM,UAAU,KAAK,MAAM,QAAQ,SAAS;AAC5C,QAAI,CAAC,WAAW,QAAQ,SAAS,OAAQ;AACzC,QAAI,mBAAmB,QAAQ,IAAI,EAAG;AACtC,UAAM,OAAO,KAAK,eAAe,QAAQ,SAAS;AAClD,QAAI,CAAC,KAAM;AACX,UAAM,WAAW,KAAK;AACtB,QAAI,WAAW,QAAQ,KAAK,GAAG;AAC7B,WAAK,MAAM,OAAO,WAAW,EAAE,MAAM,EAAE,GAAG,QAAQ,KAAK,GAAG,GAAG,SAAS,EAAE,CAAC;AAAA,IAC3E;AAAA,EACF;AAAA,EAEQ,eAAe,WAAyB;AAC9C,UAAM,UAAU,KAAK,MAAM,QAAQ,SAAS;AAC5C,QAAI,CAAC,QAAS;AAEd,QAAI,QAAQ,SAAS,QAAQ;AAC3B,UAAI,mBAAmB,QAAQ,IAAI,GAAG;AACpC,aAAK,MAAM,OAAO,SAAS;AAC3B;AAAA,MACF;AACA,WAAK,cAAc,SAAS;AAC5B;AAAA,IACF;AAEA,QAAI,QAAQ,SAAS,OAAQ;AAE7B,QAAI,CAAC,QAAQ,QAAQ,QAAQ,KAAK,KAAK,MAAM,IAAI;AAC/C,WAAK,MAAM,OAAO,SAAS;AAC3B;AAAA,IACF;AAEA,UAAM,OAAO,KAAK,eAAe,QAAQ,SAAS;AAClD,QAAI,QAAQ,UAAU,SAAS;AAC7B,YAAM,WAAW,KAAK;AACtB,UAAI,aAAa,QAAQ,KAAK,GAAG;AAC/B,aAAK,MAAM,OAAO,WAAW,EAAE,MAAM,EAAE,GAAG,QAAQ,KAAK,GAAG,GAAG,SAAS,EAAE,CAAC;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,YAAY,CAAC,MAA0B;AAC7C,SAAK,WAAW,EAAE;AAClB,SAAK,WAAW,EAAE;AAAA,EACpB;AAAA,EAEQ,cAAc,CAAC,MAA0B;AAC/C,UAAM,KAAK,EAAE,UAAU,KAAK;AAC5B,UAAM,KAAK,EAAE,UAAU,KAAK;AAC5B,UAAM,QAAQ,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACzC,QAAI,QAAQ,GAAI;AAEhB,QAAI,CAAC,KAAK,kBAAkB,KAAK,CAAC,EAAG;AACrC,QAAI,OAAO,SAAS,qBAAqB,WAAY;AAErD,UAAM,KAAK,SAAS,iBAAiB,EAAE,SAAS,EAAE,OAAO;AAEzD,UAAM,SAAU,IAA2B,QAAwB,mBAAmB;AACtF,QAAI,QAAQ;AACV,YAAM,YAAY,OAAO,QAAQ,WAAW;AAC5C,UAAI,WAAW;AACb,cAAM,UAAU,KAAK,MAAM,QAAQ,SAAS;AAC5C,YAAI,SAAS,SAAS,UAAU,SAAS,SAAS,QAAQ;AACxD,eAAK,oBAAoB,SAAS;AAClC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,KAAK,QAAQ,sBAAsB;AAChD,UAAM,SAAS,EAAE,GAAG,EAAE,UAAU,KAAK,MAAM,GAAG,EAAE,UAAU,KAAK,IAAI;AACnE,UAAM,QAAQ,KAAK,OAAO,cAAc,MAAM;AAC9C,UAAM,MAAM,KAAK,aAAa,KAAK;AACnC,QAAI,KAAK,SAAS,QAAQ;AACxB,WAAK,aAAa,iBAAiB,IAAI,EAAE;AAAA,IAC3C;AAAA,EACF;AAAA,EAEQ,aAAa,OAAuD;AAC1E,UAAM,aAAa,KAAK,MAAM,WAAW,KAAK,EAAE,QAAQ;AACxD,eAAW,MAAM,YAAY;AAC3B,UAAI,EAAE,UAAU,IAAK;AACrB,YAAM,EAAE,GAAG,EAAE,IAAI,GAAG;AACpB,YAAM,EAAE,GAAG,EAAE,IAAI,GAAG;AACpB,UAAI,MAAM,KAAK,KAAK,MAAM,KAAK,IAAI,KAAK,MAAM,KAAK,KAAK,MAAM,KAAK,IAAI,GAAG;AACxE,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,kBAAwB;AACtB,SAAK,aAAa,gBAAgB;AAAA,EACpC;AAAA,EAEQ,aAAa,CAAC,MAAuB;AAC3C,MAAE,eAAe;AAAA,EACnB;AAAA,EAEQ,SAAS,CAAC,MAAuB;AACvC,MAAE,eAAe;AACjB,UAAM,OAAO,KAAK,QAAQ,sBAAsB;AAChD,UAAM,YAAY,EAAE,GAAG,EAAE,UAAU,KAAK,MAAM,GAAG,EAAE,UAAU,KAAK,IAAI;AACtE,UAAM,WAAW,KAAK,OAAO,cAAc,SAAS;AAEpD,QAAI,KAAK,aAAa;AACpB,WAAK,YAAY,GAAG,QAAQ;AAC5B;AAAA,IACF;AAEA,UAAM,QAAQ,EAAE,cAAc;AAC9B,QAAI,CAAC,MAAO;AAEZ,eAAW,QAAQ,OAAO;AACxB,UAAI,CAAC,KAAK,KAAK,WAAW,QAAQ,EAAG;AAErC,YAAM,SAAS,IAAI,WAAW;AAC9B,aAAO,SAAS,MAAM;AACpB,cAAM,MAAM,OAAO;AACnB,YAAI,OAAO,QAAQ,SAAU;AAC7B,aAAK,SAAS,KAAK,QAAQ;AAAA,MAC7B;AACA,aAAO,cAAc,IAAI;AAAA,IAC3B;AAAA,EACF;AAAA,EAEQ,iBAAiB,gBAAqC;AAC5D,UAAM,cAAc,gBAAgB,eAAe,IAAI,KAAK,KAAK;AACjE,UAAM,SAAS,iBAAiB,cAAc;AAE9C,eAAW,SAAS,aAAa;AAC/B,YAAM,UAAiC,CAAC;AAExC,UAAI,MAAM,aAAa,cAAc,eAAe,IAAI;AACtD,gBAAQ,cAAc;AACtB,YAAI,QAAQ;AACV,gBAAM,QAAQ,qBAAqB,MAAM,MAAM,MAAM,IAAI,MAAM,MAAM,CAAC;AACtE,gBAAM,YAAY;AAAA,YAChB,GAAG,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI;AAAA,YACpC,GAAG,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI;AAAA,UACtC;AACA,gBAAM,OAAO,oBAAoB,QAAQ,SAAS;AAClD,kBAAQ,OAAO;AACf,kBAAQ,WAAW;AAAA,QACrB;AAAA,MACF;AAEA,UAAI,MAAM,WAAW,cAAc,eAAe,IAAI;AACpD,gBAAQ,YAAY;AACpB,YAAI,QAAQ;AACV,gBAAM,QAAQ,qBAAqB,MAAM,MAAM,MAAM,IAAI,MAAM,MAAM,CAAC;AACtE,gBAAM,YAAY;AAAA,YAChB,GAAG,MAAM,GAAG,IAAI,KAAK,IAAI,KAAK,IAAI;AAAA,YAClC,GAAG,MAAM,GAAG,IAAI,KAAK,IAAI,KAAK,IAAI;AAAA,UACpC;AACA,kBAAQ,KAAK,oBAAoB,QAAQ,SAAS;AAAA,QACpD;AAAA,MACF;AAEA,UAAI,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AACnC,aAAK,MAAM,OAAO,MAAM,IAAI,OAAO;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBAAgC;AACtC,UAAM,KAAK,SAAS,cAAc,KAAK;AACvC,WAAO,OAAO,GAAG,OAAO;AAAA,MACtB,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,oBAAoB;AAAA,MACpB,YAAY;AAAA,MACZ,kBAAkB;AAAA,IACpB,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEQ,eAAkC;AACxC,UAAM,KAAK,SAAS,cAAc,QAAQ;AAC1C,WAAO,OAAO,GAAG,OAAO;AAAA,MACtB,UAAU;AAAA,MACV,KAAK;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,IACV,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAiC;AACvC,UAAM,KAAK,SAAS,cAAc,KAAK;AACvC,WAAO,OAAO,GAAG,OAAO;AAAA,MACtB,UAAU;AAAA,MACV,KAAK;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,eAAe;AAAA,MACf,iBAAiB;AAAA,IACnB,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEQ,uBAA6B;AACnC,SAAK,SAAS,MAAM,YAAY,KAAK,OAAO,eAAe;AAAA,EAC7D;AAAA,EAEQ,iBAAuB;AAC7B,UAAM,OAAO,KAAK,UAAU,sBAAsB;AAClD,UAAM,MAAM,OAAO,qBAAqB,cAAc,mBAAmB;AACzE,SAAK,WAAW,cAAc,KAAK,QAAQ,KAAK,KAAK,SAAS,GAAG;AACjE,SAAK,cAAc;AAAA,EACrB;AAAA,EAEQ,kBAAwB;AAC9B,UAAM,OAAO,KAAK,MAAM,kBAAkB,MAAM,EAAE,CAAC;AACnD,QAAI,MAAM;AACR,WAAK,YAAY,WAAW,KAAK;AACjC,WAAK,YAAY,WAAW,KAAK;AACjC,WAAK,YAAY,iBAAiB,KAAK;AAAA,IACzC,OAAO;AACL,WAAK,YAAY,WAAW,KAAK;AACjC,WAAK,YAAY,WAAW;AAC5B,WAAK,YAAY,iBAAiB;AAAA,IACpC;AACA,SAAK,0BAA0B;AAAA,EACjC;AAAA,EAEQ,4BAAkC;AACxC,UAAM,OAAO,KAAK,YAAY;AAC9B,eAAW,YAAY,KAAK,qBAAqB;AAC/C,eAAS,IAAI;AAAA,IACf;AAAA,EACF;AAAA,EAEQ,gBAAsB;AAC5B,QAAI,OAAO,mBAAmB,YAAa;AAC3C,SAAK,iBAAiB,IAAI,eAAe,MAAM,KAAK,eAAe,CAAC;AACpE,SAAK,eAAe,QAAQ,KAAK,SAAS;AAAA,EAC5C;AACF;;;ACxvBO,IAAM,WAAN,MAA+B;AAAA,EAC3B,OAAO;AAAA,EACR,UAAU;AAAA,EACV,aAAa,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAElC,WAAW,KAAwB;AACjC,QAAI,YAAY,MAAM;AAAA,EACxB;AAAA,EAEA,aAAa,KAAwB;AACnC,QAAI,YAAY,SAAS;AAAA,EAC3B;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,SAAK,UAAU;AACf,SAAK,aAAa,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE;AAC3C,QAAI,YAAY,UAAU;AAAA,EAC5B;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,QAAI,CAAC,KAAK,QAAS;AACnB,UAAM,KAAK,MAAM,IAAI,KAAK,WAAW;AACrC,UAAM,KAAK,MAAM,IAAI,KAAK,WAAW;AACrC,SAAK,aAAa,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE;AAC3C,QAAI,OAAO,IAAI,IAAI,EAAE;AAAA,EACvB;AAAA,EAEA,YAAY,QAAsB,KAAwB;AACxD,SAAK,UAAU;AACf,QAAI,YAAY,MAAM;AAAA,EACxB;AACF;;;ACnBA,IAAM,wBAAwB;AAC9B,IAAM,oBAAoB;AAC1B,IAAM,mBAAmB;AACzB,IAAM,6BAA6B;AACnC,IAAM,gCAAgC;AACtC,IAAM,uBAAuB;AAEtB,IAAM,aAAN,MAAiC;AAAA,EAC7B,OAAO;AAAA,EACR,UAAU;AAAA,EACV,SAAwB,CAAC;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB,oBAAI,IAAgB;AAAA,EAE9C,YAAY,UAA6B,CAAC,GAAG;AAC3C,SAAK,QAAQ,QAAQ,SAAS;AAC9B,SAAK,QAAQ,QAAQ,SAAS;AAC9B,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,mBAAmB,QAAQ,oBAAoB;AACpD,SAAK,uBACH,QAAQ,gCAAgC;AAC1C,SAAK,iBAAiB,KAAK;AAAA,EAC7B;AAAA,EAEA,WAAW,KAAwB;AACjC,QAAI,YAAY,WAAW;AAAA,EAC7B;AAAA,EAEA,aAAa,KAAwB;AACnC,QAAI,YAAY,SAAS;AAAA,EAC3B;AAAA,EAEA,aAAgC;AAC9B,WAAO;AAAA,MACL,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ,WAAW,KAAK;AAAA,MAChB,kBAAkB,KAAK;AAAA,MACvB,8BAA8B,KAAK;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,gBAAgB,UAAkC;AAChD,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO,MAAM,KAAK,gBAAgB,OAAO,QAAQ;AAAA,EACnD;AAAA,EAEA,WAAW,SAAkC;AAC3C,QAAI,QAAQ,UAAU,OAAW,MAAK,QAAQ,QAAQ;AACtD,QAAI,QAAQ,UAAU,OAAW,MAAK,QAAQ,QAAQ;AACtD,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,qBAAqB,OAAW,MAAK,mBAAmB,QAAQ;AAC5E,QAAI,QAAQ,iCAAiC;AAC3C,WAAK,uBAAuB,QAAQ;AACtC,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,SAAK,UAAU;AACf,UAAM,QAAQ,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AACjE,UAAM,WAAW,MAAM,aAAa,IAAI,mBAAmB,MAAM;AACjE,SAAK,SAAS,CAAC,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,SAAS,CAAC;AACnD,SAAK,iBAAiB,KAAK;AAAA,EAC7B;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,QAAI,CAAC,KAAK,QAAS;AACnB,UAAM,QAAQ,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AACjE,UAAM,WAAW,MAAM,aAAa,IAAI,mBAAmB,MAAM;AAEjE,UAAM,OAAO,KAAK,OAAO,KAAK,OAAO,SAAS,CAAC;AAC/C,QAAI,MAAM;AACR,YAAM,KAAK,MAAM,IAAI,KAAK;AAC1B,YAAM,KAAK,MAAM,IAAI,KAAK;AAC1B,UAAI,KAAK,KAAK,KAAK,KAAK,KAAK,mBAAmB,KAAK,iBAAkB;AAAA,IACzE;AAEA,SAAK,OAAO,KAAK,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,SAAS,CAAC;AAIrD,QAAI,KAAK,OAAO,SAAS,KAAK,gBAAgB;AAC5C,YAAM,UAAU,KAAK,OAAO,MAAM,CAAC,oBAAoB;AACvD,YAAM,WAAW,KAAK,OAAO,MAAM,GAAG,CAAC,oBAAoB;AAC3D,YAAM,aAAa,eAAe,UAAU,KAAK,YAAY,CAAC;AAC9D,WAAK,SAAS,CAAC,GAAG,YAAY,GAAG,OAAO;AACxC,WAAK,iBAAiB,KAAK,OAAO,SAAS,KAAK;AAAA,IAClD;AAEA,QAAI,cAAc;AAAA,EACpB;AAAA,EAEA,YAAY,QAAsB,KAAwB;AACxD,QAAI,CAAC,KAAK,QAAS;AACnB,SAAK,UAAU;AAEf,QAAI,KAAK,OAAO,SAAS,uBAAuB;AAC9C,WAAK,SAAS,CAAC;AACf;AAAA,IACF;AAEA,UAAM,aAAa,eAAe,KAAK,QAAQ,KAAK,SAAS;AAC7D,UAAM,SAAS,aAAa;AAAA,MAC1B,QAAQ;AAAA,MACR,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ,SAAS,IAAI,iBAAiB;AAAA,IAChC,CAAC;AACD,QAAI,MAAM,IAAI,MAAM;AACpB,0BAAsB,MAAM;AAC5B,SAAK,SAAS,CAAC;AACf,QAAI,cAAc;AAAA,EACpB;AAAA,EAEQ,sBAA4B;AAClC,eAAW,YAAY,KAAK,gBAAiB,UAAS;AAAA,EACxD;AAAA,EAEA,cAAc,KAAqC;AACjD,QAAI,CAAC,KAAK,WAAW,KAAK,OAAO,SAAS,EAAG;AAE7C,QAAI,KAAK;AACT,QAAI,cAAc,KAAK;AACvB,QAAI,UAAU;AACd,QAAI,WAAW;AACf,QAAI,cAAc;AAElB,UAAM,WAAW,iBAAiB,KAAK,MAAM;AAC7C,eAAW,OAAO,UAAU;AAC1B,YAAM,KACH,gBAAgB,IAAI,MAAM,UAAU,KAAK,KAAK,IAC7C,gBAAgB,IAAI,IAAI,UAAU,KAAK,KAAK,KAC9C;AACF,UAAI,YAAY;AAChB,UAAI,UAAU;AACd,UAAI,OAAO,IAAI,MAAM,GAAG,IAAI,MAAM,CAAC;AACnC,UAAI,cAAc,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,CAAC;AAClF,UAAI,OAAO;AAAA,IACb;AAEA,QAAI,QAAQ;AAAA,EACd;AACF;;;AC3JO,SAAS,cAAc,QAAuB,OAAc,QAAyB;AAC1F,QAAM,SAAS,iBAAiB,MAAM;AACtC,MAAI,CAAC,OAAQ,QAAO;AACpB,MACE,MAAM,IAAI,OAAO,IAAI,UACrB,MAAM,IAAI,OAAO,IAAI,OAAO,IAAI,UAChC,MAAM,IAAI,OAAO,IAAI,UACrB,MAAM,IAAI,OAAO,IAAI,OAAO,IAAI,QAChC;AACA,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,SAAS;AAC1B,QAAM,QAAe,EAAE,GAAG,MAAM,IAAI,OAAO,SAAS,GAAG,GAAG,MAAM,IAAI,OAAO,SAAS,EAAE;AACtF,QAAM,EAAE,SAAS,IAAI,oBAAoB,MAAM;AAE/C,MAAI,SAAS,WAAW,GAAG;AACzB,UAAM,IAAI,OAAO,OAAO,CAAC;AACzB,QAAI,CAAC,EAAG,QAAO;AACf,UAAM,KAAK,EAAE,IAAI,MAAM;AACvB,UAAM,KAAK,EAAE,IAAI,MAAM;AACvB,WAAO,KAAK,KAAK,KAAK,MAAM;AAAA,EAC9B;AAEA,aAAW,OAAO,UAAU;AAC1B,QAAI,gBAAgB,OAAO,IAAI,OAAO,IAAI,GAAG,KAAK,SAAU,QAAO;AAAA,EACrE;AACA,SAAO;AACT;;;ACzBA,IAAM,iBAAiB;AAEvB,SAAS,iBAAiB,QAAwB;AAChD,QAAM,OAAO,SAAS;AACtB,QAAM,MAAM,kDAAkD,IAAI,aAAa,IAAI,iBAAiB,MAAM,SAAS,MAAM,QAAQ,SAAS,CAAC;AAC3I,SAAO,2BAA2B,GAAG,MAAM,MAAM,IAAI,MAAM;AAC7D;AAEO,IAAM,aAAN,MAAiC;AAAA,EAC7B,OAAO;AAAA,EACR,UAAU;AAAA,EACD;AAAA,EACA;AAAA,EAEjB,YAAY,UAA6B,CAAC,GAAG;AAC3C,SAAK,SAAS,QAAQ,UAAU;AAChC,SAAK,SAAS,iBAAiB,KAAK,MAAM;AAAA,EAC5C;AAAA,EAEA,aAAgC;AAC9B,WAAO,EAAE,QAAQ,KAAK,OAAO;AAAA,EAC/B;AAAA,EAEA,WAAW,KAAwB;AACjC,QAAI,YAAY,KAAK,MAAM;AAAA,EAC7B;AAAA,EAEA,aAAa,KAAwB;AACnC,QAAI,YAAY,SAAS;AAAA,EAC3B;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,SAAK,UAAU;AACf,SAAK,QAAQ,OAAO,GAAG;AAAA,EACzB;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,QAAI,CAAC,KAAK,QAAS;AACnB,SAAK,QAAQ,OAAO,GAAG;AAAA,EACzB;AAAA,EAEA,YAAY,QAAsB,MAAyB;AACzD,SAAK,UAAU;AAAA,EACjB;AAAA,EAEQ,QAAQ,OAAqB,KAAwB;AAC3D,UAAM,QAAQ,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AACjE,UAAM,cAAsB;AAAA,MAC1B,GAAG,MAAM,IAAI,KAAK;AAAA,MAClB,GAAG,MAAM,IAAI,KAAK;AAAA,MAClB,GAAG,KAAK,SAAS;AAAA,MACjB,GAAG,KAAK,SAAS;AAAA,IACnB;AACA,UAAM,aAAa,IAAI,MAAM,UAAU,WAAW;AAClD,QAAI,SAAS;AAEb,eAAW,MAAM,YAAY;AAC3B,UAAI,GAAG,SAAS,SAAU;AAC1B,UAAI,IAAI,kBAAkB,CAAC,IAAI,eAAe,GAAG,OAAO,EAAG;AAC3D,UAAI,IAAI,iBAAiB,IAAI,cAAc,GAAG,OAAO,EAAG;AACxD,UAAI,KAAK,iBAAiB,IAAI,KAAK,GAAG;AACpC,YAAI,MAAM,OAAO,GAAG,EAAE;AACtB,iBAAS;AAAA,MACX;AAAA,IACF;AAEA,QAAI,OAAQ,KAAI,cAAc;AAAA,EAChC;AAAA,EAEQ,iBAAiB,QAAuB,OAAuB;AACrE,WAAO,cAAc,QAAQ,OAAO,KAAK,MAAM;AAAA,EACjD;AACF;;;AC1EA,IAAM,iBAAiB;AAIvB,IAAM,gBAAgB;AACtB,IAAM,qBAAqB;AAE3B,IAAM,uBAAoD;AAAA,EACxD,OAAO;AAAA,EACP,KAAK;AAAA,EACL,KAAK;AACP;AAEO,SAAS,qBAAqB,QAAqB,QAAyB;AACjF,MAAI,WAAW,SAAS,OAAQ,QAAO;AACvC,SAAO,qBAAqB,MAAM;AACpC;AAEO,SAAS,wBAAwB,OAA6C;AACnF,QAAM,MAAM,iBAAiB,MAAM,MAAM,MAAM,IAAI,MAAM,IAAI;AAC7D,SAAO;AAAA,IACL,CAAC,SAAS,MAAM,IAAI;AAAA,IACpB,CAAC,OAAO,GAAG;AAAA,IACX,CAAC,OAAO,MAAM,EAAE;AAAA,EAClB;AACF;AAEO,SAAS,oBACd,OACA,aACA,KACmD;AACnD,MAAI,YAAY,WAAW,EAAG,QAAO;AAErC,QAAM,OAAO,IAAI,OAAO;AACxB,QAAM,aAAa,gBAAgB,sBAAsB;AAEzD,aAAW,MAAM,aAAa;AAC5B,UAAM,KAAK,IAAI,MAAM,QAAQ,EAAE;AAC/B,QAAI,CAAC,MAAM,GAAG,SAAS,QAAS;AAEhC,UAAM,UAAU,wBAAwB,EAAE;AAC1C,eAAW,CAAC,QAAQ,GAAG,KAAK,SAAS;AACnC,YAAM,KAAK,MAAM,IAAI,IAAI;AACzB,YAAM,KAAK,MAAM,IAAI,IAAI;AACzB,UAAI,KAAK,KAAK,KAAK,MAAM,YAAY,WAAW;AAC9C,eAAO,EAAE,WAAW,IAAI,OAAO;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,qBACd,QACA,WACA,OACA,KACM;AACN,QAAM,KAAK,IAAI,MAAM,QAAQ,SAAS;AACtC,MAAI,CAAC,MAAM,GAAG,SAAS,QAAS;AAEhC,QAAM,YAAY,iBAAiB,IAAI,OAAO;AAE9C,QAAM,cAAc,CAAC,cAA6B,UAAU,YAAY,GAAG;AAE3E,UAAQ,QAAQ;AAAA,IACd,KAAK,SAAS;AACZ,YAAM,YAAY,GAAG,WAAW;AAChC,YAAM,SAAS,eAAe,OAAO,IAAI,OAAO,WAAW,WAAW,WAAW;AACjF,UAAI,QAAQ;AACV,cAAM,SAAS,iBAAiB,MAAM;AACtC,YAAI,MAAM,OAAO,WAAW;AAAA,UAC1B,MAAM;AAAA,UACN,UAAU;AAAA,UACV,aAAa,EAAE,WAAW,OAAO,GAAG;AAAA,QACtC,CAAC;AAAA,MACH,OAAO;AACL,YAAI,MAAM,OAAO,WAAW;AAAA,UAC1B,MAAM,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE;AAAA,UAC/B,UAAU,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE;AAAA,UACnC,aAAa;AAAA,QACf,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAAA,IACA,KAAK,OAAO;AACV,YAAM,YAAY,GAAG,aAAa;AAClC,YAAM,SAAS,eAAe,OAAO,IAAI,OAAO,WAAW,WAAW,WAAW;AACjF,UAAI,QAAQ;AACV,cAAM,SAAS,iBAAiB,MAAM;AACtC,YAAI,MAAM,OAAO,WAAW;AAAA,UAC1B,IAAI;AAAA,UACJ,WAAW,EAAE,WAAW,OAAO,GAAG;AAAA,QACpC,CAAC;AAAA,MACH,OAAO;AACL,YAAI,MAAM,OAAO,WAAW;AAAA,UAC1B,IAAI,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE;AAAA,UAC7B,WAAW;AAAA,QACb,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAAA,IACA,KAAK,OAAO;AACV,YAAM,OAAO,iBAAiB,GAAG,MAAM,GAAG,IAAI,KAAK;AACnD,UAAI,MAAM,OAAO,WAAW,EAAE,KAAK,CAAC;AACpC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,cAAc;AACpB;AAEO,SAAS,yBACd,QACA,WACA,OACA,KACuD;AACvD,MAAI,WAAW,MAAO,QAAO;AAE7B,QAAM,KAAK,IAAI,MAAM,QAAQ,SAAS;AACtC,MAAI,CAAC,MAAM,GAAG,SAAS,QAAS,QAAO;AAEvC,QAAM,YAAY,iBAAiB,IAAI,OAAO;AAC9C,QAAM,YAAY,WAAW,UAAU,GAAG,WAAW,YAAY,GAAG,aAAa;AACjF,QAAM,cAAc,CAAC,cAA6B,UAAU,YAAY,GAAG;AAC3E,QAAM,SAAS,eAAe,OAAO,IAAI,OAAO,WAAW,WAAW,WAAW;AACjF,MAAI,CAAC,OAAQ,QAAO;AAEpB,SAAO,iBAAiB,MAAM;AAChC;AAEO,SAAS,mBACd,WACA,OACA,MACM;AACN,QAAM,SAAS,gBAAgB;AAC/B,QAAM,UAAU,wBAAwB,KAAK;AAE7C,YAAU,YAAY,CAAC,CAAC;AACxB,YAAU,YAAY,MAAM;AAE5B,aAAW,CAAC,QAAQ,GAAG,KAAK,SAAS;AACnC,cAAU,YAAY,WAAW,QAAQ,YAAY;AACrD,cAAU,cAAc;AAExB,cAAU,UAAU;AACpB,cAAU,IAAI,IAAI,GAAG,IAAI,GAAG,QAAQ,GAAG,KAAK,KAAK,CAAC;AAClD,cAAU,KAAK;AACf,cAAU,OAAO;AAAA,EACnB;AACF;;;AC9IA,IAAM,cAAc;AACpB,IAAMC,sBAAqB;AAC3B,IAAM,gBAAgB;AACtB,IAAM,mBAAmB;AAEzB,IAAM,iBAAiD;AAAA,EACrD,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAUO,IAAM,aAAN,MAAiC;AAAA,EAC7B,OAAO;AAAA,EACR,eAAyB,CAAC;AAAA,EAC1B,OAAa,EAAE,MAAM,OAAO;AAAA,EAC5B,YAAmB,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAChC,eAAsB,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EACnC,MAA0B;AAAA,EAC1B,wBAAuC;AAAA,EACvC,aAAa;AAAA,EACb,oBAAoB;AAAA,EACpB,YAA2B;AAAA,EAEnC,IAAI,cAAwB;AAC1B,WAAO,CAAC,GAAG,KAAK,YAAY;AAAA,EAC9B;AAAA,EAEA,aAAa,KAAqB;AAChC,SAAK,eAAe;AACpB,SAAK,KAAK,cAAc;AAAA,EAC1B;AAAA,EAEA,IAAI,kBAA2B;AAC7B,WAAO,KAAK,KAAK,SAAS;AAAA,EAC5B;AAAA,EAEA,WAAW,KAAwB;AACjC,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,aAAa,KAAwB;AACnC,SAAK,eAAe,CAAC;AACrB,SAAK,OAAO,EAAE,MAAM,OAAO;AAC3B,SAAK,YAAY;AACjB,QAAI,YAAY,SAAS;AAAA,EAC3B;AAAA,EAEQ,KAAK,OAAc,KAAyB;AAClD,WAAO,UAAU,OAAO,GAAG;AAAA,EAC7B;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,SAAK,MAAM;AACX,SAAK,WAAW,MAAM,GAAG;AACzB,UAAM,QAAQ,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AACjE,SAAK,YAAY,KAAK,KAAK,OAAO,GAAG;AACrC,SAAK,eAAe;AAEpB,UAAM,WAAW,oBAAoB,OAAO,KAAK,cAAc,GAAG;AAClE,QAAI,UAAU;AACZ,WAAK,OAAO;AAAA,QACV,MAAM;AAAA,QACN,WAAW,SAAS;AAAA,QACpB,QAAQ,SAAS;AAAA,MACnB;AACA,UAAI,cAAc;AAClB;AAAA,IACF;AAEA,UAAM,oBAAoB,KAAK,4BAA4B,OAAO,GAAG;AACrE,QAAI,mBAAmB;AACrB,WAAK,OAAO,EAAE,MAAM,qBAAqB,WAAW,kBAAkB;AACtE,UAAI,cAAc;AAClB;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,oBAAoB,OAAO,GAAG;AACrD,QAAI,WAAW;AACb,YAAM,KAAK,IAAI,MAAM,QAAQ,UAAU,SAAS;AAChD,UAAI,MAAM,UAAU,IAAI;AACtB,aAAK,oBAAoB,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI;AACjE,aAAK,OAAO;AAAA,UACV,MAAM;AAAA,UACN,WAAW,UAAU;AAAA,UACrB,QAAQ,UAAU;AAAA,QACpB;AACA,YAAI,cAAc;AAClB;AAAA,MACF;AAAA,IACF;AAEA,SAAK,wBAAwB;AAC7B,SAAK,aAAa;AAClB,UAAM,MAAM,KAAK,QAAQ,OAAO,GAAG;AACnC,QAAI,KAAK;AACP,YAAM,kBAAkB,KAAK,aAAa,SAAS,IAAI,EAAE;AACzD,UAAI,MAAM,UAAU;AAClB,YAAI,iBAAiB;AACnB,eAAK,eAAe,KAAK,aAAa,OAAO,CAAC,OAAO,OAAO,IAAI,EAAE;AAClE,eAAK,OAAO,EAAE,MAAM,OAAO;AAAA,QAC7B,OAAO;AACL,eAAK,eAAe,CAAC,GAAG,KAAK,cAAc,IAAI,EAAE;AACjD,eAAK,OAAO,IAAI,SAAS,EAAE,MAAM,OAAO,IAAI,EAAE,MAAM,WAAW;AAAA,QACjE;AAAA,MACF,OAAO;AACL,YAAI,CAAC,iBAAiB;AACpB,eAAK,eAAe,CAAC,IAAI,EAAE;AAAA,QAC7B,WAAW,KAAK,aAAa,SAAS,GAAG;AACvC,eAAK,wBAAwB,IAAI;AAAA,QACnC;AACA,aAAK,OAAO,IAAI,SAAS,EAAE,MAAM,OAAO,IAAI,EAAE,MAAM,WAAW;AAAA,MACjE;AAAA,IACF,OAAO;AACL,WAAK,eAAe,CAAC;AACrB,WAAK,OAAO,EAAE,MAAM,WAAW,OAAO,MAAM;AAAA,IAC9C;AAEA,QAAI,cAAc;AAAA,EACpB;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,UAAM,QAAQ,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AACjE,SAAK,eAAe;AAEpB,QAAI,KAAK,KAAK,SAAS,gBAAgB;AACrC,UAAI,YAAY,qBAAqB,KAAK,KAAK,QAAQ,IAAI,CAAC;AAC5D,2BAAqB,KAAK,KAAK,QAAQ,KAAK,KAAK,WAAW,OAAO,GAAG;AACtE;AAAA,IACF;AAEA,QAAI,KAAK,KAAK,SAAS,qBAAqB;AAC1C,UAAI,YAAY,aAAa;AAC7B,WAAK,qBAAqB,OAAO,GAAG;AACpC;AAAA,IACF;AAEA,QAAI,KAAK,KAAK,SAAS,YAAY;AACjC,UAAI,YAAY,eAAe,KAAK,KAAK,MAAM,CAAC;AAChD,WAAK,aAAa,OAAO,KAAK,MAAM,QAAQ;AAC5C;AAAA,IACF;AAEA,QAAI,KAAK,KAAK,SAAS,cAAc,KAAK,aAAa,SAAS,GAAG;AACjE,WAAK,aAAa;AAClB,UAAI,YAAY,MAAM;AACtB,YAAM,UAAU,KAAK,KAAK,OAAO,GAAG;AACpC,YAAM,KAAK,QAAQ,IAAI,KAAK,UAAU;AACtC,YAAM,KAAK,QAAQ,IAAI,KAAK,UAAU;AACtC,WAAK,YAAY;AAEjB,iBAAW,MAAM,KAAK,cAAc;AAClC,cAAM,KAAK,IAAI,MAAM,QAAQ,EAAE;AAC/B,YAAI,CAAC,MAAM,GAAG,OAAQ;AAEtB,YAAI,GAAG,SAAS,SAAS;AACvB,cAAI,GAAG,eAAe,GAAG,WAAW;AAClC;AAAA,UACF;AAEA,cAAI,MAAM,OAAO,IAAI;AAAA,YACnB,UAAU,EAAE,GAAG,GAAG,SAAS,IAAI,IAAI,GAAG,GAAG,SAAS,IAAI,GAAG;AAAA,YACzD,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,IAAI,GAAG,GAAG,KAAK,IAAI,GAAG;AAAA,YAC7C,IAAI,EAAE,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG;AAAA,UACzC,CAAC;AAAA,QACH,WAAW,IAAI,YAAY,UAAU,IAAI;AACvC,gBAAM,UAAU,GAAG,SAAS,IAAI,GAAG,KAAK,IAAI,IAAI;AAChD,gBAAM,UAAU,GAAG,SAAS,IAAI,GAAG,KAAK,IAAI,IAAI;AAChD,gBAAM,gBAAgB,KAAK,KAAK,EAAE,GAAG,SAAS,GAAG,QAAQ,GAAG,GAAG;AAC/D,cAAI,MAAM,OAAO,IAAI;AAAA,YACnB,UAAU;AAAA,cACR,GAAG,cAAc,IAAI,GAAG,KAAK,IAAI;AAAA,cACjC,GAAG,cAAc,IAAI,GAAG,KAAK,IAAI;AAAA,YACnC;AAAA,UACF,CAAC;AAAA,QACH,OAAO;AACL,cAAI,MAAM,OAAO,IAAI;AAAA,YACnB,UAAU,EAAE,GAAG,GAAG,SAAS,IAAI,IAAI,GAAG,GAAG,SAAS,IAAI,GAAG;AAAA,UAC3D,CAAC;AAAA,QACH;AAAA,MACF;AAEA,WAAK,oBAAoB,KAAK,cAAc,GAAG;AAE/C,UAAI,cAAc;AAClB;AAAA,IACF;AAEA,QAAI,KAAK,KAAK,SAAS,WAAW;AAChC,UAAI,YAAY,WAAW;AAC3B,UAAI,cAAc;AAClB;AAAA,IACF;AAEA,SAAK,kBAAkB,OAAO,GAAG;AAAA,EACnC;AAAA,EAEA,YAAY,QAAsB,KAAwB;AACxD,QAAI,KAAK,KAAK,SAAS,WAAW;AAChC,YAAM,OAAO,KAAK,eAAe;AACjC,UAAI,MAAM;AACR,aAAK,eAAe,KAAK,mBAAmB,MAAM,GAAG;AAAA,MACvD;AACA,UAAI,cAAc;AAAA,IACpB;AAEA,QAAI,CAAC,KAAK,cAAc,KAAK,0BAA0B,MAAM;AAC3D,WAAK,eAAe,CAAC,KAAK,qBAAqB;AAAA,IACjD;AACA,SAAK,wBAAwB;AAC7B,SAAK,aAAa;AAElB,UAAM,gBAAgB,KAAK,KAAK,SAAS,aAAa,KAAK,KAAK,YAAY;AAE5E,SAAK,OAAO,EAAE,MAAM,OAAO;AAC3B,QAAI,YAAY,SAAS;AAEzB,QAAI,kBAAkB,MAAM;AAC1B,YAAM,KAAK,IAAI,MAAM,QAAQ,aAAa;AAG1C,UAAI,IAAI,SAAS,OAAQ,KAAI,gBAAgB,aAAa;AAAA,IAC5D;AAAA,EACF;AAAA,EAEA,QAAQ,OAAqB,KAAwB;AACnD,UAAM,QAAQ,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AACjE,UAAM,UAAU,KAAK,kBAAkB,OAAO,GAAG;AACjD,SAAK,WAAW,SAAS,GAAG;AAAA,EAC9B;AAAA,EAEA,cAAc,WAA2C;AACvD,SAAK,cAAc,SAAS;AAC5B,SAAK,qBAAqB,SAAS;AAEnC,QAAI,KAAK,KAAK,SAAS,kBAAkB,KAAK,KAAK;AACjD,YAAM,SAAS;AAAA,QACb,KAAK,KAAK;AAAA,QACV,KAAK,KAAK;AAAA,QACV,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AACA,UAAI,QAAQ;AACV,kBAAU,KAAK;AACf,kBAAU,cAAc;AACxB,kBAAU,YAAY,IAAI,KAAK,IAAI,OAAO;AAC1C,kBAAU,YAAY,CAAC,CAAC;AACxB,kBAAU,WAAW,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAC3D,kBAAU,QAAQ;AAAA,MACpB;AAAA,IACF;AAEA,QAAI,KAAK,aAAa,KAAK,OAAO,KAAK,KAAK,SAAS,QAAQ;AAC3D,UAAI,CAAC,KAAK,aAAa,SAAS,KAAK,SAAS,GAAG;AAC/C,cAAM,KAAK,KAAK,IAAI,MAAM,QAAQ,KAAK,SAAS;AAChD,YAAI,IAAI;AACN,gBAAM,IAAI,iBAAiB,EAAE;AAC7B,cAAI,GAAG;AACL,sBAAU,KAAK;AACf,sBAAU,cAAc;AACxB,sBAAU,cAAc;AACxB,sBAAU,YAAY,MAAM,KAAK,IAAI,OAAO;AAC5C,sBAAU,YAAY,CAAC,CAAC;AACxB,sBAAU,WAAW,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AACvC,sBAAU,QAAQ;AAAA,UACpB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,oBAAoB,KAAuB,KAAwB;AACzE,UAAM,mBAAmB,oBAAI,IAAY;AACzC,eAAW,MAAM,KAAK;AACpB,YAAM,KAAK,IAAI,MAAM,QAAQ,EAAE;AAC/B,UAAI,MAAM,GAAG,SAAS,QAAS,kBAAiB,IAAI,EAAE;AAAA,IACxD;AACA,QAAI,iBAAiB,SAAS,EAAG;AACjC,UAAM,gBAAgB,oBAAI,IAAY;AACtC,eAAW,MAAM,kBAAkB;AACjC,YAAM,cAAc,gBAAgB,IAAI,IAAI,KAAK;AACjD,iBAAW,MAAM,aAAa;AAC5B,YAAI,cAAc,IAAI,GAAG,EAAE,EAAG;AAC9B,sBAAc,IAAI,GAAG,EAAE;AACvB,cAAM,UAAU,iBAAiB,IAAI,IAAI,KAAK;AAC9C,YAAI,QAAS,KAAI,MAAM,OAAO,GAAG,IAAI,OAAO;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eAAe,IAAY,IAAY,KAA2B;AAChE,QAAI,QAAQ;AACZ,eAAW,MAAM,KAAK,cAAc;AAClC,YAAM,KAAK,IAAI,MAAM,QAAQ,EAAE;AAC/B,UAAI,CAAC,MAAM,GAAG,OAAQ;AAEtB,UAAI,GAAG,SAAS,SAAS;AACvB,YAAI,GAAG,eAAe,GAAG,UAAW;AACpC,YAAI,MAAM,OAAO,IAAI;AAAA,UACnB,UAAU,EAAE,GAAG,GAAG,SAAS,IAAI,IAAI,GAAG,GAAG,SAAS,IAAI,GAAG;AAAA,UACzD,MAAM,EAAE,GAAG,GAAG,KAAK,IAAI,IAAI,GAAG,GAAG,KAAK,IAAI,GAAG;AAAA,UAC7C,IAAI,EAAE,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG;AAAA,QACzC,CAAC;AAAA,MACH,OAAO;AACL,YAAI,MAAM,OAAO,IAAI;AAAA,UACnB,UAAU,EAAE,GAAG,GAAG,SAAS,IAAI,IAAI,GAAG,GAAG,SAAS,IAAI,GAAG;AAAA,QAC3D,CAAC;AAAA,MACH;AACA,cAAQ;AAAA,IACV;AAEA,QAAI,OAAO;AACT,WAAK,oBAAoB,KAAK,cAAc,GAAG;AAC/C,UAAI,cAAc;AAAA,IACpB;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,kBAAkB,OAAc,KAAiC;AACvE,UAAM,WAAW,oBAAoB,OAAO,KAAK,cAAc,GAAG;AAClE,QAAI,UAAU;AACZ,UAAI,YAAY,qBAAqB,SAAS,QAAQ,KAAK,CAAC;AAC5D,aAAO;AAAA,IACT;AAEA,UAAM,oBAAoB,KAAK,4BAA4B,OAAO,GAAG;AACrE,QAAI,mBAAmB;AACrB,UAAI,YAAY,aAAa;AAC7B,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,KAAK,oBAAoB,OAAO,GAAG;AACrD,QAAI,WAAW;AACb,UAAI,YAAY,eAAe,UAAU,MAAM,CAAC;AAChD,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,KAAK,QAAQ,OAAO,GAAG;AACnC,QAAI,YAAY,MAAM,SAAS,SAAS;AACxC,WAAO,MAAM,IAAI,KAAK;AAAA,EACxB;AAAA,EAEQ,WAAW,IAAmB,KAAwB;AAC5D,QAAI,KAAK,cAAc,GAAI;AAC3B,SAAK,YAAY;AACjB,QAAI,cAAc;AAAA,EACpB;AAAA,EAEQ,aAAa,OAAc,KAAkB,WAAW,OAAa;AAC3E,QAAI,KAAK,KAAK,SAAS,WAAY;AAEnC,UAAM,KAAK,IAAI,MAAM,QAAQ,KAAK,KAAK,SAAS;AAChD,QAAI,CAAC,MAAM,EAAE,UAAU,OAAO,GAAG,OAAQ;AAEzC,UAAM,EAAE,OAAO,IAAI,KAAK;AACxB,UAAM,KAAK,MAAM,IAAI,KAAK,UAAU;AACpC,UAAM,KAAK,MAAM,IAAI,KAAK,UAAU;AACpC,SAAK,YAAY;AAEjB,QAAI,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,SAAS,GAAG,GAAG,GAAG,SAAS,GAAG,GAAG,GAAG,KAAK,GAAG,GAAG,GAAG,KAAK,EAAE;AAEtF,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,aAAK;AACL,aAAK;AACL;AAAA,MACF,KAAK;AACH,aAAK;AACL,aAAK;AACL,aAAK;AACL;AAAA,MACF,KAAK;AACH,aAAK;AACL,aAAK;AACL,aAAK;AACL;AAAA,MACF,KAAK;AACH,aAAK;AACL,aAAK;AACL,aAAK;AACL,aAAK;AACL;AAAA,IACJ;AAEA,QAAI,YAAY,KAAK,oBAAoB,GAAG;AAC1C,YAAM,QAAQ,KAAK,IAAI,IAAI,GAAG,KAAK,CAAC;AACpC,YAAM,QAAQ,KAAK,IAAI,IAAI,GAAG,KAAK,CAAC;AACpC,UAAI,SAAS,OAAO;AAClB,YAAI,IAAI,KAAK;AAAA,MACf,OAAO;AACL,YAAI,IAAI,KAAK;AAAA,MACf;AACA,UAAI,WAAW,QAAQ,WAAW,MAAM;AACtC,YAAI,GAAG,SAAS,IAAI,GAAG,KAAK,IAAI;AAAA,MAClC;AACA,UAAI,WAAW,QAAQ,WAAW,MAAM;AACtC,YAAI,GAAG,SAAS,IAAI,GAAG,KAAK,IAAI;AAAA,MAClC;AAAA,IACF;AAEA,QAAI,IAAI,kBAAkB;AACxB,UAAI,WAAW,QAAQ,WAAW,KAAM,KAAI,GAAG,SAAS,IAAI,GAAG,KAAK,IAAI;AACxE,UAAI;AAAA,IACN;AACA,QAAI,IAAI,kBAAkB;AACxB,UAAI,WAAW,QAAQ,WAAW,KAAM,KAAI,GAAG,SAAS,IAAI,GAAG,KAAK,IAAI;AACxE,UAAI;AAAA,IACN;AAEA,QAAI,MAAM,OAAO,KAAK,KAAK,WAAW;AAAA,MACpC,UAAU,EAAE,GAAG,EAAE;AAAA,MACjB,MAAM,EAAE,GAAG,EAAE;AAAA,IACf,CAAC;AAED,SAAK,oBAAoB,CAAC,KAAK,KAAK,SAAS,GAAG,GAAG;AAEnD,QAAI,cAAc;AAAA,EACpB;AAAA,EAEQ,oBACN,OACA,KACsD;AACtD,QAAI,KAAK,aAAa,WAAW,EAAG,QAAO;AAE3C,UAAM,OAAO,IAAI,OAAO;AACxB,UAAM,cAAc,cAAc,IAAIA,uBAAsB;AAE5D,eAAW,MAAM,KAAK,cAAc;AAClC,YAAM,KAAK,IAAI,MAAM,QAAQ,EAAE;AAC/B,UAAI,CAAC,MAAM,EAAE,UAAU,IAAK;AAE5B,YAAM,SAAS,iBAAiB,EAAE;AAClC,UAAI,CAAC,OAAQ;AAEb,YAAM,UAAU,KAAK,mBAAmB,MAAM;AAC9C,iBAAW,CAAC,QAAQ,GAAG,KAAK,SAAS;AACnC,YAAI,KAAK,IAAI,MAAM,IAAI,IAAI,CAAC,KAAK,cAAc,KAAK,IAAI,MAAM,IAAI,IAAI,CAAC,KAAK,YAAY;AACtF,iBAAO,EAAE,WAAW,IAAI,OAAO;AAAA,QACjC;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,mBAAmB,QAA2C;AACpE,WAAO;AAAA,MACL,CAAC,MAAM,EAAE,GAAG,OAAO,GAAG,GAAG,OAAO,EAAE,CAAC;AAAA,MACnC,CAAC,MAAM,EAAE,GAAG,OAAO,IAAI,OAAO,GAAG,GAAG,OAAO,EAAE,CAAC;AAAA,MAC9C,CAAC,MAAM,EAAE,GAAG,OAAO,GAAG,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;AAAA,MAC9C,CAAC,MAAM,EAAE,GAAG,OAAO,IAAI,OAAO,GAAG,GAAG,OAAO,IAAI,OAAO,EAAE,CAAC;AAAA,IAC3D;AAAA,EACF;AAAA,EAEQ,cAAc,WAA2C;AAC/D,QAAI,KAAK,KAAK,SAAS,UAAW;AAElC,UAAM,OAAO,KAAK,eAAe;AACjC,QAAI,CAAC,KAAM;AAEX,cAAU,KAAK;AACf,cAAU,cAAc;AACxB,cAAU,YAAY;AACtB,cAAU,YAAY;AACtB,cAAU,YAAY,CAAC,GAAG,CAAC,CAAC;AAC5B,cAAU,WAAW,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AACnD,cAAU,SAAS,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AACjD,cAAU,QAAQ;AAAA,EACpB;AAAA,EAEQ,qBAAqB,WAA2C;AACtE,QAAI,KAAK,aAAa,WAAW,KAAK,CAAC,KAAK,IAAK;AAEjD,UAAM,OAAO,KAAK,IAAI,OAAO;AAC7B,UAAM,kBAAkB,cAAc;AAEtC,cAAU,KAAK;AACf,cAAU,cAAc;AACxB,cAAU,YAAY,MAAM;AAC5B,cAAU,YAAY,CAAC,IAAI,MAAM,IAAI,IAAI,CAAC;AAE1C,eAAW,MAAM,KAAK,cAAc;AAClC,YAAM,KAAK,KAAK,IAAI,MAAM,QAAQ,EAAE;AACpC,UAAI,CAAC,GAAI;AAET,UAAI,GAAG,SAAS,SAAS;AACvB,2BAAmB,WAAW,IAAI,IAAI;AACtC,aAAK,wBAAwB,WAAW,IAAI,IAAI;AAChD;AAAA,MACF;AAEA,YAAM,SAAS,iBAAiB,EAAE;AAClC,UAAI,CAAC,OAAQ;AAEb,YAAM,MAAM,gBAAgB;AAC5B,gBAAU,WAAW,OAAO,IAAI,KAAK,OAAO,IAAI,KAAK,OAAO,IAAI,MAAM,GAAG,OAAO,IAAI,MAAM,CAAC;AAE3F,UAAI,UAAU,IAAI;AAChB,kBAAU,YAAY,CAAC,CAAC;AACxB,kBAAU,YAAY;AACtB,cAAM,UAAU,KAAK,mBAAmB,MAAM;AAC9C,mBAAW,CAAC,EAAE,GAAG,KAAK,SAAS;AAC7B,oBAAU;AAAA,YACR,IAAI,IAAI,kBAAkB;AAAA,YAC1B,IAAI,IAAI,kBAAkB;AAAA,YAC1B;AAAA,YACA;AAAA,UACF;AACA,oBAAU;AAAA,YACR,IAAI,IAAI,kBAAkB;AAAA,YAC1B,IAAI,IAAI,kBAAkB;AAAA,YAC1B;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,kBAAU,YAAY,CAAC,IAAI,MAAM,IAAI,IAAI,CAAC;AAAA,MAC5C,WAAW,GAAG,SAAS,YAAY;AACjC,kBAAU,YAAY,CAAC,CAAC;AACxB,kBAAU,YAAY;AACtB,cAAM,KAAK,OAAO,IAAI,OAAO;AAC7B,cAAM,KAAK,OAAO,IAAI,OAAO;AAC7B,kBAAU;AAAA,UACR,KAAK,kBAAkB;AAAA,UACvB,KAAK,kBAAkB;AAAA,UACvB;AAAA,UACA;AAAA,QACF;AACA,kBAAU;AAAA,UACR,KAAK,kBAAkB;AAAA,UACvB,KAAK,kBAAkB;AAAA,UACvB;AAAA,UACA;AAAA,QACF;AACA,kBAAU,YAAY,CAAC,IAAI,MAAM,IAAI,IAAI,CAAC;AAAA,MAC5C;AAAA,IACF;AAEA,cAAU,QAAQ;AAAA,EACpB;AAAA,EAEQ,wBACN,WACA,OACA,MACM;AACN,QAAI,CAAC,KAAK,IAAK;AACf,QAAI,CAAC,MAAM,eAAe,CAAC,MAAM,UAAW;AAE5C,UAAM,MAAM,gBAAgB;AAE5B,cAAU,KAAK;AACf,cAAU,cAAc;AACxB,cAAU,YAAY,IAAI;AAC1B,cAAU,YAAY,CAAC,CAAC;AAExB,UAAM,QAAQ,oBAAI,IAAY;AAC9B,eAAW,WAAW,CAAC,MAAM,aAAa,MAAM,SAAS,GAAG;AAC1D,UAAI,CAAC,WAAW,MAAM,IAAI,QAAQ,SAAS,EAAG;AAC9C,YAAM,IAAI,QAAQ,SAAS;AAE3B,YAAM,SAAS,KAAK,IAAI,MAAM,QAAQ,QAAQ,SAAS;AACvD,UAAI,CAAC,OAAQ;AAEb,YAAM,SAAS,iBAAiB,MAAM;AACtC,UAAI,CAAC,OAAQ;AAEb,gBAAU,WAAW,OAAO,IAAI,KAAK,OAAO,IAAI,KAAK,OAAO,IAAI,MAAM,GAAG,OAAO,IAAI,MAAM,CAAC;AAAA,IAC7F;AAEA,cAAU,QAAQ;AAAA,EACpB;AAAA,EAEQ,4BAA4B,OAAc,KAAiC;AACjF,QAAI,KAAK,aAAa,WAAW,EAAG,QAAO;AAE3C,UAAM,OAAO,IAAI,OAAO;AACxB,UAAM,cAAc,cAAc,IAAIA,uBAAsB;AAE5D,eAAW,MAAM,KAAK,cAAc;AAClC,YAAM,KAAK,IAAI,MAAM,QAAQ,EAAE;AAC/B,UAAI,CAAC,MAAM,GAAG,SAAS,WAAY;AAEnC,YAAM,SAAS,iBAAiB,EAAE;AAClC,UAAI,CAAC,OAAQ;AAEb,YAAM,KAAK,OAAO,IAAI,OAAO;AAC7B,YAAM,KAAK,OAAO,IAAI,OAAO;AAC7B,UAAI,KAAK,IAAI,MAAM,IAAI,EAAE,KAAK,cAAc,KAAK,IAAI,MAAM,IAAI,EAAE,KAAK,YAAY;AAChF,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,qBAAqB,OAAc,KAAwB;AACjE,QAAI,KAAK,KAAK,SAAS,oBAAqB;AAE5C,UAAM,KAAK,IAAI,MAAM,QAAQ,KAAK,KAAK,SAAS;AAChD,QAAI,CAAC,MAAM,GAAG,SAAS,cAAc,GAAG,OAAQ;AAEhD,UAAM,KAAK,MAAM,IAAI,GAAG,SAAS;AACjC,UAAM,KAAK,MAAM,IAAI,GAAG,SAAS;AACjC,QAAI,YAAY,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAE3C,QAAI,IAAI,cAAc,IAAI,YAAY,IAAI,WAAW,GAAG;AACtD,YAAM,WAAW,IAAI,aAAa,QAAQ,KAAK,KAAK,CAAC,IAAI,IAAI,WAAW,IAAI;AAC5E,kBAAY,KAAK,IAAI,UAAU,KAAK,MAAM,YAAY,QAAQ,IAAI,QAAQ;AAAA,IAC5E;AACA,gBAAY,KAAK,IAAI,kBAAkB,SAAS;AAEhD,UAAM,UAAmC,EAAE,QAAQ,UAAU;AAC7D,QAAI,GAAG,eAAe,QAAQ,IAAI,YAAY,IAAI,WAAW,GAAG;AAC9D,YAAM,WAAW,IAAI,aAAa,QAAQ,KAAK,KAAK,CAAC,IAAI,IAAI,WAAW,IAAI;AAC5E,cAAQ,aAAc,YAAY,WAAY,GAAG;AAAA,IACnD;AAEA,QAAI,MAAM,OAAO,KAAK,KAAK,WAAW,OAAO;AAC7C,QAAI,cAAc;AAAA,EACpB;AAAA,EAEQ,iBAAgC;AACtC,QAAI,KAAK,KAAK,SAAS,UAAW,QAAO;AAEzC,UAAM,EAAE,MAAM,IAAI,KAAK;AACvB,UAAM,MAAM,KAAK;AACjB,UAAM,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,CAAC;AACjC,UAAM,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,CAAC;AACjC,UAAM,IAAI,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC;AAClC,UAAM,IAAI,KAAK,IAAI,IAAI,IAAI,MAAM,CAAC;AAElC,QAAI,MAAM,KAAK,MAAM,EAAG,QAAO;AAC/B,WAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EACtB;AAAA,EAEQ,mBAAmB,SAAiB,KAA4B;AACtE,UAAM,aAAa,IAAI,MAAM,UAAU,OAAO;AAC9C,UAAM,MAAgB,CAAC;AACvB,eAAW,MAAM,YAAY;AAC3B,UAAI,IAAI,kBAAkB,CAAC,IAAI,eAAe,GAAG,OAAO,EAAG;AAC3D,UAAI,IAAI,iBAAiB,IAAI,cAAc,GAAG,OAAO,EAAG;AACxD,UAAI,GAAG,SAAS,OAAQ;AACxB,YAAM,SAAS,iBAAiB,EAAE;AAClC,UAAI,UAAU,KAAK,aAAa,SAAS,MAAM,GAAG;AAChD,YAAI,KAAK,GAAG,EAAE;AAAA,MAChB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,aAAa,GAAW,GAAoB;AAClD,WAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE;AAAA,EACpF;AAAA,EAEQ,QAAQ,OAAc,KAAwC;AAEpE,UAAM,IAAI;AACV,UAAM,aAAa,IAAI,MACpB,UAAU,EAAE,GAAG,MAAM,IAAI,GAAG,GAAG,MAAM,IAAI,GAAG,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE,CAAC,EAChE,QAAQ;AACX,eAAW,MAAM,YAAY;AAC3B,UAAI,IAAI,kBAAkB,CAAC,IAAI,eAAe,GAAG,OAAO,EAAG;AAC3D,UAAI,IAAI,iBAAiB,IAAI,cAAc,GAAG,OAAO,EAAG;AACxD,UAAI,GAAG,SAAS,OAAQ;AACxB,UAAI,KAAK,eAAe,OAAO,EAAE,EAAG,QAAO;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,eAAe,OAAc,IAA4B;AAC/D,QAAI,GAAG,SAAS,OAAQ,QAAO;AAC/B,QAAI,UAAU,IAAI;AAChB,YAAM,IAAI,GAAG;AACb,aACE,MAAM,KAAK,GAAG,SAAS,KACvB,MAAM,KAAK,GAAG,SAAS,IAAI,EAAE,KAC7B,MAAM,KAAK,GAAG,SAAS,KACvB,MAAM,KAAK,GAAG,SAAS,IAAI,EAAE;AAAA,IAEjC;AAEA,QAAI,GAAG,SAAS,UAAU;AACxB,aAAO,cAAc,IAAI,OAAO,EAAE;AAAA,IACpC;AAEA,QAAI,GAAG,SAAS,SAAS;AACvB,aAAO,aAAa,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,EAAE;AAAA,IACxD;AAEA,QAAI,GAAG,SAAS,YAAY;AAC1B,YAAM,SAAS,iBAAiB,EAAE;AAClC,UAAI,CAAC,OAAQ,QAAO;AACpB,aACE,MAAM,KAAK,OAAO,KAClB,MAAM,KAAK,OAAO,IAAI,OAAO,KAC7B,MAAM,KAAK,OAAO,KAClB,MAAM,KAAK,OAAO,IAAI,OAAO;AAAA,IAEjC;AAEA,WAAO;AAAA,EACT;AACF;;;ACltBA,IAAMC,kBAAiB;AAOhB,IAAM,YAAN,MAAgC;AAAA,EAC5B,OAAO;AAAA,EACR,UAAU;AAAA,EACV,QAAe,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC5B,MAAa,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAmC;AAAA,EACnC,WAAiC;AAAA,EACjC,kBAAkB,oBAAI,IAAgB;AAAA,EAE9C,YAAY,UAA4B,CAAC,GAAG;AAC1C,SAAK,QAAQ,QAAQ,SAAS;AAC9B,SAAK,QAAQ,QAAQ,SAAS;AAAA,EAChC;AAAA,EAEA,aAA+B;AAC7B,WAAO,EAAE,OAAO,KAAK,OAAO,OAAO,KAAK,MAAM;AAAA,EAChD;AAAA,EAEA,gBAAgB,UAAkC;AAChD,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO,MAAM,KAAK,gBAAgB,OAAO,QAAQ;AAAA,EACnD;AAAA,EAEA,WAAW,SAAiC;AAC1C,QAAI,QAAQ,UAAU,OAAW,MAAK,QAAQ,QAAQ;AACtD,QAAI,QAAQ,UAAU,OAAW,MAAK,QAAQ,QAAQ;AACtD,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EAEQ,sBAA4B;AAClC,eAAW,YAAY,KAAK,gBAAiB,UAAS;AAAA,EACxD;AAAA,EAEQ,YAAY,KAAgE;AAClF,UAAM,gBAAgB,IAAI;AAC1B,QAAI,CAAC,iBAAiB,CAAC,IAAI,kBAAkB,CAAC,IAAI,cAAe,QAAO;AACxE,WAAO,CAAC,OAAsB;AAC5B,UAAI,iBAAiB,GAAG,YAAY,cAAe,QAAO;AAC1D,UAAI,IAAI,kBAAkB,CAAC,IAAI,eAAe,GAAG,OAAO,EAAG,QAAO;AAClE,UAAI,IAAI,iBAAiB,IAAI,cAAc,GAAG,OAAO,EAAG,QAAO;AAC/D,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,SAAK,UAAU;AACf,UAAM,QAAQ,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AACjE,UAAM,YAAYA,kBAAiB,IAAI,OAAO;AAC9C,UAAM,SAAS,KAAK,YAAY,GAAG;AAEnC,UAAM,SAAS,eAAe,OAAO,IAAI,OAAO,WAAW,QAAW,MAAM;AAC5E,QAAI,QAAQ;AACV,WAAK,QAAQ,iBAAiB,MAAM;AACpC,WAAK,cAAc,EAAE,WAAW,OAAO,GAAG;AAC1C,WAAK,aAAa;AAAA,IACpB,OAAO;AACL,WAAK,QAAQ,UAAU,OAAO,GAAG;AACjC,WAAK,cAAc;AACnB,WAAK,aAAa;AAAA,IACpB;AACA,SAAK,MAAM,EAAE,GAAG,KAAK,MAAM;AAC3B,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,QAAI,CAAC,KAAK,QAAS;AACnB,UAAM,QAAQ,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AACjE,UAAM,YAAYA,kBAAiB,IAAI,OAAO;AAC9C,UAAM,YAAY,KAAK,aAAa;AACpC,UAAM,SAAS,KAAK,YAAY,GAAG;AAEnC,UAAM,SAAS,eAAe,OAAO,IAAI,OAAO,WAAW,WAAW,MAAM;AAC5E,QAAI,QAAQ;AACV,WAAK,MAAM,iBAAiB,MAAM;AAClC,WAAK,WAAW;AAAA,IAClB,OAAO;AACL,WAAK,MAAM,UAAU,OAAO,GAAG;AAC/B,WAAK,WAAW;AAAA,IAClB;AACA,QAAI,cAAc;AAAA,EACpB;AAAA,EAEA,YAAY,QAAsB,KAAwB;AACxD,QAAI,CAAC,KAAK,QAAS;AACnB,SAAK,UAAU;AAEf,QAAI,KAAK,MAAM,MAAM,KAAK,IAAI,KAAK,KAAK,MAAM,MAAM,KAAK,IAAI,EAAG;AAEhE,UAAM,QAAQ,YAAY;AAAA,MACxB,MAAM,KAAK;AAAA,MACX,IAAI,KAAK;AAAA,MACT,UAAU,KAAK;AAAA,MACf,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,WAAW,KAAK,WAAW,EAAE,WAAW,KAAK,SAAS,GAAG,IAAI;AAAA,MAC7D,SAAS,IAAI,iBAAiB;AAAA,IAChC,CAAC;AACD,QAAI,MAAM,IAAI,KAAK;AACnB,SAAK,aAAa;AAClB,SAAK,WAAW;AAChB,QAAI,cAAc;AAClB,QAAI,aAAa,QAAQ;AAAA,EAC3B;AAAA,EAEA,cAAc,KAAqC;AACjD,QAAI,CAAC,KAAK,QAAS;AACnB,QAAI,KAAK,MAAM,MAAM,KAAK,IAAI,KAAK,KAAK,MAAM,MAAM,KAAK,IAAI,EAAG;AAEhE,QAAI,KAAK;AAET,QAAI,KAAK,YAAY;AACnB,YAAM,SAAS,iBAAiB,KAAK,UAAU;AAC/C,UAAI,QAAQ;AACV,YAAI,cAAc;AAClB,YAAI,YAAY;AAChB,YAAI,YAAY,CAAC,CAAC;AAClB,YAAI,WAAW,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAAA,MACvD;AAAA,IACF;AAEA,QAAI,KAAK,UAAU;AACjB,YAAM,SAAS,iBAAiB,KAAK,QAAQ;AAC7C,UAAI,QAAQ;AACV,YAAI,cAAc;AAClB,YAAI,YAAY;AAChB,YAAI,YAAY,CAAC,CAAC;AAClB,YAAI,WAAW,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAAA,MACvD;AAAA,IACF;AAEA,QAAI,cAAc,KAAK;AACvB,QAAI,YAAY,KAAK;AACrB,QAAI,UAAU;AACd,QAAI,cAAc;AAElB,QAAI,UAAU;AACd,QAAI,OAAO,KAAK,MAAM,GAAG,KAAK,MAAM,CAAC;AACrC,QAAI,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC;AACjC,QAAI,OAAO;AAEX,UAAM,QAAQ,KAAK,MAAM,KAAK,IAAI,IAAI,KAAK,MAAM,GAAG,KAAK,IAAI,IAAI,KAAK,MAAM,CAAC;AAC7E,UAAM,UAAU;AAChB,UAAM,YAAY,KAAK,KAAK;AAE5B,QAAI,YAAY,KAAK;AACrB,QAAI,UAAU;AACd,QAAI,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC;AACjC,QAAI;AAAA,MACF,KAAK,IAAI,IAAI,UAAU,KAAK,IAAI,QAAQ,SAAS;AAAA,MACjD,KAAK,IAAI,IAAI,UAAU,KAAK,IAAI,QAAQ,SAAS;AAAA,IACnD;AACA,QAAI;AAAA,MACF,KAAK,IAAI,IAAI,UAAU,KAAK,IAAI,QAAQ,SAAS;AAAA,MACjD,KAAK,IAAI,IAAI,UAAU,KAAK,IAAI,QAAQ,SAAS;AAAA,IACnD;AACA,QAAI,UAAU;AACd,QAAI,KAAK;AACT,QAAI,QAAQ;AAAA,EACd;AACF;;;ACtKO,IAAM,WAAN,MAA+B;AAAA,EAC3B,OAAO;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB,oBAAI,IAAgB;AAAA,EAE9C,YAAY,UAA2B,CAAC,GAAG;AACzC,SAAK,kBAAkB,QAAQ,mBAAmB;AAClD,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,OAAO,QAAQ,QAAQ,EAAE,GAAG,KAAK,GAAG,IAAI;AAC7C,SAAK,WAAW,QAAQ,YAAY;AAAA,EACtC;AAAA,EAEA,aAA8B;AAC5B,WAAO;AAAA,MACL,iBAAiB,KAAK;AAAA,MACtB,WAAW,KAAK;AAAA,MAChB,MAAM,EAAE,GAAG,KAAK,KAAK;AAAA,MACrB,UAAU,KAAK;AAAA,IACjB;AAAA,EACF;AAAA,EAEA,gBAAgB,UAAkC;AAChD,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO,MAAM,KAAK,gBAAgB,OAAO,QAAQ;AAAA,EACnD;AAAA,EAEA,WAAW,SAAgC;AACzC,QAAI,QAAQ,oBAAoB,OAAW,MAAK,kBAAkB,QAAQ;AAC1E,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,SAAS,OAAW,MAAK,OAAO,QAAQ;AACpD,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAC5D,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EAEQ,sBAA4B;AAClC,eAAW,YAAY,KAAK,gBAAiB,UAAS;AAAA,EACxD;AAAA,EAEA,cAAc,QAAsB,MAAyB;AAAA,EAE7D;AAAA,EAEA,cAAc,QAAsB,MAAyB;AAAA,EAE7D;AAAA,EAEA,YAAY,OAAqB,KAAwB;AACvD,QAAI,QAAQ,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AAC/D,YAAQ,UAAU,OAAO,GAAG;AAC5B,UAAM,OAAO,WAAW;AAAA,MACtB,UAAU;AAAA,MACV,MAAM,EAAE,GAAG,KAAK,KAAK;AAAA,MACrB,iBAAiB,KAAK;AAAA,MACtB,WAAW,KAAK;AAAA,MAChB,UAAU,KAAK;AAAA,MACf,SAAS,IAAI,iBAAiB;AAAA,IAChC,CAAC;AACD,QAAI,MAAM,IAAI,IAAI;AAClB,QAAI,cAAc;AAElB,QAAI,aAAa,QAAQ;AACzB,QAAI,cAAc,KAAK,EAAE;AAAA,EAC3B;AACF;;;ACpEO,IAAM,WAAN,MAA+B;AAAA,EAC3B,OAAO;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB,oBAAI,IAAgB;AAAA,EAE9C,YAAY,UAA2B,CAAC,GAAG;AACzC,SAAK,WAAW,QAAQ,YAAY;AACpC,SAAK,QAAQ,QAAQ,SAAS;AAC9B,SAAK,YAAY,QAAQ,aAAa;AAAA,EACxC;AAAA,EAEA,aAA8B;AAC5B,WAAO,EAAE,UAAU,KAAK,UAAU,OAAO,KAAK,OAAO,WAAW,KAAK,UAAU;AAAA,EACjF;AAAA,EAEA,gBAAgB,UAAkC;AAChD,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO,MAAM,KAAK,gBAAgB,OAAO,QAAQ;AAAA,EACnD;AAAA,EAEA,WAAW,SAAgC;AACzC,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAC5D,QAAI,QAAQ,UAAU,OAAW,MAAK,QAAQ,QAAQ;AACtD,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EAEQ,sBAA4B;AAClC,eAAW,YAAY,KAAK,gBAAiB,UAAS;AAAA,EACxD;AAAA,EAEA,WAAW,KAAwB;AACjC,QAAI,YAAY,MAAM;AAAA,EACxB;AAAA,EAEA,aAAa,KAAwB;AACnC,QAAI,YAAY,SAAS;AAAA,EAC3B;AAAA,EAEA,cAAc,QAAsB,MAAyB;AAAA,EAE7D;AAAA,EAEA,cAAc,QAAsB,MAAyB;AAAA,EAE7D;AAAA,EAEA,YAAY,OAAqB,KAAwB;AACvD,QAAI,QAAQ,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AAC/D,YAAQ,UAAU,OAAO,GAAG;AAC5B,UAAM,SAAS,WAAW;AAAA,MACxB,UAAU;AAAA,MACV,UAAU,KAAK;AAAA,MACf,OAAO,KAAK;AAAA,MACZ,WAAW,KAAK;AAAA,MAChB,SAAS,IAAI,iBAAiB;AAAA,IAChC,CAAC;AACD,QAAI,MAAM,IAAI,MAAM;AACpB,QAAI,cAAc;AAElB,QAAI,aAAa,QAAQ;AACzB,QAAI,cAAc,OAAO,EAAE;AAAA,EAC7B;AACF;;;AClEO,IAAM,YAAN,MAAgC;AAAA,EAC5B,OAAO;AAAA,EACR;AAAA,EACA,MAAqB;AAAA,EAE7B,YAAY,UAA4B,CAAC,GAAG;AAC1C,SAAK,OAAO,QAAQ,QAAQ,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,EAC/C;AAAA,EAEA,OAAO,KAAmB;AACxB,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,cAAc,QAAsB,MAAyB;AAAA,EAE7D;AAAA,EAEA,cAAc,QAAsB,MAAyB;AAAA,EAE7D;AAAA,EAEA,YAAY,OAAqB,KAAwB;AACvD,QAAI,CAAC,KAAK,IAAK;AAEf,UAAM,QAAQ,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AACjE,UAAM,UAAU,UAAU,OAAO,GAAG;AACpC,UAAM,QAAQ,YAAY;AAAA,MACxB,UAAU;AAAA,QACR,GAAG,QAAQ,IAAI,KAAK,KAAK,IAAI;AAAA,QAC7B,GAAG,QAAQ,IAAI,KAAK,KAAK,IAAI;AAAA,MAC/B;AAAA,MACA,MAAM,EAAE,GAAG,KAAK,KAAK;AAAA,MACrB,KAAK,KAAK;AAAA,IACZ,CAAC;AACD,QAAI,MAAM,IAAI,KAAK;AACnB,QAAI,cAAc;AAElB,SAAK,MAAM;AACX,QAAI,aAAa,QAAQ;AAAA,EAC3B;AACF;;;ACpCO,IAAM,YAAN,MAAgC;AAAA,EAC5B,OAAO;AAAA,EACR,UAAU;AAAA,EACV,QAAe,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC5B,MAAa,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC1B,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB,oBAAI,IAAgB;AAAA,EAE9C,YAAY,UAA4B,CAAC,GAAG;AAC1C,SAAK,QAAQ,QAAQ,SAAS;AAC9B,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,YAAY,QAAQ,aAAa;AAAA,EACxC;AAAA,EAEA,aAA+B;AAC7B,WAAO;AAAA,MACL,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,WAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,gBAAgB,UAAkC;AAChD,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO,MAAM,KAAK,gBAAgB,OAAO,QAAQ;AAAA,EACnD;AAAA,EAEA,WAAW,SAAiC;AAC1C,QAAI,QAAQ,UAAU,OAAW,MAAK,QAAQ,QAAQ;AACtD,QAAI,QAAQ,gBAAgB,OAAW,MAAK,cAAc,QAAQ;AAClE,QAAI,QAAQ,gBAAgB,OAAW,MAAK,cAAc,QAAQ;AAClE,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EAEA,WAAW,MAAyB;AAClC,QAAI,OAAO,WAAW,aAAa;AACjC,aAAO,iBAAiB,WAAW,KAAK,SAAS;AACjD,aAAO,iBAAiB,SAAS,KAAK,OAAO;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,aAAa,MAAyB;AACpC,SAAK,YAAY;AACjB,QAAI,OAAO,WAAW,aAAa;AACjC,aAAO,oBAAoB,WAAW,KAAK,SAAS;AACpD,aAAO,oBAAoB,SAAS,KAAK,OAAO;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,SAAK,UAAU;AACf,SAAK,QAAQ,KAAK,KAAK,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,GAAG,GAAG;AAChF,SAAK,MAAM,EAAE,GAAG,KAAK,MAAM;AAAA,EAC7B;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,QAAI,CAAC,KAAK,QAAS;AACnB,SAAK,MAAM,KAAK,KAAK,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,GAAG,GAAG;AAC9E,QAAI,cAAc;AAAA,EACpB;AAAA,EAEA,YAAY,QAAsB,KAAwB;AACxD,QAAI,CAAC,KAAK,QAAS;AACnB,SAAK,UAAU;AAEf,UAAM,EAAE,UAAU,KAAK,IAAI,KAAK,YAAY;AAC5C,QAAI,KAAK,MAAM,KAAK,KAAK,MAAM,EAAG;AAElC,UAAM,QAAQ,YAAY;AAAA,MACxB;AAAA,MACA;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,WAAW,KAAK;AAAA,MAChB,SAAS,IAAI,iBAAiB;AAAA,IAChC,CAAC;AACD,QAAI,MAAM,IAAI,KAAK;AACnB,QAAI,cAAc;AAClB,QAAI,aAAa,QAAQ;AAAA,EAC3B;AAAA,EAEA,cAAc,KAAqC;AACjD,QAAI,CAAC,KAAK,QAAS;AAEnB,UAAM,EAAE,UAAU,KAAK,IAAI,KAAK,YAAY;AAC5C,QAAI,KAAK,MAAM,KAAK,KAAK,MAAM,EAAG;AAElC,QAAI,KAAK;AACT,QAAI,cAAc;AAClB,QAAI,cAAc,KAAK;AACvB,QAAI,YAAY,KAAK;AAErB,QAAI,KAAK,cAAc,QAAQ;AAC7B,UAAI,YAAY,KAAK;AAAA,IACvB;AAEA,YAAQ,KAAK,OAAO;AAAA,MAClB,KAAK;AACH,YAAI,KAAK,cAAc,QAAQ;AAC7B,cAAI,SAAS,SAAS,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK,CAAC;AAAA,QACrD;AACA,YAAI,WAAW,SAAS,GAAG,SAAS,GAAG,KAAK,GAAG,KAAK,CAAC;AACrD;AAAA,MACF,KAAK,WAAW;AACd,cAAM,KAAK,SAAS,IAAI,KAAK,IAAI;AACjC,cAAM,KAAK,SAAS,IAAI,KAAK,IAAI;AACjC,YAAI,UAAU;AACd,YAAI,QAAQ,IAAI,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,GAAG,GAAG,KAAK,KAAK,CAAC;AAC7D,YAAI,KAAK,cAAc,OAAQ,KAAI,KAAK;AACxC,YAAI,OAAO;AACX;AAAA,MACF;AAAA,IACF;AAEA,QAAI,QAAQ;AAAA,EACd;AAAA,EAEQ,cAAmE;AACzE,QAAI,IAAI,KAAK,IAAI,KAAK,MAAM,GAAG,KAAK,IAAI,CAAC;AACzC,QAAI,IAAI,KAAK,IAAI,KAAK,MAAM,GAAG,KAAK,IAAI,CAAC;AACzC,QAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK,MAAM,CAAC;AAC1C,QAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK,MAAM,CAAC;AAE1C,QAAI,KAAK,WAAW;AAClB,YAAM,OAAO,KAAK,IAAI,GAAG,CAAC;AAC1B,UAAI;AACJ,UAAI;AACJ,UAAI,KAAK,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,MAAM,IAAI,KAAK,MAAM,IAAI;AAC/D,UAAI,KAAK,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,MAAM,IAAI,KAAK,MAAM,IAAI;AAAA,IACjE;AAEA,WAAO,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,EAAE;AAAA,EAC9C;AAAA,EAEQ,sBAA4B;AAClC,eAAW,YAAY,KAAK,gBAAiB,UAAS;AAAA,EACxD;AAAA,EAEQ,KAAK,OAAc,KAAyB;AAClD,WAAO,UAAU,OAAO,GAAG;AAAA,EAC7B;AAAA,EAEQ,YAAY,CAAC,MAA2B;AAC9C,QAAI,EAAE,QAAQ,QAAS,MAAK,YAAY;AAAA,EAC1C;AAAA,EAEQ,UAAU,CAAC,MAA2B;AAC5C,QAAI,EAAE,QAAQ,QAAS,MAAK,YAAY;AAAA,EAC1C;AACF;;;ACxJO,IAAM,cAAN,MAAkC;AAAA,EAC9B,OAAO;AAAA,EACR,QAAsB;AAAA,EACtB,MAAoB;AAAA,EACpB,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB,oBAAI,IAAgB;AAAA,EAE9C,YAAY,UAA8B,CAAC,GAAG;AAC5C,SAAK,cAAc,QAAQ,eAAe;AAAA,EAC5C;AAAA,EAEA,aAAiC;AAC/B,WAAO,EAAE,aAAa,KAAK,YAAY;AAAA,EACzC;AAAA,EAEA,WAAW,SAAmC;AAC5C,QAAI,QAAQ,gBAAgB,OAAW,MAAK,cAAc,QAAQ;AAClE,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EAEA,gBAAgB,UAAkC;AAChD,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO,MAAM,KAAK,gBAAgB,OAAO,QAAQ;AAAA,EACnD;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,SAAK,WAAW,IAAI,YAAY;AAChC,SAAK,WAAW,IAAI;AACpB,SAAK,iBAAiB,IAAI;AAC1B,UAAM,QAAQ,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AACjE,SAAK,QAAQ,KAAK,WAAW,OAAO,GAAG;AACvC,SAAK,MAAM,EAAE,GAAG,KAAK,MAAM;AAAA,EAC7B;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,QAAI,CAAC,KAAK,MAAO;AACjB,UAAM,QAAQ,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AACjE,SAAK,MAAM,KAAK,WAAW,OAAO,GAAG;AACrC,QAAI,cAAc;AAAA,EACpB;AAAA,EAEA,YAAY,QAAsB,KAAwB;AACxD,QAAI,CAAC,KAAK,MAAO;AACjB,SAAK,QAAQ;AACb,SAAK,MAAM;AACX,QAAI,cAAc;AAAA,EACpB;AAAA,EAEA,aAAa,MAAyB;AACpC,SAAK,QAAQ;AACb,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,iBAAqC;AACnC,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,IAAK,QAAO;AACrC,UAAM,KAAK,KAAK,IAAI,IAAI,KAAK,MAAM;AACnC,UAAM,KAAK,KAAK,IAAI,IAAI,KAAK,MAAM;AACnC,UAAM,gBAAgB,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAEjD,QAAI;AACJ,QAAI,KAAK,aAAa,SAAS,KAAK,gBAAgB;AAClD,cAAQ,eAAe,KAAK,OAAO,KAAK,KAAK,KAAK,UAAU,KAAK,cAAc;AAAA,IACjF,OAAO;AACL,YAAM,WAAW,KAAK;AACtB,cAAQ,gBAAgB;AAAA,IAC1B;AAEA,UAAM,OAAO,QAAQ,KAAK;AAC1B,WAAO;AAAA,MACL,OAAO,EAAE,GAAG,KAAK,MAAM;AAAA,MACvB,KAAK,EAAE,GAAG,KAAK,IAAI;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,cAAc,KAAqC;AACjD,UAAM,IAAI,KAAK,eAAe;AAC9B,QAAI,CAAC,EAAG;AAER,QAAI,KAAK;AAET,QAAI,cAAc;AAClB,QAAI,YAAY,CAAC,GAAG,CAAC,CAAC;AACtB,QAAI,YAAY;AAChB,QAAI,UAAU;AACd,QAAI,OAAO,EAAE,MAAM,GAAG,EAAE,MAAM,CAAC;AAC/B,QAAI,OAAO,EAAE,IAAI,GAAG,EAAE,IAAI,CAAC;AAC3B,QAAI,OAAO;AAEX,QAAI,YAAY,CAAC,CAAC;AAClB,QAAI,YAAY;AAChB,UAAM,YAAY;AAClB,QAAI,UAAU;AACd,QAAI,IAAI,EAAE,MAAM,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,KAAK,KAAK,CAAC;AACvD,QAAI,KAAK;AACT,QAAI,UAAU;AACd,QAAI,IAAI,EAAE,IAAI,GAAG,EAAE,IAAI,GAAG,WAAW,GAAG,KAAK,KAAK,CAAC;AACnD,QAAI,KAAK;AAET,UAAM,QAAQ,GAAG,KAAK,MAAM,EAAE,IAAI,CAAC;AACnC,UAAM,QAAQ,EAAE,MAAM,IAAI,EAAE,IAAI,KAAK;AACrC,UAAM,QAAQ,EAAE,MAAM,IAAI,EAAE,IAAI,KAAK;AACrC,QAAI,OAAO;AACX,UAAM,UAAU,IAAI,YAAY,KAAK;AACrC,UAAM,OAAO;AACb,UAAM,OAAO;AACb,UAAM,QAAQ;AAEd,QAAI,YAAY;AAChB,QAAI,UAAU;AACd,QAAI;AAAA,MACF,OAAO,QAAQ,QAAQ,IAAI;AAAA,MAC3B,OAAO,QAAQ,IAAI;AAAA,MACnB,QAAQ,QAAQ,OAAO;AAAA,MACvB,QAAQ,OAAO;AAAA,MACf;AAAA,IACF;AACA,QAAI,KAAK;AAET,QAAI,YAAY;AAChB,QAAI,YAAY;AAChB,QAAI,eAAe;AACnB,QAAI,SAAS,OAAO,MAAM,IAAI;AAE9B,QAAI,QAAQ;AAAA,EACd;AAAA,EAEQ,WAAW,OAAc,KAAyB;AACxD,QAAI,CAAC,IAAI,SAAU,QAAO;AAC1B,QAAI,IAAI,aAAa,SAAS,IAAI,gBAAgB;AAChD,aAAO,gBAAgB,OAAO,IAAI,UAAU,IAAI,cAAc;AAAA,IAChE;AACA,QAAI,IAAI,aAAa,UAAU;AAC7B,aAAO,UAAU,OAAO,IAAI,QAAQ;AAAA,IACtC;AACA,QAAI,IAAI,YAAY;AAClB,aAAO,UAAU,OAAO,IAAI,QAAQ;AAAA,IACtC;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,sBAA4B;AAClC,eAAW,YAAY,KAAK,gBAAiB,UAAS;AAAA,EACxD;AACF;;;ACjJO,IAAM,eAAN,MAAmC;AAAA,EAC/B,OAAO;AAAA,EACR,UAAU;AAAA,EACV,SAAgB,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC7B,UAAiB,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC9B,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAkB,oBAAI,IAAgB;AAAA,EAE9C,YAAY,UAA+B,CAAC,GAAG;AAC7C,SAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,cAAc,QAAQ,eAAe;AAAA,EAC5C;AAAA,EAEA,aAAkC;AAChC,WAAO;AAAA,MACL,eAAe,KAAK;AAAA,MACpB,WAAW,KAAK;AAAA,MAChB,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,SAAS,KAAK;AAAA,MACd,aAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,WAAW,SAAoC;AAC7C,QAAI,QAAQ,kBAAkB,OAAW,MAAK,gBAAgB,QAAQ;AACtE,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,gBAAgB,OAAW,MAAK,cAAc,QAAQ;AAClE,QAAI,QAAQ,gBAAgB,OAAW,MAAK,cAAc,QAAQ;AAClE,QAAI,QAAQ,YAAY,OAAW,MAAK,UAAU,QAAQ;AAC1D,QAAI,QAAQ,gBAAgB,OAAW,MAAK,cAAc,QAAQ;AAClE,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EAEA,gBAAgB,UAAkC;AAChD,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO,MAAM,KAAK,gBAAgB,OAAO,QAAQ;AAAA,EACnD;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,SAAK,UAAU;AACf,SAAK,WAAW,IAAI,YAAY;AAChC,SAAK,WAAW,IAAI;AACpB,SAAK,iBAAiB,IAAI;AAC1B,SAAK,cAAc,CAAC,CAAC,IAAI,aAAa,IAAI,cAAc;AACxD,UAAM,QAAQ,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AACjE,SAAK,SAAS,KAAK,WAAW,OAAO,GAAG;AACxC,SAAK,UAAU,EAAE,GAAG,KAAK,OAAO;AAAA,EAClC;AAAA,EAEA,cAAc,OAAqB,KAAwB;AACzD,QAAI,CAAC,KAAK,QAAS;AACnB,SAAK,UAAU,IAAI,OAAO,cAAc,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AAClE,QAAI,cAAc;AAAA,EACpB;AAAA,EAEA,YAAY,QAAsB,KAAwB;AACxD,QAAI,CAAC,KAAK,QAAS;AACnB,SAAK,UAAU;AAEf,UAAM,SAAS,KAAK,cAAc;AAClC,QAAI,UAAU,EAAG;AAEjB,UAAM,QAAQ,KAAK,aAAa;AAChC,UAAM,WAAW,IAAI;AACrB,UAAM,WACJ,YAAY,WAAW,IAAK,IAAI,aAAa,QAAQ,KAAK,KAAK,CAAC,IAAI,WAAW,WAAY;AAC7F,UAAM,QAAQ,WAAW,IAAI,SAAS,WAAW;AACjD,UAAM,aAAa,QAAQ,KAAK;AAEhC,UAAM,UAAU,eAAe;AAAA,MAC7B,UAAU,EAAE,GAAG,KAAK,OAAO;AAAA,MAC3B,eAAe,KAAK;AAAA,MACpB;AAAA,MACA;AAAA,MACA,WAAW,KAAK;AAAA,MAChB,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,SAAS,KAAK;AAAA,MACd,aAAa,KAAK;AAAA,MAClB,YAAY,aAAa,IAAI,aAAa;AAAA,MAC1C,SAAS,IAAI,iBAAiB;AAAA,IAChC,CAAC;AACD,QAAI,MAAM,IAAI,OAAO;AACrB,QAAI,cAAc;AAClB,QAAI,aAAa,QAAQ;AAAA,EAC3B;AAAA,EAEA,aAAa,MAAyB;AACpC,SAAK,UAAU;AACf,SAAK,SAAS,EAAE,GAAG,GAAG,GAAG,EAAE;AAC3B,SAAK,UAAU,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC9B;AAAA,EAEA,cAAc,KAAqC;AACjD,QAAI,CAAC,KAAK,QAAS;AAEnB,UAAM,SAAS,KAAK,cAAc;AAClC,QAAI,UAAU,EAAG;AAEjB,QAAI,KAAK,aAAa,SAAS,KAAK,gBAAgB;AAClD,WAAK,iBAAiB,KAAK,MAAM;AACjC;AAAA,IACF;AAEA,SAAK,uBAAuB,KAAK,MAAM;AAAA,EACzC;AAAA,EAEQ,uBAAuB,KAA+B,QAAsB;AAClF,UAAM,KAAK,KAAK,OAAO;AACvB,UAAM,KAAK,KAAK,OAAO;AACvB,UAAM,QAAQ,KAAK,aAAa;AAEhC,QAAI,KAAK;AACT,QAAI,cAAc;AAClB,QAAI,YAAY,KAAK;AACrB,QAAI,cAAc,KAAK;AACvB,QAAI,YAAY,KAAK;AAErB,YAAQ,KAAK,eAAe;AAAA,MAC1B,KAAK;AACH,YAAI,UAAU;AACd,YAAI,IAAI,IAAI,IAAI,QAAQ,GAAG,KAAK,KAAK,CAAC;AACtC,YAAI,KAAK;AACT,YAAI,OAAO;AACX;AAAA,MAEF,KAAK;AACH,YAAI,SAAS,KAAK,SAAS,GAAG,KAAK,SAAS,GAAG,QAAQ,MAAM;AAC7D,YAAI,WAAW,KAAK,SAAS,GAAG,KAAK,SAAS,GAAG,QAAQ,MAAM;AAC/D;AAAA,MAEF,KAAK,QAAQ;AACX,cAAM,YAAY,KAAK,KAAK,GAAG;AAC/B,YAAI,UAAU;AACd,YAAI,OAAO,IAAI,EAAE;AACjB,YAAI,IAAI,IAAI,IAAI,QAAQ,QAAQ,WAAW,QAAQ,SAAS;AAC5D,YAAI,UAAU;AACd,YAAI,KAAK;AACT,YAAI,OAAO;AACX;AAAA,MACF;AAAA,MAEA,KAAK,QAAQ;AACX,cAAM,QAAQ,SAAS;AACvB,cAAM,MAAM,KAAK,IAAI,KAAK;AAC1B,cAAM,MAAM,KAAK,IAAI,KAAK;AAC1B,cAAM,QAAQ,CAAC,MAAM;AACrB,cAAM,QAAQ,MAAM;AAEpB,YAAI,UAAU;AACd,YAAI,OAAO,KAAK,OAAO,KAAK,KAAK;AACjC,YAAI,OAAO,KAAK,SAAS,MAAM,OAAO,KAAK,SAAS,MAAM,KAAK;AAC/D,YAAI,OAAO,KAAK,SAAS,MAAM,OAAO,KAAK,SAAS,MAAM,KAAK;AAC/D,YAAI,OAAO,KAAK,OAAO,KAAK,KAAK;AACjC,YAAI,UAAU;AACd,YAAI,KAAK;AACT,YAAI,OAAO;AACX;AAAA,MACF;AAAA,IACF;AAEA,QAAI,QAAQ;AAAA,EACd;AAAA,EAEQ,iBAAiB,KAA+B,QAAsB;AAC5E,UAAM,cAAc,KAAK;AACzB,QAAI,CAAC,YAAa;AAClB,UAAM,WAAW,KAAK;AACtB,UAAM,WAAW,KAAK,KAAK,CAAC,IAAI;AAChC,UAAM,cAAc,SAAS;AAC7B,UAAM,QAAQ,KAAK,aAAa;AAChC,UAAM,SAAS,KAAK;AAEpB,QAAI;AACJ,YAAQ,KAAK,eAAe;AAAA,MAC1B,KAAK;AACH,mBAAW,oBAAoB,QAAQ,aAAa,UAAU,WAAW;AACzE;AAAA,MACF,KAAK;AACH,mBAAW,kBAAkB,QAAQ,OAAO,aAAa,UAAU,WAAW;AAC9E;AAAA,MACF,KAAK;AACH,mBAAW,kBAAkB,QAAQ,OAAO,aAAa,UAAU,WAAW;AAC9E;AAAA,MACF,KAAK;AACH,mBAAW,oBAAoB,QAAQ,aAAa,UAAU,WAAW;AACzE;AAAA,IACJ;AAEA,QAAI,KAAK;AACT,QAAI,cAAc;AAElB,QAAI,UAAU;AACd,eAAW,QAAQ,UAAU;AAC3B,kBAAY,KAAK,KAAK,GAAG,KAAK,GAAG,UAAU,WAAW;AAAA,IACxD;AACA,QAAI,YAAY,KAAK;AACrB,QAAI,KAAK;AAET,QAAI,UAAU;AACd,eAAW,QAAQ,UAAU;AAC3B,kBAAY,KAAK,KAAK,GAAG,KAAK,GAAG,UAAU,WAAW;AAAA,IACxD;AACA,QAAI,cAAc,KAAK;AACvB,QAAI,YAAY,KAAK;AACrB,QAAI,OAAO;AAEX,QACE,KAAK,kBAAkB,UACvB,KAAK,kBAAkB,UACvB,KAAK,kBAAkB,YACvB,KAAK,kBAAkB,UACvB;AACA,UAAI,cAAc;AAClB,UAAI,UAAU;AACd,kBAAY,KAAK,OAAO,GAAG,OAAO,GAAG,UAAU,WAAW;AAC1D,UAAI,YAAY,KAAK;AACrB,UAAI,KAAK;AACT,UAAI,cAAc,KAAK;AACvB,UAAI,YAAY,KAAK;AACrB,UAAI,OAAO;AAAA,IACb;AAEA,QAAI,KAAK,kBAAkB,UAAU;AACnC,YAAM,OAAO,cAAc,KAAK;AAChC,UAAI,OAAO,GAAG;AACZ,YAAI,cAAc;AAClB,cAAM,QAAQ,GAAG,KAAK,MAAM,IAAI,CAAC;AACjC,cAAM,WAAW,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,SAAS,IAAI,CAAC;AACzD,YAAI,OAAO,QAAQ,QAAQ;AAC3B,YAAI,YAAY;AAChB,YAAI,eAAe;AACnB,cAAM,QAAQ,OAAO;AACrB,cAAM,QAAQ,OAAO,IAAI;AAEzB,cAAM,UAAU,IAAI,YAAY,KAAK;AACrC,cAAM,OAAO;AACb,cAAM,OAAO;AACb,cAAM,QAAQ,QAAQ,QAAQ,OAAO;AACrC,cAAM,QAAQ,WAAW,OAAO;AAEhC,YAAI,YAAY;AAChB,YAAI,UAAU;AACd,YAAI,UAAU,QAAQ,QAAQ,GAAG,QAAQ,OAAO,OAAO,OAAO,CAAC;AAC/D,YAAI,KAAK;AAET,YAAI,YAAY,KAAK;AACrB,YAAI,SAAS,OAAO,OAAO,QAAQ,IAAI;AAAA,MACzC;AAAA,IACF;AAEA,QAAI,QAAQ;AAAA,EACd;AAAA,EAEQ,gBAAwB;AAC9B,UAAM,KAAK,KAAK,QAAQ,IAAI,KAAK,OAAO;AACxC,UAAM,KAAK,KAAK,QAAQ,IAAI,KAAK,OAAO;AACxC,UAAM,MAAM,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACvC,QAAI,KAAK,eAAe,KAAK,WAAW,GAAG;AACzC,YAAM,WAAW,KAAK,aAAa,QAAQ,KAAK,KAAK,CAAC,IAAI,KAAK,WAAW,KAAK;AAC/E,aAAO,KAAK,IAAI,UAAU,KAAK,MAAM,MAAM,QAAQ,IAAI,QAAQ;AAAA,IACjE;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,eAAuB;AAC7B,UAAM,KAAK,KAAK,QAAQ,IAAI,KAAK,OAAO;AACxC,UAAM,KAAK,KAAK,QAAQ,IAAI,KAAK,OAAO;AACxC,WAAO,KAAK,MAAM,IAAI,EAAE;AAAA,EAC1B;AAAA,EAEQ,WAAW,OAAc,KAAyB;AACxD,QAAI,CAAC,IAAI,SAAU,QAAO;AAC1B,QAAI,IAAI,aAAa,SAAS,IAAI,gBAAgB;AAChD,aAAO,gBAAgB,OAAO,IAAI,UAAU,IAAI,cAAc;AAAA,IAChE;AACA,QAAI,IAAI,aAAa,UAAU;AAC7B,aAAO,UAAU,OAAO,IAAI,QAAQ;AAAA,IACtC;AACA,QAAI,IAAI,YAAY;AAClB,aAAO,UAAU,OAAO,IAAI,QAAQ;AAAA,IACtC;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,sBAA4B;AAClC,eAAW,YAAY,KAAK,gBAAiB,UAAS;AAAA,EACxD;AACF;;;ACpUO,IAAM,UAAU;","names":["minX","minY","minX","minY","cache","cache","HANDLE_HIT_PADDING","BIND_THRESHOLD"]}
1
+ {"version":3,"sources":["../src/core/snap.ts","../src/elements/note-sanitizer.ts","../src/core/state-serializer.ts","../src/core/auto-save.ts","../src/canvas/camera.ts","../src/canvas/input-filter.ts","../src/elements/create-id.ts","../src/core/geometry.ts","../src/elements/arrow-geometry.ts","../src/elements/element-bounds.ts","../src/elements/bounds.ts","../src/canvas/keyboard-actions.ts","../src/canvas/shortcut-map.ts","../src/canvas/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/arrow-render-cache.ts","../src/elements/arrow-binding.ts","../src/elements/grid-renderer.ts","../src/elements/hex-fill.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/tools/tool-manager.ts","../src/history/history-stack.ts","../src/history/commands.ts","../src/history/layer-commands.ts","../src/history/history-recorder.ts","../src/canvas/note-canvas-renderer.ts","../src/canvas/export-image.ts","../src/layers/layer-manager.ts","../src/canvas/interact-mode.ts","../src/canvas/double-tap-detector.ts","../src/canvas/dom-node-manager.ts","../src/canvas/render-stats.ts","../src/canvas/render-loop.ts","../src/canvas/layer-cache.ts","../src/canvas/margin-viewport.ts","../src/elements/element-style.ts","../src/canvas/viewport.ts","../src/tools/hand-tool.ts","../src/tools/pencil-tool.ts","../src/elements/stroke-hit.ts","../src/tools/eraser-tool.ts","../src/tools/arrow-handles.ts","../src/tools/select-tool.ts","../src/tools/arrow-tool.ts","../src/tools/note-tool.ts","../src/tools/text-tool.ts","../src/tools/image-tool.ts","../src/tools/shape-tool.ts","../src/tools/measure-tool.ts","../src/tools/template-tool.ts","../src/index.ts"],"sourcesContent":["import type { Point } from './types';\r\nimport type { HexOrientation } from '../elements/types';\r\nimport type { ToolContext } from '../tools/types';\r\n\r\nexport function snapPoint(point: Point, gridSize: number): Point {\r\n return {\r\n x: Math.round(point.x / gridSize) * gridSize || 0,\r\n y: Math.round(point.y / gridSize) * gridSize || 0,\r\n };\r\n}\r\n\r\nexport function snapToHexCenter(\r\n point: Point,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point {\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * cellSize;\r\n const rowH = 1.5 * cellSize;\r\n const row = Math.round(point.y / rowH);\r\n const offsetX = row % 2 !== 0 ? hexW / 2 : 0;\r\n const col = Math.round((point.x - offsetX) / hexW);\r\n return { x: col * hexW + offsetX || 0, y: row * rowH || 0 };\r\n } else {\r\n const hexH = Math.sqrt(3) * cellSize;\r\n const colW = 1.5 * cellSize;\r\n const col = Math.round(point.x / colW);\r\n const offsetY = col % 2 !== 0 ? hexH / 2 : 0;\r\n const row = Math.round((point.y - offsetY) / hexH);\r\n return { x: col * colW || 0, y: row * hexH + offsetY || 0 };\r\n }\r\n}\r\n\r\nexport function smartSnap(point: Point, ctx: ToolContext): Point {\r\n if (!ctx.snapToGrid || !ctx.gridSize) return point;\r\n if (ctx.gridType === 'hex' && ctx.hexOrientation) {\r\n return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);\r\n }\r\n return snapPoint(point, ctx.gridSize);\r\n}\r\n","interface RunStyle {\r\n bold: boolean;\r\n italic: boolean;\r\n underline: boolean;\r\n strikethrough: boolean;\r\n fontSize: number;\r\n}\r\n\r\nexport interface StyledRun extends RunStyle {\r\n text: string;\r\n}\r\n\r\nconst BOLD_TAGS = new Set(['b', 'strong']);\r\nconst ITALIC_TAGS = new Set(['i', 'em']);\r\nconst UNDERLINE_TAGS = new Set(['u']);\r\nconst STRIKE_TAGS = new Set(['s', 'strike', 'del']);\r\nconst BLOCK_TAGS = new Set(['div']);\r\n\r\nexport function parseStyledRuns(html: string, baseFontSize: number): StyledRun[] {\r\n if (!html) return [];\r\n\r\n const doc = new DOMParser().parseFromString(html, 'text/html');\r\n const runs: StyledRun[] = [];\r\n const baseStyle: RunStyle = {\r\n bold: false,\r\n italic: false,\r\n underline: false,\r\n strikethrough: false,\r\n fontSize: baseFontSize,\r\n };\r\n\r\n walkNodes(doc.body, baseStyle, runs);\r\n return runs;\r\n}\r\n\r\nfunction walkNodes(node: Node, style: RunStyle, runs: StyledRun[]): void {\r\n for (const child of Array.from(node.childNodes)) {\r\n if (child.nodeType === Node.TEXT_NODE) {\r\n const text = child.textContent ?? '';\r\n if (text) {\r\n runs.push({ text, ...style });\r\n }\r\n continue;\r\n }\r\n\r\n if (child.nodeType !== Node.ELEMENT_NODE) continue;\r\n\r\n const el = child as Element;\r\n const tag = el.tagName.toLowerCase();\r\n\r\n if (tag === 'br') {\r\n runs.push({ text: '\\n', ...style });\r\n continue;\r\n }\r\n\r\n if (BLOCK_TAGS.has(tag) && runs.length > 0) {\r\n const lastRun = runs[runs.length - 1];\r\n if (lastRun && !lastRun.text.endsWith('\\n')) {\r\n runs.push({ text: '\\n', ...style });\r\n }\r\n }\r\n\r\n const childStyle = { ...style };\r\n if (BOLD_TAGS.has(tag)) childStyle.bold = true;\r\n if (ITALIC_TAGS.has(tag)) childStyle.italic = true;\r\n if (UNDERLINE_TAGS.has(tag)) childStyle.underline = true;\r\n if (STRIKE_TAGS.has(tag)) childStyle.strikethrough = true;\r\n\r\n if (tag === 'span') {\r\n const fontSize = (el as HTMLElement).style.fontSize;\r\n if (fontSize) {\r\n childStyle.fontSize = parseInt(fontSize, 10) || style.fontSize;\r\n }\r\n }\r\n\r\n walkNodes(el, childStyle, runs);\r\n }\r\n}\r\n\r\nconst ALLOWED_TAGS = new Set([\r\n 'b',\r\n 'strong',\r\n 'i',\r\n 'em',\r\n 'u',\r\n 's',\r\n 'strike',\r\n 'del',\r\n 'span',\r\n 'br',\r\n 'div',\r\n]);\r\n\r\nexport function sanitizeNoteHtml(html: string): string {\r\n if (!html) return '';\r\n\r\n const doc = new DOMParser().parseFromString(html, 'text/html');\r\n sanitizeNode(doc.body);\r\n return doc.body.innerHTML;\r\n}\r\n\r\nfunction sanitizeNode(node: Node): void {\r\n const children = Array.from(node.childNodes);\r\n\r\n for (const child of children) {\r\n if (child.nodeType === Node.TEXT_NODE) continue;\r\n\r\n if (child.nodeType !== Node.ELEMENT_NODE) {\r\n child.remove();\r\n continue;\r\n }\r\n\r\n const el = child as Element;\r\n const tag = el.tagName.toLowerCase();\r\n\r\n if (!ALLOWED_TAGS.has(tag)) {\r\n const fragment = document.createDocumentFragment();\r\n while (el.firstChild) {\r\n fragment.appendChild(el.firstChild);\r\n }\r\n node.replaceChild(fragment, el);\r\n sanitizeNode(node);\r\n return;\r\n }\r\n\r\n sanitizeAttributes(el, tag);\r\n sanitizeNode(el);\r\n }\r\n}\r\n\r\nexport function isNoteContentEmpty(html: string): boolean {\r\n if (!html) return true;\r\n const doc = new DOMParser().parseFromString(html, 'text/html');\r\n const text = doc.body.textContent ?? '';\r\n return text.replace(/\\u00a0/g, ' ').trim().length === 0;\r\n}\r\n\r\nfunction sanitizeAttributes(el: Element, tag: string): void {\r\n const attrs = Array.from(el.attributes);\r\n for (const attr of attrs) {\r\n if (tag === 'span' && attr.name === 'style') {\r\n const fontSize = (el as HTMLElement).style.fontSize;\r\n if (fontSize) {\r\n el.setAttribute('style', `font-size: ${fontSize};`);\r\n } else {\r\n el.removeAttribute('style');\r\n }\r\n continue;\r\n }\r\n el.removeAttribute(attr.name);\r\n }\r\n}\r\n","import type { CanvasElement } from '../elements/types';\r\nimport type { Point } from './types';\r\nimport type { Layer } from '../layers/types';\r\nimport { sanitizeNoteHtml } from '../elements/note-sanitizer';\r\n\r\nexport interface CanvasState {\r\n version: number;\r\n camera: {\r\n position: Point;\r\n zoom: number;\r\n };\r\n elements: CanvasElement[];\r\n layers?: Layer[];\r\n activeLayerId?: string;\r\n}\r\n\r\nconst CURRENT_VERSION = 2;\r\n\r\nexport function exportState(\r\n elements: CanvasElement[],\r\n camera: { position: Point; zoom: number },\r\n layers: Layer[] = [],\r\n activeLayerId?: string,\r\n): CanvasState {\r\n const state: CanvasState = {\r\n version: CURRENT_VERSION,\r\n camera: {\r\n position: { ...camera.position },\r\n zoom: camera.zoom,\r\n },\r\n elements: elements.map((el) => {\r\n const clone = structuredClone(el);\r\n if (clone.type === 'arrow') {\r\n delete clone.cachedControlPoint;\r\n }\r\n return clone;\r\n }),\r\n layers: layers.map((l) => ({ ...l })),\r\n };\r\n if (activeLayerId) state.activeLayerId = activeLayerId;\r\n return state;\r\n}\r\n\r\nexport function parseState(json: string): CanvasState {\r\n const data: unknown = JSON.parse(json);\r\n validateState(data);\r\n return data;\r\n}\r\n\r\nfunction validateState(data: unknown): asserts data is CanvasState {\r\n if (!data || typeof data !== 'object') {\r\n throw new Error('Invalid state: expected an object');\r\n }\r\n\r\n const obj = data as Record<string, unknown>;\r\n\r\n if (typeof obj['version'] !== 'number') {\r\n throw new Error('Invalid state: missing or invalid version');\r\n }\r\n\r\n if (!obj['camera'] || typeof obj['camera'] !== 'object') {\r\n throw new Error('Invalid state: missing camera');\r\n }\r\n\r\n const cam = obj['camera'] as Record<string, unknown>;\r\n if (!cam['position'] || typeof cam['position'] !== 'object') {\r\n throw new Error('Invalid state: missing camera.position');\r\n }\r\n\r\n const pos = cam['position'] as Record<string, unknown>;\r\n if (typeof pos['x'] !== 'number' || typeof pos['y'] !== 'number') {\r\n throw new Error('Invalid state: camera.position must have x and y numbers');\r\n }\r\n\r\n if (typeof cam['zoom'] !== 'number') {\r\n throw new Error('Invalid state: missing camera.zoom');\r\n }\r\n\r\n if (!Array.isArray(obj['elements'])) {\r\n throw new Error('Invalid state: elements must be an array');\r\n }\r\n\r\n for (const el of obj['elements'] as unknown[]) {\r\n validateElement(el);\r\n migrateElement(el as unknown as Record<string, unknown>);\r\n }\r\n\r\n cleanBindings(obj['elements'] as Record<string, unknown>[]);\r\n\r\n const layers = obj['layers'];\r\n if (!Array.isArray(layers) || layers.length === 0) {\r\n obj['layers'] = [\r\n {\r\n id: 'default-layer',\r\n name: 'Layer 1',\r\n visible: true,\r\n locked: false,\r\n order: 0,\r\n opacity: 1.0,\r\n },\r\n ];\r\n }\r\n}\r\n\r\nconst VALID_TYPES = new Set([\r\n 'stroke',\r\n 'note',\r\n 'arrow',\r\n 'image',\r\n 'html',\r\n 'text',\r\n 'shape',\r\n 'grid',\r\n 'template',\r\n]);\r\n\r\nfunction validateElement(el: unknown): asserts el is CanvasElement {\r\n if (!el || typeof el !== 'object') {\r\n throw new Error('Invalid element: expected an object');\r\n }\r\n\r\n const obj = el as Record<string, unknown>;\r\n\r\n if (typeof obj['id'] !== 'string') {\r\n throw new Error('Invalid element: missing id');\r\n }\r\n\r\n if (typeof obj['type'] !== 'string' || !VALID_TYPES.has(obj['type'])) {\r\n throw new Error(`Invalid element: unknown type \"${String(obj['type'])}\"`);\r\n }\r\n\r\n if (typeof obj['zIndex'] !== 'number') {\r\n throw new Error('Invalid element: missing zIndex');\r\n }\r\n}\r\n\r\nfunction cleanBindings(elements: Record<string, unknown>[]): void {\r\n const ids = new Set(elements.map((el) => el['id'] as string));\r\n\r\n for (const el of elements) {\r\n if (el['type'] !== 'arrow') continue;\r\n\r\n const fromBinding = el['fromBinding'] as Record<string, unknown> | undefined;\r\n if (fromBinding && !ids.has(fromBinding['elementId'] as string)) {\r\n el['fromBinding'] = undefined;\r\n }\r\n\r\n const toBinding = el['toBinding'] as Record<string, unknown> | undefined;\r\n if (toBinding && !ids.has(toBinding['elementId'] as string)) {\r\n el['toBinding'] = undefined;\r\n }\r\n }\r\n}\r\n\r\nfunction migrateElement(obj: Record<string, unknown>): void {\r\n if (typeof obj['layerId'] !== 'string') {\r\n obj['layerId'] = 'default-layer';\r\n }\r\n\r\n if (obj['type'] === 'arrow' && typeof obj['bend'] !== 'number') {\r\n obj['bend'] = 0;\r\n }\r\n\r\n if (obj['type'] === 'stroke' && Array.isArray(obj['points'])) {\r\n for (const pt of obj['points'] as Record<string, unknown>[]) {\r\n if (typeof pt['pressure'] !== 'number') {\r\n pt['pressure'] = 0.5;\r\n }\r\n }\r\n }\r\n\r\n if (obj['type'] === 'shape' && typeof obj['shape'] !== 'string') {\r\n obj['shape'] = 'rectangle';\r\n }\r\n\r\n if (obj['type'] === 'note' && typeof obj['textColor'] !== 'string') {\r\n obj['textColor'] = '#000000';\r\n }\r\n\r\n if (obj['type'] === 'note' && typeof obj['text'] === 'string') {\r\n obj['text'] = sanitizeNoteHtml(obj['text']);\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { Camera } from '../canvas/camera';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport { exportState, parseState } from './state-serializer';\r\nimport type { CanvasState } from './state-serializer';\r\n\r\nexport interface AutoSaveOptions {\r\n key?: string;\r\n debounceMs?: number;\r\n layerManager?: LayerManager;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\nconst DEFAULT_KEY = 'fieldnotes-autosave';\r\nconst DEFAULT_DEBOUNCE_MS = 1000;\r\n\r\nexport class AutoSave {\r\n private readonly key: string;\r\n private readonly debounceMs: number;\r\n private readonly layerManager?: LayerManager;\r\n private timerId: ReturnType<typeof setTimeout> | null = null;\r\n private unsubscribers: (() => void)[] = [];\r\n private readonly onError?: (error: Error) => void;\r\n\r\n constructor(\r\n private readonly store: ElementStore,\r\n private readonly camera: Camera,\r\n options: AutoSaveOptions = {},\r\n ) {\r\n this.key = options.key ?? DEFAULT_KEY;\r\n this.debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\r\n this.layerManager = options.layerManager;\r\n this.onError = options.onError;\r\n }\r\n\r\n start(): void {\r\n const schedule = () => this.scheduleSave();\r\n\r\n this.unsubscribers = [\r\n this.store.on('add', schedule),\r\n this.store.on('remove', schedule),\r\n this.store.on('update', schedule),\r\n this.camera.onChange(schedule),\r\n ];\r\n if (this.layerManager) {\r\n this.unsubscribers.push(this.layerManager.on('change', schedule));\r\n }\r\n }\r\n\r\n stop(): void {\r\n this.cancelPending();\r\n this.unsubscribers.forEach((fn) => fn());\r\n this.unsubscribers = [];\r\n }\r\n\r\n load(): CanvasState | null {\r\n if (typeof localStorage === 'undefined') return null;\r\n\r\n const json = localStorage.getItem(this.key);\r\n if (!json) return null;\r\n\r\n try {\r\n return parseState(json);\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n clear(): void {\r\n if (typeof localStorage === 'undefined') return;\r\n localStorage.removeItem(this.key);\r\n }\r\n\r\n private scheduleSave(): void {\r\n this.cancelPending();\r\n this.timerId = setTimeout(() => this.save(), this.debounceMs);\r\n }\r\n\r\n private cancelPending(): void {\r\n if (this.timerId !== null) {\r\n clearTimeout(this.timerId);\r\n this.timerId = null;\r\n }\r\n }\r\n\r\n private save(): void {\r\n if (typeof localStorage === 'undefined') return;\r\n\r\n const layers = this.layerManager?.snapshot() ?? [];\r\n const state = exportState(this.store.snapshot(), this.camera, layers);\r\n try {\r\n localStorage.setItem(this.key, JSON.stringify(state));\r\n } catch (e) {\r\n console.warn('Auto-save failed: storage quota exceeded. State too large for localStorage.');\r\n this.onError?.(e instanceof Error ? e : new Error(String(e)));\r\n }\r\n }\r\n}\r\n","import type { Bounds, Point } from '../core/types';\r\n\r\nexport interface CameraOptions {\r\n minZoom?: number;\r\n maxZoom?: number;\r\n}\r\n\r\nexport interface CameraChangeInfo {\r\n panned: boolean;\r\n zoomed: boolean;\r\n}\r\n\r\nconst DEFAULT_MIN_ZOOM = 0.1;\r\nconst DEFAULT_MAX_ZOOM = 10;\r\n\r\nexport class Camera {\r\n private x = 0;\r\n private y = 0;\r\n private z = 1;\r\n private readonly minZoom: number;\r\n private readonly maxZoom: number;\r\n private changeListeners = new Set<(info: CameraChangeInfo) => void>();\r\n\r\n constructor(options: CameraOptions = {}) {\r\n this.minZoom = options.minZoom ?? DEFAULT_MIN_ZOOM;\r\n this.maxZoom = options.maxZoom ?? DEFAULT_MAX_ZOOM;\r\n }\r\n\r\n get position(): Point {\r\n return { x: this.x, y: this.y };\r\n }\r\n\r\n get zoom(): number {\r\n return this.z;\r\n }\r\n\r\n pan(dx: number, dy: number): void {\r\n this.x += dx;\r\n this.y += dy;\r\n this.notifyPan();\r\n }\r\n\r\n moveTo(x: number, y: number): void {\r\n this.x = x;\r\n this.y = y;\r\n this.notifyPan();\r\n }\r\n\r\n setZoom(level: number): void {\r\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, level));\r\n this.notifyZoom();\r\n }\r\n\r\n zoomAt(level: number, screenPoint: Point): void {\r\n const before = this.screenToWorld(screenPoint);\r\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, level));\r\n const after = this.screenToWorld(screenPoint);\r\n this.x += (after.x - before.x) * this.z;\r\n this.y += (after.y - before.y) * this.z;\r\n this.notifyPanAndZoom();\r\n }\r\n\r\n screenToWorld(screen: Point): Point {\r\n return {\r\n x: (screen.x - this.x) / this.z,\r\n y: (screen.y - this.y) / this.z,\r\n };\r\n }\r\n\r\n worldToScreen(world: Point): Point {\r\n return {\r\n x: world.x * this.z + this.x,\r\n y: world.y * this.z + this.y,\r\n };\r\n }\r\n\r\n getVisibleRect(canvasWidth: number, canvasHeight: number): Bounds {\r\n const topLeft = this.screenToWorld({ x: 0, y: 0 });\r\n const bottomRight = this.screenToWorld({ x: canvasWidth, y: canvasHeight });\r\n return {\r\n x: topLeft.x,\r\n y: topLeft.y,\r\n w: bottomRight.x - topLeft.x,\r\n h: bottomRight.y - topLeft.y,\r\n };\r\n }\r\n\r\n fitToContent(boundingBox: Bounds, canvasWidth: number, canvasHeight: number, padding = 40): void {\r\n if (boundingBox.w === 0 && boundingBox.h === 0) return;\r\n\r\n const scaleX = canvasWidth / (boundingBox.w + 2 * padding);\r\n const scaleY = canvasHeight / (boundingBox.h + 2 * padding);\r\n this.z = Math.min(this.maxZoom, Math.max(this.minZoom, Math.min(scaleX, scaleY)));\r\n this.x = (canvasWidth - boundingBox.w * this.z) / 2 - boundingBox.x * this.z;\r\n this.y = (canvasHeight - boundingBox.h * this.z) / 2 - boundingBox.y * this.z;\r\n this.notifyPanAndZoom();\r\n }\r\n\r\n toCSSTransform(): string {\r\n return `translate3d(${this.x}px, ${this.y}px, 0) scale(${this.z})`;\r\n }\r\n\r\n onChange(listener: (info: CameraChangeInfo) => void): () => void {\r\n this.changeListeners.add(listener);\r\n return () => this.changeListeners.delete(listener);\r\n }\r\n\r\n private notifyPan(): void {\r\n this.changeListeners.forEach((fn) => fn({ panned: true, zoomed: false }));\r\n }\r\n\r\n private notifyZoom(): void {\r\n this.changeListeners.forEach((fn) => fn({ panned: false, zoomed: true }));\r\n }\r\n\r\n private notifyPanAndZoom(): void {\r\n this.changeListeners.forEach((fn) => fn({ panned: true, zoomed: true }));\r\n }\r\n}\r\n","export type FilterAction = 'dispatch' | 'suppress' | 'defer';\r\n\r\nexport interface FilteredEvent {\r\n event: PointerEvent;\r\n action: FilterAction;\r\n}\r\n\r\nexport interface FilteredUpEvent extends FilteredEvent {\r\n pendingTap?: { x: number; y: number };\r\n}\r\n\r\nexport class InputFilter {\r\n private activePenId: number | null = null;\r\n private pendingTap: { pointerId: number; x: number; y: number } | null = null;\r\n\r\n static readonly MIN_MOVE_DISTANCE = 3;\r\n\r\n filterDown(e: PointerEvent): FilteredEvent {\r\n if (e.pointerType === 'pen') {\r\n this.activePenId = e.pointerId;\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n if (e.pointerType === 'touch' && this.activePenId !== null) {\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n if (e.pointerType === 'touch') {\r\n this.pendingTap = { pointerId: e.pointerId, x: e.clientX, y: e.clientY };\r\n return { event: e, action: 'defer' };\r\n }\r\n\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n filterMove(e: PointerEvent): FilteredEvent {\r\n if (e.pointerType === 'touch' && this.activePenId !== null) {\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {\r\n const dx = e.clientX - this.pendingTap.x;\r\n const dy = e.clientY - this.pendingTap.y;\r\n if (dx * dx + dy * dy > InputFilter.MIN_MOVE_DISTANCE * InputFilter.MIN_MOVE_DISTANCE) {\r\n this.pendingTap = null;\r\n return { event: e, action: 'dispatch' };\r\n }\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n filterUp(e: PointerEvent): FilteredUpEvent {\r\n if (e.pointerId === this.activePenId) {\r\n this.activePenId = null;\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n if (e.pointerType === 'touch' && this.activePenId !== null) {\r\n return { event: e, action: 'suppress' };\r\n }\r\n\r\n if (this.pendingTap && e.pointerId === this.pendingTap.pointerId) {\r\n const tap = { x: this.pendingTap.x, y: this.pendingTap.y };\r\n this.pendingTap = null;\r\n return { event: e, action: 'dispatch', pendingTap: tap };\r\n }\r\n\r\n return { event: e, action: 'dispatch' };\r\n }\r\n\r\n reset(): void {\r\n this.activePenId = null;\r\n this.pendingTap = null;\r\n }\r\n}\r\n","let counter = 0;\n\nexport function createId(prefix: string): string {\n return `${prefix}_${Date.now().toString(36)}_${(counter++).toString(36)}`;\n}\n","import type { Point } 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","import type { Bounds, Point } from '../core/types';\r\nimport { distSqToSegment } from '../core/geometry';\r\n\r\nexport function getArrowControlPoint(from: Point, to: Point, bend: number): Point {\r\n const midX = (from.x + to.x) / 2;\r\n const midY = (from.y + to.y) / 2;\r\n\r\n if (bend === 0) return { x: midX, y: midY };\r\n\r\n const dx = to.x - from.x;\r\n const dy = to.y - from.y;\r\n const len = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (len === 0) return { x: midX, y: midY };\r\n\r\n const perpX = -dy / len;\r\n const perpY = dx / len;\r\n\r\n return {\r\n x: midX + perpX * bend,\r\n y: midY + perpY * bend,\r\n };\r\n}\r\n\r\nexport function getArrowMidpoint(from: Point, to: Point, bend: number): Point {\r\n const cp = getArrowControlPoint(from, to, bend);\r\n return {\r\n x: 0.25 * from.x + 0.5 * cp.x + 0.25 * to.x,\r\n y: 0.25 * from.y + 0.5 * cp.y + 0.25 * to.y,\r\n };\r\n}\r\n\r\nexport function getBendFromPoint(from: Point, to: Point, dragPoint: Point): number {\r\n const midX = (from.x + to.x) / 2;\r\n const midY = (from.y + to.y) / 2;\r\n\r\n const dx = to.x - from.x;\r\n const dy = to.y - from.y;\r\n const len = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (len === 0) return 0;\r\n\r\n const perpX = -dy / len;\r\n const perpY = dx / len;\r\n\r\n return (dragPoint.x - midX) * perpX + (dragPoint.y - midY) * perpY;\r\n}\r\n\r\nexport function getArrowTangentAngle(from: Point, to: Point, bend: number, t: number): number {\r\n const cp = getArrowControlPoint(from, to, bend);\r\n\r\n const tangentX = 2 * (1 - t) * (cp.x - from.x) + 2 * t * (to.x - cp.x);\r\n const tangentY = 2 * (1 - t) * (cp.y - from.y) + 2 * t * (to.y - cp.y);\r\n\r\n return Math.atan2(tangentY, tangentX);\r\n}\r\n\r\nexport function isNearBezier(\r\n point: Point,\r\n from: Point,\r\n to: Point,\r\n bend: number,\r\n threshold: number,\r\n): boolean {\r\n if (bend === 0) return isNearLine(point, from, to, threshold);\r\n\r\n const cp = getArrowControlPoint(from, to, bend);\r\n const segments = 20;\r\n\r\n for (let i = 0; i < segments; i++) {\r\n const t0 = i / segments;\r\n const t1 = (i + 1) / segments;\r\n const a = bezierPoint(from, cp, to, t0);\r\n const b = bezierPoint(from, cp, to, t1);\r\n if (isNearLine(point, a, b, threshold)) return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\nexport function getArrowBounds(from: Point, to: Point, bend: number): Bounds {\r\n if (bend === 0) {\r\n const minX = Math.min(from.x, to.x);\r\n const minY = Math.min(from.y, to.y);\r\n return {\r\n x: minX,\r\n y: minY,\r\n w: Math.abs(to.x - from.x),\r\n h: Math.abs(to.y - from.y),\r\n };\r\n }\r\n\r\n const cp = getArrowControlPoint(from, to, bend);\r\n const steps = 20;\r\n let minX = Math.min(from.x, to.x);\r\n let minY = Math.min(from.y, to.y);\r\n let maxX = Math.max(from.x, to.x);\r\n let maxY = Math.max(from.y, to.y);\r\n\r\n for (let i = 1; i < steps; i++) {\r\n const t = i / steps;\r\n const p = bezierPoint(from, cp, to, t);\r\n if (p.x < minX) minX = p.x;\r\n if (p.y < minY) minY = p.y;\r\n if (p.x > maxX) maxX = p.x;\r\n if (p.y > maxY) maxY = p.y;\r\n }\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n\r\nfunction bezierPoint(from: Point, cp: Point, to: Point, t: number): Point {\r\n const mt = 1 - t;\r\n return {\r\n x: mt * mt * from.x + 2 * mt * t * cp.x + t * t * to.x,\r\n y: mt * mt * from.y + 2 * mt * t * cp.y + t * t * to.y,\r\n };\r\n}\r\n\r\nfunction isNearLine(point: Point, a: Point, b: Point, threshold: number): boolean {\r\n return distSqToSegment(point, a, b) <= threshold * threshold;\r\n}\r\n","import type { Bounds } from '../core/types';\r\nimport type { CanvasElement, TemplateElement } from './types';\r\nimport { getArrowControlPoint } from './arrow-geometry';\r\n\r\n// Cache stroke bounds via WeakMap.\r\n// May miss after ElementStore.update() creates new object via spread,\r\n// acceptable since stroke points never change after commit.\r\nconst strokeBoundsCache = new WeakMap<CanvasElement, Bounds>();\r\n\r\nexport function getElementBounds(element: CanvasElement): Bounds | null {\r\n if (element.type === 'grid') return null;\r\n\r\n if ('size' in element) {\r\n return {\r\n x: element.position.x,\r\n y: element.position.y,\r\n w: element.size.w,\r\n h: element.size.h,\r\n };\r\n }\r\n\r\n if (element.type === 'stroke') {\r\n if (element.points.length === 0) return null;\r\n\r\n const cached = strokeBoundsCache.get(element);\r\n if (cached) return cached;\r\n\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n\r\n for (const p of element.points) {\r\n const px = p.x + element.position.x;\r\n const py = p.y + element.position.y;\r\n if (px < minX) minX = px;\r\n if (py < minY) minY = py;\r\n if (px > maxX) maxX = px;\r\n if (py > maxY) maxY = py;\r\n }\r\n\r\n const bounds: Bounds = { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n strokeBoundsCache.set(element, bounds);\r\n return bounds;\r\n }\r\n\r\n if (element.type === 'arrow') {\r\n return getArrowBoundsAnalytical(element.from, element.to, element.bend);\r\n }\r\n\r\n if (element.type === 'template') {\r\n return getTemplateBounds(element);\r\n }\r\n\r\n return null;\r\n}\r\n\r\nfunction getArrowBoundsAnalytical(\r\n from: { x: number; y: number },\r\n to: { x: number; y: number },\r\n bend: number,\r\n): Bounds {\r\n if (bend === 0) {\r\n const minX = Math.min(from.x, to.x);\r\n const minY = Math.min(from.y, to.y);\r\n return {\r\n x: minX,\r\n y: minY,\r\n w: Math.abs(to.x - from.x),\r\n h: Math.abs(to.y - from.y),\r\n };\r\n }\r\n\r\n const cp = getArrowControlPoint(from, to, bend);\r\n\r\n let minX = Math.min(from.x, to.x);\r\n let maxX = Math.max(from.x, to.x);\r\n let minY = Math.min(from.y, to.y);\r\n let maxY = Math.max(from.y, to.y);\r\n\r\n // Analytical extrema for quadratic bezier: t = (P0 - P1) / (P0 - 2*P1 + P2)\r\n const tx = from.x - 2 * cp.x + to.x;\r\n if (tx !== 0) {\r\n const t = (from.x - cp.x) / tx;\r\n if (t > 0 && t < 1) {\r\n const mt = 1 - t;\r\n const x = mt * mt * from.x + 2 * mt * t * cp.x + t * t * to.x;\r\n if (x < minX) minX = x;\r\n if (x > maxX) maxX = x;\r\n }\r\n }\r\n\r\n const ty = from.y - 2 * cp.y + to.y;\r\n if (ty !== 0) {\r\n const t = (from.y - cp.y) / ty;\r\n if (t > 0 && t < 1) {\r\n const mt = 1 - t;\r\n const y = mt * mt * from.y + 2 * mt * t * cp.y + t * t * to.y;\r\n if (y < minY) minY = y;\r\n if (y > maxY) maxY = y;\r\n }\r\n }\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n\r\nfunction getTemplateBounds(el: TemplateElement): Bounds {\r\n const { x: cx, y: cy } = el.position;\r\n const r = el.radius;\r\n\r\n switch (el.templateShape) {\r\n case 'circle':\r\n return { x: cx - r, y: cy - r, w: 2 * r, h: 2 * r };\r\n\r\n case 'square':\r\n return { x: cx - r / 2, y: cy - r / 2, w: r, h: r };\r\n\r\n case 'cone': {\r\n const halfAngle = Math.atan(0.5);\r\n const tipX = cx;\r\n const tipY = cy;\r\n const leftX = cx + r * Math.cos(el.angle - halfAngle);\r\n const leftY = cy + r * Math.sin(el.angle - halfAngle);\r\n const rightX = cx + r * Math.cos(el.angle + halfAngle);\r\n const rightY = cy + r * Math.sin(el.angle + halfAngle);\r\n const farX = cx + r * Math.cos(el.angle);\r\n const farY = cy + r * Math.sin(el.angle);\r\n\r\n const xs = [tipX, leftX, rightX, farX];\r\n const ys = [tipY, leftY, rightY, farY];\r\n\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n\r\n for (let i = 0; i < xs.length; i++) {\r\n const px = xs[i];\r\n const py = ys[i];\r\n if (px !== undefined && px < minX) minX = px;\r\n if (px !== undefined && px > maxX) maxX = px;\r\n if (py !== undefined && py < minY) minY = py;\r\n if (py !== undefined && py > maxY) maxY = py;\r\n }\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n }\r\n\r\n case 'line': {\r\n const halfW = r / 12;\r\n const cos = Math.cos(el.angle);\r\n const sin = Math.sin(el.angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n\r\n const x0 = cx + perpX;\r\n const y0 = cy + perpY;\r\n const x1 = cx + r * cos + perpX;\r\n const y1 = cy + r * sin + perpY;\r\n const x2 = cx + r * cos - perpX;\r\n const y2 = cy + r * sin - perpY;\r\n const x3 = cx - perpX;\r\n const y3 = cy - perpY;\r\n\r\n const minX = Math.min(x0, x1, x2, x3);\r\n const minY = Math.min(y0, y1, y2, y3);\r\n const maxX = Math.max(x0, x1, x2, x3);\r\n const maxY = Math.max(y0, y1, y2, y3);\r\n\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n }\r\n }\r\n}\r\n\r\nexport function transferStrokeBounds(prev: CanvasElement, next: CanvasElement): void {\r\n if (prev.type !== 'stroke' || next.type !== 'stroke') return;\r\n if (prev.points !== next.points) return;\r\n if (prev.position.x !== next.position.x || prev.position.y !== next.position.y) return;\r\n const bounds = strokeBoundsCache.get(prev);\r\n if (bounds) strokeBoundsCache.set(next, bounds);\r\n}\r\n\r\nexport function boundsIntersect(a: Bounds, b: Bounds): boolean {\r\n return a.x <= b.x + b.w && a.x + a.w >= b.x && a.y <= b.y + b.h && a.y + a.h >= b.y;\r\n}\r\n","import type { Bounds } from '../core/types';\r\nimport type { CanvasElement } from './types';\r\nimport { getElementBounds } from './element-bounds';\r\n\r\nexport function getElementsBoundingBox(elements: CanvasElement[]): Bounds | null {\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n let found = false;\r\n\r\n for (const el of elements) {\r\n const b = getElementBounds(el);\r\n if (!b) continue;\r\n found = true;\r\n if (b.x < minX) minX = b.x;\r\n if (b.y < minY) minY = b.y;\r\n if (b.x + b.w > maxX) maxX = b.x + b.w;\r\n if (b.y + b.h > maxY) maxY = b.y + b.h;\r\n }\r\n\r\n if (!found) return null;\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n","import type { ToolManager } from '../tools/tool-manager';\r\nimport type { ToolContext } from '../tools/types';\r\nimport type { SelectTool } from '../tools/select-tool';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport type { HistoryStack } from '../history/history-stack';\r\nimport type { CanvasElement, ArrowElement } from '../elements/types';\r\nimport type { Point } from '../core/types';\r\nimport { createId } from '../elements/create-id';\r\nimport { getElementsBoundingBox } from '../elements/bounds';\r\n\r\nexport interface KeyboardActionsDeps {\r\n getToolManager: () => ToolManager | null;\r\n getToolContext: () => ToolContext | null;\r\n getHistoryRecorder: () => HistoryRecorder | null;\r\n getHistoryStack: () => HistoryStack | null;\r\n isToolActive: () => boolean;\r\n fitToContent?: () => void;\r\n getLastPointerWorld?: () => Point | null;\r\n}\r\n\r\nexport class KeyboardActions {\r\n private clipboard: CanvasElement[] = [];\r\n private pasteCount = 0;\r\n private nudgeTimer: ReturnType<typeof setTimeout> | null = null;\r\n private nudgeTxId: number | null = null;\r\n\r\n constructor(private readonly deps: KeyboardActionsDeps) {}\r\n\r\n dispose(): void {\r\n this.flushPendingNudge();\r\n }\r\n\r\n private selectTool(): { tool: SelectTool; ctx: ToolContext } | null {\r\n const tm = this.deps.getToolManager();\r\n const ctx = this.deps.getToolContext();\r\n if (!tm || !ctx) return null;\r\n const tool = tm.activeTool;\r\n if (tool?.name !== 'select') return null;\r\n return { tool: tool as SelectTool, ctx };\r\n }\r\n\r\n nudge(dx: number, dy: number, byCell: boolean): boolean {\r\n if (this.deps.isToolActive()) return false;\r\n const sel = this.selectTool();\r\n if (!sel) return false;\r\n if (sel.tool.selectedIds.length === 0) return false;\r\n\r\n const step = byCell ? (sel.ctx.gridSize ?? 10) : 1;\r\n if (this.nudgeTimer === null) {\r\n const recorder = this.deps.getHistoryRecorder();\r\n recorder?.begin();\r\n this.nudgeTxId = recorder?.currentTransactionId ?? null;\r\n } else {\r\n clearTimeout(this.nudgeTimer);\r\n }\r\n const moved = sel.tool.nudgeSelection(dx * step, dy * step, sel.ctx);\r\n this.nudgeTimer = setTimeout(() => this.flushPendingNudge(), 400);\r\n return moved;\r\n }\r\n\r\n flushPendingNudge(): void {\r\n if (this.nudgeTimer === null) return;\r\n clearTimeout(this.nudgeTimer);\r\n this.nudgeTimer = null;\r\n const recorder = this.deps.getHistoryRecorder();\r\n if (this.nudgeTxId === null || recorder?.currentTransactionId === this.nudgeTxId) {\r\n recorder?.commit();\r\n }\r\n this.nudgeTxId = null;\r\n }\r\n\r\n deleteSelected(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const ids = sel.tool.selectedIds;\r\n if (ids.length === 0) return;\r\n const recorder = this.deps.getHistoryRecorder();\r\n recorder?.begin();\r\n for (const id of ids) {\r\n sel.ctx.store.remove(id);\r\n }\r\n recorder?.commit();\r\n sel.ctx.requestRender();\r\n }\r\n\r\n undo(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n const ctx = this.deps.getToolContext();\r\n const stack = this.deps.getHistoryStack();\r\n if (!stack || !ctx) return;\r\n const recorder = this.deps.getHistoryRecorder();\r\n recorder?.pause();\r\n stack.undo(ctx.store);\r\n recorder?.resume();\r\n ctx.requestRender();\r\n }\r\n\r\n redo(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n const ctx = this.deps.getToolContext();\r\n const stack = this.deps.getHistoryStack();\r\n if (!stack || !ctx) return;\r\n const recorder = this.deps.getHistoryRecorder();\r\n recorder?.pause();\r\n stack.redo(ctx.store);\r\n recorder?.resume();\r\n ctx.requestRender();\r\n }\r\n\r\n copy(): void {\r\n if (this.deps.isToolActive()) return;\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const ids = sel.tool.selectedIds;\r\n if (ids.length === 0) return;\r\n this.clipboard = [];\r\n for (const id of ids) {\r\n const el = sel.ctx.store.getById(id);\r\n if (el) this.clipboard.push(structuredClone(el));\r\n }\r\n this.pasteCount = 0;\r\n }\r\n\r\n paste(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n if (this.clipboard.length === 0) return;\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n\r\n const cursor = this.deps.getLastPointerWorld?.() ?? null;\r\n if (cursor) {\r\n const bbox = getElementsBoundingBox(this.clipboard);\r\n if (bbox) {\r\n const centerX = bbox.x + bbox.w / 2;\r\n const centerY = bbox.y + bbox.h / 2;\r\n this.insertClones(this.clipboard, { x: cursor.x - centerX, y: cursor.y - centerY }, sel);\r\n return;\r\n }\r\n }\r\n\r\n this.pasteCount++;\r\n this.insertClones(this.clipboard, { x: this.pasteCount * 20, y: this.pasteCount * 20 }, sel);\r\n }\r\n\r\n duplicate(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.flushPendingNudge();\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const source: CanvasElement[] = [];\r\n for (const id of sel.tool.selectedIds) {\r\n const el = sel.ctx.store.getById(id);\r\n if (el) source.push(el);\r\n }\r\n if (source.length === 0) return;\r\n this.insertClones(source, { x: 20, y: 20 }, sel);\r\n }\r\n\r\n deselect(): void {\r\n if (this.deps.isToolActive()) return;\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n if (sel.tool.selectedIds.length === 0) return;\r\n sel.tool.setSelection([]);\r\n sel.ctx.requestRender();\r\n }\r\n\r\n selectAll(): void {\r\n if (this.deps.isToolActive()) return;\r\n const tm = this.deps.getToolManager();\r\n const ctx = this.deps.getToolContext();\r\n if (!tm || !ctx) return;\r\n if (tm.activeTool?.name !== 'select') {\r\n ctx.switchTool?.('select');\r\n }\r\n const sel = this.selectTool();\r\n if (!sel) return;\r\n const ids = sel.ctx.store\r\n .getAll()\r\n .filter(\r\n (el) =>\r\n !el.locked &&\r\n (sel.ctx.isLayerVisible?.(el.layerId) ?? true) &&\r\n !(sel.ctx.isLayerLocked?.(el.layerId) ?? false),\r\n )\r\n .map((el) => el.id);\r\n sel.tool.setSelection(ids);\r\n sel.ctx.requestRender();\r\n }\r\n\r\n zoomToFit(): void {\r\n if (this.deps.isToolActive()) return;\r\n this.deps.fitToContent?.();\r\n }\r\n\r\n 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 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 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 as ArrowElement;\r\n arrow.from = { x: arrow.from.x + offset.x, y: arrow.from.y + offset.y };\r\n arrow.to = { x: arrow.to.x + offset.x, y: arrow.to.y + offset.y };\r\n delete arrow.cachedControlPoint;\r\n\r\n if (arrow.fromBinding) {\r\n const newTarget = idMap.get(arrow.fromBinding.elementId);\r\n if (newTarget) {\r\n arrow.fromBinding = { elementId: newTarget };\r\n } else {\r\n delete arrow.fromBinding;\r\n }\r\n }\r\n if (arrow.toBinding) {\r\n const newTarget = idMap.get(arrow.toBinding.elementId);\r\n if (newTarget) {\r\n arrow.toBinding = { elementId: newTarget };\r\n } else {\r\n delete arrow.toBinding;\r\n }\r\n }\r\n }\r\n\r\n if (sel.ctx.activeLayerId) {\r\n clone.layerId = sel.ctx.activeLayerId;\r\n }\r\n\r\n sel.ctx.store.add(clone);\r\n newIds.push(clone.id);\r\n }\r\n\r\n recorder?.commit();\r\n sel.tool.setSelection(newIds);\r\n sel.ctx.requestRender();\r\n }\r\n}\r\n","export type ShortcutBindings = Record<string, string | string[] | null>;\r\n\r\nexport interface ShortcutOptions {\r\n scope?: 'focus' | 'window';\r\n bindings?: ShortcutBindings;\r\n}\r\n\r\nexport interface ShortcutsApi {\r\n rebind(action: string, bindings: string | string[] | null): void;\r\n disable(action: string): void;\r\n reset(action?: string): void;\r\n getBindings(): Record<string, string[]>;\r\n}\r\n\r\ninterface ParsedBinding {\r\n mod: boolean;\r\n ctrl: boolean;\r\n meta: boolean;\r\n shift: boolean;\r\n alt: boolean;\r\n key: string;\r\n digit: boolean;\r\n}\r\n\r\nconst DEFAULT_BINDINGS: readonly (readonly [string, readonly string[]])[] = [\r\n ['delete', ['delete', 'backspace']],\r\n ['deselect', ['escape']],\r\n ['undo', ['mod+z']],\r\n ['redo', ['mod+y', 'mod+shift+z']],\r\n ['select-all', ['mod+a']],\r\n ['copy', ['mod+c']],\r\n ['paste', ['mod+v']],\r\n ['duplicate', ['mod+d']],\r\n ['z-forward', [']']],\r\n ['z-backward', ['[']],\r\n ['z-front', ['mod+]']],\r\n ['z-back', ['mod+[']],\r\n ['zoom-fit', ['shift+1']],\r\n ['zoom-in', ['mod+=']],\r\n ['zoom-out', ['mod+-']],\r\n ['zoom-reset', ['mod+0']],\r\n ['nudge-left', ['arrowleft']],\r\n ['nudge-right', ['arrowright']],\r\n ['nudge-up', ['arrowup']],\r\n ['nudge-down', ['arrowdown']],\r\n ['tool:select', ['v']],\r\n ['tool:hand', ['h']],\r\n ['tool:pencil', ['p']],\r\n ['tool:eraser', ['e']],\r\n ['tool:arrow', ['a']],\r\n ['tool:note', ['n']],\r\n ['tool:text', ['t']],\r\n ['tool:shape', ['s']],\r\n ['tool:measure', ['m']],\r\n ['tool:template', ['g']],\r\n];\r\n\r\nconst ALLOW_SHIFT = new Set(['nudge-left', 'nudge-right', 'nudge-up', 'nudge-down']);\r\nconst MODIFIERS = new Set(['mod', 'ctrl', 'meta', 'shift', 'alt']);\r\n\r\nfunction parseBinding(binding: string): ParsedBinding {\r\n const parts = binding.toLowerCase().split('+');\r\n const key = parts.pop();\r\n if (key === undefined || key.length === 0 || MODIFIERS.has(key)) {\r\n throw new Error(`Invalid shortcut binding \"${binding}\": missing key`);\r\n }\r\n const normalizedKey = key === 'space' ? ' ' : key;\r\n const parsed: ParsedBinding = {\r\n mod: false,\r\n ctrl: false,\r\n meta: false,\r\n shift: false,\r\n alt: false,\r\n key: normalizedKey,\r\n digit: /^[0-9]$/.test(normalizedKey),\r\n };\r\n for (const part of parts) {\r\n switch (part) {\r\n case 'mod':\r\n parsed.mod = true;\r\n break;\r\n case 'ctrl':\r\n parsed.ctrl = true;\r\n break;\r\n case 'meta':\r\n parsed.meta = true;\r\n break;\r\n case 'shift':\r\n parsed.shift = true;\r\n break;\r\n case 'alt':\r\n parsed.alt = true;\r\n break;\r\n default:\r\n throw new Error(`Invalid shortcut binding \"${binding}\": unknown modifier \"${part}\"`);\r\n }\r\n }\r\n if (parsed.mod && (parsed.ctrl || parsed.meta)) {\r\n throw new Error(\r\n `Invalid shortcut binding \"${binding}\": \"mod\" already means Ctrl or Cmd; don't combine it with ctrl/meta`,\r\n );\r\n }\r\n return parsed;\r\n}\r\n\r\nfunction bindingMatches(p: ParsedBinding, e: KeyboardEvent, allowShift: boolean): boolean {\r\n if (p.mod) {\r\n if (!e.ctrlKey && !e.metaKey) return false;\r\n } else if (e.ctrlKey !== p.ctrl || e.metaKey !== p.meta) {\r\n return false;\r\n }\r\n if (!allowShift && e.shiftKey !== p.shift) return false;\r\n if (e.altKey !== p.alt) return false;\r\n return p.digit ? e.code === `Digit${p.key}` : e.key.toLowerCase() === p.key;\r\n}\r\n\r\nfunction toArray(bindings: string | string[] | null): string[] {\r\n if (bindings === null) return [];\r\n return Array.isArray(bindings) ? [...bindings] : [bindings];\r\n}\r\n\r\nexport class ShortcutMap implements ShortcutsApi {\r\n private raw = new Map<string, string[]>();\r\n private parsed = new Map<string, ParsedBinding[]>();\r\n\r\n constructor(overrides?: ShortcutBindings) {\r\n this.applyDefaults();\r\n if (overrides) {\r\n for (const [action, bindings] of Object.entries(overrides)) {\r\n this.rebind(action, bindings);\r\n }\r\n }\r\n }\r\n\r\n /** First matching action in registration order wins when bindings conflict. */\r\n match(e: KeyboardEvent): string | null {\r\n for (const [action, parsedList] of this.parsed) {\r\n const allowShift = ALLOW_SHIFT.has(action);\r\n for (const p of parsedList) {\r\n if (bindingMatches(p, e, allowShift)) return action;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n rebind(action: string, bindings: string | string[] | null): void {\r\n const list = toArray(bindings);\r\n const parsedList = list.map(parseBinding);\r\n this.raw.set(action, list);\r\n this.parsed.set(action, parsedList);\r\n }\r\n\r\n disable(action: string): void {\r\n this.rebind(action, null);\r\n }\r\n\r\n reset(action?: string): void {\r\n if (action === undefined) {\r\n this.raw.clear();\r\n this.parsed.clear();\r\n this.applyDefaults();\r\n return;\r\n }\r\n const def = DEFAULT_BINDINGS.find(([name]) => name === action);\r\n if (def) {\r\n this.rebind(action, [...def[1]]);\r\n } else if (this.raw.has(action)) {\r\n this.raw.delete(action);\r\n this.parsed.delete(action);\r\n }\r\n }\r\n\r\n getBindings(): Record<string, string[]> {\r\n const out: Record<string, string[]> = {};\r\n for (const [action, list] of this.raw) {\r\n out[action] = [...list];\r\n }\r\n return out;\r\n }\r\n\r\n private applyDefaults(): void {\r\n for (const [action, bindings] of DEFAULT_BINDINGS) {\r\n this.rebind(action, [...bindings]);\r\n }\r\n }\r\n}\r\n","import type { Camera } from './camera';\r\nimport type { ToolManager } from '../tools/tool-manager';\r\nimport type { ToolContext, PointerState } from '../tools/types';\r\nimport type { HistoryRecorder } from '../history/history-recorder';\r\nimport type { HistoryStack } from '../history/history-stack';\r\nimport type { ShortcutOptions, ShortcutsApi } from './shortcut-map';\r\nimport { InputFilter } from './input-filter';\r\nimport { KeyboardActions } from './keyboard-actions';\r\nimport { ShortcutMap } from './shortcut-map';\r\n\r\nconst ZOOM_SENSITIVITY = 0.001;\r\nconst ZOOM_STEP = 1.2;\r\nconst MIDDLE_BUTTON = 1;\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 InputHandlerOptions {\r\n toolManager?: ToolManager;\r\n toolContext?: ToolContext;\r\n historyRecorder?: HistoryRecorder;\r\n historyStack?: HistoryStack;\r\n fitToContent?: () => void;\r\n shortcuts?: ShortcutOptions;\r\n}\r\n\r\nexport class InputHandler {\r\n private isPanning = false;\r\n private lastPointer = { x: 0, y: 0 };\r\n private spaceHeld = false;\r\n private activePointers = new Map<number, { x: number; y: number }>();\r\n private lastPinchDistance = 0;\r\n private lastPinchCenter = { x: 0, y: 0 };\r\n private toolManager: ToolManager | null;\r\n private toolContext: ToolContext | null;\r\n private historyRecorder: HistoryRecorder | null;\r\n private historyStack: HistoryStack | null;\r\n private isToolActive = false;\r\n private lastPointerEvent: PointerEvent | null = null;\r\n private readonly inputFilter = new InputFilter();\r\n private deferredDown: PointerEvent | null = null;\r\n private readonly abortController = new AbortController();\r\n private readonly actions: KeyboardActions;\r\n private readonly shortcutMap: ShortcutMap;\r\n private readonly scope: 'focus' | 'window';\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 getLastPointerWorld: () => this.lastPointerWorld(),\r\n });\r\n this.shortcutMap = new ShortcutMap(options.shortcuts?.bindings);\r\n this.scope = options.shortcuts?.scope ?? 'focus';\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.shortcutMap;\r\n }\r\n\r\n destroy(): void {\r\n this.actions.dispose();\r\n this.abortController.abort();\r\n this.inputFilter.reset();\r\n this.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 window.addEventListener('keydown', this.onKeyDown, opts);\r\n window.addEventListener('keyup', this.onKeyUp, opts);\r\n }\r\n\r\n private viewportCenter(): { x: number; y: number } {\r\n const rect = this.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.camera.zoomAt(this.camera.zoom * factor, this.viewportCenter());\r\n }\r\n\r\n private zoomToLevel(level: number): void {\r\n this.camera.zoomAt(level, this.viewportCenter());\r\n }\r\n\r\n private onWheel = (e: WheelEvent): void => {\r\n e.preventDefault();\r\n const rect = this.element.getBoundingClientRect();\r\n const zoomFactor = 1 - e.deltaY * ZOOM_SENSITIVITY;\r\n const newZoom = this.camera.zoom * zoomFactor;\r\n this.camera.zoomAt(newZoom, {\r\n x: e.clientX - rect.left,\r\n y: e.clientY - rect.top,\r\n });\r\n };\r\n\r\n private onPointerDown = (e: PointerEvent): void => {\r\n this.focusSelf();\r\n this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });\r\n\r\n this.element.setPointerCapture?.(e.pointerId);\r\n\r\n if (this.activePointers.size === 2) {\r\n this.startPinch();\r\n this.cancelToolIfActive(e);\r\n return;\r\n }\r\n\r\n if (e.button === MIDDLE_BUTTON || (e.button === 0 && this.spaceHeld)) {\r\n this.isPanning = true;\r\n this.lastPointer = { x: e.clientX, y: e.clientY };\r\n return;\r\n }\r\n\r\n if (\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 return;\r\n }\r\n this.dispatchToolDown(e);\r\n }\r\n };\r\n\r\n private onPointerMove = (e: PointerEvent): void => {\r\n this.lastPointerEvent = e;\r\n\r\n if (this.activePointers.has(e.pointerId)) {\r\n this.activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY });\r\n }\r\n\r\n if (this.activePointers.size === 2) {\r\n this.handlePinchMove();\r\n return;\r\n }\r\n\r\n if (this.isPanning) {\r\n const dx = e.clientX - this.lastPointer.x;\r\n const dy = e.clientY - this.lastPointer.y;\r\n this.lastPointer = { x: e.clientX, y: e.clientY };\r\n this.camera.pan(dx, dy);\r\n return;\r\n }\r\n\r\n if (e.pointerType === 'pen' && !this.activePointers.has(e.pointerId)) {\r\n this.dispatchToolHover(e);\r\n } else if (this.isToolActive) {\r\n this.dispatchToolMove(e);\r\n } else if (this.deferredDown) {\r\n const result = this.inputFilter.filterMove(e);\r\n if (result.action === 'dispatch') {\r\n this.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 try {\r\n this.element.releasePointerCapture(e.pointerId);\r\n } catch {\r\n // Already released (e.g., pointercancel fired first)\r\n }\r\n this.activePointers.delete(e.pointerId);\r\n\r\n if (this.activePointers.size < 2) {\r\n this.lastPinchDistance = 0;\r\n }\r\n\r\n if (this.isPanning && this.activePointers.size === 0) {\r\n this.isPanning = false;\r\n }\r\n\r\n const upResult = this.inputFilter.filterUp(e);\r\n\r\n if (this.isToolActive) {\r\n this.dispatchToolUp(e);\r\n this.isToolActive = false;\r\n } else if (this.deferredDown && upResult.pendingTap) {\r\n this.dispatchToolDown(this.deferredDown);\r\n this.dispatchToolUp(e);\r\n this.deferredDown = null;\r\n } else {\r\n this.deferredDown = null;\r\n }\r\n };\r\n\r\n private onKeyDown = (e: KeyboardEvent): void => {\r\n const target = e.target as HTMLElement | null;\r\n if (target?.isContentEditable) return;\r\n const tag = target?.tagName;\r\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return;\r\n if (!this.isInScope()) return;\r\n\r\n if (e.key === ' ') {\r\n this.spaceHeld = 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 private onKeyUp = (e: KeyboardEvent): void => {\r\n if (e.key === ' ') {\r\n this.spaceHeld = false;\r\n if (this.activePointers.size === 0) {\r\n if (this.lastPointerEvent) {\r\n this.dispatchToolHover(this.lastPointerEvent);\r\n } else {\r\n this.toolContext?.setCursor?.('default');\r\n }\r\n }\r\n }\r\n };\r\n\r\n private runAction(action: string, e: KeyboardEvent): void {\r\n switch (action) {\r\n case 'delete':\r\n e.preventDefault();\r\n this.actions.deleteSelected();\r\n return;\r\n case 'deselect':\r\n this.actions.deselect();\r\n return;\r\n case 'undo':\r\n e.preventDefault();\r\n this.actions.undo();\r\n return;\r\n case 'redo':\r\n e.preventDefault();\r\n this.actions.redo();\r\n return;\r\n case 'select-all':\r\n e.preventDefault();\r\n this.actions.selectAll();\r\n return;\r\n case 'copy':\r\n e.preventDefault();\r\n this.actions.copy();\r\n return;\r\n case 'paste':\r\n e.preventDefault();\r\n this.actions.paste();\r\n return;\r\n case 'duplicate':\r\n e.preventDefault();\r\n this.actions.duplicate();\r\n return;\r\n case 'z-forward':\r\n e.preventDefault();\r\n this.actions.zOrder('forward');\r\n return;\r\n case 'z-backward':\r\n e.preventDefault();\r\n this.actions.zOrder('backward');\r\n return;\r\n case 'z-front':\r\n e.preventDefault();\r\n this.actions.zOrder('front');\r\n return;\r\n case 'z-back':\r\n e.preventDefault();\r\n this.actions.zOrder('back');\r\n return;\r\n case 'zoom-fit':\r\n e.preventDefault();\r\n this.actions.zoomToFit();\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.actions.nudge(delta[0], delta[1], e.shiftKey)) {\r\n e.preventDefault();\r\n }\r\n return;\r\n }\r\n default:\r\n if (action.startsWith('tool:')) {\r\n if (this.isToolActive) return;\r\n e.preventDefault();\r\n this.toolContext?.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 startPinch(): void {\r\n this.inputFilter.reset();\r\n this.deferredDown = null;\r\n this.isPanning = true;\r\n const [a, b] = this.getPinchPoints();\r\n this.lastPinchDistance = this.distance(a, b);\r\n this.lastPinchCenter = this.midpoint(a, b);\r\n this.lastPointer = { ...this.lastPinchCenter };\r\n }\r\n\r\n private handlePinchMove(): void {\r\n const [a, b] = this.getPinchPoints();\r\n const dist = this.distance(a, b);\r\n const center = this.midpoint(a, b);\r\n\r\n if (this.lastPinchDistance > 0) {\r\n const scale = dist / this.lastPinchDistance;\r\n const newZoom = this.camera.zoom * scale;\r\n this.camera.zoomAt(newZoom, center);\r\n }\r\n\r\n const dx = center.x - this.lastPointer.x;\r\n const dy = center.y - this.lastPointer.y;\r\n this.camera.pan(dx, dy);\r\n\r\n this.lastPinchDistance = dist;\r\n this.lastPinchCenter = center;\r\n this.lastPointer = { ...center };\r\n }\r\n\r\n private getPinchPoints(): [{ x: number; y: number }, { x: number; y: number }] {\r\n const pts = [...this.activePointers.values()];\r\n return [pts[0] ?? { x: 0, y: 0 }, pts[1] ?? { x: 0, y: 0 }];\r\n }\r\n\r\n private distance(a: { x: number; y: number }, b: { x: number; y: number }): number {\r\n const dx = a.x - b.x;\r\n const dy = a.y - b.y;\r\n return Math.sqrt(dx * dx + dy * dy);\r\n }\r\n\r\n private midpoint(\r\n a: { x: number; y: number },\r\n b: { x: number; y: number },\r\n ): { x: number; y: number } {\r\n return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\r\n }\r\n\r\n private lastPointerWorld(): { x: number; y: number } | null {\r\n const e = this.lastPointerEvent;\r\n if (!e) return null;\r\n const rect = this.element.getBoundingClientRect();\r\n return this.camera.screenToWorld({ x: e.clientX - rect.left, y: e.clientY - rect.top });\r\n }\r\n\r\n private 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 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","import type { Camera } from './camera';\r\n\r\nexport type BackgroundPattern = 'dots' | 'grid' | 'none';\r\n\r\nexport interface BackgroundOptions {\r\n pattern?: BackgroundPattern;\r\n spacing?: number;\r\n color?: string;\r\n dotRadius?: number;\r\n lineWidth?: number;\r\n}\r\n\r\nconst MIN_PATTERN_SPACING = 16;\r\n\r\nconst DEFAULTS = {\r\n pattern: 'dots' as BackgroundPattern,\r\n spacing: 24,\r\n color: '#d0d0d0',\r\n dotRadius: 1,\r\n lineWidth: 0.5,\r\n};\r\n\r\nexport class Background {\r\n private readonly pattern: BackgroundPattern;\r\n private readonly spacing: number;\r\n private readonly color: string;\r\n private readonly dotRadius: number;\r\n private readonly lineWidth: number;\r\n private cachedCanvas: OffscreenCanvas | HTMLCanvasElement | null = null;\r\n private cachedCtx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null = null;\r\n private lastZoom = -1;\r\n private lastOffsetX = -Infinity;\r\n private lastOffsetY = -Infinity;\r\n private lastWidth = 0;\r\n private lastHeight = 0;\r\n\r\n constructor(options: BackgroundOptions = {}) {\r\n this.pattern = options.pattern ?? DEFAULTS.pattern;\r\n this.spacing = options.spacing ?? DEFAULTS.spacing;\r\n this.color = options.color ?? DEFAULTS.color;\r\n this.dotRadius = options.dotRadius ?? DEFAULTS.dotRadius;\r\n this.lineWidth = options.lineWidth ?? DEFAULTS.lineWidth;\r\n }\r\n\r\n render(ctx: CanvasRenderingContext2D, camera: Camera): void {\r\n const { width, height } = ctx.canvas;\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n const cssWidth = width / dpr;\r\n const cssHeight = height / dpr;\r\n\r\n ctx.save();\r\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n ctx.clearRect(0, 0, cssWidth, cssHeight);\r\n\r\n if (this.pattern === 'none') {\r\n ctx.restore();\r\n return;\r\n }\r\n\r\n const spacing = this.adaptSpacing(this.spacing, camera.zoom);\r\n const keyZoom = camera.zoom;\r\n const keyX = Math.floor(camera.position.x % spacing);\r\n const keyY = Math.floor(camera.position.y % spacing);\r\n\r\n if (\r\n this.cachedCanvas !== null &&\r\n keyZoom === this.lastZoom &&\r\n keyX === this.lastOffsetX &&\r\n keyY === this.lastOffsetY &&\r\n cssWidth === this.lastWidth &&\r\n cssHeight === this.lastHeight\r\n ) {\r\n ctx.drawImage(this.cachedCanvas as CanvasImageSource, 0, 0);\r\n ctx.restore();\r\n return;\r\n }\r\n\r\n this.ensureCachedCanvas(cssWidth, cssHeight, dpr);\r\n\r\n if (this.cachedCtx === null) {\r\n // Fallback: render directly when offscreen canvas is unavailable (e.g. jsdom)\r\n if (this.pattern === 'dots') {\r\n this.renderDots(ctx, camera, cssWidth, cssHeight);\r\n } else if (this.pattern === 'grid') {\r\n this.renderGrid(ctx, camera, cssWidth, cssHeight);\r\n }\r\n ctx.restore();\r\n return;\r\n }\r\n\r\n const offCtx = this.cachedCtx as CanvasRenderingContext2D;\r\n offCtx.clearRect(0, 0, cssWidth, cssHeight);\r\n if (this.pattern === 'dots') {\r\n this.renderDots(offCtx, camera, cssWidth, cssHeight);\r\n } else if (this.pattern === 'grid') {\r\n this.renderGrid(offCtx, camera, cssWidth, cssHeight);\r\n }\r\n\r\n this.lastZoom = keyZoom;\r\n this.lastOffsetX = keyX;\r\n this.lastOffsetY = keyY;\r\n this.lastWidth = cssWidth;\r\n this.lastHeight = cssHeight;\r\n\r\n ctx.drawImage(this.cachedCanvas as CanvasImageSource, 0, 0);\r\n ctx.restore();\r\n }\r\n\r\n private ensureCachedCanvas(cssWidth: number, cssHeight: number, dpr: number): void {\r\n if (\r\n this.cachedCanvas !== null &&\r\n this.lastWidth === cssWidth &&\r\n this.lastHeight === cssHeight\r\n ) {\r\n return;\r\n }\r\n\r\n const physWidth = Math.round(cssWidth * dpr);\r\n const physHeight = Math.round(cssHeight * dpr);\r\n\r\n if (typeof OffscreenCanvas !== 'undefined') {\r\n this.cachedCanvas = new OffscreenCanvas(physWidth, physHeight);\r\n } else if (typeof document !== 'undefined') {\r\n const el = document.createElement('canvas');\r\n el.width = physWidth;\r\n el.height = physHeight;\r\n this.cachedCanvas = el;\r\n } else {\r\n // No offscreen canvas support available; fall back to direct rendering\r\n this.cachedCanvas = null;\r\n this.cachedCtx = null;\r\n return;\r\n }\r\n\r\n const offCtx = this.cachedCanvas.getContext('2d');\r\n if (offCtx !== null) {\r\n (offCtx as CanvasRenderingContext2D).scale(dpr, dpr);\r\n }\r\n this.cachedCtx = offCtx as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;\r\n\r\n // Force re-render on next frame since canvas was recreated\r\n this.lastZoom = -1;\r\n }\r\n\r\n private adaptSpacing(baseSpacing: number, zoom: number): number {\r\n let spacing = baseSpacing * zoom;\r\n while (spacing < MIN_PATTERN_SPACING) {\r\n spacing *= 2;\r\n }\r\n return spacing;\r\n }\r\n\r\n private renderDots(\r\n ctx: CanvasRenderingContext2D,\r\n camera: Camera,\r\n width: number,\r\n height: number,\r\n ): void {\r\n const spacing = this.adaptSpacing(this.spacing, camera.zoom);\r\n const offsetX = camera.position.x % spacing;\r\n const offsetY = camera.position.y % spacing;\r\n const radius = this.dotRadius * Math.min(camera.zoom, 2);\r\n\r\n ctx.fillStyle = this.color;\r\n ctx.beginPath();\r\n\r\n for (let x = offsetX; x < width; x += spacing) {\r\n for (let y = offsetY; y < height; y += spacing) {\r\n ctx.moveTo(x + radius, y);\r\n ctx.arc(x, y, radius, 0, Math.PI * 2);\r\n }\r\n }\r\n\r\n ctx.fill();\r\n }\r\n\r\n private renderGrid(\r\n ctx: CanvasRenderingContext2D,\r\n camera: Camera,\r\n width: number,\r\n height: number,\r\n ): void {\r\n const spacing = this.adaptSpacing(this.spacing, camera.zoom);\r\n const offsetX = camera.position.x % spacing;\r\n const offsetY = camera.position.y % spacing;\r\n const lineW = this.lineWidth * Math.min(camera.zoom, 2);\r\n\r\n ctx.fillStyle = this.color;\r\n\r\n for (let x = offsetX; x < width; x += spacing) {\r\n ctx.fillRect(x, 0, lineW, height);\r\n }\r\n\r\n for (let y = offsetY; y < height; y += spacing) {\r\n ctx.fillRect(0, y, width, lineW);\r\n }\r\n }\r\n}\r\n","type Listener<T> = (data: T) => void;\r\n\r\nexport class EventBus<TEvents extends { [K in keyof TEvents]: TEvents[K] }> {\r\n private listeners = new Map<keyof TEvents, Set<Listener<never>>>();\r\n\r\n on<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): () => void {\r\n const existing = this.listeners.get(event);\r\n if (existing) {\r\n existing.add(listener as Listener<never>);\r\n } else {\r\n const set = new Set<Listener<never>>([listener as Listener<never>]);\r\n this.listeners.set(event, set);\r\n }\r\n return () => this.off(event, listener);\r\n }\r\n\r\n off<K extends keyof TEvents>(event: K, listener: Listener<TEvents[K]>): void {\r\n this.listeners.get(event)?.delete(listener as Listener<never>);\r\n }\r\n\r\n emit<K extends keyof TEvents>(event: K, data: TEvents[K]): void {\r\n this.listeners.get(event)?.forEach((listener) => {\r\n try {\r\n listener(data as never);\r\n } catch (err) {\r\n console.error(`[fieldnotes] listener error for \"${String(event)}\"`, err);\r\n }\r\n });\r\n }\r\n\r\n clear(): void {\r\n this.listeners.clear();\r\n }\r\n}\r\n","import type { Bounds, Point } from './types';\r\n\r\ninterface Entry {\r\n id: string;\r\n bounds: Bounds;\r\n}\r\n\r\nconst MAX_ITEMS = 8;\r\nconst MAX_DEPTH = 8;\r\n\r\nfunction intersects(a: Bounds, b: Bounds): boolean {\r\n return a.x <= b.x + b.w && a.x + a.w >= b.x && a.y <= b.y + b.h && a.y + a.h >= b.y;\r\n}\r\n\r\nclass QuadNode {\r\n items: Entry[] = [];\r\n children: QuadNode[] | null = null;\r\n\r\n constructor(\r\n readonly bounds: Bounds,\r\n readonly depth: number,\r\n ) {}\r\n\r\n insert(entry: Entry): void {\r\n if (this.children) {\r\n const idx = this.getChildIndex(entry.bounds);\r\n if (idx !== -1) {\r\n const child = this.children[idx];\r\n if (child) child.insert(entry);\r\n return;\r\n }\r\n this.items.push(entry);\r\n return;\r\n }\r\n\r\n this.items.push(entry);\r\n\r\n if (this.items.length > MAX_ITEMS && this.depth < MAX_DEPTH) {\r\n this.split();\r\n }\r\n }\r\n\r\n remove(id: string): boolean {\r\n const idx = this.items.findIndex((e) => e.id === id);\r\n if (idx !== -1) {\r\n this.items.splice(idx, 1);\r\n return true;\r\n }\r\n\r\n if (this.children) {\r\n for (const child of this.children) {\r\n if (child.remove(id)) {\r\n this.collapseIfEmpty();\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n query(rect: Bounds, result: string[]): void {\r\n if (!intersects(this.bounds, rect)) return;\r\n\r\n for (const item of this.items) {\r\n if (intersects(item.bounds, rect)) {\r\n result.push(item.id);\r\n }\r\n }\r\n\r\n if (this.children) {\r\n for (const child of this.children) {\r\n child.query(rect, result);\r\n }\r\n }\r\n }\r\n\r\n private getChildIndex(itemBounds: Bounds): number {\r\n const midX = this.bounds.x + this.bounds.w / 2;\r\n const midY = this.bounds.y + this.bounds.h / 2;\r\n\r\n const left = itemBounds.x >= this.bounds.x && itemBounds.x + itemBounds.w <= midX;\r\n const right =\r\n itemBounds.x >= midX && itemBounds.x + itemBounds.w <= this.bounds.x + this.bounds.w;\r\n const top = itemBounds.y >= this.bounds.y && itemBounds.y + itemBounds.h <= midY;\r\n const bottom =\r\n itemBounds.y >= midY && itemBounds.y + itemBounds.h <= this.bounds.y + this.bounds.h;\r\n\r\n if (left && top) return 0;\r\n if (right && top) return 1;\r\n if (left && bottom) return 2;\r\n if (right && bottom) return 3;\r\n\r\n return -1;\r\n }\r\n\r\n private split(): void {\r\n const { x, y, w, h } = this.bounds;\r\n const halfW = w / 2;\r\n const halfH = h / 2;\r\n const d = this.depth + 1;\r\n\r\n this.children = [\r\n new QuadNode({ x, y, w: halfW, h: halfH }, d),\r\n new QuadNode({ x: x + halfW, y, w: halfW, h: halfH }, d),\r\n new QuadNode({ x, y: y + halfH, w: halfW, h: halfH }, d),\r\n new QuadNode({ x: x + halfW, y: y + halfH, w: halfW, h: halfH }, d),\r\n ];\r\n\r\n const remaining: Entry[] = [];\r\n for (const item of this.items) {\r\n const idx = this.getChildIndex(item.bounds);\r\n if (idx !== -1) {\r\n const target = this.children[idx];\r\n if (target) target.insert(item);\r\n } else {\r\n remaining.push(item);\r\n }\r\n }\r\n this.items = remaining;\r\n }\r\n\r\n private collapseIfEmpty(): void {\r\n if (!this.children) return;\r\n let totalItems = this.items.length;\r\n for (const child of this.children) {\r\n if (child.children) return;\r\n totalItems += child.items.length;\r\n }\r\n if (totalItems <= MAX_ITEMS) {\r\n for (const child of this.children) {\r\n this.items.push(...child.items);\r\n }\r\n this.children = null;\r\n }\r\n }\r\n}\r\n\r\nexport class Quadtree {\r\n private root: QuadNode;\r\n private _size = 0;\r\n private readonly worldBounds: Bounds;\r\n\r\n constructor(worldBounds: Bounds) {\r\n this.worldBounds = worldBounds;\r\n this.root = new QuadNode(worldBounds, 0);\r\n }\r\n\r\n get size(): number {\r\n return this._size;\r\n }\r\n\r\n insert(id: string, bounds: Bounds): void {\r\n this.root.insert({ id, bounds });\r\n this._size++;\r\n }\r\n\r\n remove(id: string): void {\r\n if (this.root.remove(id)) {\r\n this._size--;\r\n }\r\n }\r\n\r\n update(id: string, newBounds: Bounds): void {\r\n this.remove(id);\r\n this.insert(id, newBounds);\r\n }\r\n\r\n query(rect: Bounds): string[] {\r\n const result: string[] = [];\r\n this.root.query(rect, result);\r\n return result;\r\n }\r\n\r\n queryPoint(point: Point): string[] {\r\n return this.query({ x: point.x, y: point.y, w: 0, h: 0 });\r\n }\r\n\r\n clear(): void {\r\n this.root = new QuadNode(this.worldBounds, 0);\r\n this._size = 0;\r\n }\r\n}\r\n","import type { Point, StrokePoint } from '../core/types';\r\n\r\nexport interface CurveSegment {\r\n start: StrokePoint;\r\n cp1: Point;\r\n cp2: Point;\r\n end: StrokePoint;\r\n}\r\n\r\nconst MIN_PRESSURE_SCALE = 0.2;\r\n\r\nexport function pressureToWidth(pressure: number, baseWidth: number): number {\r\n return baseWidth * (MIN_PRESSURE_SCALE + (1 - MIN_PRESSURE_SCALE) * pressure);\r\n}\r\n\r\nexport function simplifyPoints(points: StrokePoint[], tolerance: number): StrokePoint[] {\r\n if (points.length <= 2) return points.slice();\r\n return rdp(points, 0, points.length - 1, tolerance);\r\n}\r\n\r\nfunction rdp(points: StrokePoint[], start: number, end: number, tolerance: number): StrokePoint[] {\r\n const first = points[start];\r\n const last = points[end];\r\n if (!first || !last) return [];\r\n\r\n if (end - start <= 1) return [first, last];\r\n\r\n let maxDist = 0;\r\n let maxIndex = start;\r\n\r\n for (let i = start + 1; i < end; i++) {\r\n const pt = points[i];\r\n if (!pt) continue;\r\n const dist = perpendicularDistance(pt, first, last);\r\n if (dist > maxDist) {\r\n maxDist = dist;\r\n maxIndex = i;\r\n }\r\n }\r\n\r\n if (maxDist <= tolerance) return [first, last];\r\n\r\n const left = rdp(points, start, maxIndex, tolerance);\r\n const right = rdp(points, maxIndex, end, tolerance);\r\n\r\n return left.concat(right.slice(1));\r\n}\r\n\r\nfunction perpendicularDistance(pt: Point, lineStart: Point, lineEnd: Point): number {\r\n const dx = lineEnd.x - lineStart.x;\r\n const dy = lineEnd.y - lineStart.y;\r\n const lenSq = dx * dx + dy * dy;\r\n\r\n if (lenSq === 0) {\r\n const ex = pt.x - lineStart.x;\r\n const ey = pt.y - lineStart.y;\r\n return Math.sqrt(ex * ex + ey * ey);\r\n }\r\n\r\n const num = Math.abs(dy * pt.x - dx * pt.y + lineEnd.x * lineStart.y - lineEnd.y * lineStart.x);\r\n return num / Math.sqrt(lenSq);\r\n}\r\n\r\nexport function smoothToSegments(points: StrokePoint[]): CurveSegment[] {\r\n if (points.length < 2) return [];\r\n\r\n if (points.length === 2) {\r\n const p0 = points[0];\r\n const p1 = points[1];\r\n if (!p0 || !p1) return [];\r\n const mx = (p0.x + p1.x) / 2;\r\n const my = (p0.y + p1.y) / 2;\r\n return [{ start: p0, cp1: { x: mx, y: my }, cp2: { x: mx, y: my }, end: p1 }];\r\n }\r\n\r\n const segments: CurveSegment[] = [];\r\n const n = points.length;\r\n\r\n for (let i = 0; i < n - 1; i++) {\r\n const p0 = points[Math.max(0, i - 1)];\r\n const p1 = points[i];\r\n const p2 = points[i + 1];\r\n const p3 = points[Math.min(n - 1, i + 2)];\r\n if (!p0 || !p1 || !p2 || !p3) continue;\r\n\r\n const cp1: Point = {\r\n x: p1.x + (p2.x - p0.x) / 6,\r\n y: p1.y + (p2.y - p0.y) / 6,\r\n };\r\n const cp2: Point = {\r\n x: p2.x - (p3.x - p1.x) / 6,\r\n y: p2.y - (p3.y - p1.y) / 6,\r\n };\r\n\r\n segments.push({ start: p1, cp1, cp2, end: p2 });\r\n }\r\n\r\n return segments;\r\n}\r\n","import type { CanvasElement, StrokeElement } 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 { getElementBounds, transferStrokeBounds } from './element-bounds';\r\nimport { getArrowControlPoint } from './arrow-geometry';\r\nimport { sanitizeNoteHtml } from './note-sanitizer';\r\nimport { computeStrokeSegments, transferStrokeRenderData } from './stroke-cache';\r\nimport type { ArrowElement, CanvasElement, ElementType, NoteElement } from './types';\r\n\r\nexport interface ElementUpdateEvent {\r\n previous: CanvasElement;\r\n current: CanvasElement;\r\n}\r\n\r\ninterface ElementStoreEvents {\r\n add: CanvasElement;\r\n remove: CanvasElement;\r\n update: ElementUpdateEvent;\r\n clear: null;\r\n}\r\n\r\nexport class ElementStore {\r\n private elements = new Map<string, CanvasElement>();\r\n private bus = new EventBus<ElementStoreEvents>();\r\n private layerOrderMap = new Map<string, number>();\r\n private spatialIndex = new Quadtree({ x: -100000, y: -100000, w: 200000, h: 200000 });\r\n private sortedCache: CanvasElement[] | null = null;\r\n private _versions = new Map<string, number>();\r\n\r\n get count(): number {\r\n return this.elements.size;\r\n }\r\n\r\n getVersion(id: string): number {\r\n return this._versions.get(id) ?? -1;\r\n }\r\n\r\n setLayerOrder(order: Map<string, number>): void {\r\n this.layerOrderMap = new Map(order);\r\n this.sortedCache = null;\r\n }\r\n\r\n getAll(): CanvasElement[] {\r\n if (this.sortedCache) return this.sortedCache;\r\n this.sortedCache = [...this.elements.values()].sort((a, b) => {\r\n const layerA = this.layerOrderMap.get(a.layerId) ?? 0;\r\n const layerB = this.layerOrderMap.get(b.layerId) ?? 0;\r\n if (layerA !== layerB) return layerA - layerB;\r\n return a.zIndex - b.zIndex;\r\n });\r\n return this.sortedCache;\r\n }\r\n\r\n getById(id: string): CanvasElement | undefined {\r\n return this.elements.get(id);\r\n }\r\n\r\n getElementsByType<T extends ElementType>(type: T): Extract<CanvasElement, { type: T }>[] {\r\n return this.getAll().filter(\r\n (el): el is Extract<CanvasElement, { type: T }> => el.type === type,\r\n );\r\n }\r\n\r\n add(element: CanvasElement): void {\r\n this.sortedCache = null;\r\n this._versions.set(element.id, 0);\r\n this.elements.set(element.id, element);\r\n const bounds = getElementBounds(element);\r\n if (bounds) this.spatialIndex.insert(element.id, bounds);\r\n this.bus.emit('add', element);\r\n }\r\n\r\n update(id: string, partial: Partial<CanvasElement>): void {\r\n const existing = this.elements.get(id);\r\n if (!existing) return;\r\n this.sortedCache = null;\r\n this._versions.set(id, (this._versions.get(id) ?? 0) + 1);\r\n\r\n // Shallow spread preserves the points array identity when `partial` omits points;\r\n // transferStrokeRenderData/transferStrokeBounds rely on that reference equality.\r\n const updated = { ...existing, ...partial, id: existing.id, type: existing.type };\r\n\r\n if (updated.type === 'stroke' && existing.type === 'stroke') {\r\n transferStrokeRenderData(existing, updated as CanvasElement);\r\n transferStrokeBounds(existing, updated as CanvasElement);\r\n }\r\n\r\n if (updated.type === 'arrow') {\r\n const arrow = updated as ArrowElement;\r\n arrow.cachedControlPoint = getArrowControlPoint(arrow.from, arrow.to, arrow.bend);\r\n }\r\n\r\n if (updated.type === 'note' && 'text' in partial) {\r\n (updated as NoteElement).text = sanitizeNoteHtml((updated as NoteElement).text);\r\n }\r\n\r\n this.elements.set(id, updated as CanvasElement);\r\n\r\n const newBounds = getElementBounds(updated as CanvasElement);\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 as CanvasElement });\r\n }\r\n\r\n remove(id: string): void {\r\n const element = this.elements.get(id);\r\n if (!element) return;\r\n this.sortedCache = null;\r\n this._versions.delete(id);\r\n\r\n this.elements.delete(id);\r\n this.spatialIndex.remove(id);\r\n this.bus.emit('remove', element);\r\n }\r\n\r\n clear(): void {\r\n this.sortedCache = null;\r\n this._versions.clear();\r\n this.elements.clear();\r\n this.spatialIndex.clear();\r\n this.bus.emit('clear', null);\r\n }\r\n\r\n snapshot(): CanvasElement[] {\r\n return this.getAll().map((el) => ({ ...el }));\r\n }\r\n\r\n loadSnapshot(elements: CanvasElement[]): void {\r\n this.sortedCache = null;\r\n this._versions.clear();\r\n this.elements.clear();\r\n this.spatialIndex.clear();\r\n for (const el of elements) {\r\n this.elements.set(el.id, el);\r\n this._versions.set(el.id, 0);\r\n const bounds = getElementBounds(el);\r\n if (bounds) this.spatialIndex.insert(el.id, bounds);\r\n if (el.type === 'stroke') {\r\n computeStrokeSegments(el);\r\n }\r\n if (el.type === 'arrow' && el.bend !== 0 && !el.cachedControlPoint) {\r\n el.cachedControlPoint = getArrowControlPoint(el.from, el.to, el.bend);\r\n }\r\n }\r\n this.bus.emit('clear', null);\r\n for (const el of elements) {\r\n this.bus.emit('add', el);\r\n }\r\n }\r\n\r\n bringToFront(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const siblings = [...this.elements.values()].filter(\r\n (e) => e.layerId === el.layerId && e.id !== id,\r\n );\r\n if (siblings.length === 0) return;\r\n const maxZ = Math.max(...siblings.map((e) => e.zIndex));\r\n if (el.zIndex >= maxZ) return;\r\n this.update(id, { zIndex: maxZ + 1 });\r\n }\r\n\r\n sendToBack(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const siblings = [...this.elements.values()].filter(\r\n (e) => e.layerId === el.layerId && e.id !== id,\r\n );\r\n if (siblings.length === 0) return;\r\n const minZ = Math.min(...siblings.map((e) => e.zIndex));\r\n if (el.zIndex <= minZ) return;\r\n this.update(id, { zIndex: minZ - 1 });\r\n }\r\n\r\n bringForward(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const sorted = [...this.elements.values()]\r\n .filter((e) => e.layerId === el.layerId)\r\n .sort((a, b) => a.zIndex - b.zIndex);\r\n const idx = sorted.findIndex((e) => e.id === id);\r\n if (idx < 0 || idx >= sorted.length - 1) return;\r\n const next = sorted[idx + 1];\r\n if (!next) return;\r\n const myZ = el.zIndex;\r\n const nextZ = next.zIndex;\r\n this.update(id, { zIndex: nextZ });\r\n this.update(next.id, { zIndex: myZ });\r\n }\r\n\r\n sendBackward(id: string): void {\r\n const el = this.elements.get(id);\r\n if (!el) return;\r\n const sorted = [...this.elements.values()]\r\n .filter((e) => e.layerId === el.layerId)\r\n .sort((a, b) => a.zIndex - b.zIndex);\r\n const idx = sorted.findIndex((e) => e.id === id);\r\n if (idx <= 0) return;\r\n const prev = sorted[idx - 1];\r\n if (!prev) return;\r\n const myZ = el.zIndex;\r\n const prevZ = prev.zIndex;\r\n this.update(id, { zIndex: prevZ });\r\n this.update(prev.id, { zIndex: myZ });\r\n }\r\n\r\n queryRect(rect: Bounds): CanvasElement[] {\r\n const ids = this.spatialIndex.query(rect);\r\n const elements: CanvasElement[] = [];\r\n for (const id of ids) {\r\n const el = this.elements.get(id);\r\n if (el) elements.push(el);\r\n }\r\n return elements.sort((a, b) => {\r\n const layerA = this.layerOrderMap.get(a.layerId) ?? 0;\r\n const layerB = this.layerOrderMap.get(b.layerId) ?? 0;\r\n if (layerA !== layerB) return layerA - layerB;\r\n return a.zIndex - b.zIndex;\r\n });\r\n }\r\n\r\n queryPoint(point: Point): CanvasElement[] {\r\n return this.queryRect({ x: point.x, y: point.y, w: 0, h: 0 });\r\n }\r\n\r\n on<K extends keyof ElementStoreEvents>(\r\n event: K,\r\n listener: (data: ElementStoreEvents[K]) => void,\r\n ): () => void {\r\n return this.bus.on(event, listener);\r\n }\r\n\r\n onChange(listener: () => void): () => void {\r\n const unsubs = [\r\n this.bus.on('add', listener),\r\n this.bus.on('remove', listener),\r\n this.bus.on('update', listener),\r\n this.bus.on('clear', listener),\r\n ];\r\n return () => unsubs.forEach((fn) => fn());\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\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\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 { 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 { Point } from '../core/types';\r\nimport type { HexOrientation } from './types';\r\n\r\ninterface HexCoord {\r\n col: number;\r\n row: number;\r\n}\r\n\r\nfunction offsetToCube(\r\n col: number,\r\n row: number,\r\n orientation: HexOrientation,\r\n): { q: number; r: number } {\r\n if (orientation === 'pointy') {\r\n return { q: col - (row - (row & 1)) / 2, r: row };\r\n }\r\n return { q: col, r: row - (col - (col & 1)) / 2 };\r\n}\r\n\r\nfunction cubeToOffset(q: number, r: number, orientation: HexOrientation): HexCoord {\r\n if (orientation === 'pointy') {\r\n return { col: q + (r - (r & 1)) / 2, row: r };\r\n }\r\n return { col: q, row: r + (q - (q & 1)) / 2 };\r\n}\r\n\r\nfunction offsetToPixel(\r\n col: number,\r\n row: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point {\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * cellSize;\r\n const rowH = 1.5 * cellSize;\r\n const offsetX = row % 2 !== 0 ? hexW / 2 : 0;\r\n return { x: col * hexW + offsetX, y: row * rowH };\r\n }\r\n const hexH = Math.sqrt(3) * cellSize;\r\n const colW = 1.5 * cellSize;\r\n const offsetY = col % 2 !== 0 ? hexH / 2 : 0;\r\n return { x: col * colW, y: row * hexH + offsetY };\r\n}\r\n\r\nfunction pixelToOffset(\r\n x: number,\r\n y: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): HexCoord {\r\n if (orientation === 'pointy') {\r\n const hexW = Math.sqrt(3) * cellSize;\r\n const rowH = 1.5 * cellSize;\r\n const row = Math.round(y / rowH);\r\n const offsetX = row % 2 !== 0 ? hexW / 2 : 0;\r\n return { col: Math.round((x - offsetX) / hexW), row };\r\n }\r\n const hexH = Math.sqrt(3) * cellSize;\r\n const colW = 1.5 * cellSize;\r\n const col = Math.round(x / colW);\r\n const offsetY = col % 2 !== 0 ? hexH / 2 : 0;\r\n return { col, row: Math.round((y - offsetY) / hexH) };\r\n}\r\n\r\nfunction enumerateHexRing(\r\n centerQ: number,\r\n centerR: number,\r\n n: number,\r\n orientation: HexOrientation,\r\n cellSize: number,\r\n): Point[] {\r\n const cells: Point[] = [];\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n const absQ = centerQ + dq;\r\n const absR = centerR + dr;\r\n const off = cubeToOffset(absQ, absR, orientation);\r\n cells.push(offsetToPixel(off.col, off.row, cellSize, orientation));\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function getHexDistance(\r\n a: Point,\r\n b: Point,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): number {\r\n const offA = pixelToOffset(a.x, a.y, cellSize, orientation);\r\n const offB = pixelToOffset(b.x, b.y, cellSize, orientation);\r\n const cubeA = offsetToCube(offA.col, offA.row, orientation);\r\n const cubeB = offsetToCube(offB.col, offB.row, orientation);\r\n const dq = cubeA.q - cubeB.q;\r\n const dr = cubeA.r - cubeB.r;\r\n const ds = -dq - dr;\r\n return Math.max(Math.abs(dq), Math.abs(dr), Math.abs(ds));\r\n}\r\n\r\nexport function getHexCellsInRadius(\r\n center: Point,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n if (n <= 0) {\r\n return [offsetToPixel(off.col, off.row, cellSize, orientation)];\r\n }\r\n return enumerateHexRing(cube.q, cube.r, n, orientation, cellSize);\r\n}\r\n\r\nexport function getHexCellsInCone(\r\n center: Point,\r\n angle: number,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n const centerPixel = offsetToPixel(off.col, off.row, cellSize, orientation);\r\n\r\n if (n <= 0) return [centerPixel];\r\n\r\n const vertexOffset = orientation === 'pointy' ? Math.PI / 6 : 0;\r\n const step = Math.PI / 3;\r\n const snappedAngle = Math.round((angle - vertexOffset) / step) * step + vertexOffset;\r\n\r\n const halfAngle = Math.PI / 6 + 1e-6;\r\n const cells: Point[] = [centerPixel];\r\n\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n if (dq === 0 && dr === 0) continue;\r\n const absQ = cube.q + dq;\r\n const absR = cube.r + dr;\r\n const pixel = offsetToPixel(\r\n cubeToOffset(absQ, absR, orientation).col,\r\n cubeToOffset(absQ, absR, orientation).row,\r\n cellSize,\r\n orientation,\r\n );\r\n\r\n const dx = pixel.x - centerPixel.x;\r\n const dy = pixel.y - centerPixel.y;\r\n let diff = Math.atan2(dy, dx) - snappedAngle;\r\n if (diff > Math.PI) diff -= 2 * Math.PI;\r\n if (diff < -Math.PI) diff += 2 * Math.PI;\r\n\r\n if (Math.abs(diff) <= halfAngle) {\r\n cells.push(pixel);\r\n }\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function getHexCellsInLine(\r\n center: Point,\r\n angle: number,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n const centerPixel = offsetToPixel(off.col, off.row, cellSize, orientation);\r\n\r\n if (n <= 0) return [centerPixel];\r\n\r\n const vertexOffset = orientation === 'pointy' ? Math.PI / 6 : 0;\r\n const step = Math.PI / 3;\r\n const snappedAngle = Math.round((angle - vertexOffset) / step) * step + vertexOffset;\r\n\r\n const cos = Math.cos(snappedAngle);\r\n const sin = Math.sin(snappedAngle);\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const lineLength = n * snapUnit;\r\n const halfWidth = snapUnit * 0.5 + 1e-6;\r\n const cells: Point[] = [];\r\n\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n const absQ = cube.q + dq;\r\n const absR = cube.r + dr;\r\n const pixel = offsetToPixel(\r\n cubeToOffset(absQ, absR, orientation).col,\r\n cubeToOffset(absQ, absR, orientation).row,\r\n cellSize,\r\n orientation,\r\n );\r\n\r\n const dx = pixel.x - centerPixel.x;\r\n const dy = pixel.y - centerPixel.y;\r\n const along = dx * cos + dy * sin;\r\n const perp = Math.abs(-dx * sin + dy * cos);\r\n\r\n if (along >= -snapUnit * 0.1 && along <= lineLength + snapUnit * 0.1 && perp <= halfWidth) {\r\n cells.push(pixel);\r\n }\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function getHexCellsInSquare(\r\n center: Point,\r\n radiusCells: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): Point[] {\r\n const n = Math.round(radiusCells);\r\n const off = pixelToOffset(center.x, center.y, cellSize, orientation);\r\n const cube = offsetToCube(off.col, off.row, orientation);\r\n const centerPixel = offsetToPixel(off.col, off.row, cellSize, orientation);\r\n\r\n if (n <= 0) return [centerPixel];\r\n\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const halfSide = (n * snapUnit) / 2;\r\n const cells: Point[] = [];\r\n\r\n for (let dq = -n; dq <= n; dq++) {\r\n const rMin = Math.max(-n, -dq - n);\r\n const rMax = Math.min(n, -dq + n);\r\n for (let dr = rMin; dr <= rMax; dr++) {\r\n const absQ = cube.q + dq;\r\n const absR = cube.r + dr;\r\n const pixel = offsetToPixel(\r\n cubeToOffset(absQ, absR, orientation).col,\r\n cubeToOffset(absQ, absR, orientation).row,\r\n cellSize,\r\n orientation,\r\n );\r\n\r\n if (\r\n Math.abs(pixel.x - centerPixel.x) <= halfSide &&\r\n Math.abs(pixel.y - centerPixel.y) <= halfSide\r\n ) {\r\n cells.push(pixel);\r\n }\r\n }\r\n }\r\n return cells;\r\n}\r\n\r\nexport function drawHexPath(\r\n ctx: CanvasRenderingContext2D,\r\n cx: number,\r\n cy: number,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n): void {\r\n const angleOffset = orientation === 'pointy' ? Math.PI / 6 : 0;\r\n ctx.moveTo(cx + cellSize * Math.cos(angleOffset), cy + cellSize * Math.sin(angleOffset));\r\n for (let i = 1; i < 6; i++) {\r\n const a = angleOffset + (Math.PI / 3) * i;\r\n ctx.lineTo(cx + cellSize * Math.cos(a), cy + cellSize * Math.sin(a));\r\n }\r\n ctx.closePath();\r\n}\r\n","import type {\r\n CanvasElement,\r\n StrokeElement,\r\n ArrowElement,\r\n ShapeElement,\r\n ImageElement,\r\n GridElement,\r\n TemplateElement,\r\n} from './types';\r\nimport { getArrowRenderGeometry } from './arrow-render-cache';\r\nimport { getEdgeIntersection } from './arrow-binding';\r\nimport { getElementBounds } from './element-bounds';\r\nimport { getStrokeRenderData } from './stroke-cache';\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\nimport {\r\n getHexCellsInRadius,\r\n getHexCellsInCone,\r\n getHexCellsInLine,\r\n getHexCellsInSquare,\r\n drawHexPath,\r\n} from './hex-fill';\r\n\r\nconst DOM_ELEMENT_TYPES = new Set(['note', 'html', 'text']);\r\nconst ARROWHEAD_LENGTH = 12;\r\nconst ARROWHEAD_ANGLE = Math.PI / 6;\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\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 isDomElement(element: CanvasElement): boolean {\r\n return DOM_ELEMENT_TYPES.has(element.type);\r\n }\r\n\r\n renderCanvasElement(ctx: CanvasRenderingContext2D, element: CanvasElement): void {\r\n switch (element.type) {\r\n case 'stroke':\r\n this.renderStroke(ctx, element);\r\n break;\r\n case 'arrow':\r\n this.renderArrow(ctx, element);\r\n break;\r\n case 'shape':\r\n this.renderShape(ctx, element);\r\n break;\r\n case 'image':\r\n this.renderImage(ctx, element);\r\n break;\r\n case 'grid':\r\n this.renderGrid(ctx, element);\r\n break;\r\n case 'template':\r\n this.renderTemplate(ctx, element);\r\n break;\r\n }\r\n }\r\n\r\n private renderStroke(ctx: CanvasRenderingContext2D, stroke: StrokeElement): void {\r\n if (stroke.points.length < 2) return;\r\n\r\n ctx.save();\r\n ctx.translate(stroke.position.x, stroke.position.y);\r\n ctx.strokeStyle = stroke.color;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n ctx.globalAlpha = stroke.opacity;\r\n\r\n const 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\r\n private renderArrow(ctx: CanvasRenderingContext2D, arrow: ArrowElement): void {\r\n const geometry = getArrowRenderGeometry(arrow);\r\n const { visualFrom, visualTo } = this.getVisualEndpoints(arrow, geometry);\r\n\r\n ctx.save();\r\n ctx.strokeStyle = arrow.color;\r\n ctx.lineWidth = arrow.width;\r\n ctx.lineCap = 'round';\r\n\r\n if (arrow.fromBinding || arrow.toBinding) {\r\n ctx.setLineDash([8, 4]);\r\n }\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(visualFrom.x, visualFrom.y);\r\n\r\n if (arrow.bend !== 0) {\r\n const cp = geometry.controlPoint;\r\n if (cp) {\r\n ctx.quadraticCurveTo(cp.x, cp.y, visualTo.x, visualTo.y);\r\n }\r\n } else {\r\n ctx.lineTo(visualTo.x, visualTo.y);\r\n }\r\n ctx.stroke();\r\n\r\n this.renderArrowhead(ctx, arrow, visualTo, geometry.tangentEnd);\r\n ctx.restore();\r\n }\r\n\r\n private 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\n private getVisualEndpoints(\r\n arrow: ArrowElement,\r\n geometry: ReturnType<typeof getArrowRenderGeometry>,\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 (!this.store) return { visualFrom, visualTo };\r\n\r\n if (arrow.fromBinding) {\r\n const el = this.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 = this.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\r\n private renderShape(ctx: CanvasRenderingContext2D, shape: ShapeElement): void {\r\n ctx.save();\r\n\r\n if (shape.fillColor !== 'none') {\r\n ctx.fillStyle = shape.fillColor;\r\n this.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 this.strokeShapePath(ctx, shape);\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private 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\n private 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 }\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 renderTemplate(ctx: CanvasRenderingContext2D, template: TemplateElement): void {\r\n const grid = this.store?.getElementsByType('grid')[0];\r\n if (grid && grid.gridType === 'hex') {\r\n this.renderHexTemplate(ctx, template, grid.cellSize, grid.hexOrientation);\r\n return;\r\n }\r\n\r\n this.renderGeometricTemplate(ctx, template);\r\n }\r\n\r\n private renderGeometricTemplate(ctx: CanvasRenderingContext2D, template: TemplateElement): void {\r\n const { x: cx, y: cy } = template.position;\r\n const r = template.radius;\r\n\r\n ctx.save();\r\n ctx.globalAlpha = template.opacity;\r\n ctx.fillStyle = template.fillColor;\r\n ctx.strokeStyle = template.strokeColor;\r\n ctx.lineWidth = template.strokeWidth;\r\n\r\n switch (template.templateShape) {\r\n case 'circle':\r\n ctx.beginPath();\r\n ctx.arc(cx, cy, r, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.stroke();\r\n if (template.radiusFeet != null && template.radiusFeet > 0) {\r\n this.renderRadiusMarker(ctx, cx, cy, r, template.radiusFeet);\r\n }\r\n break;\r\n\r\n case 'square':\r\n ctx.fillRect(cx - r / 2, cy - r / 2, r, r);\r\n ctx.strokeRect(cx - r / 2, cy - r / 2, r, r);\r\n break;\r\n\r\n case 'cone': {\r\n const halfAngle = Math.atan(0.5);\r\n ctx.beginPath();\r\n ctx.moveTo(cx, cy);\r\n ctx.arc(cx, cy, r, template.angle - halfAngle, template.angle + halfAngle);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n\r\n case 'line': {\r\n const halfW = r / 12;\r\n const cos = Math.cos(template.angle);\r\n const sin = Math.sin(template.angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(cx + perpX, cy + perpY);\r\n ctx.lineTo(cx + r * cos + perpX, cy + r * sin + perpY);\r\n ctx.lineTo(cx + r * cos - perpX, cy + r * sin - perpY);\r\n ctx.lineTo(cx - perpX, cy - perpY);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private renderHexTemplate(\r\n ctx: CanvasRenderingContext2D,\r\n template: TemplateElement,\r\n cellSize: number,\r\n orientation: HexOrientation,\r\n ): void {\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const radiusCells = template.radius / snapUnit;\r\n const center = template.position;\r\n\r\n let cells: { x: number; y: number }[];\r\n switch (template.templateShape) {\r\n case 'circle':\r\n cells = getHexCellsInRadius(center, radiusCells, cellSize, orientation);\r\n break;\r\n case 'cone':\r\n cells = getHexCellsInCone(center, template.angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'line':\r\n cells = getHexCellsInLine(center, template.angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'square':\r\n cells = getHexCellsInSquare(center, radiusCells, cellSize, orientation);\r\n break;\r\n }\r\n\r\n ctx.save();\r\n ctx.globalAlpha = template.opacity;\r\n\r\n ctx.beginPath();\r\n for (const cell of cells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.fillStyle = template.fillColor;\r\n ctx.fill();\r\n\r\n ctx.beginPath();\r\n for (const cell of cells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.strokeStyle = template.strokeColor;\r\n ctx.lineWidth = template.strokeWidth;\r\n ctx.stroke();\r\n\r\n {\r\n ctx.globalAlpha = Math.min(template.opacity + 0.1, 1);\r\n ctx.beginPath();\r\n drawHexPath(ctx, center.x, center.y, cellSize, orientation);\r\n ctx.fillStyle = template.strokeColor;\r\n ctx.fill();\r\n ctx.strokeStyle = template.strokeColor;\r\n ctx.lineWidth = template.strokeWidth;\r\n ctx.stroke();\r\n }\r\n\r\n if (\r\n template.templateShape === 'circle' &&\r\n template.radiusFeet != null &&\r\n template.radiusFeet > 0\r\n ) {\r\n const r = template.radius;\r\n this.renderRadiusMarker(ctx, center.x, center.y, r, template.radiusFeet);\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private renderRadiusMarker(\r\n ctx: CanvasRenderingContext2D,\r\n cx: number,\r\n cy: number,\r\n r: number,\r\n feet: number,\r\n ): void {\r\n const markerColor = ctx.strokeStyle as string;\r\n\r\n ctx.save();\r\n ctx.globalAlpha = 1;\r\n\r\n ctx.beginPath();\r\n ctx.setLineDash([4, 4]);\r\n ctx.strokeStyle = markerColor;\r\n ctx.lineWidth = 1.5;\r\n ctx.moveTo(cx, cy);\r\n ctx.lineTo(cx + r, cy);\r\n ctx.stroke();\r\n ctx.setLineDash([]);\r\n\r\n const label = `${Math.round(feet)} ft`;\r\n const fontSize = Math.max(10, Math.min(14, r * 0.15));\r\n ctx.font = `bold ${fontSize}px system-ui, sans-serif`;\r\n ctx.textAlign = 'center';\r\n ctx.textBaseline = 'bottom';\r\n const textX = cx + r / 2;\r\n const textY = cy - 4;\r\n\r\n const metrics = ctx.measureText(label);\r\n const padX = 4;\r\n const padY = 2;\r\n const textW = metrics.width + padX * 2;\r\n const textH = fontSize + padY * 2;\r\n\r\n ctx.fillStyle = 'rgba(255, 255, 255, 0.85)';\r\n ctx.beginPath();\r\n ctx.roundRect(textX - textW / 2, textY - textH, textW, textH, 3);\r\n ctx.fill();\r\n\r\n ctx.fillStyle = markerColor;\r\n ctx.fillText(label, textX, textY - padY);\r\n\r\n ctx.restore();\r\n }\r\n\r\n private renderImage(ctx: CanvasRenderingContext2D, image: ImageElement): void {\r\n if (this.imageCache.get(image.src) === 'failed') {\r\n this.renderImagePlaceholder(ctx, image);\r\n return;\r\n }\r\n const img = this.getImage(image.src);\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\n private 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\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 private getImage(src: string): ImageBitmap | HTMLImageElement | null {\r\n const cached = this.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 this.imageCache.set(src, img);\r\n img.onload = () => {\r\n this.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 this.imageCache.set(src, bitmap);\r\n this.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 this.imageCache.set(src, 'failed');\r\n this.onImageError?.(src, event);\r\n this.onImageLoad?.();\r\n };\r\n return null;\r\n }\r\n}\r\n","import type { Point, Size, StrokePoint } from '../core/types';\r\nimport type {\r\n Binding,\r\n StrokeElement,\r\n NoteElement,\r\n ArrowElement,\r\n ImageElement,\r\n HtmlElement,\r\n TextElement,\r\n ShapeElement,\r\n ShapeKind,\r\n GridElement,\r\n HexOrientation,\r\n TemplateElement,\r\n TemplateShape,\r\n} from './types';\r\nimport { createId } from './create-id';\r\nimport { getArrowControlPoint } from './arrow-geometry';\r\nimport { sanitizeNoteHtml } from './note-sanitizer';\r\n\r\nexport const DEFAULT_NOTE_FONT_SIZE = 18;\r\n\r\ninterface BaseDefaults {\r\n position?: Point;\r\n zIndex?: number;\r\n locked?: boolean;\r\n layerId?: string;\r\n}\r\n\r\ninterface StrokeInput extends BaseDefaults {\r\n points: StrokePoint[];\r\n color?: string;\r\n width?: number;\r\n opacity?: number;\r\n}\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}\r\n\r\ninterface ImageInput extends BaseDefaults {\r\n position: Point;\r\n size: Size;\r\n src: string;\r\n}\r\n\r\ninterface HtmlInput extends BaseDefaults {\r\n position: Point;\r\n size: Size;\r\n domId?: string;\r\n interactive?: boolean;\r\n}\r\n\r\ninterface TextInput extends BaseDefaults {\r\n position: Point;\r\n size?: Size;\r\n text?: string;\r\n fontSize?: number;\r\n color?: string;\r\n textAlign?: 'left' | 'center' | 'right';\r\n}\r\n\r\nexport function createStroke(input: StrokeInput): StrokeElement {\r\n return {\r\n id: createId('stroke'),\r\n type: 'stroke',\r\n position: input.position ?? { x: 0, y: 0 },\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n 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}\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 return result;\r\n}\r\n\r\nexport function createImage(input: ImageInput): ImageElement {\r\n return {\r\n id: createId('image'),\r\n type: 'image',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n size: input.size,\r\n src: input.src,\r\n };\r\n}\r\n\r\nexport function createHtmlElement(input: HtmlInput): HtmlElement {\r\n const el: HtmlElement = {\r\n id: createId('html'),\r\n type: 'html',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n size: input.size,\r\n };\r\n if (input.domId) el.domId = input.domId;\r\n if (input.interactive) el.interactive = input.interactive;\r\n return el;\r\n}\r\n\r\ninterface ShapeInput extends BaseDefaults {\r\n position: Point;\r\n size: Size;\r\n shape?: ShapeKind;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n fillColor?: string;\r\n}\r\n\r\nexport function createShape(input: ShapeInput): ShapeElement {\r\n return {\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}\r\n\r\ninterface GridInput extends BaseDefaults {\r\n gridType?: 'square' | 'hex';\r\n hexOrientation?: HexOrientation;\r\n cellSize?: number;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n}\r\n\r\nexport function createGrid(input: GridInput): GridElement {\r\n return {\r\n id: createId('grid'),\r\n type: 'grid',\r\n position: input.position ?? { x: 0, y: 0 },\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n gridType: input.gridType ?? 'square',\r\n hexOrientation: input.hexOrientation ?? 'pointy',\r\n cellSize: input.cellSize ?? 40,\r\n strokeColor: input.strokeColor ?? '#000000',\r\n strokeWidth: input.strokeWidth ?? 1,\r\n opacity: input.opacity ?? 1,\r\n };\r\n}\r\n\r\nexport function createText(input: TextInput): TextElement {\r\n return {\r\n id: createId('text'),\r\n type: 'text',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n size: input.size ?? { w: 200, h: 28 },\r\n text: input.text ?? '',\r\n fontSize: input.fontSize ?? 16,\r\n color: input.color ?? '#1a1a1a',\r\n textAlign: input.textAlign ?? 'left',\r\n };\r\n}\r\n\r\ninterface TemplateInput extends BaseDefaults {\r\n position: Point;\r\n templateShape: TemplateShape;\r\n radius: number;\r\n angle?: number;\r\n fillColor?: string;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n feetPerCell?: number;\r\n radiusFeet?: number;\r\n}\r\n\r\nexport function createTemplate(input: TemplateInput): TemplateElement {\r\n return {\r\n id: createId('template'),\r\n type: 'template',\r\n position: input.position,\r\n zIndex: input.zIndex ?? 0,\r\n locked: input.locked ?? false,\r\n layerId: input.layerId ?? '',\r\n templateShape: input.templateShape,\r\n radius: input.radius,\r\n angle: input.angle ?? 0,\r\n fillColor: input.fillColor ?? 'rgba(255, 87, 34, 0.2)',\r\n strokeColor: input.strokeColor ?? '#FF5722',\r\n strokeWidth: input.strokeWidth ?? 2,\r\n opacity: input.opacity ?? 0.6,\r\n feetPerCell: input.feetPerCell,\r\n radiusFeet: input.radiusFeet,\r\n };\r\n}\r\n","export interface ActiveFormats {\r\n bold: boolean;\r\n italic: boolean;\r\n underline: boolean;\r\n strikethrough: boolean;\r\n}\r\n\r\nexport function toggleBold(): void {\r\n document.execCommand('bold');\r\n}\r\n\r\nexport function toggleItalic(): void {\r\n document.execCommand('italic');\r\n}\r\n\r\nexport function toggleUnderline(): void {\r\n document.execCommand('underline');\r\n}\r\n\r\nexport function toggleStrikethrough(): void {\r\n document.execCommand('strikeThrough');\r\n}\r\n\r\nexport function setFontSize(size: number): void {\r\n const sel = window.getSelection();\r\n if (!sel || sel.rangeCount === 0) return;\r\n\r\n const range = sel.getRangeAt(0);\r\n if (range.collapsed) return;\r\n\r\n const span = document.createElement('span');\r\n span.style.fontSize = `${size}px`;\r\n try {\r\n range.surroundContents(span);\r\n } catch {\r\n span.appendChild(range.extractContents());\r\n range.insertNode(span);\r\n }\r\n}\r\n\r\nexport function getActiveFormats(): ActiveFormats {\r\n const query = (cmd: string): boolean => {\r\n try {\r\n return document.queryCommandState(cmd);\r\n } catch {\r\n return false;\r\n }\r\n };\r\n\r\n return {\r\n bold: query('bold'),\r\n italic: query('italic'),\r\n underline: query('underline'),\r\n strikethrough: query('strikeThrough'),\r\n };\r\n}\r\n","import { DEFAULT_NOTE_FONT_SIZE } from './element-factory';\r\nimport { setFontSize, getActiveFormats } from './note-formatting';\r\n\r\nconst TOOLBAR_HEIGHT = 52;\r\nconst TOOLBAR_GAP = 4;\r\n\r\ninterface FormatButton {\r\n label: string;\r\n format: string;\r\n command: string;\r\n}\r\n\r\nconst FORMAT_BUTTONS: FormatButton[] = [\r\n { label: 'B', format: 'bold', command: 'bold' },\r\n { label: 'I', format: 'italic', command: 'italic' },\r\n { label: 'U', format: 'underline', command: 'underline' },\r\n { label: 'S', format: 'strikethrough', command: 'strikeThrough' },\r\n];\r\n\r\nexport interface FontSizePreset {\r\n label: string;\r\n size: number;\r\n}\r\n\r\nexport const DEFAULT_FONT_SIZE_PRESETS: FontSizePreset[] = [\r\n { label: 'Small', size: 14 },\r\n { label: 'Normal', size: 18 },\r\n { label: 'Large', size: 24 },\r\n { label: 'Heading', size: 32 },\r\n];\r\n\r\nexport class NoteToolbar {\r\n private el: HTMLDivElement | null = null;\r\n private anchor: HTMLElement | null = null;\r\n private selectionListener: (() => void) | null = null;\r\n private readonly fontSizePresets: FontSizePreset[];\r\n\r\n constructor(fontSizePresets?: FontSizePreset[]) {\r\n this.fontSizePresets = fontSizePresets ?? DEFAULT_FONT_SIZE_PRESETS;\r\n }\r\n\r\n show(anchor: HTMLElement): void {\r\n this.hide();\r\n this.anchor = anchor;\r\n this.el = this.createToolbarElement();\r\n document.body.appendChild(this.el);\r\n this.positionToolbar(anchor);\r\n this.selectionListener = () => this.updateActiveStates();\r\n document.addEventListener('selectionchange', this.selectionListener);\r\n }\r\n\r\n hide(): void {\r\n if (this.selectionListener) {\r\n document.removeEventListener('selectionchange', this.selectionListener);\r\n this.selectionListener = null;\r\n }\r\n if (this.el) {\r\n this.el.remove();\r\n this.el = null;\r\n }\r\n this.anchor = null;\r\n }\r\n\r\n getElement(): HTMLDivElement | null {\r\n return this.el;\r\n }\r\n\r\n updatePosition(anchor: HTMLElement): void {\r\n if (this.el) {\r\n this.positionToolbar(anchor);\r\n }\r\n }\r\n\r\n private createToolbarElement(): HTMLDivElement {\r\n const toolbar = document.createElement('div');\r\n toolbar.dataset['noteToolbar'] = '';\r\n Object.assign(toolbar.style, {\r\n position: 'fixed',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '2px',\r\n padding: '2px 4px',\r\n background: '#fff',\r\n border: '1px solid #ccc',\r\n borderRadius: '4px',\r\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\r\n zIndex: '10000',\r\n height: `${TOOLBAR_HEIGHT}px`,\r\n userSelect: 'none',\r\n });\r\n\r\n for (const btn of FORMAT_BUTTONS) {\r\n toolbar.appendChild(this.createFormatButton(btn));\r\n }\r\n\r\n toolbar.appendChild(this.createFontSizeSelect());\r\n\r\n return toolbar;\r\n }\r\n\r\n private createFormatButton(config: FormatButton): HTMLButtonElement {\r\n const btn = document.createElement('button');\r\n btn.dataset['format'] = config.format;\r\n btn.textContent = config.label;\r\n Object.assign(btn.style, {\r\n border: '1px solid transparent',\r\n borderRadius: '3px',\r\n background: 'none',\r\n cursor: 'pointer',\r\n padding: '2px 6px',\r\n fontSize: '13px',\r\n fontWeight: config.format === 'bold' ? 'bold' : 'normal',\r\n fontStyle: config.format === 'italic' ? 'italic' : 'normal',\r\n textDecoration:\r\n config.format === 'underline'\r\n ? 'underline'\r\n : config.format === 'strikethrough'\r\n ? 'line-through'\r\n : 'none',\r\n minWidth: '44px',\r\n height: '44px',\r\n lineHeight: '44px',\r\n });\r\n\r\n btn.addEventListener('pointerdown', (e) => {\r\n e.preventDefault();\r\n document.execCommand(config.command);\r\n this.updateActiveStates();\r\n });\r\n\r\n return btn;\r\n }\r\n\r\n private createFontSizeSelect(): HTMLSelectElement {\r\n const select = document.createElement('select');\r\n Object.assign(select.style, {\r\n border: '1px solid #ccc',\r\n borderRadius: '3px',\r\n background: '#fff',\r\n cursor: 'pointer',\r\n padding: '2px',\r\n fontSize: '12px',\r\n height: '44px',\r\n marginLeft: '4px',\r\n });\r\n\r\n for (const preset of this.fontSizePresets) {\r\n const option = document.createElement('option');\r\n option.value = String(preset.size);\r\n option.textContent = preset.label;\r\n select.appendChild(option);\r\n }\r\n\r\n select.value = String(DEFAULT_NOTE_FONT_SIZE);\r\n\r\n select.addEventListener('pointerdown', (e) => {\r\n e.stopPropagation();\r\n });\r\n\r\n select.addEventListener('change', () => {\r\n setFontSize(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 positionToolbar(anchor: HTMLElement): void {\r\n if (!this.el) return;\r\n\r\n const rect = anchor.getBoundingClientRect();\r\n const toolbarWidth = this.el.offsetWidth || 200;\r\n\r\n let top = rect.top - TOOLBAR_HEIGHT - TOOLBAR_GAP;\r\n if (top < 0) {\r\n top = rect.bottom + TOOLBAR_GAP;\r\n }\r\n\r\n let left = rect.left + (rect.width - toolbarWidth) / 2;\r\n left = Math.max(4, left);\r\n\r\n Object.assign(this.el.style, {\r\n top: `${top}px`,\r\n left: `${left}px`,\r\n });\r\n }\r\n\r\n private updateActiveStates(): void {\r\n if (!this.el) return;\r\n\r\n const active = getActiveFormats();\r\n for (const config of FORMAT_BUTTONS) {\r\n const btn = this.el.querySelector(`[data-format=\"${config.format}\"]`) as HTMLElement | null;\r\n if (!btn) continue;\r\n\r\n const isActive = active[config.format as keyof typeof active] ?? false;\r\n btn.style.background = isActive ? '#e0e0e0' : 'none';\r\n btn.style.borderColor = isActive ? '#bbb' : 'transparent';\r\n }\r\n }\r\n}\r\n","import type { ElementStore } from './element-store';\r\nimport { NoteToolbar } from './note-toolbar';\r\nimport type { FontSizePreset } from './note-toolbar';\r\nimport { sanitizeNoteHtml } from './note-sanitizer';\r\nimport { toggleBold, toggleItalic, toggleUnderline } from './note-formatting';\r\n\r\nconst FORMAT_SHORTCUTS: Record<string, () => void> = {\r\n b: toggleBold,\r\n i: toggleItalic,\r\n u: toggleUnderline,\r\n};\r\n\r\nexport interface NoteEditorOptions {\r\n fontSizePresets?: FontSizePreset[];\r\n toolbar?: boolean;\r\n placeholder?: string;\r\n}\r\n\r\nfunction ensureEditorStyles(): void {\r\n if (document.querySelector('style[data-fieldnotes-editor]')) return;\r\n const style = document.createElement('style');\r\n style.setAttribute('data-fieldnotes-editor', '');\r\n style.textContent = `[data-fn-placeholder][data-fn-empty='true']::before {\r\n content: attr(data-fn-placeholder);\r\n color: #9e9e9e;\r\n position: absolute;\r\n pointer-events: none;\r\n}`;\r\n document.head.appendChild(style);\r\n}\r\n\r\nfunction isNodeEmpty(node: HTMLElement): boolean {\r\n const text = node.textContent ?? '';\r\n return text.replace(/\\u00a0/g, ' ').trim().length === 0;\r\n}\r\n\r\nexport class NoteEditor {\r\n private editingId: string | null = null;\r\n private editingNode: HTMLDivElement | null = null;\r\n private blurHandler: ((e: FocusEvent) => void) | null = null;\r\n private keyHandler: ((e: KeyboardEvent) => void) | null = null;\r\n private pointerHandler: ((e: PointerEvent) => void) | null = null;\r\n private inputHandler: (() => void) | null = null;\r\n private pendingEditId: string | null = null;\r\n private onStopCallback: ((elementId: string) => void) | null = null;\r\n private beginHistory: (() => void) | null = null;\r\n private commitHistory: (() => void) | null = null;\r\n private toolbar: NoteToolbar | null;\r\n private readonly placeholder: string;\r\n\r\n constructor(options?: NoteEditorOptions) {\r\n this.toolbar = options?.toolbar === false ? null : new NoteToolbar(options?.fontSizePresets);\r\n this.placeholder = options?.placeholder ?? 'Type…';\r\n }\r\n\r\n get isEditing(): boolean {\r\n return this.editingId !== null;\r\n }\r\n\r\n get editingElementId(): string | null {\r\n return this.editingId;\r\n }\r\n\r\n setOnStop(callback: (elementId: string) => void): void {\r\n this.onStopCallback = callback;\r\n }\r\n\r\n setHistoryHooks(begin: () => void, commit: () => void): void {\r\n this.beginHistory = begin;\r\n this.commitHistory = commit;\r\n }\r\n\r\n startEditing(node: HTMLDivElement, elementId: string, store: ElementStore): void {\r\n if (this.editingId === elementId) return;\r\n\r\n if (this.editingId) {\r\n this.stopEditing(store);\r\n }\r\n\r\n this.pendingEditId = elementId;\r\n\r\n requestAnimationFrame(() => {\r\n if (this.pendingEditId !== elementId) return;\r\n this.pendingEditId = null;\r\n this.activateEditing(node, elementId, store);\r\n });\r\n }\r\n\r\n stopEditing(store: ElementStore): void {\r\n this.pendingEditId = null;\r\n\r\n if (!this.editingId || !this.editingNode) return;\r\n\r\n if (this.blurHandler) {\r\n this.editingNode.removeEventListener('blur', this.blurHandler);\r\n }\r\n if (this.keyHandler) {\r\n this.editingNode.removeEventListener('keydown', this.keyHandler);\r\n }\r\n if (this.pointerHandler) {\r\n this.editingNode.removeEventListener('pointerdown', this.pointerHandler);\r\n }\r\n if (this.inputHandler) {\r\n this.editingNode.removeEventListener('input', this.inputHandler);\r\n }\r\n this.editingNode.removeAttribute('data-fn-placeholder');\r\n this.editingNode.removeAttribute('data-fn-empty');\r\n\r\n const text = sanitizeNoteHtml(this.editingNode.innerHTML);\r\n const current = store.getById(this.editingId);\r\n const textChanged =\r\n !!current && (current.type === 'note' || current.type === 'text') && current.text !== text;\r\n\r\n this.editingNode.contentEditable = 'false';\r\n Object.assign(this.editingNode.style, {\r\n userSelect: 'none',\r\n cursor: 'default',\r\n });\r\n\r\n this.toolbar?.hide();\r\n\r\n // One history transaction spans the text write and the onStop height-fit/cleanup,\r\n // so a single note/text edit collapses to one undo step (both touch the same element).\r\n this.beginHistory?.();\r\n if (textChanged) {\r\n store.update(this.editingId, { text });\r\n }\r\n if (this.editingId && this.onStopCallback) {\r\n this.onStopCallback(this.editingId);\r\n }\r\n this.commitHistory?.();\r\n\r\n this.editingId = null;\r\n this.editingNode = null;\r\n this.blurHandler = null;\r\n this.keyHandler = null;\r\n this.pointerHandler = null;\r\n this.inputHandler = null;\r\n }\r\n\r\n destroy(store: ElementStore): void {\r\n this.pendingEditId = null;\r\n if (this.isEditing) {\r\n this.stopEditing(store);\r\n }\r\n }\r\n\r\n updateToolbarPosition(): void {\r\n if (this.editingNode) {\r\n this.toolbar?.updatePosition(this.editingNode);\r\n }\r\n }\r\n\r\n private activateEditing(node: HTMLDivElement, elementId: string, store: ElementStore): void {\r\n this.editingId = elementId;\r\n this.editingNode = node;\r\n\r\n node.contentEditable = 'true';\r\n Object.assign(node.style, {\r\n userSelect: 'text',\r\n cursor: 'text',\r\n outline: 'none',\r\n });\r\n node.focus();\r\n\r\n const selection = window.getSelection?.();\r\n if (selection) {\r\n const range = document.createRange();\r\n range.selectNodeContents(node);\r\n range.collapse(false);\r\n selection.removeAllRanges();\r\n selection.addRange(range);\r\n }\r\n\r\n ensureEditorStyles();\r\n node.setAttribute('data-fn-placeholder', this.placeholder);\r\n node.setAttribute('data-fn-empty', String(isNodeEmpty(node)));\r\n this.inputHandler = () => {\r\n node.setAttribute('data-fn-empty', String(isNodeEmpty(node)));\r\n };\r\n node.addEventListener('input', this.inputHandler);\r\n\r\n this.toolbar?.show(node);\r\n\r\n this.blurHandler = (e: FocusEvent) => {\r\n const related = e.relatedTarget as Node | null;\r\n if (related && this.toolbar?.getElement()?.contains(related)) return;\r\n this.stopEditing(store);\r\n };\r\n this.keyHandler = (e: KeyboardEvent) => {\r\n if ((e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) {\r\n const action = FORMAT_SHORTCUTS[e.key.toLowerCase()];\r\n if (action) {\r\n e.preventDefault();\r\n action();\r\n return;\r\n }\r\n }\r\n if (e.key === 'Escape') {\r\n node.blur();\r\n }\r\n e.stopPropagation();\r\n };\r\n this.pointerHandler = (e: PointerEvent) => {\r\n e.stopPropagation();\r\n };\r\n\r\n node.addEventListener('blur', this.blurHandler);\r\n node.addEventListener('keydown', this.keyHandler);\r\n node.addEventListener('pointerdown', this.pointerHandler);\r\n }\r\n}\r\n","import type { Tool, ToolContext, PointerState } from './types';\r\n\r\nexport class ToolManager {\r\n private tools = new Map<string, Tool>();\r\n private current: Tool | null = null;\r\n private changeListeners = new Set<(name: string) => void>();\r\n\r\n get activeTool(): Tool | null {\r\n return this.current;\r\n }\r\n\r\n get toolNames(): string[] {\r\n return [...this.tools.keys()];\r\n }\r\n\r\n register(tool: Tool): void {\r\n this.tools.set(tool.name, tool);\r\n }\r\n\r\n getTool<T extends Tool = Tool>(name: string): T | undefined {\r\n return this.tools.get(name) as T | undefined;\r\n }\r\n\r\n setTool(name: string, ctx: ToolContext): void {\r\n const tool = this.tools.get(name);\r\n if (!tool) return;\r\n\r\n this.current?.onDeactivate?.(ctx);\r\n this.current = tool;\r\n this.current.onActivate?.(ctx);\r\n this.changeListeners.forEach((fn) => fn(name));\r\n }\r\n\r\n handlePointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.current?.onPointerDown(state, ctx);\r\n }\r\n\r\n handlePointerMove(state: PointerState, ctx: ToolContext): void {\r\n this.current?.onPointerMove(state, ctx);\r\n }\r\n\r\n handlePointerUp(state: PointerState, ctx: ToolContext): void {\r\n this.current?.onPointerUp(state, ctx);\r\n }\r\n\r\n onChange(listener: (name: string) => void): () => void {\r\n this.changeListeners.add(listener);\r\n return () => this.changeListeners.delete(listener);\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\nimport type { Command } from './types';\n\nexport interface HistoryStackOptions {\n maxSize?: number;\n}\n\nconst DEFAULT_MAX_SIZE = 100;\n\nexport class HistoryStack {\n private undoStack: Command[] = [];\n private redoStack: Command[] = [];\n private readonly maxSize: number;\n private changeListeners = new Set<() => void>();\n\n constructor(options: HistoryStackOptions = {}) {\n this.maxSize = options.maxSize ?? DEFAULT_MAX_SIZE;\n }\n\n get canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n get canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n get undoCount(): number {\n return this.undoStack.length;\n }\n\n get redoCount(): number {\n return this.redoStack.length;\n }\n\n push(command: Command): void {\n this.undoStack.push(command);\n this.redoStack = [];\n\n if (this.undoStack.length > this.maxSize) {\n this.undoStack.shift();\n }\n\n this.notifyChange();\n }\n\n undo(store: ElementStore): boolean {\n const command = this.undoStack.pop();\n if (!command) return false;\n\n command.undo(store);\n this.redoStack.push(command);\n this.notifyChange();\n return true;\n }\n\n redo(store: ElementStore): boolean {\n const command = this.redoStack.pop();\n if (!command) return false;\n\n command.execute(store);\n this.undoStack.push(command);\n this.notifyChange();\n return true;\n }\n\n clear(): void {\n this.undoStack = [];\n this.redoStack = [];\n this.notifyChange();\n }\n\n onChange(listener: () => void): () => void {\n this.changeListeners.add(listener);\n return () => this.changeListeners.delete(listener);\n }\n\n private notifyChange(): void {\n this.changeListeners.forEach((fn) => fn());\n }\n}\n","import type { CanvasElement } from '../elements/types';\nimport type { ElementStore } from '../elements/element-store';\nimport type { Command } from './types';\n\nexport class AddElementCommand implements Command {\n private readonly element: CanvasElement;\n\n constructor(element: CanvasElement) {\n this.element = { ...element };\n }\n\n execute(store: ElementStore): void {\n store.add(this.element);\n }\n\n undo(store: ElementStore): void {\n store.remove(this.element.id);\n }\n}\n\nexport class RemoveElementCommand implements Command {\n private readonly element: CanvasElement;\n\n constructor(element: CanvasElement) {\n this.element = { ...element };\n }\n\n execute(store: ElementStore): void {\n store.remove(this.element.id);\n }\n\n undo(store: ElementStore): void {\n store.add(this.element);\n }\n}\n\nexport class UpdateElementCommand implements Command {\n constructor(\n private readonly id: string,\n private readonly previous: CanvasElement,\n private readonly current: CanvasElement,\n ) {}\n\n execute(store: ElementStore): void {\n store.update(this.id, { ...this.current });\n }\n\n undo(store: ElementStore): void {\n store.update(this.id, { ...this.previous });\n }\n}\n\nexport class BatchCommand implements Command {\n readonly commands: readonly Command[];\n\n constructor(commands: Command[]) {\n this.commands = [...commands];\n }\n\n execute(store: ElementStore): void {\n for (const cmd of this.commands) {\n cmd.execute(store);\n }\n }\n\n undo(store: ElementStore): void {\n for (let i = this.commands.length - 1; i >= 0; i--) {\n this.commands[i]?.undo(store);\n }\n }\n}\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { Command } from './types';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport type { Layer } from '../layers/types';\r\n\r\nexport class CreateLayerCommand implements Command {\r\n constructor(\r\n private readonly manager: LayerManager,\r\n private readonly layer: Layer,\r\n ) {}\r\n\r\n execute(_store: ElementStore): void {\r\n this.manager.addLayerDirect(this.layer);\r\n }\r\n\r\n undo(_store: ElementStore): void {\r\n this.manager.removeLayerDirect(this.layer.id);\r\n }\r\n}\r\n\r\nexport class RemoveLayerCommand implements Command {\r\n constructor(\r\n private readonly manager: LayerManager,\r\n private readonly layer: Layer,\r\n ) {}\r\n\r\n execute(_store: ElementStore): void {\r\n this.manager.removeLayerDirect(this.layer.id);\r\n }\r\n\r\n undo(_store: ElementStore): void {\r\n this.manager.addLayerDirect(this.layer);\r\n }\r\n}\r\n\r\nexport class UpdateLayerCommand implements Command {\r\n constructor(\r\n private readonly manager: LayerManager,\r\n private readonly layerId: string,\r\n private readonly previous: Layer,\r\n private readonly current: Layer,\r\n ) {}\r\n\r\n execute(_store: ElementStore): void {\r\n this.manager.updateLayerDirect(this.layerId, { ...this.current });\r\n }\r\n\r\n undo(_store: ElementStore): void {\r\n this.manager.updateLayerDirect(this.layerId, { ...this.previous });\r\n }\r\n}\r\n","import type { ElementStore } from '../elements/element-store';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport type { Command } from './types';\r\nimport type { HistoryStack } from './history-stack';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport type { Layer } from '../layers/types';\r\nimport {\r\n AddElementCommand,\r\n RemoveElementCommand,\r\n UpdateElementCommand,\r\n BatchCommand,\r\n} from './commands';\r\nimport { CreateLayerCommand, RemoveLayerCommand, UpdateLayerCommand } from './layer-commands';\r\n\r\nexport class HistoryRecorder {\r\n private recording = true;\r\n private transaction: Command[] | null = null;\r\n private generation = 0;\r\n private updateSnapshots = new Map<string, CanvasElement>();\r\n private unsubscribers: (() => void)[];\r\n\r\n constructor(\r\n private readonly store: ElementStore,\r\n private readonly stack: HistoryStack,\r\n private readonly layerManager?: LayerManager,\r\n ) {\r\n this.unsubscribers = [\r\n store.on('add', (el) => this.onAdd(el)),\r\n store.on('remove', (el) => this.onRemove(el)),\r\n store.on('update', ({ previous, current }) => this.onUpdate(previous, current)),\r\n ];\r\n\r\n if (layerManager) {\r\n this.unsubscribers.push(\r\n layerManager.on('create', (layer) => this.onLayerCreate(layer)),\r\n layerManager.on('remove', (layer) => this.onLayerRemove(layer)),\r\n layerManager.on('update', ({ previous, current }) => this.onLayerUpdate(previous, current)),\r\n );\r\n }\r\n }\r\n\r\n pause(): void {\r\n this.recording = false;\r\n }\r\n\r\n resume(): void {\r\n this.recording = true;\r\n }\r\n\r\n begin(): void {\r\n if (this.transaction !== null) {\r\n this.commit();\r\n }\r\n this.transaction = [];\r\n this.updateSnapshots.clear();\r\n this.generation += 1;\r\n }\r\n\r\n get currentTransactionId(): number | null {\r\n return this.transaction !== null ? this.generation : null;\r\n }\r\n\r\n commit(): void {\r\n if (!this.transaction) return;\r\n\r\n const finalCommands = this.flushUpdateSnapshots();\r\n const all = [...this.transaction, ...finalCommands];\r\n this.transaction = null;\r\n this.updateSnapshots.clear();\r\n\r\n if (all.length === 0) return;\r\n const first = all[0];\r\n this.stack.push(all.length === 1 && first ? first : new BatchCommand(all));\r\n }\r\n\r\n rollback(): void {\r\n this.transaction = null;\r\n this.updateSnapshots.clear();\r\n }\r\n\r\n destroy(): void {\r\n this.unsubscribers.forEach((fn) => fn());\r\n }\r\n\r\n private record(command: Command): void {\r\n if (this.transaction) {\r\n this.transaction.push(command);\r\n } else {\r\n this.stack.push(command);\r\n }\r\n }\r\n\r\n private onAdd(element: CanvasElement): void {\r\n if (!this.recording) return;\r\n this.record(new AddElementCommand(element));\r\n }\r\n\r\n private onRemove(element: CanvasElement): void {\r\n if (!this.recording) return;\r\n\r\n if (this.transaction && this.updateSnapshots.has(element.id)) {\r\n this.updateSnapshots.delete(element.id);\r\n }\r\n\r\n this.record(new RemoveElementCommand(element));\r\n }\r\n\r\n private onUpdate(previous: CanvasElement, current: CanvasElement): void {\r\n if (!this.recording) return;\r\n\r\n if (this.transaction) {\r\n if (!this.updateSnapshots.has(current.id)) {\r\n this.updateSnapshots.set(current.id, { ...previous });\r\n }\r\n } else {\r\n this.stack.push(new UpdateElementCommand(current.id, previous, current));\r\n }\r\n }\r\n\r\n private onLayerCreate(layer: Layer): void {\r\n if (!this.recording) return;\r\n if (!this.layerManager) return;\r\n this.record(new CreateLayerCommand(this.layerManager, layer));\r\n }\r\n\r\n private onLayerRemove(layer: Layer): void {\r\n if (!this.recording) return;\r\n if (!this.layerManager) return;\r\n this.record(new RemoveLayerCommand(this.layerManager, layer));\r\n }\r\n\r\n private onLayerUpdate(previous: Layer, current: Layer): void {\r\n if (!this.recording) return;\r\n if (!this.layerManager) return;\r\n this.record(new UpdateLayerCommand(this.layerManager, current.id, previous, current));\r\n }\r\n\r\n private flushUpdateSnapshots(): Command[] {\r\n const commands: Command[] = [];\r\n for (const [id, previous] of this.updateSnapshots) {\r\n const current = this.store.getById(id);\r\n if (current) {\r\n commands.push(new UpdateElementCommand(id, previous, current));\r\n }\r\n }\r\n return commands;\r\n }\r\n}\r\n","import type { NoteElement } from '../elements/types';\r\nimport { DEFAULT_NOTE_FONT_SIZE } from '../elements/element-factory';\r\nimport { parseStyledRuns } from '../elements/note-sanitizer';\r\nimport type { StyledRun } from '../elements/note-sanitizer';\r\n\r\nexport function renderNoteOnCanvas(ctx: CanvasRenderingContext2D, note: NoteElement): void {\r\n const { x, y } = note.position;\r\n const { w, h } = note.size;\r\n const r = 4;\r\n const pad = 8;\r\n const baseFontSize = note.fontSize ?? DEFAULT_NOTE_FONT_SIZE;\r\n\r\n ctx.save();\r\n ctx.fillStyle = note.backgroundColor;\r\n ctx.beginPath();\r\n ctx.moveTo(x + r, y);\r\n ctx.lineTo(x + w - r, y);\r\n ctx.arcTo(x + w, y, x + w, y + r, r);\r\n ctx.lineTo(x + w, y + h - r);\r\n ctx.arcTo(x + w, y + h, x + w - r, y + h, r);\r\n ctx.lineTo(x + r, y + h);\r\n ctx.arcTo(x, y + h, x, y + h - r, r);\r\n ctx.lineTo(x, y + r);\r\n ctx.arcTo(x, y, x + r, y, r);\r\n ctx.closePath();\r\n ctx.fill();\r\n\r\n if (note.text) {\r\n ctx.fillStyle = note.textColor;\r\n const runs = parseStyledRuns(note.text, baseFontSize);\r\n renderStyledRuns(ctx, runs, x + pad, y + pad, w - pad * 2);\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nfunction buildFontString(run: StyledRun): string {\r\n const style = run.italic ? 'italic' : 'normal';\r\n const weight = run.bold ? 'bold' : 'normal';\r\n return `${style} ${weight} ${run.fontSize}px system-ui, sans-serif`;\r\n}\r\n\r\nfunction renderStyledRuns(\r\n ctx: CanvasRenderingContext2D,\r\n runs: StyledRun[],\r\n startX: number,\r\n startY: number,\r\n maxWidth: number,\r\n): void {\r\n ctx.textBaseline = 'top';\r\n let cursorX = startX;\r\n let cursorY = startY;\r\n let lineHeight = 0;\r\n\r\n for (const run of runs) {\r\n ctx.font = buildFontString(run);\r\n const runLineHeight = run.fontSize * 1.3;\r\n lineHeight = Math.max(lineHeight, runLineHeight);\r\n\r\n const words = run.text.split(/(\\n| )/);\r\n for (const word of words) {\r\n if (word === '\\n') {\r\n cursorX = startX;\r\n cursorY += lineHeight;\r\n lineHeight = runLineHeight;\r\n continue;\r\n }\r\n if (word === ' ') {\r\n const spaceWidth = ctx.measureText(' ').width;\r\n if (cursorX + spaceWidth > startX + maxWidth && cursorX > startX) {\r\n cursorX = startX;\r\n cursorY += lineHeight;\r\n lineHeight = runLineHeight;\r\n } else {\r\n cursorX += spaceWidth;\r\n }\r\n continue;\r\n }\r\n if (!word) continue;\r\n\r\n const metrics = ctx.measureText(word);\r\n if (cursorX + metrics.width > startX + maxWidth && cursorX > startX) {\r\n cursorX = startX;\r\n cursorY += lineHeight;\r\n lineHeight = runLineHeight;\r\n }\r\n\r\n ctx.fillText(word, cursorX, cursorY);\r\n\r\n if (run.underline) {\r\n const underY = cursorY + run.fontSize + 1;\r\n ctx.fillRect(cursorX, underY, metrics.width, 1);\r\n }\r\n\r\n if (run.strikethrough) {\r\n const strikeY = cursorY + run.fontSize * 0.55;\r\n ctx.fillRect(cursorX, strikeY, metrics.width, 1);\r\n }\r\n\r\n cursorX += metrics.width;\r\n }\r\n }\r\n}\r\n","import type { CanvasElement, TextElement, GridElement } from '../elements/types';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport { ElementRenderer } from '../elements/element-renderer';\r\nimport { getArrowBounds } from '../elements/arrow-geometry';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { renderSquareGrid, renderHexGrid } from '../elements/grid-renderer';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport { renderNoteOnCanvas } from './note-canvas-renderer';\r\n\r\nexport interface ExportImageOptions {\r\n scale?: number;\r\n padding?: number;\r\n background?: string;\r\n filter?: (element: CanvasElement) => boolean;\r\n}\r\n\r\ninterface Rect {\r\n x: number;\r\n y: number;\r\n w: number;\r\n h: number;\r\n}\r\n\r\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 return getStrokeBounds(el);\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 { x: el.position.x, y: el.position.y, w: el.size.w, h: el.size.h };\r\n }\r\n return null;\r\n default:\r\n return null;\r\n }\r\n}\r\n\r\nfunction computeBounds(\r\n elements: CanvasElement[],\r\n padding: number,\r\n): { x: number; y: number; w: number; h: number } | null {\r\n let minX = Infinity;\r\n let minY = Infinity;\r\n let maxX = -Infinity;\r\n let maxY = -Infinity;\r\n let found = false;\r\n\r\n for (const el of elements) {\r\n const rect = getElementRect(el);\r\n if (!rect) continue;\r\n found = true;\r\n minX = Math.min(minX, rect.x);\r\n minY = Math.min(minY, rect.y);\r\n maxX = Math.max(maxX, rect.x + rect.w);\r\n maxY = Math.max(maxY, rect.y + rect.h);\r\n }\r\n\r\n if (!found) return null;\r\n\r\n return {\r\n x: minX - padding,\r\n y: minY - padding,\r\n w: maxX - minX + padding * 2,\r\n h: maxY - minY + padding * 2,\r\n };\r\n}\r\n\r\nfunction renderTextOnCanvas(ctx: CanvasRenderingContext2D, text: TextElement): void {\r\n if (!text.text) return;\r\n\r\n ctx.save();\r\n ctx.fillStyle = text.color;\r\n ctx.font = `${text.fontSize}px system-ui, sans-serif`;\r\n ctx.textBaseline = 'top';\r\n ctx.textAlign = text.textAlign;\r\n\r\n const pad = 2;\r\n let textX = text.position.x + pad;\r\n if (text.textAlign === 'center') {\r\n textX = text.position.x + text.size.w / 2;\r\n } else if (text.textAlign === 'right') {\r\n textX = text.position.x + text.size.w - pad;\r\n }\r\n\r\n const lineHeight = text.fontSize * 1.4;\r\n const lines = text.text.split('\\n');\r\n for (let i = 0; i < lines.length; i++) {\r\n const line = lines[i];\r\n if (line !== undefined) {\r\n ctx.fillText(line, textX, text.position.y + pad + i * lineHeight);\r\n }\r\n }\r\n\r\n ctx.restore();\r\n}\r\n\r\nfunction renderGridForBounds(\r\n ctx: CanvasRenderingContext2D,\r\n grid: GridElement,\r\n bounds: { x: number; y: number; w: number; h: number },\r\n): void {\r\n const visibleBounds = {\r\n minX: bounds.x,\r\n minY: bounds.y,\r\n maxX: bounds.x + bounds.w,\r\n maxY: bounds.y + bounds.h,\r\n };\r\n\r\n if (grid.gridType === 'hex') {\r\n renderHexGrid(\r\n ctx,\r\n visibleBounds,\r\n grid.cellSize,\r\n grid.hexOrientation,\r\n grid.strokeColor,\r\n grid.strokeWidth,\r\n grid.opacity,\r\n );\r\n } else {\r\n renderSquareGrid(\r\n ctx,\r\n visibleBounds,\r\n grid.cellSize,\r\n grid.strokeColor,\r\n grid.strokeWidth,\r\n grid.opacity,\r\n );\r\n }\r\n}\r\n\r\nfunction loadImages(elements: CanvasElement[]): Promise<Map<string, HTMLImageElement>> {\r\n const imageElements = elements.filter(\r\n (el): el is CanvasElement & { src: string } => el.type === 'image' && 'src' in el,\r\n );\r\n\r\n const cache = new Map<string, HTMLImageElement>();\r\n if (imageElements.length === 0) return Promise.resolve(cache);\r\n\r\n return new Promise((resolve) => {\r\n let remaining = imageElements.length;\r\n const done = () => {\r\n remaining--;\r\n if (remaining <= 0) resolve(cache);\r\n };\r\n\r\n for (const el of imageElements) {\r\n const img = new Image();\r\n img.crossOrigin = 'anonymous';\r\n img.onload = () => {\r\n cache.set(el.id, img);\r\n done();\r\n };\r\n img.onerror = done;\r\n const sep = el.src.includes('?') ? '&' : '?';\r\n img.src = `${el.src}${sep}_cors=1`;\r\n }\r\n });\r\n}\r\n\r\nexport async function exportImage(\r\n store: ElementStore,\r\n options: ExportImageOptions = {},\r\n layerManager?: LayerManager,\r\n): Promise<Blob | null> {\r\n const scale = options.scale ?? 2;\r\n const padding = options.padding ?? 0;\r\n const background = options.background ?? '#ffffff';\r\n const filter = options.filter;\r\n\r\n const allElements = store.getAll();\r\n let visibleElements = layerManager\r\n ? allElements.filter((el) => layerManager.isLayerVisible(el.layerId))\r\n : allElements;\r\n\r\n if (filter) {\r\n visibleElements = visibleElements.filter(filter);\r\n }\r\n\r\n const bounds = computeBounds(visibleElements, padding);\r\n if (!bounds) return null;\r\n\r\n const imageCache = await loadImages(visibleElements);\r\n\r\n const canvas = document.createElement('canvas');\r\n canvas.width = Math.ceil(bounds.w * scale);\r\n canvas.height = Math.ceil(bounds.h * scale);\r\n\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return null;\r\n\r\n ctx.scale(scale, scale);\r\n ctx.translate(-bounds.x, -bounds.y);\r\n\r\n ctx.fillStyle = background;\r\n ctx.fillRect(bounds.x, bounds.y, bounds.w, bounds.h);\r\n\r\n const renderer = new ElementRenderer();\r\n renderer.setStore(store);\r\n\r\n const grids: GridElement[] = [];\r\n\r\n for (const el of visibleElements) {\r\n if (el.type === 'grid') {\r\n grids.push(el);\r\n continue;\r\n }\r\n\r\n if (el.type === 'note') {\r\n renderNoteOnCanvas(ctx, el);\r\n continue;\r\n }\r\n\r\n if (el.type === 'text') {\r\n renderTextOnCanvas(ctx, el);\r\n continue;\r\n }\r\n\r\n if (el.type === 'html') {\r\n continue;\r\n }\r\n\r\n if (el.type === 'image') {\r\n const img = imageCache.get(el.id);\r\n if (img) {\r\n ctx.drawImage(img, el.position.x, el.position.y, el.size.w, el.size.h);\r\n }\r\n continue;\r\n }\r\n\r\n renderer.renderCanvasElement(ctx, el);\r\n }\r\n\r\n for (const grid of grids) {\r\n renderGridForBounds(ctx, grid, bounds);\r\n }\r\n\r\n return new Promise((resolve) => {\r\n canvas.toBlob((blob) => resolve(blob), 'image/png');\r\n });\r\n}\r\n\r\nexport { computeBounds, getElementRect };\r\n","import { EventBus } from '../core/event-bus';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { Layer } from './types';\r\nimport { createId } from '../elements/create-id';\r\n\r\ninterface LayerManagerEvents {\r\n change: null;\r\n create: Layer;\r\n remove: Layer;\r\n update: { previous: Layer; current: Layer };\r\n}\r\n\r\nexport class LayerManager {\r\n private layers = new Map<string, Layer>();\r\n private _activeLayerId: string;\r\n private bus = new EventBus<LayerManagerEvents>();\r\n\r\n constructor(private readonly store: ElementStore) {\r\n const defaultLayer: Layer = {\r\n id: createId('layer'),\r\n name: 'Layer 1',\r\n visible: true,\r\n locked: false,\r\n order: 0,\r\n opacity: 1.0,\r\n };\r\n this.layers.set(defaultLayer.id, defaultLayer);\r\n this._activeLayerId = defaultLayer.id;\r\n this.syncLayerOrder();\r\n }\r\n\r\n get activeLayer(): Layer {\r\n const layer = this.layers.get(this._activeLayerId);\r\n if (!layer) throw new Error('Active layer not found');\r\n return { ...layer };\r\n }\r\n\r\n get activeLayerId(): string {\r\n return this._activeLayerId;\r\n }\r\n\r\n getLayers(): Layer[] {\r\n return [...this.layers.values()].sort((a, b) => a.order - b.order).map((l) => ({ ...l }));\r\n }\r\n\r\n getLayer(id: string): Layer | undefined {\r\n const layer = this.layers.get(id);\r\n return layer ? { ...layer } : undefined;\r\n }\r\n\r\n isLayerVisible(id: string): boolean {\r\n return this.layers.get(id)?.visible ?? true;\r\n }\r\n\r\n isLayerLocked(id: string): boolean {\r\n return this.layers.get(id)?.locked ?? false;\r\n }\r\n\r\n createLayer(name?: string): Layer {\r\n const maxOrder = Math.max(...[...this.layers.values()].map((l) => l.order), -1);\r\n const autoName = name ?? `Layer ${this.layers.size + 1}`;\r\n const layer: Layer = {\r\n id: createId('layer'),\r\n name: autoName,\r\n visible: true,\r\n locked: false,\r\n order: maxOrder + 1,\r\n opacity: 1.0,\r\n };\r\n this.addLayerDirect(layer);\r\n return { ...layer };\r\n }\r\n\r\n removeLayer(id: string): void {\r\n if (this.layers.size <= 1) {\r\n throw new Error('Cannot remove the last layer');\r\n }\r\n if (this._activeLayerId === id) {\r\n const remaining = [...this.layers.values()]\r\n .filter((l) => l.id !== id)\r\n .sort((a, b) => b.order - a.order);\r\n const fallback = remaining[0];\r\n if (fallback) this._activeLayerId = fallback.id;\r\n }\r\n const elements = this.store.getAll().filter((el) => el.layerId === id);\r\n for (const el of elements) {\r\n this.store.update(el.id, { layerId: this._activeLayerId });\r\n }\r\n this.removeLayerDirect(id);\r\n }\r\n\r\n renameLayer(id: string, name: string): void {\r\n this.updateLayerDirect(id, { name });\r\n }\r\n\r\n reorderLayer(id: string, newOrder: number): void {\r\n if (!this.layers.has(id)) return;\r\n this.updateLayerDirect(id, { order: newOrder });\r\n }\r\n\r\n setLayerVisible(id: string, visible: boolean): boolean {\r\n if (!visible && id === this._activeLayerId) {\r\n const fallback = this.findFallbackLayer(id);\r\n if (!fallback) return false;\r\n this._activeLayerId = fallback.id;\r\n }\r\n this.updateLayerDirect(id, { visible });\r\n return true;\r\n }\r\n\r\n setLayerLocked(id: string, locked: boolean): boolean {\r\n if (locked && id === this._activeLayerId) {\r\n const fallback = this.findFallbackLayer(id);\r\n if (!fallback) return false;\r\n this._activeLayerId = fallback.id;\r\n }\r\n this.updateLayerDirect(id, { locked });\r\n return true;\r\n }\r\n\r\n setLayerOpacity(id: string, opacity: number): void {\r\n if (!this.layers.has(id)) return;\r\n this.updateLayerDirect(id, { opacity: Math.max(0, Math.min(1, opacity)) });\r\n }\r\n\r\n setActiveLayer(id: string): void {\r\n if (!this.layers.has(id)) return;\r\n this._activeLayerId = id;\r\n this.bus.emit('change', null);\r\n }\r\n\r\n moveElementToLayer(elementId: string, layerId: string): void {\r\n if (!this.layers.has(layerId)) return;\r\n this.store.update(elementId, { layerId });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n snapshot(): Layer[] {\r\n return this.getLayers();\r\n }\r\n\r\n loadSnapshot(layers: Layer[]): void {\r\n this.layers.clear();\r\n for (const layer of layers) {\r\n this.layers.set(layer.id, { ...layer });\r\n }\r\n const first = this.getLayers()[0];\r\n if (first) this._activeLayerId = first.id;\r\n this.syncLayerOrder();\r\n this.bus.emit('change', null);\r\n }\r\n\r\n on<K extends keyof LayerManagerEvents>(\r\n event: K,\r\n callback: (data: LayerManagerEvents[K]) => void,\r\n ): () => void {\r\n return this.bus.on(event, callback);\r\n }\r\n\r\n addLayerDirect(layer: Layer): void {\r\n this.layers.set(layer.id, { ...layer });\r\n this.syncLayerOrder();\r\n this.bus.emit('create', { ...layer });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n removeLayerDirect(id: string): void {\r\n const layer = this.layers.get(id);\r\n this.layers.delete(id);\r\n this.syncLayerOrder();\r\n if (layer) this.bus.emit('remove', { ...layer });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n updateLayerDirect(id: string, props: Omit<Partial<Layer>, 'id'>): void {\r\n const layer = this.layers.get(id);\r\n if (!layer) return;\r\n const previous = { ...layer };\r\n Object.assign(layer, props);\r\n if ('order' in props) this.syncLayerOrder();\r\n this.bus.emit('update', { previous, current: { ...layer } });\r\n this.bus.emit('change', null);\r\n }\r\n\r\n private syncLayerOrder(): void {\r\n const order = new Map<string, number>();\r\n for (const layer of this.layers.values()) {\r\n order.set(layer.id, layer.order);\r\n }\r\n this.store.setLayerOrder(order);\r\n }\r\n\r\n private findFallbackLayer(excludeId: string): Layer | undefined {\r\n return [...this.layers.values()]\r\n .filter((l) => l.id !== excludeId && l.visible && !l.locked)\r\n .sort((a, b) => b.order - a.order)[0];\r\n }\r\n}\r\n","export interface InteractModeDeps {\r\n getNode: (id: string) => HTMLDivElement | undefined;\r\n}\r\n\r\nexport class InteractMode {\r\n private interactingElementId: string | null = null;\r\n private readonly getNode: (id: string) => HTMLDivElement | undefined;\r\n\r\n constructor(deps: InteractModeDeps) {\r\n this.getNode = deps.getNode;\r\n }\r\n\r\n startInteracting(id: string): void {\r\n this.stopInteracting();\r\n const node = this.getNode(id);\r\n if (!node) return;\r\n\r\n this.interactingElementId = id;\r\n node.style.pointerEvents = 'auto';\r\n node.addEventListener('pointerdown', this.onNodePointerDown);\r\n\r\n window.addEventListener('keydown', this.onKeyDown);\r\n window.addEventListener('pointerdown', this.onPointerDown);\r\n }\r\n\r\n stopInteracting(): void {\r\n if (!this.interactingElementId) return;\r\n\r\n const node = this.getNode(this.interactingElementId);\r\n if (node) {\r\n node.style.pointerEvents = 'none';\r\n node.removeEventListener('pointerdown', this.onNodePointerDown);\r\n }\r\n\r\n this.interactingElementId = null;\r\n window.removeEventListener('keydown', this.onKeyDown);\r\n window.removeEventListener('pointerdown', this.onPointerDown);\r\n }\r\n\r\n isInteracting(): boolean {\r\n return this.interactingElementId !== null;\r\n }\r\n\r\n destroy(): void {\r\n this.stopInteracting();\r\n }\r\n\r\n private onNodePointerDown = (e: PointerEvent): void => {\r\n e.stopPropagation();\r\n };\r\n\r\n private onKeyDown = (e: KeyboardEvent): void => {\r\n if (e.key === 'Escape') {\r\n this.stopInteracting();\r\n }\r\n };\r\n\r\n private onPointerDown = (e: PointerEvent): void => {\r\n if (!this.interactingElementId) return;\r\n const target = e.target;\r\n if (!(target instanceof Element)) {\r\n this.stopInteracting();\r\n return;\r\n }\r\n\r\n const node = this.getNode(this.interactingElementId);\r\n if (node && !node.contains(target)) {\r\n this.stopInteracting();\r\n }\r\n };\r\n}\r\n","export interface DoubleTapDetectorOptions {\r\n timeout?: number;\r\n maxDistance?: number;\r\n}\r\n\r\nconst DEFAULT_TIMEOUT = 300;\r\nconst DEFAULT_MAX_DISTANCE = 20;\r\n\r\nexport class DoubleTapDetector {\r\n private readonly timeout: number;\r\n private readonly maxDistance: number;\r\n private lastTapTime = 0;\r\n private lastTapX = 0;\r\n private lastTapY = 0;\r\n private hasPendingTap = false;\r\n\r\n constructor(options?: DoubleTapDetectorOptions) {\r\n this.timeout = options?.timeout ?? DEFAULT_TIMEOUT;\r\n this.maxDistance = options?.maxDistance ?? DEFAULT_MAX_DISTANCE;\r\n }\r\n\r\n feed(e: PointerEvent): boolean {\r\n const now = Date.now();\r\n const x = e.clientX;\r\n const y = e.clientY;\r\n\r\n if (this.hasPendingTap) {\r\n const elapsed = now - this.lastTapTime;\r\n const dx = x - this.lastTapX;\r\n const dy = y - this.lastTapY;\r\n const dist = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (elapsed <= this.timeout && dist <= this.maxDistance) {\r\n this.reset();\r\n return true;\r\n }\r\n }\r\n\r\n this.lastTapTime = now;\r\n this.lastTapX = x;\r\n this.lastTapY = y;\r\n this.hasPendingTap = true;\r\n return false;\r\n }\r\n\r\n reset(): void {\r\n this.hasPendingTap = false;\r\n this.lastTapTime = 0;\r\n this.lastTapX = 0;\r\n this.lastTapY = 0;\r\n }\r\n}\r\n","import type { CanvasElement } from '../elements/types';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport { DEFAULT_NOTE_FONT_SIZE } from '../elements/element-factory';\r\nimport { DoubleTapDetector } from './double-tap-detector';\r\nexport interface DomNodeManagerDeps {\r\n domLayer: HTMLDivElement;\r\n onEditRequest: (id: string) => void;\r\n isEditingElement: (id: string) => boolean;\r\n getVersion?: (id: string) => number;\r\n}\r\n\r\nexport class DomNodeManager {\r\n private domNodes = new Map<string, HTMLDivElement>();\r\n private htmlContent = new Map<string, HTMLElement>();\r\n private readonly domLayer: HTMLDivElement;\r\n private readonly onEditRequest: (id: string) => void;\r\n private readonly isEditingElement: (id: string) => boolean;\r\n private readonly getVersion: ((id: string) => number) | null;\r\n private lastSyncedVersion = new Map<string, number>();\r\n private lastSyncedZIndex = new Map<string, number>();\r\n\r\n constructor(deps: DomNodeManagerDeps) {\r\n this.domLayer = deps.domLayer;\r\n this.onEditRequest = deps.onEditRequest;\r\n this.isEditingElement = deps.isEditingElement;\r\n this.getVersion = deps.getVersion ?? null;\r\n }\r\n\r\n getNode(id: string): HTMLDivElement | undefined {\r\n return this.domNodes.get(id);\r\n }\r\n\r\n storeHtmlContent(elementId: string, dom: HTMLElement): void {\r\n this.htmlContent.set(elementId, dom);\r\n }\r\n\r\n hasContent(elementId: string): boolean {\r\n return this.htmlContent.has(elementId);\r\n }\r\n\r\n resetHtmlContent(elementId: string): void {\r\n this.htmlContent.delete(elementId);\r\n this.lastSyncedVersion.delete(elementId);\r\n this.lastSyncedZIndex.delete(elementId);\r\n const node = this.domNodes.get(elementId);\r\n if (!node) return;\r\n while (node.firstChild) {\r\n node.removeChild(node.firstChild);\r\n }\r\n delete node.dataset['initialized'];\r\n }\r\n\r\n syncDomNode(element: CanvasElement, zIndex = 0): void {\r\n let node = this.domNodes.get(element.id);\r\n if (!node) {\r\n node = document.createElement('div');\r\n node.dataset['elementId'] = element.id;\r\n Object.assign(node.style, {\r\n position: 'absolute',\r\n pointerEvents: 'auto',\r\n });\r\n this.domLayer.appendChild(node);\r\n this.domNodes.set(element.id, node);\r\n } else if (this.getVersion) {\r\n const currentVersion = this.getVersion(element.id);\r\n const lastVersion = this.lastSyncedVersion.get(element.id);\r\n const lastZ = this.lastSyncedZIndex.get(element.id);\r\n if (lastVersion === currentVersion && lastZ === zIndex) {\r\n return;\r\n }\r\n }\r\n\r\n if (this.getVersion) {\r\n this.lastSyncedVersion.set(element.id, this.getVersion(element.id));\r\n this.lastSyncedZIndex.set(element.id, zIndex);\r\n }\r\n\r\n const size = 'size' in element ? element.size : null;\r\n Object.assign(node.style, {\r\n display: 'block',\r\n left: `${element.position.x}px`,\r\n top: `${element.position.y}px`,\r\n width: size ? `${size.w}px` : 'auto',\r\n height: size ? `${size.h}px` : 'auto',\r\n zIndex: String(zIndex),\r\n });\r\n\r\n this.renderDomContent(node, element);\r\n }\r\n\r\n hideDomNode(id: string): void {\r\n const node = this.domNodes.get(id);\r\n if (node) node.style.display = 'none';\r\n }\r\n\r\n removeDomNode(id: string): void {\r\n this.htmlContent.delete(id);\r\n this.lastSyncedVersion.delete(id);\r\n this.lastSyncedZIndex.delete(id);\r\n const node = this.domNodes.get(id);\r\n if (node) {\r\n node.remove();\r\n this.domNodes.delete(id);\r\n }\r\n }\r\n\r\n clearDomNodes(): void {\r\n this.domNodes.forEach((node) => node.remove());\r\n this.domNodes.clear();\r\n this.htmlContent.clear();\r\n this.lastSyncedVersion.clear();\r\n this.lastSyncedZIndex.clear();\r\n }\r\n\r\n reattachHtmlContent(store: ElementStore): void {\r\n for (const el of store.getElementsByType('html')) {\r\n if (el.domId) {\r\n const dom = document.getElementById(el.domId);\r\n if (dom) {\r\n this.htmlContent.set(el.id, dom);\r\n }\r\n }\r\n }\r\n }\r\n\r\n private renderDomContent(node: HTMLDivElement, element: CanvasElement): void {\r\n if (element.type === 'note') {\r\n if (!node.dataset['initialized']) {\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n backgroundColor: element.backgroundColor,\r\n color: element.textColor,\r\n padding: '8px',\r\n borderRadius: '4px',\r\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\r\n fontSize: `${element.fontSize ?? DEFAULT_NOTE_FONT_SIZE}px`,\r\n overflow: 'hidden',\r\n cursor: 'default',\r\n userSelect: 'none',\r\n wordWrap: 'break-word',\r\n });\r\n node.innerHTML = element.text || '';\r\n\r\n const detector = new DoubleTapDetector();\r\n node.addEventListener('pointerup', (e) => {\r\n if (detector.feed(e)) {\r\n e.stopPropagation();\r\n const id = node.dataset['elementId'];\r\n if (id) this.onEditRequest(id);\r\n }\r\n });\r\n }\r\n\r\n if (!this.isEditingElement(element.id)) {\r\n const text = element.text || '';\r\n if (node.innerHTML !== text) {\r\n node.innerHTML = text;\r\n }\r\n node.style.backgroundColor = element.backgroundColor;\r\n node.style.color = element.textColor;\r\n node.style.fontSize = `${element.fontSize ?? DEFAULT_NOTE_FONT_SIZE}px`;\r\n }\r\n }\r\n\r\n if (element.type === 'html') {\r\n if (!node.dataset['initialized']) {\r\n const content = this.htmlContent.get(element.id);\r\n if (content) {\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n overflow: 'hidden',\r\n pointerEvents: element.interactive ? 'auto' : 'none',\r\n });\r\n node.appendChild(content);\r\n }\r\n } else {\r\n node.style.pointerEvents = element.interactive ? 'auto' : 'none';\r\n }\r\n }\r\n\r\n if (element.type === 'text') {\r\n if (!node.dataset['initialized']) {\r\n node.dataset['initialized'] = 'true';\r\n Object.assign(node.style, {\r\n padding: '2px',\r\n fontSize: `${element.fontSize}px`,\r\n color: element.color,\r\n textAlign: element.textAlign,\r\n background: 'none',\r\n border: 'none',\r\n boxShadow: 'none',\r\n overflow: 'visible',\r\n cursor: 'default',\r\n userSelect: 'none',\r\n wordWrap: 'break-word',\r\n whiteSpace: 'pre-wrap',\r\n lineHeight: '1.4',\r\n });\r\n node.textContent = element.text || '';\r\n\r\n const detector = new DoubleTapDetector();\r\n node.addEventListener('pointerup', (e) => {\r\n if (detector.feed(e)) {\r\n e.stopPropagation();\r\n const id = node.dataset['elementId'];\r\n if (id) this.onEditRequest(id);\r\n }\r\n });\r\n }\r\n\r\n if (!this.isEditingElement(element.id)) {\r\n if (node.textContent !== element.text) {\r\n node.textContent = element.text || '';\r\n }\r\n Object.assign(node.style, {\r\n fontSize: `${element.fontSize}px`,\r\n color: element.color,\r\n textAlign: element.textAlign,\r\n });\r\n }\r\n }\r\n }\r\n}\r\n","const SAMPLE_SIZE = 60;\r\n\r\nexport interface RenderStatsSnapshot {\r\n fps: number;\r\n avgFrameMs: number;\r\n p95FrameMs: number;\r\n lastFrameMs: number;\r\n lastGridMs: number;\r\n layersMs: number;\r\n backgroundMs: number;\r\n compositeMs: number;\r\n overlayMs: number;\r\n frameCount: number;\r\n}\r\n\r\ninterface FrameBreakdown {\r\n gridMs?: number;\r\n layersMs?: number;\r\n backgroundMs?: number;\r\n compositeMs?: number;\r\n overlayMs?: number;\r\n}\r\n\r\nexport class RenderStats {\r\n private frameTimes: number[] = [];\r\n private frameCount = 0;\r\n private _lastGridMs = 0;\r\n private _lastLayersMs = 0;\r\n private _lastBackgroundMs = 0;\r\n private _lastCompositeMs = 0;\r\n private _lastOverlayMs = 0;\r\n\r\n recordFrame(durationMs: number, breakdown?: FrameBreakdown): void {\r\n this.frameCount++;\r\n this.frameTimes.push(durationMs);\r\n if (this.frameTimes.length > SAMPLE_SIZE) {\r\n this.frameTimes.shift();\r\n }\r\n if (breakdown !== undefined) {\r\n if (breakdown.gridMs !== undefined) this._lastGridMs = breakdown.gridMs;\r\n if (breakdown.layersMs !== undefined) this._lastLayersMs = breakdown.layersMs;\r\n if (breakdown.backgroundMs !== undefined) this._lastBackgroundMs = breakdown.backgroundMs;\r\n if (breakdown.compositeMs !== undefined) this._lastCompositeMs = breakdown.compositeMs;\r\n if (breakdown.overlayMs !== undefined) this._lastOverlayMs = breakdown.overlayMs;\r\n }\r\n }\r\n\r\n getSnapshot(): RenderStatsSnapshot {\r\n const times = this.frameTimes;\r\n if (times.length === 0) {\r\n return {\r\n fps: 0,\r\n avgFrameMs: 0,\r\n p95FrameMs: 0,\r\n lastFrameMs: 0,\r\n lastGridMs: 0,\r\n layersMs: 0,\r\n backgroundMs: 0,\r\n compositeMs: 0,\r\n overlayMs: 0,\r\n frameCount: 0,\r\n };\r\n }\r\n\r\n const avg = times.reduce((a, b) => a + b, 0) / times.length;\r\n const sorted = [...times].sort((a, b) => a - b);\r\n const p95Index = Math.min(Math.floor(sorted.length * 0.95), sorted.length - 1);\r\n const lastFrame = times[times.length - 1] ?? 0;\r\n\r\n return {\r\n fps: avg > 0 ? Math.round(1000 / avg) : 0,\r\n avgFrameMs: Math.round(avg * 100) / 100,\r\n p95FrameMs: Math.round((sorted[p95Index] ?? 0) * 100) / 100,\r\n lastFrameMs: Math.round(lastFrame * 100) / 100,\r\n lastGridMs: Math.round(this._lastGridMs * 100) / 100,\r\n layersMs: Math.round(this._lastLayersMs * 100) / 100,\r\n backgroundMs: Math.round(this._lastBackgroundMs * 100) / 100,\r\n compositeMs: Math.round(this._lastCompositeMs * 100) / 100,\r\n overlayMs: Math.round(this._lastOverlayMs * 100) / 100,\r\n frameCount: this.frameCount,\r\n };\r\n }\r\n\r\n reset(): void {\r\n this.frameTimes = [];\r\n this.frameCount = 0;\r\n }\r\n}\r\n","import type { Camera } from './camera';\r\nimport type { Background } from './background';\r\nimport type { ElementStore } from '../elements/element-store';\r\nimport type { ElementRenderer } from '../elements/element-renderer';\r\nimport type { ToolManager } from '../tools/tool-manager';\r\nimport type { LayerManager } from '../layers/layer-manager';\r\nimport type { DomNodeManager } from './dom-node-manager';\r\nimport type { LayerCache } from './layer-cache';\r\nimport type { MarginViewport } from './margin-viewport';\r\nimport type { Bounds } from '../core/types';\r\nimport type { CanvasElement } from '../elements/types';\r\nimport { getElementBounds, boundsIntersect } from '../elements/element-bounds';\r\nimport { RenderStats } from './render-stats';\r\nimport type { RenderStatsSnapshot } from './render-stats';\r\n\r\nexport interface RenderLoopDeps {\r\n canvasEl: HTMLCanvasElement;\r\n camera: Camera;\r\n background: Background;\r\n store: ElementStore;\r\n renderer: ElementRenderer;\r\n toolManager: ToolManager;\r\n layerManager: LayerManager;\r\n domNodeManager: DomNodeManager;\r\n layerCache: LayerCache;\r\n marginViewport: MarginViewport;\r\n}\r\n\r\nexport class RenderLoop {\r\n private needsRender = false;\r\n private animFrameId = 0;\r\n private readonly canvasEl: HTMLCanvasElement;\r\n private readonly camera: Camera;\r\n private readonly background: Background;\r\n private readonly store: ElementStore;\r\n private readonly renderer: ElementRenderer;\r\n private readonly toolManager: ToolManager;\r\n private readonly layerManager: LayerManager;\r\n private readonly domNodeManager: DomNodeManager;\r\n private readonly layerCache: LayerCache;\r\n private readonly marginViewport: MarginViewport;\r\n private activeDrawingLayerId: string | null = null;\r\n private gridCacheDirty = true; // set on recenter/viewport-change; consumed by the grid block\r\n private readonly stats = new RenderStats();\r\n private layerGroups = new Map<string, CanvasElement[]>();\r\n private gridCacheCanvas: HTMLCanvasElement | null = null;\r\n private gridCacheCtx: CanvasRenderingContext2D | null = null;\r\n private lastGridRef: unknown = null;\r\n\r\n constructor(deps: RenderLoopDeps) {\r\n this.canvasEl = deps.canvasEl;\r\n this.camera = deps.camera;\r\n this.background = deps.background;\r\n this.store = deps.store;\r\n this.renderer = deps.renderer;\r\n this.toolManager = deps.toolManager;\r\n this.layerManager = deps.layerManager;\r\n this.domNodeManager = deps.domNodeManager;\r\n this.layerCache = deps.layerCache;\r\n this.marginViewport = deps.marginViewport;\r\n }\r\n\r\n requestRender(): void {\r\n this.needsRender = true;\r\n }\r\n\r\n flush(): void {\r\n if (this.needsRender) {\r\n this.render();\r\n this.needsRender = false;\r\n }\r\n }\r\n\r\n start(): void {\r\n const loop = (): void => {\r\n if (this.needsRender) {\r\n this.render();\r\n this.needsRender = false;\r\n }\r\n this.animFrameId = requestAnimationFrame(loop);\r\n };\r\n this.animFrameId = requestAnimationFrame(loop);\r\n }\r\n\r\n stop(): void {\r\n cancelAnimationFrame(this.animFrameId);\r\n }\r\n\r\n setCanvasSize(width: number, height: number): void {\r\n this.canvasEl.width = width;\r\n this.canvasEl.height = height;\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n this.marginViewport.setViewport(width / dpr, height / dpr, dpr);\r\n this.layerCache.resize();\r\n }\r\n\r\n setActiveDrawingLayer(layerId: string | null): void {\r\n this.activeDrawingLayerId = layerId;\r\n }\r\n\r\n markLayerDirty(layerId: string): void {\r\n this.layerCache.markDirty(layerId);\r\n }\r\n\r\n markAllLayersDirty(): void {\r\n this.layerCache.markAllDirty();\r\n }\r\n\r\n getStats(): RenderStatsSnapshot {\r\n return this.stats.getSnapshot();\r\n }\r\n\r\n private compositeLayerCache(ctx: CanvasRenderingContext2D, layerId: string): void {\r\n const cached = this.layerCache.getCanvas(layerId);\r\n const offset = this.marginViewport.compositeOffset(\r\n this.camera.position.x,\r\n this.camera.position.y,\r\n );\r\n ctx.save();\r\n ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n ctx.drawImage(cached as CanvasImageSource, offset.x, offset.y);\r\n ctx.restore();\r\n }\r\n\r\n private ensureGridCache(): void {\r\n const w = this.marginViewport.physicalWidth();\r\n const h = this.marginViewport.physicalHeight();\r\n if (\r\n this.gridCacheCanvas !== null &&\r\n this.gridCacheCanvas.width === w &&\r\n this.gridCacheCanvas.height === h\r\n ) {\r\n return;\r\n }\r\n\r\n if (typeof OffscreenCanvas !== 'undefined') {\r\n this.gridCacheCanvas = new OffscreenCanvas(w, h) as unknown as HTMLCanvasElement;\r\n } else if (typeof document !== 'undefined') {\r\n const el = document.createElement('canvas');\r\n el.width = w;\r\n el.height = h;\r\n this.gridCacheCanvas = el;\r\n } else {\r\n this.gridCacheCanvas = null;\r\n this.gridCacheCtx = null;\r\n return;\r\n }\r\n\r\n this.gridCacheCtx = this.gridCacheCanvas.getContext('2d') as CanvasRenderingContext2D | null;\r\n }\r\n\r\n private render(): void {\r\n const t0 = performance.now();\r\n const ctx = this.canvasEl.getContext('2d');\r\n if (!ctx) return;\r\n\r\n let layersMs = 0;\r\n let compositeMs = 0;\r\n let gridMs = 0;\r\n\r\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\r\n const cssWidth = this.canvasEl.clientWidth;\r\n const cssHeight = this.canvasEl.clientHeight;\r\n\r\n // idempotent; catches resizes that bypass setCanvasSize\r\n this.marginViewport.setViewport(cssWidth, cssHeight, dpr);\r\n\r\n const currentZoom = this.camera.zoom;\r\n const currentCamX = this.camera.position.x;\r\n const currentCamY = this.camera.position.y;\r\n if (this.marginViewport.needsRecenter(currentCamX, currentCamY, currentZoom)) {\r\n this.marginViewport.recenter(currentCamX, currentCamY, currentZoom);\r\n this.layerCache.markAllDirty();\r\n this.gridCacheDirty = true;\r\n }\r\n\r\n ctx.save();\r\n ctx.scale(dpr, dpr);\r\n\r\n this.renderer.setCanvasSize(cssWidth, cssHeight);\r\n const hasGridElement = this.store.getElementsByType('grid').length > 0;\r\n const bgT0 = performance.now();\r\n if (hasGridElement) {\r\n ctx.save();\r\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n ctx.clearRect(0, 0, cssWidth, cssHeight);\r\n ctx.restore();\r\n } else {\r\n this.background.render(ctx, this.camera);\r\n }\r\n const backgroundMs = performance.now() - bgT0;\r\n\r\n ctx.save();\r\n ctx.translate(this.camera.position.x, this.camera.position.y);\r\n ctx.scale(this.camera.zoom, this.camera.zoom);\r\n\r\n const cullBounds = this.marginViewport.cachedWorldBounds();\r\n const cullPad = Math.max(cullBounds.w, cullBounds.h) * 0.05;\r\n const cullingRect: Bounds = {\r\n x: cullBounds.x - cullPad,\r\n y: cullBounds.y - cullPad,\r\n w: cullBounds.w + cullPad * 2,\r\n h: cullBounds.h + cullPad * 2,\r\n };\r\n\r\n const allElements = this.store.getAll();\r\n this.layerGroups.clear();\r\n const gridElements: CanvasElement[] = [];\r\n let domZIndex = 0;\r\n\r\n for (const element of allElements) {\r\n if (!this.layerManager.isLayerVisible(element.layerId)) {\r\n if (this.renderer.isDomElement(element)) {\r\n this.domNodeManager.hideDomNode(element.id);\r\n }\r\n continue;\r\n }\r\n\r\n if (this.renderer.isDomElement(element)) {\r\n const elBounds = getElementBounds(element);\r\n if (elBounds && !boundsIntersect(elBounds, cullingRect)) {\r\n this.domNodeManager.hideDomNode(element.id);\r\n } else {\r\n this.domNodeManager.syncDomNode(element, domZIndex++);\r\n }\r\n continue;\r\n }\r\n\r\n // Grids are viewport-filling; handled via anchored cache below\r\n if (element.type === 'grid') {\r\n gridElements.push(element);\r\n continue;\r\n }\r\n\r\n let group = this.layerGroups.get(element.layerId);\r\n if (!group) {\r\n group = [];\r\n this.layerGroups.set(element.layerId, group);\r\n }\r\n group.push(element);\r\n }\r\n\r\n for (const [layerId, elements] of this.layerGroups) {\r\n const isActiveDrawingLayer = layerId === this.activeDrawingLayerId;\r\n\r\n if (!this.layerCache.isDirty(layerId)) {\r\n const compT0 = performance.now();\r\n this.compositeLayerCache(ctx, layerId);\r\n compositeMs += performance.now() - compT0;\r\n continue;\r\n }\r\n\r\n if (isActiveDrawingLayer) {\r\n const compT0 = performance.now();\r\n this.compositeLayerCache(ctx, layerId);\r\n compositeMs += performance.now() - compT0;\r\n continue;\r\n }\r\n\r\n const offCtx = this.layerCache.getContext(layerId);\r\n if (offCtx) {\r\n const layerT0 = performance.now();\r\n const offCanvas = this.layerCache.getCanvas(layerId);\r\n offCtx.clearRect(0, 0, offCanvas.width, offCanvas.height);\r\n offCtx.save();\r\n this.marginViewport.applyRenderTransform(offCtx);\r\n for (const element of elements) {\r\n const elBounds = getElementBounds(element);\r\n if (elBounds && !boundsIntersect(elBounds, cullingRect)) continue;\r\n this.renderer.renderCanvasElement(offCtx as CanvasRenderingContext2D, element);\r\n }\r\n offCtx.restore();\r\n this.layerCache.markClean(layerId);\r\n layersMs += performance.now() - layerT0;\r\n\r\n const compT0 = performance.now();\r\n this.compositeLayerCache(ctx, layerId);\r\n compositeMs += performance.now() - compT0;\r\n }\r\n }\r\n\r\n // Render grids on top of layer elements\r\n if (gridElements.length > 0) {\r\n const gridT0 = performance.now();\r\n const gridRef = gridElements[0];\r\n const gridDirty = this.gridCacheDirty || gridRef !== this.lastGridRef;\r\n\r\n if (gridDirty) {\r\n this.ensureGridCache();\r\n if (this.gridCacheCtx && this.gridCacheCanvas) {\r\n const cb = this.marginViewport.cachedWorldBounds();\r\n this.renderer.setGridBoundsOverride({\r\n minX: cb.x,\r\n minY: cb.y,\r\n maxX: cb.x + cb.w,\r\n maxY: cb.y + cb.h,\r\n });\r\n const gc = this.gridCacheCtx;\r\n gc.clearRect(0, 0, this.gridCacheCanvas.width, this.gridCacheCanvas.height);\r\n gc.save();\r\n this.marginViewport.applyRenderTransform(gc);\r\n try {\r\n for (const grid of gridElements) {\r\n this.renderer.renderCanvasElement(gc as CanvasRenderingContext2D, grid);\r\n }\r\n } finally {\r\n gc.restore();\r\n this.renderer.setGridBoundsOverride(null);\r\n }\r\n }\r\n this.gridCacheDirty = false;\r\n this.lastGridRef = gridRef;\r\n }\r\n\r\n if (this.gridCacheCanvas) {\r\n const offset = this.marginViewport.compositeOffset(\r\n this.camera.position.x,\r\n this.camera.position.y,\r\n );\r\n ctx.save();\r\n ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n ctx.drawImage(this.gridCacheCanvas as CanvasImageSource, offset.x, offset.y);\r\n ctx.restore();\r\n } else {\r\n for (const grid of gridElements) {\r\n this.renderer.renderCanvasElement(ctx, grid);\r\n }\r\n }\r\n gridMs = performance.now() - gridT0;\r\n }\r\n\r\n const overlayT0 = performance.now();\r\n const activeTool = this.toolManager.activeTool;\r\n if (activeTool?.renderOverlay) {\r\n activeTool.renderOverlay(ctx);\r\n }\r\n const overlayMs = performance.now() - overlayT0;\r\n\r\n ctx.restore();\r\n ctx.restore();\r\n\r\n this.stats.recordFrame(performance.now() - t0, {\r\n gridMs,\r\n layersMs,\r\n backgroundMs,\r\n compositeMs,\r\n overlayMs,\r\n });\r\n }\r\n}\r\n","import type { MarginViewport } from './margin-viewport';\r\n\r\nfunction createOffscreenCanvas(width: number, height: number): HTMLCanvasElement | OffscreenCanvas {\r\n if (typeof OffscreenCanvas !== 'undefined') {\r\n return new OffscreenCanvas(width, height);\r\n }\r\n const canvas = document.createElement('canvas');\r\n canvas.width = width;\r\n canvas.height = height;\r\n return canvas;\r\n}\r\n\r\nexport class LayerCache {\r\n private canvases = new Map<string, HTMLCanvasElement | OffscreenCanvas>();\r\n private dirtyFlags = new Map<string, boolean>();\r\n\r\n constructor(private readonly viewport: MarginViewport) {}\r\n\r\n isDirty(layerId: string): boolean {\r\n return this.dirtyFlags.get(layerId) !== false;\r\n }\r\n\r\n markDirty(layerId: string): void {\r\n this.dirtyFlags.set(layerId, true);\r\n }\r\n\r\n markClean(layerId: string): void {\r\n this.dirtyFlags.set(layerId, false);\r\n }\r\n\r\n markAllDirty(): void {\r\n for (const [id] of this.dirtyFlags) {\r\n this.dirtyFlags.set(id, true);\r\n }\r\n }\r\n\r\n getCanvas(layerId: string): HTMLCanvasElement | OffscreenCanvas {\r\n let canvas = this.canvases.get(layerId);\r\n if (!canvas) {\r\n canvas = createOffscreenCanvas(this.viewport.physicalWidth(), this.viewport.physicalHeight());\r\n this.canvases.set(layerId, canvas);\r\n this.dirtyFlags.set(layerId, true);\r\n }\r\n return canvas;\r\n }\r\n\r\n getContext(layerId: string): CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null {\r\n const canvas = this.getCanvas(layerId);\r\n return canvas.getContext('2d') as\r\n | CanvasRenderingContext2D\r\n | OffscreenCanvasRenderingContext2D\r\n | null;\r\n }\r\n\r\n resize(): void {\r\n const w = this.viewport.physicalWidth();\r\n const h = this.viewport.physicalHeight();\r\n for (const [id, canvas] of this.canvases) {\r\n canvas.width = w;\r\n canvas.height = h;\r\n this.dirtyFlags.set(id, true);\r\n }\r\n }\r\n\r\n clear(): void {\r\n this.canvases.clear();\r\n this.dirtyFlags.clear();\r\n }\r\n}\r\n","import type { Bounds } from '../core/types';\r\n\r\n/**\r\n * Owns the cache anchor (the camera state the screen-space caches were last rendered at)\r\n * and the margin geometry. Pure — holds no canvas. Caches render a region inflated by\r\n * `marginPx` on every side, so a pan within the margin is an offset-blit, not a re-raster.\r\n *\r\n * Call setViewport(cssW, cssH, dpr) before physicalWidth/Height, applyRenderTransform, or compositeOffset — they read the stored dpr.\r\n */\r\nexport class MarginViewport {\r\n private cssW = 0;\r\n private cssH = 0;\r\n private dpr = 1;\r\n private anchorCamX = 0;\r\n private anchorCamY = 0;\r\n private anchorZoom = Number.NaN; // sentinel → first needsRecenter is true\r\n private viewportDirty = true;\r\n\r\n constructor(private marginPx: number) {}\r\n\r\n setMargin(marginPx: number): void {\r\n if (marginPx !== this.marginPx) {\r\n this.marginPx = marginPx;\r\n this.viewportDirty = true;\r\n }\r\n }\r\n\r\n setViewport(cssW: number, cssH: number, dpr: number): void {\r\n if (cssW !== this.cssW || cssH !== this.cssH || dpr !== this.dpr) {\r\n this.cssW = cssW;\r\n this.cssH = cssH;\r\n this.dpr = dpr;\r\n this.viewportDirty = true;\r\n }\r\n }\r\n\r\n physicalWidth(): number {\r\n return Math.round((this.cssW + 2 * this.marginPx) * this.dpr);\r\n }\r\n\r\n physicalHeight(): number {\r\n return Math.round((this.cssH + 2 * this.marginPx) * this.dpr);\r\n }\r\n\r\n needsRecenter(camX: number, camY: number, zoom: number): boolean {\r\n return (\r\n this.viewportDirty ||\r\n zoom !== this.anchorZoom ||\r\n Math.abs(camX - this.anchorCamX) > this.marginPx ||\r\n Math.abs(camY - this.anchorCamY) > this.marginPx\r\n );\r\n }\r\n\r\n recenter(camX: number, camY: number, zoom: number): void {\r\n this.anchorCamX = camX;\r\n this.anchorCamY = camY;\r\n this.anchorZoom = zoom;\r\n this.viewportDirty = false;\r\n }\r\n\r\n /** Applies dpr scale + anchor-relative world transform. setViewport must have been called first. */\r\n applyRenderTransform(ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D): void {\r\n ctx.scale(this.dpr, this.dpr);\r\n ctx.translate(this.marginPx + this.anchorCamX, this.marginPx + this.anchorCamY);\r\n ctx.scale(this.anchorZoom, this.anchorZoom);\r\n }\r\n\r\n // Device-px destination for drawImage(cache, x, y).\r\n // A world point P sits in the cache at CSS x `margin + anchorCamX + P*zoom`; it must land on\r\n // screen at `camX + P*zoom`; so the blit offset is `camX - anchorCamX - margin` (CSS) * dpr.\r\n compositeOffset(camX: number, camY: number): { x: number; y: number } {\r\n return {\r\n x: (camX - this.anchorCamX - this.marginPx) * this.dpr,\r\n y: (camY - this.anchorCamY - this.marginPx) * this.dpr,\r\n };\r\n }\r\n\r\n // World-space bounds of the whole cached region at the anchor (cull rect for re-renders).\r\n cachedWorldBounds(): Bounds {\r\n const z = this.anchorZoom;\r\n return {\r\n x: (-this.marginPx - this.anchorCamX) / z,\r\n y: (-this.marginPx - this.anchorCamY) / z,\r\n w: (this.cssW + 2 * this.marginPx) / z,\r\n h: (this.cssH + 2 * this.marginPx) / z,\r\n };\r\n }\r\n}\r\n","import type { CanvasElement } from './types';\n\nexport interface ElementStyle {\n color?: string;\n fillColor?: string;\n strokeWidth?: number;\n opacity?: number;\n fontSize?: number;\n}\n\nexport function styleToPatch(element: CanvasElement, style: ElementStyle): Partial<CanvasElement> {\n const { color, fillColor, strokeWidth, opacity, fontSize } = style;\n switch (element.type) {\n case 'stroke':\n return {\n ...(color !== undefined ? { color } : {}),\n ...(strokeWidth !== undefined ? { width: strokeWidth } : {}),\n ...(opacity !== undefined ? { opacity } : {}),\n };\n case 'arrow':\n return {\n ...(color !== undefined ? { color } : {}),\n ...(strokeWidth !== undefined ? { width: strokeWidth } : {}),\n };\n case 'shape':\n return {\n ...(color !== undefined ? { strokeColor: color } : {}),\n ...(fillColor !== undefined ? { fillColor } : {}),\n ...(strokeWidth !== undefined ? { strokeWidth } : {}),\n };\n case 'text':\n return {\n ...(color !== undefined ? { color } : {}),\n ...(fontSize !== undefined ? { fontSize } : {}),\n };\n case 'note':\n return {\n ...(color !== undefined ? { textColor: color } : {}),\n ...(fillColor !== undefined ? { backgroundColor: fillColor } : {}),\n ...(fontSize !== undefined ? { fontSize } : {}),\n };\n case 'grid':\n return {\n ...(color !== undefined ? { strokeColor: color } : {}),\n ...(strokeWidth !== undefined ? { strokeWidth } : {}),\n ...(opacity !== undefined ? { opacity } : {}),\n };\n case 'template':\n return {\n ...(color !== undefined ? { strokeColor: color } : {}),\n ...(fillColor !== undefined ? { fillColor } : {}),\n ...(strokeWidth !== undefined ? { strokeWidth } : {}),\n ...(opacity !== undefined ? { opacity } : {}),\n };\n default:\n return {};\n }\n}\n\nexport function getElementStyle(element: CanvasElement): ElementStyle {\n switch (element.type) {\n case 'stroke':\n return { color: element.color, strokeWidth: element.width, opacity: element.opacity };\n case 'arrow':\n return { color: element.color, strokeWidth: element.width };\n case 'shape':\n return {\n color: element.strokeColor,\n fillColor: element.fillColor,\n strokeWidth: element.strokeWidth,\n };\n case 'text':\n return { color: element.color, fontSize: element.fontSize };\n case 'note':\n return {\n color: element.textColor,\n fillColor: element.backgroundColor,\n ...(element.fontSize !== undefined ? { fontSize: element.fontSize } : {}),\n };\n case 'grid':\n return {\n color: element.strokeColor,\n strokeWidth: element.strokeWidth,\n opacity: element.opacity,\n };\n case 'template':\n return {\n color: element.strokeColor,\n fillColor: element.fillColor,\n strokeWidth: element.strokeWidth,\n opacity: element.opacity,\n };\n default:\n return {};\n }\n}\n","import { Camera } from './camera';\nimport type { CameraOptions } from './camera';\nimport { InputHandler } from './input-handler';\nimport type { ShortcutOptions, ShortcutsApi } from './shortcut-map';\nimport { Background } from './background';\nimport type { BackgroundOptions } from './background';\nimport { ElementStore } from '../elements/element-store';\nimport { ElementRenderer } from '../elements/element-renderer';\nimport { NoteEditor } from '../elements/note-editor';\nimport type { FontSizePreset } from '../elements/note-toolbar';\nimport type { CanvasElement, ArrowElement, GridElement } from '../elements/types';\nimport { findBoundArrows, getEdgeIntersection } from '../elements/arrow-binding';\nimport { getElementBounds } from '../elements/element-bounds';\nimport { getElementsBoundingBox } from '../elements/bounds';\nimport { getArrowTangentAngle } from '../elements/arrow-geometry';\nimport { ToolManager } from '../tools/tool-manager';\nimport type { ToolContext } from '../tools/types';\nimport type { SelectTool } from '../tools/select-tool';\nimport { HistoryStack } from '../history/history-stack';\nimport { HistoryRecorder } from '../history/history-recorder';\nimport { createImage, createHtmlElement, createGrid } from '../elements/element-factory';\nimport { exportState as exportCanvasState, parseState } from '../core/state-serializer';\nimport { exportImage } from './export-image';\nimport type { ExportImageOptions } from './export-image';\nimport type { CanvasState } from '../core/state-serializer';\nimport { LayerManager } from '../layers/layer-manager';\nimport { InteractMode } from './interact-mode';\nimport { DomNodeManager } from './dom-node-manager';\nimport { DoubleTapDetector } from './double-tap-detector';\nimport { RenderLoop } from './render-loop';\nimport type { RenderStatsSnapshot } from './render-stats';\nimport { LayerCache } from './layer-cache';\nimport { MarginViewport } from './margin-viewport';\nimport { isNoteContentEmpty } from '../elements/note-sanitizer';\nimport { styleToPatch, getElementStyle } from '../elements/element-style';\nimport type { ElementStyle } from '../elements/element-style';\n\nconst EMPTY_IDS: string[] = [];\n\nfunction noop(): void {\n // Stable unsubscribe handle returned when no select tool is registered.\n}\n\nfunction sharedValue<T>(values: (T | undefined)[]): T | undefined {\n const present = values.filter((v): v is T => v !== undefined);\n if (present.length === 0) return undefined;\n const first = present[0];\n return present.every((v) => v === first) ? first : undefined;\n}\n\nexport interface GridInfo {\n gridType: 'square' | 'hex';\n hexOrientation: 'pointy' | 'flat';\n cellSize: number;\n cellRadius: number;\n}\n\nexport interface ViewportOptions {\n camera?: CameraOptions;\n background?: BackgroundOptions;\n fontSizePresets?: FontSizePreset[];\n toolbar?: boolean;\n placeholder?: string;\n shortcuts?: ShortcutOptions;\n onHtmlElementMount?: (\n elementId: string,\n domId: string | undefined,\n container: HTMLDivElement,\n ) => void;\n onDrop?: (event: DragEvent, worldPosition: { x: number; y: number }) => void;\n onImageError?: (info: { src: string; elementIds: string[]; cause?: unknown }) => void;\n /** CSS-pixel margin cached beyond the viewport. Default `256`. Set `0` to disable. */\n panBufferMargin?: number;\n}\n\nexport class Viewport {\n readonly camera: Camera;\n readonly store: ElementStore;\n readonly layerManager: LayerManager;\n readonly toolManager: ToolManager;\n readonly history: HistoryStack;\n readonly domLayer: HTMLDivElement;\n private readonly canvasEl: HTMLCanvasElement;\n private readonly wrapper: HTMLDivElement;\n private readonly unsubCamera: () => void;\n private readonly unsubStore: (() => void)[];\n private readonly inputHandler: InputHandler;\n private readonly background: Background;\n private readonly renderer: ElementRenderer;\n private readonly noteEditor: NoteEditor;\n private readonly historyRecorder: HistoryRecorder;\n readonly toolContext: ToolContext;\n private readonly marginViewport: MarginViewport;\n private resizeObserver: ResizeObserver | null = null;\n private _snapToGrid = false;\n private readonly _gridSize: number;\n private readonly renderLoop: RenderLoop;\n private readonly domNodeManager: DomNodeManager;\n private readonly interactMode: InteractMode;\n private readonly onHtmlElementMount?: (\n elementId: string,\n domId: string | undefined,\n container: HTMLDivElement,\n ) => void;\n private readonly dropHandler?: (\n event: DragEvent,\n worldPosition: { x: number; y: number },\n ) => void;\n private readonly gridChangeListeners = new Set<(info: GridInfo | null) => void>();\n private readonly doubleTapDetector = new DoubleTapDetector();\n private tapDownX = 0;\n private tapDownY = 0;\n\n constructor(\n private readonly container: HTMLElement,\n options: ViewportOptions = {},\n ) {\n this.camera = new Camera(options.camera);\n this.background = new Background(options.background);\n this._gridSize = options.background?.spacing ?? 24;\n this.store = new ElementStore();\n this.layerManager = new LayerManager(this.store);\n this.toolManager = new ToolManager();\n this.renderer = new ElementRenderer();\n this.renderer.setStore(this.store);\n this.renderer.setCamera(this.camera);\n this.renderer.setOnImageLoad(() => {\n this.renderLoop.markAllLayersDirty();\n this.requestRender();\n });\n this.renderer.setOnImageError((src, cause) => {\n const elementIds: string[] = [];\n for (const el of this.store.getAll()) {\n if (el.type === 'image' && el.src === src) elementIds.push(el.id);\n }\n if (options.onImageError) {\n options.onImageError({ src, elementIds, cause });\n } else {\n console.warn(`[fieldnotes] image failed to load: ${src}`);\n }\n });\n this.noteEditor = new NoteEditor({\n fontSizePresets: options.fontSizePresets,\n toolbar: options.toolbar,\n placeholder: options.placeholder,\n });\n this.noteEditor.setOnStop((id) => this.onTextEditStop(id));\n this.noteEditor.setHistoryHooks(\n () => this.historyRecorder.begin(),\n () => this.historyRecorder.commit(),\n );\n this.onHtmlElementMount = options.onHtmlElementMount;\n this.dropHandler = options.onDrop;\n this.history = new HistoryStack();\n this.historyRecorder = new HistoryRecorder(this.store, this.history, this.layerManager);\n\n this.wrapper = this.createWrapper();\n this.canvasEl = this.createCanvas();\n this.domLayer = this.createDomLayer();\n\n this.wrapper.appendChild(this.canvasEl);\n this.wrapper.appendChild(this.domLayer);\n this.container.appendChild(this.wrapper);\n\n this.toolContext = {\n camera: this.camera,\n store: this.store,\n requestRender: () => this.requestRender(),\n switchTool: (name: string) => this.toolManager.setTool(name, this.toolContext),\n editElement: (id: string) => this.startEditingElement(id),\n fitNoteHeight: (id: string) => this.fitNoteHeight(id),\n setCursor: (cursor: string) => {\n this.wrapper.style.cursor = cursor;\n },\n snapToGrid: false,\n gridSize: this._gridSize,\n activeLayerId: this.layerManager.activeLayerId,\n isLayerVisible: (id: string) => this.layerManager.isLayerVisible(id),\n isLayerLocked: (id: string) => this.layerManager.isLayerLocked(id),\n };\n\n this.inputHandler = new InputHandler(this.wrapper, this.camera, {\n toolManager: this.toolManager,\n toolContext: this.toolContext,\n historyRecorder: this.historyRecorder,\n historyStack: this.history,\n fitToContent: () => this.fitToContent(),\n shortcuts: options.shortcuts,\n });\n\n this.domNodeManager = new DomNodeManager({\n domLayer: this.domLayer,\n onEditRequest: (id) => this.startEditingElement(id),\n isEditingElement: (id) =>\n this.noteEditor.isEditing && this.noteEditor.editingElementId === id,\n getVersion: (id) => this.store.getVersion(id),\n });\n\n this.interactMode = new InteractMode({\n getNode: (id) => this.domNodeManager.getNode(id),\n });\n\n this.marginViewport = new MarginViewport(options.panBufferMargin ?? 256);\n this.marginViewport.setViewport(\n this.canvasEl.clientWidth || 800,\n this.canvasEl.clientHeight || 600,\n typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1,\n );\n const layerCache = new LayerCache(this.marginViewport);\n\n this.renderLoop = new RenderLoop({\n canvasEl: this.canvasEl,\n camera: this.camera,\n background: this.background,\n store: this.store,\n renderer: this.renderer,\n toolManager: this.toolManager,\n layerManager: this.layerManager,\n domNodeManager: this.domNodeManager,\n layerCache,\n marginViewport: this.marginViewport,\n });\n\n this.unsubCamera = this.camera.onChange(() => {\n this.applyCameraTransform();\n this.noteEditor.updateToolbarPosition();\n this.requestRender();\n });\n\n this.unsubStore = [\n this.store.on('add', (el) => {\n if (el.type === 'grid') this.syncGridContext();\n this.renderLoop.markLayerDirty(el.layerId);\n this.requestRender();\n }),\n this.store.on('remove', (el) => {\n if (el.type === 'grid') this.syncGridContext();\n this.unbindArrowsFrom(el);\n this.domNodeManager.removeDomNode(el.id);\n this.renderLoop.markLayerDirty(el.layerId);\n this.requestRender();\n }),\n this.store.on('update', ({ previous, current }) => {\n if (current.type === 'grid') this.syncGridContext();\n this.renderLoop.markLayerDirty(current.layerId);\n if (previous.layerId !== current.layerId) {\n this.renderLoop.markLayerDirty(previous.layerId);\n }\n this.requestRender();\n }),\n this.store.on('clear', () => {\n this.domNodeManager.clearDomNodes();\n this.renderLoop.markAllLayersDirty();\n this.syncGridContext();\n this.requestRender();\n }),\n ];\n\n this.layerManager.on('change', () => {\n this.toolContext.activeLayerId = this.layerManager.activeLayerId;\n this.requestRender();\n });\n\n this.wrapper.addEventListener('pointerdown', this.onTapDown);\n this.wrapper.addEventListener('pointerup', this.onDoubleTap);\n this.wrapper.addEventListener('dragover', this.onDragOver);\n this.wrapper.addEventListener('drop', this.onDrop);\n this.observeResize();\n this.syncCanvasSize();\n this.renderLoop.start();\n this.syncGridContext();\n }\n\n get ctx(): CanvasRenderingContext2D | null {\n return this.canvasEl.getContext('2d');\n }\n\n get snapToGrid(): boolean {\n return this._snapToGrid;\n }\n\n setSnapToGrid(enabled: boolean): void {\n this._snapToGrid = enabled;\n this.toolContext.snapToGrid = enabled;\n }\n\n fitToContent(padding = 40): void {\n if (this.wrapper.clientWidth === 0 || this.wrapper.clientHeight === 0) return;\n const visibleElements = this.store\n .getAll()\n .filter((el) => this.layerManager.isLayerVisible(el.layerId));\n const bbox = getElementsBoundingBox(visibleElements);\n if (!bbox) return;\n this.camera.fitToContent(bbox, this.wrapper.clientWidth, this.wrapper.clientHeight, padding);\n }\n\n requestRender(): void {\n this.renderLoop.requestRender();\n }\n\n exportState(): CanvasState {\n return exportCanvasState(\n this.store.snapshot(),\n this.camera,\n this.layerManager.snapshot(),\n this.layerManager.activeLayerId,\n );\n }\n\n exportJSON(): string {\n return JSON.stringify(this.exportState());\n }\n\n async exportImage(options?: ExportImageOptions): Promise<Blob | null> {\n return exportImage(this.store, options, this.layerManager);\n }\n\n loadState(state: CanvasState): void {\n this.inputHandler.flushPendingHistory();\n this.historyRecorder.pause();\n this.noteEditor.destroy(this.store);\n this.domNodeManager.clearDomNodes();\n this.store.loadSnapshot(state.elements);\n if (state.layers && state.layers.length > 0) {\n this.layerManager.loadSnapshot(state.layers);\n }\n if (state.activeLayerId) {\n this.layerManager.setActiveLayer(state.activeLayerId);\n }\n this.domNodeManager.reattachHtmlContent(this.store);\n if (this.onHtmlElementMount) {\n for (const el of this.store.getElementsByType('html')) {\n if (!this.domNodeManager.hasContent(el.id)) {\n this.domNodeManager.syncDomNode(el);\n const node = this.domNodeManager.getNode(el.id);\n if (node) {\n this.onHtmlElementMount(el.id, el.domId, node);\n node.dataset['initialized'] = 'true';\n Object.assign(node.style, {\n overflow: 'hidden',\n pointerEvents: el.interactive ? 'auto' : 'none',\n });\n }\n }\n }\n }\n this.history.clear();\n this.historyRecorder.resume();\n this.camera.moveTo(state.camera.position.x, state.camera.position.y);\n this.camera.setZoom(state.camera.zoom);\n }\n\n loadJSON(json: string): void {\n this.loadState(parseState(json));\n }\n\n setTool(name: string): void {\n if (!this.toolManager.getTool(name)) {\n console.warn(`[fieldnotes] setTool: no tool registered as \"${name}\"`);\n return;\n }\n this.toolManager.setTool(name, this.toolContext);\n }\n\n get shortcuts(): ShortcutsApi {\n return this.inputHandler.shortcuts;\n }\n\n undo(): boolean {\n this.inputHandler.flushPendingHistory();\n this.historyRecorder.pause();\n const result = this.history.undo(this.store);\n this.historyRecorder.resume();\n if (result) this.requestRender();\n return result;\n }\n\n redo(): boolean {\n this.inputHandler.flushPendingHistory();\n this.historyRecorder.pause();\n const result = this.history.redo(this.store);\n this.historyRecorder.resume();\n if (result) this.requestRender();\n return result;\n }\n\n addImage(src: string, position: { x: number; y: number }, size = { w: 300, h: 200 }): string {\n const image = createImage({ position, size, src, layerId: this.layerManager.activeLayerId });\n this.historyRecorder.begin();\n this.store.add(image);\n this.historyRecorder.commit();\n this.requestRender();\n return image.id;\n }\n\n addHtmlElement(\n dom: HTMLElement,\n position: { x: number; y: number },\n size = { w: 200, h: 150 },\n ): string {\n const domId = dom.id || undefined;\n const el = createHtmlElement({\n position,\n size,\n domId,\n layerId: this.layerManager.activeLayerId,\n });\n this.domNodeManager.storeHtmlContent(el.id, dom);\n this.historyRecorder.begin();\n this.store.add(el);\n this.historyRecorder.commit();\n this.requestRender();\n return el.id;\n }\n\n removeLayer(id: string): void {\n this.historyRecorder.begin();\n this.layerManager.removeLayer(id);\n this.historyRecorder.commit();\n }\n\n updateHtmlElement(id: string, newContent: HTMLElement): void {\n const el = this.store.getById(id);\n if (!el) throw new Error(`Element not found: ${id}`);\n if (el.type !== 'html') throw new Error(`Element ${id} is not an HTML element`);\n this.domNodeManager.resetHtmlContent(id);\n this.domNodeManager.storeHtmlContent(id, newContent);\n this.requestRender();\n }\n\n addGrid(input: {\n gridType?: 'square' | 'hex';\n hexOrientation?: 'pointy' | 'flat';\n cellSize?: number;\n strokeColor?: string;\n strokeWidth?: number;\n opacity?: number;\n }): string {\n const existing = this.store.getElementsByType('grid')[0];\n this.historyRecorder.begin();\n if (existing) {\n this.store.remove(existing.id);\n }\n const grid = createGrid({ ...input, layerId: this.layerManager.activeLayerId });\n this.store.add(grid);\n this.historyRecorder.commit();\n this.requestRender();\n return grid.id;\n }\n\n updateGrid(\n updates: Partial<\n Pick<\n GridElement,\n 'gridType' | 'hexOrientation' | 'cellSize' | 'strokeColor' | 'strokeWidth' | 'opacity'\n >\n >,\n ): void {\n const grid = this.store.getElementsByType('grid')[0];\n if (!grid) return;\n this.historyRecorder.begin();\n this.store.update(grid.id, updates);\n this.historyRecorder.commit();\n this.requestRender();\n }\n\n removeGrid(): void {\n const grid = this.store.getElementsByType('grid')[0];\n if (!grid) return;\n this.historyRecorder.begin();\n this.store.remove(grid.id);\n this.historyRecorder.commit();\n this.requestRender();\n }\n\n getGridInfo(): GridInfo | null {\n const grid = this.store.getElementsByType('grid')[0];\n if (!grid) return null;\n return {\n gridType: grid.gridType,\n hexOrientation: grid.hexOrientation,\n cellSize: grid.cellSize,\n cellRadius: grid.gridType === 'hex' ? grid.cellSize : grid.cellSize / 2,\n };\n }\n\n onGridChange(listener: (info: GridInfo | null) => void): () => void {\n this.gridChangeListeners.add(listener);\n return () => {\n this.gridChangeListeners.delete(listener);\n };\n }\n\n private getSelectTool(): SelectTool | undefined {\n return this.toolManager.getTool<SelectTool>('select');\n }\n\n getSelectedIds(): string[] {\n return this.getSelectTool()?.selectedIds ?? EMPTY_IDS;\n }\n\n onSelectionChange(listener: () => void): () => void {\n const tool = this.getSelectTool();\n return tool ? tool.onSelectionChange(listener) : noop;\n }\n\n getSelectionStyle(): ElementStyle | null {\n const ids = this.getSelectedIds();\n if (ids.length === 0) return null;\n const styles: ElementStyle[] = [];\n for (const id of ids) {\n const el = this.store.getById(id);\n if (el) styles.push(getElementStyle(el));\n }\n if (styles.length === 0) return null;\n const result: ElementStyle = {};\n const color = sharedValue(styles.map((s) => s.color));\n if (color !== undefined) result.color = color;\n const fillColor = sharedValue(styles.map((s) => s.fillColor));\n if (fillColor !== undefined) result.fillColor = fillColor;\n const strokeWidth = sharedValue(styles.map((s) => s.strokeWidth));\n if (strokeWidth !== undefined) result.strokeWidth = strokeWidth;\n const opacity = sharedValue(styles.map((s) => s.opacity));\n if (opacity !== undefined) result.opacity = opacity;\n const fontSize = sharedValue(styles.map((s) => s.fontSize));\n if (fontSize !== undefined) result.fontSize = fontSize;\n return result;\n }\n\n applyStyleToSelection(style: ElementStyle): void {\n const ids = this.getSelectedIds();\n if (ids.length === 0) return;\n this.historyRecorder.begin();\n for (const id of ids) {\n const el = this.store.getById(id);\n if (!el) continue;\n const patch = styleToPatch(el, style);\n if (Object.keys(patch).length > 0) {\n this.store.update(id, patch);\n }\n }\n this.historyRecorder.commit();\n }\n\n getRenderStats(): RenderStatsSnapshot {\n return this.renderLoop.getStats();\n }\n\n logPerformance(intervalMs = 2000): () => void {\n const id = setInterval(() => {\n const s = this.getRenderStats();\n console.log(\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`,\n );\n }, intervalMs);\n return () => clearInterval(id);\n }\n\n destroy(): void {\n this.renderLoop.stop();\n this.interactMode.destroy();\n this.noteEditor.destroy(this.store);\n this.historyRecorder.destroy();\n this.wrapper.removeEventListener('pointerdown', this.onTapDown);\n this.wrapper.removeEventListener('pointerup', this.onDoubleTap);\n this.wrapper.removeEventListener('dragover', this.onDragOver);\n this.wrapper.removeEventListener('drop', this.onDrop);\n this.inputHandler.destroy();\n this.unsubCamera();\n this.unsubStore.forEach((fn) => fn());\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n this.wrapper.remove();\n }\n\n private startEditingElement(id: string): void {\n const element = this.store.getById(id);\n if (!element || (element.type !== 'note' && element.type !== 'text')) return;\n\n this.renderLoop.flush();\n\n const node = this.domNodeManager.getNode(id);\n if (node) {\n this.noteEditor.startEditing(node, id, this.store);\n }\n }\n\n private fitNoteHeight(elementId: string): void {\n const element = this.store.getById(elementId);\n if (!element || element.type !== 'note') return;\n if (isNoteContentEmpty(element.text)) return;\n const node = this.domNodeManager.getNode(elementId);\n if (!node) return;\n const measured = node.scrollHeight;\n if (measured > element.size.h) {\n this.store.update(elementId, { size: { w: element.size.w, h: measured } });\n }\n }\n\n private onTextEditStop(elementId: string): void {\n const element = this.store.getById(elementId);\n if (!element) return;\n\n if (element.type === 'note') {\n if (isNoteContentEmpty(element.text)) {\n this.store.remove(elementId);\n return;\n }\n this.fitNoteHeight(elementId);\n return;\n }\n\n if (element.type !== 'text') return;\n\n if (!element.text || element.text.trim() === '') {\n this.store.remove(elementId);\n return;\n }\n\n const node = this.domNodeManager.getNode(elementId);\n if (node && 'size' in element) {\n const measured = node.scrollHeight;\n if (measured !== element.size.h) {\n this.store.update(elementId, { size: { w: element.size.w, h: measured } });\n }\n }\n }\n\n private onTapDown = (e: PointerEvent): void => {\n this.tapDownX = e.clientX;\n this.tapDownY = e.clientY;\n };\n\n private 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.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.wrapper.getBoundingClientRect();\n const screen = { x: e.clientX - rect.left, y: e.clientY - rect.top };\n const world = this.camera.screenToWorld(screen);\n const hit = this.hitTestWorld(world);\n if (hit?.type === 'html') {\n this.interactMode.startInteracting(hit.id);\n }\n };\n\n private hitTestWorld(world: { x: number; y: number }): CanvasElement | null {\n const candidates = this.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 stopInteracting(): void {\n this.interactMode.stopInteracting();\n }\n\n private onDragOver = (e: DragEvent): void => {\n e.preventDefault();\n };\n\n private onDrop = (e: DragEvent): void => {\n e.preventDefault();\n const rect = this.wrapper.getBoundingClientRect();\n const screenPos = { x: e.clientX - rect.left, y: e.clientY - rect.top };\n const worldPos = this.camera.screenToWorld(screenPos);\n\n if (this.dropHandler) {\n this.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.addImage(src, worldPos);\n };\n reader.readAsDataURL(file);\n }\n };\n\n private unbindArrowsFrom(removedElement: CanvasElement): void {\n const boundArrows = findBoundArrows(removedElement.id, this.store);\n const bounds = getElementBounds(removedElement);\n\n for (const arrow of boundArrows) {\n const updates: Partial<ArrowElement> = {};\n\n if (arrow.fromBinding?.elementId === removedElement.id) {\n updates.fromBinding = undefined;\n if (bounds) {\n const angle = getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 0);\n const rayTarget = {\n x: arrow.from.x + Math.cos(angle) * 1000,\n y: arrow.from.y + Math.sin(angle) * 1000,\n };\n const edge = getEdgeIntersection(bounds, rayTarget);\n updates.from = edge;\n updates.position = edge;\n }\n }\n\n if (arrow.toBinding?.elementId === removedElement.id) {\n updates.toBinding = undefined;\n if (bounds) {\n const angle = getArrowTangentAngle(arrow.from, arrow.to, arrow.bend, 1);\n const rayTarget = {\n x: arrow.to.x - Math.cos(angle) * 1000,\n y: arrow.to.y - Math.sin(angle) * 1000,\n };\n updates.to = getEdgeIntersection(bounds, rayTarget);\n }\n }\n\n if (Object.keys(updates).length > 0) {\n this.store.update(arrow.id, updates);\n }\n }\n }\n\n private createWrapper(): HTMLDivElement {\n const el = document.createElement('div');\n Object.assign(el.style, {\n position: 'relative',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n overscrollBehavior: 'none',\n userSelect: 'none',\n webkitUserSelect: 'none',\n });\n return el;\n }\n\n private createCanvas(): HTMLCanvasElement {\n const el = document.createElement('canvas');\n Object.assign(el.style, {\n position: 'absolute',\n top: '0',\n left: '0',\n width: '100%',\n height: '100%',\n });\n return el;\n }\n\n private createDomLayer(): HTMLDivElement {\n const el = document.createElement('div');\n Object.assign(el.style, {\n position: 'absolute',\n top: '0',\n left: '0',\n width: '100%',\n height: '100%',\n pointerEvents: 'none',\n transformOrigin: '0 0',\n });\n return el;\n }\n\n private applyCameraTransform(): void {\n this.domLayer.style.transform = this.camera.toCSSTransform();\n }\n\n private syncCanvasSize(): void {\n const rect = this.container.getBoundingClientRect();\n const dpr = typeof devicePixelRatio !== 'undefined' ? devicePixelRatio : 1;\n this.renderLoop.setCanvasSize(rect.width * dpr, rect.height * dpr);\n this.requestRender();\n }\n\n private syncGridContext(): void {\n const grid = this.store.getElementsByType('grid')[0];\n if (grid) {\n this.toolContext.gridSize = grid.cellSize;\n this.toolContext.gridType = grid.gridType;\n this.toolContext.hexOrientation = grid.hexOrientation;\n } else {\n this.toolContext.gridSize = this._gridSize;\n this.toolContext.gridType = undefined;\n this.toolContext.hexOrientation = undefined;\n }\n this.notifyGridChangeListeners();\n }\n\n private notifyGridChangeListeners(): void {\n const info = this.getGridInfo();\n for (const listener of this.gridChangeListeners) {\n listener(info);\n }\n }\n\n private observeResize(): void {\n if (typeof ResizeObserver === 'undefined') return;\n this.resizeObserver = new ResizeObserver(() => this.syncCanvasSize());\n this.resizeObserver.observe(this.container);\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 color?: string;\r\n width?: number;\r\n smoothing?: number;\r\n minPointDistance?: number;\r\n progressiveSimplifyThreshold?: number;\r\n}\r\n\r\nconst MIN_POINTS_FOR_STROKE = 2;\r\nconst DEFAULT_SMOOTHING = 1.5;\r\nconst DEFAULT_PRESSURE = 0.5;\r\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 = 'pencil';\r\n private drawing = false;\r\n private points: StrokePoint[] = [];\r\n private color: string;\r\n private width: number;\r\n private smoothing: number;\r\n private minPointDistance: number;\r\n private progressiveThreshold: number;\r\n private nextSimplifyAt: number;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: PencilToolOptions = {}) {\r\n this.color = options.color ?? '#000000';\r\n this.width = options.width ?? 2;\r\n this.smoothing = options.smoothing ?? DEFAULT_SMOOTHING;\r\n 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 }\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 };\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 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 });\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 ctx.globalAlpha = 0.8;\r\n\r\n const segments = smoothToSegments(this.points);\r\n for (const seg of segments) {\r\n const w =\r\n (pressureToWidth(seg.start.pressure, this.width) +\r\n pressureToWidth(seg.end.pressure, this.width)) /\r\n 2;\r\n ctx.lineWidth = w;\r\n ctx.beginPath();\r\n ctx.moveTo(seg.start.x, seg.start.y);\r\n ctx.bezierCurveTo(seg.cp1.x, seg.cp1.y, seg.cp2.x, seg.cp2.y, seg.end.x, seg.end.y);\r\n ctx.stroke();\r\n }\r\n\r\n ctx.restore();\r\n }\r\n}\r\n","import type { Point } from '../core/types';\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 { 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\n\r\nexport interface EraserToolOptions {\r\n radius?: number;\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 readonly radius: number;\r\n private readonly cursor: string;\r\n\r\n constructor(options: EraserToolOptions = {}) {\r\n this.radius = options.radius ?? DEFAULT_RADIUS;\r\n this.cursor = makeEraserCursor(this.radius);\r\n }\r\n\r\n getOptions(): EraserToolOptions {\r\n return { radius: this.radius };\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 queryBounds: Bounds = {\r\n x: world.x - this.radius,\r\n y: world.y - this.radius,\r\n w: this.radius * 2,\r\n h: this.radius * 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)) {\r\n ctx.store.remove(el.id);\r\n erased = true;\r\n }\r\n }\r\n\r\n if (erased) ctx.requestRender();\r\n }\r\n\r\n private strokeIntersects(stroke: StrokeElement, point: Point): boolean {\r\n return hitTestStroke(stroke, point, this.radius);\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { ArrowElement, CanvasElement } from '../elements/types';\r\nimport type { ToolContext } from './types';\r\nimport { getArrowMidpoint, getBendFromPoint } from '../elements/arrow-geometry';\r\nimport { findBindTarget, getElementCenter } from '../elements/arrow-binding';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\n\r\nconst BIND_THRESHOLD = 20;\r\n\r\nexport type ArrowHandle = 'start' | 'mid' | 'end';\r\n\r\nconst HANDLE_RADIUS = 5;\r\nconst HANDLE_HIT_PADDING = 4;\r\n\r\nconst ARROW_HANDLE_CURSORS: Record<ArrowHandle, string> = {\r\n start: 'crosshair',\r\n end: 'crosshair',\r\n mid: 'grab',\r\n};\r\n\r\nexport function getArrowHandleCursor(handle: ArrowHandle, active: boolean): string {\r\n if (handle === 'mid' && active) return 'grabbing';\r\n return ARROW_HANDLE_CURSORS[handle];\r\n}\r\n\r\nexport function getArrowHandlePositions(arrow: ArrowElement): [ArrowHandle, Point][] {\r\n const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);\r\n return [\r\n ['start', arrow.from],\r\n ['mid', mid],\r\n ['end', arrow.to],\r\n ];\r\n}\r\n\r\nexport function hitTestArrowHandles(\r\n world: Point,\r\n selectedIds: string[],\r\n ctx: ToolContext,\r\n): { elementId: string; handle: ArrowHandle } | null {\r\n if (selectedIds.length === 0) return null;\r\n\r\n const zoom = ctx.camera.zoom;\r\n const hitRadius = (HANDLE_RADIUS + HANDLE_HIT_PADDING) / zoom;\r\n\r\n for (const id of selectedIds) {\r\n const el = ctx.store.getById(id);\r\n if (!el || el.type !== 'arrow') continue;\r\n\r\n const handles = getArrowHandlePositions(el);\r\n for (const [handle, pos] of handles) {\r\n const dx = world.x - pos.x;\r\n const dy = world.y - pos.y;\r\n if (dx * dx + dy * dy <= hitRadius * hitRadius) {\r\n return { elementId: id, handle };\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\nexport function applyArrowHandleDrag(\r\n handle: ArrowHandle,\r\n elementId: string,\r\n world: Point,\r\n ctx: ToolContext,\r\n): void {\r\n const el = ctx.store.getById(elementId);\r\n if (!el || el.type !== 'arrow') return;\r\n\r\n const threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n\r\n const layerFilter = (candidate: CanvasElement) => candidate.layerId === el.layerId;\r\n\r\n switch (handle) {\r\n case 'start': {\r\n const excludeId = el.toBinding?.elementId;\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);\r\n if (target) {\r\n const center = getElementCenter(target);\r\n ctx.store.update(elementId, {\r\n from: center,\r\n position: center,\r\n fromBinding: { elementId: target.id },\r\n });\r\n } else {\r\n ctx.store.update(elementId, {\r\n from: { x: world.x, y: world.y },\r\n position: { x: world.x, y: world.y },\r\n fromBinding: undefined,\r\n });\r\n }\r\n break;\r\n }\r\n case 'end': {\r\n const excludeId = el.fromBinding?.elementId;\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);\r\n if (target) {\r\n const center = getElementCenter(target);\r\n ctx.store.update(elementId, {\r\n to: center,\r\n toBinding: { elementId: target.id },\r\n });\r\n } else {\r\n ctx.store.update(elementId, {\r\n to: { x: world.x, y: world.y },\r\n toBinding: undefined,\r\n });\r\n }\r\n break;\r\n }\r\n case 'mid': {\r\n const bend = getBendFromPoint(el.from, el.to, world);\r\n ctx.store.update(elementId, { bend });\r\n break;\r\n }\r\n }\r\n\r\n ctx.requestRender();\r\n}\r\n\r\nexport function getArrowHandleDragTarget(\r\n handle: ArrowHandle,\r\n elementId: string,\r\n world: Point,\r\n ctx: ToolContext,\r\n): { x: number; y: number; w: number; h: number } | null {\r\n if (handle === 'mid') return null;\r\n\r\n const el = ctx.store.getById(elementId);\r\n if (!el || el.type !== 'arrow') return null;\r\n\r\n const threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n const excludeId = handle === 'start' ? el.toBinding?.elementId : el.fromBinding?.elementId;\r\n const layerFilter = (candidate: CanvasElement) => candidate.layerId === el.layerId;\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, layerFilter);\r\n if (!target) return null;\r\n\r\n return getElementBounds(target);\r\n}\r\n\r\nexport function renderArrowHandles(\r\n canvasCtx: CanvasRenderingContext2D,\r\n arrow: ArrowElement,\r\n zoom: number,\r\n): void {\r\n const radius = HANDLE_RADIUS / zoom;\r\n const handles = getArrowHandlePositions(arrow);\r\n\r\n canvasCtx.setLineDash([]);\r\n canvasCtx.lineWidth = 1.5 / zoom;\r\n\r\n for (const [handle, pos] of handles) {\r\n canvasCtx.fillStyle = handle === 'mid' ? '#2196F3' : '#ffffff';\r\n canvasCtx.strokeStyle = '#2196F3';\r\n\r\n canvasCtx.beginPath();\r\n canvasCtx.arc(pos.x, pos.y, radius, 0, Math.PI * 2);\r\n canvasCtx.fill();\r\n canvasCtx.stroke();\r\n }\r\n}\r\n","import type { Bounds, Point } from '../core/types';\nimport type { Tool, ToolContext, PointerState } from './types';\nimport { smartSnap } from '../core/snap';\nimport type { CanvasElement, ArrowElement } from '../elements/types';\nimport { isNearBezier } from '../elements/arrow-geometry';\nimport { findBoundArrows, updateBoundArrow } from '../elements/arrow-binding';\nimport { getElementBounds } from '../elements/element-bounds';\nimport { hitTestStroke } from '../elements/stroke-hit';\nimport {\n type ArrowHandle,\n hitTestArrowHandles,\n applyArrowHandleDrag,\n renderArrowHandles,\n getArrowHandleCursor,\n getArrowHandleDragTarget,\n} from './arrow-handles';\n\ntype HandlePosition = 'nw' | 'ne' | 'sw' | 'se';\n\nconst HANDLE_SIZE = 8;\nconst HANDLE_HIT_PADDING = 4;\nconst SELECTION_PAD = 4;\nconst MIN_ELEMENT_SIZE = 20;\n\nconst HANDLE_CURSORS: Record<HandlePosition, string> = {\n nw: 'nwse-resize',\n se: 'nwse-resize',\n ne: 'nesw-resize',\n sw: 'nesw-resize',\n};\n\ntype Mode =\n | { type: 'idle' }\n | { type: 'dragging' }\n | { type: 'marquee'; start: Point }\n | { type: 'resizing'; elementId: string; handle: HandlePosition }\n | { type: 'resizing-template'; elementId: string }\n | { type: 'arrow-handle'; elementId: string; handle: ArrowHandle };\n\nexport class SelectTool implements Tool {\n readonly name = 'select';\n private _selectedIds: string[] = [];\n private selectionListeners = new Set<() => void>();\n private mode: Mode = { type: 'idle' };\n private lastWorld: Point = { x: 0, y: 0 };\n private currentWorld: Point = { x: 0, y: 0 };\n private ctx: ToolContext | null = null;\n private pendingSingleSelectId: string | null = null;\n private hasDragged = false;\n private resizeAspectRatio = 0;\n private hoveredId: string | null = null;\n\n get selectedIds(): string[] {\n return this._selectedIds;\n }\n\n onSelectionChange(listener: () => void): () => void {\n this.selectionListeners.add(listener);\n return () => {\n this.selectionListeners.delete(listener);\n };\n }\n\n private setSelectedIds(ids: string[]): void {\n const prev = this._selectedIds;\n if (prev.length === ids.length && prev.every((id, i) => id === ids[i])) return;\n this._selectedIds = ids;\n for (const listener of this.selectionListeners) listener();\n }\n\n setSelection(ids: string[]): void {\n this.setSelectedIds(ids);\n this.ctx?.requestRender();\n }\n\n get isMarqueeActive(): boolean {\n return this.mode.type === 'marquee';\n }\n\n onActivate(ctx: ToolContext): void {\n this.ctx = ctx;\n }\n\n onDeactivate(ctx: ToolContext): void {\n this.setSelectedIds([]);\n this.mode = { type: 'idle' };\n this.hoveredId = null;\n ctx.setCursor?.('default');\n }\n\n private snap(point: Point, ctx: ToolContext): Point {\n return smartSnap(point, ctx);\n }\n\n onPointerDown(state: PointerState, ctx: ToolContext): void {\n this.ctx = ctx;\n this.setHovered(null, ctx);\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\n this.lastWorld = this.snap(world, ctx);\n this.currentWorld = world;\n\n const arrowHit = hitTestArrowHandles(world, this._selectedIds, ctx);\n if (arrowHit) {\n this.mode = {\n type: 'arrow-handle',\n elementId: arrowHit.elementId,\n handle: arrowHit.handle,\n };\n ctx.requestRender();\n return;\n }\n\n const templateResizeHit = this.hitTestTemplateResizeHandle(world, ctx);\n if (templateResizeHit) {\n this.mode = { type: 'resizing-template', elementId: templateResizeHit };\n ctx.requestRender();\n return;\n }\n\n const resizeHit = this.hitTestResizeHandle(world, ctx);\n if (resizeHit) {\n const el = ctx.store.getById(resizeHit.elementId);\n if (el && 'size' in el) {\n this.resizeAspectRatio = el.size.h > 0 ? el.size.w / el.size.h : 0;\n this.mode = {\n type: 'resizing',\n elementId: resizeHit.elementId,\n handle: resizeHit.handle,\n };\n ctx.requestRender();\n return;\n }\n }\n\n this.pendingSingleSelectId = null;\n this.hasDragged = false;\n const hit = this.hitTest(world, ctx);\n if (hit) {\n const alreadySelected = this._selectedIds.includes(hit.id);\n if (state.shiftKey) {\n if (alreadySelected) {\n this.setSelectedIds(this._selectedIds.filter((id) => id !== hit.id));\n this.mode = { type: 'idle' };\n } else {\n this.setSelectedIds([...this._selectedIds, hit.id]);\n this.mode = hit.locked ? { type: 'idle' } : { type: 'dragging' };\n }\n } else {\n if (!alreadySelected) {\n this.setSelectedIds([hit.id]);\n } else if (this._selectedIds.length > 1) {\n this.pendingSingleSelectId = hit.id;\n }\n this.mode = hit.locked ? { type: 'idle' } : { type: 'dragging' };\n }\n } else {\n this.setSelectedIds([]);\n this.mode = { type: 'marquee', start: world };\n }\n\n ctx.requestRender();\n }\n\n onPointerMove(state: PointerState, ctx: ToolContext): void {\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\n this.currentWorld = world;\n\n if (this.mode.type === 'arrow-handle') {\n ctx.setCursor?.(getArrowHandleCursor(this.mode.handle, true));\n applyArrowHandleDrag(this.mode.handle, this.mode.elementId, world, ctx);\n return;\n }\n\n if (this.mode.type === 'resizing-template') {\n ctx.setCursor?.('nwse-resize');\n this.handleTemplateResize(world, ctx);\n return;\n }\n\n if (this.mode.type === 'resizing') {\n ctx.setCursor?.(HANDLE_CURSORS[this.mode.handle]);\n this.handleResize(world, ctx, state.shiftKey);\n return;\n }\n\n if (this.mode.type === 'dragging' && this._selectedIds.length > 0) {\n this.hasDragged = true;\n ctx.setCursor?.('move');\n const snapped = this.snap(world, ctx);\n const dx = snapped.x - this.lastWorld.x;\n const dy = snapped.y - this.lastWorld.y;\n this.lastWorld = snapped;\n\n for (const id of this._selectedIds) {\n const el = ctx.store.getById(id);\n if (!el || el.locked) continue;\n\n if (el.type === 'arrow') {\n if (el.fromBinding || el.toBinding) {\n continue;\n }\n\n ctx.store.update(id, {\n position: { x: el.position.x + dx, y: el.position.y + dy },\n from: { x: el.from.x + dx, y: el.from.y + dy },\n to: { x: el.to.x + dx, y: el.to.y + dy },\n });\n } else if (ctx.gridType && 'size' in el) {\n const centerX = el.position.x + el.size.w / 2 + dx;\n const centerY = el.position.y + el.size.h / 2 + dy;\n const snappedCenter = this.snap({ x: centerX, y: centerY }, ctx);\n ctx.store.update(id, {\n position: {\n x: snappedCenter.x - el.size.w / 2,\n y: snappedCenter.y - el.size.h / 2,\n },\n });\n } else {\n ctx.store.update(id, {\n position: { x: el.position.x + dx, y: el.position.y + dy },\n });\n }\n }\n\n this.updateArrowsBoundTo(this._selectedIds, ctx);\n\n ctx.requestRender();\n return;\n }\n\n if (this.mode.type === 'marquee') {\n ctx.setCursor?.('crosshair');\n ctx.requestRender();\n return;\n }\n\n this.updateHoverCursor(world, ctx);\n }\n\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\n if (this.mode.type === 'marquee') {\n const rect = this.getMarqueeRect();\n if (rect) {\n this.setSelectedIds(this.findElementsInRect(rect, ctx));\n }\n ctx.requestRender();\n }\n\n if (!this.hasDragged && this.pendingSingleSelectId !== null) {\n this.setSelectedIds([this.pendingSingleSelectId]);\n }\n this.pendingSingleSelectId = null;\n this.hasDragged = false;\n\n const resizedNoteId = this.mode.type === 'resizing' ? this.mode.elementId : null;\n\n this.mode = { type: 'idle' };\n ctx.setCursor?.('default');\n\n if (resizedNoteId !== null) {\n const el = ctx.store.getById(resizedNoteId);\n // Runs during tool pointer-up, inside the InputHandler resize transaction, so the\n // height fit coalesces into the same undo step as the resize.\n if (el?.type === 'note') ctx.fitNoteHeight?.(resizedNoteId);\n }\n }\n\n onHover(state: PointerState, ctx: ToolContext): void {\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\n const hoverId = this.updateHoverCursor(world, ctx);\n this.setHovered(hoverId, ctx);\n }\n\n renderOverlay(canvasCtx: CanvasRenderingContext2D): void {\n this.renderMarquee(canvasCtx);\n this.renderSelectionBoxes(canvasCtx);\n\n if (this.mode.type === 'arrow-handle' && this.ctx) {\n const target = getArrowHandleDragTarget(\n this.mode.handle,\n this.mode.elementId,\n this.currentWorld,\n this.ctx,\n );\n if (target) {\n canvasCtx.save();\n canvasCtx.strokeStyle = '#2196F3';\n canvasCtx.lineWidth = 2 / this.ctx.camera.zoom;\n canvasCtx.setLineDash([]);\n canvasCtx.strokeRect(target.x, target.y, target.w, target.h);\n canvasCtx.restore();\n }\n }\n\n if (this.hoveredId && this.ctx && this.mode.type === 'idle') {\n if (!this._selectedIds.includes(this.hoveredId)) {\n const el = this.ctx.store.getById(this.hoveredId);\n if (el) {\n const b = getElementBounds(el);\n if (b) {\n canvasCtx.save();\n canvasCtx.strokeStyle = '#2196F3';\n canvasCtx.globalAlpha = 0.35;\n canvasCtx.lineWidth = 1.5 / this.ctx.camera.zoom;\n canvasCtx.setLineDash([]);\n canvasCtx.strokeRect(b.x, b.y, b.w, b.h);\n canvasCtx.restore();\n }\n }\n }\n }\n }\n\n private updateArrowsBoundTo(ids: Iterable<string>, ctx: ToolContext): void {\n const movedNonArrowIds = new Set<string>();\n for (const id of ids) {\n const el = ctx.store.getById(id);\n if (el && el.type !== 'arrow') movedNonArrowIds.add(id);\n }\n if (movedNonArrowIds.size === 0) return;\n const updatedArrows = new Set<string>();\n for (const id of movedNonArrowIds) {\n const boundArrows = findBoundArrows(id, ctx.store);\n for (const ba of boundArrows) {\n if (updatedArrows.has(ba.id)) continue;\n updatedArrows.add(ba.id);\n const updates = updateBoundArrow(ba, ctx.store);\n if (updates) ctx.store.update(ba.id, updates);\n }\n }\n }\n\n nudgeSelection(dx: number, dy: number, ctx: ToolContext): boolean {\n let moved = false;\n for (const id of this._selectedIds) {\n const el = ctx.store.getById(id);\n if (!el || el.locked) continue;\n\n if (el.type === 'arrow') {\n if (el.fromBinding || el.toBinding) continue;\n ctx.store.update(id, {\n position: { x: el.position.x + dx, y: el.position.y + dy },\n from: { x: el.from.x + dx, y: el.from.y + dy },\n to: { x: el.to.x + dx, y: el.to.y + dy },\n });\n } else {\n ctx.store.update(id, {\n position: { x: el.position.x + dx, y: el.position.y + dy },\n });\n }\n moved = true;\n }\n\n if (moved) {\n this.updateArrowsBoundTo(this._selectedIds, ctx);\n ctx.requestRender();\n }\n return moved;\n }\n\n private updateHoverCursor(world: Point, ctx: ToolContext): string | null {\n const arrowHit = hitTestArrowHandles(world, this._selectedIds, ctx);\n if (arrowHit) {\n ctx.setCursor?.(getArrowHandleCursor(arrowHit.handle, false));\n return null;\n }\n\n const templateResizeHit = this.hitTestTemplateResizeHandle(world, ctx);\n if (templateResizeHit) {\n ctx.setCursor?.('nwse-resize');\n return null;\n }\n\n const resizeHit = this.hitTestResizeHandle(world, ctx);\n if (resizeHit) {\n ctx.setCursor?.(HANDLE_CURSORS[resizeHit.handle]);\n return null;\n }\n\n const hit = this.hitTest(world, ctx);\n ctx.setCursor?.(hit ? 'move' : 'default');\n return hit ? hit.id : null;\n }\n\n private setHovered(id: string | null, ctx: ToolContext): void {\n if (this.hoveredId === id) return;\n this.hoveredId = id;\n ctx.requestRender();\n }\n\n private handleResize(world: Point, ctx: ToolContext, shiftKey = false): void {\n if (this.mode.type !== 'resizing') return;\n\n const el = ctx.store.getById(this.mode.elementId);\n if (!el || !('size' in el) || el.locked) return;\n\n const { handle } = this.mode;\n const dx = world.x - this.lastWorld.x;\n const dy = world.y - this.lastWorld.y;\n this.lastWorld = world;\n\n let { x, y, w, h } = { x: el.position.x, y: el.position.y, w: el.size.w, h: el.size.h };\n\n switch (handle) {\n case 'se':\n w += dx;\n h += dy;\n break;\n case 'sw':\n x += dx;\n w -= dx;\n h += dy;\n break;\n case 'ne':\n y += dy;\n w += dx;\n h -= dy;\n break;\n case 'nw':\n x += dx;\n y += dy;\n w -= dx;\n h -= dy;\n break;\n }\n\n if (shiftKey && this.resizeAspectRatio > 0) {\n const absDw = Math.abs(w - el.size.w);\n const absDh = Math.abs(h - el.size.h);\n if (absDw >= absDh) {\n h = w / this.resizeAspectRatio;\n } else {\n w = h * this.resizeAspectRatio;\n }\n if (handle === 'nw' || handle === 'sw') {\n x = el.position.x + el.size.w - w;\n }\n if (handle === 'nw' || handle === 'ne') {\n y = el.position.y + el.size.h - h;\n }\n }\n\n if (w < MIN_ELEMENT_SIZE) {\n if (handle === 'nw' || handle === 'sw') x = el.position.x + el.size.w - MIN_ELEMENT_SIZE;\n w = MIN_ELEMENT_SIZE;\n }\n if (h < MIN_ELEMENT_SIZE) {\n if (handle === 'nw' || handle === 'ne') y = el.position.y + el.size.h - MIN_ELEMENT_SIZE;\n h = MIN_ELEMENT_SIZE;\n }\n\n ctx.store.update(this.mode.elementId, {\n position: { x, y },\n size: { w, h },\n });\n\n this.updateArrowsBoundTo([this.mode.elementId], ctx);\n\n ctx.requestRender();\n }\n\n private hitTestResizeHandle(\n world: Point,\n ctx: ToolContext,\n ): { elementId: string; handle: HandlePosition } | null {\n if (this._selectedIds.length === 0) return null;\n\n const zoom = ctx.camera.zoom;\n const handleHalf = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / zoom;\n\n for (const id of this._selectedIds) {\n const el = ctx.store.getById(id);\n if (!el || !('size' in el)) continue;\n\n const bounds = getElementBounds(el);\n if (!bounds) continue;\n\n const corners = this.getHandlePositions(bounds);\n for (const [handle, pos] of corners) {\n if (Math.abs(world.x - pos.x) <= handleHalf && Math.abs(world.y - pos.y) <= handleHalf) {\n return { elementId: id, handle };\n }\n }\n }\n\n return null;\n }\n\n private getHandlePositions(bounds: Bounds): [HandlePosition, Point][] {\n return [\n ['nw', { x: bounds.x, y: bounds.y }],\n ['ne', { x: bounds.x + bounds.w, y: bounds.y }],\n ['sw', { x: bounds.x, y: bounds.y + bounds.h }],\n ['se', { x: bounds.x + bounds.w, y: bounds.y + bounds.h }],\n ];\n }\n\n private renderMarquee(canvasCtx: CanvasRenderingContext2D): void {\n if (this.mode.type !== 'marquee') return;\n\n const rect = this.getMarqueeRect();\n if (!rect) return;\n\n canvasCtx.save();\n canvasCtx.strokeStyle = '#2196F3';\n canvasCtx.fillStyle = 'rgba(33, 150, 243, 0.08)';\n canvasCtx.lineWidth = 1;\n canvasCtx.setLineDash([4, 4]);\n canvasCtx.strokeRect(rect.x, rect.y, rect.w, rect.h);\n canvasCtx.fillRect(rect.x, rect.y, rect.w, rect.h);\n canvasCtx.restore();\n }\n\n private renderSelectionBoxes(canvasCtx: CanvasRenderingContext2D): void {\n if (this._selectedIds.length === 0 || !this.ctx) return;\n\n const zoom = this.ctx.camera.zoom;\n const handleWorldSize = HANDLE_SIZE / zoom;\n\n canvasCtx.save();\n canvasCtx.strokeStyle = '#2196F3';\n canvasCtx.lineWidth = 1.5 / zoom;\n canvasCtx.setLineDash([4 / zoom, 4 / zoom]);\n\n for (const id of this._selectedIds) {\n const el = this.ctx.store.getById(id);\n if (!el) continue;\n\n if (el.type === 'arrow') {\n renderArrowHandles(canvasCtx, el, zoom);\n this.renderBindingHighlights(canvasCtx, el, zoom);\n continue;\n }\n\n const bounds = getElementBounds(el);\n if (!bounds) continue;\n\n const pad = SELECTION_PAD / zoom;\n canvasCtx.strokeRect(bounds.x - pad, bounds.y - pad, bounds.w + pad * 2, bounds.h + pad * 2);\n\n if ('size' in el) {\n canvasCtx.setLineDash([]);\n canvasCtx.fillStyle = '#ffffff';\n const corners = this.getHandlePositions(bounds);\n for (const [, pos] of corners) {\n canvasCtx.fillRect(\n pos.x - handleWorldSize / 2,\n pos.y - handleWorldSize / 2,\n handleWorldSize,\n handleWorldSize,\n );\n canvasCtx.strokeRect(\n pos.x - handleWorldSize / 2,\n pos.y - handleWorldSize / 2,\n handleWorldSize,\n handleWorldSize,\n );\n }\n canvasCtx.setLineDash([4 / zoom, 4 / zoom]);\n } else if (el.type === 'template') {\n canvasCtx.setLineDash([]);\n canvasCtx.fillStyle = '#ffffff';\n const hx = bounds.x + bounds.w;\n const hy = bounds.y + bounds.h;\n canvasCtx.fillRect(\n hx - handleWorldSize / 2,\n hy - handleWorldSize / 2,\n handleWorldSize,\n handleWorldSize,\n );\n canvasCtx.strokeRect(\n hx - handleWorldSize / 2,\n hy - handleWorldSize / 2,\n handleWorldSize,\n handleWorldSize,\n );\n canvasCtx.setLineDash([4 / zoom, 4 / zoom]);\n }\n }\n\n canvasCtx.restore();\n }\n\n private renderBindingHighlights(\n canvasCtx: CanvasRenderingContext2D,\n arrow: ArrowElement,\n zoom: number,\n ): void {\n if (!this.ctx) return;\n if (!arrow.fromBinding && !arrow.toBinding) return;\n\n const pad = SELECTION_PAD / zoom;\n\n canvasCtx.save();\n canvasCtx.strokeStyle = '#2196F3';\n canvasCtx.lineWidth = 2 / zoom;\n canvasCtx.setLineDash([]);\n\n const drawn = new Set<string>();\n for (const binding of [arrow.fromBinding, arrow.toBinding]) {\n if (!binding || drawn.has(binding.elementId)) continue;\n drawn.add(binding.elementId);\n\n const target = this.ctx.store.getById(binding.elementId);\n if (!target) continue;\n\n const bounds = getElementBounds(target);\n if (!bounds) continue;\n\n canvasCtx.strokeRect(bounds.x - pad, bounds.y - pad, bounds.w + pad * 2, bounds.h + pad * 2);\n }\n\n canvasCtx.restore();\n }\n\n private hitTestTemplateResizeHandle(world: Point, ctx: ToolContext): string | null {\n if (this._selectedIds.length === 0) return null;\n\n const zoom = ctx.camera.zoom;\n const handleHalf = (HANDLE_SIZE / 2 + HANDLE_HIT_PADDING) / zoom;\n\n for (const id of this._selectedIds) {\n const el = ctx.store.getById(id);\n if (!el || el.type !== 'template') continue;\n\n const bounds = getElementBounds(el);\n if (!bounds) continue;\n\n const hx = bounds.x + bounds.w;\n const hy = bounds.y + bounds.h;\n if (Math.abs(world.x - hx) <= handleHalf && Math.abs(world.y - hy) <= handleHalf) {\n return id;\n }\n }\n\n return null;\n }\n\n private handleTemplateResize(world: Point, ctx: ToolContext): void {\n if (this.mode.type !== 'resizing-template') return;\n\n const el = ctx.store.getById(this.mode.elementId);\n if (!el || el.type !== 'template' || el.locked) return;\n\n const dx = world.x - el.position.x;\n const dy = world.y - el.position.y;\n let newRadius = Math.sqrt(dx * dx + dy * dy);\n\n if (ctx.snapToGrid && ctx.gridSize && ctx.gridSize > 0) {\n const snapUnit = ctx.gridType === 'hex' ? Math.sqrt(3) * ctx.gridSize : ctx.gridSize;\n newRadius = Math.max(snapUnit, Math.round(newRadius / snapUnit) * snapUnit);\n }\n newRadius = Math.max(MIN_ELEMENT_SIZE, newRadius);\n\n const updates: Record<string, unknown> = { radius: newRadius };\n if (el.feetPerCell != null && ctx.gridSize && ctx.gridSize > 0) {\n const snapUnit = ctx.gridType === 'hex' ? Math.sqrt(3) * ctx.gridSize : ctx.gridSize;\n updates.radiusFeet = (newRadius / snapUnit) * el.feetPerCell;\n }\n\n ctx.store.update(this.mode.elementId, updates);\n ctx.requestRender();\n }\n\n private getMarqueeRect(): Bounds | null {\n if (this.mode.type !== 'marquee') return null;\n\n const { start } = this.mode;\n const end = this.currentWorld;\n const x = Math.min(start.x, end.x);\n const y = Math.min(start.y, end.y);\n const w = Math.abs(end.x - start.x);\n const h = Math.abs(end.y - start.y);\n\n if (w === 0 && h === 0) return null;\n return { x, y, w, h };\n }\n\n private findElementsInRect(marquee: Bounds, ctx: ToolContext): string[] {\n const candidates = ctx.store.queryRect(marquee);\n const ids: string[] = [];\n for (const el of candidates) {\n if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) continue;\n if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) continue;\n if (el.type === 'grid') continue;\n const bounds = getElementBounds(el);\n if (bounds && this.rectsOverlap(marquee, bounds)) {\n ids.push(el.id);\n }\n }\n return ids;\n }\n\n private rectsOverlap(a: Bounds, b: Bounds): boolean {\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;\n }\n\n private hitTest(world: Point, ctx: ToolContext): CanvasElement | null {\n // Inflate query by hit radius so strokes/arrows near the point are included\n const r = 10;\n const candidates = ctx.store\n .queryRect({ x: world.x - r, y: world.y - r, w: r * 2, h: r * 2 })\n .reverse();\n for (const el of candidates) {\n if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) continue;\n if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) continue;\n if (el.type === 'grid') continue;\n if (this.isInsideBounds(world, el)) return el;\n }\n return null;\n }\n\n private isInsideBounds(point: Point, el: CanvasElement): boolean {\n if (el.type === 'grid') return false;\n if ('size' in el) {\n const s = el.size;\n return (\n point.x >= el.position.x &&\n point.x <= el.position.x + s.w &&\n point.y >= el.position.y &&\n point.y <= el.position.y + s.h\n );\n }\n\n if (el.type === 'stroke') {\n return hitTestStroke(el, point, 10);\n }\n\n if (el.type === 'arrow') {\n return isNearBezier(point, el.from, el.to, el.bend, 10);\n }\n\n if (el.type === 'template') {\n const bounds = getElementBounds(el);\n if (!bounds) return false;\n return (\n point.x >= bounds.x &&\n point.x <= bounds.x + bounds.w &&\n point.y >= bounds.y &&\n point.y <= bounds.y + bounds.h\n );\n }\n\n return false;\n }\n}\n","import type { Point } from '../core/types';\r\nimport type { Binding, CanvasElement } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createArrow } from '../elements/element-factory';\r\nimport { findBindTarget, getElementCenter } from '../elements/arrow-binding';\r\nimport { getElementBounds } from '../elements/element-bounds';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nconst BIND_THRESHOLD = 20;\r\n\r\nexport interface ArrowToolOptions {\r\n color?: string;\r\n width?: number;\r\n}\r\n\r\nexport class ArrowTool implements Tool {\r\n readonly name = 'arrow';\r\n private drawing = false;\r\n private start: Point = { x: 0, y: 0 };\r\n private end: Point = { x: 0, y: 0 };\r\n private color: string;\r\n private width: number;\r\n private fromBinding: Binding | undefined;\r\n private fromTarget: CanvasElement | null = null;\r\n private toTarget: CanvasElement | null = null;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: ArrowToolOptions = {}) {\r\n this.color = options.color ?? '#000000';\r\n this.width = options.width ?? 2;\r\n }\r\n\r\n getOptions(): ArrowToolOptions {\r\n return { color: this.color, width: this.width };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n setOptions(options: ArrowToolOptions): void {\r\n if (options.color !== undefined) this.color = options.color;\r\n if (options.width !== undefined) this.width = options.width;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n\r\n private layerFilter(ctx: ToolContext): ((el: CanvasElement) => boolean) | undefined {\r\n const activeLayerId = ctx.activeLayerId;\r\n if (!activeLayerId && !ctx.isLayerVisible && !ctx.isLayerLocked) return undefined;\r\n return (el: CanvasElement) => {\r\n if (activeLayerId && el.layerId !== activeLayerId) return false;\r\n if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) return false;\r\n if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) return false;\r\n return true;\r\n };\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.drawing = true;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n const filter = this.layerFilter(ctx);\r\n\r\n const target = findBindTarget(world, ctx.store, threshold, undefined, filter);\r\n if (target) {\r\n this.start = getElementCenter(target);\r\n this.fromBinding = { elementId: target.id };\r\n this.fromTarget = target;\r\n } else {\r\n this.start = smartSnap(world, ctx);\r\n this.fromBinding = undefined;\r\n this.fromTarget = null;\r\n }\r\n this.end = { ...this.start };\r\n this.toTarget = null;\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const threshold = BIND_THRESHOLD / ctx.camera.zoom;\r\n const excludeId = this.fromBinding?.elementId;\r\n const filter = this.layerFilter(ctx);\r\n\r\n const target = findBindTarget(world, ctx.store, threshold, excludeId, filter);\r\n if (target) {\r\n this.end = getElementCenter(target);\r\n this.toTarget = target;\r\n } else {\r\n this.end = smartSnap(world, ctx);\r\n this.toTarget = null;\r\n }\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.drawing = false;\r\n\r\n if (this.start.x === this.end.x && this.start.y === this.end.y) return;\r\n\r\n const arrow = createArrow({\r\n from: this.start,\r\n to: this.end,\r\n position: this.start,\r\n color: this.color,\r\n width: this.width,\r\n fromBinding: this.fromBinding,\r\n toBinding: this.toTarget ? { elementId: this.toTarget.id } : undefined,\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(arrow);\r\n this.fromTarget = null;\r\n this.toTarget = null;\r\n ctx.requestRender();\r\n ctx.switchTool?.('select');\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (!this.drawing) return;\r\n if (this.start.x === this.end.x && this.start.y === this.end.y) return;\r\n\r\n ctx.save();\r\n\r\n if (this.fromTarget) {\r\n const bounds = getElementBounds(this.fromTarget);\r\n if (bounds) {\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.lineWidth = 2;\r\n ctx.setLineDash([]);\r\n ctx.strokeRect(bounds.x, bounds.y, bounds.w, bounds.h);\r\n }\r\n }\r\n\r\n if (this.toTarget) {\r\n const bounds = getElementBounds(this.toTarget);\r\n if (bounds) {\r\n ctx.strokeStyle = '#2196F3';\r\n ctx.lineWidth = 2;\r\n ctx.setLineDash([]);\r\n ctx.strokeRect(bounds.x, bounds.y, bounds.w, bounds.h);\r\n }\r\n }\r\n\r\n ctx.strokeStyle = this.color;\r\n ctx.lineWidth = this.width;\r\n ctx.lineCap = 'round';\r\n ctx.globalAlpha = 0.6;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(this.start.x, this.start.y);\r\n ctx.lineTo(this.end.x, this.end.y);\r\n ctx.stroke();\r\n\r\n const angle = Math.atan2(this.end.y - this.start.y, this.end.x - this.start.x);\r\n const headLen = 12;\r\n const headAngle = Math.PI / 6;\r\n\r\n ctx.fillStyle = this.color;\r\n ctx.beginPath();\r\n ctx.moveTo(this.end.x, this.end.y);\r\n ctx.lineTo(\r\n this.end.x - headLen * Math.cos(angle - headAngle),\r\n this.end.y - headLen * Math.sin(angle - headAngle),\r\n );\r\n ctx.lineTo(\r\n this.end.x - headLen * Math.cos(angle + headAngle),\r\n this.end.y - headLen * Math.sin(angle + headAngle),\r\n );\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n}\r\n","import type { Size } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createNote, DEFAULT_NOTE_FONT_SIZE } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nexport interface NoteToolOptions {\r\n backgroundColor?: string;\r\n textColor?: string;\r\n size?: Size;\r\n fontSize?: number;\r\n}\r\n\r\nexport class NoteTool implements Tool {\r\n readonly name = 'note';\r\n private backgroundColor: string;\r\n private textColor: string;\r\n private size: Size;\r\n private fontSize: number;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: NoteToolOptions = {}) {\r\n this.backgroundColor = options.backgroundColor ?? '#ffeb3b';\r\n this.textColor = options.textColor ?? '#000000';\r\n this.size = options.size ?? { w: 200, h: 100 };\r\n this.fontSize = options.fontSize ?? DEFAULT_NOTE_FONT_SIZE;\r\n }\r\n\r\n getOptions(): NoteToolOptions {\r\n return {\r\n backgroundColor: this.backgroundColor,\r\n textColor: this.textColor,\r\n size: { ...this.size },\r\n fontSize: this.fontSize,\r\n };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n setOptions(options: NoteToolOptions): void {\r\n if (options.backgroundColor !== undefined) this.backgroundColor = options.backgroundColor;\r\n if (options.textColor !== undefined) this.textColor = options.textColor;\r\n if (options.size !== undefined) this.size = options.size;\r\n if (options.fontSize !== undefined) this.fontSize = options.fontSize;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n\r\n onPointerDown(_state: PointerState, _ctx: ToolContext): void {\r\n // Note is placed on pointer up\r\n }\r\n\r\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\r\n // No drag behavior for note placement\r\n }\r\n\r\n onPointerUp(state: PointerState, ctx: ToolContext): void {\r\n let world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n world = smartSnap(world, ctx);\r\n const note = createNote({\r\n position: world,\r\n size: { ...this.size },\r\n backgroundColor: this.backgroundColor,\r\n textColor: this.textColor,\r\n fontSize: this.fontSize,\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(note);\r\n ctx.requestRender();\r\n\r\n ctx.switchTool?.('select');\r\n ctx.editElement?.(note.id);\r\n }\r\n}\r\n","import type { Tool, ToolContext, PointerState } from './types';\r\nimport { createText } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nexport interface TextToolOptions {\r\n fontSize?: number;\r\n color?: string;\r\n textAlign?: 'left' | 'center' | 'right';\r\n}\r\n\r\nexport class TextTool implements Tool {\r\n readonly name = 'text';\r\n private fontSize: number;\r\n private color: string;\r\n private textAlign: 'left' | 'center' | 'right';\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: TextToolOptions = {}) {\r\n this.fontSize = options.fontSize ?? 16;\r\n this.color = options.color ?? '#1a1a1a';\r\n this.textAlign = options.textAlign ?? 'left';\r\n }\r\n\r\n getOptions(): TextToolOptions {\r\n return { fontSize: this.fontSize, color: this.color, textAlign: this.textAlign };\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n setOptions(options: TextToolOptions): void {\r\n if (options.fontSize !== undefined) this.fontSize = options.fontSize;\r\n if (options.color !== undefined) this.color = options.color;\r\n if (options.textAlign !== undefined) this.textAlign = options.textAlign;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n\r\n onActivate(ctx: ToolContext): void {\r\n ctx.setCursor?.('text');\r\n }\r\n\r\n onDeactivate(ctx: ToolContext): void {\r\n ctx.setCursor?.('default');\r\n }\r\n\r\n onPointerDown(_state: PointerState, _ctx: ToolContext): void {\r\n // Text is placed on pointer up\r\n }\r\n\r\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\r\n // No drag behavior for text placement\r\n }\r\n\r\n onPointerUp(state: PointerState, ctx: ToolContext): void {\r\n let world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n world = smartSnap(world, ctx);\r\n const textEl = createText({\r\n position: world,\r\n fontSize: this.fontSize,\r\n color: this.color,\r\n textAlign: this.textAlign,\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(textEl);\r\n ctx.requestRender();\r\n\r\n ctx.switchTool?.('select');\r\n ctx.editElement?.(textEl.id);\r\n }\r\n}\r\n","import type { Size } from '../core/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createImage } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\nexport interface ImageToolOptions {\r\n size?: Size;\r\n}\r\n\r\nexport class ImageTool implements Tool {\r\n readonly name = 'image';\r\n private size: Size;\r\n private src: string | null = null;\r\n\r\n constructor(options: ImageToolOptions = {}) {\r\n this.size = options.size ?? { w: 300, h: 200 };\r\n }\r\n\r\n setSrc(src: string): void {\r\n this.src = src;\r\n }\r\n\r\n onPointerDown(_state: PointerState, _ctx: ToolContext): void {\r\n // No action on pointer down — image is placed on pointer up\r\n }\r\n\r\n onPointerMove(_state: PointerState, _ctx: ToolContext): void {\r\n // No action on pointer move\r\n }\r\n\r\n onPointerUp(state: PointerState, ctx: ToolContext): void {\r\n if (!this.src) return;\r\n\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n const snapped = smartSnap(world, ctx);\r\n const image = createImage({\r\n position: {\r\n x: snapped.x - this.size.w / 2,\r\n y: snapped.y - this.size.h / 2,\r\n },\r\n size: { ...this.size },\r\n src: this.src,\r\n });\r\n ctx.store.add(image);\r\n ctx.requestRender();\r\n\r\n this.src = null;\r\n ctx.switchTool?.('select');\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { ShapeKind } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createShape } from '../elements/element-factory';\r\nimport { smartSnap } from '../core/snap';\r\n\r\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 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 if (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 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 }\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) {\r\n const side = Math.max(w, h);\r\n w = side;\r\n h = side;\r\n x = this.end.x >= this.start.x ? this.start.x : this.start.x - side;\r\n y = this.end.y >= this.start.y ? this.start.y : this.start.y - side;\r\n }\r\n\r\n return { position: { x, y }, size: { w, h } };\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n\r\n private snap(point: Point, ctx: ToolContext): Point {\r\n return smartSnap(point, ctx);\r\n }\r\n\r\n private onKeyDown = (e: KeyboardEvent): void => {\r\n if (e.key === 'Shift') this.shiftHeld = true;\r\n };\r\n\r\n private onKeyUp = (e: KeyboardEvent): void => {\r\n if (e.key === 'Shift') this.shiftHeld = false;\r\n };\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { HexOrientation } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { snapPoint, snapToHexCenter } from '../core/snap';\r\nimport { getHexDistance } from '../elements/hex-fill';\r\n\r\nexport interface MeasureToolOptions {\r\n feetPerCell?: number;\r\n}\r\n\r\nexport interface Measurement {\r\n start: Point;\r\n end: Point;\r\n worldDistance: number;\r\n cells: number;\r\n feet: number;\r\n}\r\n\r\nexport class MeasureTool implements Tool {\r\n readonly name = 'measure';\r\n private start: Point | null = null;\r\n private end: Point | null = null;\r\n private gridSize = 1;\r\n private gridType: 'square' | 'hex' | undefined;\r\n private hexOrientation: HexOrientation | undefined;\r\n private feetPerCell: number;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: MeasureToolOptions = {}) {\r\n this.feetPerCell = options.feetPerCell ?? 5;\r\n }\r\n\r\n getOptions(): MeasureToolOptions {\r\n return { feetPerCell: this.feetPerCell };\r\n }\r\n\r\n setOptions(options: MeasureToolOptions): void {\r\n if (options.feetPerCell !== undefined) this.feetPerCell = options.feetPerCell;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.gridSize = ctx.gridSize ?? 1;\r\n this.gridType = ctx.gridType;\r\n this.hexOrientation = ctx.hexOrientation;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.start = this.snapToGrid(world, ctx);\r\n this.end = { ...this.start };\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.start) return;\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.end = this.snapToGrid(world, ctx);\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\r\n if (!this.start) return;\r\n this.start = null;\r\n this.end = null;\r\n ctx.requestRender();\r\n }\r\n\r\n onDeactivate(_ctx: ToolContext): void {\r\n this.start = null;\r\n this.end = null;\r\n }\r\n\r\n getMeasurement(): Measurement | null {\r\n if (!this.start || !this.end) return null;\r\n const dx = this.end.x - this.start.x;\r\n const dy = this.end.y - this.start.y;\r\n const worldDistance = Math.sqrt(dx * dx + dy * dy);\r\n\r\n let cells: number;\r\n if (this.gridType === 'hex' && this.hexOrientation) {\r\n cells = getHexDistance(this.start, this.end, this.gridSize, this.hexOrientation);\r\n } else {\r\n const snapUnit = this.gridSize;\r\n cells = worldDistance / snapUnit;\r\n }\r\n\r\n const feet = cells * this.feetPerCell;\r\n return {\r\n start: { ...this.start },\r\n end: { ...this.end },\r\n worldDistance,\r\n cells,\r\n feet,\r\n };\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n const m = this.getMeasurement();\r\n if (!m) return;\r\n\r\n ctx.save();\r\n\r\n ctx.strokeStyle = '#FF5722';\r\n ctx.setLineDash([8, 4]);\r\n ctx.lineWidth = 2;\r\n ctx.beginPath();\r\n ctx.moveTo(m.start.x, m.start.y);\r\n ctx.lineTo(m.end.x, m.end.y);\r\n ctx.stroke();\r\n\r\n ctx.setLineDash([]);\r\n ctx.fillStyle = '#FF5722';\r\n const dotRadius = 4;\r\n ctx.beginPath();\r\n ctx.arc(m.start.x, m.start.y, dotRadius, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.beginPath();\r\n ctx.arc(m.end.x, m.end.y, dotRadius, 0, Math.PI * 2);\r\n ctx.fill();\r\n\r\n const label = `${Math.round(m.feet)} ft`;\r\n const midX = (m.start.x + m.end.x) / 2;\r\n const midY = (m.start.y + m.end.y) / 2;\r\n ctx.font = '14px sans-serif';\r\n const metrics = ctx.measureText(label);\r\n const padX = 6;\r\n const padY = 4;\r\n const textH = 14;\r\n\r\n ctx.fillStyle = 'rgba(0, 0, 0, 0.75)';\r\n ctx.beginPath();\r\n ctx.roundRect(\r\n midX - metrics.width / 2 - padX,\r\n midY - textH / 2 - padY,\r\n metrics.width + padX * 2,\r\n textH + padY * 2,\r\n 4,\r\n );\r\n ctx.fill();\r\n\r\n ctx.fillStyle = '#FFFFFF';\r\n ctx.textAlign = 'center';\r\n ctx.textBaseline = 'middle';\r\n ctx.fillText(label, midX, midY);\r\n\r\n ctx.restore();\r\n }\r\n\r\n private snapToGrid(point: Point, ctx: ToolContext): Point {\r\n if (!ctx.gridSize) return point;\r\n if (ctx.gridType === 'hex' && ctx.hexOrientation) {\r\n return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);\r\n }\r\n if (ctx.gridType === 'square') {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n if (ctx.snapToGrid) {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n return point;\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n}\r\n","import type { Point } from '../core/types';\r\nimport type { TemplateShape, HexOrientation } from '../elements/types';\r\nimport type { Tool, ToolContext, PointerState } from './types';\r\nimport { createTemplate } from '../elements/element-factory';\r\nimport { snapPoint, snapToHexCenter } from '../core/snap';\r\nimport {\r\n getHexCellsInRadius,\r\n getHexCellsInCone,\r\n getHexCellsInLine,\r\n getHexCellsInSquare,\r\n drawHexPath,\r\n} from '../elements/hex-fill';\r\n\r\nexport interface TemplateToolOptions {\r\n templateShape?: TemplateShape;\r\n fillColor?: string;\r\n strokeColor?: string;\r\n strokeWidth?: number;\r\n opacity?: number;\r\n feetPerCell?: number;\r\n}\r\n\r\nexport class TemplateTool implements Tool {\r\n readonly name = 'template';\r\n private drawing = false;\r\n private origin: Point = { x: 0, y: 0 };\r\n private current: Point = { x: 0, y: 0 };\r\n private gridSize = 1;\r\n private gridType: 'square' | 'hex' | undefined;\r\n private hexOrientation: HexOrientation | undefined;\r\n private snapEnabled = false;\r\n private templateShape: TemplateShape;\r\n private fillColor: string;\r\n private strokeColor: string;\r\n private strokeWidth: number;\r\n private opacity: number;\r\n private feetPerCell: number;\r\n private optionListeners = new Set<() => void>();\r\n\r\n constructor(options: TemplateToolOptions = {}) {\r\n this.templateShape = options.templateShape ?? 'circle';\r\n this.fillColor = options.fillColor ?? 'rgba(255, 87, 34, 0.2)';\r\n this.strokeColor = options.strokeColor ?? '#FF5722';\r\n this.strokeWidth = options.strokeWidth ?? 2;\r\n this.opacity = options.opacity ?? 0.6;\r\n this.feetPerCell = options.feetPerCell ?? 5;\r\n }\r\n\r\n getOptions(): TemplateToolOptions {\r\n return {\r\n templateShape: this.templateShape,\r\n fillColor: this.fillColor,\r\n strokeColor: this.strokeColor,\r\n strokeWidth: this.strokeWidth,\r\n opacity: this.opacity,\r\n feetPerCell: this.feetPerCell,\r\n };\r\n }\r\n\r\n setOptions(options: TemplateToolOptions): void {\r\n if (options.templateShape !== undefined) this.templateShape = options.templateShape;\r\n if (options.fillColor !== undefined) this.fillColor = options.fillColor;\r\n if (options.strokeColor !== undefined) this.strokeColor = options.strokeColor;\r\n if (options.strokeWidth !== undefined) this.strokeWidth = options.strokeWidth;\r\n if (options.opacity !== undefined) this.opacity = options.opacity;\r\n if (options.feetPerCell !== undefined) this.feetPerCell = options.feetPerCell;\r\n this.notifyOptionsChange();\r\n }\r\n\r\n onOptionsChange(listener: () => void): () => void {\r\n this.optionListeners.add(listener);\r\n return () => this.optionListeners.delete(listener);\r\n }\r\n\r\n onPointerDown(state: PointerState, ctx: ToolContext): void {\r\n this.drawing = true;\r\n this.gridSize = ctx.gridSize ?? 1;\r\n this.gridType = ctx.gridType;\r\n this.hexOrientation = ctx.hexOrientation;\r\n this.snapEnabled = !!ctx.gridType || (ctx.snapToGrid ?? false);\r\n const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n this.origin = this.snapToGrid(world, ctx);\r\n this.current = { ...this.origin };\r\n }\r\n\r\n onPointerMove(state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.current = ctx.camera.screenToWorld({ x: state.x, y: state.y });\r\n ctx.requestRender();\r\n }\r\n\r\n onPointerUp(_state: PointerState, ctx: ToolContext): void {\r\n if (!this.drawing) return;\r\n this.drawing = false;\r\n\r\n const radius = this.computeRadius();\r\n if (radius <= 0) return;\r\n\r\n const angle = this.computeAngle();\r\n const gridSize = ctx.gridSize;\r\n const snapUnit =\r\n gridSize && gridSize > 0 ? (ctx.gridType === 'hex' ? Math.sqrt(3) * gridSize : gridSize) : 0;\r\n const cells = snapUnit > 0 ? radius / snapUnit : 0;\r\n const radiusFeet = cells * this.feetPerCell;\r\n\r\n const element = createTemplate({\r\n position: { ...this.origin },\r\n templateShape: this.templateShape,\r\n radius,\r\n angle,\r\n fillColor: this.fillColor,\r\n strokeColor: this.strokeColor,\r\n strokeWidth: this.strokeWidth,\r\n opacity: this.opacity,\r\n feetPerCell: this.feetPerCell,\r\n radiusFeet: radiusFeet > 0 ? radiusFeet : undefined,\r\n layerId: ctx.activeLayerId ?? '',\r\n });\r\n ctx.store.add(element);\r\n ctx.requestRender();\r\n ctx.switchTool?.('select');\r\n }\r\n\r\n onDeactivate(_ctx: ToolContext): void {\r\n this.drawing = false;\r\n this.origin = { x: 0, y: 0 };\r\n this.current = { x: 0, y: 0 };\r\n }\r\n\r\n renderOverlay(ctx: CanvasRenderingContext2D): void {\r\n if (!this.drawing) return;\r\n\r\n const radius = this.computeRadius();\r\n if (radius <= 0) return;\r\n\r\n if (this.gridType === 'hex' && this.hexOrientation) {\r\n this.renderHexOverlay(ctx, radius);\r\n return;\r\n }\r\n\r\n this.renderGeometricOverlay(ctx, radius);\r\n }\r\n\r\n private renderGeometricOverlay(ctx: CanvasRenderingContext2D, radius: number): void {\r\n const cx = this.origin.x;\r\n const cy = this.origin.y;\r\n const angle = this.computeAngle();\r\n\r\n ctx.save();\r\n ctx.globalAlpha = 0.4;\r\n ctx.fillStyle = this.fillColor;\r\n ctx.strokeStyle = this.strokeColor;\r\n ctx.lineWidth = this.strokeWidth;\r\n\r\n switch (this.templateShape) {\r\n case 'circle':\r\n ctx.beginPath();\r\n ctx.arc(cx, cy, radius, 0, Math.PI * 2);\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n\r\n case 'square':\r\n ctx.fillRect(cx - radius / 2, cy - radius / 2, radius, radius);\r\n ctx.strokeRect(cx - radius / 2, cy - radius / 2, radius, radius);\r\n break;\r\n\r\n case 'cone': {\r\n const halfAngle = Math.atan(0.5);\r\n ctx.beginPath();\r\n ctx.moveTo(cx, cy);\r\n ctx.arc(cx, cy, radius, angle - halfAngle, angle + halfAngle);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n\r\n case 'line': {\r\n const halfW = radius / 12;\r\n const cos = Math.cos(angle);\r\n const sin = Math.sin(angle);\r\n const perpX = -sin * halfW;\r\n const perpY = cos * halfW;\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(cx + perpX, cy + perpY);\r\n ctx.lineTo(cx + radius * cos + perpX, cy + radius * sin + perpY);\r\n ctx.lineTo(cx + radius * cos - perpX, cy + radius * sin - perpY);\r\n ctx.lineTo(cx - perpX, cy - perpY);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.stroke();\r\n break;\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private renderHexOverlay(ctx: CanvasRenderingContext2D, radius: number): void {\r\n const orientation = this.hexOrientation;\r\n if (!orientation) return;\r\n const cellSize = this.gridSize;\r\n const snapUnit = Math.sqrt(3) * cellSize;\r\n const radiusCells = radius / snapUnit;\r\n const angle = this.computeAngle();\r\n const center = this.origin;\r\n\r\n let hexCells: Point[];\r\n switch (this.templateShape) {\r\n case 'circle':\r\n hexCells = getHexCellsInRadius(center, radiusCells, cellSize, orientation);\r\n break;\r\n case 'cone':\r\n hexCells = getHexCellsInCone(center, angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'line':\r\n hexCells = getHexCellsInLine(center, angle, radiusCells, cellSize, orientation);\r\n break;\r\n case 'square':\r\n hexCells = getHexCellsInSquare(center, radiusCells, cellSize, orientation);\r\n break;\r\n }\r\n\r\n ctx.save();\r\n ctx.globalAlpha = 0.4;\r\n\r\n ctx.beginPath();\r\n for (const cell of hexCells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.fillStyle = this.fillColor;\r\n ctx.fill();\r\n\r\n ctx.beginPath();\r\n for (const cell of hexCells) {\r\n drawHexPath(ctx, cell.x, cell.y, cellSize, orientation);\r\n }\r\n ctx.strokeStyle = this.strokeColor;\r\n ctx.lineWidth = this.strokeWidth;\r\n ctx.stroke();\r\n\r\n if (\r\n this.templateShape === 'cone' ||\r\n this.templateShape === 'line' ||\r\n this.templateShape === 'circle' ||\r\n this.templateShape === 'square'\r\n ) {\r\n ctx.globalAlpha = 0.5;\r\n ctx.beginPath();\r\n drawHexPath(ctx, center.x, center.y, cellSize, orientation);\r\n ctx.fillStyle = this.strokeColor;\r\n ctx.fill();\r\n ctx.strokeStyle = this.strokeColor;\r\n ctx.lineWidth = this.strokeWidth;\r\n ctx.stroke();\r\n }\r\n\r\n if (this.templateShape === 'circle') {\r\n const feet = radiusCells * this.feetPerCell;\r\n if (feet > 0) {\r\n ctx.globalAlpha = 1;\r\n const label = `${Math.round(feet)} ft`;\r\n const fontSize = Math.max(10, Math.min(14, radius * 0.15));\r\n ctx.font = `bold ${fontSize}px system-ui, sans-serif`;\r\n ctx.textAlign = 'center';\r\n ctx.textBaseline = 'bottom';\r\n const textX = center.x;\r\n const textY = center.y - 4;\r\n\r\n const metrics = ctx.measureText(label);\r\n const padX = 4;\r\n const padY = 2;\r\n const textW = metrics.width + padX * 2;\r\n const textH = fontSize + padY * 2;\r\n\r\n ctx.fillStyle = 'rgba(255, 255, 255, 0.85)';\r\n ctx.beginPath();\r\n ctx.roundRect(textX - textW / 2, textY - textH, textW, textH, 3);\r\n ctx.fill();\r\n\r\n ctx.fillStyle = this.strokeColor;\r\n ctx.fillText(label, textX, textY - padY);\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n private computeRadius(): number {\r\n const dx = this.current.x - this.origin.x;\r\n const dy = this.current.y - this.origin.y;\r\n const raw = Math.sqrt(dx * dx + dy * dy);\r\n if (this.snapEnabled && this.gridSize > 0) {\r\n const snapUnit = this.gridType === 'hex' ? Math.sqrt(3) * this.gridSize : this.gridSize;\r\n return Math.max(snapUnit, Math.round(raw / snapUnit) * snapUnit);\r\n }\r\n return raw;\r\n }\r\n\r\n private computeAngle(): number {\r\n const dx = this.current.x - this.origin.x;\r\n const dy = this.current.y - this.origin.y;\r\n return Math.atan2(dy, dx);\r\n }\r\n\r\n private snapToGrid(point: Point, ctx: ToolContext): Point {\r\n if (!ctx.gridSize) return point;\r\n if (ctx.gridType === 'hex' && ctx.hexOrientation) {\r\n return snapToHexCenter(point, ctx.gridSize, ctx.hexOrientation);\r\n }\r\n if (ctx.gridType === 'square') {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n if (ctx.snapToGrid) {\r\n return snapPoint(point, ctx.gridSize);\r\n }\r\n return point;\r\n }\r\n\r\n private notifyOptionsChange(): void {\r\n for (const listener of this.optionListeners) listener();\r\n }\r\n}\r\n","export const VERSION = '0.27.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';\n\nexport { Camera } from './canvas/camera';\nexport type { CameraOptions, CameraChangeInfo } from './canvas/camera';\nexport type { BackgroundOptions, BackgroundPattern } from './canvas/background';\nexport type { ShortcutOptions, ShortcutBindings, ShortcutsApi } from './canvas/shortcut-map';\nexport { Viewport } from './canvas/viewport';\nexport type { ViewportOptions, GridInfo } from './canvas/viewport';\nexport { exportImage } from './canvas/export-image';\nexport type { ExportImageOptions } from './canvas/export-image';\nexport type { RenderStatsSnapshot } from './canvas/render-stats';\n\nexport { ElementStore } from './elements/element-store';\nexport type { ElementUpdateEvent } from './elements/element-store';\nexport type { FontSizePreset } from './elements/note-toolbar';\nexport {\n toggleBold,\n toggleItalic,\n toggleUnderline,\n toggleStrikethrough,\n setFontSize,\n getActiveFormats,\n} from './elements/note-formatting';\nexport type { ActiveFormats } from './elements/note-formatting';\nexport {\n createStroke,\n createNote,\n createArrow,\n createImage,\n createHtmlElement,\n createText,\n createShape,\n createGrid,\n createTemplate,\n DEFAULT_NOTE_FONT_SIZE,\n} from './elements/element-factory';\nexport {\n getArrowControlPoint,\n getArrowMidpoint,\n getBendFromPoint,\n getArrowTangentAngle,\n isNearBezier,\n getArrowBounds,\n} from './elements/arrow-geometry';\nexport { getElementBounds, boundsIntersect } from './elements/element-bounds';\nexport { styleToPatch, getElementStyle } from './elements/element-style';\nexport type { ElementStyle } from './elements/element-style';\nexport { getElementsBoundingBox } from './elements/bounds';\nexport {\n getHexDistance,\n getHexCellsInRadius,\n getHexCellsInCone,\n getHexCellsInLine,\n getHexCellsInSquare,\n drawHexPath,\n} from './elements/hex-fill';\nexport type {\n Binding,\n CanvasElement,\n ElementType,\n StrokeElement,\n NoteElement,\n ArrowElement,\n ImageElement,\n HtmlElement,\n TextElement,\n ShapeElement,\n ShapeKind,\n GridElement,\n HexOrientation,\n TemplateElement,\n TemplateShape,\n} from './elements/types';\n\nexport type { Command } from './history/types';\nexport { HistoryStack } from './history/history-stack';\nexport type { HistoryStackOptions } from './history/history-stack';\n\nexport { ToolManager } from './tools/tool-manager';\nexport { HandTool } from './tools/hand-tool';\nexport { PencilTool } from './tools/pencil-tool';\nexport type { PencilToolOptions } from './tools/pencil-tool';\nexport { EraserTool } from './tools/eraser-tool';\nexport type { EraserToolOptions } from './tools/eraser-tool';\nexport { SelectTool } from './tools/select-tool';\nexport { ArrowTool } from './tools/arrow-tool';\nexport type { ArrowToolOptions } from './tools/arrow-tool';\nexport { NoteTool } from './tools/note-tool';\nexport type { NoteToolOptions } from './tools/note-tool';\nexport { TextTool } from './tools/text-tool';\nexport type { TextToolOptions } from './tools/text-tool';\nexport { ImageTool } from './tools/image-tool';\nexport type { ImageToolOptions } from './tools/image-tool';\nexport { ShapeTool } from './tools/shape-tool';\nexport type { ShapeToolOptions } from './tools/shape-tool';\nexport { MeasureTool } from './tools/measure-tool';\nexport type { MeasureToolOptions, Measurement } from './tools/measure-tool';\nexport { TemplateTool } from './tools/template-tool';\nexport type { TemplateToolOptions } from './tools/template-tool';\nexport type { Tool, ToolContext, PointerState, ToolName } from './tools/types';\n\nexport { LayerManager } from './layers/layer-manager';\nexport type { Layer } from './layers/types';\n"],"mappings":"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","names":["minX","minY","minX","minY","cache","cache","HANDLE_HIT_PADDING","BIND_THRESHOLD"]}