@jamesyong42/infinite-canvas 1.0.0 → 1.2.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.
Files changed (54) hide show
  1. package/README.md +170 -9
  2. package/dist/SelectionRenderer-CR2PBQwx.d.cts +105 -0
  3. package/dist/SelectionRenderer-CR2PBQwx.d.cts.map +1 -0
  4. package/dist/SelectionRenderer-DlsBstAq.d.mts +105 -0
  5. package/dist/SelectionRenderer-DlsBstAq.d.mts.map +1 -0
  6. package/dist/WebGLWidgetLayer-BBMuwzHq.cjs +3560 -0
  7. package/dist/WebGLWidgetLayer-BBMuwzHq.cjs.map +1 -0
  8. package/dist/WebGLWidgetLayer-C3p1tnpm.mjs +3375 -0
  9. package/dist/WebGLWidgetLayer-C3p1tnpm.mjs.map +1 -0
  10. package/dist/advanced.cjs +110 -165
  11. package/dist/advanced.cjs.map +1 -1
  12. package/dist/advanced.d.cts +58 -40
  13. package/dist/advanced.d.cts.map +1 -0
  14. package/dist/advanced.d.mts +99 -0
  15. package/dist/advanced.d.mts.map +1 -0
  16. package/dist/advanced.mjs +105 -0
  17. package/dist/advanced.mjs.map +1 -0
  18. package/dist/devtools.cjs +654 -0
  19. package/dist/devtools.cjs.map +1 -0
  20. package/dist/devtools.d.cts +23 -0
  21. package/dist/devtools.d.cts.map +1 -0
  22. package/dist/devtools.d.mts +23 -0
  23. package/dist/devtools.d.mts.map +1 -0
  24. package/dist/devtools.mjs +652 -0
  25. package/dist/devtools.mjs.map +1 -0
  26. package/dist/engine-BfbvWXSk.d.mts +982 -0
  27. package/dist/engine-BfbvWXSk.d.mts.map +1 -0
  28. package/dist/engine-CCjuFMC-.d.cts +982 -0
  29. package/dist/engine-CCjuFMC-.d.cts.map +1 -0
  30. package/dist/hooks-BwY7rRHg.mjs +425 -0
  31. package/dist/hooks-BwY7rRHg.mjs.map +1 -0
  32. package/dist/hooks-DHShH86C.cjs +707 -0
  33. package/dist/hooks-DHShH86C.cjs.map +1 -0
  34. package/dist/index.cjs +909 -803
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +199 -67
  37. package/dist/index.d.cts.map +1 -0
  38. package/dist/index.d.mts +258 -0
  39. package/dist/index.d.mts.map +1 -0
  40. package/dist/index.mjs +855 -0
  41. package/dist/index.mjs.map +1 -0
  42. package/package.json +47 -15
  43. package/dist/SelectionRenderer-CeWSNZT8.d.cts +0 -891
  44. package/dist/SelectionRenderer-CeWSNZT8.d.ts +0 -891
  45. package/dist/advanced.d.ts +0 -81
  46. package/dist/advanced.js +0 -124
  47. package/dist/advanced.js.map +0 -1
  48. package/dist/chunk-VSHXWTJH.cjs +0 -3228
  49. package/dist/chunk-VSHXWTJH.cjs.map +0 -1
  50. package/dist/chunk-Z6JQQOWL.js +0 -3142
  51. package/dist/chunk-Z6JQQOWL.js.map +0 -1
  52. package/dist/index.d.ts +0 -126
  53. package/dist/index.js +0 -602
  54. package/dist/index.js.map +0 -1
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/react/WidgetProvider.tsx","../src/react/InfiniteCanvas.tsx","../src/react/widget-hooks.ts"],"names":["InfiniteCanvas","useCallback","camera","visible","jsx"],"mappings":"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","file":"index.js","sourcesContent":["import type { ReactNode } from 'react';\nimport { useCallback } from 'react';\nimport type { LayoutEngine } from '../engine.js';\nimport type { ResolvedWidget } from './context.js';\nimport { WidgetResolverProvider } from './context.js';\nimport { isR3FWidget } from './registry.js';\n\ninterface WidgetProviderProps {\n\tengine: LayoutEngine;\n\tchildren?: ReactNode;\n}\n\n/**\n * Bridges the engine's widget registry to React context so WidgetSlot /\n * WebGLWidgetLayer can resolve components by type.\n */\nexport function WidgetProvider({ engine, children }: WidgetProviderProps) {\n\tconst resolver = useCallback(\n\t\t(_entityId: number, widgetType: string): ResolvedWidget | null => {\n\t\t\tconst def = engine.getWidget(widgetType);\n\t\t\tif (!def) return null;\n\t\t\tif (isR3FWidget(def)) {\n\t\t\t\treturn { surface: 'webgl', component: def.component };\n\t\t\t}\n\t\t\treturn { surface: 'dom', component: def.component };\n\t\t},\n\t\t[engine],\n\t);\n\n\treturn <WidgetResolverProvider value={resolver}>{children}</WidgetResolverProvider>;\n}\n","import type { EntityId } from '@jamesyong42/reactive-ecs';\nimport React, {\n\tuseCallback,\n\tuseEffect,\n\tuseImperativeHandle,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport { Vector2 } from 'three';\nimport { Widget, WorldBounds } from '../components.js';\nimport type { LayoutEngine } from '../engine.js';\nimport { DEAD_ZONE_TOUCH_PX } from '../interaction-constants.js';\nimport { CursorResource, NavigationStackResource } from '../resources.js';\nimport { ContainerRefProvider, EngineProvider, useWidgetResolver } from './context.js';\nimport { SelectionOverlaySlot } from './SelectionOverlaySlot.js';\nimport { WidgetProvider } from './WidgetProvider.js';\nimport { WidgetSlot } from './WidgetSlot.js';\nimport type { GridConfig } from './webgl/GridRenderer.js';\nimport { GridRenderer } from './webgl/GridRenderer.js';\nimport type { SelectionBounds, SelectionConfig } from './webgl/SelectionRenderer.js';\nimport { SelectionRenderer } from './webgl/SelectionRenderer.js';\nimport { WebGLWidgetLayer } from './webgl/WebGLWidgetLayer.js';\n\n/** Imperative handle exposed via `ref` on InfiniteCanvas for programmatic control. */\nexport interface InfiniteCanvasHandle {\n\t/** Moves the camera to the specified world coordinates. */\n\tpanTo(worldX: number, worldY: number): void;\n\t/** Sets the zoom level directly. */\n\tzoomTo(zoom: number): void;\n\t/** Adjusts camera to fit all entities in the viewport. */\n\tzoomToFit(padding?: number): void;\n\t/** Undoes the last command or command group. */\n\tundo(): void;\n\t/** Redoes the last undone command. */\n\tredo(): void;\n\t/** Returns the underlying LayoutEngine instance. */\n\tgetEngine(): LayoutEngine;\n}\n\n/** Props for the InfiniteCanvas component. */\ninterface InfiniteCanvasProps {\n\t/**\n\t * The LayoutEngine instance powering this canvas. Create with `createLayoutEngine()`.\n\t * Widgets and archetypes must be registered on the engine — via config or\n\t * `engine.registerWidget` / `engine.registerArchetype`.\n\t */\n\tengine: LayoutEngine;\n\t/** Grid configuration. Pass `false` to disable the grid entirely. */\n\tgrid?: Partial<GridConfig> | false;\n\t/** Selection highlight style configuration. */\n\tselection?: Partial<SelectionConfig>;\n\t/** Called when the set of selected entities changes. */\n\tonSelectionChange?: (entityIds: EntityId[]) => void;\n\t/** Called when the camera (pan/zoom) changes. */\n\tonCameraChange?: (camera: { x: number; y: number; zoom: number }) => void;\n\t/** Called when navigation depth changes (entering/exiting containers). */\n\tonNavigationChange?: (depth: number, containerId: EntityId | null) => void;\n\t/** CSS class name applied to the root container div. */\n\tclassName?: string;\n\t/** Inline styles applied to the root container div. */\n\tstyle?: React.CSSProperties;\n\t/** Overlay children (toolbars, panels) rendered on top of the canvas. */\n\tchildren?: React.ReactNode;\n}\n\nexport const InfiniteCanvas = React.forwardRef<InfiniteCanvasHandle, InfiniteCanvasProps>(\n\tfunction InfiniteCanvas(\n\t\t{\n\t\t\tengine,\n\t\t\tgrid,\n\t\t\tselection,\n\t\t\tonSelectionChange,\n\t\t\tonCameraChange,\n\t\t\tonNavigationChange,\n\t\t\tclassName,\n\t\t\tstyle,\n\t\t\tchildren,\n\t\t},\n\t\tref,\n\t) {\n\t\tconst containerRef = useRef<HTMLDivElement>(null);\n\n\t\t// Keep latest callback refs to avoid stale closures in the rAF loop\n\t\tconst onSelectionChangeRef = useRef(onSelectionChange);\n\t\tconst onCameraChangeRef = useRef(onCameraChange);\n\t\tconst onNavigationChangeRef = useRef(onNavigationChange);\n\t\tuseEffect(() => {\n\t\t\tonSelectionChangeRef.current = onSelectionChange;\n\t\t}, [onSelectionChange]);\n\t\tuseEffect(() => {\n\t\t\tonCameraChangeRef.current = onCameraChange;\n\t\t}, [onCameraChange]);\n\t\tuseEffect(() => {\n\t\t\tonNavigationChangeRef.current = onNavigationChange;\n\t\t}, [onNavigationChange]);\n\n\t\t// Imperative handle\n\t\tuseImperativeHandle(\n\t\t\tref,\n\t\t\t() => ({\n\t\t\t\tpanTo: (x, y) => {\n\t\t\t\t\tengine.panTo(x, y);\n\t\t\t\t\tengine.markDirty();\n\t\t\t\t},\n\t\t\t\tzoomTo: (zoom) => {\n\t\t\t\t\tengine.zoomTo(zoom);\n\t\t\t\t\tengine.markDirty();\n\t\t\t\t},\n\t\t\t\tzoomToFit: (padding) => {\n\t\t\t\t\tengine.zoomToFit(undefined, padding);\n\t\t\t\t\tengine.markDirty();\n\t\t\t\t},\n\t\t\t\tundo: () => {\n\t\t\t\t\tengine.undo();\n\t\t\t\t\tengine.markDirty();\n\t\t\t\t},\n\t\t\t\tredo: () => {\n\t\t\t\t\tengine.redo();\n\t\t\t\t\tengine.markDirty();\n\t\t\t\t},\n\t\t\t\tgetEngine: () => engine,\n\t\t\t}),\n\t\t\t[engine],\n\t\t);\n\n\t\tconst webglCanvasRef = useRef<HTMLCanvasElement>(null);\n\t\tconst gridRendererRef = useRef<GridRenderer | null>(null);\n\t\tconst selectionRendererRef = useRef<SelectionRenderer | null>(null);\n\t\tconst cameraLayerRef = useRef<HTMLDivElement>(null);\n\t\tconst slotRefs = useRef(new Map<EntityId, HTMLDivElement>());\n\t\tconst [visibleEntities, setVisibleEntities] = useState<EntityId[]>([]);\n\n\t\t// Register slot ref for batch updater\n\t\tconst registerSlotRef = useCallback((entityId: EntityId, el: HTMLDivElement | null) => {\n\t\t\tif (el) {\n\t\t\t\tslotRefs.current.set(entityId, el);\n\t\t\t} else {\n\t\t\t\tslotRefs.current.delete(entityId);\n\t\t\t}\n\t\t}, []);\n\n\t\t// Initialize GridRenderer + set viewport size on mount/resize\n\t\tuseLayoutEffect(() => {\n\t\t\tconst container = containerRef.current;\n\t\t\tconst canvas = webglCanvasRef.current;\n\t\t\tif (!container || !canvas) return;\n\n\t\t\tconst gridEnabled = grid !== false;\n\t\t\tlet gridInst: GridRenderer | null = null;\n\t\t\tif (gridEnabled) {\n\t\t\t\tgridInst = new GridRenderer(canvas);\n\t\t\t\tgridRendererRef.current = gridInst;\n\t\t\t}\n\n\t\t\t// SelectionRenderer shares the WebGLRenderer from GridRenderer\n\t\t\tconst selInst = new SelectionRenderer();\n\t\t\tselectionRendererRef.current = selInst;\n\n\t\t\tconst updateSize = () => {\n\t\t\t\tconst rect = container.getBoundingClientRect();\n\t\t\t\tconst dpr = window.devicePixelRatio;\n\t\t\t\tengine.setViewport(rect.width, rect.height, dpr);\n\t\t\t\tcanvas.style.width = `${rect.width}px`;\n\t\t\t\tcanvas.style.height = `${rect.height}px`;\n\t\t\t\tif (gridInst) {\n\t\t\t\t\tgridInst.setSize(rect.width, rect.height, dpr);\n\t\t\t\t}\n\t\t\t\tselInst.setSize(new Vector2(rect.width * dpr, rect.height * dpr), dpr);\n\t\t\t};\n\n\t\t\tupdateSize();\n\t\t\tconst observer = new ResizeObserver(updateSize);\n\t\t\tobserver.observe(container);\n\t\t\treturn () => {\n\t\t\t\tobserver.disconnect();\n\t\t\t\tif (gridInst) {\n\t\t\t\t\tgridInst.dispose();\n\t\t\t\t\tgridRendererRef.current = null;\n\t\t\t\t}\n\t\t\t\tselInst.dispose();\n\t\t\t\tselectionRendererRef.current = null;\n\t\t\t};\n\t\t}, [engine, grid]);\n\n\t\t// Apply grid + selection config on every render\n\t\tuseEffect(() => {\n\t\t\tconst gridR = gridRendererRef.current;\n\t\t\tif (gridR && grid !== false) {\n\t\t\t\tconst isDark = document.documentElement.classList.contains('dark');\n\t\t\t\tgridR.setConfig({\n\t\t\t\t\tdotColor: isDark ? [1, 1, 1] : [0, 0, 0],\n\t\t\t\t\tdotAlpha: isDark ? 0.12 : 0.18,\n\t\t\t\t\t...grid,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst selR = selectionRendererRef.current;\n\t\t\tif (selR && selection) {\n\t\t\t\tselR.setConfig(selection);\n\t\t\t}\n\t\t\tengine.markDirty();\n\t\t}, [engine, grid, selection]);\n\n\t\t// Wheel handler — pan/zoom (gesture channel, always active)\n\t\tuseEffect(() => {\n\t\t\tconst container = containerRef.current;\n\t\t\tif (!container) return;\n\n\t\t\tconst onWheel = (e: WheelEvent) => {\n\t\t\t\te.preventDefault();\n\t\t\t\tif (e.ctrlKey || e.metaKey) {\n\t\t\t\t\t// Pinch zoom or ctrl+scroll\n\t\t\t\t\tconst rect = container.getBoundingClientRect();\n\t\t\t\t\tengine.zoomAtPoint(e.clientX - rect.left, e.clientY - rect.top, -e.deltaY * 0.01);\n\t\t\t\t} else {\n\t\t\t\t\t// Two-finger scroll pan\n\t\t\t\t\tengine.panBy(-e.deltaX, -e.deltaY);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tcontainer.addEventListener('wheel', onWheel, { passive: false });\n\t\t\treturn () => container.removeEventListener('wheel', onWheel);\n\t\t}, [engine]);\n\n\t\t// Touch gesture handler — iOS Freeform-style interactions\n\t\t// 1 finger on background → pan; 1 finger on entity → select/drag;\n\t\t// 2 fingers → pinch-to-zoom + pan; double-tap → zoom step / enter container\n\t\tuseEffect(() => {\n\t\t\tconst container = containerRef.current;\n\t\t\tif (!container) return;\n\n\t\t\ttype TouchGesture =\n\t\t\t\t| { type: 'idle' }\n\t\t\t\t| { type: 'pending-pan'; x: number; y: number; time: number }\n\t\t\t\t| { type: 'panning'; lastX: number; lastY: number }\n\t\t\t\t| { type: 'pending-entity'; x: number; y: number; time: number }\n\t\t\t\t| { type: 'entity-dragging' }\n\t\t\t\t| { type: 'pinching'; lastDist: number; lastCx: number; lastCy: number };\n\n\t\t\tlet gesture: TouchGesture = { type: 'idle' };\n\t\t\tlet lastTapTime = 0;\n\t\t\tlet lastTapX = 0;\n\t\t\tlet lastTapY = 0;\n\t\t\tconst DOUBLE_TAP_MS = 300;\n\t\t\tconst DOUBLE_TAP_DIST = 30;\n\n\t\t\tfunction isOnWidget(target: EventTarget | null): boolean {\n\t\t\t\tlet el = target as HTMLElement | null;\n\t\t\t\twhile (el && el !== container) {\n\t\t\t\t\tif (el.hasAttribute('data-widget-slot')) return true;\n\t\t\t\t\tel = el.parentElement;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfunction isInteractive(target: EventTarget | null): boolean {\n\t\t\t\tconst el = target as HTMLElement | null;\n\t\t\t\tif (!el) return false;\n\t\t\t\tconst tag = el.tagName;\n\t\t\t\treturn (\n\t\t\t\t\ttag === 'INPUT' ||\n\t\t\t\t\ttag === 'TEXTAREA' ||\n\t\t\t\t\ttag === 'BUTTON' ||\n\t\t\t\t\ttag === 'SELECT' ||\n\t\t\t\t\tel.isContentEditable ||\n\t\t\t\t\tel.closest('button') !== null\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tfunction getRect() {\n\t\t\t\treturn container?.getBoundingClientRect() ?? new DOMRect();\n\t\t\t}\n\n\t\t\tfunction touchDist(t1: Touch, t2: Touch) {\n\t\t\t\tconst dx = t1.clientX - t2.clientX;\n\t\t\t\tconst dy = t1.clientY - t2.clientY;\n\t\t\t\treturn Math.sqrt(dx * dx + dy * dy);\n\t\t\t}\n\n\t\t\tfunction touchCenter(t1: Touch, t2: Touch, rect: DOMRect) {\n\t\t\t\treturn {\n\t\t\t\t\tx: (t1.clientX + t2.clientX) / 2 - rect.left,\n\t\t\t\t\ty: (t1.clientY + t2.clientY) / 2 - rect.top,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tfunction cancelEngineGesture() {\n\t\t\t\tif (gesture.type === 'pending-entity' || gesture.type === 'entity-dragging') {\n\t\t\t\t\tengine.handlePointerUp();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst noMods = { shift: false, ctrl: false, alt: false, meta: false };\n\n\t\t\tfunction onTouchStart(e: TouchEvent) {\n\t\t\t\tconst rect = getRect();\n\t\t\t\tconst touches = e.touches;\n\n\t\t\t\t// --- 2+ fingers → pinch (override everything) ---\n\t\t\t\tif (touches.length >= 2) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tcancelEngineGesture();\n\t\t\t\t\tconst dist = touchDist(touches[0], touches[1]);\n\t\t\t\t\tconst center = touchCenter(touches[0], touches[1], rect);\n\t\t\t\t\tgesture = { type: 'pinching', lastDist: dist, lastCx: center.x, lastCy: center.y };\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// --- 1 finger ---\n\t\t\t\tconst touch = touches[0];\n\t\t\t\tconst x = touch.clientX - rect.left;\n\t\t\t\tconst y = touch.clientY - rect.top;\n\n\t\t\t\t// Let interactive elements (buttons, inputs) handle their own touch\n\t\t\t\tif (isInteractive(e.target)) return;\n\n\t\t\t\te.preventDefault();\n\n\t\t\t\t// Double-tap detection\n\t\t\t\tconst now = Date.now();\n\t\t\t\tif (\n\t\t\t\t\tnow - lastTapTime < DOUBLE_TAP_MS &&\n\t\t\t\t\tMath.abs(x - lastTapX) < DOUBLE_TAP_DIST &&\n\t\t\t\t\tMath.abs(y - lastTapY) < DOUBLE_TAP_DIST\n\t\t\t\t) {\n\t\t\t\t\tlastTapTime = 0;\n\t\t\t\t\t// Hit test to check for entity\n\t\t\t\t\tconst directive = engine.handlePointerDown(x, y, 0, noMods);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (directive.action === 'passthrough-track-drag') {\n\t\t\t\t\t\t\t// Double-tap on entity → enter container\n\t\t\t\t\t\t\tconst selected = engine.getSelectedEntities();\n\t\t\t\t\t\t\tif (selected.length === 1) {\n\t\t\t\t\t\t\t\tengine.enterContainer(selected[0]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Double-tap on empty → zoom step\n\t\t\t\t\t\t\tconst camera = engine.getCamera();\n\t\t\t\t\t\t\tconst target = camera.zoom < 0.9 ? 1 : camera.zoom < 1.8 ? 2 : 1;\n\t\t\t\t\t\t\tengine.zoomAtPoint(x, y, (target - camera.zoom) / camera.zoom);\n\t\t\t\t\t\t}\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tengine.handlePointerUp();\n\t\t\t\t\t\tengine.markDirty();\n\t\t\t\t\t}\n\t\t\t\t\tgesture = { type: 'idle' };\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (isOnWidget(e.target)) {\n\t\t\t\t\t// Touch on entity → delegate to engine\n\t\t\t\t\tengine.handlePointerDown(x, y, 0, noMods);\n\t\t\t\t\tgesture = { type: 'pending-entity', x, y, time: now };\n\t\t\t\t} else {\n\t\t\t\t\t// Touch on empty space → prepare to pan (don't tell engine yet)\n\t\t\t\t\tgesture = { type: 'pending-pan', x, y, time: now };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction onTouchMove(e: TouchEvent) {\n\t\t\t\te.preventDefault();\n\t\t\t\tconst rect = getRect();\n\t\t\t\tconst touches = e.touches;\n\n\t\t\t\t// --- Pinch ---\n\t\t\t\tif (gesture.type === 'pinching' && touches.length >= 2) {\n\t\t\t\t\tconst dist = touchDist(touches[0], touches[1]);\n\t\t\t\t\tconst center = touchCenter(touches[0], touches[1], rect);\n\t\t\t\t\tconst scale = dist / gesture.lastDist;\n\t\t\t\t\tengine.zoomAtPoint(center.x, center.y, scale - 1);\n\t\t\t\t\tengine.panBy(center.x - gesture.lastCx, center.y - gesture.lastCy);\n\t\t\t\t\tgesture.lastDist = dist;\n\t\t\t\t\tgesture.lastCx = center.x;\n\t\t\t\t\tgesture.lastCy = center.y;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Transition to pinch if second finger added\n\t\t\t\tif (touches.length >= 2) {\n\t\t\t\t\tcancelEngineGesture();\n\t\t\t\t\tconst dist = touchDist(touches[0], touches[1]);\n\t\t\t\t\tconst center = touchCenter(touches[0], touches[1], rect);\n\t\t\t\t\tgesture = { type: 'pinching', lastDist: dist, lastCx: center.x, lastCy: center.y };\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (touches.length < 1) return;\n\t\t\t\tconst touch = touches[0];\n\t\t\t\tconst x = touch.clientX - rect.left;\n\t\t\t\tconst y = touch.clientY - rect.top;\n\n\t\t\t\t// Pending pan → check dead zone\n\t\t\t\tif (gesture.type === 'pending-pan') {\n\t\t\t\t\tif (\n\t\t\t\t\t\tMath.abs(x - gesture.x) > DEAD_ZONE_TOUCH_PX ||\n\t\t\t\t\t\tMath.abs(y - gesture.y) > DEAD_ZONE_TOUCH_PX\n\t\t\t\t\t) {\n\t\t\t\t\t\tgesture = { type: 'panning', lastX: x, lastY: y };\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Active panning\n\t\t\t\tif (gesture.type === 'panning') {\n\t\t\t\t\tengine.panBy(x - gesture.lastX, y - gesture.lastY);\n\t\t\t\t\tgesture.lastX = x;\n\t\t\t\t\tgesture.lastY = y;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Entity drag → delegate to engine\n\t\t\t\tif (gesture.type === 'pending-entity' || gesture.type === 'entity-dragging') {\n\t\t\t\t\tengine.handlePointerMove(x, y, noMods);\n\t\t\t\t\tif (gesture.type === 'pending-entity') {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tMath.abs(x - gesture.x) > DEAD_ZONE_TOUCH_PX ||\n\t\t\t\t\t\t\tMath.abs(y - gesture.y) > DEAD_ZONE_TOUCH_PX\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tgesture = { type: 'entity-dragging' };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction onTouchEnd(e: TouchEvent) {\n\t\t\t\te.preventDefault();\n\t\t\t\tconst remaining = e.touches.length;\n\t\t\t\tconst rect = getRect();\n\n\t\t\t\t// Pinch → transition based on remaining fingers\n\t\t\t\tif (gesture.type === 'pinching') {\n\t\t\t\t\tif (remaining === 1) {\n\t\t\t\t\t\tconst t = e.touches[0];\n\t\t\t\t\t\tgesture = {\n\t\t\t\t\t\t\ttype: 'panning',\n\t\t\t\t\t\t\tlastX: t.clientX - rect.left,\n\t\t\t\t\t\t\tlastY: t.clientY - rect.top,\n\t\t\t\t\t\t};\n\t\t\t\t\t} else if (remaining === 0) {\n\t\t\t\t\t\tgesture = { type: 'idle' };\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (remaining > 0) return;\n\n\t\t\t\t// Tap on empty space → deselect\n\t\t\t\tif (gesture.type === 'pending-pan') {\n\t\t\t\t\tengine.handlePointerDown(gesture.x, gesture.y, 0, noMods);\n\t\t\t\t\tengine.handlePointerUp();\n\t\t\t\t\tengine.markDirty();\n\t\t\t\t\tlastTapTime = Date.now();\n\t\t\t\t\tlastTapX = gesture.x;\n\t\t\t\t\tlastTapY = gesture.y;\n\t\t\t\t}\n\n\t\t\t\t// Tap on entity (no drag) → selection already happened\n\t\t\t\tif (gesture.type === 'pending-entity') {\n\t\t\t\t\tengine.handlePointerUp();\n\t\t\t\t\tengine.markDirty();\n\t\t\t\t\tlastTapTime = Date.now();\n\t\t\t\t\tlastTapX = gesture.x;\n\t\t\t\t\tlastTapY = gesture.y;\n\t\t\t\t}\n\n\t\t\t\t// Entity drag end\n\t\t\t\tif (gesture.type === 'entity-dragging') {\n\t\t\t\t\tengine.handlePointerUp();\n\t\t\t\t\tengine.markDirty();\n\t\t\t\t}\n\n\t\t\t\tgesture = { type: 'idle' };\n\t\t\t}\n\n\t\t\tfunction onTouchCancel(_e: TouchEvent) {\n\t\t\t\t// Reset gesture state unconditionally — the browser cancelled the touch.\n\t\t\t\t// Unlike onTouchEnd we don't inspect e.touches (which may be empty).\n\t\t\t\tgesture = { type: 'idle' };\n\t\t\t\tengine.handlePointerCancel();\n\t\t\t}\n\n\t\t\tcontainer.addEventListener('touchstart', onTouchStart, { passive: false });\n\t\t\tcontainer.addEventListener('touchmove', onTouchMove, { passive: false });\n\t\t\tcontainer.addEventListener('touchend', onTouchEnd, { passive: false });\n\t\t\tcontainer.addEventListener('touchcancel', onTouchCancel, { passive: true });\n\n\t\t\treturn () => {\n\t\t\t\tcontainer.removeEventListener('touchstart', onTouchStart);\n\t\t\t\tcontainer.removeEventListener('touchmove', onTouchMove);\n\t\t\t\tcontainer.removeEventListener('touchend', onTouchEnd);\n\t\t\t\tcontainer.removeEventListener('touchcancel', onTouchCancel);\n\t\t\t};\n\t\t}, [engine]);\n\n\t\t// Canvas-level pointer handlers — attached to the root container div so\n\t\t// pointer events in the \"outside handle strip\" (handle hit zone that\n\t\t// extends beyond a widget slot's DOM bounds) reach the engine. Widget\n\t\t// slots still have their own handlers and stopPropagation, so events\n\t\t// inside widgets never reach these fallbacks.\n\t\tconst onCanvasPointerDown = useCallback(\n\t\t\t(e: React.PointerEvent) => {\n\t\t\t\tconst target = e.target as HTMLElement | null;\n\t\t\t\t// Respect interactive form elements inside widget children.\n\t\t\t\tif (target?.closest('button, input, textarea, select, [contenteditable]')) return;\n\t\t\t\tconst rect = containerRef.current?.getBoundingClientRect();\n\t\t\t\tif (!rect) return;\n\t\t\t\tconst directive = engine.handlePointerDown(\n\t\t\t\t\te.clientX - rect.left,\n\t\t\t\t\te.clientY - rect.top,\n\t\t\t\t\te.button,\n\t\t\t\t\t{\n\t\t\t\t\t\tshift: e.shiftKey,\n\t\t\t\t\t\tctrl: e.ctrlKey,\n\t\t\t\t\t\talt: e.altKey,\n\t\t\t\t\t\tmeta: e.metaKey,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\t// Capture on the container so subsequent moves route here even when\n\t\t\t\t// the pointer leaves the viewport. Widget slot already captures for\n\t\t\t\t// events that reach it first; this is for empty-space / outside-strip\n\t\t\t\t// events that bypass widget slots.\n\t\t\t\tif (\n\t\t\t\t\tdirective.action === 'capture-resize' ||\n\t\t\t\t\tdirective.action === 'passthrough-track-drag'\n\t\t\t\t) {\n\t\t\t\t\tcontainerRef.current?.setPointerCapture(e.pointerId);\n\t\t\t\t}\n\t\t\t\tif (directive.action === 'capture-resize') e.preventDefault();\n\t\t\t},\n\t\t\t[engine],\n\t\t);\n\n\t\tconst onCanvasPointerMove = useCallback(\n\t\t\t(e: React.PointerEvent) => {\n\t\t\t\t// Skip if a widget slot is handling this pointer — avoids double\n\t\t\t\t// handlePointerMove when the event bubbles from a captured widget.\n\t\t\t\tconst target = e.target as HTMLElement;\n\t\t\t\tif (target.closest?.('[data-widget-slot]') && target !== containerRef.current) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst rect = containerRef.current?.getBoundingClientRect();\n\t\t\t\tif (!rect) return;\n\t\t\t\tengine.handlePointerMove(e.clientX - rect.left, e.clientY - rect.top, {\n\t\t\t\t\tshift: e.shiftKey,\n\t\t\t\t\tctrl: e.ctrlKey,\n\t\t\t\t\talt: e.altKey,\n\t\t\t\t\tmeta: e.metaKey,\n\t\t\t\t});\n\t\t\t},\n\t\t\t[engine],\n\t\t);\n\n\t\tconst onCanvasPointerUp = useCallback(\n\t\t\t(e: React.PointerEvent) => {\n\t\t\t\tif (containerRef.current?.hasPointerCapture(e.pointerId)) {\n\t\t\t\t\tcontainerRef.current.releasePointerCapture(e.pointerId);\n\t\t\t\t}\n\t\t\t\tengine.handlePointerUp();\n\t\t\t},\n\t\t\t[engine],\n\t\t);\n\n\t\t// rAF tick loop — flushes the engine when dirty, then applies updates.\n\t\t// This is THE render loop. Input handlers set engine dirty; this loop ticks.\n\t\tuseEffect(() => {\n\t\t\tlet rafId: number;\n\t\t\tlet running = true;\n\n\t\t\tfunction loop() {\n\t\t\t\tif (!running) return;\n\n\t\t\t\tconst didTick = engine.flushIfDirty();\n\t\t\t\tif (didTick) {\n\t\t\t\t\tconst camera = engine.getCamera();\n\t\t\t\t\tconst changes = engine.getFrameChanges();\n\n\t\t\t\t\t// 1. Update camera layer CSS transform (O(1) for pan/zoom)\n\t\t\t\t\tif (cameraLayerRef.current) {\n\t\t\t\t\t\tcameraLayerRef.current.style.transform = `scale(${camera.zoom}) translate(${-camera.x}px, ${-camera.y}px)`;\n\t\t\t\t\t}\n\n\t\t\t\t\t// RFC-001 Phase 7: apply derived cursor to root container.\n\t\t\t\t\t// Equality guard avoids redundant DOM writes in devtools diffs.\n\t\t\t\t\tconst cursor = engine.world.getResource(CursorResource).cursor;\n\t\t\t\t\tif (containerRef.current && containerRef.current.style.cursor !== cursor) {\n\t\t\t\t\t\tcontainerRef.current.style.cursor = cursor;\n\t\t\t\t\t}\n\n\t\t\t\t\t// 1b. Render WebGL dot grid + selection\n\t\t\t\t\tif (gridRendererRef.current) {\n\t\t\t\t\t\tgridRendererRef.current.render(camera.x, camera.y, camera.zoom);\n\t\t\t\t\t}\n\t\t\t\t\tif (selectionRendererRef.current && gridRendererRef.current) {\n\t\t\t\t\t\tconst selected = engine.getSelectedEntities();\n\t\t\t\t\t\tconst selBounds: SelectionBounds[] = [];\n\t\t\t\t\t\tfor (const id of selected) {\n\t\t\t\t\t\t\tconst wb = engine.get(id, WorldBounds);\n\t\t\t\t\t\t\tif (wb)\n\t\t\t\t\t\t\t\tselBounds.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}\n\t\t\t\t\t\tconst hovId = engine.getHoveredEntity();\n\t\t\t\t\t\tlet hovBounds: SelectionBounds | null = null;\n\t\t\t\t\t\tif (hovId !== null) {\n\t\t\t\t\t\t\tconst wb = engine.get(hovId, WorldBounds);\n\t\t\t\t\t\t\tif (wb)\n\t\t\t\t\t\t\t\thovBounds = {\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}\n\t\t\t\t\t\tselectionRendererRef.current.render(\n\t\t\t\t\t\t\tgridRendererRef.current.getWebGLRenderer(),\n\t\t\t\t\t\t\tcamera.x,\n\t\t\t\t\t\t\tcamera.y,\n\t\t\t\t\t\t\tcamera.zoom,\n\t\t\t\t\t\t\tselBounds,\n\t\t\t\t\t\t\thovBounds,\n\t\t\t\t\t\t\tengine.getSnapGuides(),\n\t\t\t\t\t\t\tengine.getEqualSpacing(),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\t// 2. Fix #1: Use WorldBounds (world-space) not Transform2D (local/parent-relative)\n\t\t\t\t\tfor (const entityId of changes.positionsChanged) {\n\t\t\t\t\t\tconst el = slotRefs.current.get(entityId);\n\t\t\t\t\t\tif (!el) continue;\n\t\t\t\t\t\tconst wb = engine.get(entityId, WorldBounds);\n\t\t\t\t\t\tif (!wb) continue;\n\t\t\t\t\t\tel.style.transform = `translate(${wb.worldX}px, ${wb.worldY}px)`;\n\t\t\t\t\t\tel.style.width = `${wb.worldWidth}px`;\n\t\t\t\t\t\tel.style.height = `${wb.worldHeight}px`;\n\t\t\t\t\t}\n\n\t\t\t\t\t// 3. Update visible entity list if entities entered/exited\n\t\t\t\t\tif (changes.entered.length > 0 || changes.exited.length > 0) {\n\t\t\t\t\t\tconst visible = engine.getVisibleEntities();\n\t\t\t\t\t\tsetVisibleEntities(visible.map((v) => v.entityId));\n\t\t\t\t\t}\n\n\t\t\t\t\t// 4. Fire event callbacks\n\t\t\t\t\tif (changes.selectionChanged && onSelectionChangeRef.current) {\n\t\t\t\t\t\tonSelectionChangeRef.current(engine.getSelectedEntities());\n\t\t\t\t\t}\n\t\t\t\t\tif (changes.cameraChanged && onCameraChangeRef.current) {\n\t\t\t\t\t\tonCameraChangeRef.current({ x: camera.x, y: camera.y, zoom: camera.zoom });\n\t\t\t\t\t}\n\t\t\t\t\tif (changes.navigationChanged && onNavigationChangeRef.current) {\n\t\t\t\t\t\tconst navStack = engine.world.getResource(NavigationStackResource);\n\t\t\t\t\t\tconst depth = navStack.frames.length - 1;\n\t\t\t\t\t\tconst containerId = navStack.frames[navStack.frames.length - 1].containerId;\n\t\t\t\t\t\tonNavigationChangeRef.current(depth, containerId);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\trafId = requestAnimationFrame(loop);\n\t\t\t}\n\n\t\t\t// Initial tick on mount\n\t\t\tengine.tick();\n\t\t\tconst visible = engine.getVisibleEntities();\n\t\t\tsetVisibleEntities(visible.map((v) => v.entityId));\n\n\t\t\t// Set initial camera transform + grid\n\t\t\tconst camera = engine.getCamera();\n\t\t\tif (cameraLayerRef.current) {\n\t\t\t\tcameraLayerRef.current.style.transform = `scale(${camera.zoom}) translate(${-camera.x}px, ${-camera.y}px)`;\n\t\t\t}\n\t\t\t// Initial WebGL grid render\n\t\t\tif (gridRendererRef.current) {\n\t\t\t\tgridRendererRef.current.render(camera.x, camera.y, camera.zoom);\n\t\t\t}\n\n\t\t\t// Set initial slot positions\n\t\t\tfor (const v of visible) {\n\t\t\t\tconst el = slotRefs.current.get(v.entityId);\n\t\t\t\tif (!el) continue;\n\t\t\t\tel.style.transform = `translate(${v.worldX}px, ${v.worldY}px)`;\n\t\t\t\tel.style.width = `${v.worldWidth}px`;\n\t\t\t\tel.style.height = `${v.worldHeight}px`;\n\t\t\t}\n\n\t\t\t// Start the loop\n\t\t\trafId = requestAnimationFrame(loop);\n\n\t\t\treturn () => {\n\t\t\t\trunning = false;\n\t\t\t\tcancelAnimationFrame(rafId);\n\t\t\t};\n\t\t}, [engine]);\n\n\t\t// Fix #4: useLayoutEffect to set initial positions BEFORE browser paint\n\t\t// Prevents one-frame flash at (0,0) when new widgets enter the viewport\n\t\tuseLayoutEffect(() => {\n\t\t\tfor (const entityId of visibleEntities) {\n\t\t\t\tconst el = slotRefs.current.get(entityId);\n\t\t\t\tif (!el) continue;\n\t\t\t\tconst wb = engine.get(entityId, WorldBounds);\n\t\t\t\tif (!wb) continue;\n\t\t\t\tel.style.transform = `translate(${wb.worldX}px, ${wb.worldY}px)`;\n\t\t\t\tel.style.width = `${wb.worldWidth}px`;\n\t\t\t\tel.style.height = `${wb.worldHeight}px`;\n\t\t\t}\n\t\t}, [visibleEntities, engine]);\n\n\t\t// Split visible entities by surface\n\t\tconst { domEntities, webglEntities } = useMemo(() => {\n\t\t\tconst dom: EntityId[] = [];\n\t\t\tconst webgl: EntityId[] = [];\n\t\t\tfor (const id of visibleEntities) {\n\t\t\t\tconst w = engine.get(id, Widget);\n\t\t\t\tif (w?.surface === 'webgl') {\n\t\t\t\t\twebgl.push(id);\n\t\t\t\t} else {\n\t\t\t\t\tdom.push(id);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { domEntities: dom, webglEntities: webgl };\n\t\t}, [visibleEntities, engine]);\n\n\t\tconst canvasContent = (\n\t\t\t<div\n\t\t\t\tref={containerRef}\n\t\t\t\tclassName={`relative overflow-hidden ${className ?? ''}`}\n\t\t\t\tstyle={{\n\t\t\t\t\t...style,\n\t\t\t\t\ttouchAction: 'none',\n\t\t\t\t\tbackgroundColor: 'var(--canvas-bg, #fafafa)',\n\t\t\t\t}}\n\t\t\t\tonPointerDown={onCanvasPointerDown}\n\t\t\t\tonPointerMove={onCanvasPointerMove}\n\t\t\t\tonPointerUp={onCanvasPointerUp}\n\t\t\t>\n\t\t\t\t{/* WebGL layer — dot grid, selection overlays, connections */}\n\t\t\t\t<canvas ref={webglCanvasRef} className=\"absolute inset-0 pointer-events-none\" />\n\n\t\t\t\t{/* R3F layer — WebGL widgets (lazy, only when webgl entities exist) */}\n\t\t\t\t{webglEntities.length > 0 && <WebGLWidgetBridge engine={engine} entities={webglEntities} />}\n\n\t\t\t\t{/* Background — purely visual; pointer handlers live on the container.\n\t\t\t Kept as a div so the paint order (canvas, background, camera layer)\n\t\t\t is stable and future background visuals have a dedicated layer. */}\n\t\t\t\t<div className=\"absolute inset-0 pointer-events-none\" />\n\n\t\t\t\t{/* Camera transform layer — DOM widgets + selection overlays for WebGL widgets */}\n\t\t\t\t<div\n\t\t\t\t\tref={cameraLayerRef}\n\t\t\t\t\tclassName=\"absolute left-0 top-0 origin-top-left will-change-transform\"\n\t\t\t\t>\n\t\t\t\t\t{domEntities.map((entityId) => (\n\t\t\t\t\t\t<WidgetSlot key={entityId} entityId={entityId} slotRef={registerSlotRef} />\n\t\t\t\t\t))}\n\t\t\t\t\t{webglEntities.map((entityId) => (\n\t\t\t\t\t\t<SelectionOverlaySlot key={entityId} entityId={entityId} slotRef={registerSlotRef} />\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\n\t\t\t\t{/* Children: toolbars, panels, etc. */}\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t);\n\n\t\treturn (\n\t\t\t<EngineProvider value={engine}>\n\t\t\t\t<ContainerRefProvider value={containerRef}>\n\t\t\t\t\t<WidgetProvider engine={engine}>{canvasContent}</WidgetProvider>\n\t\t\t\t</ContainerRefProvider>\n\t\t\t</EngineProvider>\n\t\t);\n\t},\n);\n\n/** Bridge component — reads widget resolver from context and passes to WebGLWidgetLayer */\nfunction WebGLWidgetBridge({ engine, entities }: { engine: LayoutEngine; entities: EntityId[] }) {\n\tconst resolver = useWidgetResolver();\n\tconst resolve = useCallback(\n\t\t(entityId: EntityId) => {\n\t\t\tif (!resolver) return null;\n\t\t\tconst w = engine.get(entityId, Widget);\n\t\t\treturn resolver(entityId, w?.type ?? '');\n\t\t},\n\t\t[resolver, engine],\n\t);\n\n\tif (!resolver) return null;\n\n\treturn <WebGLWidgetLayer engine={engine} entities={entities} resolve={resolve} />;\n}\n","import type { EntityId } from '@jamesyong42/reactive-ecs';\nimport { useCallback } from 'react';\nimport { Children, Selected, WidgetBreakpoint, WidgetData } from '../components.js';\nimport type { Breakpoint } from '../resources.js';\nimport { useLayoutEngine } from './context.js';\nimport { useComponent, useTag } from './hooks.js';\n\n/**\n * Returns the custom data attached to a widget entity.\n * Use the generic parameter for type safety: `useWidgetData<MyData>(entityId)`. Re-renders when data changes.\n */\nexport function useWidgetData<T = Record<string, unknown>>(entityId: EntityId): T {\n\tconst comp = useComponent(entityId, WidgetData);\n\treturn (comp?.data ?? {}) as T;\n}\n\n/**\n * Returns the current responsive breakpoint for a widget based on its screen-space size.\n * Re-renders when the breakpoint changes.\n */\nexport function useBreakpoint(entityId: EntityId): Breakpoint {\n\tconst comp = useComponent(entityId, WidgetBreakpoint);\n\treturn comp?.current ?? 'normal';\n}\n\n/**\n * Returns child entity IDs of a container entity.\n * Re-renders when children are added or removed.\n */\nexport function useChildren(entityId: EntityId): EntityId[] {\n\tconst comp = useComponent(entityId, Children);\n\treturn comp?.ids ?? [];\n}\n\n/**\n * Returns whether the entity is currently selected.\n * Re-renders when the entity's selection state changes.\n */\nexport function useIsSelected(entityId: EntityId): boolean {\n\treturn useTag(entityId, Selected);\n}\n\n/**\n * Returns a function to update the widget's custom data.\n * Merges the patch into existing data via shallow spread.\n */\nexport function useUpdateWidget(entityId: EntityId): (patch: Record<string, unknown>) => void {\n\tconst engine = useLayoutEngine();\n\treturn useCallback(\n\t\t(patch: Record<string, unknown>) => {\n\t\t\tconst existing = engine.get(entityId, WidgetData);\n\t\t\tif (existing) {\n\t\t\t\tengine.set(entityId, WidgetData, {\n\t\t\t\t\tdata: { ...existing.data, ...patch },\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t[engine, entityId],\n\t);\n}\n"]}