koin.js 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,18 +1,18 @@
1
1
  'use strict';
2
2
 
3
- var React3 = require('react');
3
+ var React5 = require('react');
4
4
  var lucideReact = require('lucide-react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var nostalgist = require('nostalgist');
7
7
 
8
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
9
 
10
- var React3__default = /*#__PURE__*/_interopDefault(React3);
10
+ var React5__default = /*#__PURE__*/_interopDefault(React5);
11
11
 
12
12
  var __defProp = Object.defineProperty;
13
13
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
14
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
15
- var ControlButton = React3.memo(function ControlButton2({
15
+ var ControlButton = React5.memo(function ControlButton2({
16
16
  onClick,
17
17
  onMouseDown,
18
18
  onMouseUp,
@@ -59,7 +59,7 @@ var ControlButton = React3.memo(function ControlButton2({
59
59
  });
60
60
  var SPEED_OPTIONS = [1, 2];
61
61
  function SpeedMenu({ speed, onSpeedChange, disabled = false }) {
62
- const [showMenu, setShowMenu] = React3.useState(false);
62
+ const [showMenu, setShowMenu] = React5.useState(false);
63
63
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
64
64
  /* @__PURE__ */ jsxRuntime.jsxs(
65
65
  "button",
@@ -177,7 +177,7 @@ function HardcoreTooltip({ show, message = "Disabled in Hardcore mode", children
177
177
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 px-2 py-1 bg-amber-500/90 text-black text-xs rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none z-50", children: message })
178
178
  ] });
179
179
  }
180
- var PlaybackControls = React3.memo(function PlaybackControls2({
180
+ var PlaybackControls = React5.memo(function PlaybackControls2({
181
181
  isPaused,
182
182
  isRunning,
183
183
  speed,
@@ -260,10 +260,10 @@ function AutoSaveIndicator({
260
260
  isPaused = false,
261
261
  onClick
262
262
  }) {
263
- const prevStateRef = React3.useRef(state);
264
- const [displayProgress, setDisplayProgress] = React3.useState(progress);
265
- const [iconOpacity, setIconOpacity] = React3.useState(1);
266
- React3.useEffect(() => {
263
+ const prevStateRef = React5.useRef(state);
264
+ const [displayProgress, setDisplayProgress] = React5.useState(progress);
265
+ const [iconOpacity, setIconOpacity] = React5.useState(1);
266
+ React5.useEffect(() => {
267
267
  const prevState = prevStateRef.current;
268
268
  if (state === "done" && prevState === "saving") {
269
269
  const startProgress = displayProgress;
@@ -306,7 +306,7 @@ function AutoSaveIndicator({
306
306
  }
307
307
  prevStateRef.current = state;
308
308
  }, [state, progress]);
309
- React3.useEffect(() => {
309
+ React5.useEffect(() => {
310
310
  if (state !== prevStateRef.current) {
311
311
  setIconOpacity(0);
312
312
  const timer = setTimeout(() => {
@@ -421,7 +421,7 @@ function AutoSaveIndicator({
421
421
  }
422
422
  );
423
423
  }
424
- var SaveLoadControls = React3.memo(function SaveLoadControls2({
424
+ var SaveLoadControls = React5.memo(function SaveLoadControls2({
425
425
  onSave,
426
426
  onLoad,
427
427
  onScreenshot,
@@ -517,17 +517,17 @@ var QUICK_PRESETS = [
517
517
  { id: "crt/crt-geom", label: "CRT Geom" },
518
518
  { id: "handheld/lcd-grid-v2", label: "LCD Grid" }
519
519
  ];
520
- var ShaderDropdown = React3.memo(function ShaderDropdown2({
520
+ var ShaderDropdown = React5.memo(function ShaderDropdown2({
521
521
  currentShader = "",
522
522
  onShaderChange,
523
523
  isRunning = false,
524
524
  systemColor = "#00FF41",
525
525
  disabled = false
526
526
  }) {
527
- const [isOpen, setIsOpen] = React3.useState(false);
528
- const [pendingShader, setPendingShader] = React3.useState(null);
529
- const dropdownRef = React3.useRef(null);
530
- React3.useEffect(() => {
527
+ const [isOpen, setIsOpen] = React5.useState(false);
528
+ const [pendingShader, setPendingShader] = React5.useState(null);
529
+ const dropdownRef = React5.useRef(null);
530
+ React5.useEffect(() => {
531
531
  const handleClickOutside = (e) => {
532
532
  if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
533
533
  setIsOpen(false);
@@ -671,7 +671,7 @@ function RAButton({
671
671
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 px-2 py-1 bg-gray-900/95 text-white text-xs rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none z-50 border border-white/10", children: isIdentifying ? "Identifying game..." : isGameFound ? `${achievementCount} achievements available` : isConnected ? "Connected - Game not in RA database" : "Connect RetroAchievements" })
672
672
  ] });
673
673
  }
674
- var SettingsControls = React3.memo(function SettingsControls2({
674
+ var SettingsControls = React5.memo(function SettingsControls2({
675
675
  onFullscreen,
676
676
  onControls,
677
677
  onGamepadSettings,
@@ -775,12 +775,12 @@ var SettingsControls = React3.memo(function SettingsControls2({
775
775
  /* @__PURE__ */ jsxRuntime.jsx(ControlButton, { onClick: onExit, icon: lucideReact.Power, label: "Exit", danger: true, disabled, systemColor })
776
776
  ] });
777
777
  });
778
- var MobileControlDrawer = React3.memo(function MobileControlDrawer2({
778
+ var MobileControlDrawer = React5.memo(function MobileControlDrawer2({
779
779
  children,
780
780
  systemColor = "#00FF41"
781
781
  }) {
782
- const [isExpanded, setIsExpanded] = React3.useState(false);
783
- React3.useEffect(() => {
782
+ const [isExpanded, setIsExpanded] = React5.useState(false);
783
+ React5.useEffect(() => {
784
784
  if (isExpanded) {
785
785
  const handleInteract = (e) => {
786
786
  const target = e.target;
@@ -866,7 +866,7 @@ var MobileControlDrawer = React3.memo(function MobileControlDrawer2({
866
866
  ] });
867
867
  });
868
868
  var MobileControlDrawer_default = MobileControlDrawer;
869
- var PlayerControls = React3.memo(function PlayerControls2({
869
+ var PlayerControls = React5.memo(function PlayerControls2({
870
870
  isPaused,
871
871
  isRunning,
872
872
  speed,
@@ -980,7 +980,7 @@ var PlayerControls = React3.memo(function PlayerControls2({
980
980
  ] });
981
981
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
982
982
  /* @__PURE__ */ jsxRuntime.jsx(MobileControlDrawer_default, { systemColor, children: controlsContent }),
983
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:flex w-full items-center justify-between gap-4 px-6 py-3 bg-black/80 backdrop-blur-sm border-t border-white/10 shrink-0", children: controlsContent })
983
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:flex w-full items-center justify-between gap-2 px-4 py-2 bg-black/80 backdrop-blur-sm border-t border-white/10 shrink-0 overflow-x-auto", children: controlsContent })
984
984
  ] });
985
985
  });
986
986
  var PlayerControls_default = PlayerControls;
@@ -1028,11 +1028,11 @@ var TOAST_CONFIGS = {
1028
1028
  }
1029
1029
  };
1030
1030
  function ToastItem({ toast, onDismiss }) {
1031
- const [isVisible, setIsVisible] = React3.useState(false);
1032
- const [isExiting, setIsExiting] = React3.useState(false);
1031
+ const [isVisible, setIsVisible] = React5.useState(false);
1032
+ const [isExiting, setIsExiting] = React5.useState(false);
1033
1033
  const config = TOAST_CONFIGS[toast.type];
1034
1034
  const IconComponent = config.icon;
1035
- React3.useEffect(() => {
1035
+ React5.useEffect(() => {
1036
1036
  requestAnimationFrame(() => {
1037
1037
  setIsVisible(true);
1038
1038
  });
@@ -1138,17 +1138,17 @@ function ToastContainer({ toasts, onDismiss }) {
1138
1138
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed top-4 right-4 z-[9999] flex flex-col gap-2 pointer-events-none", children: toasts.map((toast) => /* @__PURE__ */ jsxRuntime.jsx(ToastItem, { toast, onDismiss }, toast.id)) })
1139
1139
  ] });
1140
1140
  }
1141
- var PerformanceOverlay = React3.memo(function PerformanceOverlay2({
1141
+ var PerformanceOverlay = React5.memo(function PerformanceOverlay2({
1142
1142
  isVisible,
1143
1143
  coreName = "Unknown",
1144
1144
  systemColor = "#00FF41"
1145
1145
  }) {
1146
- const [fps, setFps] = React3.useState(0);
1147
- const [frameTime, setFrameTime] = React3.useState(0);
1148
- const frameTimesRef = React3.useRef([]);
1149
- const lastTimeRef = React3.useRef(performance.now());
1150
- const rafIdRef = React3.useRef(null);
1151
- React3.useEffect(() => {
1146
+ const [fps, setFps] = React5.useState(0);
1147
+ const [frameTime, setFrameTime] = React5.useState(0);
1148
+ const frameTimesRef = React5.useRef([]);
1149
+ const lastTimeRef = React5.useRef(performance.now());
1150
+ const rafIdRef = React5.useRef(null);
1151
+ React5.useEffect(() => {
1152
1152
  if (!isVisible) {
1153
1153
  if (rafIdRef.current) {
1154
1154
  cancelAnimationFrame(rafIdRef.current);
@@ -1254,14 +1254,14 @@ var KEY_TO_BUTTON = {
1254
1254
  "ShiftRight": "SELECT",
1255
1255
  "Space": "COIN"
1256
1256
  };
1257
- var InputDisplay = React3.memo(function InputDisplay2({
1257
+ var InputDisplay = React5.memo(function InputDisplay2({
1258
1258
  isVisible,
1259
1259
  system,
1260
1260
  systemColor = "#00FF41",
1261
1261
  position = "bottom-right"
1262
1262
  }) {
1263
- const [activeKeys, setActiveKeys] = React3.useState(/* @__PURE__ */ new Set());
1264
- React3.useEffect(() => {
1263
+ const [activeKeys, setActiveKeys] = React5.useState(/* @__PURE__ */ new Set());
1264
+ React5.useEffect(() => {
1265
1265
  if (!isVisible) return;
1266
1266
  const handleKeyDown = (e) => {
1267
1267
  const button = KEY_TO_BUTTON[e.code];
@@ -1335,7 +1335,7 @@ var InputDisplay = React3.memo(function InputDisplay2({
1335
1335
  }
1336
1336
  );
1337
1337
  });
1338
- var DpadButton = React3.memo(function DpadButton2({
1338
+ var DpadButton = React5.memo(function DpadButton2({
1339
1339
  active,
1340
1340
  color,
1341
1341
  children
@@ -1353,7 +1353,7 @@ var DpadButton = React3.memo(function DpadButton2({
1353
1353
  }
1354
1354
  );
1355
1355
  });
1356
- var ActionButton = React3.memo(function ActionButton2({
1356
+ var ActionButton = React5.memo(function ActionButton2({
1357
1357
  active,
1358
1358
  color,
1359
1359
  children
@@ -1372,7 +1372,7 @@ var ActionButton = React3.memo(function ActionButton2({
1372
1372
  );
1373
1373
  });
1374
1374
  var InputDisplay_default = InputDisplay;
1375
- var RecordingIndicator = React3.memo(function RecordingIndicator2({
1375
+ var RecordingIndicator = React5.memo(function RecordingIndicator2({
1376
1376
  isRecording,
1377
1377
  isPaused,
1378
1378
  duration,
@@ -1381,7 +1381,7 @@ var RecordingIndicator = React3.memo(function RecordingIndicator2({
1381
1381
  onStop,
1382
1382
  systemColor = "#FF3333"
1383
1383
  }) {
1384
- const [isHovered, setIsHovered] = React3.useState(false);
1384
+ const [isHovered, setIsHovered] = React5.useState(false);
1385
1385
  if (!isRecording) return null;
1386
1386
  const minutes = Math.floor(duration / 60);
1387
1387
  const seconds = duration % 60;
@@ -1495,7 +1495,7 @@ var SHORTCUTS = [
1495
1495
  ]
1496
1496
  }
1497
1497
  ];
1498
- var ShortcutsModal = React3.memo(function ShortcutsModal2({
1498
+ var ShortcutsModal = React5.memo(function ShortcutsModal2({
1499
1499
  isOpen,
1500
1500
  onClose,
1501
1501
  systemColor = "#00FF41"
@@ -1705,10 +1705,10 @@ function createOrientationChangeHandler(callback, checkReady, maxRafs = 3) {
1705
1705
 
1706
1706
  // src/hooks/useMobile.ts
1707
1707
  function useMobile() {
1708
- const [isMobile, setIsMobile] = React3.useState(false);
1709
- const [isLandscape, setIsLandscape] = React3.useState(false);
1710
- const [isPortrait, setIsPortrait] = React3.useState(true);
1711
- React3.useEffect(() => {
1708
+ const [isMobile, setIsMobile] = React5.useState(false);
1709
+ const [isLandscape, setIsLandscape] = React5.useState(false);
1710
+ const [isPortrait, setIsPortrait] = React5.useState(true);
1711
+ React5.useEffect(() => {
1712
1712
  let lastOrientation = null;
1713
1713
  let orientationTimeout = null;
1714
1714
  const checkOrientation = () => {
@@ -1860,17 +1860,17 @@ function useTouchHandlers({
1860
1860
  onRelease,
1861
1861
  onPositionChange
1862
1862
  }) {
1863
- const isDraggingRef = React3.useRef(false);
1864
- const dragStartRef = React3.useRef({ x: 0, y: 0 });
1865
- const dragTimerRef = React3.useRef(null);
1866
- const touchStartPosRef = React3.useRef({ x: 0, y: 0 });
1867
- const clearDragTimer = React3.useCallback(() => {
1863
+ const isDraggingRef = React5.useRef(false);
1864
+ const dragStartRef = React5.useRef({ x: 0, y: 0 });
1865
+ const dragTimerRef = React5.useRef(null);
1866
+ const touchStartPosRef = React5.useRef({ x: 0, y: 0 });
1867
+ const clearDragTimer = React5.useCallback(() => {
1868
1868
  if (dragTimerRef.current) {
1869
1869
  clearTimeout(dragTimerRef.current);
1870
1870
  dragTimerRef.current = null;
1871
1871
  }
1872
1872
  }, []);
1873
- const startDragging = React3.useCallback(
1873
+ const startDragging = React5.useCallback(
1874
1874
  (touchX, touchY) => {
1875
1875
  isDraggingRef.current = true;
1876
1876
  dragStartRef.current = {
@@ -1883,7 +1883,7 @@ function useTouchHandlers({
1883
1883
  },
1884
1884
  [displayX, displayY, containerWidth, containerHeight, isSystemButton, buttonType, onRelease]
1885
1885
  );
1886
- const handleTouchStart = React3.useCallback(
1886
+ const handleTouchStart = React5.useCallback(
1887
1887
  (e) => {
1888
1888
  const touch = e.touches[0];
1889
1889
  touchStartPosRef.current = { x: touch.clientX, y: touch.clientY };
@@ -1918,7 +1918,7 @@ function useTouchHandlers({
1918
1918
  },
1919
1919
  [isSystemButton, buttonType, onPress, onPressDown, onPositionChange, buttonSize, startDragging]
1920
1920
  );
1921
- const handleTouchMove = React3.useCallback(
1921
+ const handleTouchMove = React5.useCallback(
1922
1922
  (e) => {
1923
1923
  const touch = e.touches[0];
1924
1924
  if (onPositionChange && !isDraggingRef.current) {
@@ -1945,7 +1945,7 @@ function useTouchHandlers({
1945
1945
  },
1946
1946
  [onPositionChange, clearDragTimer, startDragging, containerWidth, containerHeight, buttonSize]
1947
1947
  );
1948
- const handleTouchEnd = React3.useCallback(
1948
+ const handleTouchEnd = React5.useCallback(
1949
1949
  (e) => {
1950
1950
  clearDragTimer();
1951
1951
  if (isDraggingRef.current) {
@@ -1962,7 +1962,7 @@ function useTouchHandlers({
1962
1962
  },
1963
1963
  [clearDragTimer, isSystemButton, buttonType, onRelease]
1964
1964
  );
1965
- const handleTouchCancel = React3.useCallback(
1965
+ const handleTouchCancel = React5.useCallback(
1966
1966
  (e) => {
1967
1967
  clearDragTimer();
1968
1968
  if (isDraggingRef.current) {
@@ -1979,7 +1979,7 @@ function useTouchHandlers({
1979
1979
  },
1980
1980
  [clearDragTimer, isSystemButton, buttonType, onRelease]
1981
1981
  );
1982
- const cleanup = React3.useCallback(() => {
1982
+ const cleanup = React5.useCallback(() => {
1983
1983
  clearDragTimer();
1984
1984
  }, [clearDragTimer]);
1985
1985
  return {
@@ -2043,7 +2043,7 @@ function getButtonStyles(buttonType, isPressed) {
2043
2043
  };
2044
2044
  }
2045
2045
  }
2046
- var VirtualButton = React3__default.default.memo(function VirtualButton2({
2046
+ var VirtualButton = React5__default.default.memo(function VirtualButton2({
2047
2047
  config,
2048
2048
  isPressed,
2049
2049
  onPress,
@@ -2057,7 +2057,7 @@ var VirtualButton = React3__default.default.memo(function VirtualButton2({
2057
2057
  systemColor = "#00FF41"
2058
2058
  // Default retro green
2059
2059
  }) {
2060
- const buttonRef = React3.useRef(null);
2060
+ const buttonRef = React5.useRef(null);
2061
2061
  const isSystemButton = config.type === "start" || config.type === "select";
2062
2062
  const displayX = customPosition ? customPosition.x : config.x;
2063
2063
  const displayY = customPosition ? customPosition.y : config.y;
@@ -2080,7 +2080,7 @@ var VirtualButton = React3__default.default.memo(function VirtualButton2({
2080
2080
  onRelease,
2081
2081
  onPositionChange
2082
2082
  });
2083
- React3.useEffect(() => {
2083
+ React5.useEffect(() => {
2084
2084
  const button = buttonRef.current;
2085
2085
  if (!button) return;
2086
2086
  button.addEventListener("touchstart", handleTouchStart, { passive: false });
@@ -2757,7 +2757,7 @@ function dispatchKeyboardEvent(type, code) {
2757
2757
  canvas.dispatchEvent(event);
2758
2758
  return true;
2759
2759
  }
2760
- var Dpad = React3__default.default.memo(function Dpad2({
2760
+ var Dpad = React5__default.default.memo(function Dpad2({
2761
2761
  size,
2762
2762
  x,
2763
2763
  y,
@@ -2767,14 +2767,14 @@ var Dpad = React3__default.default.memo(function Dpad2({
2767
2767
  systemColor = "#00FF41",
2768
2768
  isLandscape = false
2769
2769
  }) {
2770
- const dpadRef = React3.useRef(null);
2771
- const activeTouchRef = React3.useRef(null);
2772
- const activeDirectionsRef = React3.useRef(/* @__PURE__ */ new Set());
2773
- const upRef = React3.useRef(null);
2774
- const downRef = React3.useRef(null);
2775
- const leftRef = React3.useRef(null);
2776
- const rightRef = React3.useRef(null);
2777
- const getKeyCode = React3.useCallback((direction) => {
2770
+ const dpadRef = React5.useRef(null);
2771
+ const activeTouchRef = React5.useRef(null);
2772
+ const activeDirectionsRef = React5.useRef(/* @__PURE__ */ new Set());
2773
+ const upRef = React5.useRef(null);
2774
+ const downRef = React5.useRef(null);
2775
+ const leftRef = React5.useRef(null);
2776
+ const rightRef = React5.useRef(null);
2777
+ const getKeyCode = React5.useCallback((direction) => {
2778
2778
  if (!controls) {
2779
2779
  const defaults = {
2780
2780
  up: "ArrowUp",
@@ -2786,7 +2786,7 @@ var Dpad = React3__default.default.memo(function Dpad2({
2786
2786
  }
2787
2787
  return controls[direction] || "";
2788
2788
  }, [controls]);
2789
- const getDirectionsFromTouch = React3.useCallback((touchX, touchY, rect) => {
2789
+ const getDirectionsFromTouch = React5.useCallback((touchX, touchY, rect) => {
2790
2790
  const centerX = rect.left + rect.width / 2;
2791
2791
  const centerY = rect.top + rect.height / 2;
2792
2792
  const dx = touchX - centerX;
@@ -2802,7 +2802,7 @@ var Dpad = React3__default.default.memo(function Dpad2({
2802
2802
  if (angle >= -67.5 && angle <= 67.5) directions.add("right");
2803
2803
  return directions;
2804
2804
  }, []);
2805
- const updateVisuals = React3.useCallback((directions) => {
2805
+ const updateVisuals = React5.useCallback((directions) => {
2806
2806
  const activeColor = systemColor;
2807
2807
  const inactiveColor = "#1a1a1a";
2808
2808
  if (upRef.current) upRef.current.style.fill = directions.has("up") ? activeColor : inactiveColor;
@@ -2810,7 +2810,7 @@ var Dpad = React3__default.default.memo(function Dpad2({
2810
2810
  if (leftRef.current) leftRef.current.style.fill = directions.has("left") ? activeColor : inactiveColor;
2811
2811
  if (rightRef.current) rightRef.current.style.fill = directions.has("right") ? activeColor : inactiveColor;
2812
2812
  }, [systemColor]);
2813
- const updateDirections = React3.useCallback((newDirections) => {
2813
+ const updateDirections = React5.useCallback((newDirections) => {
2814
2814
  const prev = activeDirectionsRef.current;
2815
2815
  prev.forEach((dir) => {
2816
2816
  if (!newDirections.has(dir)) {
@@ -2830,7 +2830,7 @@ var Dpad = React3__default.default.memo(function Dpad2({
2830
2830
  activeDirectionsRef.current = newDirections;
2831
2831
  updateVisuals(newDirections);
2832
2832
  }, [getKeyCode, updateVisuals]);
2833
- const handleTouchStart = React3.useCallback((e) => {
2833
+ const handleTouchStart = React5.useCallback((e) => {
2834
2834
  e.preventDefault();
2835
2835
  e.stopPropagation();
2836
2836
  const touch = e.touches[0];
@@ -2839,7 +2839,7 @@ var Dpad = React3__default.default.memo(function Dpad2({
2839
2839
  if (!rect) return;
2840
2840
  updateDirections(getDirectionsFromTouch(touch.clientX, touch.clientY, rect));
2841
2841
  }, [getDirectionsFromTouch, updateDirections]);
2842
- const handleTouchMove = React3.useCallback((e) => {
2842
+ const handleTouchMove = React5.useCallback((e) => {
2843
2843
  e.preventDefault();
2844
2844
  let touch = null;
2845
2845
  for (let i = 0; i < e.touches.length; i++) {
@@ -2853,7 +2853,7 @@ var Dpad = React3__default.default.memo(function Dpad2({
2853
2853
  if (!rect) return;
2854
2854
  updateDirections(getDirectionsFromTouch(touch.clientX, touch.clientY, rect));
2855
2855
  }, [getDirectionsFromTouch, updateDirections]);
2856
- const handleTouchEnd = React3.useCallback((e) => {
2856
+ const handleTouchEnd = React5.useCallback((e) => {
2857
2857
  e.preventDefault();
2858
2858
  let touchEnded = true;
2859
2859
  for (let i = 0; i < e.touches.length; i++) {
@@ -2872,7 +2872,7 @@ var Dpad = React3__default.default.memo(function Dpad2({
2872
2872
  updateVisuals(/* @__PURE__ */ new Set());
2873
2873
  }
2874
2874
  }, [getKeyCode, updateVisuals]);
2875
- React3.useEffect(() => {
2875
+ React5.useEffect(() => {
2876
2876
  const dpad = dpadRef.current;
2877
2877
  if (!dpad) return;
2878
2878
  dpad.addEventListener("touchstart", handleTouchStart, { passive: false });
@@ -2930,9 +2930,9 @@ function adjustButtonPosition(config, context) {
2930
2930
  }
2931
2931
  var STORAGE_KEY = "virtual-button-positions";
2932
2932
  function useButtonPositions() {
2933
- const [landscapePositions, setLandscapePositions] = React3.useState({});
2934
- const [portraitPositions, setPortraitPositions] = React3.useState({});
2935
- React3.useEffect(() => {
2933
+ const [landscapePositions, setLandscapePositions] = React5.useState({});
2934
+ const [portraitPositions, setPortraitPositions] = React5.useState({});
2935
+ React5.useEffect(() => {
2936
2936
  try {
2937
2937
  const stored = localStorage.getItem(STORAGE_KEY);
2938
2938
  if (stored) {
@@ -2948,7 +2948,7 @@ function useButtonPositions() {
2948
2948
  console.error("Failed to load button positions:", e);
2949
2949
  }
2950
2950
  }, []);
2951
- const savePosition = React3.useCallback((buttonType, x, y, isLandscape) => {
2951
+ const savePosition = React5.useCallback((buttonType, x, y, isLandscape) => {
2952
2952
  if (isLandscape) {
2953
2953
  setLandscapePositions((prev) => {
2954
2954
  const updated = { ...prev, [buttonType]: { x, y } };
@@ -2979,11 +2979,11 @@ function useButtonPositions() {
2979
2979
  });
2980
2980
  }
2981
2981
  }, [landscapePositions, portraitPositions]);
2982
- const getPosition = React3.useCallback((buttonType, isLandscape) => {
2982
+ const getPosition = React5.useCallback((buttonType, isLandscape) => {
2983
2983
  const positions = isLandscape ? landscapePositions : portraitPositions;
2984
2984
  return positions[buttonType] || null;
2985
2985
  }, [landscapePositions, portraitPositions]);
2986
- const resetPositions = React3.useCallback(() => {
2986
+ const resetPositions = React5.useCallback(() => {
2987
2987
  setLandscapePositions({});
2988
2988
  setPortraitPositions({});
2989
2989
  try {
@@ -3008,9 +3008,9 @@ function VirtualController({
3008
3008
  // Default retro green
3009
3009
  }) {
3010
3010
  const { isMobile, isLandscape, isPortrait } = useMobile();
3011
- const [pressedButtons, setPressedButtons] = React3.useState(/* @__PURE__ */ new Set());
3012
- const [containerSize, setContainerSize] = React3.useState({ width: 0, height: 0 });
3013
- const [isFullscreenState, setIsFullscreenState] = React3.useState(false);
3011
+ const [pressedButtons, setPressedButtons] = React5.useState(/* @__PURE__ */ new Set());
3012
+ const [containerSize, setContainerSize] = React5.useState({ width: 0, height: 0 });
3013
+ const [isFullscreenState, setIsFullscreenState] = React5.useState(false);
3014
3014
  const { getPosition, savePosition } = useButtonPositions();
3015
3015
  const layout = getLayoutForSystem(system);
3016
3016
  const visibleButtons = layout.buttons.filter((btn) => {
@@ -3021,7 +3021,7 @@ function VirtualController({
3021
3021
  });
3022
3022
  const DPAD_TYPES = ["up", "down", "left", "right"];
3023
3023
  const dpadButtons = visibleButtons.filter((btn) => DPAD_TYPES.includes(btn.type));
3024
- React3.useEffect(() => {
3024
+ React5.useEffect(() => {
3025
3025
  const updateSize = () => {
3026
3026
  const { width, height } = getViewportSize();
3027
3027
  setContainerSize({ width, height });
@@ -3064,14 +3064,14 @@ function VirtualController({
3064
3064
  cleanupFullscreen();
3065
3065
  };
3066
3066
  }, [containerSize.height]);
3067
- const getButtonKeyboardCode = React3.useCallback(
3067
+ const getButtonKeyboardCode = React5.useCallback(
3068
3068
  (buttonType) => {
3069
3069
  return getKeyboardCode(buttonType, controls);
3070
3070
  },
3071
3071
  [controls]
3072
3072
  );
3073
3073
  const SYSTEM_BUTTONS2 = ["start", "select"];
3074
- const handlePress = React3.useCallback(
3074
+ const handlePress = React5.useCallback(
3075
3075
  (buttonType) => {
3076
3076
  const isSystemButton = SYSTEM_BUTTONS2.includes(buttonType);
3077
3077
  if (!isSystemButton && !isRunning) {
@@ -3094,7 +3094,7 @@ function VirtualController({
3094
3094
  },
3095
3095
  [isRunning, getButtonKeyboardCode]
3096
3096
  );
3097
- const handlePressDown = React3.useCallback(
3097
+ const handlePressDown = React5.useCallback(
3098
3098
  (buttonType) => {
3099
3099
  if (!isRunning) return;
3100
3100
  const isSystemButton = SYSTEM_BUTTONS2.includes(buttonType);
@@ -3111,7 +3111,7 @@ function VirtualController({
3111
3111
  },
3112
3112
  [isRunning, getButtonKeyboardCode]
3113
3113
  );
3114
- const handleRelease = React3.useCallback(
3114
+ const handleRelease = React5.useCallback(
3115
3115
  (buttonType) => {
3116
3116
  const isSystemButton = SYSTEM_BUTTONS2.includes(buttonType);
3117
3117
  if (isSystemButton) return;
@@ -3127,7 +3127,7 @@ function VirtualController({
3127
3127
  },
3128
3128
  [getButtonKeyboardCode]
3129
3129
  );
3130
- React3.useEffect(() => {
3130
+ React5.useEffect(() => {
3131
3131
  if (!isRunning && pressedButtons.size > 0) {
3132
3132
  pressedButtons.forEach((buttonType) => {
3133
3133
  if (!SYSTEM_BUTTONS2.includes(buttonType)) {
@@ -3137,7 +3137,7 @@ function VirtualController({
3137
3137
  setPressedButtons(/* @__PURE__ */ new Set());
3138
3138
  }
3139
3139
  }, [isRunning, pressedButtons, handleRelease]);
3140
- const memoizedButtonElements = React3.useMemo(() => {
3140
+ const memoizedButtonElements = React5.useMemo(() => {
3141
3141
  const width = containerSize.width || (typeof window !== "undefined" ? window.innerWidth : 0);
3142
3142
  const height = containerSize.height || (typeof window !== "undefined" ? window.innerHeight : 0);
3143
3143
  const context = {
@@ -3408,7 +3408,7 @@ function saveMuteState(muted) {
3408
3408
  if (typeof window === "undefined") return;
3409
3409
  localStorage.setItem(MUTE_KEY, muted.toString());
3410
3410
  }
3411
- var GameCanvas = React3.memo(function GameCanvas2({
3411
+ var GameCanvas = React5.memo(function GameCanvas2({
3412
3412
  status,
3413
3413
  system,
3414
3414
  error,
@@ -3419,8 +3419,8 @@ var GameCanvas = React3.memo(function GameCanvas2({
3419
3419
  canvasRef,
3420
3420
  onSelectBios
3421
3421
  }) {
3422
- const canvasContainerRef = React3.useRef(null);
3423
- React3.useEffect(() => {
3422
+ const canvasContainerRef = React5.useRef(null);
3423
+ React5.useEffect(() => {
3424
3424
  const container = canvasContainerRef.current;
3425
3425
  if (!container || canvasRef.current) return;
3426
3426
  const canvas = document.createElement("canvas");
@@ -3438,7 +3438,7 @@ var GameCanvas = React3.memo(function GameCanvas2({
3438
3438
  canvasRef.current = null;
3439
3439
  };
3440
3440
  }, [canvasRef]);
3441
- React3.useEffect(() => {
3441
+ React5.useEffect(() => {
3442
3442
  if (status !== "ready" && status !== "running" && status !== "paused") return;
3443
3443
  return setupCanvasResize(canvasContainerRef);
3444
3444
  }, [status]);
@@ -3472,23 +3472,23 @@ function ControlMapper({
3472
3472
  onClose,
3473
3473
  system
3474
3474
  }) {
3475
- const [localControls, setLocalControls] = React3.useState(controls);
3476
- const [listeningFor, setListeningFor] = React3.useState(null);
3477
- const activeButtons = React3.useMemo(() => {
3475
+ const [localControls, setLocalControls] = React5.useState(controls);
3476
+ const [listeningFor, setListeningFor] = React5.useState(null);
3477
+ const activeButtons = React5.useMemo(() => {
3478
3478
  return getConsoleButtons(system || "SNES");
3479
3479
  }, [system]);
3480
- const controlGroups = React3.useMemo(() => {
3480
+ const controlGroups = React5.useMemo(() => {
3481
3481
  return getFilteredGroups(activeButtons);
3482
3482
  }, [activeButtons]);
3483
- const defaultControls = React3.useMemo(() => {
3483
+ const defaultControls = React5.useMemo(() => {
3484
3484
  return getConsoleKeyboardDefaults(system || "SNES");
3485
3485
  }, [system]);
3486
- React3.useEffect(() => {
3486
+ React5.useEffect(() => {
3487
3487
  if (isOpen) {
3488
3488
  setLocalControls(controls);
3489
3489
  }
3490
3490
  }, [isOpen, controls]);
3491
- React3.useEffect(() => {
3491
+ React5.useEffect(() => {
3492
3492
  if (!isOpen) {
3493
3493
  setListeningFor(null);
3494
3494
  return;
@@ -3638,17 +3638,17 @@ function toGamepadInfo(gamepad) {
3638
3638
  }
3639
3639
  function useGamepad(options) {
3640
3640
  const { onConnect, onDisconnect } = options || {};
3641
- const [gamepads, setGamepads] = React3.useState([]);
3642
- const rafRef = React3.useRef(null);
3643
- const lastStateRef = React3.useRef("");
3644
- const prevCountRef = React3.useRef(0);
3645
- const onConnectRef = React3.useRef(onConnect);
3646
- const onDisconnectRef = React3.useRef(onDisconnect);
3647
- React3.useEffect(() => {
3641
+ const [gamepads, setGamepads] = React5.useState([]);
3642
+ const rafRef = React5.useRef(null);
3643
+ const lastStateRef = React5.useRef("");
3644
+ const prevCountRef = React5.useRef(0);
3645
+ const onConnectRef = React5.useRef(onConnect);
3646
+ const onDisconnectRef = React5.useRef(onDisconnect);
3647
+ React5.useEffect(() => {
3648
3648
  onConnectRef.current = onConnect;
3649
3649
  onDisconnectRef.current = onDisconnect;
3650
3650
  }, [onConnect, onDisconnect]);
3651
- const getGamepads = React3.useCallback(() => {
3651
+ const getGamepads = React5.useCallback(() => {
3652
3652
  if (typeof navigator === "undefined" || typeof navigator.getGamepads !== "function") {
3653
3653
  return [];
3654
3654
  }
@@ -3662,14 +3662,14 @@ function useGamepad(options) {
3662
3662
  }
3663
3663
  return connected;
3664
3664
  }, []);
3665
- const getRawGamepad = React3.useCallback((index) => {
3665
+ const getRawGamepad = React5.useCallback((index) => {
3666
3666
  const rawGamepads = navigator.getGamepads?.() ?? [];
3667
3667
  return rawGamepads[index] ?? null;
3668
3668
  }, []);
3669
- const refresh = React3.useCallback(() => {
3669
+ const refresh = React5.useCallback(() => {
3670
3670
  setGamepads(getGamepads());
3671
3671
  }, [getGamepads]);
3672
- React3.useEffect(() => {
3672
+ React5.useEffect(() => {
3673
3673
  if (typeof window === "undefined" || typeof navigator === "undefined") {
3674
3674
  return;
3675
3675
  }
@@ -3770,11 +3770,11 @@ function GamepadMapper({
3770
3770
  onSave,
3771
3771
  systemColor = "#00FF41"
3772
3772
  }) {
3773
- const [selectedPlayer, setSelectedPlayer] = React3.useState(1);
3774
- const [bindings, setBindings] = React3.useState({});
3775
- const [listeningFor, setListeningFor] = React3.useState(null);
3776
- const rafRef = React3.useRef(null);
3777
- React3.useEffect(() => {
3773
+ const [selectedPlayer, setSelectedPlayer] = React5.useState(1);
3774
+ const [bindings, setBindings] = React5.useState({});
3775
+ const [listeningFor, setListeningFor] = React5.useState(null);
3776
+ const rafRef = React5.useRef(null);
3777
+ React5.useEffect(() => {
3778
3778
  if (isOpen) {
3779
3779
  const loadedBindings = {};
3780
3780
  for (let i = 1; i <= 4; i++) {
@@ -3786,7 +3786,7 @@ function GamepadMapper({
3786
3786
  }
3787
3787
  }
3788
3788
  }, [isOpen, gamepads]);
3789
- React3.useEffect(() => {
3789
+ React5.useEffect(() => {
3790
3790
  if (!isOpen || !listeningFor) {
3791
3791
  if (rafRef.current) {
3792
3792
  cancelAnimationFrame(rafRef.current);
@@ -3821,7 +3821,7 @@ function GamepadMapper({
3821
3821
  }
3822
3822
  };
3823
3823
  }, [isOpen, listeningFor, selectedPlayer]);
3824
- React3.useEffect(() => {
3824
+ React5.useEffect(() => {
3825
3825
  if (!isOpen) return;
3826
3826
  const handleKeyDown = (e) => {
3827
3827
  if (e.code === "Escape") {
@@ -4009,7 +4009,7 @@ function CheatModal({
4009
4009
  onToggle,
4010
4010
  onClose
4011
4011
  }) {
4012
- const [copiedId, setCopiedId] = React3__default.default.useState(null);
4012
+ const [copiedId, setCopiedId] = React5__default.default.useState(null);
4013
4013
  if (!isOpen) return null;
4014
4014
  const handleCopy = async (code, id) => {
4015
4015
  await navigator.clipboard.writeText(code);
@@ -4908,13 +4908,13 @@ function RASidebar({
4908
4908
  unlockedIds
4909
4909
  }) {
4910
4910
  const defaultTab = isLoggedIn && currentGame && achievements.length > 0 ? "achievements" : "settings";
4911
- const [activeTab, setActiveTab] = React3.useState(defaultTab);
4912
- const [filter, setFilter] = React3.useState("all");
4913
- const [username, setUsername] = React3.useState("");
4914
- const [password, setPassword] = React3.useState("");
4915
- const [showPassword, setShowPassword] = React3.useState(false);
4916
- const [localError, setLocalError] = React3.useState(null);
4917
- React3.useEffect(() => {
4911
+ const [activeTab, setActiveTab] = React5.useState(defaultTab);
4912
+ const [filter, setFilter] = React5.useState("all");
4913
+ const [username, setUsername] = React5.useState("");
4914
+ const [password, setPassword] = React5.useState("");
4915
+ const [showPassword, setShowPassword] = React5.useState(false);
4916
+ const [localError, setLocalError] = React5.useState(null);
4917
+ React5.useEffect(() => {
4918
4918
  if (!isOpen) {
4919
4919
  setUsername("");
4920
4920
  setPassword("");
@@ -5069,8 +5069,8 @@ function RASidebar({
5069
5069
  ] });
5070
5070
  }
5071
5071
  function useToast(defaultDuration = 3e3) {
5072
- const [toasts, setToasts] = React3.useState([]);
5073
- const showToast = React3.useCallback((message, type = "info", options) => {
5072
+ const [toasts, setToasts] = React5.useState([]);
5073
+ const showToast = React5.useCallback((message, type = "info", options) => {
5074
5074
  const id = crypto.randomUUID();
5075
5075
  const duration = options?.duration ?? defaultDuration;
5076
5076
  const newToast = {
@@ -5089,10 +5089,10 @@ function useToast(defaultDuration = 3e3) {
5089
5089
  }, duration);
5090
5090
  }
5091
5091
  }, [defaultDuration]);
5092
- const dismissToast = React3.useCallback((id) => {
5092
+ const dismissToast = React5.useCallback((id) => {
5093
5093
  setToasts((prev) => prev.filter((t) => t.id !== id));
5094
5094
  }, []);
5095
- const clearToasts = React3.useCallback(() => {
5095
+ const clearToasts = React5.useCallback(() => {
5096
5096
  setToasts([]);
5097
5097
  }, []);
5098
5098
  return {
@@ -5106,21 +5106,21 @@ function useToast(defaultDuration = 3e3) {
5106
5106
  // src/hooks/useGameUI.ts
5107
5107
  function useGameUI() {
5108
5108
  const { isMobile } = useMobile();
5109
- const containerRef = React3.useRef(null);
5110
- const canvasRef = React3.useRef(null);
5109
+ const containerRef = React5.useRef(null);
5110
+ const canvasRef = React5.useRef(null);
5111
5111
  const { toasts, showToast, dismissToast } = useToast(3500);
5112
- const [isFullscreen2, setIsFullscreen] = React3.useState(false);
5113
- const [raSidebarOpen, setRaSidebarOpen] = React3.useState(false);
5114
- const checkFullscreen = React3.useCallback(() => {
5112
+ const [isFullscreen2, setIsFullscreen] = React5.useState(false);
5113
+ const [raSidebarOpen, setRaSidebarOpen] = React5.useState(false);
5114
+ const checkFullscreen = React5.useCallback(() => {
5115
5115
  const fullscreen = isFullscreen();
5116
5116
  setIsFullscreen(fullscreen);
5117
5117
  return fullscreen;
5118
5118
  }, []);
5119
- React3.useEffect(() => {
5119
+ React5.useEffect(() => {
5120
5120
  checkFullscreen();
5121
5121
  return setupFullscreenListener(checkFullscreen);
5122
5122
  }, [checkFullscreen]);
5123
- const handleFullscreen = React3.useCallback(async () => {
5123
+ const handleFullscreen = React5.useCallback(async () => {
5124
5124
  if (!containerRef.current) return;
5125
5125
  try {
5126
5126
  const nativeWorked = await toggleFullscreen(containerRef.current);
@@ -5663,15 +5663,15 @@ function useEmulatorCore({
5663
5663
  onReady,
5664
5664
  onError
5665
5665
  }) {
5666
- const [status, setStatus] = React3.useState("idle");
5667
- const [error, setError] = React3.useState(null);
5668
- const [isPaused, setIsPaused] = React3.useState(false);
5669
- const [speed, setSpeedState] = React3.useState(1);
5670
- const [isFastForwardOn, setIsFastForwardOn] = React3.useState(false);
5671
- const [isPerformanceMode, setIsPerformanceMode] = React3.useState(false);
5672
- const nostalgistRef = React3.useRef(null);
5673
- const isStartingRef = React3.useRef(false);
5674
- const prepare = React3.useCallback(async () => {
5666
+ const [status, setStatus] = React5.useState("idle");
5667
+ const [error, setError] = React5.useState(null);
5668
+ const [isPaused, setIsPaused] = React5.useState(false);
5669
+ const [speed, setSpeedState] = React5.useState(1);
5670
+ const [isFastForwardOn, setIsFastForwardOn] = React5.useState(false);
5671
+ const [isPerformanceMode, setIsPerformanceMode] = React5.useState(false);
5672
+ const nostalgistRef = React5.useRef(null);
5673
+ const isStartingRef = React5.useRef(false);
5674
+ const prepare = React5.useCallback(async () => {
5675
5675
  if (!romUrl || !system) {
5676
5676
  console.warn("[Nostalgist] Missing romUrl or system");
5677
5677
  return;
@@ -5802,7 +5802,7 @@ function useEmulatorCore({
5802
5802
  onError?.(err instanceof Error ? err : new Error(errorMessage));
5803
5803
  }
5804
5804
  }, [system, romUrl, coreOverride, biosUrl, initialState, getCanvasElement, keyboardControls, gamepadBindings, initialVolume, onError, retroAchievements]);
5805
- const start = React3.useCallback(async () => {
5805
+ const start = React5.useCallback(async () => {
5806
5806
  if (isStartingRef.current) {
5807
5807
  console.log("[Nostalgist] Already starting");
5808
5808
  return;
@@ -5835,7 +5835,7 @@ function useEmulatorCore({
5835
5835
  isStartingRef.current = false;
5836
5836
  }
5837
5837
  }, [prepare, onReady, onError]);
5838
- const stop = React3.useCallback(() => {
5838
+ const stop = React5.useCallback(() => {
5839
5839
  if (nostalgistRef.current) {
5840
5840
  try {
5841
5841
  nostalgistRef.current.exit();
@@ -5848,7 +5848,7 @@ function useEmulatorCore({
5848
5848
  setIsPaused(false);
5849
5849
  }
5850
5850
  }, []);
5851
- React3.useEffect(() => {
5851
+ React5.useEffect(() => {
5852
5852
  return () => {
5853
5853
  if (nostalgistRef.current) {
5854
5854
  console.log("[Nostalgist] Cleaning up emulator on unmount");
@@ -5856,7 +5856,7 @@ function useEmulatorCore({
5856
5856
  }
5857
5857
  };
5858
5858
  }, [stop]);
5859
- const restart = React3.useCallback(async () => {
5859
+ const restart = React5.useCallback(async () => {
5860
5860
  if (nostalgistRef.current) {
5861
5861
  try {
5862
5862
  nostalgistRef.current.restart();
@@ -5871,7 +5871,7 @@ function useEmulatorCore({
5871
5871
  }
5872
5872
  }
5873
5873
  }, [stop, start]);
5874
- const pause = React3.useCallback(() => {
5874
+ const pause = React5.useCallback(() => {
5875
5875
  if (nostalgistRef.current && !isPaused && status === "running") {
5876
5876
  try {
5877
5877
  nostalgistRef.current.pause();
@@ -5882,7 +5882,7 @@ function useEmulatorCore({
5882
5882
  }
5883
5883
  }
5884
5884
  }, [isPaused, status]);
5885
- const resume = React3.useCallback(() => {
5885
+ const resume = React5.useCallback(() => {
5886
5886
  if (nostalgistRef.current) {
5887
5887
  try {
5888
5888
  nostalgistRef.current.resume();
@@ -5895,14 +5895,14 @@ function useEmulatorCore({
5895
5895
  }
5896
5896
  }
5897
5897
  }, [status]);
5898
- const togglePause = React3.useCallback(() => {
5898
+ const togglePause = React5.useCallback(() => {
5899
5899
  if (isPaused) {
5900
5900
  resume();
5901
5901
  } else {
5902
5902
  pause();
5903
5903
  }
5904
5904
  }, [isPaused, pause, resume]);
5905
- const setSpeed = React3.useCallback((multiplier) => {
5905
+ const setSpeed = React5.useCallback((multiplier) => {
5906
5906
  if (!nostalgistRef.current) return;
5907
5907
  try {
5908
5908
  const nostalgist = nostalgistRef.current;
@@ -5922,7 +5922,7 @@ function useEmulatorCore({
5922
5922
  console.error("[Nostalgist] Set speed error:", err);
5923
5923
  }
5924
5924
  }, [isFastForwardOn]);
5925
- const screenshot = React3.useCallback(async () => {
5925
+ const screenshot = React5.useCallback(async () => {
5926
5926
  if (!nostalgistRef.current) {
5927
5927
  return null;
5928
5928
  }
@@ -5952,7 +5952,7 @@ function useEmulatorCore({
5952
5952
  return null;
5953
5953
  }
5954
5954
  }, []);
5955
- const resize = React3.useCallback((size) => {
5955
+ const resize = React5.useCallback((size) => {
5956
5956
  if (!nostalgistRef.current) {
5957
5957
  console.warn("[Nostalgist] Cannot resize: emulator not ready");
5958
5958
  return;
@@ -5963,7 +5963,7 @@ function useEmulatorCore({
5963
5963
  console.error("[Nostalgist] Resize error:", err);
5964
5964
  }
5965
5965
  }, []);
5966
- React3.useCallback(() => {
5966
+ React5.useCallback(() => {
5967
5967
  return nostalgistRef.current;
5968
5968
  }, []);
5969
5969
  return {
@@ -5989,11 +5989,11 @@ function useEmulatorCore({
5989
5989
  };
5990
5990
  }
5991
5991
  function useEmulatorAudio({ nostalgistRef, initialVolume = 100 }) {
5992
- const [volume, setVolume] = React3.useState(initialVolume);
5993
- const [isMuted, setIsMuted] = React3.useState(false);
5994
- const gainNodeRef = React3.useRef(null);
5995
- const lastVolumeRef = React3.useRef(initialVolume);
5996
- React3.useEffect(() => {
5992
+ const [volume, setVolume] = React5.useState(initialVolume);
5993
+ const [isMuted, setIsMuted] = React5.useState(false);
5994
+ const gainNodeRef = React5.useRef(null);
5995
+ const lastVolumeRef = React5.useRef(initialVolume);
5996
+ React5.useEffect(() => {
5997
5997
  const originalConnect = AudioNode.prototype.connect;
5998
5998
  const contextGainMap = /* @__PURE__ */ new WeakMap();
5999
5999
  AudioNode.prototype.connect = function(destination, output, input) {
@@ -6021,7 +6021,7 @@ function useEmulatorAudio({ nostalgistRef, initialVolume = 100 }) {
6021
6021
  AudioNode.prototype.connect = originalConnect;
6022
6022
  };
6023
6023
  }, []);
6024
- const setVolumeLevel = React3.useCallback((newVolume) => {
6024
+ const setVolumeLevel = React5.useCallback((newVolume) => {
6025
6025
  const clampedVolume = Math.max(0, Math.min(100, newVolume));
6026
6026
  const volumeValue = clampedVolume / 100;
6027
6027
  try {
@@ -6042,7 +6042,7 @@ function useEmulatorAudio({ nostalgistRef, initialVolume = 100 }) {
6042
6042
  console.error("[Nostalgist] Volume change error:", err);
6043
6043
  }
6044
6044
  }, []);
6045
- const toggleMute = React3.useCallback(() => {
6045
+ const toggleMute = React5.useCallback(() => {
6046
6046
  if (!nostalgistRef.current) return;
6047
6047
  try {
6048
6048
  const emscripten = nostalgistRef.current.getEmscripten();
@@ -6084,7 +6084,7 @@ function useEmulatorAudio({ nostalgistRef, initialVolume = 100 }) {
6084
6084
  };
6085
6085
  }
6086
6086
  function useEmulatorInput({ nostalgistRef }) {
6087
- const pressKey = React3.useCallback((key) => {
6087
+ const pressKey = React5.useCallback((key) => {
6088
6088
  if (!nostalgistRef.current) return;
6089
6089
  try {
6090
6090
  nostalgistRef.current.press(key);
@@ -6099,10 +6099,10 @@ function useEmulatorInput({ nostalgistRef }) {
6099
6099
  var MIN_SAVE_INTERVAL = 100;
6100
6100
  var SAVE_TIMEOUT = 5e3;
6101
6101
  function useSaveScheduler(nostalgistRef) {
6102
- const queueRef = React3.useRef([]);
6103
- const savingRef = React3.useRef(false);
6104
- const lastSaveTimeRef = React3.useRef(0);
6105
- const processQueue = React3.useCallback(async () => {
6102
+ const queueRef = React5.useRef([]);
6103
+ const savingRef = React5.useRef(false);
6104
+ const lastSaveTimeRef = React5.useRef(0);
6105
+ const processQueue = React5.useCallback(async () => {
6106
6106
  if (savingRef.current || queueRef.current.length === 0) {
6107
6107
  return;
6108
6108
  }
@@ -6156,7 +6156,7 @@ function useSaveScheduler(nostalgistRef) {
6156
6156
  setTimeout(() => processQueue(), MIN_SAVE_INTERVAL);
6157
6157
  }
6158
6158
  }, [nostalgistRef]);
6159
- const save = React3.useCallback(() => {
6159
+ const save = React5.useCallback(() => {
6160
6160
  return new Promise((resolve) => {
6161
6161
  queueRef.current.push({
6162
6162
  priority: "high",
@@ -6166,7 +6166,7 @@ function useSaveScheduler(nostalgistRef) {
6166
6166
  processQueue();
6167
6167
  });
6168
6168
  }, [processQueue]);
6169
- const queueRewindCapture = React3.useCallback(() => {
6169
+ const queueRewindCapture = React5.useCallback(() => {
6170
6170
  const lowPriorityCount = queueRef.current.filter((q) => q.priority === "low").length;
6171
6171
  if (lowPriorityCount >= 3) {
6172
6172
  return Promise.resolve(null);
@@ -6180,13 +6180,13 @@ function useSaveScheduler(nostalgistRef) {
6180
6180
  processQueue();
6181
6181
  });
6182
6182
  }, [processQueue]);
6183
- const isSaving = React3.useCallback(() => savingRef.current, []);
6184
- const getQueueLength = React3.useCallback(() => queueRef.current.length, []);
6185
- const clearQueue = React3.useCallback(() => {
6183
+ const isSaving = React5.useCallback(() => savingRef.current, []);
6184
+ const getQueueLength = React5.useCallback(() => queueRef.current.length, []);
6185
+ const clearQueue = React5.useCallback(() => {
6186
6186
  queueRef.current.forEach((item) => item.resolve(null));
6187
6187
  queueRef.current = [];
6188
6188
  }, []);
6189
- const resultRef = React3.useRef({
6189
+ const resultRef = React5.useRef({
6190
6190
  save,
6191
6191
  queueRewindCapture,
6192
6192
  isSaving,
@@ -6203,22 +6203,22 @@ function useSaveScheduler(nostalgistRef) {
6203
6203
 
6204
6204
  // src/hooks/emulator/useEmulatorSaves.ts
6205
6205
  function useEmulatorSaves({ nostalgistRef, isPaused, setIsPaused, setStatus, rewindEnabled = true }) {
6206
- const [isRewinding, setIsRewinding] = React3.useState(false);
6207
- const [rewindBufferSize, setRewindBufferSize] = React3.useState(0);
6208
- const rewindIntervalRef = React3.useRef(null);
6209
- const rewindBufferRef = React3.useRef([]);
6210
- const rewindCaptureIntervalRef = React3.useRef(null);
6206
+ const [isRewinding, setIsRewinding] = React5.useState(false);
6207
+ const [rewindBufferSize, setRewindBufferSize] = React5.useState(0);
6208
+ const rewindIntervalRef = React5.useRef(null);
6209
+ const rewindBufferRef = React5.useRef([]);
6210
+ const rewindCaptureIntervalRef = React5.useRef(null);
6211
6211
  const saveScheduler = useSaveScheduler(nostalgistRef);
6212
- const saveState = React3.useCallback(async () => {
6212
+ const saveState = React5.useCallback(async () => {
6213
6213
  if (!nostalgistRef.current) return null;
6214
6214
  const result = await saveScheduler.queueRewindCapture();
6215
6215
  return result?.data ?? null;
6216
6216
  }, [saveScheduler, nostalgistRef]);
6217
- const saveStateWithBlob = React3.useCallback(async () => {
6217
+ const saveStateWithBlob = React5.useCallback(async () => {
6218
6218
  if (!nostalgistRef.current) return null;
6219
6219
  return saveScheduler.save();
6220
6220
  }, [saveScheduler, nostalgistRef]);
6221
- const loadState = React3.useCallback(async (state) => {
6221
+ const loadState = React5.useCallback(async (state) => {
6222
6222
  if (!nostalgistRef.current) {
6223
6223
  console.warn("[Nostalgist] Cannot load state: emulator not running");
6224
6224
  return false;
@@ -6239,7 +6239,7 @@ function useEmulatorSaves({ nostalgistRef, isPaused, setIsPaused, setStatus, rew
6239
6239
  return false;
6240
6240
  }
6241
6241
  }, [nostalgistRef, setIsPaused, setStatus]);
6242
- const startRewindCapture = React3.useCallback(() => {
6242
+ const startRewindCapture = React5.useCallback(() => {
6243
6243
  if (!rewindEnabled) {
6244
6244
  return;
6245
6245
  }
@@ -6267,13 +6267,13 @@ function useEmulatorSaves({ nostalgistRef, isPaused, setIsPaused, setStatus, rew
6267
6267
  }
6268
6268
  }, 500);
6269
6269
  }, [isPaused, saveState, nostalgistRef]);
6270
- const stopRewindCapture = React3.useCallback(() => {
6270
+ const stopRewindCapture = React5.useCallback(() => {
6271
6271
  if (rewindCaptureIntervalRef.current) {
6272
6272
  clearInterval(rewindCaptureIntervalRef.current);
6273
6273
  rewindCaptureIntervalRef.current = null;
6274
6274
  }
6275
6275
  }, []);
6276
- const stopRewind = React3.useCallback(() => {
6276
+ const stopRewind = React5.useCallback(() => {
6277
6277
  if (!isRewinding) {
6278
6278
  return;
6279
6279
  }
@@ -6294,7 +6294,7 @@ function useEmulatorSaves({ nostalgistRef, isPaused, setIsPaused, setStatus, rew
6294
6294
  console.error("[Nostalgist] Stop rewind error:", err);
6295
6295
  }
6296
6296
  }, [isRewinding, startRewindCapture, nostalgistRef]);
6297
- const startRewind = React3.useCallback(() => {
6297
+ const startRewind = React5.useCallback(() => {
6298
6298
  if (!nostalgistRef.current || isRewinding) {
6299
6299
  return;
6300
6300
  }
@@ -6333,7 +6333,7 @@ function useEmulatorSaves({ nostalgistRef, isPaused, setIsPaused, setStatus, rew
6333
6333
  startRewindCapture();
6334
6334
  }
6335
6335
  }, [isRewinding, loadState, stopRewindCapture, startRewindCapture, stopRewind, nostalgistRef]);
6336
- React3.useEffect(() => {
6336
+ React5.useEffect(() => {
6337
6337
  return () => {
6338
6338
  saveScheduler.clearQueue();
6339
6339
  if (rewindIntervalRef.current) {
@@ -6361,7 +6361,7 @@ function useEmulatorSaves({ nostalgistRef, isPaused, setIsPaused, setStatus, rew
6361
6361
  };
6362
6362
  }
6363
6363
  function useEmulatorCheats({ nostalgistRef }) {
6364
- const applyCheat = React3.useCallback((code) => {
6364
+ const applyCheat = React5.useCallback((code) => {
6365
6365
  if (!nostalgistRef.current) return;
6366
6366
  try {
6367
6367
  nostalgistRef.current.addCheat(code);
@@ -6369,7 +6369,7 @@ function useEmulatorCheats({ nostalgistRef }) {
6369
6369
  console.error("[Nostalgist] Apply cheat error:", err);
6370
6370
  }
6371
6371
  }, [nostalgistRef]);
6372
- const resetCheats = React3.useCallback(() => {
6372
+ const resetCheats = React5.useCallback(() => {
6373
6373
  if (!nostalgistRef.current) return;
6374
6374
  try {
6375
6375
  nostalgistRef.current.resetCheats();
@@ -6400,7 +6400,7 @@ var useNostalgist = ({
6400
6400
  romFileName,
6401
6401
  shader
6402
6402
  }) => {
6403
- const isHeavySystem = React3.useMemo(() => {
6403
+ const isHeavySystem = React5.useMemo(() => {
6404
6404
  return PERFORMANCE_TIER_2_SYSTEMS.has(system.toUpperCase());
6405
6405
  }, [system]);
6406
6406
  const {
@@ -6477,7 +6477,7 @@ var useNostalgist = ({
6477
6477
  } = useEmulatorCheats({
6478
6478
  nostalgistRef
6479
6479
  });
6480
- const start = React3.useCallback(async () => {
6480
+ const start = React5.useCallback(async () => {
6481
6481
  await coreStart();
6482
6482
  setTimeout(() => {
6483
6483
  if (nostalgistRef.current) {
@@ -6485,11 +6485,11 @@ var useNostalgist = ({
6485
6485
  }
6486
6486
  }, 2e3);
6487
6487
  }, [coreStart, startRewindCapture, nostalgistRef]);
6488
- const stop = React3.useCallback(() => {
6488
+ const stop = React5.useCallback(() => {
6489
6489
  stopRewindCapture();
6490
6490
  coreStop();
6491
6491
  }, [stopRewindCapture, coreStop]);
6492
- const hookReturn = React3.useMemo(() => ({
6492
+ const hookReturn = React5.useMemo(() => ({
6493
6493
  status,
6494
6494
  error,
6495
6495
  isPaused,
@@ -6560,18 +6560,18 @@ function useVolume({
6560
6560
  setVolume: setVolumeInHook,
6561
6561
  toggleMute: toggleMuteInHook
6562
6562
  }) {
6563
- const [volume, setVolumeState] = React3.useState(() => loadVolume());
6564
- const [isMuted, setIsMutedState] = React3.useState(() => loadMuteState());
6565
- React3.useEffect(() => {
6563
+ const [volume, setVolumeState] = React5.useState(() => loadVolume());
6564
+ const [isMuted, setIsMutedState] = React5.useState(() => loadMuteState());
6565
+ React5.useEffect(() => {
6566
6566
  setVolumeInHook(volume);
6567
6567
  }, [setVolumeInHook]);
6568
- const setVolume = React3.useCallback((newVolume) => {
6568
+ const setVolume = React5.useCallback((newVolume) => {
6569
6569
  const clampedVolume = Math.max(0, Math.min(100, newVolume));
6570
6570
  setVolumeState(clampedVolume);
6571
6571
  saveVolume(clampedVolume);
6572
6572
  setVolumeInHook(clampedVolume);
6573
6573
  }, [setVolumeInHook]);
6574
- const toggleMute = React3.useCallback(() => {
6574
+ const toggleMute = React5.useCallback(() => {
6575
6575
  setIsMutedState((prev) => {
6576
6576
  const newMuted = !prev;
6577
6577
  saveMuteState(newMuted);
@@ -6588,22 +6588,22 @@ function useVolume({
6588
6588
  }
6589
6589
  function useControls(system, onNotify) {
6590
6590
  const defaultControls = getConsoleKeyboardDefaults(system || "SNES");
6591
- const [controls, setControls] = React3.useState(() => {
6591
+ const [controls, setControls] = React5.useState(() => {
6592
6592
  if (typeof window !== "undefined") {
6593
6593
  return loadKeyboardMapping(system);
6594
6594
  }
6595
6595
  return defaultControls;
6596
6596
  });
6597
- React3.useEffect(() => {
6597
+ React5.useEffect(() => {
6598
6598
  const loaded = loadKeyboardMapping(system);
6599
6599
  setControls(loaded);
6600
6600
  }, [system]);
6601
- const saveControls = React3.useCallback((newControls) => {
6601
+ const saveControls = React5.useCallback((newControls) => {
6602
6602
  setControls(newControls);
6603
6603
  saveKeyboardMapping(newControls, system);
6604
6604
  onNotify?.("Controls saved", "success");
6605
6605
  }, [system, onNotify]);
6606
- const resetToDefaults = React3.useCallback(() => {
6606
+ const resetToDefaults = React5.useCallback(() => {
6607
6607
  setControls(defaultControls);
6608
6608
  saveKeyboardMapping(defaultControls, system);
6609
6609
  onNotify?.("Controls reset to defaults", "info");
@@ -6633,8 +6633,8 @@ function useGameSession(props) {
6633
6633
  showToast
6634
6634
  } = props;
6635
6635
  const { controls, saveControls } = useControls(system, showToast);
6636
- const [gamepadModalOpen, setGamepadModalOpen] = React3.useState(false);
6637
- const [controlsModalOpen, setControlsModalOpen] = React3.useState(false);
6636
+ const [gamepadModalOpen, setGamepadModalOpen] = React5.useState(false);
6637
+ const [controlsModalOpen, setControlsModalOpen] = React5.useState(false);
6638
6638
  const { gamepads, connectedCount } = useGamepad({
6639
6639
  onConnect: (gamepad) => {
6640
6640
  showToast(
@@ -6661,7 +6661,7 @@ function useGameSession(props) {
6661
6661
  );
6662
6662
  }
6663
6663
  });
6664
- const gamepadBindings = React3.useMemo(() => {
6664
+ const gamepadBindings = React5.useMemo(() => {
6665
6665
  return [];
6666
6666
  }, [gamepads.length]);
6667
6667
  const nostalgist = useNostalgist({
@@ -6705,7 +6705,7 @@ function useGameSession(props) {
6705
6705
  toggleMute: toggleMuteInHook,
6706
6706
  prepare
6707
6707
  } = nostalgist;
6708
- React3.useEffect(() => {
6708
+ React5.useEffect(() => {
6709
6709
  return () => {
6710
6710
  if (status === "running" || status === "paused") {
6711
6711
  onSessionEnd?.();
@@ -6716,8 +6716,8 @@ function useGameSession(props) {
6716
6716
  setVolume: setVolumeInHook,
6717
6717
  toggleMute: toggleMuteInHook
6718
6718
  });
6719
- React3.useEffect(() => suppressEmulatorWarnings(), []);
6720
- React3.useEffect(() => {
6719
+ React5.useEffect(() => suppressEmulatorWarnings(), []);
6720
+ React5.useEffect(() => {
6721
6721
  if (!romUrl || !system || status !== "idle") return;
6722
6722
  const checkAndPrepare = async () => {
6723
6723
  if (canvasRef.current && canvasRef.current.isConnected) {
@@ -6729,7 +6729,7 @@ function useGameSession(props) {
6729
6729
  const rafId = requestAnimationFrame(checkAndPrepare);
6730
6730
  return () => cancelAnimationFrame(rafId);
6731
6731
  }, [romUrl, system, status, prepare]);
6732
- const hardcoreRestrictions = React3.useMemo(() => {
6732
+ const hardcoreRestrictions = React5.useMemo(() => {
6733
6733
  const isHardcore = !!retroAchievementsConfig?.hardcore;
6734
6734
  return {
6735
6735
  isHardcore,
@@ -6800,17 +6800,17 @@ function useAutoSave({
6800
6800
  queueRef,
6801
6801
  autoSaveInterval = 6e4
6802
6802
  }) {
6803
- const [autoSavePaused, setAutoSavePaused] = React3.useState(false);
6804
- const [autoSaveState, setAutoSaveState] = React3.useState("idle");
6805
- const [autoSaveProgress, setAutoSaveProgress] = React3.useState(0);
6806
- const onAutoSaveRef = React3.useRef(onAutoSave);
6807
- const nostalgistRef = React3.useRef(nostalgist);
6808
- React3.useEffect(() => {
6803
+ const [autoSavePaused, setAutoSavePaused] = React5.useState(false);
6804
+ const [autoSaveState, setAutoSaveState] = React5.useState("idle");
6805
+ const [autoSaveProgress, setAutoSaveProgress] = React5.useState(0);
6806
+ const onAutoSaveRef = React5.useRef(onAutoSave);
6807
+ const nostalgistRef = React5.useRef(nostalgist);
6808
+ React5.useEffect(() => {
6809
6809
  onAutoSaveRef.current = onAutoSave;
6810
6810
  nostalgistRef.current = nostalgist;
6811
6811
  }, [onAutoSave, nostalgist]);
6812
- const [loopTrigger, setLoopTrigger] = React3.useState(0);
6813
- React3.useEffect(() => {
6812
+ const [loopTrigger, setLoopTrigger] = React5.useState(0);
6813
+ React5.useEffect(() => {
6814
6814
  const currentNostalgist = nostalgist;
6815
6815
  if (!onAutoSave || !currentNostalgist || currentNostalgist.status !== "running" || autoSavePaused) {
6816
6816
  setAutoSaveState("idle");
@@ -6860,10 +6860,10 @@ function useAutoSave({
6860
6860
  clearTimeout(saveTimeoutId);
6861
6861
  };
6862
6862
  }, [nostalgist?.status, autoSavePaused, !!onAutoSave, loopTrigger, autoSaveInterval]);
6863
- const handleAutoSaveToggle = React3.useCallback(() => {
6863
+ const handleAutoSaveToggle = React5.useCallback(() => {
6864
6864
  setAutoSavePaused((prev) => !prev);
6865
6865
  }, []);
6866
- React3.useEffect(() => {
6866
+ React5.useEffect(() => {
6867
6867
  if (!onAutoSave || !nostalgist || nostalgist.status !== "running") return;
6868
6868
  const performEmergencySave = async () => {
6869
6869
  try {
@@ -6925,12 +6925,12 @@ function useGameSaves({
6925
6925
  onDeleteSaveState,
6926
6926
  autoSaveInterval
6927
6927
  }) {
6928
- const [saveModalOpen, setSaveModalOpen] = React3.useState(false);
6929
- const [saveModalMode, setSaveModalMode] = React3.useState("save");
6930
- const [saveSlots, setSaveSlots] = React3.useState([]);
6931
- const [isSlotLoading, setIsSlotLoading] = React3.useState(false);
6932
- const [actioningSlot, setActioningSlot] = React3.useState(null);
6933
- const queueRef = React3.useRef(new SaveQueue());
6928
+ const [saveModalOpen, setSaveModalOpen] = React5.useState(false);
6929
+ const [saveModalMode, setSaveModalMode] = React5.useState("save");
6930
+ const [saveSlots, setSaveSlots] = React5.useState([]);
6931
+ const [isSlotLoading, setIsSlotLoading] = React5.useState(false);
6932
+ const [actioningSlot, setActioningSlot] = React5.useState(null);
6933
+ const queueRef = React5.useRef(new SaveQueue());
6934
6934
  const {
6935
6935
  autoSaveEnabled,
6936
6936
  autoSavePaused,
@@ -6943,7 +6943,7 @@ function useGameSaves({
6943
6943
  queueRef,
6944
6944
  autoSaveInterval
6945
6945
  });
6946
- const refreshSlots = React3.useCallback(async () => {
6946
+ const refreshSlots = React5.useCallback(async () => {
6947
6947
  if (!onGetSaveSlots) return;
6948
6948
  setIsSlotLoading(true);
6949
6949
  try {
@@ -7115,8 +7115,8 @@ function useGameCheats({
7115
7115
  cheats = [],
7116
7116
  onToggleCheat
7117
7117
  }) {
7118
- const [cheatsModalOpen, setCheatsModalOpen] = React3.useState(false);
7119
- const [activeCheats, setActiveCheats] = React3.useState(/* @__PURE__ */ new Set());
7118
+ const [cheatsModalOpen, setCheatsModalOpen] = React5.useState(false);
7119
+ const [activeCheats, setActiveCheats] = React5.useState(/* @__PURE__ */ new Set());
7120
7120
  const handleToggleCheat = (cheatId) => {
7121
7121
  if (!nostalgist) return;
7122
7122
  const newActiveCheats = new Set(activeCheats);
@@ -7148,16 +7148,16 @@ function useGameCheats({
7148
7148
  function useGameRecording({
7149
7149
  getCanvasElement
7150
7150
  }) {
7151
- const [isRecording, setIsRecording] = React3.useState(false);
7152
- const [isPaused, setIsPaused] = React3.useState(false);
7153
- const [recordingDuration, setRecordingDuration] = React3.useState(0);
7154
- const mediaRecorderRef = React3.useRef(null);
7155
- const chunksRef = React3.useRef([]);
7156
- const startTimeRef = React3.useRef(0);
7157
- const pausedTimeRef = React3.useRef(0);
7158
- const durationIntervalRef = React3.useRef(null);
7151
+ const [isRecording, setIsRecording] = React5.useState(false);
7152
+ const [isPaused, setIsPaused] = React5.useState(false);
7153
+ const [recordingDuration, setRecordingDuration] = React5.useState(0);
7154
+ const mediaRecorderRef = React5.useRef(null);
7155
+ const chunksRef = React5.useRef([]);
7156
+ const startTimeRef = React5.useRef(0);
7157
+ const pausedTimeRef = React5.useRef(0);
7158
+ const durationIntervalRef = React5.useRef(null);
7159
7159
  const isSupported = typeof MediaRecorder !== "undefined" && MediaRecorder.isTypeSupported("video/webm");
7160
- const startRecording = React3.useCallback(() => {
7160
+ const startRecording = React5.useCallback(() => {
7161
7161
  const canvas = getCanvasElement();
7162
7162
  if (!canvas || !isSupported) {
7163
7163
  console.warn("[Recording] Canvas not found or MediaRecorder not supported");
@@ -7195,7 +7195,7 @@ function useGameRecording({
7195
7195
  console.error("[Recording] Failed to start:", err);
7196
7196
  }
7197
7197
  }, [getCanvasElement, isSupported, isPaused]);
7198
- const stopRecording = React3.useCallback(async () => {
7198
+ const stopRecording = React5.useCallback(async () => {
7199
7199
  return new Promise((resolve) => {
7200
7200
  const mediaRecorder = mediaRecorderRef.current;
7201
7201
  if (!mediaRecorder || mediaRecorder.state === "inactive") {
@@ -7217,7 +7217,7 @@ function useGameRecording({
7217
7217
  mediaRecorder.stop();
7218
7218
  });
7219
7219
  }, []);
7220
- const pauseRecording = React3.useCallback(() => {
7220
+ const pauseRecording = React5.useCallback(() => {
7221
7221
  const mediaRecorder = mediaRecorderRef.current;
7222
7222
  if (mediaRecorder && mediaRecorder.state === "recording") {
7223
7223
  mediaRecorder.pause();
@@ -7226,7 +7226,7 @@ function useGameRecording({
7226
7226
  console.log("[Recording] Paused");
7227
7227
  }
7228
7228
  }, []);
7229
- const resumeRecording = React3.useCallback(() => {
7229
+ const resumeRecording = React5.useCallback(() => {
7230
7230
  const mediaRecorder = mediaRecorderRef.current;
7231
7231
  if (mediaRecorder && mediaRecorder.state === "paused") {
7232
7232
  pausedTimeRef.current = Date.now() - pausedTimeRef.current;
@@ -7235,7 +7235,7 @@ function useGameRecording({
7235
7235
  console.log("[Recording] Resumed");
7236
7236
  }
7237
7237
  }, []);
7238
- React3.useEffect(() => {
7238
+ React5.useEffect(() => {
7239
7239
  return () => {
7240
7240
  if (mediaRecorderRef.current && mediaRecorderRef.current.state !== "inactive") {
7241
7241
  mediaRecorderRef.current.stop();
@@ -7409,9 +7409,9 @@ var DEFAULT_SETTINGS = {
7409
7409
  showInputDisplay: false
7410
7410
  };
7411
7411
  function usePlayerPersistence(onSettingsChange) {
7412
- const [settings, setSettings] = React3.useState(DEFAULT_SETTINGS);
7413
- const [isLoaded, setIsLoaded] = React3.useState(false);
7414
- React3.useEffect(() => {
7412
+ const [settings, setSettings] = React5.useState(DEFAULT_SETTINGS);
7413
+ const [isLoaded, setIsLoaded] = React5.useState(false);
7414
+ React5.useEffect(() => {
7415
7415
  try {
7416
7416
  const stored = localStorage.getItem(STORAGE_KEY2);
7417
7417
  if (stored) {
@@ -7423,7 +7423,7 @@ function usePlayerPersistence(onSettingsChange) {
7423
7423
  }
7424
7424
  setIsLoaded(true);
7425
7425
  }, []);
7426
- const updateSettings = React3.useCallback((updates) => {
7426
+ const updateSettings = React5.useCallback((updates) => {
7427
7427
  setSettings((prev) => {
7428
7428
  const next = { ...prev, ...updates };
7429
7429
  try {
@@ -7440,10 +7440,10 @@ function usePlayerPersistence(onSettingsChange) {
7440
7440
  updateSettings
7441
7441
  };
7442
7442
  }
7443
- var GamePlayer = React3.memo(function GamePlayer2(props) {
7443
+ var GamePlayer = React5.memo(function GamePlayer2(props) {
7444
7444
  const { settings, updateSettings, isLoaded: settingsLoaded } = usePlayerPersistence();
7445
- const [biosModalOpen, setBiosModalOpen] = React3.useState(false);
7446
- const [showShortcutsModal, setShowShortcutsModal] = React3.useState(false);
7445
+ const [biosModalOpen, setBiosModalOpen] = React5.useState(false);
7446
+ const [showShortcutsModal, setShowShortcutsModal] = React5.useState(false);
7447
7447
  const effectiveShader = props.shader !== void 0 ? props.shader : settings.shader;
7448
7448
  const {
7449
7449
  // Refs
@@ -7539,65 +7539,65 @@ var GamePlayer = React3.memo(function GamePlayer2(props) {
7539
7539
  status,
7540
7540
  isPerformanceMode
7541
7541
  } = nostalgist;
7542
- React3.useEffect(() => {
7542
+ React5.useEffect(() => {
7543
7543
  if (settingsLoaded) {
7544
7544
  setVolume(settings.volume);
7545
7545
  if (muted !== settings.muted) toggleMute();
7546
7546
  }
7547
7547
  }, [settingsLoaded]);
7548
7548
  const { system, systemColor = "#00FF41", cheats = [], onExit } = props;
7549
- const handlePauseToggle = React3.useCallback(() => {
7549
+ const handlePauseToggle = React5.useCallback(() => {
7550
7550
  status === "ready" ? start() : togglePause();
7551
7551
  }, [status, start, togglePause]);
7552
- const handleScreenshot = React3.useCallback(async () => {
7552
+ const handleScreenshot = React5.useCallback(async () => {
7553
7553
  const result = await screenshot();
7554
7554
  if (result && props.onScreenshotCaptured) {
7555
7555
  props.onScreenshotCaptured(result);
7556
7556
  }
7557
7557
  }, [screenshot, props.onScreenshotCaptured]);
7558
- const handleShowControls = React3.useCallback(() => {
7558
+ const handleShowControls = React5.useCallback(() => {
7559
7559
  pause();
7560
7560
  setControlsModalOpen(true);
7561
7561
  }, [pause, setControlsModalOpen]);
7562
- const handleShowCheats = React3.useCallback(() => {
7562
+ const handleShowCheats = React5.useCallback(() => {
7563
7563
  pause();
7564
7564
  setCheatsModalOpen(true);
7565
7565
  }, [pause, setCheatsModalOpen]);
7566
- const handleShowRA = React3.useCallback(() => {
7566
+ const handleShowRA = React5.useCallback(() => {
7567
7567
  pause();
7568
7568
  setRaSidebarOpen(true);
7569
7569
  }, [pause, setRaSidebarOpen]);
7570
- const handleShowGamepadSettings = React3.useCallback(() => {
7570
+ const handleShowGamepadSettings = React5.useCallback(() => {
7571
7571
  pause();
7572
7572
  setGamepadModalOpen(true);
7573
7573
  }, [pause, setGamepadModalOpen]);
7574
- const handleExitClick = React3.useCallback(() => {
7574
+ const handleExitClick = React5.useCallback(() => {
7575
7575
  onExit?.();
7576
7576
  }, [onExit]);
7577
- const handleBiosSelection = React3.useCallback(() => {
7577
+ const handleBiosSelection = React5.useCallback(() => {
7578
7578
  setBiosModalOpen(true);
7579
7579
  }, [setBiosModalOpen]);
7580
- const handleVolumeChange = React3.useCallback((val) => {
7580
+ const handleVolumeChange = React5.useCallback((val) => {
7581
7581
  setVolume(val);
7582
7582
  updateSettings({ volume: val });
7583
7583
  }, [setVolume, updateSettings]);
7584
- const handleToggleMute = React3.useCallback(() => {
7584
+ const handleToggleMute = React5.useCallback(() => {
7585
7585
  toggleMute();
7586
7586
  updateSettings({ muted: !muted });
7587
7587
  }, [toggleMute, updateSettings, muted]);
7588
- const handleShaderChange = React3.useCallback((newShader, requiresRestart) => {
7588
+ const handleShaderChange = React5.useCallback((newShader, requiresRestart) => {
7589
7589
  updateSettings({ shader: newShader });
7590
7590
  if (props.onShaderChange) {
7591
7591
  props.onShaderChange(newShader, requiresRestart);
7592
7592
  }
7593
7593
  }, [updateSettings, props.onShaderChange]);
7594
- const handleTogglePerformanceOverlay = React3.useCallback(() => {
7594
+ const handleTogglePerformanceOverlay = React5.useCallback(() => {
7595
7595
  updateSettings({ showPerformanceOverlay: !settings.showPerformanceOverlay });
7596
7596
  }, [updateSettings, settings.showPerformanceOverlay]);
7597
- const handleToggleInputDisplay = React3.useCallback(() => {
7597
+ const handleToggleInputDisplay = React5.useCallback(() => {
7598
7598
  updateSettings({ showInputDisplay: !settings.showInputDisplay });
7599
7599
  }, [updateSettings, settings.showInputDisplay]);
7600
- const handleToggleRecording = React3.useCallback(async () => {
7600
+ const handleToggleRecording = React5.useCallback(async () => {
7601
7601
  if (!recordingSupported) {
7602
7602
  console.warn("[Recording] Not supported in this browser");
7603
7603
  return;
@@ -7618,14 +7618,14 @@ var GamePlayer = React3.memo(function GamePlayer2(props) {
7618
7618
  startRecording();
7619
7619
  }
7620
7620
  }, [isRecording, recordingSupported, startRecording, stopRecording]);
7621
- const handleToggleShortcuts = React3.useCallback(() => {
7621
+ const handleToggleShortcuts = React5.useCallback(() => {
7622
7622
  setShowShortcutsModal((prev) => {
7623
7623
  if (!prev) pause();
7624
7624
  else resume();
7625
7625
  return !prev;
7626
7626
  });
7627
7627
  }, [pause, resume]);
7628
- React3.useEffect(() => {
7628
+ React5.useEffect(() => {
7629
7629
  const handleKeyDown = (e) => {
7630
7630
  if (e.key === "F1") {
7631
7631
  e.preventDefault();
@@ -7870,9 +7870,9 @@ function AchievementPopup({
7870
7870
  onDismiss,
7871
7871
  autoDismissMs = 5e3
7872
7872
  }) {
7873
- const [isVisible, setIsVisible] = React3.useState(false);
7874
- const [isExiting, setIsExiting] = React3.useState(false);
7875
- React3.useEffect(() => {
7873
+ const [isVisible, setIsVisible] = React5.useState(false);
7874
+ const [isExiting, setIsExiting] = React5.useState(false);
7875
+ React5.useEffect(() => {
7876
7876
  requestAnimationFrame(() => {
7877
7877
  setIsVisible(true);
7878
7878
  });
@@ -7949,15 +7949,15 @@ var SHADER_PRESETS = [
7949
7949
  { id: "handheld/lcd-grid-v2", name: "LCD Grid", description: "Game Boy style LCD effect" },
7950
7950
  { id: "scanlines", name: "Scanlines", description: "Simple horizontal scanlines" }
7951
7951
  ];
7952
- var ShaderSelector = React3.memo(function ShaderSelector2({
7952
+ var ShaderSelector = React5.memo(function ShaderSelector2({
7953
7953
  currentShader,
7954
7954
  onShaderChange,
7955
7955
  disabled = false,
7956
7956
  systemColor = "#00FF41"
7957
7957
  }) {
7958
- const [isOpen, setIsOpen] = React3.useState(false);
7959
- const dropdownRef = React3.useRef(null);
7960
- React3.useEffect(() => {
7958
+ const [isOpen, setIsOpen] = React5.useState(false);
7959
+ const dropdownRef = React5.useRef(null);
7960
+ React5.useEffect(() => {
7961
7961
  const handleClickOutside = (e) => {
7962
7962
  if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
7963
7963
  setIsOpen(false);
@@ -8031,11 +8031,11 @@ var SHORTCUTS2 = [
8031
8031
  { key: "F5", description: "Record" },
8032
8032
  { key: "F9", description: "Mute" }
8033
8033
  ];
8034
- var ShortcutsReference = React3.memo(function ShortcutsReference2({
8034
+ var ShortcutsReference = React5.memo(function ShortcutsReference2({
8035
8035
  systemColor = "#00FF41",
8036
8036
  isExpanded: initialExpanded = false
8037
8037
  }) {
8038
- const [isExpanded, setIsExpanded] = React3.useState(initialExpanded);
8038
+ const [isExpanded, setIsExpanded] = React5.useState(initialExpanded);
8039
8039
  return /* @__PURE__ */ jsxRuntime.jsxs(
8040
8040
  "div",
8041
8041
  {