chg: dev: use namespaces for front-end #4
This commit is contained in:
@@ -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');
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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 }) => {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
14
assets/js/mine-seeker/components/index.js
Normal file
14
assets/js/mine-seeker/components/index.js
Normal 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';
|
||||||
@@ -1,7 +1,17 @@
|
|||||||
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';
|
||||||
|
import { IMAGES } from '@mine-utils';
|
||||||
|
|
||||||
|
const User = memo(function User(
|
||||||
|
{
|
||||||
color,
|
color,
|
||||||
webPlayer,
|
webPlayer,
|
||||||
name,
|
name,
|
||||||
@@ -11,7 +21,8 @@ const User = memo(function User({
|
|||||||
haveBomb,
|
haveBomb,
|
||||||
enabledBomb,
|
enabledBomb,
|
||||||
onClickBombSelector,
|
onClickBombSelector,
|
||||||
}) {
|
},
|
||||||
|
) {
|
||||||
const buzzClass = 'bomb-container'
|
const buzzClass = 'bomb-container'
|
||||||
+ (active && color === webPlayer && haveBomb && enabledBomb ? ' buzz' : '');
|
+ (active && color === webPlayer && haveBomb && enabledBomb ? ' buzz' : '');
|
||||||
|
|
||||||
|
|||||||
@@ -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 }) => {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
13
assets/js/mine-seeker/contexts/index.js
Normal file
13
assets/js/mine-seeker/contexts/index.js
Normal 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';
|
||||||
|
|
||||||
13
assets/js/mine-seeker/hooks/index.js
Normal file
13
assets/js/mine-seeker/hooks/index.js
Normal 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';
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
10
assets/js/mine-seeker/utils/index.js
Normal file
10
assets/js/mine-seeker/utils/index.js
Normal 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';
|
||||||
@@ -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: {
|
||||||
|
|||||||
Reference in New Issue
Block a user