Default cursor is not being displayed on top of the custom one upon
exiting fullscreen Added package-lock file so running code does not contain any vulnerabilities anymore Snake game also dynamically changes sized when fullscreen just like the other games do Invert glow effect colour on Snake as it had broken logic
This commit is contained in:
Generated
+18
-18
@@ -2342,9 +2342,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@remix-run/router": {
|
"node_modules/@remix-run/router": {
|
||||||
"version": "1.23.0",
|
"version": "1.23.2",
|
||||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz",
|
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz",
|
||||||
"integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==",
|
"integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
@@ -6042,9 +6042,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.23",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
|
||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/lodash.castarray": {
|
"node_modules/lodash.castarray": {
|
||||||
@@ -6977,9 +6977,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/qs": {
|
"node_modules/qs": {
|
||||||
"version": "6.14.0",
|
"version": "6.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
|
||||||
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
|
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -7157,12 +7157,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "6.30.1",
|
"version": "6.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz",
|
||||||
"integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==",
|
"integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/router": "1.23.0"
|
"@remix-run/router": "1.23.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
@@ -7172,13 +7172,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router-dom": {
|
"node_modules/react-router-dom": {
|
||||||
"version": "6.30.1",
|
"version": "6.30.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz",
|
||||||
"integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==",
|
"integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/router": "1.23.0",
|
"@remix-run/router": "1.23.2",
|
||||||
"react-router": "6.30.1"
|
"react-router": "6.30.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
|
|||||||
@@ -74,7 +74,13 @@ const MatrixCursor = () => {
|
|||||||
document.removeEventListener('mouseenter', handleMouseEnter);
|
document.removeEventListener('mouseenter', handleMouseEnter);
|
||||||
document.removeEventListener('mouseleave', handleMouseLeave);
|
document.removeEventListener('mouseleave', handleMouseLeave);
|
||||||
document.removeEventListener('touchstart', handleTouch);
|
document.removeEventListener('touchstart', handleTouch);
|
||||||
document.body.classList.remove('matrix-cursor');
|
|
||||||
|
// Only remove cursor class if no other MatrixCursor components are mounted
|
||||||
|
// This prevents the cursor from showing when exiting fullscreen
|
||||||
|
const otherCursors = document.querySelectorAll('.matrix-cursor-crosshair');
|
||||||
|
if (otherCursors.length === 0) {
|
||||||
|
document.body.classList.remove('matrix-cursor');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}, [isTouchDevice]);
|
}, [isTouchDevice]);
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { motion, AnimatePresence } from 'framer-motion';
|
|||||||
import { Settings, Monitor, Volume2, Cpu, X, Contrast, Binary, Smartphone } from 'lucide-react';
|
import { Settings, Monitor, Volume2, Cpu, X, Contrast, Binary, Smartphone } from 'lucide-react';
|
||||||
import { useSettings, MobileControlMode } from '@/contexts/SettingsContext';
|
import { useSettings, MobileControlMode } from '@/contexts/SettingsContext';
|
||||||
import { useAchievements } from '@/contexts/AchievementsContext';
|
import { useAchievements } from '@/contexts/AchievementsContext';
|
||||||
|
import { useIsMobile } from '@/hooks/use-mobile';
|
||||||
import CryptoConsentModal from './CryptoConsentModal';
|
import CryptoConsentModal from './CryptoConsentModal';
|
||||||
|
|
||||||
interface SettingsPanelProps {
|
interface SettingsPanelProps {
|
||||||
@@ -15,6 +16,7 @@ const SettingsPanel = ({ onToggleTheme, isRedTheme }: SettingsPanelProps) => {
|
|||||||
const [showCryptoModal, setShowCryptoModal] = useState(false);
|
const [showCryptoModal, setShowCryptoModal] = useState(false);
|
||||||
const { crtEnabled, setCrtEnabled, matrixEnabled, setMatrixEnabled, soundEnabled, setSoundEnabled, cryptoConsent, playSound, mobileControlMode, setMobileControlMode } = useSettings();
|
const { crtEnabled, setCrtEnabled, matrixEnabled, setMatrixEnabled, soundEnabled, setSoundEnabled, cryptoConsent, playSound, mobileControlMode, setMobileControlMode } = useSettings();
|
||||||
const { unlockAchievement } = useAchievements();
|
const { unlockAchievement } = useAchievements();
|
||||||
|
const isMobile = useIsMobile();
|
||||||
|
|
||||||
const handleToggle = (setter: (value: boolean) => void, currentValue: boolean, achievementId?: string) => {
|
const handleToggle = (setter: (value: boolean) => void, currentValue: boolean, achievementId?: string) => {
|
||||||
playSound('click');
|
playSound('click');
|
||||||
@@ -156,18 +158,20 @@ const SettingsPanel = ({ onToggleTheme, isRedTheme }: SettingsPanelProps) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Mobile Controls Mode */}
|
{/* Mobile Controls Mode */}
|
||||||
<div className="flex items-center justify-between">
|
{isMobile && (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center justify-between">
|
||||||
<Smartphone size={16} className="text-primary" />
|
<div className="flex items-center gap-2">
|
||||||
<span className="font-pixel text-sm text-foreground/90">Mobile Controls</span>
|
<Smartphone size={16} className="text-primary" />
|
||||||
|
<span className="font-pixel text-sm text-foreground/90">Game Controls (for touch devices)</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={handleMobileControlToggle}
|
||||||
|
className="px-3 py-1 text-xs font-pixel border border-primary transition-all duration-300 bg-transparent text-primary hover:bg-primary hover:text-background"
|
||||||
|
>
|
||||||
|
{mobileControlMode === 'buttons' ? 'BUTTONS' : 'SWIPE'}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button
|
)}
|
||||||
onClick={handleMobileControlToggle}
|
|
||||||
className="px-3 py-1 text-xs font-pixel border border-primary transition-all duration-300 bg-transparent text-primary hover:bg-primary hover:text-background"
|
|
||||||
>
|
|
||||||
{mobileControlMode === 'buttons' ? 'BUTTONS' : 'SWIPE'}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-4 pt-4 border-t border-primary/30">
|
<div className="mt-4 pt-4 border-t border-primary/30">
|
||||||
|
|||||||
+2
-2
@@ -568,7 +568,7 @@ const Snake = () => {
|
|||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<button onClick={() => { setGameMode(null); setGameStarted(false); }} className="font-pixel text-sm text-foreground/50 hover:text-primary transition-colors">{'<'} Back</button>
|
<button onClick={() => { setGameMode(null); setGameStarted(false); }} className="font-pixel text-sm text-foreground/50 hover:text-primary transition-colors">{'<'} Back</button>
|
||||||
<h1 className="font-minecraft text-2xl md:text-3xl text-primary text-glow-strong">
|
<h1 className="font-minecraft text-2xl md:text-3xl text-primary text-glow-strong">
|
||||||
Snake {gameMode === '2p' && <span className="text-secondary">2P</span>}
|
Snake {gameMode === '2p' && <span className="text-secondary" style={{ textShadow: '0 0 10px hsl(var(--secondary) / 0.8), 0 0 20px hsl(var(--secondary) / 0.4)' }}>2P</span>}
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<button onClick={toggleFullscreen} className="p-2 border border-primary/50 hover:bg-primary/20 transition-colors" title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}>
|
<button onClick={toggleFullscreen} className="p-2 border border-primary/50 hover:bg-primary/20 transition-colors" title={isFullscreen ? 'Exit fullscreen' : 'Fullscreen'}>
|
||||||
@@ -768,4 +768,4 @@ const Snake = () => {
|
|||||||
: gameUi;
|
: gameUi;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Snake;
|
export default Snake;
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ const Tetris = () => {
|
|||||||
const availableHeight = window.innerHeight - 120;
|
const availableHeight = window.innerHeight - 120;
|
||||||
const cellFromWidth = Math.floor(availableWidth / (gameMode === '2p' ? BOARD_WIDTH * 2 + 4 : BOARD_WIDTH));
|
const cellFromWidth = Math.floor(availableWidth / (gameMode === '2p' ? BOARD_WIDTH * 2 + 4 : BOARD_WIDTH));
|
||||||
const cellFromHeight = Math.floor(availableHeight / BOARD_HEIGHT);
|
const cellFromHeight = Math.floor(availableHeight / BOARD_HEIGHT);
|
||||||
return Math.min(cellFromWidth, cellFromHeight, gameMode === '2p' ? 32 : 40);
|
return Math.min(cellFromWidth, cellFromHeight);
|
||||||
}
|
}
|
||||||
if (gameMode === '2p') return 22;
|
if (gameMode === '2p') return 22;
|
||||||
return 28;
|
return 28;
|
||||||
@@ -508,7 +508,7 @@ const Tetris = () => {
|
|||||||
{nextP.shape.map((row, y) => (
|
{nextP.shape.map((row, y) => (
|
||||||
<div key={y} className="flex gap-1">
|
<div key={y} className="flex gap-1">
|
||||||
{row.map((val, x) => (
|
{row.map((val, x) => (
|
||||||
<div key={`${y}-${x}`} className={`w-4 h-4`} style={{ backgroundColor: val ? nextP.color : 'transparent', boxShadow: val ? `0 0 5px ${nextP.color}` : 'none' }} />
|
<div key={`${y}-${x}`} style={{ width: cellSize * 0.6, height: cellSize * 0.6, backgroundColor: val ? nextP.color : 'transparent', boxShadow: val ? `0 0 5px ${nextP.color}` : 'none' }} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
Reference in New Issue
Block a user