{"version":3,"sources":["../src/interactive/types.ts","../src/interactive/keyboard.ts","../src/interactive/mouse.ts","../src/interactive/loop.ts"],"names":["Keys","MouseButton","useKeyboard","target","pressedKeys","setPressedKeys","use","justPressedKeys","setJustPressedKeys","justReleasedKeys","setJustReleasedKeys","handleKeyDown","e","key","currentPressed","newPressed","currentJustPressed","newJustPressed","handleKeyUp","currentJustReleased","newJustReleased","useMouse","options","canvasGetter","position","setPosition","delta","setDelta","wheelDelta","setWheelDelta","buttons","setButtons","lastX","lastY","handleMouseMove","me","canvas","x","y","rect","handleMouseDown","button","currentButtons","newButtons","handleMouseUp","handleWheel","currentPosition","currentDelta","currentWheelDelta","useLoop","callbacks","fixedFps","onUpdate","onFixedUpdate","onRender","fixedDelta","maxDelta","running","lastTime","accumulator","fps","frameCount","fpsTime","rafId","loop","currentTime","alpha"],"mappings":"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","file":"interactive.mjs","sourcesContent":["// Keyboard types\nexport enum Keys {\n    ArrowUp = 'ArrowUp',\n    ArrowDown = 'ArrowDown',\n    ArrowLeft = 'ArrowLeft',\n    ArrowRight = 'ArrowRight',\n    KeyW = 'KeyW',\n    KeyA = 'KeyA',\n    KeyS = 'KeyS',\n    KeyD = 'KeyD',\n    Space = 'Space',\n    Enter = 'Enter',\n    Escape = 'Escape',\n    Tab = 'Tab',\n    ShiftLeft = 'ShiftLeft',\n    ShiftRight = 'ShiftRight',\n    ControlLeft = 'ControlLeft',\n    ControlRight = 'ControlRight',\n    AltLeft = 'AltLeft',\n    AltRight = 'AltRight',\n    Digit0 = 'Digit0',\n    Digit1 = 'Digit1',\n    Digit2 = 'Digit2',\n    Digit3 = 'Digit3',\n    Digit4 = 'Digit4',\n    Digit5 = 'Digit5',\n    Digit6 = 'Digit6',\n    Digit7 = 'Digit7',\n    Digit8 = 'Digit8',\n    Digit9 = 'Digit9',\n    KeyE = 'KeyE',\n    KeyQ = 'KeyQ',\n    KeyR = 'KeyR',\n    KeyF = 'KeyF',\n}\n\nexport interface KeyboardState {\n    isPressed: (key: string) => boolean\n    isJustPressed: (key: string) => boolean\n    isJustReleased: (key: string) => boolean\n    getPressedKeys: () => string[]\n    clearFrameState: () => void\n    dispose: () => void\n}\n\n// Mouse types\nexport enum MouseButton {\n    Left = 0,\n    Middle = 1,\n    Right = 2\n}\n\nexport interface MouseOptions {\n    canvas?: HTMLCanvasElement | (() => HTMLCanvasElement | undefined)\n    target?: EventTarget\n}\n\nexport interface MouseState {\n    x: number | null\n    y: number | null\n    deltaX: number\n    deltaY: number\n    wheelDelta: number\n    isPressed: (button: MouseButton) => boolean\n    isLeftPressed: () => boolean\n    isRightPressed: () => boolean\n    isMiddlePressed: () => boolean\n    clearFrameState: () => void\n    dispose: () => void\n}\n\n// Loop types\nexport interface LoopCallbacks {\n    fixedFps?: number\n    onUpdate?: (delta: number) => void\n    onFixedUpdate?: (fixedDelta: number) => void\n    onRender?: (alpha: number) => void\n}\n\nexport interface Loop {\n    start: () => void\n    stop: () => void\n    isRunning: () => boolean\n    getFps: () => number\n}\n","import { use } from 'flexium/core'\nimport { Keys, type KeyboardState } from './types'\n\nexport { Keys, type KeyboardState }\n\nexport function useKeyboard(target: EventTarget = window): KeyboardState {\n  const [pressedKeys, setPressedKeys] = use<Set<string>>(new Set<string>(), { key: ['keyboard', 'pressed'] })\n  const [justPressedKeys, setJustPressedKeys] = use<Set<string>>(new Set<string>(), { key: ['keyboard', 'justPressed'] })\n  const [justReleasedKeys, setJustReleasedKeys] = use<Set<string>>(new Set<string>(), { key: ['keyboard', 'justReleased'] })\n\n  const handleKeyDown = (e: Event) => {\n    const key = (e as KeyboardEvent).code\n    const currentPressed = pressedKeys as Set<string>\n\n    if (!currentPressed.has(key)) {\n      const newPressed = new Set(currentPressed)\n      newPressed.add(key)\n      setPressedKeys(newPressed)\n\n      const currentJustPressed = justPressedKeys as Set<string>\n      const newJustPressed = new Set(currentJustPressed)\n      newJustPressed.add(key)\n      setJustPressedKeys(newJustPressed)\n    }\n  }\n\n  const handleKeyUp = (e: Event) => {\n    const key = (e as KeyboardEvent).code\n    const currentPressed = pressedKeys as Set<string>\n\n    const newPressed = new Set(currentPressed)\n    newPressed.delete(key)\n    setPressedKeys(newPressed)\n\n    const currentJustReleased = justReleasedKeys as Set<string>\n    const newJustReleased = new Set(currentJustReleased)\n    newJustReleased.add(key)\n    setJustReleasedKeys(newJustReleased)\n  }\n\n  target.addEventListener('keydown', handleKeyDown)\n  target.addEventListener('keyup', handleKeyUp)\n\n  return {\n    isPressed: (key: string) => {\n      const current = pressedKeys as Set<string>\n      return current?.has(key) || false\n    },\n\n    isJustPressed: (key: string) => {\n      const current = justPressedKeys as Set<string>\n      return current?.has(key) || false\n    },\n\n    isJustReleased: (key: string) => {\n      const current = justReleasedKeys as Set<string>\n      return current?.has(key) || false\n    },\n\n    getPressedKeys: () => {\n      const current = pressedKeys as Set<string>\n      return Array.from(current || [])\n    },\n\n    clearFrameState: () => {\n      setJustPressedKeys(new Set<string>())\n      setJustReleasedKeys(new Set<string>())\n    },\n\n    dispose: () => {\n      target.removeEventListener('keydown', handleKeyDown)\n      target.removeEventListener('keyup', handleKeyUp)\n    }\n  }\n}\n","import { use } from 'flexium/core'\nimport { MouseButton, type MouseOptions, type MouseState } from './types'\n\nexport { MouseButton, type MouseOptions, type MouseState }\n\nexport function useMouse(options: MouseOptions = {}): MouseState {\n  const target = options.target || window\n  const canvasGetter = typeof options.canvas === 'function' ? options.canvas : () => options.canvas as HTMLCanvasElement | undefined\n\n  const [position, setPosition] = use({ x: 0, y: 0 }, { key: ['mouse', 'position'] })\n  const [delta, setDelta] = use({ x: 0, y: 0 }, { key: ['mouse', 'delta'] })\n  const [wheelDelta, setWheelDelta] = use(0, { key: ['mouse', 'wheel'] })\n  const [buttons, setButtons] = use<Set<number>>(new Set<number>(), { key: ['mouse', 'buttons'] })\n\n  let lastX = 0\n  let lastY = 0\n\n  const handleMouseMove = (e: Event) => {\n    const me = e as MouseEvent\n    const canvas = canvasGetter()\n\n    let x = me.clientX\n    let y = me.clientY\n\n    // If canvas is provided, calculate position relative to canvas\n    if (canvas) {\n      const rect = canvas.getBoundingClientRect()\n      x = me.clientX - rect.left\n      y = me.clientY - rect.top\n    }\n\n    setPosition({ x, y })\n    setDelta({ x: x - lastX, y: y - lastY })\n    lastX = x\n    lastY = y\n  }\n\n  const handleMouseDown = (e: Event) => {\n    const button = (e as MouseEvent).button\n    const currentButtons = buttons as Set<number>\n    const newButtons = new Set(currentButtons)\n    newButtons.add(button)\n    setButtons(newButtons)\n  }\n\n  const handleMouseUp = (e: Event) => {\n    const button = (e as MouseEvent).button\n    const currentButtons = buttons as Set<number>\n    const newButtons = new Set(currentButtons)\n    newButtons.delete(button)\n    setButtons(newButtons)\n  }\n\n  const handleWheel = (e: Event) => {\n    const we = e as WheelEvent\n    setWheelDelta(we.deltaY)\n  }\n\n  target.addEventListener('mousemove', handleMouseMove)\n  target.addEventListener('mousedown', handleMouseDown)\n  target.addEventListener('mouseup', handleMouseUp)\n  target.addEventListener('wheel', handleWheel)\n\n  const currentButtons = buttons as Set<number>\n  const currentPosition = position as { x: number; y: number }\n  const currentDelta = delta as { x: number; y: number }\n  const currentWheelDelta = wheelDelta as number\n\n  return {\n    get x() { return currentPosition.x },\n    get y() { return currentPosition.y },\n    get deltaX() { return currentDelta.x },\n    get deltaY() { return currentDelta.y },\n    get wheelDelta() { return currentWheelDelta },\n\n    isPressed: (button: MouseButton) => currentButtons?.has(button) || false,\n\n    isLeftPressed: () => currentButtons?.has(MouseButton.Left) || false,\n\n    isRightPressed: () => currentButtons?.has(MouseButton.Right) || false,\n\n    isMiddlePressed: () => currentButtons?.has(MouseButton.Middle) || false,\n\n    clearFrameState: () => {\n      setDelta({ x: 0, y: 0 })\n      setWheelDelta(0)\n    },\n\n    dispose: () => {\n      target.removeEventListener('mousemove', handleMouseMove)\n      target.removeEventListener('mousedown', handleMouseDown)\n      target.removeEventListener('mouseup', handleMouseUp)\n      target.removeEventListener('wheel', handleWheel)\n    }\n  }\n}\n","import type { LoopCallbacks, Loop } from './types'\n\nexport type { LoopCallbacks, Loop }\n\nexport function useLoop(callbacks: LoopCallbacks): Loop {\n  const { fixedFps = 60, onUpdate, onFixedUpdate, onRender } = callbacks\n\n  const fixedDelta = 1 / fixedFps\n  const maxDelta = 0.25 // Cap delta at 250ms to prevent spiral of death\n\n  let running = false\n  let lastTime = 0\n  let accumulator = 0\n  let fps = 0\n  let frameCount = 0\n  let fpsTime = 0\n  let rafId: number | null = null\n\n  function loop(currentTime: number) {\n    if (!running) return\n\n    // Calculate delta in seconds\n    const delta = Math.min((currentTime - lastTime) / 1000, maxDelta)\n    lastTime = currentTime\n\n    // Variable timestep update\n    if (onUpdate) {\n      onUpdate(delta)\n    }\n\n    // Fixed timestep update\n    if (onFixedUpdate) {\n      accumulator += delta\n\n      while (accumulator >= fixedDelta) {\n        onFixedUpdate(fixedDelta)\n        accumulator -= fixedDelta\n      }\n    }\n\n    // Render with interpolation alpha\n    if (onRender) {\n      const alpha = accumulator / fixedDelta\n      onRender(alpha)\n    }\n\n    // FPS calculation\n    frameCount++\n    if (currentTime - fpsTime >= 1000) {\n      fps = frameCount\n      frameCount = 0\n      fpsTime = currentTime\n    }\n\n    rafId = requestAnimationFrame(loop)\n  }\n\n  return {\n    start: () => {\n      if (running) return\n      running = true\n      lastTime = performance.now()\n      accumulator = 0\n      rafId = requestAnimationFrame(loop)\n    },\n\n    stop: () => {\n      running = false\n      if (rafId !== null) {\n        cancelAnimationFrame(rafId)\n        rafId = null\n      }\n    },\n\n    isRunning: () => running,\n\n    getFps: () => fps\n  }\n}\n"]}