Private
Public Access
1
0

chg: dev: use namespaces for front-end #4

This commit is contained in:
2026-04-10 21:53:50 +02:00
parent c660c13ea2
commit 5b55a6ce73
18 changed files with 208 additions and 34 deletions

View File

@@ -1,6 +1,14 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import React from 'react'; import React from 'react';
import { createRoot } from 'react-dom/client'; import { createRoot } from 'react-dom/client';
import MineSeeker from './mine-seeker/MineSeeker'; import MineSeeker from './mine-seeker/MineSeeker';
const wrapper = document.getElementById('mine-wrapper'); const wrapper = document.getElementById('mine-wrapper');

View File

@@ -1,7 +1,16 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import React, { useRef } from 'react'; import React, { useRef } from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { GameProvider } from './contexts/GameProvider'; import { GameProvider } from '@mine-contexts';
import { GameBoard } from './components/GameBoard'; import { GameBoard } from '@mine-components';
const queryClient = new QueryClient(); const queryClient = new QueryClient();

View File

@@ -1,4 +1,4 @@
/* /**
* This file is part of the SplendidBear Websites' projects. * This file is part of the SplendidBear Websites' projects.
* *
* Copyright (c) 2026 @ www.splendidbear.org * Copyright (c) 2026 @ www.splendidbear.org
@@ -8,8 +8,8 @@
*/ */
import React from 'react'; import React from 'react';
import { useGame } from '../contexts/GameContext'; import { useGame } from '@mine-contexts';
import useServerCommunication from '../hooks/useServerCommunication'; import { useServerCommunication } from '@mine-hooks';
import GridControl from './grid/GridControl'; import GridControl from './grid/GridControl';
export const GameBoard = ({ gameAssoc, gameInherited, isEnvDev }) => { export const GameBoard = ({ gameAssoc, gameInherited, isEnvDev }) => {

View File

@@ -1,8 +1,17 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import React from 'react'; import React from 'react';
import { useGame } from '../../contexts/GameContext'; import { useGame } from '@mine-contexts';
import GridField from './GridField'; import GridField from './GridField';
import UserControl from '../user/UserControl'; import UserControl from '../user/UserControl';
import { BOMB_SYMBOLS, bombRadius } from '../../utils/constants'; import { BOMB_SYMBOLS, bombRadius } from '@mine-utils';
const GridControl = ({ onClick, resign }) => { const GridControl = ({ onClick, resign }) => {
const { const {

View File

@@ -1,5 +1,14 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import React, { memo } from 'react'; import React, { memo } from 'react';
import { IMAGES } from '../../utils/constants'; import { IMAGES } from '@mine-utils';
const bombSrc = area => { const bombSrc = area => {
if (null === area) return null; if (null === area) return null;

View File

@@ -0,0 +1,14 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
export { GameBoard } from './GameBoard';
export { default as GridControl } from './grid/GridControl';
export { default as GridField } from './grid/GridField';
export { default as User } from './user/User';
export { default as UserControl } from './user/UserControl';

View File

@@ -1,17 +1,28 @@
import React, { memo } from 'react'; /**
import { IMAGES } from '../../utils/constants'; * This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
const User = memo(function User({ import React, { memo } from 'react';
color, import { IMAGES } from '@mine-utils';
webPlayer,
name, const User = memo(function User(
desc, {
active, color,
mines, webPlayer,
haveBomb, name,
enabledBomb, desc,
onClickBombSelector, active,
}) { mines,
haveBomb,
enabledBomb,
onClickBombSelector,
},
) {
const buzzClass = 'bomb-container' const buzzClass = 'bomb-container'
+ (active && color === webPlayer && haveBomb && enabledBomb ? ' buzz' : ''); + (active && color === webPlayer && haveBomb && enabledBomb ? ' buzz' : '');

View File

@@ -1,5 +1,14 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import React from 'react'; import React from 'react';
import { useGame } from '../../contexts/GameContext'; import { useGame } from '@mine-contexts';
import User from './User'; import User from './User';
const UserControl = ({ resign }) => { const UserControl = ({ resign }) => {

View File

@@ -1,3 +1,12 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import { createContext, useContext } from 'react'; import { createContext, useContext } from 'react';
const GameContext = createContext(null); const GameContext = createContext(null);

View File

@@ -1,9 +1,17 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import React, { useRef } from 'react'; import React, { useRef } from 'react';
import { Howl } from 'howler'; import { Howl } from 'howler';
import GameContext from './GameContext'; import GameContext from './GameContext';
import useGameRefs from '../hooks/useGameRefs'; import { useGameRefs, useGameState } from '@mine-hooks';
import useGameState from '../hooks/useGameState'; import { DESC, IMAGES, patchCells } from '@mine-utils';
import { DESC, IMAGES, patchCells } from '../utils/constants';
export const GameProvider = ({ children }) => { export const GameProvider = ({ children }) => {
const { const {
@@ -41,7 +49,8 @@ export const GameProvider = ({ children }) => {
won: new Howl({ src: ['/sound/won.mp3'] }), won: new Howl({ src: ['/sound/won.mp3'] }),
}); });
// ── Sync helpers (keep ref + state in lockstep) ────────────────────────── /** Sync helpers (keep ref + state in lockstep) */
const syncWebPlayer = v => { const syncWebPlayer = v => {
webPlayerRef.current = v; webPlayerRef.current = v;
setWebPlayer(v); setWebPlayer(v);
@@ -69,7 +78,8 @@ export const GameProvider = ({ children }) => {
setBlue(n); setBlue(n);
}; };
// ── Overlay ─────────────────────────────────────────────────────────────── /** Overlay */
const showOverlay = (title, sub) => { const showOverlay = (title, sub) => {
setOverlay(true); setOverlay(true);
setOverlayTitle(title); setOverlayTitle(title);
@@ -78,7 +88,8 @@ export const GameProvider = ({ children }) => {
const hideOverlay = () => setOverlay(false); const hideOverlay = () => setOverlay(false);
// ── Cell helpers ────────────────────────────────────────────────────────── /** Cell helpers */
const applyRevealedCell = (cell, player, isMainCell = false) => { const applyRevealedCell = (cell, player, isMainCell = false) => {
const { row, col, value } = cell; const { row, col, value } = cell;
setCells(prev => { setCells(prev => {
@@ -105,7 +116,8 @@ export const GameProvider = ({ children }) => {
}); });
}; };
// ── Game logic ──────────────────────────────────────────────────────────── /** Game logic */
const changePlayer = () => { const changePlayer = () => {
const wasColor = activePlayerRef.current ? 'blue' : 'red'; const wasColor = activePlayerRef.current ? 'blue' : 'red';
const nextColor = activePlayerRef.current ? 'red' : 'blue'; const nextColor = activePlayerRef.current ? 'red' : 'blue';

View File

@@ -0,0 +1,13 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
export { useGame } from './GameContext';
export { GameProvider } from './GameProvider';
export { default as GameContext } from './GameContext';

View File

@@ -0,0 +1,13 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
export { default as useGameRefs } from './useGameRefs';
export { default as useGameState } from './useGameState';
export { default as useServerCommunication } from './useServerCommunication';

View File

@@ -1,5 +1,14 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import { useRef } from 'react'; import { useRef } from 'react';
import { PLAYER_DEF } from '../utils/constants'; import { PLAYER_DEF } from '@mine-utils';
const useGameRefs = () => { const useGameRefs = () => {
const webPlayerRef = useRef(null); const webPlayerRef = useRef(null);

View File

@@ -1,5 +1,14 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import { useState } from 'react'; import { useState } from 'react';
import { initCells, PLAYER_DEF } from '../utils/constants'; import { initCells, PLAYER_DEF } from '@mine-utils';
const useGameState = () => { const useGameState = () => {
const [webPlayer, setWebPlayer] = useState(null); const [webPlayer, setWebPlayer] = useState(null);

View File

@@ -1,7 +1,16 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import React, { useEffect, useRef } from 'react'; import React, { useEffect, useRef } from 'react';
import { useMutation, useQuery } from '@tanstack/react-query'; import { useMutation, useQuery } from '@tanstack/react-query';
import { useGame } from '../contexts/GameContext'; import { useGame } from '@mine-contexts';
import { DESC } from '../utils/constants'; import { DESC } from '@mine-utils';
/** Handles all server communication: SSE (Mercure), REST calls, and the initialization lifecycle. */ /** Handles all server communication: SSE (Mercure), REST calls, and the initialization lifecycle. */
const useServerCommunication = (gameAssoc, gameInherited, isEnvDev) => { const useServerCommunication = (gameAssoc, gameInherited, isEnvDev) => {

View File

@@ -1,3 +1,12 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import React from 'react'; import React from 'react';
export const ROWS = 16; export const ROWS = 16;

View File

@@ -0,0 +1,10 @@
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2026 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
export { DESC, IMAGES, BOMB_SYMBOLS, PLAYER_DEF, bombRadius, initCells, patchCells } from './constants';

View File

@@ -1,12 +1,24 @@
import { defineConfig } from 'vite'; import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react'; import react from '@vitejs/plugin-react';
import symfonyPlugin from 'vite-plugin-symfony'; import symfonyPlugin from 'vite-plugin-symfony';
import { fileURLToPath } from 'url';
import { dirname, resolve } from 'path';
const __dirname = dirname(fileURLToPath(import.meta.url));
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
react(), react(),
symfonyPlugin({ refresh: true }), symfonyPlugin({ refresh: true }),
], ],
resolve: {
alias: {
'@mine-components': resolve(__dirname, './assets/js/mine-seeker/components'),
'@mine-contexts': resolve(__dirname, './assets/js/mine-seeker/contexts'),
'@mine-hooks': resolve(__dirname, './assets/js/mine-seeker/hooks'),
'@mine-utils': resolve(__dirname, './assets/js/mine-seeker/utils'),
},
},
build: { build: {
rollupOptions: { rollupOptions: {
input: { input: {