Merge pull request #27 from Vikeo/tailwind-wip

Tailwind wip
This commit is contained in:
Viktor Rådberg
2023-12-27 19:56:38 +01:00
committed by GitHub
17 changed files with 7408 additions and 274 deletions

View File

@@ -27,17 +27,22 @@
"devDependencies": { "devDependencies": {
"@emotion/react": "^11.11.1", "@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0", "@emotion/styled": "^11.11.0",
"@savvywombat/tailwindcss-grid-areas": "^3.1.0",
"@svgr/cli": "^8.1.0", "@svgr/cli": "^8.1.0",
"@types/react": "^18.2.15", "@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7", "@types/react-dom": "^18.2.7",
"@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0", "@typescript-eslint/parser": "^6.0.0",
"@vitejs/plugin-react-swc": "^3.3.2", "@vitejs/plugin-react-swc": "^3.3.2",
"autoprefixer": "^10.4.16",
"eslint": "^8.45.0", "eslint": "^8.45.0",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3", "eslint-plugin-react-refresh": "^0.4.3",
"firebase-tools": "^12.5.2", "firebase-tools": "^12.5.2",
"install": "^0.13.0",
"postcss": "^8.4.32",
"prettier": "2.8.8", "prettier": "2.8.8",
"tailwindcss": "^3.4.0",
"typescript": "^5.0.2", "typescript": "^5.0.2",
"vite": "^4.4.5" "vite": "^4.4.5"
} }

6
postcss.config.js Normal file
View File

@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View File

