@jamesyong42/infinite-canvas 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -0
- package/dist/advanced.cjs +61 -24
- package/dist/advanced.cjs.map +1 -1
- package/dist/advanced.d.cts +180 -64
- package/dist/advanced.d.cts.map +1 -1
- package/dist/advanced.d.mts +180 -64
- package/dist/advanced.d.mts.map +1 -1
- package/dist/advanced.mjs +29 -12
- package/dist/advanced.mjs.map +1 -1
- package/dist/devtools.cjs +22 -22
- package/dist/devtools.cjs.map +1 -1
- package/dist/devtools.d.cts +2 -2
- package/dist/devtools.d.cts.map +1 -1
- package/dist/devtools.d.mts +2 -2
- package/dist/devtools.d.mts.map +1 -1
- package/dist/devtools.mjs +2 -2
- package/dist/devtools.mjs.map +1 -1
- package/dist/{hooks-BwY7rRHg.mjs → ecs-3kimUV5Z.mjs} +238 -74
- package/dist/ecs-3kimUV5Z.mjs.map +1 -0
- package/dist/{hooks-DHShH86C.cjs → ecs-B4QrqfvQ.cjs} +320 -108
- package/dist/ecs-B4QrqfvQ.cjs.map +1 -0
- package/dist/hooks-CtP02JNt.cjs +3762 -0
- package/dist/hooks-CtP02JNt.cjs.map +1 -0
- package/dist/hooks-gsQDDE56.mjs +3494 -0
- package/dist/hooks-gsQDDE56.mjs.map +1 -0
- package/dist/index-3GY7T8JM.d.mts +480 -0
- package/dist/index-3GY7T8JM.d.mts.map +1 -0
- package/dist/index-B7B1tRPl.d.cts +480 -0
- package/dist/index-B7B1tRPl.d.cts.map +1 -0
- package/dist/index-DSdbSQ_t.d.cts +1451 -0
- package/dist/index-DSdbSQ_t.d.cts.map +1 -0
- package/dist/index-Dj9odADH.d.mts +1451 -0
- package/dist/index-Dj9odADH.d.mts.map +1 -0
- package/dist/index.cjs +3865 -643
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +315 -138
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +315 -138
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3767 -571
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/SelectionRenderer-CR2PBQwx.d.cts +0 -105
- package/dist/SelectionRenderer-CR2PBQwx.d.cts.map +0 -1
- package/dist/SelectionRenderer-DlsBstAq.d.mts +0 -105
- package/dist/SelectionRenderer-DlsBstAq.d.mts.map +0 -1
- package/dist/WebGLWidgetLayer-BBMuwzHq.cjs +0 -3560
- package/dist/WebGLWidgetLayer-BBMuwzHq.cjs.map +0 -1
- package/dist/WebGLWidgetLayer-C3p1tnpm.mjs +0 -3375
- package/dist/WebGLWidgetLayer-C3p1tnpm.mjs.map +0 -1
- package/dist/engine-BfbvWXSk.d.mts +0 -982
- package/dist/engine-BfbvWXSk.d.mts.map +0 -1
- package/dist/engine-CCjuFMC-.d.cts +0 -982
- package/dist/engine-CCjuFMC-.d.cts.map +0 -1
- package/dist/hooks-BwY7rRHg.mjs.map +0 -1
- package/dist/hooks-DHShH86C.cjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"WebGLWidgetLayer-C3p1tnpm.mjs","names":["RBush","RBushImport","getMods","vertexShader","fragmentShader"],"sources":["../src/archetype.ts","../src/commands.ts","../src/math.ts","../src/profiler.ts","../src/react/registry.ts","../src/snap.ts","../../../node_modules/.pnpm/quickselect@3.0.0/node_modules/quickselect/index.js","../../../node_modules/.pnpm/rbush@4.0.1/node_modules/rbush/index.js","../src/spatial.ts","../src/systems.ts","../src/engine.ts","../src/react/SelectionOverlaySlot.tsx","../src/react/WidgetSlot.tsx","../src/react/webgl/GridRenderer.ts","../src/react/webgl/SelectionRenderer.ts","../src/react/webgl/WebGLWidgetSlot.tsx","../src/react/webgl/WebGLWidgetLayer.tsx"],"sourcesContent":["import type { ComponentInit, EntityId, TagType } from '@jamesyong42/reactive-ecs';\n\n/**\n * An archetype is a recipe for creating an entity: it declares which components\n * and tags the entity should have on spawn. Archetypes may reference a widget\n * type (for visible entities) or stand alone (for logic-only entities).\n *\n * The engine auto-generates a default archetype for every registered widget\n * that does not have an explicit one — so simple widgets don't need to ship\n * an archetype at all. Write an archetype only when you need to bundle extra\n * behaviour (Container, Locked, custom components) with a widget.\n */\nexport interface Archetype {\n\t/** Unique archetype id. Pass this to `engine.spawn(id, ...)`. */\n\tid: string;\n\t/**\n\t * The widget type this archetype renders as. Required for visible entities;\n\t * omit for logic-only entities that have no view.\n\t */\n\twidget?: string;\n\t/** Extra components added on spawn, beyond Transform2D / Widget / WidgetData / ZIndex. */\n\tcomponents?: ComponentInit[];\n\t/** Extra tags added on spawn, beyond the interactive defaults. */\n\ttags?: TagType[];\n\t/**\n\t * Which interaction capabilities to grant on spawn.\n\t *\n\t * - `true` (default) / `undefined`: add Selectable, Draggable, Resizable,\n\t * and the SelectionFrame (engine-drawn outline).\n\t * - `false`: add none (backdrops, decorations, locked entities).\n\t * - object form: pick and choose — e.g. iOS-style cards use\n\t * `{ selectable: true, draggable: true, resizable: false, selectionFrame: false }`\n\t * so they can be moved and selected but never resized, and they render\n\t * their own chrome instead of the engine-drawn frame.\n\t *\n\t * Omitted interaction keys default to `false`. `selectionFrame` is an\n\t * exception: if omitted, it follows `selectable` (an entity you can\n\t * select gets a frame unless you explicitly opt out).\n\t */\n\tinteractive?:\n\t\t| boolean\n\t\t| {\n\t\t\t\tselectable?: boolean;\n\t\t\t\tdraggable?: boolean;\n\t\t\t\tresizable?: boolean;\n\t\t\t\tselectionFrame?: boolean;\n\t\t };\n\t/** Overrides the widget's defaultSize. */\n\tdefaultSize?: { width: number; height: number };\n}\n\n/**\n * Options for `engine.spawn(archetypeId, opts)`.\n * All fields are optional — defaults come from the archetype + widget.\n */\nexport interface SpawnOptions {\n\t/** World-space position. Defaults to { x: 0, y: 0 }. */\n\tat?: { x: number; y: number };\n\t/** World-space size. Falls back to archetype.defaultSize → widget.defaultSize. */\n\tsize?: { width: number; height: number };\n\t/** Initial rotation in radians. Default 0. */\n\trotation?: number;\n\t/** Data patch merged into the widget's defaultData. */\n\tdata?: Record<string, unknown>;\n\t/** Z-order. Default 0. */\n\tzIndex?: number;\n\t/** Parent entity for hierarchy nesting. */\n\tparent?: EntityId;\n}\n\n/** Simple in-memory archetype registry. */\nexport interface ArchetypeRegistry {\n\tregister(archetype: Archetype): void;\n\tget(id: string): Archetype | null;\n\tgetAll(): Archetype[];\n}\n\nexport function createArchetypeRegistry(archetypes: Archetype[] = []): ArchetypeRegistry {\n\tconst map = new Map<string, Archetype>();\n\tfor (const a of archetypes) map.set(a.id, a);\n\treturn {\n\t\tregister(a) {\n\t\t\tmap.set(a.id, a);\n\t\t},\n\t\tget(id) {\n\t\t\treturn map.get(id) ?? null;\n\t\t},\n\t\tgetAll() {\n\t\t\treturn [...map.values()];\n\t\t},\n\t};\n}\n","import type { ComponentType, EntityId, World } from '@jamesyong42/reactive-ecs';\nimport { MIN_WIDGET_SIZE } from './interaction-constants.js';\n\n// === Command Interface ===\n\nexport interface Command {\n\texecute(world: World): void;\n\tundo(world: World): void;\n}\n\n// === Command Buffer with Undo/Redo ===\n\nexport class CommandBuffer {\n\tprivate undoStack: Command[][] = [];\n\tprivate redoStack: Command[][] = [];\n\tprivate currentGroup: Command[] | null = null;\n\n\t/** Start grouping commands (e.g., on pointerdown). All commands until endGroup() are one undo step. */\n\tbeginGroup() {\n\t\tif (this.currentGroup !== null) {\n\t\t\tthis.endGroup(); // auto-close previous group\n\t\t}\n\t\tthis.currentGroup = [];\n\t}\n\n\t/** Execute a command and record it for undo. */\n\texecute(command: Command, world: World) {\n\t\tcommand.execute(world);\n\n\t\tif (this.currentGroup) {\n\t\t\tthis.currentGroup.push(command);\n\t\t} else {\n\t\t\t// Single command = its own undo group\n\t\t\tthis.undoStack.push([command]);\n\t\t\tthis.redoStack.length = 0;\n\t\t}\n\t}\n\n\t/** Close the current group — all commands since beginGroup() become one undo step. */\n\tendGroup() {\n\t\tif (this.currentGroup && this.currentGroup.length > 0) {\n\t\t\tthis.undoStack.push(this.currentGroup);\n\t\t\tthis.redoStack.length = 0;\n\t\t}\n\t\tthis.currentGroup = null;\n\t}\n\n\t/** Undo the last command group. */\n\tundo(world: World): boolean {\n\t\t// Close any open group first\n\t\tif (this.currentGroup) {\n\t\t\tthis.endGroup();\n\t\t}\n\n\t\tconst group = this.undoStack.pop();\n\t\tif (!group) return false;\n\n\t\t// Undo in reverse order\n\t\tfor (let i = group.length - 1; i >= 0; i--) {\n\t\t\tgroup[i].undo(world);\n\t\t}\n\t\tthis.redoStack.push(group);\n\t\treturn true;\n\t}\n\n\t/** Redo the last undone command group. */\n\tredo(world: World): boolean {\n\t\tconst group = this.redoStack.pop();\n\t\tif (!group) return false;\n\n\t\tfor (const cmd of group) {\n\t\t\tcmd.execute(world);\n\t\t}\n\t\tthis.undoStack.push(group);\n\t\treturn true;\n\t}\n\n\tcanUndo(): boolean {\n\t\treturn (\n\t\t\tthis.undoStack.length > 0 || (this.currentGroup !== null && this.currentGroup.length > 0)\n\t\t);\n\t}\n\n\tcanRedo(): boolean {\n\t\treturn this.redoStack.length > 0;\n\t}\n\n\tclear() {\n\t\tthis.undoStack.length = 0;\n\t\tthis.redoStack.length = 0;\n\t\tthis.currentGroup = null;\n\t}\n\n\tget undoSize(): number {\n\t\treturn this.undoStack.length;\n\t}\n\tget redoSize(): number {\n\t\treturn this.redoStack.length;\n\t}\n}\n\n// === Built-in Commands ===\n\nexport class MoveCommand implements Command {\n\tprivate beforePositions: Map<EntityId, { x: number; y: number }> = new Map();\n\tprivate afterPositions: Map<EntityId, { x: number; y: number }> = new Map();\n\tprivate captured = false;\n\n\tconstructor(\n\t\tprivate entityIds: EntityId[],\n\t\tprivate dx: number,\n\t\tprivate dy: number,\n\t\tprivate transformType: ComponentType<{ x: number; y: number }>,\n\t) {}\n\n\texecute(world: World) {\n\t\tif (!this.captured) {\n\t\t\t// First execute: snapshot before positions, compute after positions\n\t\t\tfor (const id of this.entityIds) {\n\t\t\t\tconst t = world.getComponent(id, this.transformType);\n\t\t\t\tif (t) {\n\t\t\t\t\tthis.beforePositions.set(id, { x: t.x, y: t.y });\n\t\t\t\t\tthis.afterPositions.set(id, { x: t.x + this.dx, y: t.y + this.dy });\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.captured = true;\n\t\t}\n\n\t\tfor (const [id, pos] of this.afterPositions) {\n\t\t\tworld.setComponent(id, this.transformType, { x: pos.x, y: pos.y });\n\t\t}\n\t}\n\n\tundo(world: World) {\n\t\tfor (const [id, pos] of this.beforePositions) {\n\t\t\tworld.setComponent(id, this.transformType, { x: pos.x, y: pos.y });\n\t\t}\n\t}\n}\n\nexport class ResizeCommand implements Command {\n\tconstructor(\n\t\tprivate entityId: EntityId,\n\t\tprivate before: { x: number; y: number; width: number; height: number },\n\t\tprivate after: { x: number; y: number; width: number; height: number },\n\t\tprivate transformType: ComponentType<{ x: number; y: number; width: number; height: number }>,\n\t) {\n\t\t// Enforce min-size so redo always produces valid bounds\n\t\tthis.after = {\n\t\t\t...after,\n\t\t\twidth: Math.max(MIN_WIDGET_SIZE, after.width),\n\t\t\theight: Math.max(MIN_WIDGET_SIZE, after.height),\n\t\t};\n\t}\n\n\texecute(world: World) {\n\t\tworld.setComponent(this.entityId, this.transformType, this.after);\n\t}\n\n\tundo(world: World) {\n\t\tworld.setComponent(this.entityId, this.transformType, this.before);\n\t}\n}\n\nexport class SetComponentCommand<T> implements Command {\n\tconstructor(\n\t\tprivate entityId: EntityId,\n\t\tprivate type: ComponentType<T>,\n\t\tprivate before: Partial<T>,\n\t\tprivate after: Partial<T>,\n\t) {}\n\n\texecute(world: World) {\n\t\tworld.setComponent(this.entityId, this.type, this.after);\n\t}\n\n\tundo(world: World) {\n\t\tworld.setComponent(this.entityId, this.type, this.before);\n\t}\n}\n","export interface Vec2 {\n\tx: number;\n\ty: number;\n}\n\nexport interface Rect {\n\tx: number;\n\ty: number;\n\twidth: number;\n\theight: number;\n}\n\nexport interface AABB {\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n}\n\n/** Convert WorldBounds-shaped data to AABB */\nexport function worldBoundsToAABB(wb: {\n\tworldX: number;\n\tworldY: number;\n\tworldWidth: number;\n\tworldHeight: number;\n}): AABB {\n\treturn {\n\t\tminX: wb.worldX,\n\t\tminY: wb.worldY,\n\t\tmaxX: wb.worldX + wb.worldWidth,\n\t\tmaxY: wb.worldY + wb.worldHeight,\n\t};\n}\n\n/** Convert a Rect to AABB */\nexport function rectToAABB(r: Rect): AABB {\n\treturn {\n\t\tminX: r.x,\n\t\tminY: r.y,\n\t\tmaxX: r.x + r.width,\n\t\tmaxY: r.y + r.height,\n\t};\n}\n\n/** Convert AABB to Rect */\nexport function aabbToRect(a: AABB): Rect {\n\treturn {\n\t\tx: a.minX,\n\t\ty: a.minY,\n\t\twidth: a.maxX - a.minX,\n\t\theight: a.maxY - a.minY,\n\t};\n}\n\n/** Test if two AABBs overlap */\nexport function intersectsAABB(a: AABB, b: AABB): boolean {\n\treturn a.maxX >= b.minX && a.minX <= b.maxX && a.maxY >= b.minY && a.minY <= b.maxY;\n}\n\n/** Test if a point is inside an AABB */\nexport function pointInAABB(px: number, py: number, a: AABB): boolean {\n\treturn px >= a.minX && px <= a.maxX && py >= a.minY && py <= a.maxY;\n}\n\n/** Convert screen coordinates to world coordinates */\nexport function screenToWorld(\n\tscreenX: number,\n\tscreenY: number,\n\tcamera: { x: number; y: number; zoom: number },\n): Vec2 {\n\treturn {\n\t\tx: screenX / camera.zoom + camera.x,\n\t\ty: screenY / camera.zoom + camera.y,\n\t};\n}\n\n/** Convert world coordinates to screen coordinates */\nexport function worldToScreen(\n\tworldX: number,\n\tworldY: number,\n\tcamera: { x: number; y: number; zoom: number },\n): Vec2 {\n\treturn {\n\t\tx: (worldX - camera.x) * camera.zoom,\n\t\ty: (worldY - camera.y) * camera.zoom,\n\t};\n}\n\n/** Clamp a value between min and max */\nexport function clamp(value: number, min: number, max: number): number {\n\treturn Math.max(min, Math.min(max, value));\n}\n","/**\n * Multi-layer performance profiler.\n *\n * Tracks three independent rendering concerns:\n *\n * 1. ECS tick — systems, visibility, entity counts. Driven by `engine.tick()`.\n * 2. WebGL engine pass — the library's grid + selection renderers. Runs\n * inside the rAF loop immediately after each ECS tick, so samples share\n * the ECS ring and carry matched tick ids.\n * 3. R3F canvas — the user's 3D widgets inside the shared `<Canvas>`. Runs\n * continuously at rAF cadence regardless of engine ticks, so it has its\n * own ring.\n *\n * All methods are no-ops when disabled — zero cost for production builds.\n * User Timing API marks are emitted when enabled so traces line up with\n * Chrome DevTools' Performance panel.\n */\n\n// === Sample shapes ===\n\nexport interface TickSample {\n\ttick: number;\n\ttimestamp: number;\n\t/** Total tick duration (ms) = ECS tick + WebGL engine pass. */\n\ttotalMs: number;\n\tecs: {\n\t\t/** Per-system durations (ms). */\n\t\tsystems: Record<string, number>;\n\t\t/** Visible entity computation (ms). */\n\t\tvisibilityMs: number;\n\t\t/** Entity counts at this frame. */\n\t\tentityCount: number;\n\t\tvisibleCount: number;\n\t};\n\twebgl: {\n\t\t/** Grid renderer pass duration (ms). */\n\t\tgridMs: number;\n\t\t/** Selection + hover + snap-guide render pass duration (ms). */\n\t\tselectionMs: number;\n\t\t/** Total `renderer.info.render.calls` across all passes this tick. */\n\t\tdrawCalls: number;\n\t\t/** Total `renderer.info.render.triangles` across all passes this tick. */\n\t\ttriangles: number;\n\t\t/** Selection frames drawn this tick. */\n\t\tselectionFrames: number;\n\t\t/** Snap guides drawn this tick. */\n\t\tsnapGuides: number;\n\t\t/** Equal-spacing indicators drawn this tick. */\n\t\tspacingIndicators: number;\n\t\t/** DOM slot.transform writes this tick (from changes.positionsChanged). */\n\t\tdomPositionsUpdated: number;\n\t};\n}\n\nexport interface R3FSample {\n\ttimestamp: number;\n\t/** Delta since the previous R3F frame (ms). */\n\tdtMs: number;\n\t/** three.js renderer.info snapshot. */\n\tdrawCalls: number;\n\ttriangles: number;\n\tpoints: number;\n\tlines: number;\n\tprograms: number;\n\tgeometries: number;\n\ttextures: number;\n\tactiveWidgets: number;\n}\n\n// === Stats shapes ===\n\nexport interface FrameTimeStats {\n\tavg: number;\n\tp50: number;\n\tp95: number;\n\tp99: number;\n\tmax: number;\n}\n\nexport interface EcsStats {\n\tfps: number;\n\tframeTime: FrameTimeStats;\n\tsystemAvg: Record<string, number>;\n\tsystemP95: Record<string, number>;\n\t/** Avg frame time as % of 16.67ms (60 fps). */\n\tbudgetUsed: number;\n\tsampleCount: number;\n}\n\nexport interface WebGLStats {\n\t/** Tick cadence — matches ECS since both fire together. */\n\tfps: number;\n\t/** Avg combined pass time (ms) and percentile breakdown. */\n\tframeTime: FrameTimeStats;\n\t/** Avg combined pass time as % of 16.67ms budget. */\n\tbudgetUsed: number;\n\tgridAvg: number;\n\tgridP95: number;\n\tselectionAvg: number;\n\tselectionP95: number;\n\tavgDrawCalls: number;\n\tavgTriangles: number;\n\tavgSelectionFrames: number;\n\tavgSnapGuides: number;\n\tavgDomUpdates: number;\n\tsampleCount: number;\n}\n\nexport interface R3FStats {\n\tfps: number;\n\tframeTime: FrameTimeStats;\n\tavgDrawCalls: number;\n\tavgTriangles: number;\n\t/** Latest snapshots — these don't average meaningfully. */\n\tprograms: number;\n\tgeometries: number;\n\ttextures: number;\n\tactiveWidgets: number;\n\tsampleCount: number;\n}\n\nexport interface ProfilerStats {\n\tecs: EcsStats;\n\twebgl: WebGLStats;\n\tr3f: R3FStats;\n}\n\n// === Implementation ===\n\nconst TICK_RING_SIZE = 300; // ~5 s at 60 fps\nconst R3F_RING_SIZE = 300;\n\n/** What's being timed inside the library's WebGL engine pass. */\nexport type WebGLPass = 'grid' | 'selection';\n\nexport class Profiler {\n\tprivate enabled = false;\n\n\t// Tick ring (ECS + engine WebGL pass — matched cadence).\n\tprivate tickRing: TickSample[] = [];\n\tprivate tickWrite = 0;\n\tprivate tickFilled = false;\n\n\t// R3F ring (continuous, independent cadence).\n\tprivate r3fRing: R3FSample[] = [];\n\tprivate r3fWrite = 0;\n\tprivate r3fFilled = false;\n\n\t// Scratch state for the currently-building tick sample.\n\tprivate frameStart = 0;\n\tprivate currentSystems: Record<string, number> = {};\n\tprivate visibilityMs = 0;\n\tprivate webglGridMs = 0;\n\tprivate webglSelectionMs = 0;\n\tprivate webglDrawCalls = 0;\n\tprivate webglTriangles = 0;\n\tprivate webglSelectionFrames = 0;\n\tprivate webglSnapGuides = 0;\n\tprivate webglSpacingIndicators = 0;\n\tprivate webglDomPositionsUpdated = 0;\n\tprivate currentTick = 0;\n\n\t/** Enable/disable profiling. When disabled, all methods are no-ops. */\n\tsetEnabled(on: boolean) {\n\t\tthis.enabled = on;\n\t\tif (!on) this.clear();\n\t}\n\n\tisEnabled(): boolean {\n\t\treturn this.enabled;\n\t}\n\n\t// === ECS tick instrumentation ===\n\n\t/** Call at the start of engine.tick(). */\n\tbeginFrame(tick: number) {\n\t\tif (!this.enabled) return;\n\t\tthis.currentTick = tick;\n\t\tthis.currentSystems = {};\n\t\tthis.visibilityMs = 0;\n\t\tthis.webglGridMs = 0;\n\t\tthis.webglSelectionMs = 0;\n\t\tthis.webglDrawCalls = 0;\n\t\tthis.webglTriangles = 0;\n\t\tthis.webglSelectionFrames = 0;\n\t\tthis.webglSnapGuides = 0;\n\t\tthis.webglSpacingIndicators = 0;\n\t\tthis.webglDomPositionsUpdated = 0;\n\t\tthis.frameStart = performance.now();\n\t\tperformance.mark('ic-frame-start');\n\t}\n\n\t/** Call around each ECS system execution. */\n\tbeginSystem(name: string) {\n\t\tif (!this.enabled) return;\n\t\tperformance.mark(`ic-sys-${name}-start`);\n\t}\n\n\tendSystem(name: string) {\n\t\tif (!this.enabled) return;\n\t\tperformance.mark(`ic-sys-${name}-end`);\n\t\ttry {\n\t\t\tconst measure = performance.measure(\n\t\t\t\t`ic:sys:${name}`,\n\t\t\t\t`ic-sys-${name}-start`,\n\t\t\t\t`ic-sys-${name}-end`,\n\t\t\t);\n\t\t\tthis.currentSystems[name] = measure.duration;\n\t\t} catch {\n\t\t\t// marks may be cleared\n\t\t}\n\t\tperformance.clearMarks(`ic-sys-${name}-start`);\n\t\tperformance.clearMarks(`ic-sys-${name}-end`);\n\t}\n\n\tbeginVisibility() {\n\t\tif (!this.enabled) return;\n\t\tperformance.mark('ic-vis-start');\n\t}\n\n\tendVisibility() {\n\t\tif (!this.enabled) return;\n\t\tperformance.mark('ic-vis-end');\n\t\ttry {\n\t\t\tconst measure = performance.measure('ic:visibility', 'ic-vis-start', 'ic-vis-end');\n\t\t\tthis.visibilityMs = measure.duration;\n\t\t} catch {\n\t\t\t// marks may be cleared\n\t\t}\n\t\tperformance.clearMarks('ic-vis-start');\n\t\tperformance.clearMarks('ic-vis-end');\n\t}\n\n\t// === WebGL engine pass instrumentation ===\n\n\t/** Call right before the named engine WebGL pass renders. */\n\tbeginWebGL(pass: WebGLPass) {\n\t\tif (!this.enabled) return;\n\t\tperformance.mark(`ic-gl-${pass}-start`);\n\t}\n\n\t/** Call right after the named engine WebGL pass renders. */\n\tendWebGL(pass: WebGLPass) {\n\t\tif (!this.enabled) return;\n\t\tperformance.mark(`ic-gl-${pass}-end`);\n\t\ttry {\n\t\t\tconst measure = performance.measure(\n\t\t\t\t`ic:gl:${pass}`,\n\t\t\t\t`ic-gl-${pass}-start`,\n\t\t\t\t`ic-gl-${pass}-end`,\n\t\t\t);\n\t\t\tif (pass === 'grid') this.webglGridMs = measure.duration;\n\t\t\telse this.webglSelectionMs = measure.duration;\n\t\t} catch {\n\t\t\t// marks may be cleared\n\t\t}\n\t\tperformance.clearMarks(`ic-gl-${pass}-start`);\n\t\tperformance.clearMarks(`ic-gl-${pass}-end`);\n\t}\n\n\t/**\n\t * Record WebGL engine pass counters for the current tick. `drawCalls` and\n\t * `triangles` should be the totals from `renderer.info.render` accumulated\n\t * across all engine passes in this tick (grid + selection). Callers must\n\t * reset `renderer.info` at the start of the tick (with `autoReset=false`)\n\t * so these values cover both passes.\n\t */\n\trecordWebGLStats(stats: {\n\t\tdrawCalls: number;\n\t\ttriangles: number;\n\t\tselectionFrames: number;\n\t\tsnapGuides: number;\n\t\tspacingIndicators: number;\n\t\tdomPositionsUpdated: number;\n\t}) {\n\t\tif (!this.enabled) return;\n\t\tthis.webglDrawCalls = stats.drawCalls;\n\t\tthis.webglTriangles = stats.triangles;\n\t\tthis.webglSelectionFrames = stats.selectionFrames;\n\t\tthis.webglSnapGuides = stats.snapGuides;\n\t\tthis.webglSpacingIndicators = stats.spacingIndicators;\n\t\tthis.webglDomPositionsUpdated = stats.domPositionsUpdated;\n\t}\n\n\t/** Call at the end of engine.tick() — flushes a TickSample to the ring. */\n\tendFrame(entityCount: number, visibleCount: number) {\n\t\tif (!this.enabled) return;\n\t\tperformance.mark('ic-frame-end');\n\n\t\tlet totalMs: number;\n\t\ttry {\n\t\t\tconst measure = performance.measure('ic:frame', 'ic-frame-start', 'ic-frame-end');\n\t\t\ttotalMs = measure.duration;\n\t\t} catch {\n\t\t\ttotalMs = performance.now() - this.frameStart;\n\t\t}\n\t\tperformance.clearMarks('ic-frame-start');\n\t\tperformance.clearMarks('ic-frame-end');\n\n\t\t// `totalMs` is the ECS tick only — the WebGL engine pass runs AFTER\n\t\t// endFrame. Its ms lives separately in the sample so consumers can\n\t\t// combine (ecs.totalMs + webgl.gridMs + webgl.selectionMs) if they\n\t\t// want a compound figure.\n\n\t\tconst sample: TickSample = {\n\t\t\ttick: this.currentTick,\n\t\t\ttimestamp: performance.now(),\n\t\t\ttotalMs,\n\t\t\tecs: {\n\t\t\t\tsystems: { ...this.currentSystems },\n\t\t\t\tvisibilityMs: this.visibilityMs,\n\t\t\t\tentityCount,\n\t\t\t\tvisibleCount,\n\t\t\t},\n\t\t\twebgl: {\n\t\t\t\tgridMs: this.webglGridMs,\n\t\t\t\tselectionMs: this.webglSelectionMs,\n\t\t\t\tdrawCalls: this.webglDrawCalls,\n\t\t\t\ttriangles: this.webglTriangles,\n\t\t\t\tselectionFrames: this.webglSelectionFrames,\n\t\t\t\tsnapGuides: this.webglSnapGuides,\n\t\t\t\tspacingIndicators: this.webglSpacingIndicators,\n\t\t\t\tdomPositionsUpdated: this.webglDomPositionsUpdated,\n\t\t\t},\n\t\t};\n\n\t\tif (this.tickRing.length < TICK_RING_SIZE) {\n\t\t\tthis.tickRing.push(sample);\n\t\t} else {\n\t\t\tthis.tickRing[this.tickWrite] = sample;\n\t\t}\n\t\tthis.tickWrite = (this.tickWrite + 1) % TICK_RING_SIZE;\n\t\tif (this.tickRing.length >= TICK_RING_SIZE) this.tickFilled = true;\n\t}\n\n\t// === R3F canvas instrumentation ===\n\n\t/**\n\t * Push one R3F frame sample. Called from the R3F canvas via a probe\n\t * component that has access to `useThree`.\n\t */\n\trecordR3FFrame(sample: Omit<R3FSample, 'timestamp'>) {\n\t\tif (!this.enabled) return;\n\t\tconst full: R3FSample = { ...sample, timestamp: performance.now() };\n\t\tif (this.r3fRing.length < R3F_RING_SIZE) {\n\t\t\tthis.r3fRing.push(full);\n\t\t} else {\n\t\t\tthis.r3fRing[this.r3fWrite] = full;\n\t\t}\n\t\tthis.r3fWrite = (this.r3fWrite + 1) % R3F_RING_SIZE;\n\t\tif (this.r3fRing.length >= R3F_RING_SIZE) this.r3fFilled = true;\n\t}\n\n\t// === Queries ===\n\n\t/** Get the last N tick samples (newest first). */\n\tgetSamples(count?: number): TickSample[] {\n\t\treturn readRing(this.tickRing, this.tickWrite, this.tickFilled, count);\n\t}\n\n\t/** Get the last N R3F samples (newest first). */\n\tgetR3FSamples(count?: number): R3FSample[] {\n\t\treturn readRing(this.r3fRing, this.r3fWrite, this.r3fFilled, count);\n\t}\n\n\t/** Compute rolling statistics across all three layers. */\n\tgetStats(): ProfilerStats {\n\t\treturn {\n\t\t\tecs: this.getEcsStats(),\n\t\t\twebgl: this.getWebGLStats(),\n\t\t\tr3f: this.getR3FStats(),\n\t\t};\n\t}\n\n\tprivate getEcsStats(): EcsStats {\n\t\tconst samples = this.tickRing;\n\t\tconst n = samples.length;\n\t\tif (n === 0) {\n\t\t\treturn {\n\t\t\t\tfps: 0,\n\t\t\t\tframeTime: { avg: 0, p50: 0, p95: 0, p99: 0, max: 0 },\n\t\t\t\tsystemAvg: {},\n\t\t\t\tsystemP95: {},\n\t\t\t\tbudgetUsed: 0,\n\t\t\t\tsampleCount: 0,\n\t\t\t};\n\t\t}\n\n\t\tconst frameTimes = samples.map((s) => s.totalMs).sort((a, b) => a - b);\n\t\tconst avg = mean(frameTimes);\n\n\t\tconst fps = ringFps(samples, this.tickWrite, this.tickFilled, TICK_RING_SIZE);\n\n\t\tconst systemNames = new Set<string>();\n\t\tfor (const s of samples) for (const k of Object.keys(s.ecs.systems)) systemNames.add(k);\n\n\t\tconst systemAvg: Record<string, number> = {};\n\t\tconst systemP95: Record<string, number> = {};\n\t\tfor (const name of systemNames) {\n\t\t\tconst times = samples.map((s) => s.ecs.systems[name] ?? 0).sort((a, b) => a - b);\n\t\t\tsystemAvg[name] = mean(times);\n\t\t\tsystemP95[name] = percentile(times, 95);\n\t\t}\n\n\t\treturn {\n\t\t\tfps,\n\t\t\tframeTime: {\n\t\t\t\tavg,\n\t\t\t\tp50: percentile(frameTimes, 50),\n\t\t\t\tp95: percentile(frameTimes, 95),\n\t\t\t\tp99: percentile(frameTimes, 99),\n\t\t\t\tmax: frameTimes[frameTimes.length - 1],\n\t\t\t},\n\t\t\tsystemAvg,\n\t\t\tsystemP95,\n\t\t\tbudgetUsed: (avg / 16.67) * 100,\n\t\t\tsampleCount: n,\n\t\t};\n\t}\n\n\tprivate getWebGLStats(): WebGLStats {\n\t\tconst samples = this.tickRing;\n\t\tconst n = samples.length;\n\t\tif (n === 0) {\n\t\t\treturn {\n\t\t\t\tfps: 0,\n\t\t\t\tframeTime: { avg: 0, p50: 0, p95: 0, p99: 0, max: 0 },\n\t\t\t\tbudgetUsed: 0,\n\t\t\t\tgridAvg: 0,\n\t\t\t\tgridP95: 0,\n\t\t\t\tselectionAvg: 0,\n\t\t\t\tselectionP95: 0,\n\t\t\t\tavgDrawCalls: 0,\n\t\t\t\tavgTriangles: 0,\n\t\t\t\tavgSelectionFrames: 0,\n\t\t\t\tavgSnapGuides: 0,\n\t\t\t\tavgDomUpdates: 0,\n\t\t\t\tsampleCount: 0,\n\t\t\t};\n\t\t}\n\t\tconst gridTimes = samples.map((s) => s.webgl.gridMs).sort((a, b) => a - b);\n\t\tconst selTimes = samples.map((s) => s.webgl.selectionMs).sort((a, b) => a - b);\n\t\tconst combinedTimes = samples\n\t\t\t.map((s) => s.webgl.gridMs + s.webgl.selectionMs)\n\t\t\t.sort((a, b) => a - b);\n\t\tconst combinedAvg = mean(combinedTimes);\n\t\tconst fps = ringFps(samples, this.tickWrite, this.tickFilled, TICK_RING_SIZE);\n\t\treturn {\n\t\t\tfps,\n\t\t\tframeTime: {\n\t\t\t\tavg: combinedAvg,\n\t\t\t\tp50: percentile(combinedTimes, 50),\n\t\t\t\tp95: percentile(combinedTimes, 95),\n\t\t\t\tp99: percentile(combinedTimes, 99),\n\t\t\t\tmax: combinedTimes[combinedTimes.length - 1],\n\t\t\t},\n\t\t\tbudgetUsed: (combinedAvg / 16.67) * 100,\n\t\t\tgridAvg: mean(gridTimes),\n\t\t\tgridP95: percentile(gridTimes, 95),\n\t\t\tselectionAvg: mean(selTimes),\n\t\t\tselectionP95: percentile(selTimes, 95),\n\t\t\tavgDrawCalls: mean(samples.map((s) => s.webgl.drawCalls)),\n\t\t\tavgTriangles: mean(samples.map((s) => s.webgl.triangles)),\n\t\t\tavgSelectionFrames: mean(samples.map((s) => s.webgl.selectionFrames)),\n\t\t\tavgSnapGuides: mean(samples.map((s) => s.webgl.snapGuides)),\n\t\t\tavgDomUpdates: mean(samples.map((s) => s.webgl.domPositionsUpdated)),\n\t\t\tsampleCount: n,\n\t\t};\n\t}\n\n\tprivate getR3FStats(): R3FStats {\n\t\tconst samples = this.r3fRing;\n\t\tconst n = samples.length;\n\t\tif (n === 0) {\n\t\t\treturn {\n\t\t\t\tfps: 0,\n\t\t\t\tframeTime: { avg: 0, p50: 0, p95: 0, p99: 0, max: 0 },\n\t\t\t\tavgDrawCalls: 0,\n\t\t\t\tavgTriangles: 0,\n\t\t\t\tprograms: 0,\n\t\t\t\tgeometries: 0,\n\t\t\t\ttextures: 0,\n\t\t\t\tactiveWidgets: 0,\n\t\t\t\tsampleCount: 0,\n\t\t\t};\n\t\t}\n\t\tconst dts = samples.map((s) => s.dtMs).sort((a, b) => a - b);\n\t\tconst fps = ringFps(samples, this.r3fWrite, this.r3fFilled, R3F_RING_SIZE);\n\t\t// Latest snapshot for gauge-style values.\n\t\tconst latestIdx = this.r3fFilled ? (this.r3fWrite - 1 + R3F_RING_SIZE) % R3F_RING_SIZE : n - 1;\n\t\tconst latest = samples[latestIdx];\n\t\treturn {\n\t\t\tfps,\n\t\t\tframeTime: {\n\t\t\t\tavg: mean(dts),\n\t\t\t\tp50: percentile(dts, 50),\n\t\t\t\tp95: percentile(dts, 95),\n\t\t\t\tp99: percentile(dts, 99),\n\t\t\t\tmax: dts[dts.length - 1],\n\t\t\t},\n\t\t\tavgDrawCalls: mean(samples.map((s) => s.drawCalls)),\n\t\t\tavgTriangles: mean(samples.map((s) => s.triangles)),\n\t\t\tprograms: latest.programs,\n\t\t\tgeometries: latest.geometries,\n\t\t\ttextures: latest.textures,\n\t\t\tactiveWidgets: latest.activeWidgets,\n\t\t\tsampleCount: n,\n\t\t};\n\t}\n\n\t/** Clear all collected data. */\n\tclear() {\n\t\tthis.tickRing = [];\n\t\tthis.tickWrite = 0;\n\t\tthis.tickFilled = false;\n\t\tthis.r3fRing = [];\n\t\tthis.r3fWrite = 0;\n\t\tthis.r3fFilled = false;\n\t}\n}\n\n// === Helpers ===\n\nfunction mean(xs: number[]): number {\n\tif (xs.length === 0) return 0;\n\tlet sum = 0;\n\tfor (const x of xs) sum += x;\n\treturn sum / xs.length;\n}\n\nfunction percentile(sorted: number[], p: number): number {\n\tif (sorted.length === 0) return 0;\n\tconst idx = Math.floor((p / 100) * (sorted.length - 1));\n\treturn sorted[idx] ?? 0;\n}\n\nfunction readRing<T extends { timestamp: number }>(\n\tring: T[],\n\twrite: number,\n\tfilled: boolean,\n\tcount: number | undefined,\n): T[] {\n\tconst n = ring.length;\n\tif (n === 0) return [];\n\tconst take = Math.min(count ?? n, n);\n\tconst out: T[] = [];\n\tfor (let i = 0; i < take; i++) {\n\t\tconst idx = (write - 1 - i + n) % n;\n\t\tout.push(ring[idx]);\n\t}\n\t// `filled` unused intentionally — wrap math above handles both phases.\n\tvoid filled;\n\treturn out;\n}\n\nfunction ringFps<T extends { timestamp: number }>(\n\tring: T[],\n\twrite: number,\n\tfilled: boolean,\n\tsize: number,\n): number {\n\tconst n = ring.length;\n\tif (n < 2) return 0;\n\tconst newest = ring[filled ? (write - 1 + size) % size : n - 1];\n\tconst oldest = ring[filled ? write : 0];\n\tconst spanMs = newest.timestamp - oldest.timestamp;\n\treturn spanMs > 0 ? Math.round(((n - 1) / spanMs) * 1000) : 0;\n}\n","import type { EntityId } from '@jamesyong42/reactive-ecs';\nimport type { StandardSchemaV1 } from '../schema.js';\n\n/** Rendering surface for a widget. */\nexport type WidgetSurface = 'dom' | 'webgl';\n\n// === Widget Prop Contracts ===\n\n/** Props passed to every DOM widget component. */\nexport interface DomWidgetProps {\n\tentityId: EntityId;\n}\n\n/** Props passed to every R3F widget component. Rendered in local coords. */\nexport interface R3FWidgetProps {\n\tentityId: EntityId;\n\t/** Widget width in world units. */\n\twidth: number;\n\t/** Widget height in world units. */\n\theight: number;\n}\n\n// === Widget Definitions ===\n\ninterface WidgetBase<T> {\n\t/** Unique widget type id. Matches `Widget { type }` on spawned entities. */\n\ttype: string;\n\t/**\n\t * Standard Schema v1-compatible schema for the widget's data.\n\t * Use Zod 3.24+, Valibot, ArkType, or any other conforming validator.\n\t * The schema's output type drives the widget's data type.\n\t */\n\t// biome-ignore lint/suspicious/noExplicitAny: schema Input is intentionally permissive\n\tschema: StandardSchemaV1<any, T>;\n\t/** Default data shape for new instances. Merged with user-supplied data at spawn. */\n\tdefaultData: T;\n\t/** Default world-space size at spawn. */\n\tdefaultSize: { width: number; height: number };\n\t/** Minimum world-space size when resizing. */\n\tminSize?: { width: number; height: number };\n}\n\n/** A DOM-rendered widget. The component is wrapped in a sized div — size via CSS. */\nexport interface DomWidget<T = Record<string, unknown>> extends WidgetBase<T> {\n\tsurface?: 'dom';\n\tcomponent: React.ComponentType<DomWidgetProps>;\n}\n\n/** An R3F (React Three Fiber) widget. The component receives local-space width/height. */\nexport interface R3FWidget<T = Record<string, unknown>> extends WidgetBase<T> {\n\tsurface: 'webgl';\n\tcomponent: React.ComponentType<R3FWidgetProps>;\n}\n\n/** Either kind of widget. */\nexport type Widget<T = Record<string, unknown>> = DomWidget<T> | R3FWidget<T>;\n\n// === Registry ===\n\nexport interface WidgetRegistry {\n\tregister(def: Widget): void;\n\tget(type: string): Widget | null;\n\tgetAll(): Widget[];\n}\n\nexport function createWidgetRegistry(defs: Widget[] = []): WidgetRegistry {\n\tconst map = new Map<string, Widget>();\n\tfor (const def of defs) map.set(def.type, def);\n\treturn {\n\t\tregister(def) {\n\t\t\tmap.set(def.type, def);\n\t\t},\n\t\tget(type) {\n\t\t\treturn map.get(type) ?? null;\n\t\t},\n\t\tgetAll() {\n\t\t\treturn [...map.values()];\n\t\t},\n\t};\n}\n\n/** Narrows to the R3F variant. */\nexport function isR3FWidget<T>(widget: Widget<T>): widget is R3FWidget<T> {\n\treturn widget.surface === 'webgl';\n}\n","/**\n * Snap guide computation for alignment during drag operations.\n * Implements Figma-style snapping:\n * 1. Edge/center alignment guides\n * 2. Equal spacing snap + indicators\n */\n\nexport interface SnapGuide {\n\t/** Axis this guide aligns on */\n\taxis: 'x' | 'y';\n\t/** World-space coordinate of the alignment line */\n\tposition: number;\n\t/** What kind of alignment */\n\ttype: 'edge' | 'center';\n}\n\nexport interface EqualSpacingIndicator {\n\t/** Axis along which the equal gaps run */\n\taxis: 'x' | 'y';\n\t/** The equal gap value (world units) */\n\tgap: number;\n\t/** Pairs of (from, to) marking each equal gap segment */\n\tsegments: { from: number; to: number }[];\n\t/** Position on the perpendicular axis (for rendering) */\n\tperpPosition: number;\n}\n\nexport interface SnapResult {\n\t/** Snap-corrected delta (world units). Apply to entity position. */\n\tsnapDx: number;\n\tsnapDy: number;\n\t/** Active alignment guide lines to render */\n\tguides: SnapGuide[];\n\t/** Equal spacing indicators */\n\tspacings: EqualSpacingIndicator[];\n}\n\nexport interface EntityBounds {\n\tx: number;\n\ty: number;\n\twidth: number;\n\theight: number;\n}\n\n/**\n * Compute snap guides for a dragged entity against reference entities.\n */\nexport function computeSnapGuides(\n\tdragged: EntityBounds,\n\treferences: EntityBounds[],\n\tthreshold: number,\n): SnapResult {\n\tconst guides: SnapGuide[] = [];\n\tconst spacings: EqualSpacingIndicator[] = [];\n\tlet snapDx = 0;\n\tlet snapDy = 0;\n\n\t// Dragged entity edges and center\n\tconst dLeft = dragged.x;\n\tconst dRight = dragged.x + dragged.width;\n\tconst dCenterX = dragged.x + dragged.width / 2;\n\tconst dTop = dragged.y;\n\tconst dBottom = dragged.y + dragged.height;\n\tconst dCenterY = dragged.y + dragged.height / 2;\n\n\tlet bestSnapX = Number.POSITIVE_INFINITY;\n\tlet bestSnapY = Number.POSITIVE_INFINITY;\n\tlet bestDx = 0;\n\tlet bestDy = 0;\n\tconst xGuides: SnapGuide[] = [];\n\tconst yGuides: SnapGuide[] = [];\n\n\t// --- Phase 1: Edge/center alignment ---\n\n\tfor (const ref of references) {\n\t\tconst rLeft = ref.x;\n\t\tconst rRight = ref.x + ref.width;\n\t\tconst rCenterX = ref.x + ref.width / 2;\n\t\tconst rTop = ref.y;\n\t\tconst rBottom = ref.y + ref.height;\n\t\tconst rCenterY = ref.y + ref.height / 2;\n\n\t\t// X-axis alignment (vertical guide lines)\n\t\tconst xPairs: [number, number, 'edge' | 'center'][] = [\n\t\t\t[dLeft, rLeft, 'edge'],\n\t\t\t[dLeft, rRight, 'edge'],\n\t\t\t[dRight, rLeft, 'edge'],\n\t\t\t[dRight, rRight, 'edge'],\n\t\t\t[dCenterX, rCenterX, 'center'],\n\t\t\t[dLeft, rCenterX, 'edge'],\n\t\t\t[dRight, rCenterX, 'edge'],\n\t\t];\n\n\t\tfor (const [dVal, rVal, type] of xPairs) {\n\t\t\tconst dist = Math.abs(dVal - rVal);\n\t\t\tif (dist <= threshold) {\n\t\t\t\tconst dx = rVal - dVal;\n\t\t\t\tif (dist < bestSnapX) {\n\t\t\t\t\tbestSnapX = dist;\n\t\t\t\t\tbestDx = dx;\n\t\t\t\t\txGuides.length = 0;\n\t\t\t\t}\n\t\t\t\tif (dist <= bestSnapX + 0.01) {\n\t\t\t\t\txGuides.push({ axis: 'x', position: rVal, type });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Y-axis alignment (horizontal guide lines)\n\t\tconst yPairs: [number, number, 'edge' | 'center'][] = [\n\t\t\t[dTop, rTop, 'edge'],\n\t\t\t[dTop, rBottom, 'edge'],\n\t\t\t[dBottom, rTop, 'edge'],\n\t\t\t[dBottom, rBottom, 'edge'],\n\t\t\t[dCenterY, rCenterY, 'center'],\n\t\t\t[dTop, rCenterY, 'edge'],\n\t\t\t[dBottom, rCenterY, 'edge'],\n\t\t];\n\n\t\tfor (const [dVal, rVal, type] of yPairs) {\n\t\t\tconst dist = Math.abs(dVal - rVal);\n\t\t\tif (dist <= threshold) {\n\t\t\t\tconst dy = rVal - dVal;\n\t\t\t\tif (dist < bestSnapY) {\n\t\t\t\t\tbestSnapY = dist;\n\t\t\t\t\tbestDy = dy;\n\t\t\t\t\tyGuides.length = 0;\n\t\t\t\t}\n\t\t\t\tif (dist <= bestSnapY + 0.01) {\n\t\t\t\t\tyGuides.push({ axis: 'y', position: rVal, type });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// --- Phase 2: Equal spacing snap ---\n\t// Check if we can place the dragged entity so that the gap to its\n\t// left and right (or top and bottom) neighbors are equal.\n\n\tconst eqResult = computeEqualSpacing(dragged, references, threshold);\n\n\t// Merge: alignment snap takes priority, equal spacing fills in the other axis\n\tif (bestSnapX <= threshold) {\n\t\tsnapDx = bestDx;\n\t} else if (eqResult.snapDx !== undefined) {\n\t\tsnapDx = eqResult.snapDx;\n\t}\n\tif (bestSnapY <= threshold) {\n\t\tsnapDy = bestDy;\n\t} else if (eqResult.snapDy !== undefined) {\n\t\tsnapDy = eqResult.snapDy;\n\t}\n\n\t// Collect alignment guides\n\tif (bestSnapX <= threshold) {\n\t\tconst seen = new Set<number>();\n\t\tfor (const g of xGuides) {\n\t\t\tif (!seen.has(g.position)) {\n\t\t\t\tseen.add(g.position);\n\t\t\t\tguides.push(g);\n\t\t\t}\n\t\t}\n\t}\n\tif (bestSnapY <= threshold) {\n\t\tconst seen = new Set<number>();\n\t\tfor (const g of yGuides) {\n\t\t\tif (!seen.has(g.position)) {\n\t\t\t\tseen.add(g.position);\n\t\t\t\tguides.push(g);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Collect equal spacing indicators (after applying snap)\n\tconst snappedBounds: EntityBounds = {\n\t\tx: dragged.x + snapDx,\n\t\ty: dragged.y + snapDy,\n\t\twidth: dragged.width,\n\t\theight: dragged.height,\n\t};\n\tconst eqFinal = computeEqualSpacing(snappedBounds, references, threshold * 0.5);\n\tspacings.push(...eqFinal.indicators);\n\n\treturn { snapDx, snapDy, guides, spacings };\n}\n\n// --- Equal spacing computation ---\n\ninterface EqualSpacingResult {\n\tsnapDx?: number;\n\tsnapDy?: number;\n\tindicators: EqualSpacingIndicator[];\n}\n\nfunction computeEqualSpacing(\n\tdragged: EntityBounds,\n\treferences: EntityBounds[],\n\tthreshold: number,\n): EqualSpacingResult {\n\tconst indicators: EqualSpacingIndicator[] = [];\n\tlet snapDx: number | undefined;\n\tlet snapDy: number | undefined;\n\n\t// Check X-axis (horizontal spacing)\n\tconst xResult = checkAxisSpacing(dragged, references, threshold, 'x');\n\tif (xResult) {\n\t\tsnapDx = xResult.snap;\n\t\tindicators.push(...xResult.indicators);\n\t}\n\n\t// Check Y-axis (vertical spacing)\n\tconst yResult = checkAxisSpacing(dragged, references, threshold, 'y');\n\tif (yResult) {\n\t\tsnapDy = yResult.snap;\n\t\tindicators.push(...yResult.indicators);\n\t}\n\n\treturn { snapDx, snapDy, indicators };\n}\n\nfunction checkAxisSpacing(\n\tdragged: EntityBounds,\n\treferences: EntityBounds[],\n\tthreshold: number,\n\taxis: 'x' | 'y',\n): { snap: number; indicators: EqualSpacingIndicator[] } | null {\n\tconst isX = axis === 'x';\n\n\t// Get position/size accessors based on axis\n\tconst pos = (b: EntityBounds) => (isX ? b.x : b.y);\n\tconst size = (b: EntityBounds) => (isX ? b.width : b.height);\n\tconst perpPos = (b: EntityBounds) => (isX ? b.y : b.x);\n\tconst perpSize = (b: EntityBounds) => (isX ? b.height : b.width);\n\tconst end = (b: EntityBounds) => pos(b) + size(b);\n\n\t// Filter to entities on the same perpendicular band (overlapping)\n\tconst neighbors = references.filter(\n\t\t(ref) =>\n\t\t\tperpPos(ref) < perpPos(dragged) + perpSize(dragged) &&\n\t\t\tperpPos(ref) + perpSize(ref) > perpPos(dragged),\n\t);\n\n\tif (neighbors.length < 1) return null;\n\n\t// Sort neighbors by position on this axis\n\tconst sorted = [...neighbors].sort((a, b) => pos(a) - pos(b));\n\n\t// Find existing gaps between consecutive reference entities\n\tconst refGaps: { from: EntityBounds; to: EntityBounds; gap: number }[] = [];\n\tfor (let i = 0; i < sorted.length - 1; i++) {\n\t\tconst gap = pos(sorted[i + 1]) - end(sorted[i]);\n\t\tif (gap > 0.1) {\n\t\t\trefGaps.push({ from: sorted[i], to: sorted[i + 1], gap });\n\t\t}\n\t}\n\n\tlet bestSnap: number | null = null;\n\tlet bestIndicators: EqualSpacingIndicator[] = [];\n\tlet bestDiff = Number.POSITIVE_INFINITY;\n\n\t// Case 1: Between two neighbors (left gap ≈ right gap)\n\t// Find the nearest left and right neighbors\n\tlet leftN: EntityBounds | null = null;\n\tlet rightN: EntityBounds | null = null;\n\tfor (const ref of sorted) {\n\t\tif (end(ref) <= pos(dragged) + threshold) {\n\t\t\tif (!leftN || end(ref) > end(leftN)) leftN = ref;\n\t\t}\n\t\tif (pos(ref) >= end(dragged) - threshold) {\n\t\t\tif (!rightN || pos(ref) < pos(rightN)) rightN = ref;\n\t\t}\n\t}\n\n\tif (leftN && rightN) {\n\t\tconst lGap = pos(dragged) - end(leftN);\n\t\tconst rGap = pos(rightN) - end(dragged);\n\t\tconst diff = Math.abs(lGap - rGap);\n\t\tif (diff <= threshold && diff < bestDiff) {\n\t\t\tconst idealPos = (end(leftN) + pos(rightN) - size(dragged)) / 2;\n\t\t\tconst snap = idealPos - pos(dragged);\n\t\t\tconst equalGap = (pos(rightN) - end(leftN) - size(dragged)) / 2;\n\t\t\tif (equalGap > 0.1) {\n\t\t\t\tconst perpY = computePerpCenter(dragged, [leftN, rightN], isX);\n\t\t\t\tbestSnap = snap;\n\t\t\t\tbestDiff = diff;\n\t\t\t\tbestIndicators = [\n\t\t\t\t\t{\n\t\t\t\t\t\taxis,\n\t\t\t\t\t\tgap: equalGap,\n\t\t\t\t\t\tsegments: [\n\t\t\t\t\t\t\t{ from: end(leftN), to: idealPos },\n\t\t\t\t\t\t\t{ from: idealPos + size(dragged), to: pos(rightN) },\n\t\t\t\t\t\t],\n\t\t\t\t\t\tperpPosition: perpY,\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\t}\n\n\t// Case 2: Extend pattern — dragged at the end or beginning of a row\n\t// Find gaps in the existing reference layout and try to match\n\tfor (const refGap of refGaps) {\n\t\tconst patternGap = refGap.gap;\n\n\t\t// Try placing dragged to the right of the rightmost entity in this pattern\n\t\tif (rightN === null || pos(refGap.to) >= end(dragged) - threshold * 2) {\n\t\t\t// Find the rightmost entity in the chain with this gap\n\t\t\tconst chainEnd = refGap.to;\n\t\t\t// Check: dragged gap to chainEnd matches patternGap?\n\t\t\tconst dragGap = pos(dragged) - end(chainEnd);\n\t\t\tconst diff = Math.abs(dragGap - patternGap);\n\t\t\tif (diff <= threshold && diff < bestDiff) {\n\t\t\t\tconst idealPos = end(chainEnd) + patternGap;\n\t\t\t\tconst snap = idealPos - pos(dragged);\n\t\t\t\tconst perpY = computePerpCenter(dragged, [refGap.from, refGap.to], isX);\n\t\t\t\tbestSnap = snap;\n\t\t\t\tbestDiff = diff;\n\t\t\t\t// Show all equal gaps: the existing one + the new one\n\t\t\t\tbestIndicators = [\n\t\t\t\t\t{\n\t\t\t\t\t\taxis,\n\t\t\t\t\t\tgap: patternGap,\n\t\t\t\t\t\tsegments: [\n\t\t\t\t\t\t\t{ from: end(refGap.from), to: pos(refGap.to) },\n\t\t\t\t\t\t\t{ from: end(chainEnd), to: idealPos },\n\t\t\t\t\t\t],\n\t\t\t\t\t\tperpPosition: perpY,\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\n\t\t// Try placing dragged to the left of the leftmost entity in this pattern\n\t\tif (leftN === null || end(refGap.from) <= pos(dragged) + threshold * 2) {\n\t\t\tconst chainStart = refGap.from;\n\t\t\tconst dragGap = pos(chainStart) - end(dragged);\n\t\t\tconst diff = Math.abs(dragGap - patternGap);\n\t\t\tif (diff <= threshold && diff < bestDiff) {\n\t\t\t\tconst idealPos = pos(chainStart) - patternGap - size(dragged);\n\t\t\t\tconst snap = idealPos - pos(dragged);\n\t\t\t\tconst perpY = computePerpCenter(dragged, [refGap.from, refGap.to], isX);\n\t\t\t\tbestSnap = snap;\n\t\t\t\tbestDiff = diff;\n\t\t\t\tbestIndicators = [\n\t\t\t\t\t{\n\t\t\t\t\t\taxis,\n\t\t\t\t\t\tgap: patternGap,\n\t\t\t\t\t\tsegments: [\n\t\t\t\t\t\t\t{ from: idealPos + size(dragged), to: pos(chainStart) },\n\t\t\t\t\t\t\t{ from: end(refGap.from), to: pos(refGap.to) },\n\t\t\t\t\t\t],\n\t\t\t\t\t\tperpPosition: perpY,\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t}\n\t\t}\n\t}\n\n\tif (bestSnap !== null) {\n\t\treturn { snap: bestSnap, indicators: bestIndicators };\n\t}\n\treturn null;\n}\n\nfunction computePerpCenter(dragged: EntityBounds, refs: EntityBounds[], isX: boolean): number {\n\tconst perpPos = (b: EntityBounds) => (isX ? b.y : b.x);\n\tconst perpSize = (b: EntityBounds) => (isX ? b.height : b.width);\n\tconst allBounds = [dragged, ...refs];\n\tconst maxStart = Math.max(...allBounds.map(perpPos));\n\tconst minEnd = Math.min(...allBounds.map((b) => perpPos(b) + perpSize(b)));\n\tif (minEnd < maxStart) {\n\t\t// No overlap — fall back to the dragged entity's perpendicular center\n\t\treturn perpPos(allBounds[0]) + perpSize(allBounds[0]) / 2;\n\t}\n\treturn maxStart + (minEnd - maxStart) / 2;\n}\n","\n/**\n * Rearranges items so that all items in the [left, k] are the smallest.\n * The k-th element will have the (k - left + 1)-th smallest value in [left, right].\n *\n * @template T\n * @param {T[]} arr the array to partially sort (in place)\n * @param {number} k middle index for partial sorting (as defined above)\n * @param {number} [left=0] left index of the range to sort\n * @param {number} [right=arr.length-1] right index\n * @param {(a: T, b: T) => number} [compare = (a, b) => a - b] compare function\n */\nexport default function quickselect(arr, k, left = 0, right = arr.length - 1, compare = defaultCompare) {\n\n while (right > left) {\n if (right - left > 600) {\n const n = right - left + 1;\n const m = k - left + 1;\n const z = Math.log(n);\n const s = 0.5 * Math.exp(2 * z / 3);\n const sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);\n const newLeft = Math.max(left, Math.floor(k - m * s / n + sd));\n const newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));\n quickselect(arr, k, newLeft, newRight, compare);\n }\n\n const t = arr[k];\n let i = left;\n /** @type {number} */\n let j = right;\n\n swap(arr, left, k);\n if (compare(arr[right], t) > 0) swap(arr, left, right);\n\n while (i < j) {\n swap(arr, i, j);\n i++;\n j--;\n while (compare(arr[i], t) < 0) i++;\n while (compare(arr[j], t) > 0) j--;\n }\n\n if (compare(arr[left], t) === 0) swap(arr, left, j);\n else {\n j++;\n swap(arr, j, right);\n }\n\n if (j <= k) left = j + 1;\n if (k <= j) right = j - 1;\n }\n}\n\n/**\n * @template T\n * @param {T[]} arr\n * @param {number} i\n * @param {number} j\n */\nfunction swap(arr, i, j) {\n const tmp = arr[i];\n arr[i] = arr[j];\n arr[j] = tmp;\n}\n\n/**\n * @template T\n * @param {T} a\n * @param {T} b\n * @returns {number}\n */\nfunction defaultCompare(a, b) {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n","import quickselect from 'quickselect';\n\nexport default class RBush {\n constructor(maxEntries = 9) {\n // max entries in a node is 9 by default; min node fill is 40% for best performance\n this._maxEntries = Math.max(4, maxEntries);\n this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));\n this.clear();\n }\n\n all() {\n return this._all(this.data, []);\n }\n\n search(bbox) {\n let node = this.data;\n const result = [];\n\n if (!intersects(bbox, node)) return result;\n\n const toBBox = this.toBBox;\n const nodesToSearch = [];\n\n while (node) {\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n const childBBox = node.leaf ? toBBox(child) : child;\n\n if (intersects(bbox, childBBox)) {\n if (node.leaf) result.push(child);\n else if (contains(bbox, childBBox)) this._all(child, result);\n else nodesToSearch.push(child);\n }\n }\n node = nodesToSearch.pop();\n }\n\n return result;\n }\n\n collides(bbox) {\n let node = this.data;\n\n if (!intersects(bbox, node)) return false;\n\n const nodesToSearch = [];\n while (node) {\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n const childBBox = node.leaf ? this.toBBox(child) : child;\n\n if (intersects(bbox, childBBox)) {\n if (node.leaf || contains(bbox, childBBox)) return true;\n nodesToSearch.push(child);\n }\n }\n node = nodesToSearch.pop();\n }\n\n return false;\n }\n\n load(data) {\n if (!(data && data.length)) return this;\n\n if (data.length < this._minEntries) {\n for (let i = 0; i < data.length; i++) {\n this.insert(data[i]);\n }\n return this;\n }\n\n // recursively build the tree with the given data from scratch using OMT algorithm\n let node = this._build(data.slice(), 0, data.length - 1, 0);\n\n if (!this.data.children.length) {\n // save as is if tree is empty\n this.data = node;\n\n } else if (this.data.height === node.height) {\n // split root if trees have the same height\n this._splitRoot(this.data, node);\n\n } else {\n if (this.data.height < node.height) {\n // swap trees if inserted one is bigger\n const tmpNode = this.data;\n this.data = node;\n node = tmpNode;\n }\n\n // insert the small tree into the large tree at appropriate level\n this._insert(node, this.data.height - node.height - 1, true);\n }\n\n return this;\n }\n\n insert(item) {\n if (item) this._insert(item, this.data.height - 1);\n return this;\n }\n\n clear() {\n this.data = createNode([]);\n return this;\n }\n\n remove(item, equalsFn) {\n if (!item) return this;\n\n let node = this.data;\n const bbox = this.toBBox(item);\n const path = [];\n const indexes = [];\n let i, parent, goingUp;\n\n // depth-first iterative tree traversal\n while (node || path.length) {\n\n if (!node) { // go up\n node = path.pop();\n parent = path[path.length - 1];\n i = indexes.pop();\n goingUp = true;\n }\n\n if (node.leaf) { // check current node\n const index = findItem(item, node.children, equalsFn);\n\n if (index !== -1) {\n // item found, remove the item and condense tree upwards\n node.children.splice(index, 1);\n path.push(node);\n this._condense(path);\n return this;\n }\n }\n\n if (!goingUp && !node.leaf && contains(node, bbox)) { // go down\n path.push(node);\n indexes.push(i);\n i = 0;\n parent = node;\n node = node.children[0];\n\n } else if (parent) { // go right\n i++;\n node = parent.children[i];\n goingUp = false;\n\n } else node = null; // nothing found\n }\n\n return this;\n }\n\n toBBox(item) { return item; }\n\n compareMinX(a, b) { return a.minX - b.minX; }\n compareMinY(a, b) { return a.minY - b.minY; }\n\n toJSON() { return this.data; }\n\n fromJSON(data) {\n this.data = data;\n return this;\n }\n\n _all(node, result) {\n const nodesToSearch = [];\n while (node) {\n if (node.leaf) result.push(...node.children);\n else nodesToSearch.push(...node.children);\n\n node = nodesToSearch.pop();\n }\n return result;\n }\n\n _build(items, left, right, height) {\n\n const N = right - left + 1;\n let M = this._maxEntries;\n let node;\n\n if (N <= M) {\n // reached leaf level; return leaf\n node = createNode(items.slice(left, right + 1));\n calcBBox(node, this.toBBox);\n return node;\n }\n\n if (!height) {\n // target height of the bulk-loaded tree\n height = Math.ceil(Math.log(N) / Math.log(M));\n\n // target number of root entries to maximize storage utilization\n M = Math.ceil(N / Math.pow(M, height - 1));\n }\n\n node = createNode([]);\n node.leaf = false;\n node.height = height;\n\n // split the items into M mostly square tiles\n\n const N2 = Math.ceil(N / M);\n const N1 = N2 * Math.ceil(Math.sqrt(M));\n\n multiSelect(items, left, right, N1, this.compareMinX);\n\n for (let i = left; i <= right; i += N1) {\n\n const right2 = Math.min(i + N1 - 1, right);\n\n multiSelect(items, i, right2, N2, this.compareMinY);\n\n for (let j = i; j <= right2; j += N2) {\n\n const right3 = Math.min(j + N2 - 1, right2);\n\n // pack each entry recursively\n node.children.push(this._build(items, j, right3, height - 1));\n }\n }\n\n calcBBox(node, this.toBBox);\n\n return node;\n }\n\n _chooseSubtree(bbox, node, level, path) {\n while (true) {\n path.push(node);\n\n if (node.leaf || path.length - 1 === level) break;\n\n let minArea = Infinity;\n let minEnlargement = Infinity;\n let targetNode;\n\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n const area = bboxArea(child);\n const enlargement = enlargedArea(bbox, child) - area;\n\n // choose entry with the least area enlargement\n if (enlargement < minEnlargement) {\n minEnlargement = enlargement;\n minArea = area < minArea ? area : minArea;\n targetNode = child;\n\n } else if (enlargement === minEnlargement) {\n // otherwise choose one with the smallest area\n if (area < minArea) {\n minArea = area;\n targetNode = child;\n }\n }\n }\n\n node = targetNode || node.children[0];\n }\n\n return node;\n }\n\n _insert(item, level, isNode) {\n const bbox = isNode ? item : this.toBBox(item);\n const insertPath = [];\n\n // find the best node for accommodating the item, saving all nodes along the path too\n const node = this._chooseSubtree(bbox, this.data, level, insertPath);\n\n // put the item into the node\n node.children.push(item);\n extend(node, bbox);\n\n // split on node overflow; propagate upwards if necessary\n while (level >= 0) {\n if (insertPath[level].children.length > this._maxEntries) {\n this._split(insertPath, level);\n level--;\n } else break;\n }\n\n // adjust bboxes along the insertion path\n this._adjustParentBBoxes(bbox, insertPath, level);\n }\n\n // split overflowed node into two\n _split(insertPath, level) {\n const node = insertPath[level];\n const M = node.children.length;\n const m = this._minEntries;\n\n this._chooseSplitAxis(node, m, M);\n\n const splitIndex = this._chooseSplitIndex(node, m, M);\n\n const newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));\n newNode.height = node.height;\n newNode.leaf = node.leaf;\n\n calcBBox(node, this.toBBox);\n calcBBox(newNode, this.toBBox);\n\n if (level) insertPath[level - 1].children.push(newNode);\n else this._splitRoot(node, newNode);\n }\n\n _splitRoot(node, newNode) {\n // split root node\n this.data = createNode([node, newNode]);\n this.data.height = node.height + 1;\n this.data.leaf = false;\n calcBBox(this.data, this.toBBox);\n }\n\n _chooseSplitIndex(node, m, M) {\n let index;\n let minOverlap = Infinity;\n let minArea = Infinity;\n\n for (let i = m; i <= M - m; i++) {\n const bbox1 = distBBox(node, 0, i, this.toBBox);\n const bbox2 = distBBox(node, i, M, this.toBBox);\n\n const overlap = intersectionArea(bbox1, bbox2);\n const area = bboxArea(bbox1) + bboxArea(bbox2);\n\n // choose distribution with minimum overlap\n if (overlap < minOverlap) {\n minOverlap = overlap;\n index = i;\n\n minArea = area < minArea ? area : minArea;\n\n } else if (overlap === minOverlap) {\n // otherwise choose distribution with minimum area\n if (area < minArea) {\n minArea = area;\n index = i;\n }\n }\n }\n\n return index || M - m;\n }\n\n // sorts node children by the best axis for split\n _chooseSplitAxis(node, m, M) {\n const compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;\n const compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;\n const xMargin = this._allDistMargin(node, m, M, compareMinX);\n const yMargin = this._allDistMargin(node, m, M, compareMinY);\n\n // if total distributions margin value is minimal for x, sort by minX,\n // otherwise it's already sorted by minY\n if (xMargin < yMargin) node.children.sort(compareMinX);\n }\n\n // total margin of all possible split distributions where each node is at least m full\n _allDistMargin(node, m, M, compare) {\n node.children.sort(compare);\n\n const toBBox = this.toBBox;\n const leftBBox = distBBox(node, 0, m, toBBox);\n const rightBBox = distBBox(node, M - m, M, toBBox);\n let margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);\n\n for (let i = m; i < M - m; i++) {\n const child = node.children[i];\n extend(leftBBox, node.leaf ? toBBox(child) : child);\n margin += bboxMargin(leftBBox);\n }\n\n for (let i = M - m - 1; i >= m; i--) {\n const child = node.children[i];\n extend(rightBBox, node.leaf ? toBBox(child) : child);\n margin += bboxMargin(rightBBox);\n }\n\n return margin;\n }\n\n _adjustParentBBoxes(bbox, path, level) {\n // adjust bboxes along the given tree path\n for (let i = level; i >= 0; i--) {\n extend(path[i], bbox);\n }\n }\n\n _condense(path) {\n // go through the path, removing empty nodes and updating bboxes\n for (let i = path.length - 1, siblings; i >= 0; i--) {\n if (path[i].children.length === 0) {\n if (i > 0) {\n siblings = path[i - 1].children;\n siblings.splice(siblings.indexOf(path[i]), 1);\n\n } else this.clear();\n\n } else calcBBox(path[i], this.toBBox);\n }\n }\n}\n\nfunction findItem(item, items, equalsFn) {\n if (!equalsFn) return items.indexOf(item);\n\n for (let i = 0; i < items.length; i++) {\n if (equalsFn(item, items[i])) return i;\n }\n return -1;\n}\n\n// calculate node's bbox from bboxes of its children\nfunction calcBBox(node, toBBox) {\n distBBox(node, 0, node.children.length, toBBox, node);\n}\n\n// min bounding rectangle of node children from k to p-1\nfunction distBBox(node, k, p, toBBox, destNode) {\n if (!destNode) destNode = createNode(null);\n destNode.minX = Infinity;\n destNode.minY = Infinity;\n destNode.maxX = -Infinity;\n destNode.maxY = -Infinity;\n\n for (let i = k; i < p; i++) {\n const child = node.children[i];\n extend(destNode, node.leaf ? toBBox(child) : child);\n }\n\n return destNode;\n}\n\nfunction extend(a, b) {\n a.minX = Math.min(a.minX, b.minX);\n a.minY = Math.min(a.minY, b.minY);\n a.maxX = Math.max(a.maxX, b.maxX);\n a.maxY = Math.max(a.maxY, b.maxY);\n return a;\n}\n\nfunction compareNodeMinX(a, b) { return a.minX - b.minX; }\nfunction compareNodeMinY(a, b) { return a.minY - b.minY; }\n\nfunction bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }\nfunction bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }\n\nfunction enlargedArea(a, b) {\n return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *\n (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));\n}\n\nfunction intersectionArea(a, b) {\n const minX = Math.max(a.minX, b.minX);\n const minY = Math.max(a.minY, b.minY);\n const maxX = Math.min(a.maxX, b.maxX);\n const maxY = Math.min(a.maxY, b.maxY);\n\n return Math.max(0, maxX - minX) *\n Math.max(0, maxY - minY);\n}\n\nfunction contains(a, b) {\n return a.minX <= b.minX &&\n a.minY <= b.minY &&\n b.maxX <= a.maxX &&\n b.maxY <= a.maxY;\n}\n\nfunction intersects(a, b) {\n return b.minX <= a.maxX &&\n b.minY <= a.maxY &&\n b.maxX >= a.minX &&\n b.maxY >= a.minY;\n}\n\nfunction createNode(children) {\n return {\n children,\n height: 1,\n leaf: true,\n minX: Infinity,\n minY: Infinity,\n maxX: -Infinity,\n maxY: -Infinity\n };\n}\n\n// sort an array so that items come in groups of n unsorted items, with groups sorted between each other;\n// combines selection algorithm with binary divide & conquer approach\n\nfunction multiSelect(arr, left, right, n, compare) {\n const stack = [left, right];\n\n while (stack.length) {\n right = stack.pop();\n left = stack.pop();\n\n if (right - left <= n) continue;\n\n const mid = left + Math.ceil((right - left) / n / 2) * n;\n quickselect(arr, mid, left, right, compare);\n\n stack.push(left, mid, mid, right);\n }\n}\n","import RBushImport from 'rbush';\n\n// Handle CJS/ESM interop — rbush exports differently depending on context\ntype RBushModule = typeof RBushImport & { default?: typeof RBushImport };\nconst rbushModule = RBushImport as RBushModule;\nconst RBush = (\n\ttypeof rbushModule.default === 'function' ? rbushModule.default : RBushImport\n) as typeof RBushImport;\n\nimport type { EntityId } from '@jamesyong42/reactive-ecs';\nimport type { AABB } from './math.js';\n\nexport interface SpatialEntry extends AABB {\n\tentityId: EntityId;\n}\n\n/**\n * Spatial index backed by an R-tree (rbush).\n * Stores world-space AABBs for fast viewport culling and hit testing.\n */\nexport class SpatialIndex {\n\tprivate tree = new RBush<SpatialEntry>();\n\tprivate entries = new Map<EntityId, SpatialEntry>();\n\n\tupsert(entityId: EntityId, bounds: AABB) {\n\t\tconst existing = this.entries.get(entityId);\n\t\tif (existing) {\n\t\t\t// Fix #8: Pass known reference directly — O(log n) instead of O(n) comparator scan\n\t\t\tthis.tree.remove(existing);\n\t\t}\n\t\tconst entry: SpatialEntry = { ...bounds, entityId };\n\t\tthis.entries.set(entityId, entry);\n\t\tthis.tree.insert(entry);\n\t}\n\n\tremove(entityId: EntityId) {\n\t\tconst existing = this.entries.get(entityId);\n\t\tif (existing) {\n\t\t\tthis.tree.remove(existing);\n\t\t\tthis.entries.delete(entityId);\n\t\t}\n\t}\n\n\t/** Query all entries intersecting the given AABB */\n\tsearch(bounds: AABB): SpatialEntry[] {\n\t\treturn this.tree.search(bounds);\n\t}\n\n\t/** Find the topmost entity at a point (by z-order — caller sorts) */\n\tsearchPoint(x: number, y: number, tolerance = 0): SpatialEntry[] {\n\t\treturn this.tree.search({\n\t\t\tminX: x - tolerance,\n\t\t\tminY: y - tolerance,\n\t\t\tmaxX: x + tolerance,\n\t\t\tmaxY: y + tolerance,\n\t\t});\n\t}\n\n\tclear() {\n\t\tthis.tree.clear();\n\t\tthis.entries.clear();\n\t}\n\n\tget size(): number {\n\t\treturn this.entries.size;\n\t}\n}\n","import type { EntityId, World } from '@jamesyong42/reactive-ecs';\nimport { defineSystem } from '@jamesyong42/reactive-ecs';\nimport type { CSSCursor, ResizeHandlePos } from './components.js';\nimport {\n\tActive,\n\tCard,\n\tChildren,\n\tCursorHint,\n\tHandleSet,\n\tHitbox,\n\tInteractionRole,\n\tParent,\n\tResizable,\n\tSelected,\n\tTransform2D,\n\tVisible,\n\tWidget,\n\tWidgetBreakpoint,\n\tWorldBounds,\n} from './components.js';\nimport { SpatialIndexResource } from './engine.js';\nimport { HANDLE_HIT_SIZE_PX } from './interaction-constants.js';\nimport { intersectsAABB, worldBoundsToAABB } from './math.js';\nimport type { Breakpoint } from './resources.js';\nimport {\n\tBreakpointConfigResource,\n\tCameraResource,\n\tCardPresetsResource,\n\tNavigationStackResource,\n\tViewportResource,\n} from './resources.js';\n\n/**\n * Stamp Transform2D width/height from Card.preset.\n * Runs before transformPropagateSystem so WorldBounds reflect the preset\n * size in the same tick. Manual writes to Transform2D.width/height on a\n * card entity get overwritten — to change card size, update `Card.preset`.\n */\nexport const cardSystem = defineSystem({\n\tname: 'card',\n\tbefore: 'transformPropagate',\n\texecute: (world: World) => {\n\t\tconst resource = world.getResource(CardPresetsResource);\n\t\tif (!resource) return;\n\t\tconst { presets } = resource;\n\n\t\tfor (const entity of world.query(Card, Transform2D)) {\n\t\t\tconst card = world.getComponent(entity, Card);\n\t\t\tconst transform = world.getComponent(entity, Transform2D);\n\t\t\tif (!card || !transform) continue;\n\t\t\tconst size = presets[card.preset];\n\t\t\tif (!size) continue;\n\t\t\tif (transform.width !== size.width || transform.height !== size.height) {\n\t\t\t\tworld.setComponent(entity, Transform2D, {\n\t\t\t\t\twidth: size.width,\n\t\t\t\t\theight: size.height,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t},\n});\n\n/**\n * Propagate transforms down the parent-child hierarchy.\n * Computes WorldBounds for every entity with Transform2D.\n * Uses change detection — only processes dirty entities and their descendants.\n */\nexport const transformPropagateSystem = defineSystem({\n\tname: 'transformPropagate',\n\texecute: (world: World) => {\n\t\tconst changed = world.queryChanged(Transform2D);\n\t\tconst processed = new Set<number>();\n\n\t\tfor (const entity of changed) {\n\t\t\tpropagateEntity(world, entity, processed);\n\t\t}\n\n\t\tfor (const entity of world.queryAdded(Transform2D)) {\n\t\t\tif (!processed.has(entity)) {\n\t\t\t\tpropagateEntity(world, entity, processed);\n\t\t\t}\n\t\t}\n\t},\n});\n\nfunction propagateEntity(world: World, entity: number, processed: Set<number>) {\n\tif (processed.has(entity)) return;\n\tprocessed.add(entity);\n\n\tconst transform = world.getComponent(entity, Transform2D);\n\tif (!transform) return;\n\n\tlet worldX = transform.x;\n\tlet worldY = transform.y;\n\n\tconst parentComp = world.getComponent(entity, Parent);\n\tif (parentComp && world.entityExists(parentComp.id)) {\n\t\t// Fix #7: Recursively propagate parent first if it hasn't been processed,\n\t\t// so we never read stale parent WorldBounds.\n\t\tif (!processed.has(parentComp.id)) {\n\t\t\tpropagateEntity(world, parentComp.id, processed);\n\t\t}\n\t\tconst parentBounds = world.getComponent(parentComp.id, WorldBounds);\n\t\tif (parentBounds) {\n\t\t\tworldX += parentBounds.worldX;\n\t\t\tworldY += parentBounds.worldY;\n\t\t}\n\t}\n\n\tif (!world.hasComponent(entity, WorldBounds)) {\n\t\tworld.addComponent(entity, WorldBounds, {\n\t\t\tworldX,\n\t\t\tworldY,\n\t\t\tworldWidth: transform.width,\n\t\t\tworldHeight: transform.height,\n\t\t});\n\t} else {\n\t\tworld.setComponent(entity, WorldBounds, {\n\t\t\tworldX,\n\t\t\tworldY,\n\t\t\tworldWidth: transform.width,\n\t\t\tworldHeight: transform.height,\n\t\t});\n\t}\n\n\tconst children = world.getComponent(entity, Children);\n\tif (children) {\n\t\tfor (const childId of children.ids) {\n\t\t\tpropagateEntity(world, childId, processed);\n\t\t}\n\t}\n}\n\n/**\n * Specification for the 8 resize handles spawned around a selected resizable.\n * anchorX/anchorY are in 0..1 parent-local coordinates.\n * Corners (layer 15) sit above edges (layer 10) so corners win overlapping hit tests.\n */\nconst HANDLE_SPECS: Array<{\n\tpos: ResizeHandlePos;\n\tax: number;\n\tay: number;\n\tlayer: number;\n\tcursor: CSSCursor;\n}> = [\n\t{ pos: 'nw', ax: 0, ay: 0, layer: 15, cursor: 'nw-resize' },\n\t{ pos: 'ne', ax: 1, ay: 0, layer: 15, cursor: 'ne-resize' },\n\t{ pos: 'sw', ax: 0, ay: 1, layer: 15, cursor: 'sw-resize' },\n\t{ pos: 'se', ax: 1, ay: 1, layer: 15, cursor: 'se-resize' },\n\t{ pos: 'n', ax: 0.5, ay: 0, layer: 10, cursor: 'n-resize' },\n\t{ pos: 's', ax: 0.5, ay: 1, layer: 10, cursor: 's-resize' },\n\t{ pos: 'w', ax: 0, ay: 0.5, layer: 10, cursor: 'w-resize' },\n\t{ pos: 'e', ax: 1, ay: 0.5, layer: 10, cursor: 'e-resize' },\n];\n\nfunction spawnResizeHandles(world: World, parentId: EntityId): void {\n\tconst S = HANDLE_HIT_SIZE_PX;\n\tconst parentActive = world.hasTag(parentId, Active);\n\tconst ids: EntityId[] = [];\n\n\tfor (const spec of HANDLE_SPECS) {\n\t\tconst id = world.createEntity();\n\t\tworld.addComponent(id, Parent, { id: parentId });\n\t\tworld.addComponent(id, Hitbox, {\n\t\t\tanchorX: spec.ax,\n\t\t\tanchorY: spec.ay,\n\t\t\twidth: S,\n\t\t\theight: S,\n\t\t});\n\t\tworld.addComponent(id, InteractionRole, {\n\t\t\tlayer: spec.layer,\n\t\t\trole: { type: 'resize', handle: spec.pos },\n\t\t});\n\t\tworld.addComponent(id, CursorHint, { hover: spec.cursor, active: spec.cursor });\n\t\tif (parentActive) world.addTag(id, Active);\n\t\tids.push(id);\n\t}\n\n\tworld.addComponent(parentId, HandleSet, { ids });\n}\n\nfunction despawnHandles(world: World, parentId: EntityId): void {\n\tconst set = world.getComponent(parentId, HandleSet);\n\tif (!set) return;\n\tfor (const id of set.ids) {\n\t\tif (world.entityExists(id)) world.destroyEntity(id);\n\t}\n\tworld.removeComponent(parentId, HandleSet);\n}\n\n/**\n * Spawn/despawn resize handle child entities based on selection state.\n * Handles appear only when exactly one Resizable entity is Selected.\n * Runs after transformPropagate (parent bounds fresh) and before hitboxWorldBounds\n * (so newly-spawned handles get their WorldBounds in the same tick).\n *\n * Phase 5: handles now drive interaction directly via the unified hit test —\n * InteractionRole + Hitbox on each handle entity replaces hitTestResizeHandle.\n */\nexport const handleSyncSystem = defineSystem({\n\tname: 'handleSync',\n\tafter: 'transformPropagate',\n\tbefore: 'hitboxWorldBounds',\n\texecute: (world: World) => {\n\t\t// Who should have handles right now? Exactly one selected resizable.\n\t\tconst selectedResizable: EntityId[] = [];\n\t\tfor (const entity of world.queryTagged(Resizable)) {\n\t\t\tif (world.hasTag(entity, Selected)) selectedResizable.push(entity);\n\t\t}\n\t\tconst shouldSpawn = selectedResizable.length === 1 ? selectedResizable[0] : null;\n\n\t\t// Despawn handles on anything that shouldn't have them.\n\t\t// Snapshot the query result before mutating.\n\t\tconst owners = world.query(HandleSet).slice();\n\t\tfor (const parentId of owners) {\n\t\t\tif (parentId !== shouldSpawn) despawnHandles(world, parentId);\n\t\t}\n\n\t\t// Spawn on the sole selected resizable if it doesn't already have them.\n\t\tif (shouldSpawn !== null && !world.hasComponent(shouldSpawn, HandleSet)) {\n\t\t\tspawnResizeHandles(world, shouldSpawn);\n\t\t}\n\n\t\t// Orphan sweep: handles whose parent has been destroyed out-of-band.\n\t\t// Fix #8: Only auto-destroy handle entities (resize/rotate), not other\n\t\t// Hitbox+Parent combos that may be user-created.\n\t\tfor (const entity of world.query(Hitbox, Parent).slice()) {\n\t\t\tconst parent = world.getComponent(entity, Parent);\n\t\t\tif (!parent || !world.entityExists(parent.id)) {\n\t\t\t\tconst role = world.getComponent(entity, InteractionRole);\n\t\t\t\tif (role && (role.role.type === 'resize' || role.role.type === 'rotate')) {\n\t\t\t\t\tworld.destroyEntity(entity);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n});\n\n/**\n * Derive WorldBounds for every entity with Hitbox + Parent from the parent's\n * WorldBounds + anchor offset. Runs after transformPropagateSystem so parent\n * WorldBounds are up to date. No-op until Phase 4 spawns entities with Hitbox.\n */\nexport const hitboxWorldBoundsSystem = defineSystem({\n\tname: 'hitboxWorldBounds',\n\tafter: 'transformPropagate',\n\texecute: (world: World) => {\n\t\tfor (const entity of world.query(Hitbox, Parent)) {\n\t\t\tconst parentRef = world.getComponent(entity, Parent);\n\t\t\tif (!parentRef) continue;\n\t\t\tif (!world.entityExists(parentRef.id)) continue;\n\n\t\t\tconst parentWB = world.getComponent(parentRef.id, WorldBounds);\n\t\t\tif (!parentWB) continue;\n\n\t\t\tconst hb = world.getComponent(entity, Hitbox);\n\t\t\tif (!hb) continue;\n\n\t\t\tconst cx = parentWB.worldX + parentWB.worldWidth * hb.anchorX;\n\t\t\tconst cy = parentWB.worldY + parentWB.worldHeight * hb.anchorY;\n\n\t\t\tconst next = {\n\t\t\t\tworldX: cx - hb.width / 2,\n\t\t\t\tworldY: cy - hb.height / 2,\n\t\t\t\tworldWidth: hb.width,\n\t\t\t\tworldHeight: hb.height,\n\t\t\t};\n\n\t\t\tif (world.hasComponent(entity, WorldBounds)) {\n\t\t\t\tworld.setComponent(entity, WorldBounds, next);\n\t\t\t} else {\n\t\t\t\tworld.addComponent(entity, WorldBounds, next);\n\t\t\t}\n\t\t}\n\t},\n});\n\n/**\n * Filter entities to the active navigation layer.\n * Runs on nav-stack changes (full refilter) and incrementally whenever new\n * Transform2D entities are added (so runtime spawns land in the active layer).\n */\nexport const navigationFilterSystem = defineSystem({\n\tname: 'navigationFilter',\n\tafter: 'transformPropagate',\n\texecute: (world: World) => {\n\t\tconst navStack = world.getResource(NavigationStackResource);\n\t\tconst stackChanged = navStack.changed;\n\t\tconst newEntities = world.queryAdded(Transform2D);\n\t\tif (!stackChanged && newEntities.length === 0) return;\n\n\t\tconst currentFrame = navStack.frames[navStack.frames.length - 1];\n\t\tconst activeContainer = currentFrame.containerId;\n\n\t\tconst belongsToCurrentFrame = (entity: number): boolean => {\n\t\t\tif (activeContainer === null) return !world.hasComponent(entity, Parent);\n\t\t\treturn world.getComponent(entity, Parent)?.id === activeContainer;\n\t\t};\n\n\t\tif (stackChanged) {\n\t\t\tfor (const entity of world.queryTagged(Active)) {\n\t\t\t\tworld.removeTag(entity, Active);\n\t\t\t}\n\t\t\tfor (const entity of world.query(Transform2D)) {\n\t\t\t\tif (belongsToCurrentFrame(entity)) world.addTag(entity, Active);\n\t\t\t}\n\t\t\t// Fix #9: Intentional direct mutation — navStack.changed is a side-channel\n\t\t\t// flag read by engine.tick() before systems run. Using setResource() here\n\t\t\t// would trigger unnecessary resource-change bookkeeping on a hot path.\n\t\t\tnavStack.changed = false;\n\t\t} else {\n\t\t\tfor (const entity of newEntities) {\n\t\t\t\tif (belongsToCurrentFrame(entity) && !world.hasTag(entity, Active)) {\n\t\t\t\t\tworld.addTag(entity, Active);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n});\n\n/**\n * Viewport culling — mark Active entities that intersect the viewport as Visible.\n */\nexport const cullSystem = defineSystem({\n\tname: 'cull',\n\tafter: 'navigationFilter',\n\texecute: (world: World) => {\n\t\tconst camera = world.getResource(CameraResource);\n\t\tconst viewport = world.getResource(ViewportResource);\n\t\tif (viewport.width === 0 || viewport.height === 0) return;\n\n\t\tconst res = world.getResource(SpatialIndexResource);\n\t\tconst spatialIndex = res.instance;\n\n\t\tconst overscan = 200 / camera.zoom;\n\t\tconst vpWorldAABB = {\n\t\t\tminX: camera.x - overscan,\n\t\t\tminY: camera.y - overscan,\n\t\t\tmaxX: camera.x + viewport.width / camera.zoom + overscan,\n\t\t\tmaxY: camera.y + viewport.height / camera.zoom + overscan,\n\t\t};\n\n\t\tfor (const entity of world.queryTagged(Visible)) {\n\t\t\tworld.removeTag(entity, Visible);\n\t\t}\n\n\t\tif (spatialIndex && spatialIndex.size > 0) {\n\t\t\tconst candidates = spatialIndex.search(vpWorldAABB);\n\t\t\tfor (const entry of candidates) {\n\t\t\t\tif (world.hasTag(entry.entityId, Active)) {\n\t\t\t\t\tworld.addTag(entry.entityId, Visible);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor (const entity of world.queryTagged(Active)) {\n\t\t\t\tconst wb = world.getComponent(entity, WorldBounds);\n\t\t\t\tif (wb && intersectsAABB(worldBoundsToAABB(wb), vpWorldAABB)) {\n\t\t\t\t\tworld.addTag(entity, Visible);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n});\n\n/**\n * Compute breakpoints for visible widgets based on screen size.\n * Fix #10: Always update screenWidth/screenHeight even if breakpoint tier doesn't change.\n */\nexport const breakpointSystem = defineSystem({\n\tname: 'breakpoint',\n\tafter: 'cull',\n\texecute: (world: World) => {\n\t\tconst camera = world.getResource(CameraResource);\n\t\tconst config = world.getResource(BreakpointConfigResource);\n\n\t\tfor (const entity of world.query(Widget, Visible)) {\n\t\t\tconst transform = world.getComponent(entity, Transform2D);\n\t\t\tif (!transform) continue;\n\n\t\t\tconst screenWidth = transform.width * camera.zoom;\n\t\t\tconst screenHeight = transform.height * camera.zoom;\n\n\t\t\tlet bp: Breakpoint;\n\t\t\tif (screenWidth < config.micro) bp = 'micro';\n\t\t\telse if (screenWidth < config.compact) bp = 'compact';\n\t\t\telse if (screenWidth < config.normal) bp = 'normal';\n\t\t\telse if (screenWidth < config.expanded) bp = 'expanded';\n\t\t\telse bp = 'detailed';\n\n\t\t\tconst existing = world.getComponent(entity, WidgetBreakpoint);\n\t\t\tif (!existing) {\n\t\t\t\tworld.addComponent(entity, WidgetBreakpoint, {\n\t\t\t\t\tcurrent: bp,\n\t\t\t\t\tscreenWidth,\n\t\t\t\t\tscreenHeight,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Fix #10: Update if breakpoint tier changed OR screen dimensions changed significantly.\n\t\t\t\t// Compare rounded values to avoid floating-point instability at fractional zoom levels.\n\t\t\t\tconst bpChanged = existing.current !== bp;\n\t\t\t\tconst sizeChanged =\n\t\t\t\t\tMath.round(existing.screenWidth) !== Math.round(screenWidth) ||\n\t\t\t\t\tMath.round(existing.screenHeight) !== Math.round(screenHeight);\n\n\t\t\t\tif (bpChanged || sizeChanged) {\n\t\t\t\t\tworld.setComponent(entity, WidgetBreakpoint, {\n\t\t\t\t\t\tcurrent: bp,\n\t\t\t\t\t\tscreenWidth,\n\t\t\t\t\t\tscreenHeight,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n});\n\n/**\n * Sort visible entities by z-index (handled in engine.tick()).\n */\nexport const sortSystem = defineSystem({\n\tname: 'sort',\n\tafter: 'breakpoint',\n\texecute: (_world: World) => {\n\t\t// Sorting is done in engine.tick() after systems run\n\t},\n});\n","import type {\n\tComponentInit,\n\tComponentType,\n\tEntityId,\n\tSystemDef,\n\tTagType,\n\tUnsubscribe,\n\tWorld,\n} from '@jamesyong42/reactive-ecs';\nimport { createWorld, defineResource, SystemScheduler } from '@jamesyong42/reactive-ecs';\nimport type { Archetype, ArchetypeRegistry, SpawnOptions } from './archetype.js';\nimport { createArchetypeRegistry } from './archetype.js';\nimport type { Command } from './commands.js';\nimport { CommandBuffer, MoveCommand, ResizeCommand } from './commands.js';\nimport type {\n\tCardPreset,\n\tCSSCursor,\n\tInteractionRoleData,\n\tInteractionRoleType,\n\tResizeHandlePos,\n} from './components.js';\nimport {\n\tActive,\n\tChildren,\n\tContainer,\n\tCursorHint,\n\tDraggable,\n\tDragging,\n\tHandleSet,\n\tHitbox,\n\tInteractionRole,\n\tParent,\n\tResizable,\n\tSelectable,\n\tSelected,\n\tSelectionFrame,\n\tTransform2D,\n\tVisible,\n\tWidget,\n\tWidgetBreakpoint,\n\tWidgetData,\n\tWorldBounds,\n\tZIndex,\n} from './components.js';\nimport { DEAD_ZONE_MOUSE_PX, MIN_WIDGET_SIZE } from './interaction-constants.js';\nimport { clamp, screenToWorld, worldBoundsToAABB } from './math.js';\nimport { Profiler } from './profiler.js';\nimport type { Widget as WidgetDef, WidgetRegistry } from './react/registry.js';\nimport { createWidgetRegistry } from './react/registry.js';\nimport type { Breakpoint } from './resources.js';\nimport {\n\tBreakpointConfigResource,\n\tCameraResource,\n\tCardPresetsResource,\n\tCursorResource,\n\tNavigationStackResource,\n\tViewportResource,\n\tZoomConfigResource,\n} from './resources.js';\nimport type { StandardSchemaV1 } from './schema.js';\nimport type { EqualSpacingIndicator, SnapGuide, SnapResult } from './snap.js';\nimport { computeSnapGuides } from './snap.js';\nimport { SpatialIndex } from './spatial.js';\nimport {\n\tbreakpointSystem,\n\tcardSystem,\n\tcullSystem,\n\thandleSyncSystem,\n\thitboxWorldBoundsSystem,\n\tnavigationFilterSystem,\n\tsortSystem,\n\ttransformPropagateSystem,\n} from './systems.js';\n\n/** ECS resource holding the SpatialIndex instance for viewport culling and hit testing. */\nexport const SpatialIndexResource = defineResource('SpatialIndex', {\n\tinstance: null as SpatialIndex | null,\n});\n\n// === Pointer Directives ===\n\n/** Directive returned by pointer handlers indicating how the canvas should handle capture. */\nexport type PointerDirective =\n\t| { action: 'passthrough' }\n\t| { action: 'passthrough-track-drag' }\n\t| { action: 'capture-drag' }\n\t| { action: 'capture-resize'; handle: ResizeHandlePos }\n\t| { action: 'capture-marquee' };\n\nexport type { ResizeHandlePos } from './components.js';\n\n/** Keyboard modifier state captured alongside pointer events. */\nexport interface Modifiers {\n\tshift: boolean;\n\tctrl: boolean;\n\talt: boolean;\n\tmeta: boolean;\n}\n\n// === Input state machine ===\n\ntype InputState =\n\t| { mode: 'idle' }\n\t| { mode: 'tracking'; entityId: EntityId; startX: number; startY: number }\n\t| {\n\t\t\tmode: 'dragging';\n\t\t\tentityId: EntityId;\n\t\t\tstartScreenX: number;\n\t\t\tstartScreenY: number;\n\t\t\tstartPositions: Map<EntityId, { x: number; y: number }>;\n\t\t\toriginalZIndices: Map<EntityId, number>;\n\t }\n\t| {\n\t\t\tmode: 'resizing';\n\t\t\tentityId: EntityId;\n\t\t\t/**\n\t\t\t * The child handle entity that was hit (not the parent widget).\n\t\t\t * Phase 7's cursorSystem reads CursorHint from this id.\n\t\t\t */\n\t\t\thandleEntityId: EntityId;\n\t\t\thandle: ResizeHandlePos;\n\t\t\tstartX: number;\n\t\t\tstartY: number;\n\t\t\tstartBounds: { x: number; y: number; width: number; height: number };\n\t }\n\t| { mode: 'marquee'; startX: number; startY: number };\n\n// === Visible entity for renderers ===\n\n/** A visible entity with its computed world-space bounds and display metadata. */\nexport interface VisibleEntity {\n\tentityId: EntityId;\n\tworldX: number;\n\tworldY: number;\n\tworldWidth: number;\n\tworldHeight: number;\n\tbreakpoint: Breakpoint;\n\tzIndex: number;\n\tsurface: string;\n\twidgetType: string;\n}\n\n// === Frame changes ===\n\n/** Per-frame change flags indicating what changed during the last tick. */\nexport interface FrameChanges {\n\t/** Entities whose world-space position or size changed. */\n\tpositionsChanged: EntityId[];\n\t/** Entities whose responsive breakpoint changed. */\n\tbreakpointsChanged: EntityId[];\n\t/** Entities that entered the visible viewport. */\n\tentered: EntityId[];\n\t/** Entities that exited the visible viewport. */\n\texited: EntityId[];\n\t/** Whether the camera position or zoom changed. */\n\tcameraChanged: boolean;\n\t/** Whether the navigation stack changed (entered/exited container). */\n\tnavigationChanged: boolean;\n\t/** Whether the selection set changed. */\n\tselectionChanged: boolean;\n}\n\n// === Engine Config ===\n\n/** Configuration options for `createLayoutEngine()`. */\nexport interface LayoutEngineConfig {\n\t/** Maximum entity count (default: 10000). */\n\tmaxEntities?: number;\n\t/** Minimum and maximum zoom levels. */\n\tzoom?: { min: number; max: number };\n\t/** Screen-space pixel thresholds for responsive breakpoints. */\n\tbreakpoints?: { micro: number; compact: number; normal: number; expanded: number };\n\t/** Snap alignment configuration. */\n\tsnap?: {\n\t\t/** Whether snapping is enabled initially. */\n\t\tenabled?: boolean;\n\t\t/** Snap distance threshold in screen pixels. */\n\t\tthreshold?: number;\n\t};\n\t/** Widget definitions available to `spawn()`. */\n\twidgets?: WidgetDef[];\n\t/** Archetype definitions available to `spawn()`. */\n\tarchetypes?: Archetype[];\n\t/**\n\t * Override the default iOS-style card preset sizes (small/medium/large/xl).\n\t * Partial — unspecified presets keep their built-in defaults.\n\t */\n\tcardPresets?: {\n\t\tpresets?: Partial<Record<CardPreset, { width: number; height: number }>>;\n\t\tgap?: number;\n\t};\n}\n\n// === Engine ===\n\n/**\n * The core layout engine. Manages the ECS world, camera, input, undo/redo,\n * spatial indexing, and frame lifecycle for an infinite canvas.\n */\nexport interface LayoutEngine {\n\t/** The underlying ECS world. Use for direct component/tag/resource access. */\n\treadonly world: World;\n\n\t// Entity CRUD\n\n\t/** Creates a bare entity with optional initial components/tags. Low-level escape hatch. */\n\tcreateEntity(inits?: ComponentInit[]): EntityId;\n\t/**\n\t * Spawns a new entity from a registered archetype or widget type.\n\t * If `id` matches a registered archetype, that archetype is used.\n\t * Otherwise, if `id` matches a registered widget, a default archetype is synthesized.\n\t * Otherwise, a bare default archetype with type=`id` is used (useful in tests).\n\t */\n\tspawn(id: string, opts?: SpawnOptions): EntityId;\n\t/** Spawns at the current camera viewport centre (sized from the archetype/widget default). */\n\tspawnAtCameraCenter(id: string, opts?: Omit<SpawnOptions, 'at'>): EntityId;\n\t/** Removes an entity and cleans up all components, tags, and spatial index entries. */\n\tdestroyEntity(id: EntityId): void;\n\n\t// Widget / Archetype registries\n\n\t/** Registers a widget definition. Auto-creates a matching default archetype if none exists. */\n\tregisterWidget(widget: WidgetDef): void;\n\t/** Returns a registered widget by type, or null. */\n\tgetWidget(type: string): WidgetDef | null;\n\t/** Returns all registered widgets. */\n\tgetWidgets(): WidgetDef[];\n\t/** Registers a custom archetype. */\n\tregisterArchetype(archetype: Archetype): void;\n\t/** Returns a registered archetype by id, or null. */\n\tgetArchetype(id: string): Archetype | null;\n\n\t// Shorthand\n\n\t/** Reads a component from an entity. Returns undefined if not present. */\n\tget<T>(entity: EntityId, type: ComponentType<T>): T | undefined;\n\t/** Updates a component on an entity (partial merge). */\n\tset<T>(entity: EntityId, type: ComponentType<T>, data: Partial<T>): void;\n\t/** Checks if an entity has a component or tag. */\n\thas(entity: EntityId, type: ComponentType | TagType): boolean;\n\t/** Attaches a component to an entity. Uses type defaults if `data` is omitted. Marks dirty. */\n\taddComponent<T>(entity: EntityId, type: ComponentType<T>, data?: T): void;\n\t/** Removes a component from an entity. Marks dirty. */\n\tremoveComponent(entity: EntityId, type: ComponentType): void;\n\t/** Adds a tag to an entity. Marks dirty. */\n\taddTag(entity: EntityId, type: TagType): void;\n\t/** Removes a tag from an entity. Marks dirty. */\n\tremoveTag(entity: EntityId, type: TagType): void;\n\t/** Returns the Standard Schema for a widget entity's `WidgetData.data`, if the widget declared one. */\n\tgetSchemaFor(entity: EntityId): StandardSchemaV1 | undefined;\n\n\t// Extensions\n\n\t/** Registers a custom ECS system to run each tick. */\n\tregisterSystem(system: SystemDef): void;\n\t/** Removes a registered system by name. */\n\tremoveSystem(name: string): void;\n\n\t// Camera\n\n\t/** Returns the current camera state {x, y, zoom}. */\n\tgetCamera(): { x: number; y: number; zoom: number };\n\t/** Moves the camera by the specified screen-space delta. */\n\tpanBy(dx: number, dy: number): void;\n\t/** Moves the camera to the specified world coordinates. */\n\tpanTo(worldX: number, worldY: number): void;\n\t/** Adjusts zoom level anchored at a screen point. Delta is a multiplier offset. */\n\tzoomAtPoint(screenX: number, screenY: number, delta: number): void;\n\t/** Sets the zoom level directly. */\n\tzoomTo(zoom: number): void;\n\t/** Adjusts camera to fit all entities (or specified entities) in the viewport. */\n\tzoomToFit(entityIds?: EntityId[], padding?: number): void;\n\n\t// Viewport\n\n\t/** Updates the viewport dimensions. Called automatically by InfiniteCanvas on resize. */\n\tsetViewport(width: number, height: number, dpr?: number): void;\n\n\t// Pointer input\n\n\t/** Pointer-down handler. Returns a directive for how the canvas should capture the pointer. */\n\thandlePointerDown(\n\t\tscreenX: number,\n\t\tscreenY: number,\n\t\tbutton: number,\n\t\tmodifiers: Modifiers,\n\t): PointerDirective;\n\t/** Pointer-move handler. Returns a directive reflecting the current interaction. */\n\thandlePointerMove(screenX: number, screenY: number, modifiers: Modifiers): PointerDirective;\n\t/** Pointer-up handler. Commits drags/resizes and returns a directive. */\n\thandlePointerUp(): PointerDirective;\n\t/** Cancels the current pointer interaction without committing changes. */\n\thandlePointerCancel(): void;\n\n\t// Selection & Hover\n\n\t/** Returns IDs of all currently selected entities. */\n\tgetSelectedEntities(): EntityId[];\n\t/** Returns the entity currently under the pointer, or null. */\n\tgetHoveredEntity(): EntityId | null;\n\n\t// Navigation\n\n\t/** Navigates into a container entity, pushing the current camera onto the navigation stack. */\n\tenterContainer(entity: EntityId): void;\n\t/** Navigates out of the current container, restoring the previous camera state. */\n\texitContainer(): void;\n\t/** Returns the entity ID of the currently active container, or null if at root. */\n\tgetActiveContainer(): EntityId | null;\n\t/** Returns the current navigation depth (0 = root). */\n\tgetNavigationDepth(): number;\n\n\t// Commands + Undo/Redo\n\n\t/** Executes a command and pushes it onto the undo stack. */\n\texecute(command: Command): void;\n\t/** Begins a command group -- subsequent commands are bundled into one undo step. */\n\tbeginCommandGroup(): void;\n\t/** Ends the current command group. */\n\tendCommandGroup(): void;\n\t/** Undoes the last command or command group. Returns true if anything was undone. */\n\tundo(): boolean;\n\t/** Redoes the last undone command. Returns true if anything was redone. */\n\tredo(): boolean;\n\t/** Returns whether there is a command to undo. */\n\tcanUndo(): boolean;\n\t/** Returns whether there is a command to redo. */\n\tcanRedo(): boolean;\n\n\t// Frame\n\n\t/** Schedules a tick on the next animation frame. Call after programmatic changes. */\n\tmarkDirty(): void;\n\t/** Runs one frame: executes all ECS systems, updates spatial index, emits frame events. */\n\ttick(): void;\n\t/** Ticks only if dirty. Returns true if a tick was performed. */\n\tflushIfDirty(): boolean;\n\n\t// Output\n\n\t/** Returns visible entities with their world-space bounds, breakpoint, and surface info. */\n\tgetVisibleEntities(): VisibleEntity[];\n\t/** Returns per-frame change flags from the last tick. */\n\tgetFrameChanges(): FrameChanges;\n\n\t// Spatial index (exposed for systems)\n\n\t/** Returns the spatial index used for viewport culling and hit testing. */\n\tgetSpatialIndex(): SpatialIndex;\n\n\t// Snap guides\n\n\t/** Returns active snap guide lines from the last tick. */\n\tgetSnapGuides(): SnapGuide[];\n\t/** Returns equal-spacing indicators from the last tick. */\n\tgetEqualSpacing(): EqualSpacingIndicator[];\n\t/** Enables or disables snap alignment. */\n\tsetSnapEnabled(on: boolean): void;\n\t/** Sets the snap distance threshold in world pixels. */\n\tsetSnapThreshold(worldPx: number): void;\n\n\t// Performance profiling\n\n\t/** Performance profiler for measuring system execution times. */\n\treadonly profiler: Profiler;\n\n\t// Events\n\n\t/** Registers a callback invoked after each tick. Returns an unsubscribe function. */\n\tonFrame(handler: () => void): Unsubscribe;\n\n\t// Lifecycle\n\n\t/** Destroys the engine, releasing all resources and subscriptions. */\n\tdestroy(): void;\n}\n\n/**\n * Creates a new LayoutEngine instance with the given configuration.\n * This is the main entry point for the infinite canvas library.\n */\nexport function createLayoutEngine(config?: LayoutEngineConfig): LayoutEngine {\n\tconst world = createWorld();\n\tconst scheduler = new SystemScheduler();\n\tconst spatialIndex = new SpatialIndex();\n\tconst profiler = new Profiler();\n\tscheduler.profiler = profiler;\n\n\t// Fix #11: Store spatial index as a proper resource\n\tworld.setResource(SpatialIndexResource, { instance: spatialIndex });\n\n\tconst commandBuffer = new CommandBuffer();\n\n\t// Widget + archetype registries. Archetype registry holds explicit archetypes\n\t// and auto-synthesized defaults for widgets without explicit archetypes.\n\tconst widgetRegistry: WidgetRegistry = createWidgetRegistry();\n\tconst archetypeRegistry: ArchetypeRegistry = createArchetypeRegistry();\n\n\t// Apply config\n\tif (config?.zoom) {\n\t\tworld.setResource(ZoomConfigResource, config.zoom);\n\t}\n\tif (config?.breakpoints) {\n\t\tworld.setResource(BreakpointConfigResource, config.breakpoints);\n\t}\n\tif (config?.cardPresets) {\n\t\tconst current = world.getResource(CardPresetsResource);\n\t\tworld.setResource(CardPresetsResource, {\n\t\t\tpresets: { ...current.presets, ...config.cardPresets.presets },\n\t\t\tgap: config.cardPresets.gap ?? current.gap,\n\t\t});\n\t}\n\n\t// Apply snap config\n\tlet snapEnabledInit = true;\n\tlet snapThresholdInit = 5;\n\tif (config?.snap?.enabled !== undefined) snapEnabledInit = config.snap.enabled;\n\tif (config?.snap?.threshold !== undefined) snapThresholdInit = config.snap.threshold;\n\n\t// Register built-in systems. cardSystem runs first via its `before`\n\t// declaration so Transform2D reflects card presets before propagation.\n\tscheduler.register(cardSystem);\n\tscheduler.register(transformPropagateSystem);\n\tscheduler.register(handleSyncSystem);\n\tscheduler.register(hitboxWorldBoundsSystem);\n\tscheduler.register(navigationFilterSystem);\n\tscheduler.register(cullSystem);\n\tscheduler.register(breakpointSystem);\n\tscheduler.register(sortSystem);\n\n\t// Collect observer unsubscribe functions for cleanup in destroy()\n\tconst unsubscribers: Unsubscribe[] = [];\n\n\t// P3: Wire spatial index reactively via observer instead of per-frame system scan\n\tunsubscribers.push(\n\t\tworld.onComponentChanged(WorldBounds, (entityId, _prev, wb) => {\n\t\t\tif (wb) {\n\t\t\t\tspatialIndex.upsert(entityId, worldBoundsToAABB(wb));\n\t\t\t}\n\t\t}),\n\t);\n\n\t// Fix #3: Clean up spatial index when ANY entity is destroyed (including\n\t// handles destroyed directly by systems via world.destroyEntity).\n\tunsubscribers.push(\n\t\tworld.onEntityDestroyed((entity) => {\n\t\t\tspatialIndex.remove(entity);\n\t\t}),\n\t);\n\n\t// Auto-attach InteractionRole and CursorHint based on Draggable/Selectable\n\t// tag presence. This lets users create entities via createEntity() with the\n\t// traditional tag-based API without needing to know about the new\n\t// InteractionRole component introduced in RFC-001. addWidget's path\n\t// continues to work because it adds the same tags. Entities with an\n\t// explicit resize/rotate/connect role (e.g. spawned handles) are left\n\t// alone so this never fights handleSyncSystem.\n\tfunction refreshInteractionRole(entity: EntityId): void {\n\t\tconst current = world.getComponent(entity, InteractionRole);\n\t\t// Never touch roles we don't own (resize/rotate/connect live on handles\n\t\t// and future sub-entities; they are managed explicitly by their spawner).\n\t\tif (\n\t\t\tcurrent &&\n\t\t\tcurrent.role.type !== 'drag' &&\n\t\t\tcurrent.role.type !== 'select' &&\n\t\t\tcurrent.role.type !== 'canvas'\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst hasDraggable = world.hasTag(entity, Draggable);\n\t\tconst hasSelectable = world.hasTag(entity, Selectable);\n\t\tconst desiredRole: InteractionRoleType | null = hasDraggable\n\t\t\t? { type: 'drag' }\n\t\t\t: hasSelectable\n\t\t\t\t? { type: 'select' }\n\t\t\t\t: null;\n\n\t\tif (desiredRole === null) {\n\t\t\tif (current) world.removeComponent(entity, InteractionRole);\n\t\t\tif (world.hasComponent(entity, CursorHint)) world.removeComponent(entity, CursorHint);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!current) {\n\t\t\tworld.addComponent(entity, InteractionRole, { layer: 5, role: desiredRole });\n\t\t} else if (current.role.type !== desiredRole.type) {\n\t\t\tworld.setComponent(entity, InteractionRole, { role: desiredRole });\n\t\t}\n\n\t\tif (desiredRole.type === 'drag' && !world.hasComponent(entity, CursorHint)) {\n\t\t\tworld.addComponent(entity, CursorHint, { hover: 'grab', active: 'grabbing' });\n\t\t}\n\t}\n\tunsubscribers.push(world.onTagAdded(Draggable, refreshInteractionRole));\n\tunsubscribers.push(world.onTagRemoved(Draggable, refreshInteractionRole));\n\tunsubscribers.push(world.onTagAdded(Selectable, refreshInteractionRole));\n\tunsubscribers.push(world.onTagRemoved(Selectable, refreshInteractionRole));\n\n\t// Pre-register widgets and archetypes from config\n\tif (config?.widgets) {\n\t\tfor (const w of config.widgets) widgetRegistry.register(w);\n\t}\n\tif (config?.archetypes) {\n\t\tfor (const a of config.archetypes) archetypeRegistry.register(a);\n\t}\n\n\t// Initialize navigation — mark root entities as Active on first tick\n\tworld.setResource(NavigationStackResource, { changed: true });\n\n\t// State\n\tlet inputState: InputState = { mode: 'idle' };\n\tlet hoveredEntity: EntityId | null = null;\n\tlet snapEnabled = snapEnabledInit;\n\tlet snapThreshold = snapThresholdInit; // screen pixels — divided by zoom to convert to world units\n\tlet currentSnap: SnapResult = { snapDx: 0, snapDy: 0, guides: [], spacings: [] };\n\tlet dirty = false;\n\tlet cameraChangedThisTick = false;\n\tlet selectionChangedThisTick = false; // Fix #2: proper selection tracking\n\tlet prevVisible = new Set<EntityId>();\n\tlet currentVisible: VisibleEntity[] = [];\n\tlet frameChanges: FrameChanges = {\n\t\tpositionsChanged: [],\n\t\tbreakpointsChanged: [],\n\t\tentered: [],\n\t\texited: [],\n\t\tcameraChanged: false,\n\t\tnavigationChanged: false,\n\t\tselectionChanged: false,\n\t};\n\n\tfunction markDirtyInternal() {\n\t\tdirty = true;\n\t}\n\n\tfunction hitTest(\n\t\tscreenX: number,\n\t\tscreenY: number,\n\t): { entityId: EntityId; role: InteractionRoleData } | null {\n\t\tconst camera = world.getResource(CameraResource);\n\t\tconst worldPos = screenToWorld(screenX, screenY, camera);\n\n\t\t// Zero-tolerance point query: RBush returns only entries whose AABB\n\t\t// strictly contains the point, so no secondary pointInAABB check is\n\t\t// needed. Generous hit slop lives in Hitbox size, not in tolerance.\n\t\tconst candidates = spatialIndex.searchPoint(worldPos.x, worldPos.y, 0);\n\n\t\t// Filter: must be Active (in current navigation frame) AND have a role.\n\t\ttype Candidate = { entityId: EntityId; role: InteractionRoleData };\n\t\tconst interactable: Candidate[] = [];\n\t\tfor (const c of candidates) {\n\t\t\tif (!world.hasTag(c.entityId, Active)) continue;\n\t\t\tconst role = world.getComponent(c.entityId, InteractionRole);\n\t\t\tif (!role) continue;\n\t\t\tinteractable.push({ entityId: c.entityId, role });\n\t\t}\n\t\tif (interactable.length === 0) return null;\n\n\t\t// Sort: role.layer desc, then ZIndex desc as tiebreaker.\n\t\tinteractable.sort((a, b) => {\n\t\t\tif (b.role.layer !== a.role.layer) return b.role.layer - a.role.layer;\n\t\t\tconst zA = world.getComponent(a.entityId, ZIndex)?.value ?? 0;\n\t\t\tconst zB = world.getComponent(b.entityId, ZIndex)?.value ?? 0;\n\t\t\treturn zB - zA;\n\t\t});\n\n\t\treturn interactable[0];\n\t}\n\n\t/**\n\t * RFC-001 Phase 7: derive the root-container cursor from input state +\n\t * hover, write to CursorResource. Closes over `inputState`, `hoveredEntity`\n\t * and `world`, which is why it's a plain function instead of a SystemDef.\n\t * Called from engine.tick() after scheduler.execute(world).\n\t */\n\tfunction cursorSystem(): void {\n\t\tlet cursor: CSSCursor = 'default';\n\n\t\tswitch (inputState.mode) {\n\t\t\tcase 'idle':\n\t\t\tcase 'marquee': {\n\t\t\t\tif (hoveredEntity !== null) {\n\t\t\t\t\tcursor = world.getComponent(hoveredEntity, CursorHint)?.hover ?? 'default';\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'tracking': {\n\t\t\t\t// Dead zone not yet crossed — show hover intent (grab), not active (grabbing).\n\t\t\t\tcursor = world.getComponent(inputState.entityId, CursorHint)?.hover ?? 'default';\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'dragging': {\n\t\t\t\tcursor = world.getComponent(inputState.entityId, CursorHint)?.active ?? 'grabbing';\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'resizing': {\n\t\t\t\tcursor = world.getComponent(inputState.handleEntityId, CursorHint)?.active ?? 'default';\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tworld.setResource(CursorResource, { cursor });\n\t}\n\n\t// Fix #2: track selection changes explicitly\n\tfunction selectEntity(entity: EntityId, additive: boolean) {\n\t\tif (!world.hasTag(entity, Selectable)) return;\n\n\t\tif (additive) {\n\t\t\tif (world.hasTag(entity, Selected)) {\n\t\t\t\tworld.removeTag(entity, Selected);\n\t\t\t} else {\n\t\t\t\tworld.addTag(entity, Selected);\n\t\t\t}\n\t\t} else {\n\t\t\tfor (const e of world.queryTagged(Selected)) {\n\t\t\t\tif (e !== entity) world.removeTag(e, Selected);\n\t\t\t}\n\t\t\tworld.addTag(entity, Selected);\n\t\t}\n\t\tselectionChangedThisTick = true;\n\t}\n\n\tfunction clearSelection() {\n\t\tconst selected = world.queryTagged(Selected);\n\t\tif (selected.length > 0) {\n\t\t\tfor (const e of selected) {\n\t\t\t\tworld.removeTag(e, Selected);\n\t\t\t}\n\t\t\tselectionChangedThisTick = true;\n\t\t}\n\t}\n\n\tconst engine: LayoutEngine = {\n\t\tworld,\n\n\t\t// === Entity CRUD ===\n\n\t\tcreateEntity(inits?: ComponentInit[]): EntityId {\n\t\t\tconst entity = world.createEntity();\n\t\t\tif (inits) {\n\t\t\t\tfor (const init of inits) {\n\t\t\t\t\tconst type = init[0];\n\t\t\t\t\tif (type.__kind === 'tag') {\n\t\t\t\t\t\tworld.addTag(entity, type as TagType);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tworld.addComponent(entity, type as ComponentType, init[1] ?? {});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tmarkDirtyInternal();\n\t\t\treturn entity;\n\t\t},\n\n\t\tspawn(id: string, opts: SpawnOptions = {}): EntityId {\n\t\t\t// Resolve archetype: explicit → widget-derived default → bare default.\n\t\t\tconst archetype = archetypeRegistry.get(id);\n\t\t\tconst widgetTypeId = archetype?.widget ?? id;\n\t\t\tconst widget = widgetRegistry.get(widgetTypeId);\n\n\t\t\tconst surface = widget?.surface ?? 'dom';\n\t\t\tconst defaultData = (widget?.defaultData as Record<string, unknown> | undefined) ?? {};\n\t\t\tconst defaultSize = archetype?.defaultSize ??\n\t\t\t\twidget?.defaultSize ?? { width: 100, height: 100 };\n\n\t\t\tconst position = opts.at ?? { x: 0, y: 0 };\n\t\t\tconst size = opts.size ?? defaultSize;\n\t\t\tconst data = { ...defaultData, ...opts.data };\n\n\t\t\tconst inits: ComponentInit[] = [\n\t\t\t\t[\n\t\t\t\t\tTransform2D,\n\t\t\t\t\t{\n\t\t\t\t\t\tx: position.x,\n\t\t\t\t\t\ty: position.y,\n\t\t\t\t\t\twidth: size.width,\n\t\t\t\t\t\theight: size.height,\n\t\t\t\t\t\trotation: opts.rotation ?? 0,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t[Widget, { surface, type: widgetTypeId }],\n\t\t\t\t[WidgetData, { data }],\n\t\t\t\t[ZIndex, { value: opts.zIndex ?? 0 }],\n\t\t\t];\n\n\t\t\tif (archetype?.components) {\n\t\t\t\tfor (const init of archetype.components) inits.push(init);\n\t\t\t}\n\n\t\t\tif (opts.parent !== undefined) {\n\t\t\t\tinits.push([Parent, { id: opts.parent }]);\n\t\t\t}\n\n\t\t\t// Interactive defaults (Selectable/Draggable/Resizable/SelectionFrame)\n\t\t\t// trigger the reactive observer that auto-attaches InteractionRole +\n\t\t\t// CursorHint for the interaction tags. Accepts boolean (all-or-none)\n\t\t\t// or an object picking specific caps. `selectionFrame` controls the\n\t\t\t// engine-drawn outline and defaults to `selectable` so Selectable\n\t\t\t// entities are framed unless they explicitly opt out (iOS cards).\n\t\t\tconst interactiveConfig = archetype?.interactive;\n\t\t\tconst caps =\n\t\t\t\tinteractiveConfig === false\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tselectable: false,\n\t\t\t\t\t\t\tdraggable: false,\n\t\t\t\t\t\t\tresizable: false,\n\t\t\t\t\t\t\tselectionFrame: false,\n\t\t\t\t\t\t}\n\t\t\t\t\t: interactiveConfig === undefined || interactiveConfig === true\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tselectable: true,\n\t\t\t\t\t\t\t\tdraggable: true,\n\t\t\t\t\t\t\t\tresizable: true,\n\t\t\t\t\t\t\t\tselectionFrame: true,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: (() => {\n\t\t\t\t\t\t\t\tconst selectable = interactiveConfig.selectable ?? false;\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tselectable,\n\t\t\t\t\t\t\t\t\tdraggable: interactiveConfig.draggable ?? false,\n\t\t\t\t\t\t\t\t\tresizable: interactiveConfig.resizable ?? false,\n\t\t\t\t\t\t\t\t\tselectionFrame: interactiveConfig.selectionFrame ?? selectable,\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t})();\n\t\t\tif (caps.selectable) inits.push([Selectable]);\n\t\t\tif (caps.draggable) inits.push([Draggable]);\n\t\t\tif (caps.resizable) inits.push([Resizable]);\n\t\t\tif (caps.selectionFrame) inits.push([SelectionFrame]);\n\n\t\t\tif (archetype?.tags) {\n\t\t\t\tfor (const tag of archetype.tags) inits.push([tag]);\n\t\t\t}\n\n\t\t\treturn engine.createEntity(inits);\n\t\t},\n\n\t\tspawnAtCameraCenter(id: string, opts: Omit<SpawnOptions, 'at'> = {}): EntityId {\n\t\t\tconst camera = world.getResource(CameraResource);\n\t\t\tconst viewport = world.getResource(ViewportResource);\n\t\t\tconst centerX = camera.x + viewport.width / (2 * camera.zoom);\n\t\t\tconst centerY = camera.y + viewport.height / (2 * camera.zoom);\n\t\t\tconst archetype = archetypeRegistry.get(id);\n\t\t\tconst widget = widgetRegistry.get(archetype?.widget ?? id);\n\t\t\tconst size = opts.size ??\n\t\t\t\tarchetype?.defaultSize ??\n\t\t\t\twidget?.defaultSize ?? { width: 100, height: 100 };\n\t\t\treturn engine.spawn(id, {\n\t\t\t\t...opts,\n\t\t\t\tat: { x: centerX - size.width / 2, y: centerY - size.height / 2 },\n\t\t\t});\n\t\t},\n\n\t\tregisterWidget(widget: WidgetDef) {\n\t\t\twidgetRegistry.register(widget);\n\t\t},\n\n\t\tgetWidget(type: string) {\n\t\t\treturn widgetRegistry.get(type);\n\t\t},\n\n\t\tgetWidgets() {\n\t\t\treturn widgetRegistry.getAll();\n\t\t},\n\n\t\tregisterArchetype(archetype: Archetype) {\n\t\t\tarchetypeRegistry.register(archetype);\n\t\t},\n\n\t\tgetArchetype(id: string) {\n\t\t\treturn archetypeRegistry.get(id);\n\t\t},\n\n\t\tdestroyEntity(id: EntityId) {\n\t\t\t// Cascade through HandleSet first so handles get cleaned up.\n\t\t\tconst set = world.getComponent(id, HandleSet);\n\t\t\tif (set) {\n\t\t\t\tfor (const handleId of set.ids) {\n\t\t\t\t\tif (world.entityExists(handleId)) {\n\t\t\t\t\t\tspatialIndex.remove(handleId);\n\t\t\t\t\t\tworld.destroyEntity(handleId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tspatialIndex.remove(id);\n\t\t\tworld.destroyEntity(id);\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\tget<T>(entity: EntityId, type: ComponentType<T>): T | undefined {\n\t\t\treturn world.getComponent(entity, type);\n\t\t},\n\n\t\tset<T>(entity: EntityId, type: ComponentType<T>, data: Partial<T>) {\n\t\t\tworld.setComponent(entity, type, data);\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\thas(entity: EntityId, type: ComponentType | TagType): boolean {\n\t\t\tif (type.__kind === 'tag') return world.hasTag(entity, type as TagType);\n\t\t\treturn world.hasComponent(entity, type as ComponentType);\n\t\t},\n\n\t\taddComponent<T>(entity: EntityId, type: ComponentType<T>, data?: T) {\n\t\t\tworld.addComponent(entity, type, data ?? type.defaults);\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\tremoveComponent(entity: EntityId, type: ComponentType) {\n\t\t\tworld.removeComponent(entity, type);\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\taddTag(entity: EntityId, type: TagType) {\n\t\t\tworld.addTag(entity, type);\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\tremoveTag(entity: EntityId, type: TagType) {\n\t\t\tworld.removeTag(entity, type);\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\tgetSchemaFor(entity: EntityId): StandardSchemaV1 | undefined {\n\t\t\tconst w = world.getComponent(entity, Widget);\n\t\t\tif (!w) return undefined;\n\t\t\treturn widgetRegistry.get(w.type)?.schema;\n\t\t},\n\n\t\t// === Extensions ===\n\n\t\tregisterSystem(system: SystemDef) {\n\t\t\tscheduler.register(system);\n\t\t},\n\n\t\tremoveSystem(name: string) {\n\t\t\tscheduler.remove(name);\n\t\t},\n\n\t\t// === Camera ===\n\n\t\tgetCamera() {\n\t\t\treturn world.getResource(CameraResource);\n\t\t},\n\n\t\tpanBy(dx: number, dy: number) {\n\t\t\tconst camera = world.getResource(CameraResource);\n\t\t\tcamera.x -= dx / camera.zoom;\n\t\t\tcamera.y -= dy / camera.zoom;\n\t\t\tcameraChangedThisTick = true;\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\tpanTo(worldX: number, worldY: number) {\n\t\t\tconst camera = world.getResource(CameraResource);\n\t\t\tconst viewport = world.getResource(ViewportResource);\n\t\t\tcamera.x = worldX - viewport.width / (2 * camera.zoom);\n\t\t\tcamera.y = worldY - viewport.height / (2 * camera.zoom);\n\t\t\tcameraChangedThisTick = true;\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\tzoomAtPoint(screenX: number, screenY: number, delta: number) {\n\t\t\tconst camera = world.getResource(CameraResource);\n\t\t\tconst zoomConfig = world.getResource(ZoomConfigResource);\n\n\t\t\tconst worldBefore = screenToWorld(screenX, screenY, camera);\n\t\t\tconst newZoom = clamp(camera.zoom * (1 + delta), zoomConfig.min, zoomConfig.max);\n\t\t\tcamera.zoom = newZoom;\n\t\t\tcamera.x = worldBefore.x - screenX / newZoom;\n\t\t\tcamera.y = worldBefore.y - screenY / newZoom;\n\t\t\tcameraChangedThisTick = true;\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\tzoomTo(zoom: number) {\n\t\t\tconst camera = world.getResource(CameraResource);\n\t\t\tconst zoomConfig = world.getResource(ZoomConfigResource);\n\t\t\tconst viewport = world.getResource(ViewportResource);\n\t\t\tconst centerWorldX = camera.x + viewport.width / (2 * camera.zoom);\n\t\t\tconst centerWorldY = camera.y + viewport.height / (2 * camera.zoom);\n\t\t\tcamera.zoom = clamp(zoom, zoomConfig.min, zoomConfig.max);\n\t\t\tcamera.x = centerWorldX - viewport.width / (2 * camera.zoom);\n\t\t\tcamera.y = centerWorldY - viewport.height / (2 * camera.zoom);\n\t\t\tcameraChangedThisTick = true;\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\tzoomToFit(entityIds?: EntityId[], padding = 50) {\n\t\t\tconst viewport = world.getResource(ViewportResource);\n\t\t\tif (viewport.width === 0) return;\n\n\t\t\tconst entities = entityIds ?? world.queryTagged(Active);\n\t\t\tif (entities.length === 0) return;\n\n\t\t\tlet minX = Number.POSITIVE_INFINITY;\n\t\t\tlet minY = Number.POSITIVE_INFINITY;\n\t\t\tlet maxX = Number.NEGATIVE_INFINITY;\n\t\t\tlet maxY = Number.NEGATIVE_INFINITY;\n\t\t\tfor (const e of entities) {\n\t\t\t\tconst wb = world.getComponent(e, WorldBounds);\n\t\t\t\tif (!wb) continue;\n\t\t\t\tminX = Math.min(minX, wb.worldX);\n\t\t\t\tminY = Math.min(minY, wb.worldY);\n\t\t\t\tmaxX = Math.max(maxX, wb.worldX + wb.worldWidth);\n\t\t\t\tmaxY = Math.max(maxY, wb.worldY + wb.worldHeight);\n\t\t\t}\n\t\t\tif (!Number.isFinite(minX)) return;\n\n\t\t\tconst contentWidth = maxX - minX + padding * 2;\n\t\t\tconst contentHeight = maxY - minY + padding * 2;\n\t\t\tconst zoomConfig = world.getResource(ZoomConfigResource);\n\t\t\tconst zoom = clamp(\n\t\t\t\tMath.min(viewport.width / contentWidth, viewport.height / contentHeight),\n\t\t\t\tzoomConfig.min,\n\t\t\t\tzoomConfig.max,\n\t\t\t);\n\n\t\t\tconst camera = world.getResource(CameraResource);\n\t\t\tcamera.zoom = zoom;\n\t\t\tcamera.x = minX - padding - (viewport.width / zoom - contentWidth) / 2;\n\t\t\tcamera.y = minY - padding - (viewport.height / zoom - contentHeight) / 2;\n\t\t\tcameraChangedThisTick = true;\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\t// === Viewport ===\n\n\t\tsetViewport(width: number, height: number, dpr?: number) {\n\t\t\tworld.setResource(ViewportResource, { width, height, dpr: dpr ?? 1 });\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\t// === Commands + Undo/Redo ===\n\n\t\texecute(command: Command) {\n\t\t\tcommandBuffer.execute(command, world);\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\tbeginCommandGroup() {\n\t\t\tcommandBuffer.beginGroup();\n\t\t},\n\n\t\tendCommandGroup() {\n\t\t\tcommandBuffer.endGroup();\n\t\t},\n\n\t\tundo(): boolean {\n\t\t\tconst did = commandBuffer.undo(world);\n\t\t\tif (did) markDirtyInternal();\n\t\t\treturn did;\n\t\t},\n\n\t\tredo(): boolean {\n\t\t\tconst did = commandBuffer.redo(world);\n\t\t\tif (did) markDirtyInternal();\n\t\t\treturn did;\n\t\t},\n\n\t\tcanUndo(): boolean {\n\t\t\treturn commandBuffer.canUndo();\n\t\t},\n\n\t\tcanRedo(): boolean {\n\t\t\treturn commandBuffer.canRedo();\n\t\t},\n\n\t\t// === Pointer Input ===\n\n\t\thandlePointerDown(screenX, screenY, _button, modifiers): PointerDirective {\n\t\t\tconst hit = hitTest(screenX, screenY);\n\n\t\t\tif (!hit) {\n\t\t\t\tclearSelection();\n\t\t\t\tinputState = { mode: 'marquee', startX: screenX, startY: screenY };\n\t\t\t\tmarkDirtyInternal();\n\t\t\t\treturn { action: 'capture-marquee' };\n\t\t\t}\n\n\t\t\tswitch (hit.role.role.type) {\n\t\t\t\tcase 'resize': {\n\t\t\t\t\tconst parentRef = world.getComponent(hit.entityId, Parent);\n\t\t\t\t\tif (!parentRef) return { action: 'passthrough' };\n\t\t\t\t\tconst parentId = parentRef.id;\n\t\t\t\t\tconst t = world.getComponent(parentId, Transform2D);\n\t\t\t\t\tif (!t) return { action: 'passthrough' };\n\t\t\t\t\tcommandBuffer.beginGroup(); // undo group for entire resize\n\t\t\t\t\tinputState = {\n\t\t\t\t\t\tmode: 'resizing',\n\t\t\t\t\t\tentityId: parentId,\n\t\t\t\t\t\thandleEntityId: hit.entityId,\n\t\t\t\t\t\thandle: hit.role.role.handle,\n\t\t\t\t\t\tstartX: screenX,\n\t\t\t\t\t\tstartY: screenY,\n\t\t\t\t\t\tstartBounds: { x: t.x, y: t.y, width: t.width, height: t.height },\n\t\t\t\t\t};\n\t\t\t\t\tmarkDirtyInternal();\n\t\t\t\t\treturn { action: 'capture-resize', handle: hit.role.role.handle };\n\t\t\t\t}\n\n\t\t\t\tcase 'drag': {\n\t\t\t\t\tselectEntity(hit.entityId, modifiers.shift);\n\t\t\t\t\tif (world.hasTag(hit.entityId, Draggable)) {\n\t\t\t\t\t\tinputState = {\n\t\t\t\t\t\t\tmode: 'tracking',\n\t\t\t\t\t\t\tentityId: hit.entityId,\n\t\t\t\t\t\t\tstartX: screenX,\n\t\t\t\t\t\t\tstartY: screenY,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\tmarkDirtyInternal();\n\t\t\t\t\treturn { action: 'passthrough-track-drag' };\n\t\t\t\t}\n\n\t\t\t\tcase 'select': {\n\t\t\t\t\tselectEntity(hit.entityId, modifiers.shift);\n\t\t\t\t\tmarkDirtyInternal();\n\t\t\t\t\treturn { action: 'passthrough' };\n\t\t\t\t}\n\n\t\t\t\t// 'canvas' | 'rotate' | 'connect' — no handler yet, fall through.\n\t\t\t\tdefault:\n\t\t\t\t\treturn { action: 'passthrough' };\n\t\t\t}\n\t\t},\n\n\t\thandlePointerMove(screenX, screenY, _modifiers): PointerDirective {\n\t\t\tif (inputState.mode === 'tracking') {\n\t\t\t\tconst dx = screenX - inputState.startX;\n\t\t\t\tconst dy = screenY - inputState.startY;\n\t\t\t\tif (Math.abs(dx) > DEAD_ZONE_MOUSE_PX || Math.abs(dy) > DEAD_ZONE_MOUSE_PX) {\n\t\t\t\t\t// Fix #5: Save original z-indices, temporarily bring to top\n\t\t\t\t\tconst originalZIndices = new Map<EntityId, number>();\n\t\t\t\t\tlet maxZ = 0;\n\t\t\t\t\tfor (const e of world.queryTagged(Active)) {\n\t\t\t\t\t\tconst z = world.getComponent(e, ZIndex);\n\t\t\t\t\t\tif (z && z.value > maxZ) maxZ = z.value;\n\t\t\t\t\t}\n\t\t\t\t\tfor (const e of world.queryTagged(Selected)) {\n\t\t\t\t\t\tconst z = world.getComponent(e, ZIndex);\n\t\t\t\t\t\toriginalZIndices.set(e, z?.value ?? 0);\n\t\t\t\t\t\tworld.setComponent(e, ZIndex, { value: maxZ + 1 });\n\t\t\t\t\t}\n\n\t\t\t\t\t// Capture start positions for all selected entities\n\t\t\t\t\tconst startPositions = new Map<EntityId, { x: number; y: number }>();\n\t\t\t\t\tfor (const e of world.queryTagged(Selected)) {\n\t\t\t\t\t\tconst t = world.getComponent(e, Transform2D);\n\t\t\t\t\t\tif (t) startPositions.set(e, { x: t.x, y: t.y });\n\t\t\t\t\t}\n\n\t\t\t\t\t// Mark each participating entity as Dragging (transient state tag).\n\t\t\t\t\t// Renderers read this via useTag to apply lift/shadow affordances.\n\t\t\t\t\tfor (const e of startPositions.keys()) {\n\t\t\t\t\t\tworld.addTag(e, Dragging);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Start undo group for the entire drag operation\n\t\t\t\t\tcommandBuffer.beginGroup();\n\n\t\t\t\t\tinputState = {\n\t\t\t\t\t\tmode: 'dragging',\n\t\t\t\t\t\tentityId: inputState.entityId,\n\t\t\t\t\t\tstartScreenX: screenX,\n\t\t\t\t\t\tstartScreenY: screenY,\n\t\t\t\t\t\tstartPositions,\n\t\t\t\t\t\toriginalZIndices,\n\t\t\t\t\t};\n\t\t\t\t\tmarkDirtyInternal();\n\t\t\t\t\treturn { action: 'capture-drag' };\n\t\t\t\t}\n\t\t\t\treturn { action: 'passthrough' };\n\t\t\t}\n\n\t\t\tif (inputState.mode === 'dragging') {\n\t\t\t\tconst camera = world.getResource(CameraResource);\n\t\t\t\tconst totalDx = (screenX - inputState.startScreenX) / camera.zoom;\n\t\t\t\tconst totalDy = (screenY - inputState.startScreenY) / camera.zoom;\n\n\t\t\t\t// Compute snap guides against visible non-dragged entities\n\t\t\t\tif (snapEnabled && inputState.startPositions.size > 0) {\n\t\t\t\t\t// Build dragged bounds (use first entity as reference for snap)\n\t\t\t\t\tconst draggedIds = new Set(inputState.startPositions.keys());\n\t\t\t\t\tconst firstId = inputState.startPositions.keys().next().value as EntityId;\n\t\t\t\t\tconst firstStart = inputState.startPositions.get(firstId);\n\t\t\t\t\tconst firstT = world.getComponent(firstId, Transform2D);\n\t\t\t\t\tif (firstT && firstStart) {\n\t\t\t\t\t\tconst draggedBounds = {\n\t\t\t\t\t\t\tx: firstStart.x + totalDx,\n\t\t\t\t\t\t\ty: firstStart.y + totalDy,\n\t\t\t\t\t\t\twidth: firstT.width,\n\t\t\t\t\t\t\theight: firstT.height,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// Collect reference bounds from visible entities. Skip the dragged\n\t\t\t\t\t\t// set and skip anything with a Hitbox component — Hitbox entities\n\t\t\t\t\t\t// are sub-entity interaction zones (resize handles), not snap\n\t\t\t\t\t\t// targets. Without this filter the dragged widget's own 8 handles\n\t\t\t\t\t\t// become snap refs and every axis matches trivially, producing\n\t\t\t\t\t\t// guide lines for every edge on every drag frame.\n\t\t\t\t\t\tconst refs = [];\n\t\t\t\t\t\tfor (const entity of world.queryTagged(Active)) {\n\t\t\t\t\t\t\tif (draggedIds.has(entity)) continue;\n\t\t\t\t\t\t\tif (world.hasComponent(entity, Hitbox)) continue;\n\t\t\t\t\t\t\tconst wb = world.getComponent(entity, WorldBounds);\n\t\t\t\t\t\t\tif (wb) {\n\t\t\t\t\t\t\t\trefs.push({\n\t\t\t\t\t\t\t\t\tx: wb.worldX,\n\t\t\t\t\t\t\t\t\ty: wb.worldY,\n\t\t\t\t\t\t\t\t\twidth: wb.worldWidth,\n\t\t\t\t\t\t\t\t\theight: wb.worldHeight,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcurrentSnap = computeSnapGuides(draggedBounds, refs, snapThreshold / camera.zoom);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tcurrentSnap = { snapDx: 0, snapDy: 0, guides: [], spacings: [] };\n\t\t\t\t}\n\n\t\t\t\t// Apply snap-corrected positions\n\t\t\t\tconst finalDx = totalDx + currentSnap.snapDx;\n\t\t\t\tconst finalDy = totalDy + currentSnap.snapDy;\n\t\t\t\tfor (const [e, start] of inputState.startPositions) {\n\t\t\t\t\tworld.setComponent(e, Transform2D, {\n\t\t\t\t\t\tx: start.x + finalDx,\n\t\t\t\t\t\ty: start.y + finalDy,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tmarkDirtyInternal();\n\t\t\t\treturn { action: 'capture-drag' };\n\t\t\t}\n\n\t\t\tif (inputState.mode === 'resizing') {\n\t\t\t\tconst camera = world.getResource(CameraResource);\n\t\t\t\tconst dx = (screenX - inputState.startX) / camera.zoom;\n\t\t\t\tconst dy = (screenY - inputState.startY) / camera.zoom;\n\t\t\t\tconst { x, y, width: w, height: h } = inputState.startBounds;\n\t\t\t\tconst handle = inputState.handle;\n\n\t\t\t\tlet newX = x;\n\t\t\t\tlet newY = y;\n\t\t\t\tlet newW = w;\n\t\t\t\tlet newH = h;\n\n\t\t\t\tif (handle.includes('e')) {\n\t\t\t\t\tnewW = Math.max(MIN_WIDGET_SIZE, w + dx);\n\t\t\t\t}\n\t\t\t\tif (handle.includes('w')) {\n\t\t\t\t\tconst clampedW = Math.max(MIN_WIDGET_SIZE, w - dx);\n\t\t\t\t\tnewX = x + w - clampedW; // right edge stays fixed\n\t\t\t\t\tnewW = clampedW;\n\t\t\t\t}\n\t\t\t\tif (handle.includes('s')) {\n\t\t\t\t\tnewH = Math.max(MIN_WIDGET_SIZE, h + dy);\n\t\t\t\t}\n\t\t\t\tif (handle.includes('n')) {\n\t\t\t\t\tconst clampedH = Math.max(MIN_WIDGET_SIZE, h - dy);\n\t\t\t\t\tnewY = y + h - clampedH; // bottom edge stays fixed\n\t\t\t\t\tnewH = clampedH;\n\t\t\t\t}\n\n\t\t\t\tworld.setComponent(inputState.entityId, Transform2D, {\n\t\t\t\t\tx: newX,\n\t\t\t\t\ty: newY,\n\t\t\t\t\twidth: newW,\n\t\t\t\t\theight: newH,\n\t\t\t\t});\n\t\t\t\tmarkDirtyInternal();\n\t\t\t\treturn { action: 'capture-resize', handle: inputState.handle };\n\t\t\t}\n\n\t\t\tif (inputState.mode === 'marquee') {\n\t\t\t\t// TODO: marquee selection in Phase 7\n\t\t\t\treturn { action: 'capture-marquee' };\n\t\t\t}\n\n\t\t\t// Hover tracking in idle mode\n\t\t\tif (inputState.mode === 'idle') {\n\t\t\t\tconst hit = hitTest(screenX, screenY);\n\t\t\t\t// RFC-001 Phase 7: use the raw hit id so cursorSystem can read\n\t\t\t\t// CursorHint from handles (e.g. 'se-resize'). Selection outline is\n\t\t\t\t// already drawn for the parent via Selected tag whenever handles\n\t\t\t\t// exist — hover-to-parent resolution would only clobber the\n\t\t\t\t// directional cursor affordance with no benefit.\n\t\t\t\tconst hoverTarget: EntityId | null = hit ? hit.entityId : null;\n\t\t\t\tif (hoverTarget !== hoveredEntity) {\n\t\t\t\t\thoveredEntity = hoverTarget;\n\t\t\t\t\tmarkDirtyInternal();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { action: 'passthrough' };\n\t\t},\n\n\t\thandlePointerUp(): PointerDirective {\n\t\t\tconst prevState = inputState;\n\n\t\t\tif (prevState.mode === 'dragging') {\n\t\t\t\t// Clear Dragging state tag from every participating entity.\n\t\t\t\tfor (const e of prevState.startPositions.keys()) {\n\t\t\t\t\tif (world.hasTag(e, Dragging)) world.removeTag(e, Dragging);\n\t\t\t\t}\n\t\t\t\t// Fix #5: Restore original z-indices on drag end\n\t\t\t\tfor (const [entity, originalZ] of prevState.originalZIndices) {\n\t\t\t\t\tworld.setComponent(entity, ZIndex, { value: originalZ });\n\t\t\t\t}\n\t\t\t\t// Compute total delta from any moved entity\n\t\t\t\tconst entityIds = [...prevState.startPositions.keys()];\n\t\t\t\tif (entityIds.length > 0) {\n\t\t\t\t\tconst firstId = entityIds[0];\n\t\t\t\t\tconst start = prevState.startPositions.get(firstId);\n\t\t\t\t\tconst current = world.getComponent(firstId, Transform2D);\n\t\t\t\t\tif (current && start) {\n\t\t\t\t\t\tconst totalDx = current.x - start.x;\n\t\t\t\t\t\tconst totalDy = current.y - start.y;\n\t\t\t\t\t\tif (totalDx !== 0 || totalDy !== 0) {\n\t\t\t\t\t\t\t// Revert all to start positions, then commit as single command\n\t\t\t\t\t\t\tfor (const [e, s] of prevState.startPositions) {\n\t\t\t\t\t\t\t\tworld.setComponent(e, Transform2D, { x: s.x, y: s.y });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcommandBuffer.execute(\n\t\t\t\t\t\t\t\tnew MoveCommand(entityIds, totalDx, totalDy, Transform2D),\n\t\t\t\t\t\t\t\tworld,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcommandBuffer.endGroup();\n\t\t\t\tcurrentSnap = { snapDx: 0, snapDy: 0, guides: [], spacings: [] };\n\t\t\t}\n\n\t\t\tif (prevState.mode === 'resizing') {\n\t\t\t\t// Capture final bounds before reverting\n\t\t\t\tconst t = world.getComponent(prevState.entityId, Transform2D);\n\t\t\t\tif (t) {\n\t\t\t\t\tconst finalBounds = { x: t.x, y: t.y, width: t.width, height: t.height };\n\t\t\t\t\tconst sb = prevState.startBounds;\n\t\t\t\t\t// Revert to start bounds so the command's execute() applies cleanly\n\t\t\t\t\tworld.setComponent(prevState.entityId, Transform2D, sb);\n\t\t\t\t\tcommandBuffer.execute(\n\t\t\t\t\t\tnew ResizeCommand(prevState.entityId, sb, finalBounds, Transform2D),\n\t\t\t\t\t\tworld,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcommandBuffer.endGroup();\n\t\t\t}\n\n\t\t\t// Fix #12: TODO — emit a 'widget-clicked' event when prevState.mode === 'tracking'\n\n\t\t\tinputState = { mode: 'idle' };\n\n\t\t\tif (prevState.mode === 'dragging' || prevState.mode === 'resizing') {\n\t\t\t\tmarkDirtyInternal();\n\t\t\t}\n\n\t\t\treturn { action: 'passthrough' };\n\t\t},\n\n\t\thandlePointerCancel(): void {\n\t\t\t// End any open undo group to prevent leaked groups\n\t\t\tif (inputState.mode === 'dragging' || inputState.mode === 'resizing') {\n\t\t\t\tcommandBuffer.endGroup();\n\t\t\t}\n\t\t\t// Clear Dragging tag from every participating entity.\n\t\t\tif (inputState.mode === 'dragging') {\n\t\t\t\tfor (const e of inputState.startPositions.keys()) {\n\t\t\t\t\tif (world.hasTag(e, Dragging)) world.removeTag(e, Dragging);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Clear snap state\n\t\t\tcurrentSnap = { snapDx: 0, snapDy: 0, guides: [], spacings: [] };\n\t\t\t// Reset interaction state to idle\n\t\t\tinputState = { mode: 'idle' };\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\t// === Selection ===\n\n\t\tgetSelectedEntities(): EntityId[] {\n\t\t\treturn world.queryTagged(Selected);\n\t\t},\n\n\t\tgetHoveredEntity(): EntityId | null {\n\t\t\treturn hoveredEntity;\n\t\t},\n\n\t\t// === Snap Guides ===\n\n\t\tgetSnapGuides(): SnapGuide[] {\n\t\t\treturn currentSnap.guides;\n\t\t},\n\n\t\tgetEqualSpacing(): EqualSpacingIndicator[] {\n\t\t\treturn currentSnap.spacings;\n\t\t},\n\n\t\tsetSnapEnabled(on: boolean) {\n\t\t\tsnapEnabled = on;\n\t\t},\n\n\t\tsetSnapThreshold(worldPx: number) {\n\t\t\tsnapThreshold = worldPx;\n\t\t},\n\n\t\t// === Navigation ===\n\n\t\tenterContainer(entity: EntityId) {\n\t\t\tif (!world.hasComponent(entity, Container)) return;\n\t\t\tif (!world.hasComponent(entity, Children)) return;\n\n\t\t\tconst navStack = world.getResource(NavigationStackResource);\n\t\t\tconst camera = world.getResource(CameraResource);\n\n\t\t\tconst currentFrame = navStack.frames[navStack.frames.length - 1];\n\t\t\tcurrentFrame.camera = { x: camera.x, y: camera.y, zoom: camera.zoom };\n\n\t\t\tnavStack.frames.push({\n\t\t\t\tcontainerId: entity,\n\t\t\t\tcamera: { x: camera.x, y: camera.y, zoom: camera.zoom },\n\t\t\t});\n\t\t\tnavStack.changed = true;\n\n\t\t\tclearSelection();\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\texitContainer() {\n\t\t\tconst navStack = world.getResource(NavigationStackResource);\n\t\t\tif (navStack.frames.length <= 1) return;\n\n\t\t\tnavStack.frames.pop();\n\t\t\tnavStack.changed = true;\n\n\t\t\tconst parentFrame = navStack.frames[navStack.frames.length - 1];\n\t\t\tconst camera = world.getResource(CameraResource);\n\t\t\tcamera.x = parentFrame.camera.x;\n\t\t\tcamera.y = parentFrame.camera.y;\n\t\t\tcamera.zoom = parentFrame.camera.zoom;\n\n\t\t\tclearSelection();\n\t\t\tcameraChangedThisTick = true;\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\tgetActiveContainer(): EntityId | null {\n\t\t\tconst navStack = world.getResource(NavigationStackResource);\n\t\t\treturn navStack.frames[navStack.frames.length - 1].containerId;\n\t\t},\n\n\t\tgetNavigationDepth(): number {\n\t\t\treturn world.getResource(NavigationStackResource).frames.length - 1;\n\t\t},\n\n\t\t// === Frame ===\n\n\t\tmarkDirty() {\n\t\t\tmarkDirtyInternal();\n\t\t},\n\n\t\tprofiler,\n\n\t\ttick() {\n\t\t\tprofiler.beginFrame(world.currentTick);\n\n\t\t\t// Fix #4: Capture navigation changed flag before systems clear it\n\t\t\tconst navStackPreTick = world.getResource(NavigationStackResource);\n\t\t\tconst navigationChangedThisTick = navStackPreTick?.changed ?? false;\n\n\t\t\t// Run all systems\n\t\t\tscheduler.execute(world);\n\n\t\t\t// RFC-001 Phase 7: derive the root-container cursor from input state + hover.\n\t\t\tcursorSystem();\n\n\t\t\t// Compute visible entities for renderers\n\t\t\tprofiler.beginVisibility();\n\t\t\tconst newVisible: VisibleEntity[] = [];\n\t\t\tconst newVisibleSet = new Set<EntityId>();\n\n\t\t\tfor (const entity of world.query(Widget, Visible)) {\n\t\t\t\tconst wb = world.getComponent(entity, WorldBounds);\n\t\t\t\tconst widget = world.getComponent(entity, Widget);\n\t\t\t\tconst bp = world.getComponent(entity, WidgetBreakpoint);\n\t\t\t\tconst zIdx = world.getComponent(entity, ZIndex);\n\t\t\t\tif (!wb || !widget) continue;\n\n\t\t\t\tnewVisibleSet.add(entity);\n\t\t\t\tnewVisible.push({\n\t\t\t\t\tentityId: entity,\n\t\t\t\t\tworldX: wb.worldX,\n\t\t\t\t\tworldY: wb.worldY,\n\t\t\t\t\tworldWidth: wb.worldWidth,\n\t\t\t\t\tworldHeight: wb.worldHeight,\n\t\t\t\t\tbreakpoint: bp?.current ?? 'normal',\n\t\t\t\t\tzIndex: zIdx?.value ?? 0,\n\t\t\t\t\tsurface: widget.surface,\n\t\t\t\t\twidgetType: widget.type,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Sort by z-index\n\t\t\tnewVisible.sort((a, b) => a.zIndex - b.zIndex);\n\t\t\tprofiler.endVisibility();\n\n\t\t\t// Compute frame changes\n\t\t\tconst entered: EntityId[] = [];\n\t\t\tconst exited: EntityId[] = [];\n\t\t\tfor (const entity of newVisibleSet) {\n\t\t\t\tif (!prevVisible.has(entity)) entered.push(entity);\n\t\t\t}\n\t\t\tfor (const entity of prevVisible) {\n\t\t\t\tif (!newVisibleSet.has(entity)) exited.push(entity);\n\t\t\t}\n\n\t\t\t// Fix #2: Use selectionChangedThisTick instead of wrong breakpoint check\n\t\t\tframeChanges = {\n\t\t\t\tpositionsChanged: world.queryChanged(WorldBounds),\n\t\t\t\tbreakpointsChanged: world.queryChanged(WidgetBreakpoint),\n\t\t\t\tentered,\n\t\t\t\texited,\n\t\t\t\tcameraChanged: cameraChangedThisTick,\n\t\t\t\tnavigationChanged: navigationChangedThisTick,\n\t\t\t\tselectionChanged: selectionChangedThisTick,\n\t\t\t};\n\n\t\t\tcurrentVisible = newVisible;\n\t\t\tprevVisible = newVisibleSet;\n\t\t\tcameraChangedThisTick = false;\n\t\t\tselectionChangedThisTick = false;\n\n\t\t\tprofiler.endFrame(world.entityCount, newVisible.length);\n\n\t\t\t// Clear dirty sets and increment tick\n\t\t\tworld.clearDirty();\n\t\t\tworld.incrementTick();\n\t\t\tworld.emitFrame();\n\n\t\t\tdirty = false;\n\t\t},\n\n\t\tflushIfDirty(): boolean {\n\t\t\tif (!dirty) return false;\n\t\t\tengine.tick();\n\t\t\treturn true;\n\t\t},\n\n\t\t// === Output ===\n\n\t\tgetVisibleEntities(): VisibleEntity[] {\n\t\t\treturn currentVisible;\n\t\t},\n\n\t\tgetFrameChanges(): FrameChanges {\n\t\t\treturn frameChanges;\n\t\t},\n\n\t\t// Fix #11: Expose spatial index properly\n\t\tgetSpatialIndex(): SpatialIndex {\n\t\t\treturn spatialIndex;\n\t\t},\n\n\t\t// === Events ===\n\n\t\tonFrame(handler: () => void): Unsubscribe {\n\t\t\treturn world.onFrame(handler);\n\t\t},\n\n\t\t// === Lifecycle ===\n\n\t\tdestroy() {\n\t\t\t// Unsubscribe all observers\n\t\t\tfor (const unsub of unsubscribers) {\n\t\t\t\tunsub();\n\t\t\t}\n\t\t\tunsubscribers.length = 0;\n\n\t\t\t// Clear command buffer (undo/redo stacks and any open group)\n\t\t\tcommandBuffer.clear();\n\n\t\t\t// Disable profiler and clear its ring buffer\n\t\t\tprofiler.setEnabled(false);\n\t\t\tprofiler.clear();\n\n\t\t\t// Clear spatial index\n\t\t\tspatialIndex.clear();\n\t\t},\n\t};\n\n\treturn engine;\n}\n","import type { EntityId } from '@jamesyong42/reactive-ecs';\nimport { memo, useCallback, useEffect, useRef } from 'react';\nimport { WorldBounds } from '../components.js';\nimport type { Modifiers } from '../engine.js';\nimport { useContainerRef, useLayoutEngine } from './context.js';\n\ninterface SelectionOverlaySlotProps {\n\tentityId: EntityId;\n\tslotRef: (entityId: EntityId, el: HTMLDivElement | null) => void;\n}\n\nfunction getMods(e: React.PointerEvent): Modifiers {\n\treturn { shift: e.shiftKey, ctrl: e.ctrlKey, alt: e.altKey, meta: e.metaKey };\n}\n\n/**\n * DOM overlay for WebGL widgets — provides selection frame and pointer\n * interaction (select, drag, resize) without rendering widget content.\n */\nexport const SelectionOverlaySlot = memo(function SelectionOverlaySlot({\n\tentityId,\n\tslotRef,\n}: SelectionOverlaySlotProps) {\n\tconst wrapperRef = useRef<HTMLDivElement>(null);\n\tconst engine = useLayoutEngine();\n\tconst containerRefObj = useContainerRef();\n\n\tuseEffect(() => {\n\t\tslotRef(entityId, wrapperRef.current);\n\t\treturn () => slotRef(entityId, null);\n\t}, [entityId, slotRef]);\n\n\tconst toLocal = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\tconst rect = containerRefObj?.current?.getBoundingClientRect();\n\t\t\tif (!rect) return { x: e.clientX, y: e.clientY };\n\t\t\treturn { x: e.clientX - rect.left, y: e.clientY - rect.top };\n\t\t},\n\t\t[containerRefObj],\n\t);\n\n\tconst capturedRef = useRef(false);\n\n\tconst onPointerDown = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\te.stopPropagation();\n\t\t\tconst { x, y } = toLocal(e);\n\t\t\tconst directive = engine.handlePointerDown(x, y, e.button, getMods(e));\n\t\t\tif (directive.action === 'capture-resize' || directive.action === 'passthrough-track-drag') {\n\t\t\t\twrapperRef.current?.setPointerCapture(e.pointerId);\n\t\t\t}\n\t\t\tif (directive.action === 'capture-resize') {\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t},\n\t\t[engine, toLocal],\n\t);\n\n\tconst onPointerMove = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\tconst { x, y } = toLocal(e);\n\t\t\tconst directive = engine.handlePointerMove(x, y, getMods(e));\n\t\t\tif (directive.action === 'capture-drag' && !capturedRef.current) {\n\t\t\t\tcapturedRef.current = true;\n\t\t\t\te.stopPropagation();\n\t\t\t}\n\t\t},\n\t\t[engine, toLocal],\n\t);\n\n\tconst onPointerUp = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\te.stopPropagation();\n\t\t\tcapturedRef.current = false;\n\t\t\tif (wrapperRef.current?.hasPointerCapture(e.pointerId)) {\n\t\t\t\twrapperRef.current.releasePointerCapture(e.pointerId);\n\t\t\t}\n\t\t\tengine.handlePointerUp();\n\t\t},\n\t\t[engine],\n\t);\n\n\tconst onDoubleClick = useCallback(\n\t\t(e: React.MouseEvent) => {\n\t\t\te.stopPropagation();\n\t\t\tengine.enterContainer(entityId);\n\t\t},\n\t\t[engine, entityId],\n\t);\n\n\tconst wb = engine.get(entityId, WorldBounds);\n\tconst initialStyle: React.CSSProperties = wb\n\t\t? {\n\t\t\t\ttransform: `translate(${wb.worldX}px, ${wb.worldY}px)`,\n\t\t\t\twidth: `${wb.worldWidth}px`,\n\t\t\t\theight: `${wb.worldHeight}px`,\n\t\t\t}\n\t\t: {};\n\n\treturn (\n\t\t<div\n\t\t\tref={wrapperRef}\n\t\t\tclassName=\"absolute left-0 top-0 origin-top-left will-change-transform\"\n\t\t\tdata-widget-slot=\"\"\n\t\t\tstyle={initialStyle}\n\t\t\tonPointerDown={onPointerDown}\n\t\t\tonPointerMove={onPointerMove}\n\t\t\tonPointerUp={onPointerUp}\n\t\t\tonDoubleClick={onDoubleClick}\n\t\t/>\n\t);\n});\n","import type { EntityId } from '@jamesyong42/reactive-ecs';\nimport { memo, useCallback, useEffect, useRef } from 'react';\nimport { Widget, WorldBounds } from '../components.js';\nimport type { Modifiers } from '../engine.js';\nimport { useContainerRef, useLayoutEngine, useWidgetResolver } from './context.js';\nimport { useComponent } from './hooks.js';\n\ninterface WidgetSlotProps {\n\tentityId: EntityId;\n\tslotRef: (entityId: EntityId, el: HTMLDivElement | null) => void;\n}\n\nfunction getMods(e: React.PointerEvent): Modifiers {\n\treturn { shift: e.shiftKey, ctrl: e.ctrlKey, alt: e.altKey, meta: e.metaKey };\n}\n\nexport const WidgetSlot = memo(function WidgetSlot({ entityId, slotRef }: WidgetSlotProps) {\n\tconst wrapperRef = useRef<HTMLDivElement>(null);\n\tconst engine = useLayoutEngine();\n\tconst containerRefObj = useContainerRef();\n\tconst resolve = useWidgetResolver();\n\n\tconst widgetComp = useComponent(entityId, Widget);\n\n\t// DOM slot — only renders DOM widgets. R3F widgets go through WebGLWidgetLayer.\n\tconst resolved = resolve?.(entityId, widgetComp?.type ?? '');\n\tconst WidgetComponent = resolved && resolved.surface === 'dom' ? resolved.component : null;\n\n\t// Register wrapper ref with the batch updater\n\tuseEffect(() => {\n\t\tslotRef(entityId, wrapperRef.current);\n\t\treturn () => slotRef(entityId, null);\n\t}, [entityId, slotRef]);\n\n\t// Convert clientX/Y to container-relative coords\n\tconst toLocal = useCallback(\n\t\t(e: React.PointerEvent): { x: number; y: number } => {\n\t\t\tconst rect = containerRefObj?.current?.getBoundingClientRect();\n\t\t\tif (!rect) return { x: e.clientX, y: e.clientY };\n\t\t\treturn { x: e.clientX - rect.left, y: e.clientY - rect.top };\n\t\t},\n\t\t[containerRefObj],\n\t);\n\n\t// Fix #3: Capture pointer immediately on pointerdown for any widget interaction.\n\t// This ensures we always get pointerup even if the cursor leaves the window.\n\tconst onPointerDown = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\t// Don't intercept clicks on interactive elements inside widgets\n\t\t\tconst target = e.target as HTMLElement;\n\t\t\tif (target.closest('button, input, textarea, select, [contenteditable]')) {\n\t\t\t\te.stopPropagation(); // still prevent background handler\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst { x, y } = toLocal(e);\n\t\t\tconst directive = engine.handlePointerDown(x, y, e.button, getMods(e));\n\n\t\t\t// Always stop propagation — prevent background handler from double-processing\n\t\t\te.stopPropagation();\n\n\t\t\tif (directive.action === 'capture-resize' || directive.action === 'passthrough-track-drag') {\n\t\t\t\t// Capture pointer for both resize AND tracking (so we get pointerup reliably)\n\t\t\t\twrapperRef.current?.setPointerCapture(e.pointerId);\n\t\t\t}\n\t\t\tif (directive.action === 'capture-resize') {\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t},\n\t\t[engine, toLocal],\n\t);\n\n\tconst capturedRef = useRef(false);\n\n\tconst onPointerMove = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\tconst { x, y } = toLocal(e);\n\t\t\tconst directive = engine.handlePointerMove(x, y, getMods(e));\n\n\t\t\t// Fix #3: Only call setPointerCapture once when drag starts (not every move)\n\t\t\tif (directive.action === 'capture-drag' && !capturedRef.current) {\n\t\t\t\tcapturedRef.current = true;\n\t\t\t\te.stopPropagation();\n\t\t\t}\n\t\t},\n\t\t[engine, toLocal],\n\t);\n\n\tconst onPointerUp = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\te.stopPropagation();\n\t\t\tcapturedRef.current = false;\n\t\t\t// Release pointer capture (browser does this automatically, but be explicit)\n\t\t\tif (wrapperRef.current?.hasPointerCapture(e.pointerId)) {\n\t\t\t\twrapperRef.current.releasePointerCapture(e.pointerId);\n\t\t\t}\n\t\t\tengine.handlePointerUp();\n\t\t},\n\t\t[engine],\n\t);\n\n\tconst onDoubleClick = useCallback(\n\t\t(e: React.MouseEvent) => {\n\t\t\te.stopPropagation();\n\t\t\tengine.enterContainer(entityId);\n\t\t},\n\t\t[engine, entityId],\n\t);\n\n\t// Read WorldBounds at render time for initial inline position.\n\t// This ensures the div has the correct position on its very first paint —\n\t// no flash at (0,0). Subsequent updates come from the batch updater (rAF).\n\tconst wb = engine.get(entityId, WorldBounds);\n\tconst initialStyle: React.CSSProperties = wb\n\t\t? {\n\t\t\t\ttransform: `translate(${wb.worldX}px, ${wb.worldY}px)`,\n\t\t\t\twidth: `${wb.worldWidth}px`,\n\t\t\t\theight: `${wb.worldHeight}px`,\n\t\t\t}\n\t\t: {};\n\n\tconst content = WidgetComponent ? (\n\t\t<WidgetComponent entityId={entityId} />\n\t) : (\n\t\t<div className=\"h-full w-full rounded border border-dashed border-gray-300 bg-gray-50\" />\n\t);\n\n\treturn (\n\t\t<div\n\t\t\tref={wrapperRef}\n\t\t\tdata-widget-slot=\"\"\n\t\t\tclassName=\"absolute left-0 top-0 origin-top-left will-change-transform\"\n\t\t\tstyle={initialStyle}\n\t\t\tonPointerDown={onPointerDown}\n\t\t\tonPointerMove={onPointerMove}\n\t\t\tonPointerUp={onPointerUp}\n\t\t\tonDoubleClick={onDoubleClick}\n\t\t>\n\t\t\t{content}\n\t\t</div>\n\t);\n});\n","import * as THREE from 'three';\n\n// === Public config ===\n\nexport interface GridConfig {\n\t/** World-unit spacings for up to 3 grid levels [fine, medium, coarse]. */\n\tspacings: [number, number, number];\n\t/** Dot RGB color as [r, g, b] in 0–1 range. */\n\tdotColor: [number, number, number];\n\t/** Base dot opacity multiplier (0–1). */\n\tdotAlpha: number;\n\t/** CSS-pixel range where a grid level fades in: [start, end]. */\n\tfadeIn: [number, number];\n\t/** CSS-pixel range where a grid level fades out: [start, end]. */\n\tfadeOut: [number, number];\n\t/** Dot radius range in CSS pixels [min, max]. Scaled by DPR internally. */\n\tdotRadius: [number, number];\n\t/** Per-level opacity weight: level i gets (base + i * step). */\n\tlevelWeight: [number, number];\n}\n\nexport const DEFAULT_GRID_CONFIG: GridConfig = {\n\tspacings: [8, 64, 512],\n\tdotColor: [0, 0, 0],\n\tdotAlpha: 0.18,\n\tfadeIn: [4, 12],\n\tfadeOut: [250, 500],\n\tdotRadius: [0.5, 1.4],\n\tlevelWeight: [1.0, 0.4],\n};\n\n// === Shader source ===\n\nconst vertexShader = /* glsl */ `\nvoid main() {\n\tgl_Position = vec4(position.xy, 0.0, 1.0);\n}\n`;\n\nconst fragmentShader = /* glsl */ `\nprecision highp float;\n\nuniform vec2 u_resolution; // device pixels\nuniform vec2 u_camera; // world-space top-left\nuniform float u_zoom; // CSS zoom\nuniform float u_dpr; // device pixel ratio\nuniform vec3 u_spacings; // world-unit grid spacings\nuniform vec3 u_dotColor; // dot RGB\nuniform float u_dotAlpha; // dot base alpha\nuniform vec2 u_fadeIn; // CSS-px [start, end]\nuniform vec2 u_fadeOut; // CSS-px [start, end]\nuniform vec2 u_dotRadius; // CSS-px [min, max]\nuniform vec2 u_levelWeight; // [base, step]\n\nvoid main() {\n\tvec2 devicePos = gl_FragCoord.xy;\n\tdevicePos.y = u_resolution.y - devicePos.y;\n\n\tfloat effectiveZoom = u_zoom * u_dpr;\n\tvec2 worldPos = devicePos / effectiveZoom + u_camera;\n\n\tfloat totalAlpha = 0.0;\n\n\tfor (int i = 0; i < 3; i++) {\n\t\tfloat spacing;\n\t\tif (i == 0) spacing = u_spacings.x;\n\t\telse if (i == 1) spacing = u_spacings.y;\n\t\telse spacing = u_spacings.z;\n\n\t\t// Screen spacing in CSS pixels (DPR-independent for consistent fading)\n\t\tfloat cssSpacing = spacing * u_zoom;\n\n\t\t// Fade curve\n\t\tfloat opacity = 0.0;\n\t\tif (cssSpacing >= u_fadeIn.x && cssSpacing < u_fadeIn.y) {\n\t\t\topacity = (cssSpacing - u_fadeIn.x) / (u_fadeIn.y - u_fadeIn.x);\n\t\t} else if (cssSpacing >= u_fadeIn.y && cssSpacing < u_fadeOut.x) {\n\t\t\topacity = 1.0;\n\t\t} else if (cssSpacing >= u_fadeOut.x && cssSpacing < u_fadeOut.y) {\n\t\t\topacity = 1.0 - (cssSpacing - u_fadeOut.x) / (u_fadeOut.y - u_fadeOut.x);\n\t\t}\n\t\tif (opacity <= 0.001) continue;\n\n\t\t// Distance to nearest grid intersection in device pixels\n\t\tvec2 f = fract(worldPos / spacing + 0.5) - 0.5;\n\t\tfloat dist = length(f) * spacing * effectiveZoom;\n\n\t\t// Dot radius in device pixels — grows as grid becomes sparser\n\t\tfloat t = clamp((cssSpacing - u_fadeIn.x) / 40.0, 0.0, 1.0);\n\t\tfloat radius = mix(u_dotRadius.x, u_dotRadius.y, t) * u_dpr;\n\n\t\t// Anti-aliased dot (0.5 device pixel smoothstep)\n\t\tfloat dot = 1.0 - smoothstep(radius - 0.5, radius + 0.5, dist);\n\n\t\t// Larger grid levels get progressively stronger dots\n\t\tfloat weight = u_levelWeight.x + float(i) * u_levelWeight.y;\n\t\ttotalAlpha += dot * opacity * weight;\n\t}\n\n\tgl_FragColor = vec4(u_dotColor, clamp(totalAlpha * u_dotAlpha, 0.0, 1.0));\n}\n`;\n\n// === Renderer class ===\n\nexport class GridRenderer {\n\tprivate renderer: THREE.WebGLRenderer;\n\tprivate scene: THREE.Scene;\n\tprivate camera: THREE.OrthographicCamera;\n\tprivate material: THREE.ShaderMaterial;\n\tprivate mesh: THREE.Mesh;\n\n\tconstructor(canvas: HTMLCanvasElement) {\n\t\tthis.renderer = new THREE.WebGLRenderer({\n\t\t\tcanvas,\n\t\t\talpha: true,\n\t\t\tantialias: false,\n\t\t\tpremultipliedAlpha: false,\n\t\t});\n\t\tthis.renderer.setClearColor(0x000000, 0);\n\t\t// Accumulate `renderer.info.render.calls/triangles` across multiple\n\t\t// render() calls per tick (grid + selection share this renderer). The\n\t\t// InfiniteCanvas rAF loop calls `renderer.info.reset()` once per tick\n\t\t// before the first pass.\n\t\tthis.renderer.info.autoReset = false;\n\n\t\tthis.scene = new THREE.Scene();\n\t\tthis.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);\n\n\t\tthis.material = new THREE.ShaderMaterial({\n\t\t\tvertexShader,\n\t\t\tfragmentShader,\n\t\t\tuniforms: {\n\t\t\t\tu_resolution: { value: new THREE.Vector2(1, 1) },\n\t\t\t\tu_camera: { value: new THREE.Vector2(0, 0) },\n\t\t\t\tu_zoom: { value: 1 },\n\t\t\t\tu_dpr: { value: 1 },\n\t\t\t\tu_spacings: { value: new THREE.Vector3(8, 64, 512) },\n\t\t\t\tu_dotColor: { value: new THREE.Vector3(0, 0, 0) },\n\t\t\t\tu_dotAlpha: { value: 0.18 },\n\t\t\t\tu_fadeIn: { value: new THREE.Vector2(4, 12) },\n\t\t\t\tu_fadeOut: { value: new THREE.Vector2(250, 500) },\n\t\t\t\tu_dotRadius: { value: new THREE.Vector2(0.5, 1.4) },\n\t\t\t\tu_levelWeight: { value: new THREE.Vector2(1.0, 0.4) },\n\t\t\t},\n\t\t\ttransparent: true,\n\t\t\tdepthTest: false,\n\t\t\tdepthWrite: false,\n\t\t});\n\n\t\t// Fullscreen triangle (more efficient than quad — no diagonal seam)\n\t\tconst geometry = new THREE.BufferGeometry();\n\t\tconst vertices = new Float32Array([-1, -1, 0, 3, -1, 0, -1, 3, 0]);\n\t\tgeometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));\n\n\t\tthis.mesh = new THREE.Mesh(geometry, this.material);\n\t\tthis.scene.add(this.mesh);\n\t}\n\n\t/** Apply a (partial) grid config. Only provided fields are updated. */\n\tsetConfig(config: Partial<GridConfig>) {\n\t\tconst u = this.material.uniforms;\n\t\tif (config.spacings) u.u_spacings.value.set(...config.spacings);\n\t\tif (config.dotColor) u.u_dotColor.value.set(...config.dotColor);\n\t\tif (config.dotAlpha !== undefined) u.u_dotAlpha.value = config.dotAlpha;\n\t\tif (config.fadeIn) u.u_fadeIn.value.set(...config.fadeIn);\n\t\tif (config.fadeOut) u.u_fadeOut.value.set(...config.fadeOut);\n\t\tif (config.dotRadius) u.u_dotRadius.value.set(...config.dotRadius);\n\t\tif (config.levelWeight) u.u_levelWeight.value.set(...config.levelWeight);\n\t}\n\n\tsetSize(width: number, height: number, dpr = 1) {\n\t\tthis.renderer.setSize(width, height, false);\n\t\tthis.renderer.setPixelRatio(dpr);\n\t\tconst u = this.material.uniforms;\n\t\tu.u_resolution.value.set(width * dpr, height * dpr);\n\t\tu.u_dpr.value = dpr;\n\t}\n\n\trender(cameraX: number, cameraY: number, zoom: number) {\n\t\tconst u = this.material.uniforms;\n\t\tu.u_camera.value.set(cameraX, cameraY);\n\t\tu.u_zoom.value = zoom;\n\t\tthis.renderer.render(this.scene, this.camera);\n\t}\n\n\tdispose() {\n\t\tthis.mesh.geometry.dispose();\n\t\tthis.material.dispose();\n\t\tthis.renderer.dispose();\n\t}\n\n\t/** Expose for future WebGL widget rendering */\n\tgetWebGLRenderer(): THREE.WebGLRenderer {\n\t\treturn this.renderer;\n\t}\n}\n","import * as THREE from 'three';\nimport { HANDLE_VISUAL_SIZE_PX } from '../../interaction-constants.js';\nimport type { EqualSpacingIndicator, SnapGuide } from '../../snap.js';\n\n// === Public config (Figma-style defaults) ===\n\nexport interface SelectionConfig {\n\t/** Selection outline color [r,g,b] 0-1. Default: Figma blue. */\n\toutlineColor: [number, number, number];\n\t/** Selection outline width in screen px. */\n\toutlineWidth: number;\n\t/** Hover outline color [r,g,b] 0-1. */\n\thoverColor: [number, number, number];\n\t/** Hover outline width in screen px. */\n\thoverWidth: number;\n\t/** Handle size in screen px. */\n\thandleSize: number;\n\t/** Handle fill color [r,g,b] 0-1 (white). */\n\thandleFill: [number, number, number];\n\t/** Handle border color [r,g,b] 0-1 (same as outline). */\n\thandleBorder: [number, number, number];\n\t/** Handle border width in screen px. */\n\thandleBorderWidth: number;\n\t/** Group bbox dash length in screen px (0 = solid). */\n\tgroupDash: number;\n}\n\nexport const DEFAULT_SELECTION_CONFIG: SelectionConfig = {\n\toutlineColor: [0.051, 0.6, 1.0], // #0d99ff (Figma blue)\n\toutlineWidth: 1.5,\n\thoverColor: [0.051, 0.6, 1.0],\n\thoverWidth: 1.0,\n\thandleSize: HANDLE_VISUAL_SIZE_PX,\n\thandleFill: [1, 1, 1],\n\thandleBorder: [0.051, 0.6, 1.0],\n\thandleBorderWidth: 1.5,\n\tgroupDash: 4,\n};\n\n// === Bounds data passed per frame ===\n\nexport interface SelectionBounds {\n\tx: number;\n\ty: number;\n\twidth: number;\n\theight: number;\n}\n\n// === Shader ===\n\nconst MAX_ENTITIES = 32;\n\nconst vertexShader = /* glsl */ `\nvoid main() {\n\tgl_Position = vec4(position.xy, 0.0, 1.0);\n}\n`;\n\nconst fragmentShader = /* glsl */ `\nprecision highp float;\n\nuniform vec2 u_resolution;\nuniform vec2 u_camera;\nuniform float u_zoom;\nuniform float u_dpr;\n\n// Selection data\nuniform int u_count;\nuniform vec4 u_bounds[${MAX_ENTITIES}]; // (worldX, worldY, width, height)\nuniform int u_hoverIdx; // -1 = none\nuniform vec4 u_groupBounds; // group bbox (0 if count <= 1)\nuniform int u_hasGroup;\n\n// Snap guides\nuniform int u_guideCount;\nuniform vec4 u_guides[16]; // (axis: 0=x/1=y, position, 0, 0)\nuniform int u_spacingCount;\nuniform vec4 u_spacings[8]; // equal-spacing segments: (axis, from, to, perpPos)\nuniform vec3 u_guideColor;\n\n// Style\nuniform vec3 u_outlineColor;\nuniform float u_outlineWidth;\nuniform vec3 u_hoverColor;\nuniform float u_hoverWidth;\nuniform float u_handleSize;\nuniform vec3 u_handleFill;\nuniform vec3 u_handleBorder;\nuniform float u_handleBorderWidth;\nuniform float u_groupDash;\n\n// SDF for axis-aligned rectangle outline (returns distance to edge)\nfloat sdRectOutline(vec2 p, vec2 center, vec2 halfSize) {\n\tvec2 d = abs(p - center) - halfSize;\n\tfloat outside = length(max(d, 0.0));\n\tfloat inside = min(max(d.x, d.y), 0.0);\n\treturn abs(outside + inside);\n}\n\n// SDF for filled square\nfloat sdSquare(vec2 p, vec2 center, float halfSize) {\n\tvec2 d = abs(p - center) - vec2(halfSize);\n\treturn max(d.x, d.y);\n}\n\nvoid main() {\n\tif (u_count == 0 && u_hoverIdx < 0) discard;\n\n\tvec2 devicePos = gl_FragCoord.xy;\n\tdevicePos.y = u_resolution.y - devicePos.y;\n\n\tfloat effectiveZoom = u_zoom * u_dpr;\n\tvec2 worldPos = devicePos / effectiveZoom + u_camera;\n\n\t// Screen-space conversion factor\n\tfloat pxToWorld = 1.0 / effectiveZoom;\n\n\tvec4 color = vec4(0.0);\n\n\t// --- Hover outline ---\n\tif (u_hoverIdx >= 0 && u_hoverIdx < ${MAX_ENTITIES}) {\n\t\tvec4 b = u_bounds[u_hoverIdx];\n\t\tvec2 center = vec2(b.x + b.z * 0.5, b.y + b.w * 0.5);\n\t\tvec2 halfSize = vec2(b.z, b.w) * 0.5;\n\t\tfloat dist = sdRectOutline(worldPos, center, halfSize);\n\t\tfloat width = u_hoverWidth * pxToWorld;\n\t\tfloat alpha = 1.0 - smoothstep(width - pxToWorld * 0.5, width + pxToWorld * 0.5, dist);\n\t\tcolor = max(color, vec4(u_hoverColor, alpha * 0.6));\n\t}\n\n\t// --- Selection outlines ---\n\tfor (int i = 0; i < ${MAX_ENTITIES}; i++) {\n\t\tif (i >= u_count) break;\n\t\tvec4 b = u_bounds[i];\n\t\tvec2 center = vec2(b.x + b.z * 0.5, b.y + b.w * 0.5);\n\t\tvec2 halfSize = vec2(b.z, b.w) * 0.5;\n\n\t\t// Outline\n\t\tfloat dist = sdRectOutline(worldPos, center, halfSize);\n\t\tfloat width = u_outlineWidth * pxToWorld;\n\t\tfloat outlineAlpha = 1.0 - smoothstep(width - pxToWorld * 0.5, width + pxToWorld * 0.5, dist);\n\t\tcolor = max(color, vec4(u_outlineColor, outlineAlpha));\n\n\t\t// 8 resize handles\n\t\tfloat hs = u_handleSize * 0.5 * pxToWorld;\n\t\tfloat bw = u_handleBorderWidth * pxToWorld;\n\t\tvec2 corners[8];\n\t\tcorners[0] = vec2(b.x, b.y); // nw\n\t\tcorners[1] = vec2(b.x + b.z * 0.5, b.y); // n\n\t\tcorners[2] = vec2(b.x + b.z, b.y); // ne\n\t\tcorners[3] = vec2(b.x + b.z, b.y + b.w * 0.5); // e\n\t\tcorners[4] = vec2(b.x + b.z, b.y + b.w); // se\n\t\tcorners[5] = vec2(b.x + b.z * 0.5, b.y + b.w); // s\n\t\tcorners[6] = vec2(b.x, b.y + b.w); // sw\n\t\tcorners[7] = vec2(b.x, b.y + b.w * 0.5); // w\n\n\t\tfor (int h = 0; h < 8; h++) {\n\t\t\tfloat d = sdSquare(worldPos, corners[h], hs);\n\t\t\t// Fill (white)\n\t\t\tfloat fillAlpha = 1.0 - smoothstep(-pxToWorld * 0.5, pxToWorld * 0.5, d);\n\t\t\t// Border\n\t\t\tfloat borderDist = abs(d + bw * 0.5) - bw * 0.5;\n\t\t\tfloat borderAlpha = 1.0 - smoothstep(-pxToWorld * 0.5, pxToWorld * 0.5, borderDist);\n\n\t\t\tif (fillAlpha > 0.01) {\n\t\t\t\t// Composite: border color on top of fill\n\t\t\t\tvec3 handleColor = mix(u_handleFill, u_handleBorder, borderAlpha);\n\t\t\t\tcolor = vec4(handleColor, max(fillAlpha, color.a));\n\t\t\t}\n\t\t}\n\t}\n\n\t// --- Group bounding box (dashed) ---\n\tif (u_hasGroup == 1 && u_count > 1) {\n\t\tvec4 gb = u_groupBounds;\n\t\tvec2 center = vec2(gb.x + gb.z * 0.5, gb.y + gb.w * 0.5);\n\t\tvec2 halfSize = vec2(gb.z, gb.w) * 0.5;\n\t\tfloat dist = sdRectOutline(worldPos, center, halfSize);\n\t\tfloat width = u_outlineWidth * 0.75 * pxToWorld;\n\t\tfloat lineAlpha = 1.0 - smoothstep(width - pxToWorld * 0.5, width + pxToWorld * 0.5, dist);\n\n\t\t// Dash pattern along the rectangle perimeter\n\t\tif (u_groupDash > 0.0 && lineAlpha > 0.01) {\n\t\t\t// Proper perimeter arc-length from top-left corner going clockwise\n\t\t\tfloat perim;\n\t\t\tvec2 rel = worldPos - vec2(gb.x, gb.y);\n\t\t\tfloat w = gb.z;\n\t\t\tfloat h = gb.w;\n\n\t\t\t// Determine which edge is nearest and compute cumulative arc length\n\t\t\tfloat dTop = abs(rel.y);\n\t\t\tfloat dRight = abs(rel.x - w);\n\t\t\tfloat dBottom = abs(rel.y - h);\n\t\t\tfloat dLeft = abs(rel.x);\n\n\t\t\tif (dTop <= dBottom && dTop <= dLeft && dTop <= dRight) {\n\t\t\t\tperim = rel.x; // top edge: 0 to w\n\t\t\t} else if (dRight <= dLeft) {\n\t\t\t\tperim = w + rel.y; // right edge: w to w+h\n\t\t\t} else if (dBottom <= dTop) {\n\t\t\t\tperim = w + h + (w - rel.x); // bottom edge: w+h to 2w+h\n\t\t\t} else {\n\t\t\t\tperim = 2.0 * w + h + (h - rel.y); // left edge: 2w+h to 2w+2h\n\t\t\t}\n\n\t\t\tfloat dashWorld = u_groupDash * pxToWorld;\n\t\t\tfloat dashPattern = step(0.5, fract(perim / (dashWorld * 2.0)));\n\t\t\tlineAlpha *= dashPattern;\n\t\t}\n\n\t\tcolor = max(color, vec4(u_outlineColor, lineAlpha * 0.5));\n\t}\n\n\t// --- Snap guide lines ---\n\tfor (int i = 0; i < 16; i++) {\n\t\tif (i >= u_guideCount) break;\n\t\tvec4 g = u_guides[i];\n\t\tfloat guideWidth = 0.5 * pxToWorld;\n\t\tfloat dist;\n\t\tif (g.x < 0.5) {\n\t\t\t// Vertical line (x-axis alignment)\n\t\t\tdist = abs(worldPos.x - g.y);\n\t\t} else {\n\t\t\t// Horizontal line (y-axis alignment)\n\t\t\tdist = abs(worldPos.y - g.y);\n\t\t}\n\t\tfloat guideAlpha = 1.0 - smoothstep(guideWidth - pxToWorld * 0.3, guideWidth + pxToWorld * 0.3, dist);\n\t\tcolor = max(color, vec4(u_guideColor, guideAlpha * 0.8));\n\t}\n\n\t// --- Equal spacing indicators ---\n\tfor (int i = 0; i < 8; i++) {\n\t\tif (i >= u_spacingCount) break;\n\t\tvec4 s = u_spacings[i];\n\t\tfloat lineWidth = 0.5 * pxToWorld;\n\t\tfloat segAlpha = 0.0;\n\t\tif (s.x < 0.5) {\n\t\t\t// Horizontal segment (x-axis gap)\n\t\t\tfloat yDist = abs(worldPos.y - s.w);\n\t\t\tfloat xInRange = step(s.y, worldPos.x) * step(worldPos.x, s.z);\n\t\t\t// Center line\n\t\t\tsegAlpha = (1.0 - smoothstep(lineWidth, lineWidth + pxToWorld, yDist)) * xInRange;\n\t\t\t// End bars (perpendicular marks at from and to)\n\t\t\tfloat barHeight = 4.0 * pxToWorld;\n\t\t\tfloat barFromDist = abs(worldPos.x - s.y);\n\t\t\tfloat barFromAlpha = (1.0 - smoothstep(lineWidth, lineWidth + pxToWorld, barFromDist))\n\t\t\t\t* (1.0 - smoothstep(barHeight, barHeight + pxToWorld, abs(worldPos.y - s.w)));\n\t\t\tfloat barToDist = abs(worldPos.x - s.z);\n\t\t\tfloat barToAlpha = (1.0 - smoothstep(lineWidth, lineWidth + pxToWorld, barToDist))\n\t\t\t\t* (1.0 - smoothstep(barHeight, barHeight + pxToWorld, abs(worldPos.y - s.w)));\n\t\t\tsegAlpha = max(segAlpha, max(barFromAlpha, barToAlpha));\n\t\t} else {\n\t\t\t// Vertical segment (y-axis gap)\n\t\t\tfloat xDist = abs(worldPos.x - s.w);\n\t\t\tfloat yInRange = step(s.y, worldPos.y) * step(worldPos.y, s.z);\n\t\t\tsegAlpha = (1.0 - smoothstep(lineWidth, lineWidth + pxToWorld, xDist)) * yInRange;\n\t\t\tfloat barWidth = 4.0 * pxToWorld;\n\t\t\tfloat barFromAlpha = (1.0 - smoothstep(lineWidth, lineWidth + pxToWorld, abs(worldPos.y - s.y)))\n\t\t\t\t* (1.0 - smoothstep(barWidth, barWidth + pxToWorld, abs(worldPos.x - s.w)));\n\t\t\tfloat barToAlpha = (1.0 - smoothstep(lineWidth, lineWidth + pxToWorld, abs(worldPos.y - s.z)))\n\t\t\t\t* (1.0 - smoothstep(barWidth, barWidth + pxToWorld, abs(worldPos.x - s.w)));\n\t\t\tsegAlpha = max(segAlpha, max(barFromAlpha, barToAlpha));\n\t\t}\n\t\tcolor = max(color, vec4(u_guideColor, segAlpha * 0.7));\n\t}\n\n\tif (color.a < 0.01) discard;\n\tgl_FragColor = color;\n}\n`;\n\n// === Renderer class ===\n\nexport class SelectionRenderer {\n\tprivate material: THREE.ShaderMaterial;\n\tprivate mesh: THREE.Mesh;\n\tprivate scene: THREE.Scene;\n\tprivate camera: THREE.OrthographicCamera;\n\n\tconstructor() {\n\t\tthis.scene = new THREE.Scene();\n\t\tthis.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);\n\n\t\tconst boundsDefault = [];\n\t\tfor (let i = 0; i < MAX_ENTITIES; i++) {\n\t\t\tboundsDefault.push(new THREE.Vector4(0, 0, 0, 0));\n\t\t}\n\n\t\tthis.material = new THREE.ShaderMaterial({\n\t\t\tvertexShader,\n\t\t\tfragmentShader,\n\t\t\tuniforms: {\n\t\t\t\tu_resolution: { value: new THREE.Vector2(1, 1) },\n\t\t\t\tu_camera: { value: new THREE.Vector2(0, 0) },\n\t\t\t\tu_zoom: { value: 1 },\n\t\t\t\tu_dpr: { value: 1 },\n\t\t\t\tu_count: { value: 0 },\n\t\t\t\tu_bounds: { value: boundsDefault },\n\t\t\t\tu_hoverIdx: { value: -1 },\n\t\t\t\tu_groupBounds: { value: new THREE.Vector4(0, 0, 0, 0) },\n\t\t\t\tu_hasGroup: { value: 0 },\n\t\t\t\t// Style (Figma defaults)\n\t\t\t\tu_outlineColor: { value: new THREE.Vector3(...DEFAULT_SELECTION_CONFIG.outlineColor) },\n\t\t\t\tu_outlineWidth: { value: DEFAULT_SELECTION_CONFIG.outlineWidth },\n\t\t\t\tu_hoverColor: { value: new THREE.Vector3(...DEFAULT_SELECTION_CONFIG.hoverColor) },\n\t\t\t\tu_hoverWidth: { value: DEFAULT_SELECTION_CONFIG.hoverWidth },\n\t\t\t\tu_handleSize: { value: DEFAULT_SELECTION_CONFIG.handleSize },\n\t\t\t\tu_handleFill: { value: new THREE.Vector3(...DEFAULT_SELECTION_CONFIG.handleFill) },\n\t\t\t\tu_handleBorder: { value: new THREE.Vector3(...DEFAULT_SELECTION_CONFIG.handleBorder) },\n\t\t\t\tu_handleBorderWidth: { value: DEFAULT_SELECTION_CONFIG.handleBorderWidth },\n\t\t\t\tu_groupDash: { value: DEFAULT_SELECTION_CONFIG.groupDash },\n\t\t\t\t// Snap guides\n\t\t\t\tu_guideCount: { value: 0 },\n\t\t\t\tu_guides: { value: Array.from({ length: 16 }, () => new THREE.Vector4(0, 0, 0, 0)) },\n\t\t\t\tu_spacingCount: { value: 0 },\n\t\t\t\tu_spacings: { value: Array.from({ length: 8 }, () => new THREE.Vector4(0, 0, 0, 0)) },\n\t\t\t\tu_guideColor: { value: new THREE.Vector3(1.0, 0.0, 0.55) }, // magenta/pink\n\t\t\t},\n\t\t\ttransparent: true,\n\t\t\tdepthTest: false,\n\t\t\tdepthWrite: false,\n\t\t});\n\n\t\tconst geometry = new THREE.BufferGeometry();\n\t\tconst vertices = new Float32Array([-1, -1, 0, 3, -1, 0, -1, 3, 0]);\n\t\tgeometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));\n\n\t\tthis.mesh = new THREE.Mesh(geometry, this.material);\n\t\tthis.scene.add(this.mesh);\n\t}\n\n\tsetConfig(config: Partial<SelectionConfig>) {\n\t\tconst u = this.material.uniforms;\n\t\tif (config.outlineColor) u.u_outlineColor.value.set(...config.outlineColor);\n\t\tif (config.outlineWidth !== undefined) u.u_outlineWidth.value = config.outlineWidth;\n\t\tif (config.hoverColor) u.u_hoverColor.value.set(...config.hoverColor);\n\t\tif (config.hoverWidth !== undefined) u.u_hoverWidth.value = config.hoverWidth;\n\t\tif (config.handleSize !== undefined) u.u_handleSize.value = config.handleSize;\n\t\tif (config.handleFill) u.u_handleFill.value.set(...config.handleFill);\n\t\tif (config.handleBorder) u.u_handleBorder.value.set(...config.handleBorder);\n\t\tif (config.handleBorderWidth !== undefined)\n\t\t\tu.u_handleBorderWidth.value = config.handleBorderWidth;\n\t\tif (config.groupDash !== undefined) u.u_groupDash.value = config.groupDash;\n\t}\n\n\tsetSize(resolution: THREE.Vector2, dpr: number) {\n\t\tthis.material.uniforms.u_resolution.value.copy(resolution);\n\t\tthis.material.uniforms.u_dpr.value = dpr;\n\t}\n\n\trender(\n\t\trenderer: THREE.WebGLRenderer,\n\t\tcameraX: number,\n\t\tcameraY: number,\n\t\tzoom: number,\n\t\tselected: SelectionBounds[],\n\t\thovered: SelectionBounds | null,\n\t\tguides: SnapGuide[] = [],\n\t\tspacings: EqualSpacingIndicator[] = [],\n\t) {\n\t\tconst u = this.material.uniforms;\n\t\tu.u_camera.value.set(cameraX, cameraY);\n\t\tu.u_zoom.value = zoom;\n\n\t\t// Upload selected bounds\n\t\tconst count = Math.min(selected.length, MAX_ENTITIES);\n\t\tu.u_count.value = count;\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tconst b = selected[i];\n\t\t\tu.u_bounds.value[i].set(b.x, b.y, b.width, b.height);\n\t\t}\n\n\t\t// Upload hover\n\t\tif (hovered && count < MAX_ENTITIES) {\n\t\t\t// Find if hovered is in the selected list\n\t\t\tlet hoverIdx = -1;\n\t\t\tfor (let i = 0; i < count; i++) {\n\t\t\t\tconst b = selected[i];\n\t\t\t\tif (b.x === hovered.x && b.y === hovered.y) {\n\t\t\t\t\thoverIdx = i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (hoverIdx < 0) {\n\t\t\t\t// Hovered but not selected — add to bounds array\n\t\t\t\tu.u_bounds.value[count].set(hovered.x, hovered.y, hovered.width, hovered.height);\n\t\t\t\tu.u_hoverIdx.value = count;\n\t\t\t} else {\n\t\t\t\tu.u_hoverIdx.value = -1; // already selected, no separate hover\n\t\t\t}\n\t\t} else {\n\t\t\tu.u_hoverIdx.value = -1;\n\t\t}\n\n\t\t// Group bounding box\n\t\tif (count > 1) {\n\t\t\tlet minX = Number.POSITIVE_INFINITY;\n\t\t\tlet minY = Number.POSITIVE_INFINITY;\n\t\t\tlet maxX = Number.NEGATIVE_INFINITY;\n\t\t\tlet maxY = Number.NEGATIVE_INFINITY;\n\t\t\tfor (let i = 0; i < count; i++) {\n\t\t\t\tconst b = selected[i];\n\t\t\t\tminX = Math.min(minX, b.x);\n\t\t\t\tminY = Math.min(minY, b.y);\n\t\t\t\tmaxX = Math.max(maxX, b.x + b.width);\n\t\t\t\tmaxY = Math.max(maxY, b.y + b.height);\n\t\t\t}\n\t\t\tu.u_groupBounds.value.set(minX, minY, maxX - minX, maxY - minY);\n\t\t\tu.u_hasGroup.value = 1;\n\t\t} else {\n\t\t\tu.u_hasGroup.value = 0;\n\t\t}\n\n\t\t// Upload snap guides\n\t\tconst gCount = Math.min(guides.length, 16);\n\t\tu.u_guideCount.value = gCount;\n\t\tfor (let i = 0; i < gCount; i++) {\n\t\t\tconst g = guides[i];\n\t\t\tu.u_guides.value[i].set(g.axis === 'x' ? 0 : 1, g.position, 0, 0);\n\t\t}\n\n\t\t// Upload equal spacing segments\n\t\tlet sIdx = 0;\n\t\tfor (const sp of spacings) {\n\t\t\tfor (const seg of sp.segments) {\n\t\t\t\tif (sIdx >= 8) break;\n\t\t\t\tu.u_spacings.value[sIdx].set(sp.axis === 'x' ? 0 : 1, seg.from, seg.to, sp.perpPosition);\n\t\t\t\tsIdx++;\n\t\t\t}\n\t\t}\n\t\tu.u_spacingCount.value = sIdx;\n\n\t\t// Render without clearing (composites on top of grid)\n\t\tconst prevAutoClear = renderer.autoClear;\n\t\trenderer.autoClear = false;\n\t\trenderer.render(this.scene, this.camera);\n\t\trenderer.autoClear = prevAutoClear;\n\t}\n\n\tdispose() {\n\t\tthis.mesh.geometry.dispose();\n\t\tthis.material.dispose();\n\t}\n}\n","import type { EntityId } from '@jamesyong42/reactive-ecs';\nimport { useFrame } from '@react-three/fiber';\nimport { useRef } from 'react';\nimport type { Group } from 'three';\nimport { WorldBounds } from '../../components.js';\nimport { useLayoutEngine } from '../context.js';\nimport { useComponent } from '../hooks.js';\nimport type { R3FWidgetProps } from '../registry.js';\n\ninterface WebGLWidgetSlotProps {\n\tentityId: EntityId;\n\tcomponent: React.ComponentType<R3FWidgetProps>;\n}\n\n/**\n * Positions a Three.js Group at the entity's world-space center.\n * The widget component renders in local space: origin at center,\n * X right, Y up, dimensions = (width, height) in world units.\n */\nexport function WebGLWidgetSlot({ entityId, component: WidgetComponent }: WebGLWidgetSlotProps) {\n\tconst groupRef = useRef<Group>(null);\n\tconst engine = useLayoutEngine();\n\n\t// Read WorldBounds reactively for initial render\n\tconst wb = useComponent(entityId, WorldBounds);\n\n\t// Update position every frame (camera may have moved)\n\tuseFrame(() => {\n\t\tif (!groupRef.current) return;\n\t\tconst bounds = engine.get(entityId, WorldBounds);\n\t\tif (!bounds) return;\n\t\t// Position at center of bounding box; flip Y for Three.js\n\t\tgroupRef.current.position.set(\n\t\t\tbounds.worldX + bounds.worldWidth / 2,\n\t\t\t-(bounds.worldY + bounds.worldHeight / 2),\n\t\t\t0,\n\t\t);\n\t});\n\n\tif (!wb) return null;\n\n\treturn (\n\t\t<group ref={groupRef}>\n\t\t\t<WidgetComponent entityId={entityId} width={wb.worldWidth} height={wb.worldHeight} />\n\t\t</group>\n\t);\n}\n","import type { EntityId } from '@jamesyong42/reactive-ecs';\nimport { Canvas, useFrame, useThree } from '@react-three/fiber';\nimport { useLayoutEffect, useMemo, useRef } from 'react';\nimport * as THREE from 'three';\nimport type { LayoutEngine } from '../../engine.js';\nimport type { ResolvedWidget } from '../context.js';\nimport { EngineProvider } from '../context.js';\nimport type { R3FWidgetProps } from '../registry.js';\nimport { WebGLWidgetSlot } from './WebGLWidgetSlot.js';\n\n// === Profiler probe (runs inside the R3F canvas) ===\n\n/**\n * Reports one R3F frame sample per animation frame to the engine profiler.\n * Reads `renderer.info` from three.js — draw calls / triangles / memory /\n * programs — which is maintained by R3F's default render loop regardless\n * of whether we opt in. Only samples when the profiler is enabled.\n */\nfunction ProfilerProbe({ engine, widgetCount }: { engine: LayoutEngine; widgetCount: number }) {\n\tconst { gl } = useThree();\n\tconst prevTimeRef = useRef<number | null>(null);\n\tconst prevCallsRef = useRef(0);\n\tconst prevTrianglesRef = useRef(0);\n\tconst prevPointsRef = useRef(0);\n\tconst prevLinesRef = useRef(0);\n\n\tuseFrame(() => {\n\t\tconst profiler = engine.profiler;\n\t\tif (!profiler.isEnabled()) {\n\t\t\tprevTimeRef.current = null;\n\t\t\treturn;\n\t\t}\n\t\tconst now = performance.now();\n\t\tconst dtMs = prevTimeRef.current === null ? 0 : now - prevTimeRef.current;\n\t\tprevTimeRef.current = now;\n\n\t\tconst info = gl.info;\n\t\t// renderer.info.render resets per frame when autoReset is true (default).\n\t\t// Read the current values as this frame's counts. But programs/memory\n\t\t// are cumulative gauges. Capture deltas defensively in case a future\n\t\t// change flips autoReset off.\n\t\tconst calls = info.render.calls;\n\t\tconst triangles = info.render.triangles;\n\t\tconst points = info.render.points;\n\t\tconst lines = info.render.lines;\n\t\tconst frameCalls = info.autoReset ? calls : Math.max(0, calls - prevCallsRef.current);\n\t\tconst frameTris = info.autoReset\n\t\t\t? triangles\n\t\t\t: Math.max(0, triangles - prevTrianglesRef.current);\n\t\tconst framePoints = info.autoReset ? points : Math.max(0, points - prevPointsRef.current);\n\t\tconst frameLines = info.autoReset ? lines : Math.max(0, lines - prevLinesRef.current);\n\t\tprevCallsRef.current = calls;\n\t\tprevTrianglesRef.current = triangles;\n\t\tprevPointsRef.current = points;\n\t\tprevLinesRef.current = lines;\n\n\t\tprofiler.recordR3FFrame({\n\t\t\tdtMs,\n\t\t\tdrawCalls: frameCalls,\n\t\t\ttriangles: frameTris,\n\t\t\tpoints: framePoints,\n\t\t\tlines: frameLines,\n\t\t\tprograms: info.programs?.length ?? 0,\n\t\t\tgeometries: info.memory.geometries,\n\t\t\ttextures: info.memory.textures,\n\t\t\tactiveWidgets: widgetCount,\n\t\t});\n\t});\n\n\treturn null;\n}\n\n// === Camera sync component (runs inside R3F) ===\n\nfunction syncCamera(\n\tcamera: THREE.Camera,\n\tsize: { width: number; height: number },\n\tengine: LayoutEngine,\n) {\n\tconst cam = engine.getCamera();\n\tconst ortho = camera as THREE.OrthographicCamera;\n\n\t// Frustum in world units — matches our engine coordinate system\n\tortho.left = 0;\n\tortho.right = size.width / cam.zoom;\n\tortho.top = 0;\n\tortho.bottom = -(size.height / cam.zoom);\n\tortho.near = 0.1;\n\tortho.far = 10000;\n\n\t// Position camera at engine camera origin; flip Y for Three.js\n\tortho.position.set(cam.x, -cam.y, 1000);\n\tortho.updateProjectionMatrix();\n}\n\nfunction CameraSync({ engine }: { engine: LayoutEngine }) {\n\tconst { camera, size } = useThree();\n\n\t// Sync camera immediately on mount — don't wait for the first useFrame tick\n\tuseLayoutEffect(() => {\n\t\tsyncCamera(camera, size, engine);\n\t}, [camera, size, engine]);\n\n\tuseFrame(() => {\n\t\tsyncCamera(camera, size, engine);\n\t});\n\n\treturn null;\n}\n\n// === Main layer component ===\n\ninterface WebGLWidgetLayerProps {\n\tengine: LayoutEngine;\n\tentities: EntityId[];\n\tresolve: (entityId: EntityId) => ResolvedWidget | null;\n}\n\nexport function WebGLWidgetLayer({ engine, entities, resolve }: WebGLWidgetLayerProps) {\n\tconst canvasRef = useRef<HTMLCanvasElement>(null);\n\n\t// Create a stable orthographic camera (R3F needs one at init)\n\tconst initialCamera = useMemo(() => {\n\t\tconst cam = new THREE.OrthographicCamera(0, 1, 0, -1, 0.1, 10000);\n\t\tcam.position.set(0, 0, 1000);\n\t\treturn cam;\n\t}, []);\n\n\t// Build a map of entityId → component for rendering\n\tconst widgetEntries = useMemo(() => {\n\t\tconst result: {\n\t\t\tentityId: EntityId;\n\t\t\tcomponent: React.ComponentType<R3FWidgetProps>;\n\t\t}[] = [];\n\t\tfor (const id of entities) {\n\t\t\tconst resolved = resolve(id);\n\t\t\tif (resolved && resolved.surface === 'webgl') {\n\t\t\t\tresult.push({ entityId: id, component: resolved.component });\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}, [entities, resolve]);\n\n\treturn (\n\t\t<Canvas\n\t\t\tref={canvasRef}\n\t\t\tcamera={initialCamera}\n\t\t\tframeloop=\"always\"\n\t\t\tgl={{ alpha: true, antialias: true }}\n\t\t\tstyle={{\n\t\t\t\tposition: 'absolute',\n\t\t\t\tinset: 0,\n\t\t\t\tpointerEvents: 'none',\n\t\t\t\tzIndex: 1,\n\t\t\t\tdisplay: widgetEntries.length === 0 ? 'none' : 'block',\n\t\t\t}}\n\t\t>\n\t\t\t<EngineProvider value={engine}>\n\t\t\t\t<CameraSync engine={engine} />\n\t\t\t\t<ProfilerProbe engine={engine} widgetCount={widgetEntries.length} />\n\t\t\t\t{widgetEntries.map(({ entityId, component }) => (\n\t\t\t\t\t<WebGLWidgetSlot key={entityId} entityId={entityId} component={component} />\n\t\t\t\t))}\n\t\t\t</EngineProvider>\n\t\t</Canvas>\n\t);\n}\n"],"x_google_ignoreList":[6,7],"mappings":"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"}
|