@@ -151,6 +151,7 @@ const Health = ({
const textContainer = textContainerRef.current; const textContainer = textContainerRef.current;
const resizeObserver = new ResizeObserver(() => { const resizeObserver = new ResizeObserver(() => {
const calcFontSize = calculateFontSize(textContainer); const calcFontSize = calculateFontSize(textContainer);
console.log(calcFontSize);
setFontSize(calcFontSize); setFontSize(calcFontSize);
}); });
@@ -180,9 +181,9 @@ const Health = ({
const minRatio = Math.min(widthRatio, heightRatio); const minRatio = Math.min(widthRatio, heightRatio);
const heightIsLarger = heightRatio > widthRatio; const heightIs40PercentSmaller = heightRatio > widthRatio * 0.6;
const scaleFactor = heightIsLarger ? 0.8 : 1; const scaleFactor = heightIs40PercentSmaller ? 0.8 : 1;
return minRatio * scaleFactor * 1; return minRatio * scaleFactor * 1;
}; };

View File

@@ -6,7 +6,7 @@ import { LoseGameButton } from '../Buttons/LoseButton';
import SettingsButton from '../Buttons/SettingsButton'; import SettingsButton from '../Buttons/SettingsButton';
import CommanderDamageBar from '../Counters/CommanderDamageBar'; import CommanderDamageBar from '../Counters/CommanderDamageBar';
import ExtraCountersBar from '../Counters/ExtraCountersBar'; import ExtraCountersBar from '../Counters/ExtraCountersBar';
import PlayerMenu from '../PlayerMenu/PlayerMenu'; import PlayerMenu from '../Player/PlayerMenu';
import Health from './Health'; import Health from './Health';
import { usePlayers } from '../../Hooks/usePlayers'; import { usePlayers } from '../../Hooks/usePlayers';
import { useGlobalSettings } from '../../Hooks/useGlobalSettings'; import { useGlobalSettings } from '../../Hooks/useGlobalSettings';

View File

@@ -1,7 +1,7 @@
import styled from 'styled-components'; import styled from 'styled-components';
import Play from './Views/Play';
import StartMenu from './Views/StartMenu/StartMenu';
import { useGlobalSettings } from '../Hooks/useGlobalSettings'; import { useGlobalSettings } from '../Hooks/useGlobalSettings';
import StartMenu from './Views/StartMenu/StartMenu';
import { Play } from './Views/Play';
const StartWrapper = styled.div` const StartWrapper = styled.div`
max-width: fit-content; max-width: fit-content;
@@ -35,7 +35,7 @@ export const LifeTrinket = () => {
<> <>
{showPlay && initialGameSettings ? ( {showPlay && initialGameSettings ? (
<PlayWrapper> <PlayWrapper>
<Play gridAreas={initialGameSettings?.gridAreas} /> <Play />
<EmergencyResetButton onClick={goToStart}> <EmergencyResetButton onClick={goToStart}>
<p>If you can see this, something is wrong.</p> <p>If you can see this, something is wrong.</p>
<p>Press screen to go to start.</p> <p>Press screen to go to start.</p>

View File

@@ -0,0 +1,47 @@
import LifeCounter from '../LifeCounter/LifeCounter';
import { Player as PlayerType } from '../../Types/Player';
const getGridArea = (player: PlayerType) => {
switch (player.index) {
case 0:
return 'grid-in-player0';
case 1:
return 'grid-in-player1';
case 2:
return 'grid-in-player2';
case 3:
return 'grid-in-player3';
case 4:
return 'grid-in-player4';
case 5:
return 'grid-in-player5';
default:
throw new Error('Invalid player index');
}
};
export const Player = (players: PlayerType[], gridClasses: string) => {
return (
<div className="w-full h-full bg-black">
<div className={`grid w-full h-full gap-1 box-border ${gridClasses} `}>
{players.map((player) => {
const gridArea = getGridArea(player);
return (
<div
key={player.index}
className={`flex justify-center items-center align-middle ${gridArea}`}
>
<LifeCounter
player={player}
opponents={players.filter(
(opponent) => opponent.index !== player.index
)}
/>
</div>
);
})}
</div>
</div>
);
};

View File

@@ -1,5 +1,8 @@
import styled from 'styled-components'; import styled from 'styled-components';
import Counters from '../Counters/Counters'; import { useGlobalSettings } from '../../Hooks/useGlobalSettings';
import { usePlayers } from '../../Hooks/usePlayers';
import { Orientation } from '../../Types/Settings';
import { Player } from '../Player/Player';
const MainWrapper = styled.div` const MainWrapper = styled.div`
width: 100vmax; width: 100vmax;
@@ -9,16 +12,62 @@ const MainWrapper = styled.div`
overflow: hidden; overflow: hidden;
`; `;
type PlayProps = { export const Play = () => {
gridAreas: string; const { players } = usePlayers();
}; const { initialGameSettings } = useGlobalSettings();
const Play = ({ gridAreas }: PlayProps) => { let Layout: JSX.Element;
return ( switch (players.length) {
<MainWrapper> case 1:
<Counters gridAreas={gridAreas} /> if (initialGameSettings?.orientation === Orientation.Portrait) {
</MainWrapper> Layout = Player(players, 'grid-areas-onePlayerPortrait');
); }
}; Layout = Player(players, 'grid-areas-onePlayerLandscape');
break;
case 2:
switch (initialGameSettings?.orientation) {
case Orientation.Portrait:
Layout = Player(players, 'grid-areas-twoPlayersOppositePortrait');
break;
default:
case Orientation.Landscape:
Layout = Player(players, 'grid-areas-twoPlayersSameSideLandscape');
break;
case Orientation.OppositeLandscape:
Layout = Player(players, 'grid-areas-twoPlayersOppositeLandscape');
break;
}
break;
case 3:
if (initialGameSettings?.orientation === Orientation.Portrait) {
Layout = Player(players, 'grid-areas-threePlayersSide');
break;
}
Layout = Player(players, 'grid-areas-threePlayers');
break;
default:
case 4:
if (initialGameSettings?.orientation === Orientation.Portrait) {
Layout = Player(players, 'grid-areas-fourPlayerPortrait');
break;
}
Layout = Player(players, 'grid-areas-fourPlayer');
break;
case 5:
if (initialGameSettings?.orientation === Orientation.Portrait) {
Layout = Player(players, 'grid-areas-fivePlayersSide');
break;
}
Layout = Player(players, 'grid-areas-fivePlayers');
break;
case 6:
if (initialGameSettings?.orientation === Orientation.Portrait) {
Layout = Player(players, 'grid-areas-sixPlayersSide');
break;
}
Layout = Player(players, 'grid-areas-sixPlayers');
break;
}
export default Play; return <MainWrapper>{Layout}</MainWrapper>;
};

View File

@@ -1,21 +1,22 @@
import { FormControlLabel, Radio, RadioGroup } from '@mui/material';
import React from 'react'; import React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { GridTemplateAreas } from '../../../Data/GridTemplateAreas';
import { FormControlLabel, Radio, RadioGroup } from '@mui/material';
import { theme } from '../../../Data/theme'; import { theme } from '../../../Data/theme';
import { import {
OnePlayerPortrait, FivePlayers,
TwoPlayersOppositeLandscape,
TwoPlayersOppositePortrait,
ThreePlayers,
ThreePlayersSide,
FourPlayers, FourPlayers,
FourPlayersSide, FourPlayersSide,
FivePlayers, OnePlayerPortrait,
SixPlayers, SixPlayers,
ThreePlayers,
ThreePlayersSide,
TwoPlayersOppositeLandscape,
TwoPlayersOppositePortrait,
TwoPlayersSameSide, TwoPlayersSameSide,
} from '../../../Icons/generated/Layouts'; } from '../../../Icons/generated/Layouts';
import OnePlayerLandscape from '../../../Icons/generated/Layouts/OnePlayerLandscape'; import OnePlayerLandscape from '../../../Icons/generated/Layouts/OnePlayerLandscape';
import { Orientation } from '../../../Types/Settings';
const LayoutWrapper = styled.div` const LayoutWrapper = styled.div`
flex-direction: row; flex-direction: row;
@@ -25,13 +26,13 @@ const LayoutWrapper = styled.div`
type LayoutOptionsProps = { type LayoutOptionsProps = {
numberOfPlayers: number; numberOfPlayers: number;
gridAreas: GridTemplateAreas; selectedOrientation: Orientation;
onChange: (gridAreas: GridTemplateAreas) => void; onChange: (orientation: Orientation) => void;
}; };
const LayoutOptions: React.FC<LayoutOptionsProps> = ({ export const LayoutOptions: React.FC<LayoutOptionsProps> = ({
numberOfPlayers, numberOfPlayers,
gridAreas, selectedOrientation,
onChange, onChange,
}) => { }) => {
const iconHeight = '30vmin'; const iconHeight = '30vmin';
@@ -43,7 +44,7 @@ const LayoutOptions: React.FC<LayoutOptionsProps> = ({
return ( return (
<> <>
<FormControlLabel <FormControlLabel
value={GridTemplateAreas.OnePlayerLandscape} value={Orientation.Landscape}
control={ control={
<Radio <Radio
icon={ icon={
@@ -66,7 +67,7 @@ const LayoutOptions: React.FC<LayoutOptionsProps> = ({
label="" label=""
/> />
<FormControlLabel <FormControlLabel
value={GridTemplateAreas.OnePlayerPortrait} value={Orientation.Portrait}
control={ control={
<Radio <Radio
icon={ icon={
@@ -94,7 +95,7 @@ const LayoutOptions: React.FC<LayoutOptionsProps> = ({
return ( return (
<> <>
<FormControlLabel <FormControlLabel
value={GridTemplateAreas.TwoPlayersSameSide} value={Orientation.Landscape}
control={ control={
<Radio <Radio
icon={ icon={
@@ -117,7 +118,7 @@ const LayoutOptions: React.FC<LayoutOptionsProps> = ({
label="" label=""
/> />
<FormControlLabel <FormControlLabel
value={GridTemplateAreas.TwoPlayersOppositePortrait} value={Orientation.Portrait}
control={ control={
<Radio <Radio
icon={ icon={
@@ -140,7 +141,7 @@ const LayoutOptions: React.FC<LayoutOptionsProps> = ({
label="" label=""
/> />
<FormControlLabel <FormControlLabel
value={GridTemplateAreas.TwoPlayersOppositeLandscape} value={Orientation.OppositeLandscape}
control={ control={
<Radio <Radio
icon={ icon={
@@ -168,7 +169,7 @@ const LayoutOptions: React.FC<LayoutOptionsProps> = ({
return ( return (
<> <>
<FormControlLabel <FormControlLabel
value={GridTemplateAreas.ThreePlayers} value={Orientation.Landscape}
control={ control={
<Radio <Radio
icon={ icon={
@@ -191,7 +192,7 @@ const LayoutOptions: React.FC<LayoutOptionsProps> = ({
label="" label=""
/> />
<FormControlLabel <FormControlLabel
value={GridTemplateAreas.ThreePlayersSide} value={Orientation.Portrait}
control={ control={
<Radio <Radio
icon={ icon={
@@ -220,7 +221,7 @@ const LayoutOptions: React.FC<LayoutOptionsProps> = ({
return ( return (
<> <>
<FormControlLabel <FormControlLabel
value={GridTemplateAreas.FourPlayers} value={Orientation.Landscape}
control={ control={
<Radio <Radio
icon={ icon={
@@ -243,7 +244,7 @@ const LayoutOptions: React.FC<LayoutOptionsProps> = ({
label="" label=""
/> />
<FormControlLabel <FormControlLabel
value={GridTemplateAreas.FourPlayersSide} value={Orientation.Portrait}
control={ control={
<Radio <Radio
icon={ icon={
@@ -272,7 +273,7 @@ const LayoutOptions: React.FC<LayoutOptionsProps> = ({
return ( return (
<> <>
<FormControlLabel <FormControlLabel
value={GridTemplateAreas.FivePlayers} value={Orientation.Landscape}
control={ control={
<Radio <Radio
icon={ icon={
@@ -324,7 +325,7 @@ const LayoutOptions: React.FC<LayoutOptionsProps> = ({
return ( return (
<> <>
<FormControlLabel <FormControlLabel
value={GridTemplateAreas.SixPlayers} value={Orientation.Landscape}
control={ control={
<Radio <Radio
icon={ icon={
@@ -382,9 +383,9 @@ const LayoutOptions: React.FC<LayoutOptionsProps> = ({
<RadioGroup <RadioGroup
row row
onChange={(_e, value) => { onChange={(_e, value) => {
onChange(value as GridTemplateAreas); onChange(value as Orientation);
}} }}
value={gridAreas} value={selectedOrientation}
style={{ justifyContent: 'center' }} style={{ justifyContent: 'center' }}
> >
{renderLayoutOptions()} {renderLayoutOptions()}
@@ -392,5 +393,3 @@ const LayoutOptions: React.FC<LayoutOptionsProps> = ({
</LayoutWrapper> </LayoutWrapper>
); );
}; };
export default LayoutOptions;

View File

@@ -2,20 +2,19 @@ import { Button, FormControl, FormLabel, Switch } from '@mui/material';
import Slider from '@mui/material/Slider'; import Slider from '@mui/material/Slider';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { GridTemplateAreas } from '../../../Data/GridTemplateAreas';
import { createInitialPlayers } from '../../../Data/getInitialPlayers'; import { createInitialPlayers } from '../../../Data/getInitialPlayers';
import { theme } from '../../../Data/theme'; import { theme } from '../../../Data/theme';
import { useAnalytics } from '../../../Hooks/useAnalytics'; import { useAnalytics } from '../../../Hooks/useAnalytics';
import { useGlobalSettings } from '../../../Hooks/useGlobalSettings';
import { usePlayers } from '../../../Hooks/usePlayers';
import { Cog, Info } from '../../../Icons/generated'; import { Cog, Info } from '../../../Icons/generated';
import { InitialGameSettings, Orientation } from '../../../Types/Settings';
import { InfoModal } from '../../Misc/InfoModal'; import { InfoModal } from '../../Misc/InfoModal';
import { SettingsModal } from '../../Misc/SettingsModal';
import { Spacer } from '../../Misc/Spacer';
import { SupportMe } from '../../Misc/SupportMe'; import { SupportMe } from '../../Misc/SupportMe';
import { H1, Paragraph } from '../../Misc/TextComponents'; import { H1, Paragraph } from '../../Misc/TextComponents';
import LayoutOptions from './LayoutOptions'; import { LayoutOptions } from './LayoutOptions';
import { Spacer } from '../../Misc/Spacer';
import { usePlayers } from '../../../Hooks/usePlayers';
import { useGlobalSettings } from '../../../Hooks/useGlobalSettings';
import { InitialGameSettings } from '../../../Types/Settings';
import { SettingsModal } from '../../Misc/SettingsModal';
const MainWrapper = styled.div` const MainWrapper = styled.div`
width: 100dvw; width: 100dvw;
@@ -118,7 +117,8 @@ const Start = () => {
numberOfPlayers: 4, numberOfPlayers: 4,
startingLifeTotal: 40, startingLifeTotal: 40,
useCommanderDamage: true, useCommanderDamage: true,
gridAreas: GridTemplateAreas.FourPlayers, orientation: Orientation.Portrait,
gameFormat: 'commander',
} }
); );
@@ -156,31 +156,9 @@ const Start = () => {
return `${value}`; return `${value}`;
}; };
const getDefaultLayout = (numberOfPlayers: number) => {
switch (numberOfPlayers) {
case 1:
return GridTemplateAreas.OnePlayerLandscape;
case 2:
return GridTemplateAreas.TwoPlayersSameSide;
case 3:
return GridTemplateAreas.ThreePlayers;
case 4:
return GridTemplateAreas.FourPlayers;
case 5:
return GridTemplateAreas.FivePlayers;
case 6:
return GridTemplateAreas.SixPlayers;
default:
return GridTemplateAreas.FourPlayers;
}
};
useEffect(() => { useEffect(() => {
const defaultLayout = getDefaultLayout(playerOptions.numberOfPlayers);
setPlayerOptions({ setPlayerOptions({
...playerOptions, ...playerOptions,
gridAreas: defaultLayout,
}); });
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [playerOptions.numberOfPlayers]); }, [playerOptions.numberOfPlayers]);
@@ -228,6 +206,7 @@ const Start = () => {
setPlayerOptions({ setPlayerOptions({
...playerOptions, ...playerOptions,
numberOfPlayers: value as number, numberOfPlayers: value as number,
orientation: Orientation.Landscape,
}); });
}} }}
/> />
@@ -246,6 +225,7 @@ const Start = () => {
setPlayerOptions({ setPlayerOptions({
...playerOptions, ...playerOptions,
startingLifeTotal: value as number, startingLifeTotal: value as number,
orientation: Orientation.Landscape,
}) })
} }
/> />
@@ -267,6 +247,7 @@ const Start = () => {
useCommanderDamage: value, useCommanderDamage: value,
numberOfPlayers: 4, numberOfPlayers: 4,
startingLifeTotal: 40, startingLifeTotal: 40,
orientation: Orientation.Landscape,
}); });
return; return;
} }
@@ -275,6 +256,7 @@ const Start = () => {
useCommanderDamage: value, useCommanderDamage: value,
numberOfPlayers: 2, numberOfPlayers: 2,
startingLifeTotal: 20, startingLifeTotal: 20,
orientation: Orientation.Landscape,
}); });
}} }}
/> />
@@ -291,12 +273,28 @@ const Start = () => {
</ToggleButtonsWrapper> </ToggleButtonsWrapper>
<FormLabel>Layout</FormLabel> <FormLabel>Layout</FormLabel>
<LayoutOptions {/* <LayoutOptions
numberOfPlayers={playerOptions.numberOfPlayers} numberOfPlayers={playerOptions.numberOfPlayers}
gridAreas={playerOptions.gridAreas} gridAreas={playerOptions.gridAreas}
onChange={(gridAreas) => onChange={(gridAreas) =>
setPlayerOptions({ ...playerOptions, gridAreas }) setPlayerOptions({
...playerOptions,
gridAreas,
//TODO fix the layout selection
orientation: Orientation.Portrait,
})
} }
/> */}
<LayoutOptions
numberOfPlayers={playerOptions.numberOfPlayers}
selectedOrientation={playerOptions.orientation}
onChange={(orientation) => {
console.log('orientation', { orientation });
setPlayerOptions({
...playerOptions,
orientation,
});
}}
/> />
</FormControl> </FormControl>

View File

@@ -1,15 +0,0 @@
export enum GridTemplateAreas {
OnePlayerLandscape = '"player0 player0"',
OnePlayerPortrait = '"player0" "player0"',
TwoPlayersOppositeLandscape = '"player0" "player1"',
TwoPlayersOppositePortrait = '"player0 player1" "player0 player1"',
TwoPlayersSameSide = '"player0 player1"',
ThreePlayers = '"player0 player0" "player1 player2"',
ThreePlayersSide = '"player0 player0 player0 player2" "player1 player1 player1 player2"',
FourPlayers = '"player0 player1" "player2 player3"',
FourPlayersSide = '"player0 player1 player1 player1 player3" "player0 player2 player2 player2 player3"',
FivePlayers = '"player0 player0 player0 player1 player1 player1" "player2 player2 player3 player3 player4 player4"',
FivePlayersSide = '"player0 player0 player0 player0 player0 player1 player1 player1 player1 player1 player2" "player3 player3 player3 player3 player3 player4 player4 player4 player4 player4 player2"',
SixPlayers = '"player0 player1 player2" "player3 player4 player5"',
SixPlayersSide = '"player0 player1 player1 player1 player1 player2 player2 player2 player2 player3" "player0 player4 player4 player4 player4 player5 player5 player5 player5 player3"',
}

View File

@@ -1,6 +1,5 @@
import { Player, Rotation } from '../Types/Player'; import { Player, Rotation } from '../Types/Player';
import { InitialGameSettings } from '../Types/Settings'; import { InitialGameSettings, Orientation } from '../Types/Settings';
import { GridTemplateAreas } from './GridTemplateAreas';
const presetColors = [ const presetColors = [
'#F06292', // Light Pink '#F06292', // Light Pink
@@ -13,16 +12,26 @@ const presetColors = [
'#FF8A80', // Coral '#FF8A80', // Coral
]; ];
const getRotation = (index: number, gridAreas: GridTemplateAreas): Rotation => { const getOrientationRotations = (
if (gridAreas === GridTemplateAreas.OnePlayerLandscape && index === 0) { index: number,
numberOfPlayers: number,
orientation: Orientation
): Rotation => {
switch (numberOfPlayers) {
case 1:
switch (orientation) {
default:
case Orientation.Landscape:
return Rotation.Normal; return Rotation.Normal;
} case Orientation.Portrait:
if (gridAreas === GridTemplateAreas.OnePlayerPortrait && index === 0) {
return Rotation.Side; return Rotation.Side;
} }
case 2:
if (gridAreas === GridTemplateAreas.TwoPlayersOppositePortrait) { switch (orientation) {
default:
case Orientation.Landscape:
return Rotation.Normal;
case Orientation.Portrait:
switch (index) { switch (index) {
case 0: case 0:
return Rotation.SideFlipped; return Rotation.SideFlipped;
@@ -31,9 +40,7 @@ const getRotation = (index: number, gridAreas: GridTemplateAreas): Rotation => {
default: default:
return Rotation.Normal; return Rotation.Normal;
} }
} case Orientation.OppositeLandscape:
if (gridAreas === GridTemplateAreas.TwoPlayersOppositeLandscape) {
switch (index) { switch (index) {
case 0: case 0:
return Rotation.Flipped; return Rotation.Flipped;
@@ -43,19 +50,10 @@ const getRotation = (index: number, gridAreas: GridTemplateAreas): Rotation => {
return Rotation.Normal; return Rotation.Normal;
} }
} }
case 3:
if (gridAreas === GridTemplateAreas.TwoPlayersSameSide) { switch (orientation) {
switch (index) {
case 0:
return Rotation.Normal;
case 1:
return Rotation.Normal;
default: default:
return Rotation.Normal; case Orientation.Landscape:
}
}
if (gridAreas === GridTemplateAreas.ThreePlayers) {
switch (index) { switch (index) {
case 0: case 0:
return Rotation.Flipped; return Rotation.Flipped;
@@ -66,9 +64,7 @@ const getRotation = (index: number, gridAreas: GridTemplateAreas): Rotation => {
default: default:
return Rotation.Normal; return Rotation.Normal;
} }
} case Orientation.Portrait:
if (gridAreas === GridTemplateAreas.ThreePlayersSide) {
switch (index) { switch (index) {
case 0: case 0:
return Rotation.Flipped; return Rotation.Flipped;
@@ -80,8 +76,10 @@ const getRotation = (index: number, gridAreas: GridTemplateAreas): Rotation => {
return Rotation.Normal; return Rotation.Normal;
} }
} }
case 4:
if (gridAreas === GridTemplateAreas.FourPlayers) { switch (orientation) {
default:
case Orientation.Landscape:
switch (index) { switch (index) {
case 0: case 0:
return Rotation.Flipped; return Rotation.Flipped;
@@ -94,9 +92,7 @@ const getRotation = (index: number, gridAreas: GridTemplateAreas): Rotation => {
default: default:
return Rotation.Normal; return Rotation.Normal;
} }
} case Orientation.Portrait:
if (gridAreas === GridTemplateAreas.FourPlayersSide) {
switch (index) { switch (index) {
case 0: case 0:
return Rotation.SideFlipped; return Rotation.SideFlipped;
@@ -110,8 +106,10 @@ const getRotation = (index: number, gridAreas: GridTemplateAreas): Rotation => {
return Rotation.Normal; return Rotation.Normal;
} }
} }
case 5:
if (gridAreas === GridTemplateAreas.FivePlayers) { switch (orientation) {
default:
case Orientation.Landscape:
switch (index) { switch (index) {
case 0: case 0:
return Rotation.Flipped; return Rotation.Flipped;
@@ -126,26 +124,26 @@ const getRotation = (index: number, gridAreas: GridTemplateAreas): Rotation => {
default: default:
return Rotation.Normal; return Rotation.Normal;
} }
} case Orientation.Portrait:
if (gridAreas === GridTemplateAreas.FivePlayersSide) {
switch (index) { switch (index) {
case 0: case 0:
return Rotation.Flipped;
case 1:
return Rotation.Flipped;
case 2:
return Rotation.Side; return Rotation.Side;
case 1:
return Rotation.Side;
case 2:
return Rotation.SideFlipped;
case 3: case 3:
return Rotation.Normal; return Rotation.SideFlipped;
case 4: case 4:
return Rotation.Normal; return Rotation.SideFlipped;
default: default:
return Rotation.Normal; return Rotation.Normal;
} }
} }
case 6:
if (gridAreas === GridTemplateAreas.SixPlayers) { switch (orientation) {
default:
case Orientation.Landscape:
switch (index) { switch (index) {
case 0: case 0:
return Rotation.Flipped; return Rotation.Flipped;
@@ -162,35 +160,34 @@ const getRotation = (index: number, gridAreas: GridTemplateAreas): Rotation => {
default: default:
return Rotation.Normal; return Rotation.Normal;
} }
} case Orientation.Portrait:
if (gridAreas === GridTemplateAreas.SixPlayersSide) {
switch (index) { switch (index) {
case 0: case 0:
return Rotation.SideFlipped;
case 1:
return Rotation.Flipped;
case 2:
return Rotation.Flipped;
case 3:
return Rotation.Side; return Rotation.Side;
case 1:
return Rotation.Side;
case 2:
return Rotation.Side;
case 3:
return Rotation.SideFlipped;
case 4: case 4:
return Rotation.Normal; return Rotation.SideFlipped;
case 5: case 5:
return Rotation.Normal; return Rotation.SideFlipped;
default: default:
return Rotation.Normal; return Rotation.Normal;
} }
} }
default:
return Rotation.Normal; return Rotation.Normal;
}
}; };
export const createInitialPlayers = ({ export const createInitialPlayers = ({
numberOfPlayers, numberOfPlayers,
startingLifeTotal, startingLifeTotal,
useCommanderDamage, useCommanderDamage,
gridAreas, orientation,
}: InitialGameSettings): Player[] => { }: InitialGameSettings): Player[] => {
const players: Player[] = []; const players: Player[] = [];
const availableColors = [...presetColors]; // Create a copy of the colors array const availableColors = [...presetColors]; // Create a copy of the colors array
@@ -213,7 +210,7 @@ export const createInitialPlayers = ({
}); });
} }
const rotation = getRotation(i, gridAreas); const rotation = getOrientationRotations(i, numberOfPlayers, orientation);
const player: Player = { const player: Player = {
lifeTotal: startingLifeTotal, lifeTotal: startingLifeTotal,

View File

@@ -1,11 +1,11 @@
import { ReactNode, useEffect, useMemo, useState } from 'react'; import { ReactNode, useEffect, useMemo, useState } from 'react';
import { useWakeLock } from 'react-screen-wake-lock';
import { import {
GlobalSettingsContext, GlobalSettingsContext,
GlobalSettingsContextType, GlobalSettingsContextType,
} from '../Contexts/GlobalSettingsContext'; } from '../Contexts/GlobalSettingsContext';
import { useWakeLock } from 'react-screen-wake-lock';
import { useAnalytics } from '../Hooks/useAnalytics'; import { useAnalytics } from '../Hooks/useAnalytics';
import { InitialGameSettings, Settings } from '../Types/Settings'; import { InitialGameSettings, Orientation, Settings } from '../Types/Settings';
export const GlobalSettingsProvider = ({ export const GlobalSettingsProvider = ({
children, children,
@@ -22,11 +22,22 @@ export const GlobalSettingsProvider = ({
savedShowPlay ? savedShowPlay === 'true' : false savedShowPlay ? savedShowPlay === 'true' : false
); );
const [initialGameSettings, setInitialGameSettings] = const [initialGameSettings, setInitialSettings] =
useState<InitialGameSettings | null>( useState<InitialGameSettings | null>(
savedGameSettings ? JSON.parse(savedGameSettings) : null savedGameSettings ? JSON.parse(savedGameSettings) : null
); );
const setInitialGameSettings = (initialGameSettings: InitialGameSettings) => {
const defaultSettings: InitialGameSettings = {
numberOfPlayers: 4,
startingLifeTotal: 40,
useCommanderDamage: true,
orientation: Orientation.Landscape,
gameFormat: 'commander',
};
setInitialSettings({ ...defaultSettings, ...initialGameSettings });
};
const [settings, setSettings] = useState<Settings>( const [settings, setSettings] = useState<Settings>(
savedSettings savedSettings
? JSON.parse(savedSettings) ? JSON.parse(savedSettings)

View File

@@ -1,6 +1,8 @@
import { GridTemplateAreas } from '../Data/GridTemplateAreas'; export enum Orientation {
OppositeLandscape = 'opposite-landscape',
type Orientation = 'side' | 'landscape' | 'portrait'; Landscape = 'landscape',
Portrait = 'portrait',
}
export type Settings = { export type Settings = {
keepAwake: boolean; keepAwake: boolean;
@@ -13,8 +15,7 @@ export type InitialGameSettings = {
useCommanderDamage: boolean; useCommanderDamage: boolean;
gameFormat?: GameFormat; gameFormat?: GameFormat;
numberOfPlayers: number; numberOfPlayers: number;
gridAreas: GridTemplateAreas; orientation: Orientation;
orientation?: Orientation;
}; };
type GameFormat = 'commander' | 'standard' | 'two-headed-giant'; type GameFormat = 'commander' | 'standard' | 'two-headed-giant';

View File

@@ -1,3 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
body { body {
margin: 0; margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',

41
tailwind.config.js Normal file
View File

@@ -0,0 +1,41 @@
import tailwindcssGridAreas from '@savvywombat/tailwindcss-grid-areas';
/** @type {import('tailwindcss').Config} */
export default {
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {
gridTemplateAreas: {
onePlayerLandscape: ['player0 player0'],
onePlayerPortrait: ['player0', 'player0'],
twoPlayersOppositeLandscape: ['player0', 'player1'],
twoPlayersOppositePortrait: ['player0 player1', 'player0 player1'],
twoPlayersSameSideLandscape: ['player0 player1'],
threePlayers: ['player0 player0', 'player1 player2'],
threePlayersSide: [
'player0 player0 player0 player2',
'player1 player1 player1 player2',
],
fourPlayerPortrait: [
'player0 player1 player1 player1 player1 player3',
'player0 player2 player2 player2 player2 player3',
],
fourPlayer: ['player0 player1', 'player2 player3'],
fivePlayers: [
'player0 player0 player0 player1 player1 player1',
'player2 player2 player3 player3 player4 player4',
],
fivePlayersSide: [
'player0 player0 player0 player0 player0 player1 player1 player1 player1 player1 player2',
'player3 player3 player3 player3 player3 player4 player4 player4 player4 player4 player2',
],
sixPlayers: ['player0 player1 player2', 'player3 player4 player5'],
sixPlayersSide: [
'player0 player1 player1 player1 player1 player2 player2 player2 player2 player3',
'player0 player4 player4 player4 player4 player5 player5 player5 player5 player3',
],
},
},
},
plugins: [tailwindcssGridAreas],
};

6990
yarn.lock Normal file

File diff suppressed because it is too large Load Diff